From f39d0c595dcae7e3bd74a491ca37601b8c1291ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 17 Oct 2020 23:10:07 +0200 Subject: [PATCH 01/32] [UI/Login] Add recommended, testing and dev only badges to login modes. --- .../ui/modules/login/LoginChooserAdapter.kt | 7 ++- .../ui/modules/login/LoginChooserFragment.kt | 60 +++++++++++++------ .../edziennik/ui/modules/login/LoginInfo.kt | 11 ++-- .../login/viewholder/ModeViewHolder.kt | 18 +++++- .../res/layout/login_chooser_mode_item.xml | 20 ++++--- app/src/main/res/values/strings.xml | 5 ++ 6 files changed, 87 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserAdapter.kt index c9ed2d6e..704e660a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserAdapter.kt @@ -60,7 +60,8 @@ class LoginChooserAdapter( private val onClickListener = View.OnClickListener { view -> val model = view.getTag(R.string.tag_key_model) - if (model is LoginInfo.Register && model.loginModes.size == 1) { + if (model is LoginInfo.Register + && model.loginModes.count { App.devMode || !it.isDevOnly } == 1) { onModeClick?.invoke(model, model.loginModes.first()) return@OnClickListener } @@ -85,7 +86,9 @@ class LoginChooserAdapter( if (model.state == STATE_CLOSED) { - val subItems = model.items + val subItems = model.items.filter { + App.devMode || !it.isDevOnly + } model.state = STATE_OPENED items.addAll(position + 1, subItems) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt index abbb4ad9..8a1045af 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt @@ -13,6 +13,7 @@ import android.view.ViewGroup import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.api.* @@ -50,25 +51,7 @@ class LoginChooserFragment : Fragment(), CoroutineScope { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { if (!isAdded) return - val adapter = LoginChooserAdapter(activity) { loginType, loginMode -> - launch { - if (!checkAvailability(loginType.loginType)) - return@launch - - if (loginMode.isPlatformSelection) { - nav.navigate(R.id.loginPlatformListFragment, Bundle( - "loginType" to loginType.loginType, - "loginMode" to loginMode.loginMode - ), activity.navOptions) - return@launch - } - - nav.navigate(R.id.loginFormFragment, Bundle( - "loginType" to loginType.loginType, - "loginMode" to loginMode.loginMode - ), activity.navOptions) - } - } + val adapter = LoginChooserAdapter(activity, this::onLoginModeClicked) LoginInfo.chooserList = LoginInfo.chooserList ?: LoginInfo.list.toMutableList() @@ -106,6 +89,45 @@ class LoginChooserFragment : Fragment(), CoroutineScope { } } + private fun onLoginModeClicked( + loginType: LoginInfo.Register, + loginMode: LoginInfo.Mode + ) { + launch { + if (!checkAvailability(loginType.loginType)) + return@launch + + if (loginMode.isTesting || loginMode.isDevOnly) { + MaterialAlertDialogBuilder(activity) + .setTitle(R.string.login_chooser_testing_title) + .setMessage(R.string.login_chooser_testing_text) + .setPositiveButton(R.string.ok) { _, _ -> + navigateToLoginMode(loginType, loginMode) + } + .setNegativeButton(R.string.cancel, null) + .show() + return@launch + } + + navigateToLoginMode(loginType, loginMode) + } + } + + private fun navigateToLoginMode(loginType: LoginInfo.Register, loginMode: LoginInfo.Mode) { + if (loginMode.isPlatformSelection) { + nav.navigate(R.id.loginPlatformListFragment, Bundle( + "loginType" to loginType.loginType, + "loginMode" to loginMode.loginMode + ), activity.navOptions) + return + } + + nav.navigate(R.id.loginFormFragment, Bundle( + "loginType" to loginType.loginType, + "loginMode" to loginMode.loginMode + ), activity.navOptions) + } + private suspend fun checkAvailability(loginType: Int): Boolean { when (loginType) { LOGIN_TYPE_LIBRUS -> "librus" diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt index 4ff09d5f..2b3acd68 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt @@ -181,18 +181,18 @@ object LoginInfo { errorCodes = mapOf( ERROR_LOGIN_VULCAN_EXPIRED_TOKEN to R.string.login_error_expired_token ) - )/*, + ), Mode( loginMode = LOGIN_MODE_VULCAN_WEB, name = R.string.login_mode_vulcan_web, icon = R.drawable.login_mode_vulcan_web, hintText = R.string.login_mode_vulcan_web_hint, guideText = R.string.login_mode_vulcan_web_guide, - isTesting = true, + isDevOnly = true, isPlatformSelection = true, credentials = listOf( getEmailCredential("webEmail"), - Credential( + FormField( keyName = "webUsername", name = R.string.login_hint_username, icon = CommunityMaterial.Icon.cmd_account_outline, @@ -201,12 +201,12 @@ object LoginInfo { errorCodes = mapOf(), isRequired = true, validationRegex = "[A-Z]{7}[0-9]+", - caseMode = Credential.CaseMode.UPPER_CASE + caseMode = FormField.CaseMode.UPPER_CASE ), getPasswordCredential("webPassword") ), errorCodes = mapOf() - )*/ + ) ) ), Register( @@ -398,6 +398,7 @@ object LoginInfo { val isRecommended: Boolean = false, val isTesting: Boolean = false, + val isDevOnly: Boolean = false, val isPlatformSelection: Boolean = false, val credentials: List, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/ModeViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/ModeViewHolder.kt index cdb0e7b8..6b0d20b5 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/ModeViewHolder.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/ModeViewHolder.kt @@ -10,7 +10,10 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.LoginChooserModeItemBinding +import pl.szczodrzynski.edziennik.resolveColor +import pl.szczodrzynski.edziennik.setTintColor import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder import pl.szczodrzynski.edziennik.ui.modules.login.LoginChooserAdapter import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo @@ -34,6 +37,19 @@ class ModeViewHolder( b.description.isVisible = true b.description.setText(item.hintText) } - b.hint.isVisible = false + + b.badge.isVisible = item.isRecommended || item.isDevOnly || item.isTesting + if (item.isRecommended) { + b.badge.setText(R.string.login_chooser_mode_recommended) + b.badge.background.setTintColor(R.color.md_blue_300.resolveColor(app)) + } + if (item.isTesting) { + b.badge.setText(R.string.login_chooser_mode_testing) + b.badge.background.setTintColor(R.color.md_yellow_300.resolveColor(app)) + } + if (item.isDevOnly) { + b.badge.setText(R.string.login_chooser_mode_dev_only) + b.badge.background.setTintColor(R.color.md_red_300.resolveColor(app)) + } } } diff --git a/app/src/main/res/layout/login_chooser_mode_item.xml b/app/src/main/res/layout/login_chooser_mode_item.xml index a415a8f1..8b237795 100644 --- a/app/src/main/res/layout/login_chooser_mode_item.xml +++ b/app/src/main/res/layout/login_chooser_mode_item.xml @@ -36,6 +36,19 @@ android:orientation="vertical" android:gravity="center_vertical"> + + - - Dowiedz się więcej Stara nie zobaczy pał Wyloguj z pozostałych urządzeń + Wersja testowa + Wybrany sposób logowania jest jeszcze w fazie testów i może nie działać poprawnie.\n\nJeśli masz problemy z aplikacją, wybierz zalecany sposób logowania. + {cmd-information-outline} Zalecane + {cmd-alert-circle-outline} Wersja testowa + {cmd-android-studio} Wersja deweloperska From 477730708f9c85e58c55cfebd46624c6fcaa9361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 17 Oct 2020 23:44:17 +0200 Subject: [PATCH 02/32] [UI/Login] Add refresh button in platform list. --- .../login/LoginPlatformListFragment.kt | 38 +++++++++++++------ .../layout/login_platform_list_fragment.xml | 9 +++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt index 9beb0860..ad5fb3d9 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt @@ -47,6 +47,7 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope { } private lateinit var timeoutJob: Job + private lateinit var adapter: LoginPlatformAdapter override fun onViewCreated(view: View, savedInstanceState: Bundle?) { if (!isAdded) return @@ -57,12 +58,7 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope { val loginMode = arguments?.getInt("loginMode") ?: return val mode = register.loginModes.firstOrNull { it.loginMode == loginMode } ?: return - timeoutJob = startCoroutineTimer(5000L) { - b.timeoutText.isVisible = true - timeoutJob.cancel() - } - - val adapter = LoginPlatformAdapter(activity) { platform -> + adapter = LoginPlatformAdapter(activity) { platform -> nav.navigate(R.id.loginFormFragment, Bundle( "loginType" to platform.loginType, "loginMode" to platform.loginMode, @@ -73,7 +69,30 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope { ), activity.navOptions) } + loadPlatforms(register, mode) + b.reloadButton.isVisible = App.devMode + b.reloadButton.onClick { + LoginInfo.platformList.remove(mode.name) + loadPlatforms(register, mode) + } + + b.list.apply { + setHasFixedSize(true) + layoutManager = LinearLayoutManager(context) + addItemDecoration(SimpleDividerItemDecoration(context)) + } + } + + private fun loadPlatforms(register: LoginInfo.Register, mode: LoginInfo.Mode) { launch { + timeoutJob = startCoroutineTimer(5000L) { + b.timeoutText.isVisible = true + timeoutJob.cancel() + } + b.loadingLayout.isVisible = true + b.list.isVisible = false + b.reloadButton.isEnabled = false + val platforms = LoginInfo.platformList[mode.name] ?: run { api.runCatching(activity) { @@ -87,14 +106,11 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope { adapter.items = platforms b.list.adapter = adapter - b.list.apply { - setHasFixedSize(true) - layoutManager = LinearLayoutManager(context) - addItemDecoration(SimpleDividerItemDecoration(context)) - } + timeoutJob.cancel() b.loadingLayout.isVisible = false b.list.isVisible = true + b.reloadButton.isEnabled = true } } } diff --git a/app/src/main/res/layout/login_platform_list_fragment.xml b/app/src/main/res/layout/login_platform_list_fragment.xml index ebe8c169..699177ff 100644 --- a/app/src/main/res/layout/login_platform_list_fragment.xml +++ b/app/src/main/res/layout/login_platform_list_fragment.xml @@ -78,6 +78,15 @@ tools:visibility="visible" /> + + Date: Sun, 18 Oct 2020 22:14:41 +0200 Subject: [PATCH 03/32] [UI/Login] Add new easter eggs. --- .../ui/modules/login/LoginActivity.kt | 10 +- .../ui/modules/login/LoginChooserFragment.kt | 110 ++++++++++++++++- .../ui/modules/login/LoginEggsFragment.kt | 116 ++++++++++++++++++ .../ui/modules/login/LoginFormFragment.kt | 9 +- .../ui/modules/login/LoginPrizeFragment.kt | 77 ++++++++++++ .../res/layout/login_chooser_fragment.xml | 4 +- .../main/res/layout/login_prize_fragment.xml | 24 ++++ app/src/main/res/navigation/nav_login.xml | 18 +++ app/src/main/res/values/strings.xml | 1 + 9 files changed, 363 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginEggsFragment.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt create mode 100644 app/src/main/res/layout/login_prize_fragment.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.kt index c686b857..925b2a98 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginActivity.kt @@ -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() val loginStores = mutableListOf() + 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) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt index 8a1045af..ac1bdd3b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt @@ -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() + ?: 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 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginEggsFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginEggsFragment.kt new file mode 100644 index 00000000..0c11bb5a --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginEggsFragment.kt @@ -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) {} + } + } + } + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt index 82e4f895..e223d5fc 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt @@ -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 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt new file mode 100644 index 00000000..b9fdf43a --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt @@ -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() + } + } +} diff --git a/app/src/main/res/layout/login_chooser_fragment.xml b/app/src/main/res/layout/login_chooser_fragment.xml index a35250fb..27e6f309 100644 --- a/app/src/main/res/layout/login_chooser_fragment.xml +++ b/app/src/main/res/layout/login_chooser_fragment.xml @@ -31,6 +31,7 @@ android:textSize="24sp" /> + android:gravity="center" /> + + + + + + + + + diff --git a/app/src/main/res/navigation/nav_login.xml b/app/src/main/res/navigation/nav_login.xml index 7feb8fc7..6fb5e503 100644 --- a/app/src/main/res/navigation/nav_login.xml +++ b/app/src/main/res/navigation/nav_login.xml @@ -18,6 +18,24 @@ + + + + + + + + {cmd-information-outline} Zalecane {cmd-alert-circle-outline} Wersja testowa {cmd-android-studio} Wersja deweloperska + \??? From 9649afd43f255b4133bb49cf9150d8e34a29faea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Wed, 17 Feb 2021 14:42:08 +0100 Subject: [PATCH 04/32] [Gradle] Update libraries and dependencies. --- .idea/codeStyles/Project.xml | 16 ++++++------ .idea/codeStyles/codeStyleConfig.xml | 5 ++++ .idea/compiler.xml | 16 ++++++------ .idea/discord.xml | 2 +- .idea/runConfigurations.xml | 1 + app/build.gradle | 13 +++++----- build.gradle | 32 ++++++++++-------------- gradle.properties | 1 - gradle/wrapper/gradle-wrapper.properties | 6 ++--- 9 files changed, 45 insertions(+), 47 deletions(-) create mode 100644 .idea/codeStyles/codeStyleConfig.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 681f41ae..29204aff 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,6 +1,10 @@ + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 12871fc6..8b487d4c 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -4,14 +4,14 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml index 59b11d1d..a04e4e5f 100644 --- a/.idea/discord.xml +++ b/.idea/discord.xml @@ -1,7 +1,7 @@ -