From 184a7ab200cccd7fa1ad43243f7afb60adbedb90 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2019 21:55:28 +0000 Subject: [PATCH 01/22] Bump room from 2.2.0-rc01 to 2.2.0 (#552) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index ee372782..f5f30447 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,7 +111,7 @@ play { ext { work_manager = "2.2.0" - room = "2.2.0-rc01" + room = "2.2.0" dagger = "2.24" chucker = "2.0.4" mockk = "1.9.2" From f46649797075bb961c73665c12260545a97b70b1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2019 21:56:19 +0000 Subject: [PATCH 02/22] Bump recyclerview from 1.1.0-beta04 to 1.1.0-beta05 (#551) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index f5f30447..7bba6e51 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -135,7 +135,7 @@ dependencies { implementation "androidx.multidex:multidex:2.0.1" implementation "androidx.preference:preference-ktx:1.1.0" - implementation "androidx.recyclerview:recyclerview:1.1.0-beta04" + implementation "androidx.recyclerview:recyclerview:1.1.0-beta05" implementation "androidx.viewpager:viewpager:1.0.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" implementation "androidx.constraintlayout:constraintlayout:1.1.3" From 360dfbcdb5d2f26ece9b2d15b930fcdce03348e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Tue, 15 Oct 2019 19:15:28 +0200 Subject: [PATCH 03/22] Update androidx dependencies (#553) --- app/build.gradle | 10 +++++----- app/src/main/res/layout/activity_main.xml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7bba6e51..78b4020c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -110,7 +110,7 @@ play { } ext { - work_manager = "2.2.0" + work_manager = "2.3.0-alpha02" room = "2.2.0" dagger = "2.24" chucker = "2.0.4" @@ -126,18 +126,18 @@ dependencies { implementation "io.github.wulkanowy:api:0.11.0" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation "androidx.core:core-ktx:1.1.0" - implementation "androidx.activity:activity-ktx:1.0.0" + implementation "androidx.core:core-ktx:1.2.0-beta01" + implementation "androidx.activity:activity-ktx:1.1.0-beta01" implementation "androidx.appcompat:appcompat:1.1.0" implementation "androidx.appcompat:appcompat-resources:1.1.0" - implementation "androidx.fragment:fragment-ktx:1.1.0" + implementation "androidx.fragment:fragment-ktx:1.2.0-beta02" implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.multidex:multidex:2.0.1" implementation "androidx.preference:preference-ktx:1.1.0" implementation "androidx.recyclerview:recyclerview:1.1.0-beta05" implementation "androidx.viewpager:viewpager:1.0.0" - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" + implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03" implementation "androidx.constraintlayout:constraintlayout:1.1.3" implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0-beta01" implementation "com.google.android.material:material:1.1.0-alpha07" diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 84007c77..d07dbbd8 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -10,7 +10,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> - Date: Wed, 16 Oct 2019 20:10:24 +0200 Subject: [PATCH 04/22] Move default preferences values to separate file (#555) --- .../preferences/PreferencesRepository.kt | 48 +++++++++++-------- ..._prefernces.xml => preferences_values.xml} | 0 .../main/res/values/preferences_defaults.xml | 18 +++++++ ..._prefernces.xml => preferences_values.xml} | 0 app/src/main/res/xml/scheme_preferences.xml | 30 ++++++------ 5 files changed, 61 insertions(+), 35 deletions(-) rename app/src/main/res/values-pl/{value_prefernces.xml => preferences_values.xml} (100%) create mode 100644 app/src/main/res/values/preferences_defaults.xml rename app/src/main/res/values/{value_prefernces.xml => preferences_values.xml} (100%) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt index bb9a39b1..e1caf920 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt @@ -12,52 +12,60 @@ class PreferencesRepository @Inject constructor( val context: Context ) { val startMenuIndex: Int - get() = sharedPref.getString(context.getString(R.string.pref_key_start_menu), "0")?.toIntOrNull() ?: 0 + get() = getString(R.string.pref_key_start_menu, R.string.pref_default_startup).toInt() val isShowPresent: Boolean - get() = sharedPref.getBoolean(context.getString(R.string.pref_key_attendance_present), true) + get() = getBoolean(R.string.pref_key_attendance_present, R.bool.pref_default_attendance_present) val gradeAverageMode: String - get() = sharedPref.getString(context.getString(R.string.pref_key_grade_average_mode), "only_one_semester") ?: "only_one_semester" + get() = getString(R.string.pref_key_grade_average_mode, R.string.pref_default_grade_average_mode) val gradeAverageForceCalc: Boolean - get() = sharedPref.getBoolean(context.getString(R.string.pref_key_grade_average_force_calc), false) + get() = getBoolean(R.string.pref_key_grade_average_force_calc, R.bool.pref_default_grade_average_force_calc) val isGradeExpandable: Boolean - get() = !sharedPref.getBoolean(context.getString(R.string.pref_key_expand_grade), false) + get() = !getBoolean(R.string.pref_key_expand_grade, R.bool.pref_default_expand_grade) - val appThemeKey: String = context.getString(R.string.pref_key_app_theme) + val appThemeKey = context.getString(R.string.pref_key_app_theme) val appTheme: String - get() = sharedPref.getString(appThemeKey, "light") ?: "light" + get() = getString(appThemeKey, R.string.pref_default_app_theme) val gradeColorTheme: String - get() = sharedPref.getString(context.getString(R.string.pref_key_grade_color_scheme), "vulcan") ?: "vulcan" + get() = getString(R.string.pref_key_grade_color_scheme, R.string.pref_default_grade_color_scheme) - val serviceEnableKey: String = context.getString(R.string.pref_key_services_enable) + val serviceEnableKey = context.getString(R.string.pref_key_services_enable) val isServiceEnabled: Boolean - get() = sharedPref.getBoolean(serviceEnableKey, true) + get() = getBoolean(serviceEnableKey, R.bool.pref_default_services_enable) - val servicesIntervalKey: String = context.getString(R.string.pref_key_services_interval) + val servicesIntervalKey = context.getString(R.string.pref_key_services_interval) val servicesInterval: Long - get() = sharedPref.getString(servicesIntervalKey, "60")?.toLongOrNull() ?: 60 + get() = getString(servicesIntervalKey, R.string.pref_default_services_interval).toLong() - val servicesOnlyWifiKey: String = context.getString(R.string.pref_key_services_wifi_only) + val servicesOnlyWifiKey = context.getString(R.string.pref_key_services_wifi_only) val isServicesOnlyWifi: Boolean - get() = sharedPref.getBoolean(servicesOnlyWifiKey, false) + get() = getBoolean(servicesOnlyWifiKey, R.bool.pref_default_services_wifi_only) val isNotificationsEnable: Boolean - get() = sharedPref.getBoolean(context.getString(R.string.pref_key_notifications_enable), true) + get() = getBoolean(R.string.pref_key_notifications_enable, R.bool.pref_default_notifications_enable) - val isDebugNotificationEnableKey: String = context.getString(R.string.pref_key_notification_debug) + val isDebugNotificationEnableKey = context.getString(R.string.pref_key_notification_debug) val isDebugNotificationEnable: Boolean - get() = sharedPref.getBoolean(isDebugNotificationEnableKey, false) + get() = getBoolean(isDebugNotificationEnableKey, R.bool.pref_default_notification_debug) val gradePlusModifier: Double - get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_plus), "0.0")?.toDouble() ?: 0.0 + get() = getString(R.string.pref_key_grade_modifier_plus, R.string.pref_default_grade_modifier_plus).toDouble() val gradeMinusModifier: Double - get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_minus), "0.0")?.toDouble() ?: 0.0 + get() = getString(R.string.pref_key_grade_modifier_minus, R.string.pref_default_grade_modifier_minus).toDouble() val fillMessageContent: Boolean - get() = sharedPref.getBoolean(context.getString(R.string.pref_key_fill_message_content), true) + get() = getBoolean(R.string.pref_key_fill_message_content, R.bool.pref_default_fill_message_content) + + private fun getString(id: Int, default: Int) = getString(context.getString(id), default) + + private fun getString(id: String, default: Int) = sharedPref.getString(id, context.getString(default)) ?: context.getString(default) + + private fun getBoolean(id: Int, default: Int) = getBoolean(context.getString(id), default) + + private fun getBoolean(id: String, default: Int) = sharedPref.getBoolean(id, context.resources.getBoolean(default)) } diff --git a/app/src/main/res/values-pl/value_prefernces.xml b/app/src/main/res/values-pl/preferences_values.xml similarity index 100% rename from app/src/main/res/values-pl/value_prefernces.xml rename to app/src/main/res/values-pl/preferences_values.xml diff --git a/app/src/main/res/values/preferences_defaults.xml b/app/src/main/res/values/preferences_defaults.xml new file mode 100644 index 00000000..53b5c2ab --- /dev/null +++ b/app/src/main/res/values/preferences_defaults.xml @@ -0,0 +1,18 @@ + + + 0 + true + only_one_semester + false + false + light + vulcan + true + 60 + false + true + false + 0.0 + 0.0 + true + diff --git a/app/src/main/res/values/value_prefernces.xml b/app/src/main/res/values/preferences_values.xml similarity index 100% rename from app/src/main/res/values/value_prefernces.xml rename to app/src/main/res/values/preferences_values.xml diff --git a/app/src/main/res/xml/scheme_preferences.xml b/app/src/main/res/xml/scheme_preferences.xml index d762066a..28229f41 100644 --- a/app/src/main/res/xml/scheme_preferences.xml +++ b/app/src/main/res/xml/scheme_preferences.xml @@ -4,7 +4,7 @@ app:iconSpaceReserved="false" app:title="@string/pref_view_header"> @@ -81,7 +81,7 @@ app:iconSpaceReserved="false" app:title="@string/pref_other_header"> From ce9b12eb9311e9a4aefdc0e30fb6b5ef50f06882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Wed, 16 Oct 2019 22:27:16 +0200 Subject: [PATCH 05/22] Add system theme setting for Android 10 (#554) --- .../io/github/wulkanowy/ui/base/ThemeManager.kt | 9 +++++++-- .../main/res/values-pl-v29/preferences_values.xml | 9 +++++++++ app/src/main/res/values-pl/preferences_values.xml | 4 ++-- .../main/res/values-v29/preferences_defaults.xml | 4 ++++ .../main/res/values-v29/preferences_values.xml | 15 +++++++++++++++ app/src/main/res/values/preferences_values.xml | 6 +++--- 6 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 app/src/main/res/values-pl-v29/preferences_values.xml create mode 100644 app/src/main/res/values-v29/preferences_defaults.xml create mode 100644 app/src/main/res/values-v29/preferences_values.xml diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt index 5b347fe8..50134861 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt @@ -3,6 +3,7 @@ package io.github.wulkanowy.ui.base import android.content.pm.PackageManager.GET_ACTIVITIES import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate +import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES import io.github.wulkanowy.R @@ -22,8 +23,12 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer fun applyDefaultTheme() { AppCompatDelegate.setDefaultNightMode( - if (preferencesRepository.appTheme == "light") MODE_NIGHT_NO - else MODE_NIGHT_YES + when (val theme = preferencesRepository.appTheme) { + "light" -> MODE_NIGHT_NO + "dark", "black" -> MODE_NIGHT_YES + "system" -> MODE_NIGHT_FOLLOW_SYSTEM + else -> throw IllegalArgumentException("Wrong theme: $theme") + } ) } diff --git a/app/src/main/res/values-pl-v29/preferences_values.xml b/app/src/main/res/values-pl-v29/preferences_values.xml new file mode 100644 index 00000000..57f20804 --- /dev/null +++ b/app/src/main/res/values-pl-v29/preferences_values.xml @@ -0,0 +1,9 @@ + + + + Motyw systemu + Jasny + Ciemny + Czarny (AMOLED) + + diff --git a/app/src/main/res/values-pl/preferences_values.xml b/app/src/main/res/values-pl/preferences_values.xml index 868ead4d..e4c30eb0 100644 --- a/app/src/main/res/values-pl/preferences_values.xml +++ b/app/src/main/res/values-pl/preferences_values.xml @@ -1,5 +1,5 @@ - + 15 minut 30 minut @@ -10,7 +10,7 @@ 24 godziny - + Jasny Ciemny Czarny (AMOLED) diff --git a/app/src/main/res/values-v29/preferences_defaults.xml b/app/src/main/res/values-v29/preferences_defaults.xml new file mode 100644 index 00000000..bb573d66 --- /dev/null +++ b/app/src/main/res/values-v29/preferences_defaults.xml @@ -0,0 +1,4 @@ + + + system + diff --git a/app/src/main/res/values-v29/preferences_values.xml b/app/src/main/res/values-v29/preferences_values.xml new file mode 100644 index 00000000..f27c1c69 --- /dev/null +++ b/app/src/main/res/values-v29/preferences_values.xml @@ -0,0 +1,15 @@ + + + + System theme + Light + Dark + Black (AMOLED) + + + system + light + dark + black + + diff --git a/app/src/main/res/values/preferences_values.xml b/app/src/main/res/values/preferences_values.xml index 97396baa..289f14f3 100644 --- a/app/src/main/res/values/preferences_values.xml +++ b/app/src/main/res/values/preferences_values.xml @@ -1,5 +1,5 @@ - + @string/grade_title @string/attendance_title @@ -13,12 +13,12 @@ 3 - + Light Dark Black (AMOLED) - + light dark black From 7e30524876557340d0f8d8cc22c594b92dc55840 Mon Sep 17 00:00:00 2001 From: Dominik Korsa Date: Sun, 20 Oct 2019 19:10:32 +0200 Subject: [PATCH 06/22] Contact info after failed login (#556) --- .../modules/login/form/LoginFormFragment.kt | 20 +++++ .../modules/login/form/LoginFormPresenter.kt | 10 +++ .../ui/modules/login/form/LoginFormView.kt | 6 ++ .../LoginStudentSelectFragment.kt | 25 +++++++ .../LoginStudentSelectPresenter.kt | 10 +++ .../studentselect/LoginStudentSelectView.kt | 6 ++ .../login/symbol/LoginSymbolFragment.kt | 25 +++++++ .../login/symbol/LoginSymbolPresenter.kt | 15 +++- .../modules/login/symbol/LoginSymbolView.kt | 6 ++ .../wulkanowy/utils/ContextExtension.kt | 10 +++ .../main/res/layout/fragment_login_form.xml | 68 ++++++++++++++++- .../layout/fragment_login_student_select.xml | 73 ++++++++++++++++++- .../main/res/layout/fragment_login_symbol.xml | 73 ++++++++++++++++++- app/src/main/res/values-pl/strings.xml | 4 + app/src/main/res/values/strings.xml | 6 ++ 15 files changed, 351 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt index 4849b213..8ea4222c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt @@ -21,6 +21,7 @@ import io.github.wulkanowy.utils.openInternetBrowser import io.github.wulkanowy.utils.showSoftInput import kotlinx.android.synthetic.main.fragment_login_form.* import javax.inject.Inject +import io.github.wulkanowy.utils.openEmail class LoginFormFragment : BaseFragment(), LoginFormView { @@ -62,6 +63,8 @@ class LoginFormFragment : BaseFragment(), LoginFormView { loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() } loginFormSignIn.setOnClickListener { presenter.onSignInClick() } loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() } + loginFormContactDiscord.setOnClickListener { presenter.onDiscordClick() } + loginFormContactEmail.setOnClickListener { presenter.onEmailClick() } loginFormPass.setOnEditorActionListener { _, id, _ -> if (id == IME_ACTION_DONE || id == IME_NULL) loginFormSignIn.callOnClick() else false @@ -154,8 +157,25 @@ class LoginFormFragment : BaseFragment(), LoginFormView { context?.openInternetBrowser("https://wulkanowy.github.io/polityka-prywatnosci.html", ::showMessage) } + override fun showContact(show: Boolean) { + loginFormContact.visibility = if (show) VISIBLE else GONE + } + override fun onDestroyView() { super.onDestroyView() presenter.onDetachView() } + + override fun openDiscordInvite() { + context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) + } + + override fun openEmail() { + context?.openEmail( + requireContext().getString(R.string.login_email_intent_title), + "wulkanowyinc@gmail.com", + requireContext().getString(R.string.login_email_subject), + requireContext().getString(R.string.login_email_text, appInfo.systemModel, appInfo.systemVersion.toString(), appInfo.versionName) + ) + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt index d5b81b5b..bdab1dad 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt @@ -22,6 +22,7 @@ class LoginFormPresenter @Inject constructor( super.onAttachView(view) view.run { initView() + showContact(false) if (appInfo.isDebug) showVersion() else showPrivacyPolicy() loginErrorHandler.onBadCredentials = { @@ -86,9 +87,18 @@ class LoginFormPresenter @Inject constructor( Timber.i("Login result: An exception occurred") analytics.logEvent("registration_form", "success" to false, "students" to -1, "endpoint" to endpoint, "error" to it.message.ifNullOrBlank { "No message" }) loginErrorHandler.dispatch(it) + view?.showContact(true) })) } + fun onDiscordClick() { + view?.openDiscordInvite() + } + + fun onEmailClick() { + view?.openEmail() + } + private fun validateCredentials(login: String, password: String): Boolean { var isCorrect = true diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt index 097b6f62..7eec9477 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt @@ -42,4 +42,10 @@ interface LoginFormView : BaseView { fun notifyParentAccountLogged(students: List, loginData: Triple) fun openPrivacyPolicyPage() + + fun showContact(show: Boolean) + + fun openDiscordInvite() + + fun openEmail() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt index 5c48cf2f..dba0c951 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt @@ -13,6 +13,9 @@ import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.main.MainActivity +import io.github.wulkanowy.utils.AppInfo +import io.github.wulkanowy.utils.openEmail +import io.github.wulkanowy.utils.openInternetBrowser import io.github.wulkanowy.utils.setOnItemClickListener import kotlinx.android.synthetic.main.fragment_login_student_select.* import java.io.Serializable @@ -26,6 +29,9 @@ class LoginStudentSelectFragment : BaseFragment(), LoginStudentSelectView { @Inject lateinit var loginAdapter: FlexibleAdapter> + @Inject + lateinit var appInfo: AppInfo + companion object { const val SAVED_STUDENTS = "STUDENTS" @@ -44,6 +50,8 @@ class LoginStudentSelectFragment : BaseFragment(), LoginStudentSelectView { override fun initView() { loginStudentSelectSignIn.setOnClickListener { presenter.onSignIn() } loginAdapter.apply { setOnItemClickListener { presenter.onItemSelected(it) } } + loginStudentSelectContactDiscord.setOnClickListener { presenter.onDiscordClick() } + loginStudentSelectContactEmail.setOnClickListener { presenter.onEmailClick() } loginStudentSelectRecycler.apply { adapter = loginAdapter @@ -80,8 +88,25 @@ class LoginStudentSelectFragment : BaseFragment(), LoginStudentSelectView { outState.putSerializable(SAVED_STUDENTS, presenter.students as Serializable) } + override fun showContact(show: Boolean) { + loginStudentSelectContact.visibility = if (show) VISIBLE else GONE + } + override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() } + + override fun openDiscordInvite() { + context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) + } + + override fun openEmail() { + context?.openEmail( + requireContext().getString(R.string.login_email_intent_title), + "wulkanowyinc@gmail.com", + requireContext().getString(R.string.login_email_subject), + requireContext().getString(R.string.login_email_text, appInfo.systemModel, appInfo.systemVersion.toString(), appInfo.versionName) + ) + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt index e02227cb..288531dc 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt @@ -27,6 +27,7 @@ class LoginStudentSelectPresenter @Inject constructor( super.onAttachView(view) view.run { initView() + showContact(false) enableSignIn(false) loginErrorHandler.onStudentDuplicate = { showMessage(it) @@ -88,7 +89,16 @@ class LoginStudentSelectPresenter @Inject constructor( view?.apply { showProgress(false) showContent(true) + showContact(true) } })) } + + fun onDiscordClick() { + view?.openDiscordInvite() + } + + fun onEmailClick() { + view?.openEmail() + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt index 3967313c..23877100 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt @@ -15,4 +15,10 @@ interface LoginStudentSelectView : BaseView { fun showContent(show: Boolean) fun enableSignIn(enable: Boolean) + + fun showContact(show: Boolean) + + fun openDiscordInvite() + + fun openEmail() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt index f4f0eb9e..724e3fbb 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt @@ -14,7 +14,10 @@ import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.login.LoginActivity +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.hideSoftInput +import io.github.wulkanowy.utils.openEmail +import io.github.wulkanowy.utils.openInternetBrowser import io.github.wulkanowy.utils.showSoftInput import kotlinx.android.synthetic.main.fragment_login_symbol.* import javax.inject.Inject @@ -24,6 +27,9 @@ class LoginSymbolFragment : BaseFragment(), LoginSymbolView { @Inject lateinit var presenter: LoginSymbolPresenter + @Inject + lateinit var appInfo: AppInfo + companion object { private const val SAVED_LOGIN_DATA = "LOGIN_DATA" @@ -44,6 +50,8 @@ class LoginSymbolFragment : BaseFragment(), LoginSymbolView { override fun initView() { loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) } + loginSymbolContactDiscord.setOnClickListener { presenter.onDiscordClick() } + loginSymbolContactEmail.setOnClickListener { presenter.onEmailClick() } loginSymbolName.doOnTextChanged { _, _, _, _ -> presenter.onSymbolTextChanged() } @@ -109,8 +117,25 @@ class LoginSymbolFragment : BaseFragment(), LoginSymbolView { outState.putSerializable(SAVED_LOGIN_DATA, presenter.loginData) } + override fun showContact(show: Boolean) { + loginSymbolContact.visibility = if (show) VISIBLE else GONE + } + override fun onDestroyView() { super.onDestroyView() presenter.onDetachView() } + + override fun openDiscordInvite() { + context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) + } + + override fun openEmail() { + context?.openEmail( + requireContext().getString(R.string.login_email_intent_title), + "wulkanowyinc@gmail.com", + requireContext().getString(R.string.login_email_subject), + requireContext().getString(R.string.login_email_text, appInfo.systemModel, appInfo.systemVersion.toString(), appInfo.versionName) + ) + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt index 5a7a3777..8e4dd3b0 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt @@ -23,7 +23,10 @@ class LoginSymbolPresenter @Inject constructor( @Suppress("UNCHECKED_CAST") fun onAttachView(view: LoginSymbolView, savedLoginData: Serializable?) { super.onAttachView(view) - view.initView() + view.run { + initView() + showContact(false) + } if (savedLoginData is Triple<*, *, *>) { loginData = savedLoginData as Triple } @@ -64,6 +67,7 @@ class LoginSymbolPresenter @Inject constructor( if (it.isEmpty()) { Timber.i("Login with symbol result: Empty student list") setErrorSymbolIncorrect() + view?.showContact(true) } else { Timber.i("Login with symbol result: Success") notifyParentAccountLogged(it) @@ -73,6 +77,7 @@ class LoginSymbolPresenter @Inject constructor( Timber.i("Login with symbol result: An exception occurred") analytics.logEvent("registration_symbol", "success" to false, "students" to -1, "endpoint" to loginData?.third, "symbol" to symbol, "error" to it.message.ifNullOrBlank { "No message" }) loginErrorHandler.dispatch(it) + view?.showContact(true) })) } @@ -83,4 +88,12 @@ class LoginSymbolPresenter @Inject constructor( showSoftKeyboard() } } + + fun onDiscordClick() { + view?.openDiscordInvite() + } + + fun onEmailClick() { + view?.openEmail() + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt index 2e5143ef..9b5340cf 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt @@ -26,4 +26,10 @@ interface LoginSymbolView : BaseView { fun showContent(show: Boolean) fun notifyParentAccountLogged(students: List) + + fun showContact(show: Boolean) + + fun openDiscordInvite() + + fun openEmail() } diff --git a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt index a941c6fa..84200b3a 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt @@ -2,12 +2,14 @@ package io.github.wulkanowy.utils import android.content.Context import android.content.Intent +import android.net.Uri import android.util.DisplayMetrics.DENSITY_DEFAULT import androidx.annotation.AttrRes import androidx.annotation.ColorInt import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.core.content.ContextCompat +import io.github.wulkanowy.R @ColorInt fun Context.getThemeAttrColor(@AttrRes colorAttr: Int): Int { @@ -31,4 +33,12 @@ fun Context.openInternetBrowser(uri: String, onActivityNotFound: (uri: String) - } } +fun Context.openEmail(chooserTitle: String, email: String, subject: String?, body: String?) { + val emailIntent = Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", email, null)) + emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(email)) + if (subject != null) emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject) + if (body != null) emailIntent.putExtra(Intent.EXTRA_TEXT, body) + startActivity(Intent.createChooser(emailIntent, chooserTitle)) +} + fun Context.dpToPx(dp: Float) = dp * resources.displayMetrics.densityDpi / DENSITY_DEFAULT diff --git a/app/src/main/res/layout/fragment_login_form.xml b/app/src/main/res/layout/fragment_login_form.xml index 7627e71b..545b7726 100644 --- a/app/src/main/res/layout/fragment_login_form.xml +++ b/app/src/main/res/layout/fragment_login_form.xml @@ -25,15 +25,79 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_login_student_select.xml b/app/src/main/res/layout/fragment_login_student_select.xml index d123b553..64e06cbd 100644 --- a/app/src/main/res/layout/fragment_login_student_select.xml +++ b/app/src/main/res/layout/fragment_login_student_select.xml @@ -19,6 +19,76 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Symbol znajdziesz na stronie dziennika w Uczeń -> Dostęp Mobilny -> Zarejestruj urządzenie mobilne Wybierz uczniów do zalogowania w aplikacji Polityka prywatności + Problemy z logowaniem? Napisz do nas! + Email + Discord + Wyślij email diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 27e43dc5..c4b5218d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -36,6 +36,12 @@ The symbol can be found on the register page in Uczeń -> Dostęp Mobilny -> Zarejestruj urządzenie mobilne Select students to log in to the application Privacy policy + Trouble signing in? Contact us! + Email + Discord + Send email + Zgłoszenie: Problemy z logowaniem + Informacje o aplikacji:\n\nUrządzenie: %1$s\nWersja SDK: %2$s\nWersja aplikacji: %3$s\n\nOpis problemu: From d9b5e000f8ad1c8664189ec3f26189e0de07e0a2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2019 19:23:13 +0000 Subject: [PATCH 07/22] Bump gradle from 1.31.1 to 1.31.2 (#560) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c3abf9ad..6c004f6f 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.android.tools.build:gradle:3.5.1' classpath 'com.google.gms:google-services:4.3.2' - classpath "io.fabric.tools:gradle:1.31.1" + classpath "io.fabric.tools:gradle:1.31.2" classpath "com.github.triplet.gradle:play-publisher:2.4.2" classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.8" classpath "gradle.plugin.com.star-zero.gradle:githook:1.2.0" From 1b492d50fec9d09a3e301ef85002f7f35ee69f88 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2019 19:23:41 +0000 Subject: [PATCH 08/22] Bump aboutlibraries from 7.0.3 to 7.0.4 (#559) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 78b4020c..b70a74d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -174,7 +174,7 @@ dependencies { implementation "com.jakewharton.timber:timber:4.7.1" implementation "at.favre.lib:slf4j-timber:1.0.1" implementation "com.squareup.okhttp3:logging-interceptor:3.12.6" - implementation "com.mikepenz:aboutlibraries:7.0.3" + implementation "com.mikepenz:aboutlibraries:7.0.4" playImplementation "com.google.firebase:firebase-core:17.2.0" playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1" From 7a4cf694ca58f331e814aca09fae7cb11a32fcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Mon, 21 Oct 2019 21:25:15 +0200 Subject: [PATCH 09/22] Add school info (#557) * Add db layer to school info * Add base classes * Add database migration * Add base view * Update icon * Fix textviews height * Handle error and empty results * Improve school info look * Add strings * Fix action bar elevation in school fragment * Add missing blank lines * Reorganize strings * Make field title first in order * Make fields views selectable * Rename SchoolInfo to School --- .../18.json | 1592 +++++++++++++++++ .../github/wulkanowy/data/RepositoryModule.kt | 4 + .../github/wulkanowy/data/db/AppDatabase.kt | 13 +- .../github/wulkanowy/data/db/dao/SchoolDao.kt | 23 + .../wulkanowy/data/db/dao/TeacherDao.kt | 4 +- .../wulkanowy/data/db/entities/School.kt | 30 + .../data/db/migrations/Migration18.kt | 22 + .../data/repositories/school/SchoolLocal.kt | 22 + .../data/repositories/school/SchoolRemote.kt | 26 + .../repositories/school/SchoolRepository.kt | 41 + .../data/repositories/teacher/TeacherLocal.kt | 3 +- .../repositories/teacher/TeacherRepository.kt | 1 + .../wulkanowy/ui/modules/main/MainModule.kt | 8 +- .../ui/modules/main/MainPresenter.kt | 3 +- .../wulkanowy/ui/modules/main/MainView.kt | 3 +- .../wulkanowy/ui/modules/more/MoreFragment.kt | 11 +- .../ui/modules/more/MorePresenter.kt | 4 +- .../wulkanowy/ui/modules/more/MoreView.kt | 4 +- .../SchoolAndTeachersChildView.kt | 8 + .../SchoolAndTeachersFragment.kt | 87 + .../SchoolAndTeachersModule.kt | 32 + .../SchoolAndTeachersPresenter.kt | 47 + .../SchoolAndTeachersView.kt | 16 + .../school/SchoolFragment.kt | 80 + .../school/SchoolPresenter.kt | 70 + .../schoolandteachers/school/SchoolView.kt | 22 + .../teacher/TeacherFragment.kt | 15 +- .../teacher/TeacherItem.kt | 2 +- .../teacher/TeacherPresenter.kt | 10 +- .../teacher/TeacherView.kt | 5 +- .../wulkanowy/utils/FragmentExtension.kt | 2 + .../drawable/ic_more_schoolandteachers.xml | 9 + app/src/main/res/drawable/ic_more_teacher.xml | 7 - app/src/main/res/layout/fragment_school.xml | 195 ++ .../res/layout/fragment_schoolandteachers.xml | 38 + app/src/main/res/layout/fragment_teacher.xml | 3 +- app/src/main/res/layout/item_teacher.xml | 3 +- app/src/main/res/values-pl/strings.xml | 13 + app/src/main/res/values/strings.xml | 13 + 39 files changed, 2453 insertions(+), 38 deletions(-) create mode 100644 app/schemas/io.github.wulkanowy.data.db.AppDatabase/18.json create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/entities/School.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersChildView.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersFragment.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersPresenter.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersView.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt rename app/src/main/java/io/github/wulkanowy/ui/modules/{ => schoolandteachers}/teacher/TeacherFragment.kt (84%) rename app/src/main/java/io/github/wulkanowy/ui/modules/{ => schoolandteachers}/teacher/TeacherItem.kt (97%) rename app/src/main/java/io/github/wulkanowy/ui/modules/{ => schoolandteachers}/teacher/TeacherPresenter.kt (89%) rename app/src/main/java/io/github/wulkanowy/ui/modules/{ => schoolandteachers}/teacher/TeacherView.kt (69%) create mode 100644 app/src/main/res/drawable/ic_more_schoolandteachers.xml delete mode 100644 app/src/main/res/drawable/ic_more_teacher.xml create mode 100644 app/src/main/res/layout/fragment_school.xml create mode 100644 app/src/main/res/layout/fragment_schoolandteachers.xml diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/18.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/18.json new file mode 100644 index 00000000..4f7497fe --- /dev/null +++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/18.json @@ -0,0 +1,1592 @@ +{ + "formatVersion": 1, + "database": { + "version": 18, + "identityHash": "73b1dcfe0cf84170ba102b2818dd0191", + "entities": [ + { + "tableName": "Students", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "endpoint", + "columnName": "endpoint", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginType", + "columnName": "loginType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "symbol", + "columnName": "symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentName", + "columnName": "student_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolSymbol", + "columnName": "school_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolName", + "columnName": "school_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "className", + "columnName": "class_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "registrationDate", + "columnName": "registration_date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Students_email_symbol_student_id_school_id_class_id", + "unique": true, + "columnNames": [ + "email", + "symbol", + "student_id", + "school_id", + "class_id" + ], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Semesters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryName", + "columnName": "diary_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolYear", + "columnName": "school_year", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterName", + "columnName": "semester_name", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Semesters_student_id_diary_id_semester_id", + "unique": true, + "columnNames": [ + "student_id", + "diary_id", + "semester_id" + ], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Exams", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Timetable", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subjectOld", + "columnName": "subjectOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "room", + "columnName": "room", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roomOld", + "columnName": "roomOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherOld", + "columnName": "teacherOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "info", + "columnName": "info", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "changes", + "columnName": "changes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "canceled", + "columnName": "canceled", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Attendance", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excused", + "columnName": "excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deleted", + "columnName": "deleted", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "AttendanceSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subjectId", + "columnName": "subject_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "month", + "columnName": "month", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceExcused", + "columnName": "absence_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceForSchoolReasons", + "columnName": "absence_for_school_reasons", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "latenessExcused", + "columnName": "lateness_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Grades", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` INTEGER NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entry", + "columnName": "entry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "modifier", + "columnName": "modifier", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gradeSymbol", + "columnName": "grade_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weightValue", + "columnName": "weightValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "predictedGrade", + "columnName": "predicted_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalGrade", + "columnName": "final_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "proposedPoints", + "columnName": "proposed_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalPoints", + "columnName": "final_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pointsSum", + "columnName": "points_sum", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "average", + "columnName": "average", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "grade", + "columnName": "grade", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semester", + "columnName": "is_semester", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesPointsStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "others", + "columnName": "others", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "student", + "columnName": "student", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Messages", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recipient", + "columnName": "recipient_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "folderId", + "columnName": "folder_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unreadBy", + "columnName": "unread_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "readBy", + "columnName": "read_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "removed", + "columnName": "removed", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Notes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `category` TEXT NOT NULL, `content` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Homework", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Subjects", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "LuckyNumbers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "luckyNumber", + "columnName": "lucky_number", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CompletedLesson", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "topic", + "columnName": "topic", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "substitution", + "columnName": "substitution", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "resources", + "columnName": "resources", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ReportingUnits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderName", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roles", + "columnName": "roles", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Recipients", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "realName", + "columnName": "real_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginId", + "columnName": "login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "role", + "columnName": "role", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MobileDevices", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deviceId", + "columnName": "device_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Teachers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short_name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "School", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "address", + "columnName": "address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contact", + "columnName": "contact", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "headmaster", + "columnName": "headmaster", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pedagogue", + "columnName": "pedagogue", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '73b1dcfe0cf84170ba102b2818dd0191')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt index b3686f5e..9c89d507 100644 --- a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt +++ b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt @@ -144,4 +144,8 @@ internal class RepositoryModule { @Singleton @Provides fun provideTeacherDao(database: AppDatabase) = database.teacherDao + + @Singleton + @Provides + fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt index 4dcba3e1..b1896c75 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt @@ -22,6 +22,7 @@ import io.github.wulkanowy.data.db.dao.MobileDeviceDao import io.github.wulkanowy.data.db.dao.NoteDao import io.github.wulkanowy.data.db.dao.RecipientDao import io.github.wulkanowy.data.db.dao.ReportingUnitDao +import io.github.wulkanowy.data.db.dao.SchoolDao import io.github.wulkanowy.data.db.dao.SemesterDao import io.github.wulkanowy.data.db.dao.StudentDao import io.github.wulkanowy.data.db.dao.SubjectDao @@ -42,6 +43,7 @@ import io.github.wulkanowy.data.db.entities.MobileDevice import io.github.wulkanowy.data.db.entities.Note import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.ReportingUnit +import io.github.wulkanowy.data.db.entities.School import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Subject @@ -55,6 +57,7 @@ import io.github.wulkanowy.data.db.migrations.Migration14 import io.github.wulkanowy.data.db.migrations.Migration15 import io.github.wulkanowy.data.db.migrations.Migration16 import io.github.wulkanowy.data.db.migrations.Migration17 +import io.github.wulkanowy.data.db.migrations.Migration18 import io.github.wulkanowy.data.db.migrations.Migration2 import io.github.wulkanowy.data.db.migrations.Migration3 import io.github.wulkanowy.data.db.migrations.Migration4 @@ -87,7 +90,8 @@ import javax.inject.Singleton ReportingUnit::class, Recipient::class, MobileDevice::class, - Teacher::class + Teacher::class, + School::class ], version = AppDatabase.VERSION_SCHEMA, exportSchema = true @@ -96,7 +100,7 @@ import javax.inject.Singleton abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION_SCHEMA = 17 + const val VERSION_SCHEMA = 18 fun getMigrations(): Array { return arrayOf( @@ -115,7 +119,8 @@ abstract class AppDatabase : RoomDatabase() { Migration14(), Migration15(), Migration16(), - Migration17() + Migration17(), + Migration18() ) } @@ -168,4 +173,6 @@ abstract class AppDatabase : RoomDatabase() { abstract val mobileDeviceDao: MobileDeviceDao abstract val teacherDao: TeacherDao + + abstract val schoolDao: SchoolDao } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt new file mode 100644 index 00000000..c2b2e0bc --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt @@ -0,0 +1,23 @@ +package io.github.wulkanowy.data.db.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Query +import io.github.wulkanowy.data.db.entities.School +import io.reactivex.Maybe +import javax.inject.Singleton + +@Singleton +@Dao +interface SchoolDao { + + @Insert + fun insert(school: School) + + @Delete + fun delete(school: School) + + @Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId") + fun load(studentId: Int, classId: Int): Maybe +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt index ad0b8924..e7794248 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt @@ -13,10 +13,10 @@ import javax.inject.Singleton interface TeacherDao { @Insert - fun insertAll(devices: List) + fun insertAll(teachers: List) @Delete - fun deleteAll(devices: List) + fun deleteAll(teachers: List) @Query("SELECT * FROM Teachers WHERE student_id = :studentId AND class_id = :classId") fun loadAll(studentId: Int, classId: Int): Maybe> diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/School.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/School.kt new file mode 100644 index 00000000..20fae450 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/School.kt @@ -0,0 +1,30 @@ +package io.github.wulkanowy.data.db.entities + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import java.io.Serializable + +@Entity(tableName = "School") +data class School( + + @ColumnInfo(name = "student_id") + val studentId: Int, + + @ColumnInfo(name = "class_id") + val classId: Int, + + val name: String, + + val address: String, + + val contact: String, + + val headmaster: String, + + val pedagogue: String +) : Serializable { + + @PrimaryKey(autoGenerate = true) + var id: Long = 0 +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt new file mode 100644 index 00000000..6c5e56c6 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt @@ -0,0 +1,22 @@ +package io.github.wulkanowy.data.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration18 : Migration(17, 18) { + + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" + CREATE TABLE IF NOT EXISTS School ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + student_id INTEGER NOT NULL, + class_id INTEGER NOT NULL, + name TEXT NOT NULL, + address TEXT NOT NULL, + contact TEXT NOT NULL, + headmaster TEXT NOT NULL, + pedagogue TEXT NOT NULL + ) + """) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt new file mode 100644 index 00000000..1692e39b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt @@ -0,0 +1,22 @@ +package io.github.wulkanowy.data.repositories.school + +import io.github.wulkanowy.data.db.dao.SchoolDao +import io.github.wulkanowy.data.db.entities.School +import io.github.wulkanowy.data.db.entities.Semester +import io.reactivex.Maybe +import javax.inject.Inject + +class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) { + + fun saveSchool(school: School) { + schoolDb.insert(school) + } + + fun deleteSchool(school: School) { + schoolDb.delete(school) + } + + fun getSchool(semester: Semester): Maybe { + return schoolDb.load(semester.studentId, semester.classId) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt new file mode 100644 index 00000000..86e05f0f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt @@ -0,0 +1,26 @@ +package io.github.wulkanowy.data.repositories.school + +import io.github.wulkanowy.api.Api +import io.github.wulkanowy.data.db.entities.School +import io.github.wulkanowy.data.db.entities.Semester +import io.reactivex.Single +import javax.inject.Inject + +class SchoolRemote @Inject constructor(private val api: Api) { + + fun getSchoolInfo(semester: Semester): Single { + return Single.just(api.apply { diaryId = semester.diaryId }) + .flatMap { it.getSchool() } + .map { + School( + studentId = semester.studentId, + classId = semester.classId, + name = it.name, + address = it.address, + contact = it.contact, + headmaster = it.headmaster, + pedagogue = it.pedagogue + ) + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt new file mode 100644 index 00000000..a352324d --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt @@ -0,0 +1,41 @@ +package io.github.wulkanowy.data.repositories.school + +import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork +import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings +import io.github.wulkanowy.data.db.entities.School +import io.github.wulkanowy.data.db.entities.Semester +import io.reactivex.Maybe +import io.reactivex.Single +import java.net.UnknownHostException +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SchoolRepository @Inject constructor( + private val settings: InternetObservingSettings, + private val local: SchoolLocal, + private val remote: SchoolRemote +) { + + fun getSchoolInfo(semester: Semester, forceRefresh: Boolean = false): Maybe { + return local.getSchool(semester).filter { !forceRefresh } + .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) + .flatMap { + if (it) remote.getSchoolInfo(semester) + else Single.error(UnknownHostException()) + }.flatMapMaybe { new -> + local.getSchool(semester) + .doOnSuccess { old -> + if (new != old) { + local.deleteSchool(old) + local.saveSchool(new) + } + } + .doOnComplete { + local.saveSchool(new) + } + }.flatMap({ local.getSchool(semester) }, { Maybe.error(it) }, + { local.getSchool(semester) }) + ) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt index 9ff11b7a..dd2be5e5 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt @@ -6,7 +6,8 @@ import io.github.wulkanowy.data.db.entities.Teacher import io.reactivex.Maybe import javax.inject.Inject -class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) { +class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) { + fun saveTeachers(teachers: List) { teacherDb.insertAll(teachers) } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt index 8db0b44c..19e7a32b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt @@ -16,6 +16,7 @@ class TeacherRepository @Inject constructor( private val local: TeacherLocal, private val remote: TeacherRemote ) { + fun getTeachers(semester: Semester, forceRefresh: Boolean = false): Single> { return local.getTeachers(semester).filter { !forceRefresh } .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt index 29adcf89..095a320a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt @@ -26,8 +26,10 @@ import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceModule import io.github.wulkanowy.ui.modules.mobiledevice.token.MobileDeviceTokenDialog import io.github.wulkanowy.ui.modules.more.MoreFragment import io.github.wulkanowy.ui.modules.note.NoteFragment +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersModule import io.github.wulkanowy.ui.modules.settings.SettingsFragment -import io.github.wulkanowy.ui.modules.teacher.TeacherFragment +import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment @@ -123,6 +125,6 @@ abstract class MainModule { abstract fun bindLicenseFragment(): LicenseFragment @PerFragment - @ContributesAndroidInjector - abstract fun bindTeacherFragment(): TeacherFragment + @ContributesAndroidInjector(modules = [SchoolAndTeachersModule::class]) + abstract fun bindSchoolAndTeachersFragment(): SchoolAndTeachersFragment } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt index 07e4c8d0..1c0fd39f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt @@ -7,6 +7,7 @@ import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.main.MainView.Section.GRADE import io.github.wulkanowy.ui.modules.main.MainView.Section.MESSAGE +import io.github.wulkanowy.ui.modules.main.MainView.Section.SCHOOL import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.SchedulersProvider import timber.log.Timber @@ -38,7 +39,7 @@ class MainPresenter @Inject constructor( fun onViewChange(section: MainView.Section?) { view?.apply { - showActionBarElevation(section != GRADE && section != MESSAGE) + showActionBarElevation(section != GRADE && section != MESSAGE && section != SCHOOL) currentViewTitle?.let { setViewTitle(it) } currentStackSize?.let { if (it > 1) showHomeArrow(true) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt index c53adc5b..033b6a1f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt @@ -51,6 +51,7 @@ interface MainView : BaseView { NOTE(7), LUCKY_NUMBER(8), SETTINGS(9), - ABOUT(10) + ABOUT(10), + SCHOOL(11) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt index 8d26bfc3..7a9625c0 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt @@ -18,8 +18,9 @@ import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.message.MessageFragment import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment import io.github.wulkanowy.ui.modules.note.NoteFragment +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment import io.github.wulkanowy.ui.modules.settings.SettingsFragment -import io.github.wulkanowy.ui.modules.teacher.TeacherFragment +import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment import io.github.wulkanowy.utils.getCompatDrawable import io.github.wulkanowy.utils.setOnItemClickListener import kotlinx.android.synthetic.main.fragment_more.* @@ -55,8 +56,8 @@ class MoreFragment : BaseFragment(), MoreView, MainView.TitledView, MainView.Mai override val mobileDevicesRes: Pair? get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) } - override val teachersRes: Pair? - get() = context?.run { getString(R.string.teachers_title) to getCompatDrawable((R.drawable.ic_more_teacher)) } + override val schoolAndTeachersRes: Pair? + get() = context?.run { getString(R.string.schoolandteachers_title) to getCompatDrawable((R.drawable.ic_more_schoolandteachers)) } override val settingsRes: Pair? get() = context?.run { getString(R.string.settings_title) to getCompatDrawable(R.drawable.ic_more_settings) } @@ -110,8 +111,8 @@ class MoreFragment : BaseFragment(), MoreView, MainView.TitledView, MainView.Mai (activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance()) } - override fun openTeachersView() { - (activity as? MainActivity)?.pushView(TeacherFragment.newInstance()) + override fun openSchoolAndTeachersView() { + (activity as? MainActivity)?.pushView(SchoolAndTeachersFragment.newInstance()) } override fun openSettingsView() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt index b77b7c01..096f89e9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt @@ -31,7 +31,7 @@ class MorePresenter @Inject constructor( noteRes?.first -> openNoteView() luckyNumberRes?.first -> openLuckyNumberView() mobileDevicesRes?.first -> openMobileDevicesView() - teachersRes?.first -> openTeachersView() + schoolAndTeachersRes?.first -> openSchoolAndTeachersView() settingsRes?.first -> openSettingsView() aboutRes?.first -> openAboutView() } @@ -52,7 +52,7 @@ class MorePresenter @Inject constructor( noteRes?.let { MoreItem(it.first, it.second) }, luckyNumberRes?.let { MoreItem(it.first, it.second) }, mobileDevicesRes?.let { MoreItem(it.first, it.second) }, - teachersRes?.let { MoreItem(it.first, it.second) }, + schoolAndTeachersRes?.let { MoreItem(it.first, it.second) }, settingsRes?.let { MoreItem(it.first, it.second) }, aboutRes?.let { MoreItem(it.first, it.second) }) ) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt index 247705de..41008176 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt @@ -15,7 +15,7 @@ interface MoreView : BaseView { val mobileDevicesRes: Pair? - val teachersRes: Pair? + val schoolAndTeachersRes: Pair? val settingsRes: Pair? @@ -41,5 +41,5 @@ interface MoreView : BaseView { fun openMobileDevicesView() - fun openTeachersView() + fun openSchoolAndTeachersView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersChildView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersChildView.kt new file mode 100644 index 00000000..b5eedb6f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersChildView.kt @@ -0,0 +1,8 @@ +package io.github.wulkanowy.ui.modules.schoolandteachers + +interface SchoolAndTeachersChildView { + + fun notifyParentDataLoaded() + + fun onParentLoadData(forceRefresh: Boolean) +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersFragment.kt new file mode 100644 index 00000000..5f9c0b9a --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersFragment.kt @@ -0,0 +1,87 @@ +package io.github.wulkanowy.ui.modules.schoolandteachers + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.View.INVISIBLE +import android.view.View.VISIBLE +import android.view.ViewGroup +import io.github.wulkanowy.R +import io.github.wulkanowy.ui.base.BaseFragment +import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter +import io.github.wulkanowy.ui.modules.main.MainView +import io.github.wulkanowy.ui.modules.schoolandteachers.school.SchoolFragment +import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment +import io.github.wulkanowy.utils.dpToPx +import io.github.wulkanowy.utils.setOnSelectPageListener +import kotlinx.android.synthetic.main.fragment_schoolandteachers.* +import javax.inject.Inject + +class SchoolAndTeachersFragment : BaseFragment(), SchoolAndTeachersView, MainView.TitledView { + + @Inject + lateinit var presenter: SchoolAndTeachersPresenter + + @Inject + lateinit var pagerAdapter: BaseFragmentPagerAdapter + + companion object { + fun newInstance() = SchoolAndTeachersFragment() + } + + override val titleStringId: Int get() = R.string.schoolandteachers_title + + override val currentPageIndex get() = schoolandteachersViewPager.currentItem + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_schoolandteachers, container, false) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + presenter.onAttachView(this) + } + + override fun initView() { + with(pagerAdapter) { + containerId = schoolandteachersViewPager.id + addFragmentsWithTitle(mapOf( + SchoolFragment.newInstance() to getString(R.string.school_title), + TeacherFragment.newInstance() to getString(R.string.teachers_title) + )) + } + + with(schoolandteachersViewPager) { + adapter = pagerAdapter + offscreenPageLimit = 2 + setOnSelectPageListener(presenter::onPageSelected) + } + + with(schoolandteachersTabLayout) { + setupWithViewPager(schoolandteachersViewPager) + setElevationCompat(context.dpToPx(4f)) + } + } + + override fun showContent(show: Boolean) { + schoolandteachersViewPager.visibility = if (show) VISIBLE else INVISIBLE + schoolandteachersTabLayout.visibility = if (show) VISIBLE else INVISIBLE + } + + override fun showProgress(show: Boolean) { + schoolandteachersProgress.visibility = if (show) VISIBLE else INVISIBLE + } + + fun onChildFragmentLoaded() { + presenter.onChildViewLoaded() + } + + override fun notifyChildLoadData(index: Int, forceRefresh: Boolean) { + (pagerAdapter.getFragmentInstance(index) as? SchoolAndTeachersChildView)?.onParentLoadData(forceRefresh) + } + + override fun onDestroyView() { + presenter.onDetachView() + super.onDestroyView() + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt new file mode 100644 index 00000000..1c083f8a --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt @@ -0,0 +1,32 @@ +package io.github.wulkanowy.ui.modules.schoolandteachers + +import dagger.Module +import dagger.Provides +import dagger.android.ContributesAndroidInjector +import io.github.wulkanowy.di.scopes.PerChildFragment +import io.github.wulkanowy.di.scopes.PerFragment +import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter +import io.github.wulkanowy.ui.modules.schoolandteachers.school.SchoolFragment +import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment + +@Suppress("unused") +@Module +abstract class SchoolAndTeachersModule { + + @Module + companion object { + + @JvmStatic + @PerFragment + @Provides + fun provideSchoolAndTeachersAdapter(fragment: SchoolAndTeachersFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager) + } + + @PerChildFragment + @ContributesAndroidInjector + abstract fun provideSchoolFragment(): SchoolFragment + + @PerChildFragment + @ContributesAndroidInjector + abstract fun provideTeacherFragment(): TeacherFragment +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersPresenter.kt new file mode 100644 index 00000000..1856803c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersPresenter.kt @@ -0,0 +1,47 @@ +package io.github.wulkanowy.ui.modules.schoolandteachers + +import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.ui.base.BasePresenter +import io.github.wulkanowy.ui.base.ErrorHandler +import io.github.wulkanowy.utils.SchedulersProvider +import io.reactivex.Completable +import timber.log.Timber +import java.util.concurrent.TimeUnit +import javax.inject.Inject + +class SchoolAndTeachersPresenter @Inject constructor( + schedulers: SchedulersProvider, + errorHandler: ErrorHandler, + studentRepository: StudentRepository +) : BasePresenter(errorHandler, studentRepository, schedulers) { + + override fun onAttachView(view: SchoolAndTeachersView) { + super.onAttachView(view) + disposable.add(Completable.timer(150, TimeUnit.MILLISECONDS, schedulers.mainThread) + .subscribe { + view.initView() + Timber.i("Message view was initialized") + loadData() + }) + } + + fun onPageSelected(index: Int) { + loadChild(index) + } + + private fun loadData() { + view?.run { loadChild(currentPageIndex) } + } + + private fun loadChild(index: Int, forceRefresh: Boolean = false) { + Timber.i("Load schoolandteachers child view index: $index") + view?.notifyChildLoadData(index, forceRefresh) + } + + fun onChildViewLoaded() { + view?.apply { + showContent(true) + showProgress(false) + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersView.kt new file mode 100644 index 00000000..594441ec --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersView.kt @@ -0,0 +1,16 @@ +package io.github.wulkanowy.ui.modules.schoolandteachers + +import io.github.wulkanowy.ui.base.BaseView + +interface SchoolAndTeachersView : BaseView { + + val currentPageIndex: Int + + fun initView() + + fun showContent(show: Boolean) + + fun showProgress(show: Boolean) + + fun notifyChildLoadData(index: Int, forceRefresh: Boolean) +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt new file mode 100644 index 00000000..6c17f5ed --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt @@ -0,0 +1,80 @@ +package io.github.wulkanowy.ui.modules.schoolandteachers.school + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import io.github.wulkanowy.R +import io.github.wulkanowy.data.db.entities.School +import io.github.wulkanowy.ui.base.BaseFragment +import io.github.wulkanowy.ui.modules.main.MainView +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment +import kotlinx.android.synthetic.main.fragment_school.* +import javax.inject.Inject + +class SchoolFragment : BaseFragment(), SchoolView, MainView.TitledView, SchoolAndTeachersChildView { + + @Inject + lateinit var presenter: SchoolPresenter + + override val titleStringId get() = R.string.school_title + + companion object { + fun newInstance() = SchoolFragment() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_school, container, false) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + presenter.onAttachView(this) + } + + override fun initView() { + schoolSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } + } + + override fun updateData(data: School) { + schoolName.text = data.name + schoolAddress.text = data.address.ifBlank { "-" } + schoolTelephone.text = data.contact.ifBlank { "-" } + schoolHeadmaster.text = data.headmaster + schoolPedagogue.text = data.pedagogue + } + + override fun showEmpty(show: Boolean) { + schoolEmpty.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun showProgress(show: Boolean) { + schoolProgress.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun enableSwipe(enable: Boolean) { + schoolSwipe.isEnabled = enable + } + + override fun showContent(show: Boolean) { + schoolContent.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun hideRefresh() { + schoolSwipe.isRefreshing = false + } + + override fun notifyParentDataLoaded() { + (parentFragment as? SchoolAndTeachersFragment)?.onChildFragmentLoaded() + } + + override fun onParentLoadData(forceRefresh: Boolean) { + presenter.onParentViewLoadData(forceRefresh) + } + + override fun onDestroyView() { + presenter.onDetachView() + super.onDestroyView() + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt new file mode 100644 index 00000000..f996b165 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt @@ -0,0 +1,70 @@ +package io.github.wulkanowy.ui.modules.schoolandteachers.school + +import io.github.wulkanowy.data.repositories.school.SchoolRepository +import io.github.wulkanowy.data.repositories.semester.SemesterRepository +import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.ui.base.BasePresenter +import io.github.wulkanowy.ui.base.ErrorHandler +import io.github.wulkanowy.utils.FirebaseAnalyticsHelper +import io.github.wulkanowy.utils.SchedulersProvider +import timber.log.Timber +import javax.inject.Inject + +class SchoolPresenter @Inject constructor( + schedulers: SchedulersProvider, + errorHandler: ErrorHandler, + studentRepository: StudentRepository, + private val semesterRepository: SemesterRepository, + private val schoolRepository: SchoolRepository, + private val analytics: FirebaseAnalyticsHelper +) : BasePresenter(errorHandler, studentRepository, schedulers) { + + override fun onAttachView(view: SchoolView) { + super.onAttachView(view) + view.initView() + Timber.i("School view was initialized") + loadData() + } + + fun onSwipeRefresh() { + loadData(true) + } + + fun onParentViewLoadData(forceRefresh: Boolean) { + loadData(forceRefresh) + } + + private fun loadData(forceRefresh: Boolean = false) { + Timber.i("Loading school info started") + disposable.add(studentRepository.getCurrentStudent() + .flatMap { semesterRepository.getCurrentSemester(it) } + .flatMapMaybe { schoolRepository.getSchoolInfo(it, forceRefresh) } + .subscribeOn(schedulers.backgroundThread) + .observeOn(schedulers.mainThread) + .doFinally { + view?.run { + hideRefresh() + showProgress(false) + enableSwipe(true) + notifyParentDataLoaded() + } + }.subscribe({ + Timber.i("Loading teachers result: Success") + view?.run { + updateData(it) + showContent(true) + showEmpty(false) + } + analytics.logEvent("load_school", "force_refresh" to forceRefresh) + }, { + Timber.i("Loading school result: An exception occurred") + errorHandler.dispatch(it) + }, { + Timber.i("Loading school result: No school info found") + view?.run { + showContent(false) + showEmpty(true) + } + })) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt new file mode 100644 index 00000000..5702278c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt @@ -0,0 +1,22 @@ +package io.github.wulkanowy.ui.modules.schoolandteachers.school + +import io.github.wulkanowy.data.db.entities.School +import io.github.wulkanowy.ui.base.BaseView +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView + +interface SchoolView : BaseView, SchoolAndTeachersChildView { + + fun initView() + + fun updateData(data: School) + + fun showEmpty(show: Boolean) + + fun showProgress(show: Boolean) + + fun enableSwipe(enable: Boolean) + + fun showContent(show: Boolean) + + fun hideRefresh() +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt similarity index 84% rename from app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherFragment.kt rename to app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt index d096f23b..842e50fe 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.ui.modules.teacher +package io.github.wulkanowy.ui.modules.schoolandteachers.teacher import android.os.Bundle import android.view.LayoutInflater @@ -11,10 +11,13 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import io.github.wulkanowy.R import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.main.MainView +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment import kotlinx.android.synthetic.main.fragment_teacher.* import javax.inject.Inject -class TeacherFragment : BaseFragment(), TeacherView, MainView.TitledView { +class TeacherFragment : BaseFragment(), TeacherView, MainView.TitledView, SchoolAndTeachersChildView { + @Inject lateinit var presenter: TeacherPresenter @@ -86,6 +89,14 @@ class TeacherFragment : BaseFragment(), TeacherView, MainView.TitledView { teacherSwipe.isRefreshing = false } + override fun notifyParentDataLoaded() { + (parentFragment as? SchoolAndTeachersFragment)?.onChildFragmentLoaded() + } + + override fun onParentLoadData(forceRefresh: Boolean) { + presenter.onParentViewLoadData(forceRefresh) + } + override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherItem.kt similarity index 97% rename from app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherItem.kt rename to app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherItem.kt index c5625138..36831774 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherItem.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.ui.modules.teacher +package io.github.wulkanowy.ui.modules.schoolandteachers.teacher import android.annotation.SuppressLint import android.view.View diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt similarity index 89% rename from app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherPresenter.kt rename to app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt index 8b504f8b..aabcff28 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.ui.modules.teacher +package io.github.wulkanowy.ui.modules.schoolandteachers.teacher import io.github.wulkanowy.data.repositories.semester.SemesterRepository import io.github.wulkanowy.data.repositories.student.StudentRepository @@ -14,7 +14,6 @@ class TeacherPresenter @Inject constructor( schedulers: SchedulersProvider, errorHandler: ErrorHandler, studentRepository: StudentRepository, - private val semesterRepository: SemesterRepository, private val teacherRepository: TeacherRepository, private val analytics: FirebaseAnalyticsHelper @@ -31,12 +30,16 @@ class TeacherPresenter @Inject constructor( loadData(true) } + fun onParentViewLoadData(forceRefresh: Boolean) { + loadData(forceRefresh) + } + private fun loadData(forceRefresh: Boolean = false) { Timber.i("Loading teachers data started") disposable.add(studentRepository.getCurrentStudent() .flatMap { semesterRepository.getCurrentSemester(it) } .flatMap { teacherRepository.getTeachers(it, forceRefresh) } - .map { it.filter { teacher -> teacher.name.isNotBlank() } } + .map { it.filter { teacher -> teacher.name.isNotBlank() } } .map { items -> items.map { TeacherItem(it, view?.noSubjectString.orEmpty()) } } .subscribeOn(schedulers.backgroundThread) .observeOn(schedulers.mainThread) @@ -45,6 +48,7 @@ class TeacherPresenter @Inject constructor( hideRefresh() showProgress(false) enableSwipe(true) + notifyParentDataLoaded() } }.subscribe({ Timber.i("Loading teachers result: Success") diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt similarity index 69% rename from app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherView.kt rename to app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt index 91fa995d..2cc1139c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/teacher/TeacherView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt @@ -1,9 +1,10 @@ -package io.github.wulkanowy.ui.modules.teacher +package io.github.wulkanowy.ui.modules.schoolandteachers.teacher import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import io.github.wulkanowy.ui.base.BaseView +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView -interface TeacherView : BaseView { +interface TeacherView : BaseView, SchoolAndTeachersChildView { val isViewEmpty: Boolean diff --git a/app/src/main/java/io/github/wulkanowy/utils/FragmentExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/FragmentExtension.kt index 1fc3185c..0b71c964 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/FragmentExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/FragmentExtension.kt @@ -11,6 +11,7 @@ import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.message.MessageFragment import io.github.wulkanowy.ui.modules.more.MoreFragment import io.github.wulkanowy.ui.modules.note.NoteFragment +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment import io.github.wulkanowy.ui.modules.settings.SettingsFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment @@ -27,6 +28,7 @@ fun Fragment.toSection(): MainView.Section? { is LuckyNumberFragment -> MainView.Section.LUCKY_NUMBER is SettingsFragment -> MainView.Section.SETTINGS is AboutFragment -> MainView.Section.ABOUT + is SchoolAndTeachersFragment -> MainView.Section.SCHOOL else -> null } } diff --git a/app/src/main/res/drawable/ic_more_schoolandteachers.xml b/app/src/main/res/drawable/ic_more_schoolandteachers.xml new file mode 100644 index 00000000..9cb9aee0 --- /dev/null +++ b/app/src/main/res/drawable/ic_more_schoolandteachers.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_more_teacher.xml b/app/src/main/res/drawable/ic_more_teacher.xml deleted file mode 100644 index bc8f93e4..00000000 --- a/app/src/main/res/drawable/ic_more_teacher.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/app/src/main/res/layout/fragment_school.xml b/app/src/main/res/layout/fragment_school.xml new file mode 100644 index 00000000..8f52d46b --- /dev/null +++ b/app/src/main/res/layout/fragment_school.xml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_schoolandteachers.xml b/app/src/main/res/layout/fragment_schoolandteachers.xml new file mode 100644 index 00000000..2b3f2203 --- /dev/null +++ b/app/src/main/res/layout/fragment_schoolandteachers.xml @@ -0,0 +1,38 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_teacher.xml b/app/src/main/res/layout/fragment_teacher.xml index af3b76a1..01cf8726 100644 --- a/app/src/main/res/layout/fragment_teacher.xml +++ b/app/src/main/res/layout/fragment_teacher.xml @@ -18,6 +18,7 @@ android:layout_height="match_parent"> @@ -36,7 +37,7 @@ diff --git a/app/src/main/res/layout/item_teacher.xml b/app/src/main/res/layout/item_teacher.xml index 55679dce..3bac0573 100644 --- a/app/src/main/res/layout/item_teacher.xml +++ b/app/src/main/res/layout/item_teacher.xml @@ -1,5 +1,4 @@ + tools:context=".ui.modules.schoolandteachers.teacher.TeacherItem"> PIN + + Szkoła i nauczyciele + + + + Szkoła + Nazwa szkoły + Adres szkoły + Telefon + Imię i nazwisko dyrektora + Imię i nazwisko pedagoga + + Nauczyciele Brak informacji o nauczycielach diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c4b5218d..eeee5838 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -207,6 +207,19 @@ PIN + + School and teachers + + + + School + School name + School address + Telephone + Name of headmaster + Name of pedagogue + + Teachers No info about teachers From b16b225a1af73b967946e2fe504898fa2c51464a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2019 05:55:08 +0000 Subject: [PATCH 10/22] Bump room from 2.2.0 to 2.2.1 (#562) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index b70a74d7..ea7425df 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,7 +111,7 @@ play { ext { work_manager = "2.3.0-alpha02" - room = "2.2.0" + room = "2.2.1" dagger = "2.24" chucker = "2.0.4" mockk = "1.9.2" From 90c60f399baaad02cd1f6eec4678d7560be8d634 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2019 06:15:58 +0000 Subject: [PATCH 11/22] Bump coordinatorlayout from 1.1.0-beta01 to 1.1.0-rc01 (#565) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index ea7425df..1cd2d534 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -139,7 +139,7 @@ dependencies { implementation "androidx.viewpager:viewpager:1.0.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03" implementation "androidx.constraintlayout:constraintlayout:1.1.3" - implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0-beta01" + implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0-rc01" implementation "com.google.android.material:material:1.1.0-alpha07" implementation "com.github.wulkanowy:material-chips-input:2.0.1" implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" From 994b162ae31f98f3d1b5b260632e11644b011582 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2019 06:16:51 +0000 Subject: [PATCH 12/22] Bump activity-ktx from 1.1.0-beta01 to 1.1.0-rc01 (#567) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 1cd2d534..ed6aa554 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,7 +127,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "androidx.core:core-ktx:1.2.0-beta01" - implementation "androidx.activity:activity-ktx:1.1.0-beta01" + implementation "androidx.activity:activity-ktx:1.1.0-rc01" implementation "androidx.appcompat:appcompat:1.1.0" implementation "androidx.appcompat:appcompat-resources:1.1.0" implementation "androidx.fragment:fragment-ktx:1.2.0-beta02" From 98fdfd001a472640aa7e5790e72ed7d02be0c2e4 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2019 06:17:11 +0000 Subject: [PATCH 13/22] Bump recyclerview from 1.1.0-beta05 to 1.1.0-rc01 (#566) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index ed6aa554..9f744a5e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -135,7 +135,7 @@ dependencies { implementation "androidx.multidex:multidex:2.0.1" implementation "androidx.preference:preference-ktx:1.1.0" - implementation "androidx.recyclerview:recyclerview:1.1.0-beta05" + implementation "androidx.recyclerview:recyclerview:1.1.0-rc01" implementation "androidx.viewpager:viewpager:1.0.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03" implementation "androidx.constraintlayout:constraintlayout:1.1.3" From a72c743c6fc6638fbe85d95199859a72e99503d9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2019 06:37:24 +0000 Subject: [PATCH 14/22] Bump work_manager from 2.3.0-alpha02 to 2.3.0-alpha03 (#563) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 9f744a5e..f1151c5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -110,7 +110,7 @@ play { } ext { - work_manager = "2.3.0-alpha02" + work_manager = "2.3.0-alpha03" room = "2.2.1" dagger = "2.24" chucker = "2.0.4" From 497a3391d4b2b324c7349585f6f00605e860aed6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2019 06:58:42 +0000 Subject: [PATCH 15/22] Bump fragment-ktx from 1.2.0-beta02 to 1.2.0-rc01 (#568) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index f1151c5b..cbd8dca3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -130,7 +130,7 @@ dependencies { implementation "androidx.activity:activity-ktx:1.1.0-rc01" implementation "androidx.appcompat:appcompat:1.1.0" implementation "androidx.appcompat:appcompat-resources:1.1.0" - implementation "androidx.fragment:fragment-ktx:1.2.0-beta02" + implementation "androidx.fragment:fragment-ktx:1.2.0-rc01" implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.multidex:multidex:2.0.1" From f234b719322b8224a25ddbe44b820eb3e9da3f77 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2019 18:24:22 +0200 Subject: [PATCH 16/22] Bump dagger from 2.24 to 2.25.2 (#564) --- app/build.gradle | 2 +- .../java/io/github/wulkanowy/services/ServicesModule.kt | 6 ++---- .../io/github/wulkanowy/ui/modules/grade/GradeModule.kt | 5 ++--- .../io/github/wulkanowy/ui/modules/login/LoginModule.kt | 5 ++--- .../java/io/github/wulkanowy/ui/modules/main/MainModule.kt | 7 ++----- .../github/wulkanowy/ui/modules/message/MessageModule.kt | 5 ++--- .../modules/schoolandteachers/SchoolAndTeachersModule.kt | 5 ++--- 7 files changed, 13 insertions(+), 22 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index cbd8dca3..8f3ae958 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -112,7 +112,7 @@ play { ext { work_manager = "2.3.0-alpha03" room = "2.2.1" - dagger = "2.24" + dagger = "2.25.2" chucker = "2.0.4" mockk = "1.9.2" } diff --git a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt b/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt index 7d1b223e..78bdbd8c 100644 --- a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt +++ b/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt @@ -29,17 +29,15 @@ import javax.inject.Singleton @Suppress("unused") @AssistedModule -@Module(includes = [AssistedInject_ServicesModule::class]) +@Module(includes = [AssistedInject_ServicesModule::class, ServicesModule.Static::class]) abstract class ServicesModule { @Module - companion object { + object Static { - @JvmStatic @Provides fun provideWorkManager(context: Context) = WorkManager.getInstance(context) - @JvmStatic @Singleton @Provides fun provideNotificationManager(context: Context) = NotificationManagerCompat.from(context) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeModule.kt index 52cf087b..6e6ca2d6 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeModule.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeModule.kt @@ -11,13 +11,12 @@ import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment @Suppress("unused") -@Module +@Module(includes = [GradeModule.Static::class]) abstract class GradeModule { @Module - companion object { + object Static { - @JvmStatic @PerFragment @Provides fun provideGradeAdapter(fragment: GradeFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginModule.kt index a0b98be7..8bcf042b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginModule.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginModule.kt @@ -11,13 +11,12 @@ import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFrag import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment @Suppress("unused") -@Module +@Module(includes = [LoginModule.Static::class]) internal abstract class LoginModule { @Module - companion object { + object Static { - @JvmStatic @PerActivity @Provides fun provideLoginAdapter(activity: LoginActivity) = BaseFragmentPagerAdapter(activity.supportFragmentManager) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt index 095a320a..bbaea51c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt @@ -29,25 +29,22 @@ import io.github.wulkanowy.ui.modules.note.NoteFragment import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersModule import io.github.wulkanowy.ui.modules.settings.SettingsFragment -import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment @Suppress("unused") -@Module +@Module(includes = [MainModule.Static::class]) abstract class MainModule { @Module - companion object { + object Static { - @JvmStatic @Provides fun provideFragNavController(activity: MainActivity): FragNavController { return FragNavController(activity.supportFragmentManager, R.id.mainFragmentContainer) } //In activities must be injected as Lazy - @JvmStatic @Provides fun provideElevationOverlayProvider(activity: MainActivity) = ElevationOverlayProvider(activity) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageModule.kt index c772466f..b2521902 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageModule.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageModule.kt @@ -9,13 +9,12 @@ import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment @Suppress("unused") -@Module +@Module(includes = [MessageModule.Static::class]) abstract class MessageModule { @Module - companion object { + object Static { - @JvmStatic @PerFragment @Provides fun provideMessageAdapter(fragment: MessageFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt index 1c083f8a..62803a28 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt @@ -10,13 +10,12 @@ import io.github.wulkanowy.ui.modules.schoolandteachers.school.SchoolFragment import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment @Suppress("unused") -@Module +@Module(includes = [SchoolAndTeachersModule.Static::class]) abstract class SchoolAndTeachersModule { @Module - companion object { + object Static { - @JvmStatic @PerFragment @Provides fun provideSchoolAndTeachersAdapter(fragment: SchoolAndTeachersFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager) From 5c5993cc2a01eda076183c54ee20c8b8f712d9f2 Mon Sep 17 00:00:00 2001 From: doteq Date: Thu, 24 Oct 2019 18:45:05 +0200 Subject: [PATCH 17/22] Change FAB to extended FAB in messages (#536) --- app/src/main/res/layout/fragment_message.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/fragment_message.xml b/app/src/main/res/layout/fragment_message.xml index 7a2cfcf4..d396276f 100644 --- a/app/src/main/res/layout/fragment_message.xml +++ b/app/src/main/res/layout/fragment_message.xml @@ -27,7 +27,7 @@ android:layout_marginTop="48dp" android:visibility="invisible" /> - + android:text="@string/send_message_title" + app:icon="@drawable/ic_menu_message_write" /> Date: Thu, 24 Oct 2019 22:56:49 +0200 Subject: [PATCH 18/22] Fix restoring state in exposed dropdown menu (#569) --- .../modules/login/form/LoginFormFragment.kt | 9 ++----- .../modules/login/form/LoginSymbolAdapter.kt | 16 ++++++++++++ .../message/preview/MessagePreviewFragment.kt | 2 +- .../main/res/layout/fragment_login_form.xml | 26 ++++++++++--------- 4 files changed, 33 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginSymbolAdapter.kt diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt index 8ea4222c..6dd1a586 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt @@ -9,7 +9,6 @@ import android.view.View.VISIBLE import android.view.ViewGroup import android.view.inputmethod.EditorInfo.IME_ACTION_DONE import android.view.inputmethod.EditorInfo.IME_NULL -import android.widget.ArrayAdapter import androidx.core.widget.doOnTextChanged import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Student @@ -17,11 +16,11 @@ import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.hideSoftInput +import io.github.wulkanowy.utils.openEmail import io.github.wulkanowy.utils.openInternetBrowser import io.github.wulkanowy.utils.showSoftInput import kotlinx.android.synthetic.main.fragment_login_form.* import javax.inject.Inject -import io.github.wulkanowy.utils.openEmail class LoginFormFragment : BaseFragment(), LoginFormView { @@ -71,12 +70,8 @@ class LoginFormFragment : BaseFragment(), LoginFormView { } with(loginFormHost) { - //Bug with filter in ExposedDropdownMenu on restoring state - isSaveEnabled = false - setText(hostKeys.getOrElse(0) { "" }) - setAdapter(ArrayAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys)) - keyListener = null + setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys)) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginSymbolAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginSymbolAdapter.kt new file mode 100644 index 00000000..87fa038e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginSymbolAdapter.kt @@ -0,0 +1,16 @@ +package io.github.wulkanowy.ui.modules.login.form + +import android.content.Context +import android.widget.ArrayAdapter +import android.widget.Filter + +class LoginSymbolAdapter(context: Context, resource: Int, objects: Array) : + ArrayAdapter(context, resource, objects) { + + override fun getFilter() = object : Filter() { + + override fun performFiltering(constraint: CharSequence?) = null + + override fun publishResults(constraint: CharSequence?, results: FilterResults?) {} + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt index 93ef502f..4f881e8f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt @@ -143,7 +143,7 @@ class MessagePreviewFragment : BaseFragment(), MessagePreviewView, MainView.Titl } override fun notifyParentMessageDeleted(message: Message) { - fragmentManager?.fragments?.forEach { if (it is MessageFragment) it.onDeleteMessage(message) } + parentFragmentManager.fragments.forEach { if (it is MessageFragment) it.onDeleteMessage(message) } } override fun onSaveInstanceState(outState: Bundle) { diff --git a/app/src/main/res/layout/fragment_login_form.xml b/app/src/main/res/layout/fragment_login_form.xml index 545b7726..29943515 100644 --- a/app/src/main/res/layout/fragment_login_form.xml +++ b/app/src/main/res/layout/fragment_login_form.xml @@ -30,10 +30,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" + android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - android:visibility="gone" tools:visibility="visible"> + android:layout_marginRight="16dp" + android:orientation="horizontal"> + @@ -95,9 +96,9 @@ android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginLeft="32dp" + android:layout_marginTop="48dp" android:layout_marginEnd="32dp" android:layout_marginRight="32dp" - android:layout_marginTop="48dp" android:gravity="center_horizontal" android:text="@string/login_header_default" android:textSize="16sp" @@ -191,7 +192,8 @@ android:id="@+id/loginFormHost" android:layout_width="match_parent" android:layout_height="wrap_content" - tools:ignore="LabelFor" /> + android:editable="false" + tools:ignore="Deprecated,LabelFor" /> Date: Sun, 27 Oct 2019 00:36:39 +0200 Subject: [PATCH 19/22] Add school quick actions (#570) --- .../school/SchoolFragment.kt | 15 +++ .../school/SchoolPresenter.kt | 14 +++ .../schoolandteachers/school/SchoolView.kt | 4 + .../wulkanowy/utils/ContextExtension.kt | 15 ++- .../res/drawable/ic_school_directions.xml | 9 ++ app/src/main/res/drawable/ic_school_phone.xml | 9 ++ app/src/main/res/layout/fragment_school.xml | 116 ++++++++++++------ app/src/main/res/values-pl/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 9 files changed, 147 insertions(+), 39 deletions(-) create mode 100644 app/src/main/res/drawable/ic_school_directions.xml create mode 100644 app/src/main/res/drawable/ic_school_phone.xml diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt index 6c17f5ed..92f74ca8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt @@ -10,6 +10,8 @@ import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment +import io.github.wulkanowy.utils.dialPhone +import io.github.wulkanowy.utils.openMapLocation import kotlinx.android.synthetic.main.fragment_school.* import javax.inject.Inject @@ -35,12 +37,17 @@ class SchoolFragment : BaseFragment(), SchoolView, MainView.TitledView, SchoolAn override fun initView() { schoolSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } + + schoolAddressButton.setOnClickListener { presenter.onAddressSelected() } + schoolTelephoneButton.setOnClickListener { presenter.onTelephoneSelected() } } override fun updateData(data: School) { schoolName.text = data.name schoolAddress.text = data.address.ifBlank { "-" } + schoolAddressButton.visibility = if (data.address.isNotBlank()) View.VISIBLE else View.GONE schoolTelephone.text = data.contact.ifBlank { "-" } + schoolTelephoneButton.visibility = if (data.contact.isNotBlank()) View.VISIBLE else View.GONE schoolHeadmaster.text = data.headmaster schoolPedagogue.text = data.pedagogue } @@ -77,4 +84,12 @@ class SchoolFragment : BaseFragment(), SchoolView, MainView.TitledView, SchoolAn presenter.onDetachView() super.onDestroyView() } + + override fun openMapsLocation(location: String) { + context?.openMapLocation(location) + } + + override fun dialPhone(phone: String) { + context?.dialPhone(phone) + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt index f996b165..2b0a37b1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt @@ -19,6 +19,10 @@ class SchoolPresenter @Inject constructor( private val analytics: FirebaseAnalyticsHelper ) : BasePresenter(errorHandler, studentRepository, schedulers) { + private var address: String? = null + + private var contact: String? = null + override fun onAttachView(view: SchoolView) { super.onAttachView(view) view.initView() @@ -34,6 +38,14 @@ class SchoolPresenter @Inject constructor( loadData(forceRefresh) } + fun onAddressSelected() { + address?.let{ view?.openMapsLocation(it) } + } + + fun onTelephoneSelected() { + contact?.let { view?.dialPhone(it) } + } + private fun loadData(forceRefresh: Boolean = false) { Timber.i("Loading school info started") disposable.add(studentRepository.getCurrentStudent() @@ -51,6 +63,8 @@ class SchoolPresenter @Inject constructor( }.subscribe({ Timber.i("Loading teachers result: Success") view?.run { + address = it.address.ifBlank { null } + contact = it.contact.ifBlank { null } updateData(it) showContent(true) showEmpty(false) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt index 5702278c..39e7b805 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt @@ -19,4 +19,8 @@ interface SchoolView : BaseView, SchoolAndTeachersChildView { fun showContent(show: Boolean) fun hideRefresh() + + fun openMapsLocation(location: String) + + fun dialPhone(phone: String) } diff --git a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt index 84200b3a..5110b067 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt @@ -9,7 +9,6 @@ import androidx.annotation.ColorInt import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.core.content.ContextCompat -import io.github.wulkanowy.R @ColorInt fun Context.getThemeAttrColor(@AttrRes colorAttr: Int): Int { @@ -41,4 +40,18 @@ fun Context.openEmail(chooserTitle: String, email: String, subject: String?, bod startActivity(Intent.createChooser(emailIntent, chooserTitle)) } +fun Context.openMapLocation(location: String) { + val intentUri = Uri.parse("geo:0,0?q=${Uri.encode(location)}") + val intent = Intent(Intent.ACTION_VIEW, intentUri) + if (intent.resolveActivity(packageManager) != null) { + startActivity(intent) + } +} + +fun Context.dialPhone(phone: String) { + val intentUri = Uri.parse("tel:$phone") + val intent = Intent(Intent.ACTION_DIAL, intentUri) + startActivity(intent) +} + fun Context.dpToPx(dp: Float) = dp * resources.displayMetrics.densityDpi / DENSITY_DEFAULT diff --git a/app/src/main/res/drawable/ic_school_directions.xml b/app/src/main/res/drawable/ic_school_directions.xml new file mode 100644 index 00000000..c48db1da --- /dev/null +++ b/app/src/main/res/drawable/ic_school_directions.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_school_phone.xml b/app/src/main/res/drawable/ic_school_phone.xml new file mode 100644 index 00000000..7e3d7991 --- /dev/null +++ b/app/src/main/res/drawable/ic_school_phone.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_school.xml b/app/src/main/res/layout/fragment_school.xml index 8f52d46b..2570251b 100644 --- a/app/src/main/res/layout/fragment_school.xml +++ b/app/src/main/res/layout/fragment_school.xml @@ -60,55 +60,95 @@ - - + + android:layout_weight="1" + android:orientation="vertical" + android:paddingStart="12dp" + android:paddingLeft="12dp" + android:paddingTop="7dp" + android:paddingEnd="12dp" + android:paddingRight="12dp" + android:paddingBottom="7dp"> - + + + + + + app:srcCompat="@drawable/ic_school_directions" + android:contentDescription="@string/school_address_button" + android:background="?attr/selectableItemBackgroundBorderless" + android:tint="?colorPrimary" + android:padding="4dp" + android:layout_marginTop="8dp" + android:layout_marginRight="8dp" + android:layout_marginLeft="8dp" + android:layout_gravity="center_vertical" /> - - + + android:layout_weight="1" + android:orientation="vertical" + android:paddingStart="12dp" + android:paddingLeft="12dp" + android:paddingTop="7dp" + android:paddingEnd="12dp" + android:paddingRight="12dp" + android:paddingBottom="7dp"> - + + + + + + app:srcCompat="@drawable/ic_school_phone" + android:contentDescription="@string/school_telephone_button" + android:background="?attr/selectableItemBackgroundBorderless" + android:tint="?colorPrimary" + android:padding="4dp" + android:layout_marginTop="8dp" + android:layout_marginRight="8dp" + android:layout_marginLeft="8dp" + android:layout_gravity="center_vertical" /> Telefon Imię i nazwisko dyrektora Imię i nazwisko pedagoga + Pokaż na mpaie + Zadzwoń diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eeee5838..4660f9fe 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -218,6 +218,8 @@ Telephone Name of headmaster Name of pedagogue + Show on map + Call From 747696e386ec908fa519b95d8d3bd57c216f8f9d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2019 14:58:10 +0000 Subject: [PATCH 20/22] Bump firebase-core from 17.2.0 to 17.2.1 (#572) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 8f3ae958..ccadcf12 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -176,7 +176,7 @@ dependencies { implementation "com.squareup.okhttp3:logging-interceptor:3.12.6" implementation "com.mikepenz:aboutlibraries:7.0.4" - playImplementation "com.google.firebase:firebase-core:17.2.0" + playImplementation "com.google.firebase:firebase-core:17.2.1" playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1" releaseImplementation "fr.o80.chucker:library-no-op:$chucker" From a7c472989c6c8c6ebaf467788ca4a9fa10f2aa4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Mon, 28 Oct 2019 21:10:58 +0100 Subject: [PATCH 21/22] Add support for edu.lublin.eu (#571) --- app/build.gradle | 2 +- .../wulkanowy/ui/modules/login/form/LoginFormFragment.kt | 4 ++-- app/src/main/res/layout/fragment_attendance_summary.xml | 2 +- .../main/res/values/{api_endpoints.xml => api_hosts.xml} | 6 ++++-- 4 files changed, 8 insertions(+), 6 deletions(-) rename app/src/main/res/values/{api_endpoints.xml => api_hosts.xml} (79%) diff --git a/app/build.gradle b/app/build.gradle index ccadcf12..a02006c8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -123,7 +123,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:api:0.11.0" + implementation "io.github.wulkanowy:api:6873c00" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "androidx.core:core-ktx:1.2.0-beta01" diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt index 6dd1a586..1288e299 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt @@ -54,8 +54,8 @@ class LoginFormFragment : BaseFragment(), LoginFormView { } override fun initView() { - hostKeys = resources.getStringArray(R.array.endpoints_keys) - hostValues = resources.getStringArray(R.array.endpoints_values) + hostKeys = resources.getStringArray(R.array.hosts_keys) + hostValues = resources.getStringArray(R.array.hosts_values) loginFormName.doOnTextChanged { _, _, _, _ -> presenter.onNameTextChanged() } loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() } diff --git a/app/src/main/res/layout/fragment_attendance_summary.xml b/app/src/main/res/layout/fragment_attendance_summary.xml index 31be9900..35bc0960 100644 --- a/app/src/main/res/layout/fragment_attendance_summary.xml +++ b/app/src/main/res/layout/fragment_attendance_summary.xml @@ -26,7 +26,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="middle" - android:entries="@array/endpoints_keys" + android:entries="@array/hosts_keys" android:paddingStart="10dp" android:paddingLeft="10dp" android:paddingTop="10dp" diff --git a/app/src/main/res/values/api_endpoints.xml b/app/src/main/res/values/api_hosts.xml similarity index 79% rename from app/src/main/res/values/api_endpoints.xml rename to app/src/main/res/values/api_hosts.xml index e07f2b4b..df42f592 100644 --- a/app/src/main/res/values/api_endpoints.xml +++ b/app/src/main/res/values/api_hosts.xml @@ -1,17 +1,19 @@ - + Vulcan Opolska eSzkoła Gdańska Platforma Edukacyjna + Lubelski Portal Oświatowy EduNet Miasta Tarnowa ResMan Rzeszów Fakelog - + https://vulcan.net.pl https://eszkola.opolskie.pl https://edu.gdansk.pl + https://edu.lublin.eu https://umt.tarnow.pl https://resman.pl http://fakelog.cf From 1f4a2088570a4f5be5a51cae6bf5ac51766ebdd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 29 Oct 2019 00:25:03 +0100 Subject: [PATCH 22/22] Version 0.12.0 --- .travis.yml | 2 +- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 13 ++++++------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2d65d7bc..8bda02d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.11.0 + - 0.12.0 android: licenses: diff --git a/app/build.gradle b/app/build.gradle index a02006c8..090a643d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 16 targetSdkVersion 29 - versionCode 46 - versionName "0.11.0" + versionCode 47 + versionName "0.12.0" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -123,7 +123,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:api:6873c00" + implementation "io.github.wulkanowy:api:0.12.0" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "androidx.core:core-ktx:1.2.0-beta01" diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt index c656698c..68608c38 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,10 +1,9 @@ -Wersja 0.11.0 +Wersja 0.12.0 -- ciemny motyw dla widżetów -- lista nauczycieli -- statystyka ocen punktowych ucznia na tle klasy i lepsze wyświetlanie punktów na liście ocen -- ładniejsza nawigacja między datami w planie lekcji i nie tylko -- naprawiony szczęśliwy numerek -- naprawione logowanie do dziennika Resman +- wsparcie dla dziennika Lubelskiego Portalu Oświatowego +- naprawa problemów z wyświetlaniem ocen punktowych +- automatyczne przełączanie motywu na androidzie 10 +- wyświetlanie pomocy przy problemach z logowaniem +- wyświetlanie informacji o szkole Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases