From 429fdfa4a0380bb520e116e0112c01c524f5de1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Thu, 1 Dec 2022 19:02:25 +0100 Subject: [PATCH] Update project to Android SDK 33 (#2011) --- app/build.gradle | 14 ++-- .../res/mipmap-anydpi-v26/ic_launcher.xml | 3 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 -- .../res/mipmap-hdpi/ic_launcher_round.png | Bin 4369 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2798 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 6193 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 9606 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 13447 -> 0 bytes app/src/main/AndroidManifest.xml | 8 +- .../github/wulkanowy/ui/base/ErrorDialog.kt | 2 +- .../github/wulkanowy/ui/base/ThemeManager.kt | 18 ++++- .../accountdetails/AccountDetailsFragment.kt | 11 +-- .../account/accountedit/AccountEditDialog.kt | 13 ++-- .../accountquick/AccountQuickDialog.kt | 10 +-- .../ui/modules/attendance/AttendanceDialog.kt | 8 +- .../ui/modules/conference/ConferenceDialog.kt | 10 +-- .../wulkanowy/ui/modules/exam/ExamDialog.kt | 8 +- .../grade/details/GradeDetailsDialog.kt | 20 +++-- .../statistics/GradeStatisticsFragment.kt | 5 +- .../homework/details/HomeworkDetailsDialog.kt | 8 +- .../ui/modules/login/LoginActivity.kt | 27 ++++++- .../login/recover/LoginRecoverFragment.kt | 2 +- .../LoginStudentSelectFragment.kt | 9 +-- .../LoginStudentSelectPresenter.kt | 2 +- .../studentselect/LoginStudentSelectView.kt | 2 +- .../login/symbol/LoginSymbolFragment.kt | 8 +- .../wulkanowy/ui/modules/main/MainActivity.kt | 13 +++- .../ui/modules/main/MainPresenter.kt | 7 +- .../mailboxchooser/MailboxChooserDialog.kt | 4 +- .../message/preview/MessagePreviewFragment.kt | 12 +-- .../message/send/SendMessageActivity.kt | 9 ++- .../modules/message/tab/MessageTabFragment.kt | 12 ++- .../wulkanowy/ui/modules/note/NoteDialog.kt | 10 +-- .../notifications/NotificationsFragment.kt | 64 ++++++++++++++++ .../SchoolAnnouncementDialog.kt | 10 +-- .../notifications/NotificationsFragment.kt | 63 ++++++++++------ .../notifications/NotificationsPresenter.kt | 32 ++++++-- .../notifications/NotificationsView.kt | 10 ++- .../studentinfo/StudentInfoFragment.kt | 22 +++--- .../ui/modules/timetable/TimetableDialog.kt | 14 ++-- .../ui/modules/timetable/TimetableFragment.kt | 5 +- .../completed/CompletedLessonDialog.kt | 10 +-- .../github/wulkanowy/utils/BundleExtension.kt | 32 ++++++++ .../io/github/wulkanowy/utils/IntentUtils.kt | 21 ++++++ .../ic_launcher_foreground_dev_mono.xml | 20 +++++ .../drawable/ic_launcher_foreground_mono.xml | 12 +++ .../res/layout/fragment_notifications.xml | 69 ++++++++++++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 3 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 -- .../res/mipmap-hdpi/ic_launcher_round.png | Bin 4025 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2569 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 5740 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 8796 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 12531 -> 0 bytes app/src/main/res/values/strings.xml | 5 ++ .../main/res/xml/data_extraction_rules.xml | 17 +++++ .../LoginStudentSelectPresenterTest.kt | 4 +- 57 files changed, 496 insertions(+), 182 deletions(-) delete mode 100644 app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 app/src/debug/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 app/src/debug/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt create mode 100644 app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt create mode 100644 app/src/main/res/drawable/ic_launcher_foreground_dev_mono.xml create mode 100644 app/src/main/res/drawable/ic_launcher_foreground_mono.xml create mode 100644 app/src/main/res/layout/fragment_notifications.xml delete mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/xml/data_extraction_rules.xml diff --git a/app/build.gradle b/app/build.gradle index de3b4913..cf7223ba 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,13 +16,13 @@ apply from: 'hooks.gradle' android { namespace 'io.github.wulkanowy' - compileSdkVersion 32 + compileSdkVersion 33 defaultConfig { applicationId "io.github.wulkanowy" testApplicationId "io.github.tests.wulkanowy" minSdkVersion 21 - targetSdkVersion 32 + targetSdkVersion 33 versionCode 116 versionName "1.8.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -193,9 +193,9 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines" - implementation "androidx.core:core-ktx:1.8.0" + implementation "androidx.core:core-ktx:1.9.0" implementation 'androidx.core:core-splashscreen:1.0.0' - implementation "androidx.activity:activity-ktx:1.5.1" + implementation "androidx.activity:activity-ktx:1.6.1" implementation "androidx.appcompat:appcompat:1.5.1" implementation "androidx.fragment:fragment-ktx:1.5.4" implementation "androidx.annotation:annotation:1.5.0" @@ -271,9 +271,9 @@ dependencies { testImplementation "com.google.dagger:hilt-android-testing:$hilt_version" kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version" - androidTestImplementation "androidx.test:core:1.4.0" - androidTestImplementation "androidx.test:runner:1.4.0" - androidTestImplementation "androidx.test.ext:junit:1.1.3" + androidTestImplementation "androidx.test:core:1.5.0" + androidTestImplementation "androidx.test:runner:1.5.1" + androidTestImplementation "androidx.test.ext:junit:1.1.4" androidTestImplementation "io.mockk:mockk-android:$mockk" androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" } diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml index 7dbec2cb..b7b756b9 100644 --- a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml @@ -2,4 +2,5 @@ - \ No newline at end of file + + diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 7dbec2cb..00000000 --- a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 81e723eccf63eb93c41506650615abaf157a8f93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4369 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 A&j0`b diff --git a/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 365b4d663a8eae4600393c92446ebcbb629b0d1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6193 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 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7835db90..3773093b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,7 +8,8 @@ - + + @@ -36,13 +37,14 @@ + tools:ignore="DataExtractionRules,UnusedAttribute"> (ARGUMENT_KEY) val binding = DialogErrorBinding.inflate(layoutInflater) binding.bindErrorDetails(error) 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 2d83bbbf..e1c23457 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 @@ -1,6 +1,9 @@ package io.github.wulkanowy.ui.base +import android.content.pm.PackageInfo +import android.content.pm.PackageManager import android.content.pm.PackageManager.GET_ACTIVITIES +import android.os.Build import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM @@ -41,9 +44,8 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer ) } - private fun isThemeApplicable(activity: AppCompatActivity) = - activity.packageManager - .getPackageInfo(activity.packageName, GET_ACTIVITIES) + private fun isThemeApplicable(activity: AppCompatActivity): Boolean = + getPackageInfo(activity) .activities .singleOrNull { it.name == activity::class.java.canonicalName } ?.theme @@ -52,4 +54,14 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer || it == R.style.WulkanowyTheme_Login || it == R.style.WulkanowyTheme_Login_Black || it == R.style.WulkanowyTheme_MessageSend || it == R.style.WulkanowyTheme_MessageSend_Black } + + @Suppress("DEPRECATION") + private fun getPackageInfo(activity: AppCompatActivity): PackageInfo { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + activity.packageManager.getPackageInfo( + activity.packageName, + PackageManager.PackageInfoFlags.of(GET_ACTIVITIES.toLong()) + ) + } else activity.packageManager.getPackageInfo(activity.packageName, GET_ACTIVITIES) + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt index c6fe8a69..41b97b07 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt @@ -6,6 +6,7 @@ import android.view.MenuInflater import android.view.MenuItem import android.view.View import androidx.appcompat.app.AlertDialog +import androidx.core.os.bundleOf import androidx.core.view.get import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint @@ -21,6 +22,7 @@ import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoFragment import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoView import io.github.wulkanowy.utils.createNameInitialsDrawable import io.github.wulkanowy.utils.nickOrName +import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -37,10 +39,9 @@ class AccountDetailsFragment : private const val ARGUMENT_KEY = "Data" - fun newInstance(student: Student) = - AccountDetailsFragment().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, student) } - } + fun newInstance(student: Student) = AccountDetailsFragment().apply { + arguments = bundleOf(ARGUMENT_KEY to student) + } } @Suppress("DEPRECATION") @@ -52,7 +53,7 @@ class AccountDetailsFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentAccountDetailsBinding.bind(view) - presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student) + presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY)) } override fun initView() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt index 21a7a492..6e2bc8c4 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt @@ -4,11 +4,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.recyclerview.widget.GridLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.databinding.DialogAccountEditBinding import io.github.wulkanowy.ui.base.BaseDialogFragment +import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -24,12 +26,9 @@ class AccountEditDialog : BaseDialogFragment(), Accoun private const val ARGUMENT_KEY = "student_with_semesters" - fun newInstance(student: Student) = - AccountEditDialog().apply { - arguments = Bundle().apply { - putSerializable(ARGUMENT_KEY, student) - } - } + fun newInstance(student: Student) = AccountEditDialog().apply { + arguments = bundleOf(ARGUMENT_KEY to student) + } } override fun onCreate(savedInstanceState: Bundle?) { @@ -45,7 +44,7 @@ class AccountEditDialog : BaseDialogFragment(), Accoun override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student) + presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY)) } override fun initView() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt index 4279102e..d23978f5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.data.db.entities.StudentWithSemesters @@ -13,6 +14,7 @@ import io.github.wulkanowy.ui.modules.account.AccountAdapter import io.github.wulkanowy.ui.modules.account.AccountFragment import io.github.wulkanowy.ui.modules.account.AccountItem import io.github.wulkanowy.ui.modules.main.MainActivity +import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -30,9 +32,7 @@ class AccountQuickDialog : BaseDialogFragment(), Acco fun newInstance(studentsWithSemesters: List) = AccountQuickDialog().apply { - arguments = Bundle().apply { - putSerializable(STUDENTS_ARGUMENT_KEY, studentsWithSemesters.toTypedArray()) - } + arguments = bundleOf(STUDENTS_ARGUMENT_KEY to studentsWithSemesters.toTypedArray()) } } @@ -49,8 +49,8 @@ class AccountQuickDialog : BaseDialogFragment(), Acco @Suppress("UNCHECKED_CAST") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - val studentsWithSemesters = - (requireArguments()[STUDENTS_ARGUMENT_KEY] as Array).toList() + val studentsWithSemesters = requireArguments() + .serializable>(STUDENTS_ARGUMENT_KEY).toList() presenter.onAttachView(this, studentsWithSemesters) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt index 9b5c63e4..eab24f91 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt @@ -4,11 +4,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.databinding.DialogAttendanceBinding import io.github.wulkanowy.utils.descriptionRes import io.github.wulkanowy.utils.lifecycleAwareVariable +import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.toFormattedString class AttendanceDialog : DialogFragment() { @@ -22,16 +24,14 @@ class AttendanceDialog : DialogFragment() { private const val ARGUMENT_KEY = "Item" fun newInstance(exam: Attendance) = AttendanceDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + arguments = bundleOf(ARGUMENT_KEY to exam) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - attendance = getSerializable(ARGUMENT_KEY) as Attendance - } + attendance = requireArguments().serializable(ARGUMENT_KEY) } override fun onCreateView( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt index 477b762b..7834b6e8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt @@ -4,11 +4,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.core.view.isVisible import androidx.fragment.app.DialogFragment import io.github.wulkanowy.data.db.entities.Conference import io.github.wulkanowy.databinding.DialogConferenceBinding import io.github.wulkanowy.utils.lifecycleAwareVariable +import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.toFormattedString class ConferenceDialog : DialogFragment() { @@ -22,16 +24,14 @@ class ConferenceDialog : DialogFragment() { private const val ARGUMENT_KEY = "item" fun newInstance(conference: Conference) = ConferenceDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, conference) } + arguments = bundleOf(ARGUMENT_KEY to conference) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) - arguments?.let { - conference = it.getSerializable(ARGUMENT_KEY) as Conference - } + conference = requireArguments().serializable(ARGUMENT_KEY) } override fun onCreateView( @@ -57,4 +57,4 @@ class ConferenceDialog : DialogFragment() { conferenceDialogAgendaTitle.isVisible = conference.agenda.isNotBlank() } } -} \ No newline at end of file +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt index 41adc008..876b563f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt @@ -4,12 +4,14 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.databinding.DialogExamBinding import io.github.wulkanowy.utils.lifecycleAwareVariable import io.github.wulkanowy.utils.openCalendarEventAdd +import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.toFormattedString import java.time.LocalTime @@ -24,16 +26,14 @@ class ExamDialog : DialogFragment() { private const val ARGUMENT_KEY = "Item" fun newInstance(exam: Exam) = ExamDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + arguments = bundleOf(ARGUMENT_KEY to exam) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - exam = getSerializable(ARGUMENT_KEY) as Exam - } + exam = requireArguments().serializable(ARGUMENT_KEY) } override fun onCreateView( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt index 34594111..a1ef2ec5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt @@ -5,6 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.View.GONE import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Grade @@ -27,22 +28,19 @@ class GradeDetailsDialog : DialogFragment() { private const val COLOR_THEME_KEY = "Theme" - fun newInstance(grade: Grade, colorTheme: GradeColorTheme) = - GradeDetailsDialog().apply { - arguments = Bundle().apply { - putSerializable(ARGUMENT_KEY, grade) - putSerializable(COLOR_THEME_KEY, colorTheme) - } - } + fun newInstance(grade: Grade, colorTheme: GradeColorTheme) = GradeDetailsDialog().apply { + arguments = bundleOf( + ARGUMENT_KEY to grade, + COLOR_THEME_KEY to colorTheme + ) + } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - grade = getSerializable(ARGUMENT_KEY) as Grade - gradeColorTheme = getSerializable(COLOR_THEME_KEY) as GradeColorTheme - } + grade = requireArguments().serializable(ARGUMENT_KEY) + gradeColorTheme = requireArguments().serializable(COLOR_THEME_KEY) } override fun onCreateView( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt index 2af59c01..edc384c5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt @@ -15,6 +15,7 @@ import io.github.wulkanowy.ui.modules.grade.GradeFragment import io.github.wulkanowy.ui.modules.grade.GradeView import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.getThemeAttrColor +import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.setOnItemSelectedListener import javax.inject.Inject @@ -48,8 +49,8 @@ class GradeStatisticsFragment : messageContainer = binding.gradeStatisticsRecycler presenter.onAttachView( view = this, - type = savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? GradeStatisticsItem.DataType, - subjectName = savedInstanceState?.getSerializable(SAVED_SUBJECT_NAME) as? String, + type = savedInstanceState?.serializable(SAVED_CHART_TYPE), + subjectName = savedInstanceState?.serializable(SAVED_SUBJECT_NAME), ) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt index f9d46351..5e2cc65d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt @@ -7,6 +7,7 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import androidx.core.os.bundleOf import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -14,6 +15,7 @@ import io.github.wulkanowy.data.db.entities.Homework import io.github.wulkanowy.databinding.DialogHomeworkBinding import io.github.wulkanowy.ui.base.BaseDialogFragment import io.github.wulkanowy.utils.openInternetBrowser +import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -35,16 +37,14 @@ class HomeworkDetailsDialog : BaseDialogFragment(), Homew private const val ARGUMENT_KEY = "Item" fun newInstance(homework: Homework) = HomeworkDetailsDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, homework) } + arguments = bundleOf(ARGUMENT_KEY to homework) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - homework = getSerializable(ARGUMENT_KEY) as Homework - } + homework = requireArguments().serializable(ARGUMENT_KEY) } override fun onCreateView( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt index aac60b56..8f237e53 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt @@ -2,8 +2,11 @@ package io.github.wulkanowy.ui.modules.login import android.content.Context import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build.VERSION_CODES.TIRAMISU import android.os.Bundle import android.view.MenuItem +import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.commit import dagger.hilt.android.AndroidEntryPoint @@ -16,6 +19,9 @@ import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment +import io.github.wulkanowy.ui.modules.main.MainActivity +import io.github.wulkanowy.ui.modules.notifications.NotificationsFragment +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.UpdateHelper import javax.inject.Inject @@ -28,6 +34,9 @@ class LoginActivity : BaseActivity(), Logi @Inject lateinit var updateHelper: UpdateHelper + @Inject + lateinit var appInfo: AppInfo + companion object { fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java) } @@ -55,7 +64,7 @@ class LoginActivity : BaseActivity(), Logi } override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == android.R.id.home) onBackPressed() + if (item.itemId == android.R.id.home) onBackPressedDispatcher.onBackPressed() return true } @@ -71,6 +80,22 @@ class LoginActivity : BaseActivity(), Logi openFragment(LoginStudentSelectFragment.newInstance(studentsWithSemesters)) } + fun navigateToNotifications() { + val isNotificationsPermissionRequired = appInfo.systemVersion >= TIRAMISU + val isPermissionGranted = ContextCompat.checkSelfPermission( + this, "android.permission.POST_NOTIFICATIONS" + ) == PackageManager.PERMISSION_GRANTED + + if (isNotificationsPermissionRequired && !isPermissionGranted) { + openFragment(NotificationsFragment.newInstance(), clearBackStack = true) + } else navigateToFinish() + } + + fun navigateToFinish() { + startActivity(MainActivity.getStartIntent(this)) + finish() + } + fun onAdvancedLoginClick() { openFragment(LoginAdvancedFragment.newInstance()) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt index 786bbfce..b9afba98 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt @@ -98,7 +98,7 @@ class LoginRecoverFragment : loginRecoverButton.setOnClickListener { presenter.onRecoverClick() } loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() } loginRecoverErrorDetails.setOnClickListener { presenter.onDetailsClick() } - loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressed() } + loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressedDispatcher.onBackPressed() } } with(bindingLocal.loginRecoverHost) { 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 c42a4e9d..03aced14 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,10 +13,10 @@ import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.openEmailClient import io.github.wulkanowy.utils.openInternetBrowser +import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -51,7 +51,7 @@ class LoginStudentSelectFragment : binding = FragmentLoginStudentSelectBinding.bind(view) presenter.onAttachView( view = this, - students = requireArguments().getSerializable(ARG_STUDENTS) as List, + students = requireArguments().serializable(ARG_STUDENTS), ) } @@ -79,9 +79,8 @@ class LoginStudentSelectFragment : } } - override fun openMainView() { - startActivity(MainActivity.getStartIntent(requireContext())) - requireActivity().finish() + override fun navigateToNext() { + (requireActivity() as LoginActivity).navigateToNotifications() } override fun showProgress(show: Boolean) { 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 3455b3cf..5a40a6bc 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 @@ -100,7 +100,7 @@ class LoginStudentSelectPresenter @Inject constructor( } is Resource.Success -> { syncManager.startOneTimeSyncWorker(quiet = true) - view?.openMainView() + view?.navigateToNext() logRegisterEvent(studentsWithSemesters) } is Resource.Error -> { 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 f2acd76c..8d403271 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 @@ -9,7 +9,7 @@ interface LoginStudentSelectView : BaseView { fun updateData(data: List>) - fun openMainView() + fun navigateToNext() fun showProgress(show: Boolean) 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 36c40d15..ab27ecf3 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 @@ -18,11 +18,7 @@ import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.login.LoginData -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.hideSoftInput -import io.github.wulkanowy.utils.openEmailClient -import io.github.wulkanowy.utils.openInternetBrowser -import io.github.wulkanowy.utils.showSoftInput +import io.github.wulkanowy.utils.* import javax.inject.Inject @AndroidEntryPoint @@ -54,7 +50,7 @@ class LoginSymbolFragment : binding = FragmentLoginSymbolBinding.bind(view) presenter.onAttachView( view = this, - loginData = requireArguments().getSerializable(SAVED_LOGIN_DATA) as LoginData, + loginData = requireArguments().serializable(SAVED_LOGIN_DATA), ) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt index 5cd6fa10..d332ee35 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt @@ -6,6 +6,8 @@ import android.os.Build.VERSION_CODES.P import android.os.Bundle import android.view.Menu import android.view.MenuItem +import androidx.activity.OnBackPressedCallback +import androidx.activity.addCallback import androidx.core.view.ViewCompat import androidx.core.view.isVisible import androidx.fragment.app.DialogFragment @@ -50,6 +52,8 @@ class MainActivity : BaseActivity(), MainVie @Inject lateinit var appInfo: AppInfo + private var onBackCallback: OnBackPressedCallback? = null + private var accountMenu: MenuItem? = null private val overlayProvider by lazy { ElevationOverlayProvider(this) } @@ -88,6 +92,9 @@ class MainActivity : BaseActivity(), MainVie this.savedInstanceState = savedInstanceState messageContainer = binding.mainMessageContainer updateHelper.messageContainer = binding.mainFragmentContainer + onBackCallback = onBackPressedDispatcher.addCallback(this, enabled = false) { + presenter.onBackPressed() + } val destination = intent.getStringExtra(EXTRA_START_DESTINATION) ?.takeIf { savedInstanceState == null } @@ -266,6 +273,7 @@ class MainActivity : BaseActivity(), MainVie analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.pushFragment(fragment) + onBackCallback?.isEnabled = !isRootView } override fun popView(depth: Int) { @@ -273,10 +281,7 @@ class MainActivity : BaseActivity(), MainVie analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.safelyPopFragments(depth) - } - - override fun onBackPressed() { - presenter.onBackPressed { super.onBackPressed() } + onBackCallback?.isEnabled = !isRootView } override fun showStudentAvatar(student: Student) { 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 9c32d858..458e966d 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 @@ -139,12 +139,9 @@ class MainPresenter @Inject constructor( return true } - fun onBackPressed(default: () -> Unit) { + fun onBackPressed() { Timber.i("Back pressed in main view") - view?.run { - if (isRootView) default() - else popView() - } + view?.popView() } fun onTabSelected(index: Int, wasSelected: Boolean): Boolean { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt index 222412ef..37f9a19b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt @@ -10,6 +10,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.data.db.entities.Mailbox import io.github.wulkanowy.databinding.DialogMailboxChooserBinding import io.github.wulkanowy.ui.base.BaseDialogFragment +import io.github.wulkanowy.utils.parcelableArray import javax.inject.Inject @AndroidEntryPoint @@ -52,8 +53,7 @@ class MailboxChooserDialog : BaseDialogFragment(), presenter.onAttachView( view = this, requireMailbox = requireArguments().getBoolean(REQUIRED_KEY, false), - mailboxes = requireArguments().getParcelableArray(MAILBOX_KEY).orEmpty() - .toList() as List, + mailboxes = requireArguments().parcelableArray(MAILBOX_KEY).orEmpty().toList(), ) } 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 8c6b0402..6c54d9fc 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 @@ -13,6 +13,7 @@ import android.webkit.WebResourceRequest import android.webkit.WebView import android.webkit.WebViewClient import androidx.core.content.getSystemService +import androidx.core.os.bundleOf import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -23,6 +24,7 @@ import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity +import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.shareText import javax.inject.Inject @@ -66,10 +68,8 @@ class MessagePreviewFragment : companion object { const val MESSAGE_ID_KEY = "message_id" - fun newInstance(message: Message): MessagePreviewFragment { - return MessagePreviewFragment().apply { - arguments = Bundle().apply { putSerializable(MESSAGE_ID_KEY, message) } - } + fun newInstance(message: Message) = MessagePreviewFragment().apply { + arguments = bundleOf(MESSAGE_ID_KEY to message) } } @@ -84,8 +84,8 @@ class MessagePreviewFragment : binding = FragmentMessagePreviewBinding.bind(view) messageContainer = binding.messagePreviewContainer presenter.onAttachView( - this, - (savedInstanceState ?: arguments)?.getSerializable(MESSAGE_ID_KEY) as? Message + view = this, + message = (savedInstanceState ?: arguments)?.serializable(MESSAGE_ID_KEY), ) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt index b5f687bd..14f3d718 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt @@ -28,6 +28,7 @@ import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialo import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog.Companion.LISTENER_KEY import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.hideSoftInput +import io.github.wulkanowy.utils.nullableSerializable import io.github.wulkanowy.utils.showSoftInput import javax.inject.Inject @@ -108,12 +109,12 @@ class SendMessageActivity : BaseActivity - presenter.onMailboxSelected(bundle.getSerializable(MAILBOX_KEY) as? Mailbox) + presenter.onMailboxSelected(bundle.nullableSerializable(MAILBOX_KEY)) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt index eddb4324..c78ccc6e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt @@ -9,6 +9,7 @@ import android.view.View.* import android.widget.CompoundButton import androidx.appcompat.view.ActionMode import androidx.appcompat.widget.SearchView +import androidx.core.os.bundleOf import androidx.core.view.updatePadding import androidx.fragment.app.setFragmentResultListener import androidx.recyclerview.widget.LinearLayoutManager @@ -27,6 +28,7 @@ import io.github.wulkanowy.ui.widgets.DividerItemDecoration import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.hideSoftInput +import io.github.wulkanowy.utils.nullableSerializable import javax.inject.Inject @AndroidEntryPoint @@ -43,12 +45,8 @@ class MessageTabFragment : BaseFragment(R.layout.frag const val MESSAGE_TAB_FOLDER_ID = "message_tab_folder_id" - fun newInstance(folder: MessageFolder): MessageTabFragment { - return MessageTabFragment().apply { - arguments = Bundle().apply { - putString(MESSAGE_TAB_FOLDER_ID, folder.name) - } - } + fun newInstance(folder: MessageFolder) = MessageTabFragment().apply { + arguments = bundleOf(MESSAGE_TAB_FOLDER_ID to folder.name) } } @@ -131,7 +129,7 @@ class MessageTabFragment : BaseFragment(R.layout.frag setFragmentResultListener(requireArguments().getString(MESSAGE_TAB_FOLDER_ID)!!) { _, bundle -> presenter.onMailboxSelected( - mailbox = bundle.getSerializable(MailboxChooserDialog.MAILBOX_KEY) as? Mailbox, + mailbox = bundle.nullableSerializable(MailboxChooserDialog.MAILBOX_KEY), ) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt index 5811456b..e46ab42c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt @@ -6,6 +6,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.content.ContextCompat +import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Note @@ -13,6 +14,7 @@ import io.github.wulkanowy.databinding.DialogNoteBinding import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.lifecycleAwareVariable +import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.toFormattedString class NoteDialog : DialogFragment() { @@ -25,17 +27,15 @@ class NoteDialog : DialogFragment() { private const val ARGUMENT_KEY = "Item" - fun newInstance(exam: Note) = NoteDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + fun newInstance(note: Note) = NoteDialog().apply { + arguments = bundleOf(ARGUMENT_KEY to note) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - note = getSerializable(ARGUMENT_KEY) as Note - } + note = requireArguments().serializable(ARGUMENT_KEY) } override fun onCreateView( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt new file mode 100644 index 00000000..163ba8cd --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt @@ -0,0 +1,64 @@ +package io.github.wulkanowy.ui.modules.notifications + +import android.os.Bundle +import android.view.View +import androidx.activity.result.contract.ActivityResultContracts.RequestPermission +import androidx.appcompat.app.AlertDialog +import dagger.hilt.android.AndroidEntryPoint +import io.github.wulkanowy.R +import io.github.wulkanowy.databinding.FragmentNotificationsBinding +import io.github.wulkanowy.ui.base.BaseFragment +import io.github.wulkanowy.ui.modules.login.LoginActivity +import io.github.wulkanowy.utils.openNotificationSettings + +@AndroidEntryPoint +class NotificationsFragment : + BaseFragment(R.layout.fragment_notifications) { + + private val permission = "android.permission.POST_NOTIFICATIONS" + + private val requestPermissionLauncher = registerForActivityResult(RequestPermission()) { + if (it) { + navigateToFinish() + } else showSettingsDialog() + } + + companion object { + fun newInstance() = NotificationsFragment() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding = FragmentNotificationsBinding.bind(view) + initView() + } + + private fun initView() { + with(binding) { + notificationsSkip.setOnClickListener { navigateToFinish() } + notificationsEnable.setOnClickListener { requestPermission() } + } + } + + private fun showSettingsDialog() { + AlertDialog.Builder(requireContext()) + .setTitle(R.string.notifications_header_title) + .setMessage(R.string.notifications_header_description) + .setNegativeButton(R.string.notifications_skip) { dialog, _ -> + dialog.dismiss() + navigateToFinish() + } + .setPositiveButton(R.string.pref_notification_go_to_settings) { _, _ -> + requireActivity().openNotificationSettings() + } + .show() + } + + private fun requestPermission() { + requestPermissionLauncher.launch(permission) + } + + private fun navigateToFinish() { + (requireActivity() as LoginActivity).navigateToFinish() + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt index 7dcd51ce..0a71afef 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt @@ -4,11 +4,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.core.text.parseAsHtml import androidx.fragment.app.DialogFragment import io.github.wulkanowy.data.db.entities.SchoolAnnouncement import io.github.wulkanowy.databinding.DialogSchoolAnnouncementBinding import io.github.wulkanowy.utils.lifecycleAwareVariable +import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.toFormattedString class SchoolAnnouncementDialog : DialogFragment() { @@ -21,17 +23,15 @@ class SchoolAnnouncementDialog : DialogFragment() { private const val ARGUMENT_KEY = "item" - fun newInstance(exam: SchoolAnnouncement) = SchoolAnnouncementDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + fun newInstance(announcement: SchoolAnnouncement) = SchoolAnnouncementDialog().apply { + arguments = bundleOf(ARGUMENT_KEY to announcement) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - announcement = getSerializable(ARGUMENT_KEY) as SchoolAnnouncement - } + announcement = requireArguments().serializable(ARGUMENT_KEY) } override fun onCreateView( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt index 364ad213..77a3c6cf 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt @@ -1,18 +1,16 @@ package io.github.wulkanowy.ui.modules.settings.notifications -import android.annotation.SuppressLint import android.content.Intent import android.content.SharedPreferences -import android.net.Uri -import android.os.Build +import android.content.pm.PackageManager import android.os.Bundle -import android.provider.Settings import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.core.app.NotificationManagerCompat +import androidx.core.content.ContextCompat import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreferenceCompat @@ -26,7 +24,7 @@ import io.github.wulkanowy.ui.base.ErrorDialog import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.openInternetBrowser -import timber.log.Timber +import io.github.wulkanowy.utils.openNotificationSettings import javax.inject.Inject @AndroidEntryPoint @@ -42,7 +40,14 @@ class NotificationsFragment : PreferenceFragmentCompat(), override val titleStringId get() = R.string.pref_settings_notifications_title + private val notificationsPermission = "android.permission.POST_NOTIFICATIONS" + override val isNotificationPermissionGranted: Boolean + get() = ContextCompat.checkSelfPermission( + requireContext(), notificationsPermission + ) == PackageManager.PERMISSION_GRANTED + + override val isNotificationPiggybackPermissionGranted: Boolean get() { val packageNameList = NotificationManagerCompat.getEnabledListenerPackages(requireContext()) @@ -51,6 +56,13 @@ class NotificationsFragment : PreferenceFragmentCompat(), return appPackageName in packageNameList } + private val requestPermissionLauncher = + registerForActivityResult(ActivityResultContracts.RequestPermission()) { + if (it) { + presenter.onNotificationsPermissionResult() + } else openNotificationsPermissionDialog() + } + private val notificationSettingsPiggybackContract = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { presenter.onNotificationPiggybackPermissionResult() @@ -156,25 +168,29 @@ class NotificationsFragment : PreferenceFragmentCompat(), .show() } - @SuppressLint("InlinedApi") override fun openSystemSettings() { - val intent = if (appInfo.systemVersion >= Build.VERSION_CODES.O) { - Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { - putExtra("android.provider.extra.APP_PACKAGE", requireActivity().packageName) - } - } else { - Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { - data = Uri.fromParts("package", requireActivity().packageName, null) - } - } - try { - requireActivity().startActivity(intent) - } catch (e: Exception) { - Timber.e(e) - } + requireActivity().openNotificationSettings() } - override fun openNotificationPermissionDialog() { + override fun requestNotificationPermissions() { + requestPermissionLauncher.launch(notificationsPermission) + } + + override fun openNotificationsPermissionDialog() { + AlertDialog.Builder(requireContext()) + .setTitle(R.string.notifications_header_title) + .setMessage(R.string.notifications_header_description) + .setPositiveButton(R.string.pref_notification_go_to_settings) { _, _ -> + requireActivity().openNotificationSettings() + } + .setNegativeButton(android.R.string.cancel) { _, _ -> + setNotificationPreferencesChecked(false) + } + .setOnDismissListener { setNotificationPreferencesChecked(false) } + .show() + } + + override fun openNotificationPiggyBackPermissionDialog() { AlertDialog.Builder(requireContext()) .setTitle(getString(R.string.pref_notification_piggyback_popup_title)) .setMessage(getString(R.string.pref_notification_piggyback_popup_description)) @@ -202,6 +218,11 @@ class NotificationsFragment : PreferenceFragmentCompat(), .show() } + override fun setNotificationPreferencesChecked(isChecked: Boolean) { + findPreference(getString(R.string.pref_key_notifications_enable))?.isChecked = + isChecked + } + override fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) { findPreference(getString(R.string.pref_key_notifications_piggyback))?.isChecked = isChecked diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt index 4cbdac94..232b0348 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt @@ -26,12 +26,13 @@ class NotificationsPresenter @Inject constructor( with(view) { enableNotification( - preferencesRepository.notificationsEnableKey, - preferencesRepository.isServiceEnabled + notificationKey = preferencesRepository.notificationsEnableKey, + enable = preferencesRepository.isServiceEnabled ) initView(appInfo.isDebug) } + checkNotificationsPermissionState() checkNotificationPiggybackState() Timber.i("Settings notifications view was initialized") @@ -49,12 +50,17 @@ class NotificationsPresenter @Inject constructor( view?.openNotificationExactAlarmSettings() } } + notificationsEnableKey -> { + if (isNotificationsEnable && view?.isNotificationPermissionGranted == false) { + view?.requestNotificationPermissions() + } + } isDebugNotificationEnableKey -> { chuckerCollector.showNotification = isDebugNotificationEnable } isNotificationPiggybackEnabledKey -> { - if (isNotificationPiggybackEnabled && view?.isNotificationPermissionGranted == false) { - view?.openNotificationPermissionDialog() + if (isNotificationPiggybackEnabled && view?.isNotificationPiggybackPermissionGranted == false) { + view?.openNotificationPiggyBackPermissionDialog() } } } @@ -70,9 +76,15 @@ class NotificationsPresenter @Inject constructor( view?.openSystemSettings() } + fun onNotificationsPermissionResult() { + view?.run { + setNotificationPreferencesChecked(isNotificationPermissionGranted) + } + } + fun onNotificationPiggybackPermissionResult() { view?.run { - setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted) + setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted) } } @@ -80,10 +92,18 @@ class NotificationsPresenter @Inject constructor( view?.setUpcomingLessonsNotificationPreferenceChecked(timetableNotificationHelper.canScheduleExactAlarms()) } + private fun checkNotificationsPermissionState() { + if (preferencesRepository.isNotificationsEnable) { + view?.run { + setNotificationPreferencesChecked(isNotificationPermissionGranted) + } + } + } + private fun checkNotificationPiggybackState() { if (preferencesRepository.isNotificationPiggybackEnabled) { view?.run { - setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted) + setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted) } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt index 2bf8e31f..a391681c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt @@ -6,6 +6,8 @@ interface NotificationsView : BaseView { val isNotificationPermissionGranted: Boolean + val isNotificationPiggybackPermissionGranted: Boolean + fun initView(showDebugNotificationSwitch: Boolean) fun showFixSyncDialog() @@ -14,10 +16,16 @@ interface NotificationsView : BaseView { fun enableNotification(notificationKey: String, enable: Boolean) - fun openNotificationPermissionDialog() + fun requestNotificationPermissions() + + fun openNotificationsPermissionDialog() + + fun openNotificationPiggyBackPermissionDialog() fun openNotificationExactAlarmSettings() + fun setNotificationPreferencesChecked(isChecked: Boolean) + fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) fun setUpcomingLessonsNotificationPreferenceChecked(isChecked: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt index 6ff7a39b..598046a2 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt @@ -8,6 +8,7 @@ import android.view.MenuInflater import android.view.View import android.widget.Toast import androidx.core.content.getSystemService +import androidx.core.os.bundleOf import androidx.core.view.get import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager @@ -24,6 +25,8 @@ import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.utils.capitalise import io.github.wulkanowy.utils.getThemeAttrColor +import io.github.wulkanowy.utils.nullableSerializable +import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -38,7 +41,9 @@ class StudentInfoFragment : lateinit var studentInfoAdapter: StudentInfoAdapter override val titleStringId: Int - get() = when (requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as? StudentInfoView.Type) { + get() = when ( + requireArguments().nullableSerializable(INFO_TYPE_ARGUMENT_KEY) + ) { StudentInfoView.Type.PERSONAL -> R.string.account_personal_data StudentInfoView.Type.CONTACT -> R.string.account_contact StudentInfoView.Type.ADDRESS -> R.string.account_address @@ -58,10 +63,10 @@ class StudentInfoFragment : fun newInstance(type: StudentInfoView.Type, studentWithSemesters: StudentWithSemesters) = StudentInfoFragment().apply { - arguments = Bundle().apply { - putSerializable(INFO_TYPE_ARGUMENT_KEY, type) - putSerializable(STUDENT_ARGUMENT_KEY, studentWithSemesters) - } + arguments = bundleOf( + INFO_TYPE_ARGUMENT_KEY to type, + STUDENT_ARGUMENT_KEY to studentWithSemesters + ) } } @@ -75,9 +80,9 @@ class StudentInfoFragment : super.onViewCreated(view, savedInstanceState) binding = FragmentStudentInfoBinding.bind(view) presenter.onAttachView( - this, - requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as StudentInfoView.Type, - requireArguments().getSerializable(STUDENT_ARGUMENT_KEY) as StudentWithSemesters + view = this, + type = requireArguments().serializable(INFO_TYPE_ARGUMENT_KEY), + studentWithSemesters = requireArguments().serializable(STUDENT_ARGUMENT_KEY), ) } @@ -154,7 +159,6 @@ class StudentInfoFragment : ) } - @OptIn(ExperimentalStdlibApi::class) override fun showFamilyTypeData(studentInfo: StudentInfo) { val items = buildList { add(studentInfo.firstGuardian?.let { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt index c9243b12..4f5547d2 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt @@ -8,14 +8,12 @@ import android.view.View import android.view.View.GONE import android.view.View.VISIBLE import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.databinding.DialogTimetableBinding -import io.github.wulkanowy.utils.capitalise -import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.lifecycleAwareVariable -import io.github.wulkanowy.utils.toFormattedString +import io.github.wulkanowy.utils.* import java.time.Instant class TimetableDialog : DialogFragment() { @@ -28,17 +26,15 @@ class TimetableDialog : DialogFragment() { private const val ARGUMENT_KEY = "Item" - fun newInstance(exam: Timetable) = TimetableDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + fun newInstance(lesson: Timetable) = TimetableDialog().apply { + arguments = bundleOf(ARGUMENT_KEY to lesson) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - lesson = getSerializable(ARGUMENT_KEY) as Timetable - } + lesson = requireArguments().serializable(ARGUMENT_KEY) } override fun onCreateView( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt index 6fd12632..e95d6f82 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt @@ -7,6 +7,7 @@ import android.view.MenuItem import android.view.View import android.view.View.GONE import android.view.View.VISIBLE +import androidx.core.os.bundleOf import androidx.core.text.parseAsHtml import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint @@ -39,9 +40,7 @@ class TimetableFragment : BaseFragment(R.layout.fragme private const val ARGUMENT_DATE_KEY = "ARGUMENT_DATE" fun newInstance(date: LocalDate? = null) = TimetableFragment().apply { - arguments = Bundle().apply { - date?.let { putLong(ARGUMENT_DATE_KEY, it.toEpochDay()) } - } + arguments = date?.let { bundleOf(ARGUMENT_DATE_KEY to it.toEpochDay()) } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt index 7d32278f..ddd7488e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt @@ -4,10 +4,12 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import io.github.wulkanowy.data.db.entities.CompletedLesson import io.github.wulkanowy.databinding.DialogLessonCompletedBinding import io.github.wulkanowy.utils.lifecycleAwareVariable +import io.github.wulkanowy.utils.serializable class CompletedLessonDialog : DialogFragment() { @@ -19,17 +21,15 @@ class CompletedLessonDialog : DialogFragment() { private const val ARGUMENT_KEY = "Item" - fun newInstance(exam: CompletedLesson) = CompletedLessonDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + fun newInstance(lesson: CompletedLesson) = CompletedLessonDialog().apply { + arguments = bundleOf(ARGUMENT_KEY to lesson) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - completedLesson = getSerializable(ARGUMENT_KEY) as CompletedLesson - } + completedLesson = requireArguments().serializable(ARGUMENT_KEY) } override fun onCreateView( diff --git a/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt new file mode 100644 index 00000000..d0d47025 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt @@ -0,0 +1,32 @@ +package io.github.wulkanowy.utils + +import android.content.Intent +import android.os.Build +import android.os.Bundle +import java.io.Serializable + +inline fun Bundle.serializable(key: String): T = when { + Build.VERSION.SDK_INT >= 33 -> getSerializable(key, T::class.java)!! + else -> @Suppress("DEPRECATION") getSerializable(key) as T +} + +inline fun Bundle.nullableSerializable(key: String): T? = when { + Build.VERSION.SDK_INT >= 33 -> getSerializable(key, T::class.java) + else -> @Suppress("DEPRECATION") getSerializable(key) as T? +} + +@Suppress("DEPRECATION", "UNCHECKED_CAST") +inline fun Bundle.parcelableArray(key: String): Array? = when { + Build.VERSION.SDK_INT >= 33 -> getParcelableArray(key, T::class.java) + else -> getParcelableArray(key) as Array? +} + +inline fun Intent.serializable(key: String): T = when { + Build.VERSION.SDK_INT >= 33 -> getSerializableExtra(key, T::class.java)!! + else -> @Suppress("DEPRECATION") getSerializableExtra(key) as T +} + +inline fun Intent.nullableSerializable(key: String): T? = when { + Build.VERSION.SDK_INT >= 33 -> getSerializableExtra(key, T::class.java) + else -> @Suppress("DEPRECATION") getSerializableExtra(key) as T? +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/IntentUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/IntentUtils.kt index 1ef03f2e..62b85af4 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/IntentUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/IntentUtils.kt @@ -1,11 +1,15 @@ package io.github.wulkanowy.utils +import android.app.Activity import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.net.Uri +import android.os.Build import android.provider.CalendarContract +import android.provider.Settings import io.github.wulkanowy.BuildConfig +import timber.log.Timber import java.time.LocalDateTime import java.time.ZoneId @@ -86,6 +90,23 @@ fun Context.openDialer(phone: String) { } } +fun Activity.openNotificationSettings() { + val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { + putExtra("android.provider.extra.APP_PACKAGE", packageName) + } + } else { + Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { + data = Uri.fromParts("package", packageName, null) + } + } + try { + startActivity(intent) + } catch (e: Exception) { + Timber.e(e) + } +} + fun Context.shareText(text: String, subject: String?) { val sendIntent: Intent = Intent().apply { action = Intent.ACTION_SEND diff --git a/app/src/main/res/drawable/ic_launcher_foreground_dev_mono.xml b/app/src/main/res/drawable/ic_launcher_foreground_dev_mono.xml new file mode 100644 index 00000000..b1b01a0b --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground_dev_mono.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground_mono.xml b/app/src/main/res/drawable/ic_launcher_foreground_mono.xml new file mode 100644 index 00000000..e2e74731 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground_mono.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/fragment_notifications.xml b/app/src/main/res/layout/fragment_notifications.xml new file mode 100644 index 00000000..8e506e1e --- /dev/null +++ b/app/src/main/res/layout/fragment_notifications.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index d59ec8e1..da1bca12 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -2,4 +2,5 @@ - \ No newline at end of file + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index d59ec8e1..00000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 85f6a2c87d16f05dac43a09867994b07f527ed7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4025 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 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index dd67b87716351217f708ad5a0ed185d8bd6321e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5740 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 JPDHLkV1lpA?d$*m diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 71d1767e..874b121f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -74,6 +74,11 @@ Recover Student is already signed in Standard + + Enable notifications + Enable notifications so you don\'t miss message from teacher or new grade + Skip + Enable Account manager Log in diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 00000000..418b6d4c --- /dev/null +++ b/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt b/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt index e52ec3ae..a31ef517 100644 --- a/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt +++ b/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt @@ -90,14 +90,14 @@ class LoginStudentSelectPresenterTest { studentRepository.saveStudents(listOf(StudentWithSemesters(testStudent, emptyList()))) } just Runs - every { loginStudentSelectView.openMainView() } just Runs + every { loginStudentSelectView.navigateToNext() } just Runs presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false) presenter.onSignIn() verify { loginStudentSelectView.showContent(false) } verify { loginStudentSelectView.showProgress(true) } - verify { loginStudentSelectView.openMainView() } + verify { loginStudentSelectView.navigateToNext() } } @Test