Update project to Android SDK 33 (#2011)
@ -16,13 +16,13 @@ apply from: 'hooks.gradle'
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
namespace 'io.github.wulkanowy'
|
namespace 'io.github.wulkanowy'
|
||||||
compileSdkVersion 32
|
compileSdkVersion 33
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "io.github.wulkanowy"
|
applicationId "io.github.wulkanowy"
|
||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 32
|
targetSdkVersion 33
|
||||||
versionCode 116
|
versionCode 116
|
||||||
versionName "1.8.1"
|
versionName "1.8.1"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
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-serialization-json:1.4.1"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
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.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.appcompat:appcompat:1.5.1"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.5.4"
|
implementation "androidx.fragment:fragment-ktx:1.5.4"
|
||||||
implementation "androidx.annotation:annotation:1.5.0"
|
implementation "androidx.annotation:annotation:1.5.0"
|
||||||
@ -271,9 +271,9 @@ dependencies {
|
|||||||
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
||||||
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
|
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||||
|
|
||||||
androidTestImplementation "androidx.test:core:1.4.0"
|
androidTestImplementation "androidx.test:core:1.5.0"
|
||||||
androidTestImplementation "androidx.test:runner:1.4.0"
|
androidTestImplementation "androidx.test:runner:1.5.1"
|
||||||
androidTestImplementation "androidx.test.ext:junit:1.1.3"
|
androidTestImplementation "androidx.test.ext:junit:1.1.4"
|
||||||
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
||||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,5 @@
|
|||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/colorPrimary" />
|
<background android:drawable="@color/colorPrimary" />
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
|
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_foreground_dev_mono" />
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/colorPrimary" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
|
|
||||||
</adaptive-icon>
|
|
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 13 KiB |
@ -9,6 +9,7 @@
|
|||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
@ -36,13 +37,14 @@
|
|||||||
<application
|
<application
|
||||||
android:name=".WulkanowyApp"
|
android:name=".WulkanowyApp"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:supportsRtl="false"
|
android:supportsRtl="false"
|
||||||
android:theme="@style/WulkanowyTheme"
|
android:theme="@style/WulkanowyTheme"
|
||||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
tools:ignore="DataExtractionRules,UnusedAttribute">
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.splash.SplashActivity"
|
android:name=".ui.modules.splash.SplashActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -37,7 +37,7 @@ class ErrorDialog : DialogFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val error = requireArguments().getSerializable(ARGUMENT_KEY) as Throwable
|
val error = requireArguments().serializable<Throwable>(ARGUMENT_KEY)
|
||||||
|
|
||||||
val binding = DialogErrorBinding.inflate(layoutInflater)
|
val binding = DialogErrorBinding.inflate(layoutInflater)
|
||||||
binding.bindErrorDetails(error)
|
binding.bindErrorDetails(error)
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package io.github.wulkanowy.ui.base
|
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.content.pm.PackageManager.GET_ACTIVITIES
|
||||||
|
import android.os.Build
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
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) =
|
private fun isThemeApplicable(activity: AppCompatActivity): Boolean =
|
||||||
activity.packageManager
|
getPackageInfo(activity)
|
||||||
.getPackageInfo(activity.packageName, GET_ACTIVITIES)
|
|
||||||
.activities
|
.activities
|
||||||
.singleOrNull { it.name == activity::class.java.canonicalName }
|
.singleOrNull { it.name == activity::class.java.canonicalName }
|
||||||
?.theme
|
?.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_Login || it == R.style.WulkanowyTheme_Login_Black
|
||||||
|| it == R.style.WulkanowyTheme_MessageSend || it == R.style.WulkanowyTheme_MessageSend_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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import android.view.MenuInflater
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.get
|
import androidx.core.view.get
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
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.ui.modules.studentinfo.StudentInfoView
|
||||||
import io.github.wulkanowy.utils.createNameInitialsDrawable
|
import io.github.wulkanowy.utils.createNameInitialsDrawable
|
||||||
import io.github.wulkanowy.utils.nickOrName
|
import io.github.wulkanowy.utils.nickOrName
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -37,9 +39,8 @@ class AccountDetailsFragment :
|
|||||||
|
|
||||||
private const val ARGUMENT_KEY = "Data"
|
private const val ARGUMENT_KEY = "Data"
|
||||||
|
|
||||||
fun newInstance(student: Student) =
|
fun newInstance(student: Student) = AccountDetailsFragment().apply {
|
||||||
AccountDetailsFragment().apply {
|
arguments = bundleOf(ARGUMENT_KEY to student)
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, student) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ class AccountDetailsFragment :
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
binding = FragmentAccountDetailsBinding.bind(view)
|
binding = FragmentAccountDetailsBinding.bind(view)
|
||||||
presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student)
|
presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
|
@ -4,11 +4,13 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.databinding.DialogAccountEditBinding
|
import io.github.wulkanowy.databinding.DialogAccountEditBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -24,11 +26,8 @@ class AccountEditDialog : BaseDialogFragment<DialogAccountEditBinding>(), Accoun
|
|||||||
|
|
||||||
private const val ARGUMENT_KEY = "student_with_semesters"
|
private const val ARGUMENT_KEY = "student_with_semesters"
|
||||||
|
|
||||||
fun newInstance(student: Student) =
|
fun newInstance(student: Student) = AccountEditDialog().apply {
|
||||||
AccountEditDialog().apply {
|
arguments = bundleOf(ARGUMENT_KEY to student)
|
||||||
arguments = Bundle().apply {
|
|
||||||
putSerializable(ARGUMENT_KEY, student)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +44,7 @@ class AccountEditDialog : BaseDialogFragment<DialogAccountEditBinding>(), Accoun
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student)
|
presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
|
@ -4,6 +4,7 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
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.AccountFragment
|
||||||
import io.github.wulkanowy.ui.modules.account.AccountItem
|
import io.github.wulkanowy.ui.modules.account.AccountItem
|
||||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -30,9 +32,7 @@ class AccountQuickDialog : BaseDialogFragment<DialogAccountQuickBinding>(), Acco
|
|||||||
|
|
||||||
fun newInstance(studentsWithSemesters: List<StudentWithSemesters>) =
|
fun newInstance(studentsWithSemesters: List<StudentWithSemesters>) =
|
||||||
AccountQuickDialog().apply {
|
AccountQuickDialog().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = bundleOf(STUDENTS_ARGUMENT_KEY to studentsWithSemesters.toTypedArray())
|
||||||
putSerializable(STUDENTS_ARGUMENT_KEY, studentsWithSemesters.toTypedArray())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,8 +49,8 @@ class AccountQuickDialog : BaseDialogFragment<DialogAccountQuickBinding>(), Acco
|
|||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
val studentsWithSemesters =
|
val studentsWithSemesters = requireArguments()
|
||||||
(requireArguments()[STUDENTS_ARGUMENT_KEY] as Array<StudentWithSemesters>).toList()
|
.serializable<Array<StudentWithSemesters>>(STUDENTS_ARGUMENT_KEY).toList()
|
||||||
|
|
||||||
presenter.onAttachView(this, studentsWithSemesters)
|
presenter.onAttachView(this, studentsWithSemesters)
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,13 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.databinding.DialogAttendanceBinding
|
import io.github.wulkanowy.databinding.DialogAttendanceBinding
|
||||||
import io.github.wulkanowy.utils.descriptionRes
|
import io.github.wulkanowy.utils.descriptionRes
|
||||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
|
||||||
class AttendanceDialog : DialogFragment() {
|
class AttendanceDialog : DialogFragment() {
|
||||||
@ -22,16 +24,14 @@ class AttendanceDialog : DialogFragment() {
|
|||||||
private const val ARGUMENT_KEY = "Item"
|
private const val ARGUMENT_KEY = "Item"
|
||||||
|
|
||||||
fun newInstance(exam: Attendance) = AttendanceDialog().apply {
|
fun newInstance(exam: Attendance) = AttendanceDialog().apply {
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
arguments = bundleOf(ARGUMENT_KEY to exam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
setStyle(STYLE_NO_TITLE, 0)
|
||||||
arguments?.run {
|
attendance = requireArguments().serializable(ARGUMENT_KEY)
|
||||||
attendance = getSerializable(ARGUMENT_KEY) as Attendance
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -4,11 +4,13 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import io.github.wulkanowy.data.db.entities.Conference
|
import io.github.wulkanowy.data.db.entities.Conference
|
||||||
import io.github.wulkanowy.databinding.DialogConferenceBinding
|
import io.github.wulkanowy.databinding.DialogConferenceBinding
|
||||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
|
||||||
class ConferenceDialog : DialogFragment() {
|
class ConferenceDialog : DialogFragment() {
|
||||||
@ -22,16 +24,14 @@ class ConferenceDialog : DialogFragment() {
|
|||||||
private const val ARGUMENT_KEY = "item"
|
private const val ARGUMENT_KEY = "item"
|
||||||
|
|
||||||
fun newInstance(conference: Conference) = ConferenceDialog().apply {
|
fun newInstance(conference: Conference) = ConferenceDialog().apply {
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, conference) }
|
arguments = bundleOf(ARGUMENT_KEY to conference)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
setStyle(STYLE_NO_TITLE, 0)
|
||||||
arguments?.let {
|
conference = requireArguments().serializable(ARGUMENT_KEY)
|
||||||
conference = it.getSerializable(ARGUMENT_KEY) as Conference
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -4,12 +4,14 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.databinding.DialogExamBinding
|
import io.github.wulkanowy.databinding.DialogExamBinding
|
||||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||||
import io.github.wulkanowy.utils.openCalendarEventAdd
|
import io.github.wulkanowy.utils.openCalendarEventAdd
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
|
|
||||||
@ -24,16 +26,14 @@ class ExamDialog : DialogFragment() {
|
|||||||
private const val ARGUMENT_KEY = "Item"
|
private const val ARGUMENT_KEY = "Item"
|
||||||
|
|
||||||
fun newInstance(exam: Exam) = ExamDialog().apply {
|
fun newInstance(exam: Exam) = ExamDialog().apply {
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
arguments = bundleOf(ARGUMENT_KEY to exam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
setStyle(STYLE_NO_TITLE, 0)
|
||||||
arguments?.run {
|
exam = requireArguments().serializable(ARGUMENT_KEY)
|
||||||
exam = getSerializable(ARGUMENT_KEY) as Exam
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -5,6 +5,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
@ -27,22 +28,19 @@ class GradeDetailsDialog : DialogFragment() {
|
|||||||
|
|
||||||
private const val COLOR_THEME_KEY = "Theme"
|
private const val COLOR_THEME_KEY = "Theme"
|
||||||
|
|
||||||
fun newInstance(grade: Grade, colorTheme: GradeColorTheme) =
|
fun newInstance(grade: Grade, colorTheme: GradeColorTheme) = GradeDetailsDialog().apply {
|
||||||
GradeDetailsDialog().apply {
|
arguments = bundleOf(
|
||||||
arguments = Bundle().apply {
|
ARGUMENT_KEY to grade,
|
||||||
putSerializable(ARGUMENT_KEY, grade)
|
COLOR_THEME_KEY to colorTheme
|
||||||
putSerializable(COLOR_THEME_KEY, colorTheme)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
setStyle(STYLE_NO_TITLE, 0)
|
||||||
arguments?.run {
|
grade = requireArguments().serializable(ARGUMENT_KEY)
|
||||||
grade = getSerializable(ARGUMENT_KEY) as Grade
|
gradeColorTheme = requireArguments().serializable(COLOR_THEME_KEY)
|
||||||
gradeColorTheme = getSerializable(COLOR_THEME_KEY) as GradeColorTheme
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -15,6 +15,7 @@ import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
|||||||
import io.github.wulkanowy.ui.modules.grade.GradeView
|
import io.github.wulkanowy.ui.modules.grade.GradeView
|
||||||
import io.github.wulkanowy.utils.dpToPx
|
import io.github.wulkanowy.utils.dpToPx
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import io.github.wulkanowy.utils.setOnItemSelectedListener
|
import io.github.wulkanowy.utils.setOnItemSelectedListener
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -48,8 +49,8 @@ class GradeStatisticsFragment :
|
|||||||
messageContainer = binding.gradeStatisticsRecycler
|
messageContainer = binding.gradeStatisticsRecycler
|
||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
view = this,
|
view = this,
|
||||||
type = savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? GradeStatisticsItem.DataType,
|
type = savedInstanceState?.serializable(SAVED_CHART_TYPE),
|
||||||
subjectName = savedInstanceState?.getSerializable(SAVED_SUBJECT_NAME) as? String,
|
subjectName = savedInstanceState?.serializable(SAVED_SUBJECT_NAME),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
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.databinding.DialogHomeworkBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
import io.github.wulkanowy.utils.openInternetBrowser
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -35,16 +37,14 @@ class HomeworkDetailsDialog : BaseDialogFragment<DialogHomeworkBinding>(), Homew
|
|||||||
private const val ARGUMENT_KEY = "Item"
|
private const val ARGUMENT_KEY = "Item"
|
||||||
|
|
||||||
fun newInstance(homework: Homework) = HomeworkDetailsDialog().apply {
|
fun newInstance(homework: Homework) = HomeworkDetailsDialog().apply {
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, homework) }
|
arguments = bundleOf(ARGUMENT_KEY to homework)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
setStyle(STYLE_NO_TITLE, 0)
|
||||||
arguments?.run {
|
homework = requireArguments().serializable(ARGUMENT_KEY)
|
||||||
homework = getSerializable(ARGUMENT_KEY) as Homework
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -2,8 +2,11 @@ package io.github.wulkanowy.ui.modules.login
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build.VERSION_CODES.TIRAMISU
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
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.recover.LoginRecoverFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
|
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
|
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 io.github.wulkanowy.utils.UpdateHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -28,6 +34,9 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var updateHelper: UpdateHelper
|
lateinit var updateHelper: UpdateHelper
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var appInfo: AppInfo
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
|
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
|
||||||
}
|
}
|
||||||
@ -55,7 +64,7 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +80,22 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
|||||||
openFragment(LoginStudentSelectFragment.newInstance(studentsWithSemesters))
|
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() {
|
fun onAdvancedLoginClick() {
|
||||||
openFragment(LoginAdvancedFragment.newInstance())
|
openFragment(LoginAdvancedFragment.newInstance())
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ class LoginRecoverFragment :
|
|||||||
loginRecoverButton.setOnClickListener { presenter.onRecoverClick() }
|
loginRecoverButton.setOnClickListener { presenter.onRecoverClick() }
|
||||||
loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() }
|
loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() }
|
||||||
loginRecoverErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
loginRecoverErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||||
loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressed() }
|
loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressedDispatcher.onBackPressed() }
|
||||||
}
|
}
|
||||||
|
|
||||||
with(bindingLocal.loginRecoverHost) {
|
with(bindingLocal.loginRecoverHost) {
|
||||||
|
@ -13,10 +13,10 @@ import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|||||||
import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding
|
import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
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.AppInfo
|
||||||
import io.github.wulkanowy.utils.openEmailClient
|
import io.github.wulkanowy.utils.openEmailClient
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
import io.github.wulkanowy.utils.openInternetBrowser
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -51,7 +51,7 @@ class LoginStudentSelectFragment :
|
|||||||
binding = FragmentLoginStudentSelectBinding.bind(view)
|
binding = FragmentLoginStudentSelectBinding.bind(view)
|
||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
view = this,
|
view = this,
|
||||||
students = requireArguments().getSerializable(ARG_STUDENTS) as List<StudentWithSemesters>,
|
students = requireArguments().serializable(ARG_STUDENTS),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,9 +79,8 @@ class LoginStudentSelectFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openMainView() {
|
override fun navigateToNext() {
|
||||||
startActivity(MainActivity.getStartIntent(requireContext()))
|
(requireActivity() as LoginActivity).navigateToNotifications()
|
||||||
requireActivity().finish()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
override fun showProgress(show: Boolean) {
|
||||||
|
@ -100,7 +100,7 @@ class LoginStudentSelectPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
syncManager.startOneTimeSyncWorker(quiet = true)
|
syncManager.startOneTimeSyncWorker(quiet = true)
|
||||||
view?.openMainView()
|
view?.navigateToNext()
|
||||||
logRegisterEvent(studentsWithSemesters)
|
logRegisterEvent(studentsWithSemesters)
|
||||||
}
|
}
|
||||||
is Resource.Error -> {
|
is Resource.Error -> {
|
||||||
|
@ -9,7 +9,7 @@ interface LoginStudentSelectView : BaseView {
|
|||||||
|
|
||||||
fun updateData(data: List<Pair<StudentWithSemesters, Boolean>>)
|
fun updateData(data: List<Pair<StudentWithSemesters, Boolean>>)
|
||||||
|
|
||||||
fun openMainView()
|
fun navigateToNext()
|
||||||
|
|
||||||
fun showProgress(show: Boolean)
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
|
@ -18,11 +18,7 @@ import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding
|
|||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.*
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -54,7 +50,7 @@ class LoginSymbolFragment :
|
|||||||
binding = FragmentLoginSymbolBinding.bind(view)
|
binding = FragmentLoginSymbolBinding.bind(view)
|
||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
view = this,
|
view = this,
|
||||||
loginData = requireArguments().getSerializable(SAVED_LOGIN_DATA) as LoginData,
|
loginData = requireArguments().serializable(SAVED_LOGIN_DATA),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ import android.os.Build.VERSION_CODES.P
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import androidx.activity.OnBackPressedCallback
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
@ -50,6 +52,8 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var appInfo: AppInfo
|
lateinit var appInfo: AppInfo
|
||||||
|
|
||||||
|
private var onBackCallback: OnBackPressedCallback? = null
|
||||||
|
|
||||||
private var accountMenu: MenuItem? = null
|
private var accountMenu: MenuItem? = null
|
||||||
|
|
||||||
private val overlayProvider by lazy { ElevationOverlayProvider(this) }
|
private val overlayProvider by lazy { ElevationOverlayProvider(this) }
|
||||||
@ -88,6 +92,9 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
|||||||
this.savedInstanceState = savedInstanceState
|
this.savedInstanceState = savedInstanceState
|
||||||
messageContainer = binding.mainMessageContainer
|
messageContainer = binding.mainMessageContainer
|
||||||
updateHelper.messageContainer = binding.mainFragmentContainer
|
updateHelper.messageContainer = binding.mainFragmentContainer
|
||||||
|
onBackCallback = onBackPressedDispatcher.addCallback(this, enabled = false) {
|
||||||
|
presenter.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
val destination = intent.getStringExtra(EXTRA_START_DESTINATION)
|
val destination = intent.getStringExtra(EXTRA_START_DESTINATION)
|
||||||
?.takeIf { savedInstanceState == null }
|
?.takeIf { savedInstanceState == null }
|
||||||
@ -266,6 +273,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
|||||||
|
|
||||||
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
|
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
|
||||||
navController.pushFragment(fragment)
|
navController.pushFragment(fragment)
|
||||||
|
onBackCallback?.isEnabled = !isRootView
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popView(depth: Int) {
|
override fun popView(depth: Int) {
|
||||||
@ -273,10 +281,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
|||||||
|
|
||||||
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
|
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
|
||||||
navController.safelyPopFragments(depth)
|
navController.safelyPopFragments(depth)
|
||||||
}
|
onBackCallback?.isEnabled = !isRootView
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
presenter.onBackPressed { super.onBackPressed() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showStudentAvatar(student: Student) {
|
override fun showStudentAvatar(student: Student) {
|
||||||
|
@ -139,12 +139,9 @@ class MainPresenter @Inject constructor(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onBackPressed(default: () -> Unit) {
|
fun onBackPressed() {
|
||||||
Timber.i("Back pressed in main view")
|
Timber.i("Back pressed in main view")
|
||||||
view?.run {
|
view?.popView()
|
||||||
if (isRootView) default()
|
|
||||||
else popView()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onTabSelected(index: Int, wasSelected: Boolean): Boolean {
|
fun onTabSelected(index: Int, wasSelected: Boolean): Boolean {
|
||||||
|
@ -10,6 +10,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
import io.github.wulkanowy.data.db.entities.Mailbox
|
||||||
import io.github.wulkanowy.databinding.DialogMailboxChooserBinding
|
import io.github.wulkanowy.databinding.DialogMailboxChooserBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||||
|
import io.github.wulkanowy.utils.parcelableArray
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -52,8 +53,7 @@ class MailboxChooserDialog : BaseDialogFragment<DialogMailboxChooserBinding>(),
|
|||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
view = this,
|
view = this,
|
||||||
requireMailbox = requireArguments().getBoolean(REQUIRED_KEY, false),
|
requireMailbox = requireArguments().getBoolean(REQUIRED_KEY, false),
|
||||||
mailboxes = requireArguments().getParcelableArray(MAILBOX_KEY).orEmpty()
|
mailboxes = requireArguments().parcelableArray<Mailbox>(MAILBOX_KEY).orEmpty().toList(),
|
||||||
.toList() as List<Mailbox>,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import android.webkit.WebResourceRequest
|
|||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
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.MainActivity
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import io.github.wulkanowy.utils.shareText
|
import io.github.wulkanowy.utils.shareText
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -66,10 +68,8 @@ class MessagePreviewFragment :
|
|||||||
companion object {
|
companion object {
|
||||||
const val MESSAGE_ID_KEY = "message_id"
|
const val MESSAGE_ID_KEY = "message_id"
|
||||||
|
|
||||||
fun newInstance(message: Message): MessagePreviewFragment {
|
fun newInstance(message: Message) = MessagePreviewFragment().apply {
|
||||||
return MessagePreviewFragment().apply {
|
arguments = bundleOf(MESSAGE_ID_KEY to message)
|
||||||
arguments = Bundle().apply { putSerializable(MESSAGE_ID_KEY, message) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,8 +84,8 @@ class MessagePreviewFragment :
|
|||||||
binding = FragmentMessagePreviewBinding.bind(view)
|
binding = FragmentMessagePreviewBinding.bind(view)
|
||||||
messageContainer = binding.messagePreviewContainer
|
messageContainer = binding.messagePreviewContainer
|
||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
this,
|
view = this,
|
||||||
(savedInstanceState ?: arguments)?.getSerializable(MESSAGE_ID_KEY) as? Message
|
message = (savedInstanceState ?: arguments)?.serializable(MESSAGE_ID_KEY),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.ui.modules.message.mailboxchooser.MailboxChooserDialog.Companion.LISTENER_KEY
|
||||||
import io.github.wulkanowy.utils.dpToPx
|
import io.github.wulkanowy.utils.dpToPx
|
||||||
import io.github.wulkanowy.utils.hideSoftInput
|
import io.github.wulkanowy.utils.hideSoftInput
|
||||||
|
import io.github.wulkanowy.utils.nullableSerializable
|
||||||
import io.github.wulkanowy.utils.showSoftInput
|
import io.github.wulkanowy.utils.showSoftInput
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -108,12 +109,12 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter, ActivitySendMessa
|
|||||||
|
|
||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
view = this,
|
view = this,
|
||||||
reason = intent.getSerializableExtra(EXTRA_REASON) as? String,
|
reason = intent.nullableSerializable(EXTRA_REASON),
|
||||||
message = intent.getSerializableExtra(EXTRA_MESSAGE) as? Message,
|
message = intent.nullableSerializable(EXTRA_MESSAGE),
|
||||||
reply = intent.getSerializableExtra(EXTRA_REPLY) as? Boolean
|
reply = intent.nullableSerializable(EXTRA_REPLY)
|
||||||
)
|
)
|
||||||
supportFragmentManager.setFragmentResultListener(LISTENER_KEY, this) { _, bundle ->
|
supportFragmentManager.setFragmentResultListener(LISTENER_KEY, this) { _, bundle ->
|
||||||
presenter.onMailboxSelected(bundle.getSerializable(MAILBOX_KEY) as? Mailbox)
|
presenter.onMailboxSelected(bundle.nullableSerializable(MAILBOX_KEY))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import android.view.View.*
|
|||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.setFragmentResultListener
|
import androidx.fragment.app.setFragmentResultListener
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
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.dpToPx
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
import io.github.wulkanowy.utils.hideSoftInput
|
import io.github.wulkanowy.utils.hideSoftInput
|
||||||
|
import io.github.wulkanowy.utils.nullableSerializable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -43,12 +45,8 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
|
|||||||
|
|
||||||
const val MESSAGE_TAB_FOLDER_ID = "message_tab_folder_id"
|
const val MESSAGE_TAB_FOLDER_ID = "message_tab_folder_id"
|
||||||
|
|
||||||
fun newInstance(folder: MessageFolder): MessageTabFragment {
|
fun newInstance(folder: MessageFolder) = MessageTabFragment().apply {
|
||||||
return MessageTabFragment().apply {
|
arguments = bundleOf(MESSAGE_TAB_FOLDER_ID to folder.name)
|
||||||
arguments = Bundle().apply {
|
|
||||||
putString(MESSAGE_TAB_FOLDER_ID, folder.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +129,7 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
|
|||||||
|
|
||||||
setFragmentResultListener(requireArguments().getString(MESSAGE_TAB_FOLDER_ID)!!) { _, bundle ->
|
setFragmentResultListener(requireArguments().getString(MESSAGE_TAB_FOLDER_ID)!!) { _, bundle ->
|
||||||
presenter.onMailboxSelected(
|
presenter.onMailboxSelected(
|
||||||
mailbox = bundle.getSerializable(MailboxChooserDialog.MAILBOX_KEY) as? Mailbox,
|
mailbox = bundle.nullableSerializable(MailboxChooserDialog.MAILBOX_KEY),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Note
|
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.sdk.scrapper.notes.NoteCategory
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
|
||||||
class NoteDialog : DialogFragment() {
|
class NoteDialog : DialogFragment() {
|
||||||
@ -25,17 +27,15 @@ class NoteDialog : DialogFragment() {
|
|||||||
|
|
||||||
private const val ARGUMENT_KEY = "Item"
|
private const val ARGUMENT_KEY = "Item"
|
||||||
|
|
||||||
fun newInstance(exam: Note) = NoteDialog().apply {
|
fun newInstance(note: Note) = NoteDialog().apply {
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
arguments = bundleOf(ARGUMENT_KEY to note)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
setStyle(STYLE_NO_TITLE, 0)
|
||||||
arguments?.run {
|
note = requireArguments().serializable(ARGUMENT_KEY)
|
||||||
note = getSerializable(ARGUMENT_KEY) as Note
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -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<FragmentNotificationsBinding>(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()
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,13 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.text.parseAsHtml
|
import androidx.core.text.parseAsHtml
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
||||||
import io.github.wulkanowy.databinding.DialogSchoolAnnouncementBinding
|
import io.github.wulkanowy.databinding.DialogSchoolAnnouncementBinding
|
||||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
|
||||||
class SchoolAnnouncementDialog : DialogFragment() {
|
class SchoolAnnouncementDialog : DialogFragment() {
|
||||||
@ -21,17 +23,15 @@ class SchoolAnnouncementDialog : DialogFragment() {
|
|||||||
|
|
||||||
private const val ARGUMENT_KEY = "item"
|
private const val ARGUMENT_KEY = "item"
|
||||||
|
|
||||||
fun newInstance(exam: SchoolAnnouncement) = SchoolAnnouncementDialog().apply {
|
fun newInstance(announcement: SchoolAnnouncement) = SchoolAnnouncementDialog().apply {
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
arguments = bundleOf(ARGUMENT_KEY to announcement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
setStyle(STYLE_NO_TITLE, 0)
|
||||||
arguments?.run {
|
announcement = requireArguments().serializable(ARGUMENT_KEY)
|
||||||
announcement = getSerializable(ARGUMENT_KEY) as SchoolAnnouncement
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
package io.github.wulkanowy.ui.modules.settings.notifications
|
package io.github.wulkanowy.ui.modules.settings.notifications
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.SwitchPreferenceCompat
|
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.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
import io.github.wulkanowy.utils.openInternetBrowser
|
||||||
import timber.log.Timber
|
import io.github.wulkanowy.utils.openNotificationSettings
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -42,7 +40,14 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
|||||||
|
|
||||||
override val titleStringId get() = R.string.pref_settings_notifications_title
|
override val titleStringId get() = R.string.pref_settings_notifications_title
|
||||||
|
|
||||||
|
private val notificationsPermission = "android.permission.POST_NOTIFICATIONS"
|
||||||
|
|
||||||
override val isNotificationPermissionGranted: Boolean
|
override val isNotificationPermissionGranted: Boolean
|
||||||
|
get() = ContextCompat.checkSelfPermission(
|
||||||
|
requireContext(), notificationsPermission
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
|
||||||
|
override val isNotificationPiggybackPermissionGranted: Boolean
|
||||||
get() {
|
get() {
|
||||||
val packageNameList =
|
val packageNameList =
|
||||||
NotificationManagerCompat.getEnabledListenerPackages(requireContext())
|
NotificationManagerCompat.getEnabledListenerPackages(requireContext())
|
||||||
@ -51,6 +56,13 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
|||||||
return appPackageName in packageNameList
|
return appPackageName in packageNameList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val requestPermissionLauncher =
|
||||||
|
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||||
|
if (it) {
|
||||||
|
presenter.onNotificationsPermissionResult()
|
||||||
|
} else openNotificationsPermissionDialog()
|
||||||
|
}
|
||||||
|
|
||||||
private val notificationSettingsPiggybackContract =
|
private val notificationSettingsPiggybackContract =
|
||||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
presenter.onNotificationPiggybackPermissionResult()
|
presenter.onNotificationPiggybackPermissionResult()
|
||||||
@ -156,25 +168,29 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
|
||||||
override fun openSystemSettings() {
|
override fun openSystemSettings() {
|
||||||
val intent = if (appInfo.systemVersion >= Build.VERSION_CODES.O) {
|
requireActivity().openNotificationSettings()
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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())
|
AlertDialog.Builder(requireContext())
|
||||||
.setTitle(getString(R.string.pref_notification_piggyback_popup_title))
|
.setTitle(getString(R.string.pref_notification_piggyback_popup_title))
|
||||||
.setMessage(getString(R.string.pref_notification_piggyback_popup_description))
|
.setMessage(getString(R.string.pref_notification_piggyback_popup_description))
|
||||||
@ -202,6 +218,11 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setNotificationPreferencesChecked(isChecked: Boolean) {
|
||||||
|
findPreference<SwitchPreferenceCompat>(getString(R.string.pref_key_notifications_enable))?.isChecked =
|
||||||
|
isChecked
|
||||||
|
}
|
||||||
|
|
||||||
override fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) {
|
override fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) {
|
||||||
findPreference<SwitchPreferenceCompat>(getString(R.string.pref_key_notifications_piggyback))?.isChecked =
|
findPreference<SwitchPreferenceCompat>(getString(R.string.pref_key_notifications_piggyback))?.isChecked =
|
||||||
isChecked
|
isChecked
|
||||||
|
@ -26,12 +26,13 @@ class NotificationsPresenter @Inject constructor(
|
|||||||
|
|
||||||
with(view) {
|
with(view) {
|
||||||
enableNotification(
|
enableNotification(
|
||||||
preferencesRepository.notificationsEnableKey,
|
notificationKey = preferencesRepository.notificationsEnableKey,
|
||||||
preferencesRepository.isServiceEnabled
|
enable = preferencesRepository.isServiceEnabled
|
||||||
)
|
)
|
||||||
initView(appInfo.isDebug)
|
initView(appInfo.isDebug)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkNotificationsPermissionState()
|
||||||
checkNotificationPiggybackState()
|
checkNotificationPiggybackState()
|
||||||
|
|
||||||
Timber.i("Settings notifications view was initialized")
|
Timber.i("Settings notifications view was initialized")
|
||||||
@ -49,12 +50,17 @@ class NotificationsPresenter @Inject constructor(
|
|||||||
view?.openNotificationExactAlarmSettings()
|
view?.openNotificationExactAlarmSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
notificationsEnableKey -> {
|
||||||
|
if (isNotificationsEnable && view?.isNotificationPermissionGranted == false) {
|
||||||
|
view?.requestNotificationPermissions()
|
||||||
|
}
|
||||||
|
}
|
||||||
isDebugNotificationEnableKey -> {
|
isDebugNotificationEnableKey -> {
|
||||||
chuckerCollector.showNotification = isDebugNotificationEnable
|
chuckerCollector.showNotification = isDebugNotificationEnable
|
||||||
}
|
}
|
||||||
isNotificationPiggybackEnabledKey -> {
|
isNotificationPiggybackEnabledKey -> {
|
||||||
if (isNotificationPiggybackEnabled && view?.isNotificationPermissionGranted == false) {
|
if (isNotificationPiggybackEnabled && view?.isNotificationPiggybackPermissionGranted == false) {
|
||||||
view?.openNotificationPermissionDialog()
|
view?.openNotificationPiggyBackPermissionDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,9 +76,15 @@ class NotificationsPresenter @Inject constructor(
|
|||||||
view?.openSystemSettings()
|
view?.openSystemSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onNotificationsPermissionResult() {
|
||||||
|
view?.run {
|
||||||
|
setNotificationPreferencesChecked(isNotificationPermissionGranted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun onNotificationPiggybackPermissionResult() {
|
fun onNotificationPiggybackPermissionResult() {
|
||||||
view?.run {
|
view?.run {
|
||||||
setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
|
setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,10 +92,18 @@ class NotificationsPresenter @Inject constructor(
|
|||||||
view?.setUpcomingLessonsNotificationPreferenceChecked(timetableNotificationHelper.canScheduleExactAlarms())
|
view?.setUpcomingLessonsNotificationPreferenceChecked(timetableNotificationHelper.canScheduleExactAlarms())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkNotificationsPermissionState() {
|
||||||
|
if (preferencesRepository.isNotificationsEnable) {
|
||||||
|
view?.run {
|
||||||
|
setNotificationPreferencesChecked(isNotificationPermissionGranted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkNotificationPiggybackState() {
|
private fun checkNotificationPiggybackState() {
|
||||||
if (preferencesRepository.isNotificationPiggybackEnabled) {
|
if (preferencesRepository.isNotificationPiggybackEnabled) {
|
||||||
view?.run {
|
view?.run {
|
||||||
setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
|
setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ interface NotificationsView : BaseView {
|
|||||||
|
|
||||||
val isNotificationPermissionGranted: Boolean
|
val isNotificationPermissionGranted: Boolean
|
||||||
|
|
||||||
|
val isNotificationPiggybackPermissionGranted: Boolean
|
||||||
|
|
||||||
fun initView(showDebugNotificationSwitch: Boolean)
|
fun initView(showDebugNotificationSwitch: Boolean)
|
||||||
|
|
||||||
fun showFixSyncDialog()
|
fun showFixSyncDialog()
|
||||||
@ -14,10 +16,16 @@ interface NotificationsView : BaseView {
|
|||||||
|
|
||||||
fun enableNotification(notificationKey: String, enable: Boolean)
|
fun enableNotification(notificationKey: String, enable: Boolean)
|
||||||
|
|
||||||
fun openNotificationPermissionDialog()
|
fun requestNotificationPermissions()
|
||||||
|
|
||||||
|
fun openNotificationsPermissionDialog()
|
||||||
|
|
||||||
|
fun openNotificationPiggyBackPermissionDialog()
|
||||||
|
|
||||||
fun openNotificationExactAlarmSettings()
|
fun openNotificationExactAlarmSettings()
|
||||||
|
|
||||||
|
fun setNotificationPreferencesChecked(isChecked: Boolean)
|
||||||
|
|
||||||
fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean)
|
fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean)
|
||||||
|
|
||||||
fun setUpcomingLessonsNotificationPreferenceChecked(isChecked: Boolean)
|
fun setUpcomingLessonsNotificationPreferenceChecked(isChecked: Boolean)
|
||||||
|
@ -8,6 +8,7 @@ import android.view.MenuInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.get
|
import androidx.core.view.get
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
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.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.utils.capitalise
|
import io.github.wulkanowy.utils.capitalise
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
|
import io.github.wulkanowy.utils.nullableSerializable
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -38,7 +41,9 @@ class StudentInfoFragment :
|
|||||||
lateinit var studentInfoAdapter: StudentInfoAdapter
|
lateinit var studentInfoAdapter: StudentInfoAdapter
|
||||||
|
|
||||||
override val titleStringId: Int
|
override val titleStringId: Int
|
||||||
get() = when (requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as? StudentInfoView.Type) {
|
get() = when (
|
||||||
|
requireArguments().nullableSerializable<StudentInfoView.Type>(INFO_TYPE_ARGUMENT_KEY)
|
||||||
|
) {
|
||||||
StudentInfoView.Type.PERSONAL -> R.string.account_personal_data
|
StudentInfoView.Type.PERSONAL -> R.string.account_personal_data
|
||||||
StudentInfoView.Type.CONTACT -> R.string.account_contact
|
StudentInfoView.Type.CONTACT -> R.string.account_contact
|
||||||
StudentInfoView.Type.ADDRESS -> R.string.account_address
|
StudentInfoView.Type.ADDRESS -> R.string.account_address
|
||||||
@ -58,10 +63,10 @@ class StudentInfoFragment :
|
|||||||
|
|
||||||
fun newInstance(type: StudentInfoView.Type, studentWithSemesters: StudentWithSemesters) =
|
fun newInstance(type: StudentInfoView.Type, studentWithSemesters: StudentWithSemesters) =
|
||||||
StudentInfoFragment().apply {
|
StudentInfoFragment().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = bundleOf(
|
||||||
putSerializable(INFO_TYPE_ARGUMENT_KEY, type)
|
INFO_TYPE_ARGUMENT_KEY to type,
|
||||||
putSerializable(STUDENT_ARGUMENT_KEY, studentWithSemesters)
|
STUDENT_ARGUMENT_KEY to studentWithSemesters
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,9 +80,9 @@ class StudentInfoFragment :
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
binding = FragmentStudentInfoBinding.bind(view)
|
binding = FragmentStudentInfoBinding.bind(view)
|
||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
this,
|
view = this,
|
||||||
requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as StudentInfoView.Type,
|
type = requireArguments().serializable(INFO_TYPE_ARGUMENT_KEY),
|
||||||
requireArguments().getSerializable(STUDENT_ARGUMENT_KEY) as StudentWithSemesters
|
studentWithSemesters = requireArguments().serializable(STUDENT_ARGUMENT_KEY),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +159,6 @@ class StudentInfoFragment :
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
|
||||||
override fun showFamilyTypeData(studentInfo: StudentInfo) {
|
override fun showFamilyTypeData(studentInfo: StudentInfo) {
|
||||||
val items = buildList {
|
val items = buildList {
|
||||||
add(studentInfo.firstGuardian?.let {
|
add(studentInfo.firstGuardian?.let {
|
||||||
|
@ -8,14 +8,12 @@ import android.view.View
|
|||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.databinding.DialogTimetableBinding
|
import io.github.wulkanowy.databinding.DialogTimetableBinding
|
||||||
import io.github.wulkanowy.utils.capitalise
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
|
||||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
class TimetableDialog : DialogFragment() {
|
class TimetableDialog : DialogFragment() {
|
||||||
@ -28,17 +26,15 @@ class TimetableDialog : DialogFragment() {
|
|||||||
|
|
||||||
private const val ARGUMENT_KEY = "Item"
|
private const val ARGUMENT_KEY = "Item"
|
||||||
|
|
||||||
fun newInstance(exam: Timetable) = TimetableDialog().apply {
|
fun newInstance(lesson: Timetable) = TimetableDialog().apply {
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
arguments = bundleOf(ARGUMENT_KEY to lesson)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
setStyle(STYLE_NO_TITLE, 0)
|
||||||
arguments?.run {
|
lesson = requireArguments().serializable(ARGUMENT_KEY)
|
||||||
lesson = getSerializable(ARGUMENT_KEY) as Timetable
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -7,6 +7,7 @@ import android.view.MenuItem
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.text.parseAsHtml
|
import androidx.core.text.parseAsHtml
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@ -39,9 +40,7 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
|
|||||||
private const val ARGUMENT_DATE_KEY = "ARGUMENT_DATE"
|
private const val ARGUMENT_DATE_KEY = "ARGUMENT_DATE"
|
||||||
|
|
||||||
fun newInstance(date: LocalDate? = null) = TimetableFragment().apply {
|
fun newInstance(date: LocalDate? = null) = TimetableFragment().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = date?.let { bundleOf(ARGUMENT_DATE_KEY to it.toEpochDay()) }
|
||||||
date?.let { putLong(ARGUMENT_DATE_KEY, it.toEpochDay()) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,10 +4,12 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||||
import io.github.wulkanowy.databinding.DialogLessonCompletedBinding
|
import io.github.wulkanowy.databinding.DialogLessonCompletedBinding
|
||||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||||
|
import io.github.wulkanowy.utils.serializable
|
||||||
|
|
||||||
class CompletedLessonDialog : DialogFragment() {
|
class CompletedLessonDialog : DialogFragment() {
|
||||||
|
|
||||||
@ -19,17 +21,15 @@ class CompletedLessonDialog : DialogFragment() {
|
|||||||
|
|
||||||
private const val ARGUMENT_KEY = "Item"
|
private const val ARGUMENT_KEY = "Item"
|
||||||
|
|
||||||
fun newInstance(exam: CompletedLesson) = CompletedLessonDialog().apply {
|
fun newInstance(lesson: CompletedLesson) = CompletedLessonDialog().apply {
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
arguments = bundleOf(ARGUMENT_KEY to lesson)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
setStyle(STYLE_NO_TITLE, 0)
|
||||||
arguments?.run {
|
completedLesson = requireArguments().serializable(ARGUMENT_KEY)
|
||||||
completedLesson = getSerializable(ARGUMENT_KEY) as CompletedLesson
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -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 <reified T : Serializable> 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 <reified T : Serializable> 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 <reified T : Serializable> Bundle.parcelableArray(key: String): Array<T>? = when {
|
||||||
|
Build.VERSION.SDK_INT >= 33 -> getParcelableArray(key, T::class.java)
|
||||||
|
else -> getParcelableArray(key) as Array<T>?
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : Serializable> 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 <reified T : Serializable> Intent.nullableSerializable(key: String): T? = when {
|
||||||
|
Build.VERSION.SDK_INT >= 33 -> getSerializableExtra(key, T::class.java)
|
||||||
|
else -> @Suppress("DEPRECATION") getSerializableExtra(key) as T?
|
||||||
|
}
|
@ -1,11 +1,15 @@
|
|||||||
package io.github.wulkanowy.utils
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.provider.CalendarContract
|
import android.provider.CalendarContract
|
||||||
|
import android.provider.Settings
|
||||||
import io.github.wulkanowy.BuildConfig
|
import io.github.wulkanowy.BuildConfig
|
||||||
|
import timber.log.Timber
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneId
|
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?) {
|
fun Context.shareText(text: String, subject: String?) {
|
||||||
val sendIntent: Intent = Intent().apply {
|
val sendIntent: Intent = Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="1926"
|
||||||
|
android:viewportHeight="1926">
|
||||||
|
<path
|
||||||
|
android:fillColor="#fff"
|
||||||
|
android:pathData="M920,1357.7v-184.5h42.7q19.3,0.3 34.3,6.6 15.2,6.2 25.6,17.5 10.6,11.2 16,26.9 5.6,15.6 5.7, 34.6v13.5q-0.1,19 -5.7,34.7 -5.4,15.6 -16,26.9 -10.4,11.2 -25.6,17.5 -15,6.2 -34.3,6.3zM943.8,1192.5v146.1h18.9q15, -0.1 25.8,-5.2 11,-5.2 18,-14 7.3,-9 10.7,-21 3.5,-12 3.6,-26v-13.9q0,-14 -3.6,-26t-10.7,-20.7q-7,-9 -18,-14 -10.9,-5 -25.8,-5.3zM1179.5,1272.5h-77v65.4h89.8v19.9L1079,1357.8v-184.6h112.2v20h-88.7v59.4h77zM1288.9, 1320l43.6,-146.8h25l-58.2,184.6h-20.4l-58.3,-184.6h25z"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:strokeColor="#000" />
|
||||||
|
<clip-path android:pathData="M 0 0 L 1926 0 L 1926 1111 L 850 1111 L 850 1926 L 0 1926 z" />
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#fff"
|
||||||
|
android:pathData="M1082,1260v4l-6,73c0,5 -5,9 -10,9H879c-4,0 -8,-2 -10,-5l-31,-58 -29,-71v-8l48,-94c2,-3 2,-5 1, -8l-24,-65c-1,-2 0,-5 1,-7l39,-84c4,-8 17,-8 20,1l12,38 38,101c1,2 3,5 6,6l80,27c3,1 6,3 7,6l45,135zM852,717c0,-23 15,-43 35,-52l-2,-8c0,-11 13,-20 29,-20h1a38,38 0,0 1,36 -18l3,-2c11,-16 37,-27 68,-27 12,0 23,2 32,4 3,-3 8,-6 14,-6s12,3 14,8c8,-9 22,-16 38,-16 25,0 45,16 45,36l-1,7 3,4c16,6 27,17 27,30 0,14 -15,27 -34,32 -2,0 -3,1 -3,3 0,11 -11,21 -26,22v1c0,22 -41,40 -92,40 -11,0 -21,-1 -31,-3v1c0,9 -12,16 -26,16h-2l2,7c0,14 -18,25 -40,25h-7l-4, 2c-2,7 -8,12 -15,12 -9,0 -16,-7 -16,-16 0,-5 1,-8 4,-11l1,-4c-2,-3 -2,-5 -2,-8 0,-2 -2,-3 -3,-3 -27,-6 -48,-29 -48,-56z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#fff"
|
||||||
|
android:pathData="M1336,1346h-125c-3,0 -6,-1 -8,-4l-84,-118 -1,-2 -42,-122 -5,-5 -102,-52 -5,-6 -15,-75 -2,-3 -34,-51c-2,-3 -2,-6 -1,-9l21,-45c2,-4 5,-6 9,-6l39,-2c3,0 5,-1 6,-3l29,-22c5,-4 14,-2 17,4l98,201 1,2 13,81 2,5 197,216c6,6 1,16 -8,16zM801,1302c1,3 1,6 -1,8l-19,31c-2,3 -5,5 -9,5H591c-8,0 -13,-8 -9,-15l116,-171 2,-3 53, -228c1,-3 3,-5 5,-6l72,-40c3,-1 5,-4 5,-7l10,-42c2,-9 15,-11 20,-3l3,6c2,2 2,5 1,8l-66,190v5l16,91v5l-40,88v6l22,72z" />
|
||||||
|
|
||||||
|
</vector>
|
12
app/src/main/res/drawable/ic_launcher_foreground_mono.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="1926"
|
||||||
|
android:viewportHeight="1926">
|
||||||
|
<path
|
||||||
|
android:fillColor="#fff"
|
||||||
|
android:pathData="M1082,1260v4l-6,73c0,5 -5,9 -10,9H879c-4,0 -8,-2 -10,-5l-31,-58 -29,-71v-8l48,-94c2,-3 2,-5 1, -8l-24,-65c-1,-2 0,-5 1,-7l39,-84c4,-8 17,-8 20,1l12,38 38,101c1,2 3,5 6,6l80,27c3,1 6,3 7,6l45,135zM852,717c0,-23 15,-43 35,-52l-2,-8c0,-11 13,-20 29,-20h1a38,38 0,0 1,36 -18l3,-2c11,-16 37,-27 68,-27 12,0 23,2 32,4 3,-3 8,-6 14,-6s12,3 14,8c8,-9 22,-16 38,-16 25,0 45,16 45,36l-1,7 3,4c16,6 27,17 27,30 0,14 -15,27 -34,32 -2,0 -3,1 -3,3 0,11 -11,21 -26,22v1c0,22 -41,40 -92,40 -11,0 -21,-1 -31,-3v1c0,9 -12,16 -26,16h-2l2,7c0,14 -18,25 -40,25h-7l-4, 2c-2,7 -8,12 -15,12 -9,0 -16,-7 -16,-16 0,-5 1,-8 4,-11l1,-4c-2,-3 -2,-5 -2,-8 0,-2 -2,-3 -3,-3 -27,-6 -48,-29 -48,-56z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#fff"
|
||||||
|
android:pathData="M1336,1346h-125c-3,0 -6,-1 -8,-4l-84,-118 -1,-2 -42,-122 -5,-5 -102,-52 -5,-6 -15,-75 -2,-3 -34,-51c-2,-3 -2,-6 -1,-9l21,-45c2,-4 5,-6 9,-6l39,-2c3,0 5,-1 6,-3l29,-22c5,-4 14,-2 17,4l98,201 1,2 13,81 2,5 197,216c6,6 1,16 -8,16zM801,1302c1,3 1,6 -1,8l-19,31c-2,3 -5,5 -9,5H591c-8,0 -13,-8 -9,-15l116,-171 2,-3 53, -228c1,-3 3,-5 5,-6l72,-40c3,-1 5,-4 5,-7l10,-42c2,-9 15,-11 20,-3l3,6c2,2 2,5 1,8l-66,190v5l16,91v5l-40,88v6l22,72z" />
|
||||||
|
</vector>
|
69
app/src/main/res/layout/fragment_notifications.xml
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.modules.notifications.NotificationsFragment">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/notifications_header_icon"
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:src="@drawable/ic_settings_notifications"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/notifications_header_title"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.4"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/notifications_header_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:layout_marginVertical="16dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:text="@string/notifications_header_title"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="24sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/notifications_header_description"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/notifications_header_icon"
|
||||||
|
app:lineHeight="30sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/notifications_header_description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:text="@string/notifications_header_description"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/notifications_skip"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/notifications_header_title"
|
||||||
|
app:lineHeight="24sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/notifications_skip"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:text="@string/notifications_skip"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/notifications_enable"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:text="@string/notifications_enable"
|
||||||
|
app:icon="@drawable/ic_settings_notifications"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -2,4 +2,5 @@
|
|||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/colorPrimary" />
|
<background android:drawable="@color/colorPrimary" />
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_foreground_mono" />
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/colorPrimary" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 12 KiB |
@ -74,6 +74,11 @@
|
|||||||
<string name="login_recover">Recover</string>
|
<string name="login_recover">Recover</string>
|
||||||
<string name="login_signed_in">Student is already signed in</string>
|
<string name="login_signed_in">Student is already signed in</string>
|
||||||
<string name="login_host_standard">Standard</string>
|
<string name="login_host_standard">Standard</string>
|
||||||
|
<!--Notifications-->
|
||||||
|
<string name="notifications_header_title">Enable notifications</string>
|
||||||
|
<string name="notifications_header_description">Enable notifications so you don\'t miss message from teacher or new grade</string>
|
||||||
|
<string name="notifications_skip">Skip</string>
|
||||||
|
<string name="notifications_enable">Enable</string>
|
||||||
<!--Main-->
|
<!--Main-->
|
||||||
<string name="main_account_picker">Account manager</string>
|
<string name="main_account_picker">Account manager</string>
|
||||||
<string name="main_log_in">Log in</string>
|
<string name="main_log_in">Log in</string>
|
||||||
|
17
app/src/main/res/xml/data_extraction_rules.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<data-extraction-rules>
|
||||||
|
<cloud-backup>
|
||||||
|
<exclude domain="file" />
|
||||||
|
<exclude domain="database" />
|
||||||
|
<exclude domain="sharedpref" />
|
||||||
|
<exclude domain="external" />
|
||||||
|
<exclude domain="root" />
|
||||||
|
</cloud-backup>
|
||||||
|
<device-transfer>
|
||||||
|
<exclude domain="file" />
|
||||||
|
<exclude domain="database" />
|
||||||
|
<exclude domain="sharedpref" />
|
||||||
|
<exclude domain="external" />
|
||||||
|
<exclude domain="root" />
|
||||||
|
</device-transfer>
|
||||||
|
</data-extraction-rules>
|
@ -90,14 +90,14 @@ class LoginStudentSelectPresenterTest {
|
|||||||
studentRepository.saveStudents(listOf(StudentWithSemesters(testStudent, emptyList())))
|
studentRepository.saveStudents(listOf(StudentWithSemesters(testStudent, emptyList())))
|
||||||
} just Runs
|
} just Runs
|
||||||
|
|
||||||
every { loginStudentSelectView.openMainView() } just Runs
|
every { loginStudentSelectView.navigateToNext() } just Runs
|
||||||
|
|
||||||
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
|
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
|
||||||
presenter.onSignIn()
|
presenter.onSignIn()
|
||||||
|
|
||||||
verify { loginStudentSelectView.showContent(false) }
|
verify { loginStudentSelectView.showContent(false) }
|
||||||
verify { loginStudentSelectView.showProgress(true) }
|
verify { loginStudentSelectView.showProgress(true) }
|
||||||
verify { loginStudentSelectView.openMainView() }
|
verify { loginStudentSelectView.navigateToNext() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|