forked from github/szkolny
[UI/Login] Add new easter eggs.
This commit is contained in:
parent
477730708f
commit
ed3a245b51
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@
|
||||
android:textSize="24sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitleText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
@ -47,13 +48,14 @@
|
||||
tools:listitem="@layout/login_chooser_item" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/footnoteText"
|
||||
style="@style/TextAppearance.AppCompat.Small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="8dp"
|
||||
android:text="@string/login_copyright_notice"
|
||||
android:textAlignment="center" />
|
||||
android:gravity="center" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
24
app/src/main/res/layout/login_prize_fragment.xml
Normal file
24
app/src/main/res/layout/login_prize_fragment.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2020-10-18.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="48dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitXY"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
</FrameLayout>
|
||||
</layout>
|
@ -18,6 +18,24 @@
|
||||
<action
|
||||
android:id="@+id/action_loginChooserFragment_to_loginFormFragment"
|
||||
app:destination="@id/loginFormFragment" />
|
||||
<!-- eggs -->
|
||||
<action
|
||||
android:id="@+id/action_loginChooserFragment_to_loginEggsFragment"
|
||||
app:destination="@id/loginEggsFragment" />
|
||||
</fragment>
|
||||
<!-- eggs -->
|
||||
<fragment
|
||||
android:id="@+id/loginEggsFragment"
|
||||
android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginEggsFragment"
|
||||
android:label="LoginEggsFragment">
|
||||
<action
|
||||
android:id="@+id/action_loginEggsFragment_to_loginPrizeFragment"
|
||||
app:destination="@id/loginPrizeFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/loginPrizeFragment"
|
||||
android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginPrizeFragment"
|
||||
android:label="LoginPrizeFragment">
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/loginPlatformListFragment"
|
||||
|
@ -1385,4 +1385,5 @@
|
||||
<string name="login_chooser_mode_recommended">{cmd-information-outline} Zalecane</string>
|
||||
<string name="login_chooser_mode_testing">{cmd-alert-circle-outline} Wersja testowa</string>
|
||||
<string name="login_chooser_mode_dev_only">{cmd-android-studio} Wersja deweloperska</string>
|
||||
<string name="eggs">\???</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user