mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-06-10 20:50:47 +02:00
[UI/Login] Add new easter eggs.
This commit is contained in:
@ -25,7 +25,6 @@ import kotlin.coroutines.CoroutineContext
|
||||
class LoginActivity : AppCompatActivity(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LoginActivity"
|
||||
var thisOneIsTricky = 0
|
||||
}
|
||||
|
||||
private val app: App by lazy { applicationContext as App }
|
||||
@ -42,6 +41,8 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
|
||||
val profiles = mutableListOf<LoginSummaryAdapter.Item>()
|
||||
val loginStores = mutableListOf<LoginStore>()
|
||||
|
||||
fun getRootView() = b.root
|
||||
|
||||
override fun onBackPressed() {
|
||||
val destination = nav.currentDestination ?: run {
|
||||
nav.navigateUp()
|
||||
@ -55,6 +56,11 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
|
||||
return
|
||||
if (destination.id == R.id.loginFinishFragment)
|
||||
return
|
||||
// eggs
|
||||
if (destination.id == R.id.loginPrizeFragment) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
if (destination.id == R.id.loginChooserFragment && loginStores.isEmpty()) {
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
finish()
|
||||
@ -79,8 +85,6 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
|
||||
super.onCreate(savedInstanceState)
|
||||
setTheme(R.style.AppTheme_Light)
|
||||
|
||||
thisOneIsTricky = -1
|
||||
|
||||
navOptions = NavOptions.Builder()
|
||||
.setEnterAnim(R.anim.slide_in_right)
|
||||
.setExitAnim(R.anim.slide_out_left)
|
||||
|
@ -4,12 +4,18 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.login
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.RotateAnimation
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@ -27,6 +33,8 @@ import kotlin.coroutines.CoroutineContext
|
||||
class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LoginChooserFragment"
|
||||
// eggs
|
||||
var isRotated = false
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
@ -48,13 +56,33 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||
return b.root
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
if (!isAdded) return
|
||||
|
||||
val adapter = LoginChooserAdapter(activity, this::onLoginModeClicked)
|
||||
|
||||
LoginInfo.chooserList = LoginInfo.chooserList
|
||||
?: LoginInfo.list.toMutableList<Any>()
|
||||
?: LoginInfo.list.toMutableList()
|
||||
|
||||
// eggs
|
||||
if (isRotated) {
|
||||
isRotated = false
|
||||
LoginFormFragment.wantEggs = false
|
||||
LoginInfo.chooserList = LoginInfo.list.toMutableList()
|
||||
val anim = RotateAnimation(
|
||||
180f,
|
||||
0f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f
|
||||
)
|
||||
anim.interpolator = AccelerateDecelerateInterpolator()
|
||||
anim.duration = 500
|
||||
anim.fillAfter = true
|
||||
activity.getRootView().startAnimation(anim)
|
||||
}
|
||||
|
||||
adapter.items = LoginInfo.chooserList!!
|
||||
b.list.adapter = adapter
|
||||
@ -68,6 +96,81 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||
startActivity(Intent(activity, FeedbackActivity::class.java))
|
||||
}
|
||||
|
||||
// eggs
|
||||
b.footnoteText.onClick {
|
||||
if (!LoginFormFragment.wantEggs || isRotated)
|
||||
return@onClick
|
||||
|
||||
val text = b.subtitleText.text.toString()
|
||||
if (text.endsWith(".."))
|
||||
b.subtitleText.text = text.substring(0, text.length - 2)
|
||||
else
|
||||
b.subtitleText.text = "$text..."
|
||||
}
|
||||
var clickCount = 0
|
||||
val color = R.color.md_blue_500.resolveColor(app)
|
||||
val hsv = FloatArray(3)
|
||||
Color.colorToHSV(color, hsv)
|
||||
val hueOriginal = hsv[0]
|
||||
b.subtitleText.onClick {
|
||||
if (isRotated)
|
||||
return@onClick
|
||||
val text = b.subtitleText.text.toString()
|
||||
if (text.endsWith("..") && !text.endsWith("...")) {
|
||||
clickCount++
|
||||
}
|
||||
if (clickCount == 5) {
|
||||
val anim = ValueAnimator.ofFloat(0f, 1f)
|
||||
anim.duration = 5000
|
||||
anim.addUpdateListener {
|
||||
hsv[0] = hueOriginal + it.animatedFraction * 3f * 360f
|
||||
hsv[0] = hsv[0] % 360f
|
||||
b.topLogo.drawable.setTintColor(Color.HSVToColor(Color.alpha(color), hsv))
|
||||
}
|
||||
anim.start()
|
||||
}
|
||||
}
|
||||
b.topLogo.onClick {
|
||||
if (clickCount != 5 || isRotated) {
|
||||
clickCount = 0
|
||||
return@onClick
|
||||
}
|
||||
isRotated = true
|
||||
val anim = RotateAnimation(
|
||||
0f,
|
||||
180f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f
|
||||
)
|
||||
anim.interpolator = AccelerateDecelerateInterpolator()
|
||||
anim.duration = 2000
|
||||
anim.fillAfter = true
|
||||
activity.getRootView().startAnimation(anim)
|
||||
|
||||
b.list.smoothScrollToPosition(0)
|
||||
adapter.items.add(
|
||||
LoginInfo.Register(
|
||||
loginType = 74,
|
||||
internalName = "eggs",
|
||||
registerName = R.string.eggs,
|
||||
registerLogo = R.drawable.face_1,
|
||||
loginModes = listOf(
|
||||
LoginInfo.Mode(
|
||||
loginMode = 0,
|
||||
name = 0,
|
||||
icon = 0,
|
||||
guideText = 0,
|
||||
credentials = listOf(),
|
||||
errorCodes = mapOf()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
adapter.notifyItemInserted(adapter.items.size - 1)
|
||||
}
|
||||
|
||||
when {
|
||||
activity.loginStores.isNotEmpty() -> {
|
||||
// we are navigated here from LoginSummary
|
||||
@ -93,6 +196,11 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||
loginType: LoginInfo.Register,
|
||||
loginMode: LoginInfo.Mode
|
||||
) {
|
||||
if (loginType.internalName == "eggs") {
|
||||
nav.navigate(R.id.loginEggsFragment, null, activity.navOptions)
|
||||
return
|
||||
}
|
||||
|
||||
launch {
|
||||
if (!checkAvailability(loginType.loginType))
|
||||
return@launch
|
||||
|
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-10-18.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.login
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.RotateAnimation
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.FrameLayout
|
||||
import androidx.fragment.app.Fragment
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.BuildConfig
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.md5
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LoginEggsFragment : Fragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LoginEggsFragment"
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: LoginActivity
|
||||
private lateinit var view: ViewGroup
|
||||
private lateinit var webView: WebView
|
||||
private val nav by lazy { activity.nav }
|
||||
|
||||
private val job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
// local/private variables go here
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
activity = (getActivity() as LoginActivity?) ?: return null
|
||||
context ?: return null
|
||||
app = activity.application as App
|
||||
webView = WebView(activity)
|
||||
view = FrameLayout(activity)
|
||||
view.addView(webView)
|
||||
return view
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
if (!isAdded) return
|
||||
|
||||
if (!LoginChooserFragment.isRotated) {
|
||||
nav.navigateUp()
|
||||
return
|
||||
}
|
||||
|
||||
val anim = RotateAnimation(
|
||||
180f,
|
||||
0f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f
|
||||
)
|
||||
anim.interpolator = AccelerateDecelerateInterpolator()
|
||||
anim.duration = 10
|
||||
anim.fillAfter = true
|
||||
activity.getRootView().startAnimation(anim)
|
||||
|
||||
webView.apply {
|
||||
settings.apply {
|
||||
javaScriptEnabled = true
|
||||
}
|
||||
addJavascriptInterface(object : Any() {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
@JavascriptInterface
|
||||
fun getPrize() {
|
||||
val anim = RotateAnimation(
|
||||
0f,
|
||||
180f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f
|
||||
)
|
||||
anim.interpolator = AccelerateDecelerateInterpolator()
|
||||
anim.duration = 10
|
||||
anim.fillAfter = true
|
||||
activity.getRootView().startAnimation(anim)
|
||||
nav.navigate(R.id.loginPrizeFragment, null, activity.navOptions)
|
||||
}
|
||||
}, "EggInterface")
|
||||
loadUrl("https://szkolny.eu/game/runner.html")
|
||||
webViewClient = object : WebViewClient() {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
super.onPageFinished(view, url)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val deviceId = app.deviceId.md5()
|
||||
val version = BuildConfig.VERSION_NAME
|
||||
val js = """initPage("$deviceId", true, "$version");"""
|
||||
webView.evaluateJavascript(js) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -32,6 +32,8 @@ import kotlin.coroutines.CoroutineContext
|
||||
class LoginFormFragment : Fragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LoginFormFragment"
|
||||
// eggs
|
||||
var wantEggs = false
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
@ -108,8 +110,13 @@ class LoginFormFragment : Fragment(), CoroutineScope {
|
||||
if (credential is LoginInfo.FormCheckbox) {
|
||||
val b = LoginFormCheckboxItemBinding.inflate(layoutInflater)
|
||||
b.checkbox.text = app.getString(credential.name)
|
||||
b.checkbox.onChange { _, _ ->
|
||||
b.checkbox.onChange { _, isChecked ->
|
||||
b.errorText.text = null
|
||||
|
||||
// eggs
|
||||
if (register.internalName == "podlasie") {
|
||||
wantEggs = !isChecked
|
||||
}
|
||||
}
|
||||
if (arguments?.containsKey(credential.keyName) == true) {
|
||||
b.checkbox.isChecked = arguments?.getBoolean(credential.keyName) == true
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-10-18.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.login
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Process
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import coil.api.load
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.LoginPrizeFragmentBinding
|
||||
import pl.szczodrzynski.edziennik.onClick
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class LoginPrizeFragment : Fragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LoginPrizeFragment"
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: LoginActivity
|
||||
private lateinit var b: LoginPrizeFragmentBinding
|
||||
private val nav by lazy { activity.nav }
|
||||
|
||||
private val job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
// local/private variables go here
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
activity = (getActivity() as LoginActivity?) ?: return null
|
||||
context ?: return null
|
||||
app = activity.application as App
|
||||
b = LoginPrizeFragmentBinding.inflate(inflater)
|
||||
return b.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
b.button.load("https://szkolny.eu/game/button.png")
|
||||
b.button.onClick {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.are_you_sure)
|
||||
.setMessage(R.string.dev_mode_enable_warning)
|
||||
.setPositiveButton(R.string.yes) { _, _ ->
|
||||
app.config.debugMode = true
|
||||
App.devMode = true
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle("Restart")
|
||||
.setMessage("Wymagany restart aplikacji")
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
Process.killProcess(Process.myPid())
|
||||
Runtime.getRuntime().exit(0)
|
||||
exitProcess(0)
|
||||
}
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
.setNegativeButton(R.string.no) { _, _ ->
|
||||
app.config.debugMode = false
|
||||
App.devMode = false
|
||||
activity.finish()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user