Update project to Android SDK 31 (#1570)

This commit is contained in:
Rafał Borcz
2021-11-11 15:23:20 +01:00
committed by GitHub
parent f88d44f0ec
commit 007d62e61d
76 changed files with 316 additions and 384 deletions

View File

@ -22,11 +22,14 @@ class SharedPrefProvider @Inject constructor(
fun getString(key: String) = sharedPref.getString(key, null)
fun getString(key: String, defaultValue: String): String = sharedPref.getString(key, defaultValue) ?: defaultValue
fun getString(key: String, defaultValue: String): String =
sharedPref.getString(key, defaultValue) ?: defaultValue
fun getBoolean(key: String, defaultValue: Boolean): Boolean = sharedPref.getBoolean(key, defaultValue)
fun getBoolean(key: String, defaultValue: Boolean): Boolean =
sharedPref.getBoolean(key, defaultValue)
fun putBoolean(key: String, value: Boolean, sync: Boolean = false) = sharedPref.edit(sync) { putBoolean(key, value) }
fun putBoolean(key: String, value: Boolean, sync: Boolean = false) =
sharedPref.edit(sync) { putBoolean(key, value) }
fun putString(key: String, value: String?, sync: Boolean = false) {
sharedPref.edit(sync) { putString(key, value) }

View File

@ -1,7 +1,6 @@
package io.github.wulkanowy.services.alarm
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context
import android.content.Intent
import android.os.Build
@ -16,7 +15,8 @@ import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.services.HiltBroadcastReceiver
import io.github.wulkanowy.services.sync.channels.UpcomingLessonsChannel.Companion.CHANNEL_ID
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.PendingIntentCompat
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.getCompatColor
import io.github.wulkanowy.utils.toLocalDateTime
@ -138,8 +138,8 @@ class TimetableNotificationReceiver : HiltBroadcastReceiver() {
PendingIntent.getActivity(
context,
NOTIFICATION_ID,
MainActivity.getStartIntent(context, Destination.Timetable(), true),
FLAG_UPDATE_CURRENT
SplashActivity.getStartIntent(context, Destination.Timetable(), true),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
)
.build()

View File

@ -3,7 +3,6 @@ package io.github.wulkanowy.services.alarm
import android.app.AlarmManager
import android.app.AlarmManager.RTC_WAKEUP
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context
import android.content.Intent
import androidx.core.app.AlarmManagerCompat
@ -26,6 +25,7 @@ import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companio
import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.STUDENT_ID
import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.STUDENT_NAME
import io.github.wulkanowy.utils.DispatchersProvider
import io.github.wulkanowy.utils.PendingIntentCompat
import io.github.wulkanowy.utils.nickOrName
import io.github.wulkanowy.utils.toTimestamp
import kotlinx.coroutines.withContext
@ -72,8 +72,14 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
private fun cancelScheduledTo(range: ClosedRange<LocalDateTime>, requestCode: Int) {
if (now() in range) cancelNotification()
alarmManager.cancel(
PendingIntent.getBroadcast(context, requestCode, Intent(), FLAG_UPDATE_CURRENT)
PendingIntent.getBroadcast(
context,
requestCode,
Intent(),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
)
}
@ -156,7 +162,7 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
alarmManager, RTC_WAKEUP, time.toTimestamp(),
PendingIntent.getBroadcast(context, getRequestCode(time, studentId), intent.also {
it.putExtra(LESSON_TYPE, notificationType)
}, FLAG_UPDATE_CURRENT)
}, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE)
)
Timber.d(
"TimetableNotification scheduled: type: $notificationType, subject: ${

View File

@ -8,7 +8,7 @@ import androidx.core.graphics.drawable.IconCompat
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.R
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import javax.inject.Inject
import javax.inject.Singleton
@ -35,7 +35,7 @@ class ShortcutsHelper @Inject constructor(@ApplicationContext private val contex
.setShortLabel(context.getString(R.string.grade_title))
.setLongLabel(context.getString(R.string.grade_title))
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_grade))
.setIntent(MainActivity.getStartIntent(context, startNewTask = true)
.setIntent(SplashActivity.getStartIntent(context, startNewTask = true)
.apply {
action = Intent.ACTION_VIEW
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "grade")
@ -47,7 +47,7 @@ class ShortcutsHelper @Inject constructor(@ApplicationContext private val contex
.setShortLabel(context.getString(R.string.attendance_title))
.setLongLabel(context.getString(R.string.attendance_title))
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_attendance))
.setIntent(MainActivity.getStartIntent(context, startNewTask = true)
.setIntent(SplashActivity.getStartIntent(context, startNewTask = true)
.apply {
action = Intent.ACTION_VIEW
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "attendance")
@ -59,7 +59,7 @@ class ShortcutsHelper @Inject constructor(@ApplicationContext private val contex
.setShortLabel(context.getString(R.string.exam_title))
.setLongLabel(context.getString(R.string.exam_title))
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_exam))
.setIntent(MainActivity.getStartIntent(context, startNewTask = true)
.setIntent(SplashActivity.getStartIntent(context, startNewTask = true)
.apply {
action = Intent.ACTION_VIEW
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "exam")
@ -71,7 +71,7 @@ class ShortcutsHelper @Inject constructor(@ApplicationContext private val contex
.setShortLabel(context.getString(R.string.timetable_title))
.setLongLabel(context.getString(R.string.timetable_title))
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_timetable))
.setIntent(MainActivity.getStartIntent(context, startNewTask = true)
.setIntent(SplashActivity.getStartIntent(context, startNewTask = true)
.apply {
action = Intent.ACTION_VIEW
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "timetable")

View File

@ -13,6 +13,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.data.repositories.NotificationRepository
import io.github.wulkanowy.utils.PendingIntentCompat
import io.github.wulkanowy.utils.getCompatBitmap
import io.github.wulkanowy.utils.getCompatColor
import io.github.wulkanowy.utils.nickOrName
@ -45,7 +46,7 @@ class AppNotificationManager @Inject constructor(
context,
Random.nextInt(),
notificationData.intentToStart,
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
)
.setContentTitle(notificationData.title)
@ -86,7 +87,7 @@ class AppNotificationManager @Inject constructor(
context,
Random.nextInt(),
notificationData.intentToStart,
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
)
.setContentTitle(notificationData.title)
@ -134,7 +135,7 @@ class AppNotificationManager @Inject constructor(
context,
Random.nextInt(),
groupNotificationData.intentToStart,
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
)
.setLocalOnly(true)

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.getPlural
import io.github.wulkanowy.utils.toFormattedString
import java.time.LocalDate
@ -32,7 +32,7 @@ class ChangeTimetableNotification @Inject constructor(
1
),
content = it,
intentToStart = MainActivity.getStartIntent(
intentToStart = SplashActivity.getStartIntent(
context = context,
destination = Destination.Timetable(date),
startNewTask = true
@ -54,7 +54,7 @@ class ChangeTimetableNotification @Inject constructor(
changedLessons.size,
changedLessons.size
),
intentToStart = MainActivity.getStartIntent(context, Destination.Timetable(), true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Timetable(), true),
type = NotificationType.CHANGE_TIMETABLE
)

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.descriptionRes
import io.github.wulkanowy.utils.getPlural
import io.github.wulkanowy.utils.toFormattedString
@ -31,7 +31,7 @@ class NewAttendanceNotification @Inject constructor(
NotificationData(
title = context.getPlural(R.plurals.attendance_notify_new_items_title, 1),
content = it,
intentToStart = MainActivity.getStartIntent(context, Destination.Attendance, true)
intentToStart = SplashActivity.getStartIntent(context, Destination.Attendance, true)
)
}
@ -46,7 +46,7 @@ class NewAttendanceNotification @Inject constructor(
notificationDataList.size,
notificationDataList.size
),
intentToStart = MainActivity.getStartIntent(context, Destination.Attendance, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Attendance, true),
type = NotificationType.NEW_ATTENDANCE
)

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.getPlural
import io.github.wulkanowy.utils.toFormattedString
import java.time.LocalDateTime
@ -31,7 +31,7 @@ class NewConferenceNotification @Inject constructor(
NotificationData(
title = context.getPlural(R.plurals.conference_notify_new_item_title, 1),
content = it,
intentToStart = MainActivity.getStartIntent(context, Destination.Conference, true)
intentToStart = SplashActivity.getStartIntent(context, Destination.Conference, true)
)
}
@ -43,7 +43,7 @@ class NewConferenceNotification @Inject constructor(
lines.size,
lines.size
),
intentToStart = MainActivity.getStartIntent(context, Destination.Conference, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Conference, true),
type = NotificationType.NEW_CONFERENCE
)

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.getPlural
import io.github.wulkanowy.utils.toFormattedString
import java.time.LocalDate
@ -31,7 +31,7 @@ class NewExamNotification @Inject constructor(
NotificationData(
title = context.getPlural(R.plurals.exam_notify_new_item_title, 1),
content = it,
intentToStart = MainActivity.getStartIntent(context, Destination.Exam, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Exam, true),
)
}
@ -43,7 +43,7 @@ class NewExamNotification @Inject constructor(
lines.size,
lines.size
),
intentToStart = MainActivity.getStartIntent(context, Destination.Exam, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Exam, true),
type = NotificationType.NEW_EXAM
)

View File

@ -9,7 +9,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.getPlural
import javax.inject.Inject
@ -23,7 +23,7 @@ class NewGradeNotification @Inject constructor(
NotificationData(
title = context.getPlural(R.plurals.grade_new_items, 1),
content = "${it.subject}: ${it.entry}",
intentToStart = MainActivity.getStartIntent(context, Destination.Grade, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Grade, true),
)
}
@ -31,7 +31,7 @@ class NewGradeNotification @Inject constructor(
notificationDataList = notificationDataList,
title = context.getPlural(R.plurals.grade_new_items, items.size),
content = context.getPlural(R.plurals.grade_notify_new_items, items.size, items.size),
intentToStart = MainActivity.getStartIntent(context, Destination.Grade, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Grade, true),
type = NotificationType.NEW_GRADE_DETAILS
)
@ -43,7 +43,7 @@ class NewGradeNotification @Inject constructor(
NotificationData(
title = context.getPlural(R.plurals.grade_new_items_predicted, 1),
content = "${it.subject}: ${it.predictedGrade}",
intentToStart = MainActivity.getStartIntent(context, Destination.Grade, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Grade, true),
)
}
@ -55,7 +55,7 @@ class NewGradeNotification @Inject constructor(
items.size,
items.size
),
intentToStart = MainActivity.getStartIntent(context, Destination.Grade, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Grade, true),
type = NotificationType.NEW_GRADE_PREDICTED
)
@ -67,7 +67,7 @@ class NewGradeNotification @Inject constructor(
NotificationData(
title = context.getPlural(R.plurals.grade_new_items_final, 1),
content = "${it.subject}: ${it.finalGrade}",
intentToStart = MainActivity.getStartIntent(context, Destination.Grade, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Grade, true),
)
}
@ -79,7 +79,7 @@ class NewGradeNotification @Inject constructor(
items.size,
items.size
),
intentToStart = MainActivity.getStartIntent(context, Destination.Grade, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Grade, true),
type = NotificationType.NEW_GRADE_FINAL
)

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.getPlural
import io.github.wulkanowy.utils.toFormattedString
import java.time.LocalDate
@ -31,7 +31,7 @@ class NewHomeworkNotification @Inject constructor(
NotificationData(
title = context.getPlural(R.plurals.homework_notify_new_item_title, 1),
content = it,
intentToStart = MainActivity.getStartIntent(context, Destination.Homework, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Homework, true),
)
}
@ -42,7 +42,7 @@ class NewHomeworkNotification @Inject constructor(
lines.size,
lines.size
),
intentToStart = MainActivity.getStartIntent(context, Destination.Homework, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Homework, true),
type = NotificationType.NEW_HOMEWORK,
notificationDataList = notificationDataList
)

View File

@ -7,7 +7,7 @@ import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import javax.inject.Inject
class NewLuckyNumberNotification @Inject constructor(
@ -22,7 +22,7 @@ class NewLuckyNumberNotification @Inject constructor(
R.string.lucky_number_notify_new_item,
item.luckyNumber.toString()
),
intentToStart = MainActivity.getStartIntent(context, Destination.LuckyNumber, true)
intentToStart = SplashActivity.getStartIntent(context, Destination.LuckyNumber, true)
)
appNotificationManager.sendSingleNotification(

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.getPlural
import javax.inject.Inject
@ -22,7 +22,7 @@ class NewMessageNotification @Inject constructor(
NotificationData(
title = context.getPlural(R.plurals.message_new_items, 1),
content = "${it.sender}: ${it.subject}",
intentToStart = MainActivity.getStartIntent(context, Destination.Message, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Message, true),
)
}
@ -30,7 +30,7 @@ class NewMessageNotification @Inject constructor(
notificationDataList = notificationDataList,
title = context.getPlural(R.plurals.message_new_items, items.size),
content = context.getPlural(R.plurals.message_notify_new_items, items.size, items.size),
intentToStart = MainActivity.getStartIntent(context, Destination.Message, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Message, true),
type = NotificationType.NEW_MESSAGE
)

View File

@ -9,7 +9,7 @@ import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.getPlural
import javax.inject.Inject
@ -29,13 +29,13 @@ class NewNoteNotification @Inject constructor(
NotificationData(
title = context.getPlural(titleRes, 1),
content = "${it.teacher}: ${it.category}",
intentToStart = MainActivity.getStartIntent(context, Destination.Note, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Note, true),
)
}
val groupNotificationData = GroupNotificationData(
notificationDataList = notificationDataList,
intentToStart = MainActivity.getStartIntent(context, Destination.Note, true),
intentToStart = SplashActivity.getStartIntent(context, Destination.Note, true),
title = context.getPlural(R.plurals.note_new_items, items.size),
content = context.getPlural(R.plurals.note_notify_new_items, items.size, items.size),
type = NotificationType.NEW_NOTE

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.GroupNotificationData
import io.github.wulkanowy.data.pojos.NotificationData
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.getPlural
import javax.inject.Inject
@ -20,7 +20,7 @@ class NewSchoolAnnouncementNotification @Inject constructor(
suspend fun notify(items: List<SchoolAnnouncement>, student: Student) {
val notificationDataList = items.map {
NotificationData(
intentToStart = MainActivity.getStartIntent(
intentToStart = SplashActivity.getStartIntent(
context = context,
destination = Destination.SchoolAnnouncement,
startNewTask = true
@ -34,7 +34,7 @@ class NewSchoolAnnouncementNotification @Inject constructor(
}
val groupNotificationData = GroupNotificationData(
type = NotificationType.NEW_ANNOUNCEMENT,
intentToStart = MainActivity.getStartIntent(
intentToStart = SplashActivity.getStartIntent(
context = context,
destination = Destination.SchoolAnnouncement,
startNewTask = true

View File

@ -1,14 +1,11 @@
package io.github.wulkanowy.ui.base
import android.app.ActivityManager
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.viewbinding.ViewBinding
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
@ -40,7 +37,6 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>, VB : ViewBinding> :
themeManager.applyActivityTheme(this)
super.onCreate(savedInstanceState)
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleLogger, true)
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
@Suppress("DEPRECATION")
setTaskDescription(
@ -83,8 +79,8 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>, VB : ViewBinding> :
}
override fun openClearLoginView() {
startActivity(LoginActivity.getStartIntent(this)
.apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) })
startActivity(LoginActivity.getStartIntent(this))
finishAffinity()
}
override fun onDestroy() {

View File

@ -20,7 +20,7 @@ open class BasePresenter<T : BaseView>(
) {
private val job = SupervisorJob()
protected val presenterScope = CoroutineScope(job + Dispatchers.Main)
protected val presenterScope = CoroutineScope(job + Dispatchers.Main.immediate)
private val childrenJobs = mutableMapOf<String, Job>()

View File

@ -41,14 +41,15 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer
)
}
private fun isThemeApplicable(activity: AppCompatActivity): Boolean {
return activity.packageManager
private fun isThemeApplicable(activity: AppCompatActivity) =
activity.packageManager
.getPackageInfo(activity.packageName, GET_ACTIVITIES)
.activities.singleOrNull { it.name == activity::class.java.canonicalName }
?.theme.let {
.activities
.singleOrNull { it.name == activity::class.java.canonicalName }
?.theme
.let {
it == R.style.WulkanowyTheme_Black || it == R.style.WulkanowyTheme_NoActionBar
|| it == R.style.WulkanowyTheme_Login || it == R.style.WulkanowyTheme_Login_Black
|| it == R.style.WulkanowyTheme_MessageSend || it == R.style.WulkanowyTheme_MessageSend_Black
}
}
}

View File

@ -19,6 +19,10 @@ import java.time.LocalDate
sealed interface Destination : Serializable {
/*
Type in children classes have to be as getter to avoid null in enums
https://stackoverflow.com/questions/68866453/kotlin-enum-val-is-returning-null-despite-being-set-at-compile-time
*/
val type: Type
val fragment: Fragment
@ -41,91 +45,91 @@ sealed interface Destination : Serializable {
object Dashboard : Destination {
override val type = Type.DASHBOARD
override val type get() = Type.DASHBOARD
override val fragment get() = DashboardFragment.newInstance()
}
object Grade : Destination {
override val type = Type.GRADE
override val type get() = Type.GRADE
override val fragment get() = GradeFragment.newInstance()
}
object Attendance : Destination {
override val type = Type.ATTENDANCE
override val type get() = Type.ATTENDANCE
override val fragment get() = AttendanceFragment.newInstance()
}
object Exam : Destination {
override val type = Type.EXAM
override val type get() = Type.EXAM
override val fragment get() = ExamFragment.newInstance()
}
data class Timetable(val date: LocalDate? = null) : Destination {
override val type = Type.TIMETABLE
override val type get() = Type.TIMETABLE
override val fragment get() = TimetableFragment.newInstance(date)
}
object Homework : Destination {
override val type = Type.HOMEWORK
override val type get() = Type.HOMEWORK
override val fragment get() = HomeworkFragment.newInstance()
}
object Note : Destination {
override val type = Type.NOTE
override val type get() = Type.NOTE
override val fragment get() = NoteFragment.newInstance()
}
object Conference : Destination {
override val type = Type.CONFERENCE
override val type get() = Type.CONFERENCE
override val fragment get() = ConferenceFragment.newInstance()
}
object SchoolAnnouncement : Destination {
override val type = Type.SCHOOL_ANNOUNCEMENT
override val type get() = Type.SCHOOL_ANNOUNCEMENT
override val fragment get() = SchoolAnnouncementFragment.newInstance()
}
object School : Destination {
override val type = Type.SCHOOL
override val type get() = Type.SCHOOL
override val fragment get() = SchoolFragment.newInstance()
}
object LuckyNumber : Destination {
override val type = Type.LUCKY_NUMBER
override val type get() = Type.LUCKY_NUMBER
override val fragment get() = LuckyNumberFragment.newInstance()
}
object More : Destination {
override val type = Type.MORE
override val type get() = Type.MORE
override val fragment get() = MoreFragment.newInstance()
}
object Message : Destination {
override val type = Type.MESSAGE
override val type get() = Type.MESSAGE
override val fragment get() = MessageFragment.newInstance()
}

View File

@ -3,12 +3,9 @@ package io.github.wulkanowy.ui.modules.account.accountedit
import android.annotation.SuppressLint
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.RippleDrawable
import android.graphics.drawable.StateListDrawable
import android.os.Build
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.view.isVisible
@ -52,30 +49,13 @@ class AccountEditColorAdapter @Inject constructor() :
}
}
private fun Int.createForegroundDrawable(): Drawable =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val mask = GradientDrawable().apply {
shape = GradientDrawable.OVAL
setColor(Color.BLACK)
}
RippleDrawable(ColorStateList.valueOf(this.rippleColor), null, mask)
} else {
val foreground = StateListDrawable().apply {
alpha = 80
setEnterFadeDuration(250)
setExitFadeDuration(250)
}
val mask = GradientDrawable().apply {
shape = GradientDrawable.OVAL
setColor(this@createForegroundDrawable.rippleColor)
}
foreground.apply {
addState(intArrayOf(android.R.attr.state_pressed), mask)
addState(intArrayOf(), ColorDrawable(Color.TRANSPARENT))
}
private fun Int.createForegroundDrawable(): Drawable {
val mask = GradientDrawable().apply {
shape = GradientDrawable.OVAL
setColor(Color.BLACK)
}
return RippleDrawable(ColorStateList.valueOf(this.rippleColor), null, mask)
}
private inline val Int.rippleColor: Int
get() {

View File

@ -121,9 +121,7 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
attendanceSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary))
attendanceSwipe.setProgressBackgroundColorSchemeColor(
requireContext().getThemeAttrColor(
R.attr.colorSwipeRefresh
)
requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh)
)
attendanceErrorRetry.setOnClickListener { presenter.onRetry() }
attendanceErrorDetails.setOnClickListener { presenter.onDetailsClick() }
@ -134,7 +132,7 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
attendanceExcuseButton.setOnClickListener { presenter.onExcuseButtonClick() }
attendanceNavContainer.setElevationCompat(requireContext().dpToPx(8f))
attendanceNavContainer.elevation = requireContext().dpToPx(8f)
}
}

View File

@ -71,7 +71,7 @@ class AttendanceSummaryFragment :
setOnItemSelectedListener<TextView> { presenter.onSubjectSelected(it?.text?.toString()) }
}
binding.attendanceSummarySubjectsContainer.setElevationCompat(requireContext().dpToPx(1f))
binding.attendanceSummarySubjectsContainer.elevation = requireContext().dpToPx(1f)
}
override fun updateSubjects(data: ArrayList<String>) {

View File

@ -64,7 +64,7 @@ class ExamFragment : BaseFragment<FragmentExamBinding>(R.layout.fragment_exam),
examPreviousButton.setOnClickListener { presenter.onPreviousWeek() }
examNextButton.setOnClickListener { presenter.onNextWeek() }
examNavContainer.setElevationCompat(requireContext().dpToPx(8f))
examNavContainer.elevation = requireContext().dpToPx(8f)
}
}

View File

@ -96,9 +96,7 @@ class GradeFragment : BaseFragment<FragmentGradeBinding>(R.layout.fragment_grade
TabLayoutMediator(binding.gradeTabLayout, binding.gradeViewPager, this).attach()
}
with(binding.gradeTabLayout) {
setElevationCompat(context.dpToPx(4f))
}
binding.gradeTabLayout.elevation = requireContext().dpToPx(4f)
with(binding) {
gradeErrorRetry.setOnClickListener { presenter.onRetry() }

View File

@ -68,7 +68,7 @@ class GradeStatisticsFragment :
}
with(binding) {
gradeStatisticsSubjectsContainer.setElevationCompat(requireContext().dpToPx(1f))
gradeStatisticsSubjectsContainer.elevation = requireContext().dpToPx(1f)
gradeStatisticsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
gradeStatisticsSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary))

View File

@ -67,7 +67,7 @@ class HomeworkFragment : BaseFragment<FragmentHomeworkBinding>(R.layout.fragment
openAddHomeworkButton.setOnClickListener { presenter.onHomeworkAddButtonClicked() }
homeworkNavContainer.setElevationCompat(requireContext().dpToPx(8f))
homeworkNavContainer.elevation = requireContext().dpToPx(8f)
}
}

View File

@ -35,13 +35,13 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
@Inject
lateinit var updateHelper: UpdateHelper
override val currentViewIndex get() = binding.loginViewpager.currentItem
companion object {
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
}
override val currentViewIndex get() = binding.loginViewpager.currentItem
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityLoginBinding.inflate(layoutInflater).apply { binding = this }.root)

View File

@ -66,14 +66,8 @@ class LoginStudentSelectFragment :
}
override fun openMainView() {
activity?.let {
startActivity(
MainActivity.getStartIntent(
context = it,
startNewTask = true
)
)
}
startActivity(MainActivity.getStartIntent(requireContext()))
requireActivity().finish()
}
override fun showProgress(show: Boolean) {
@ -115,7 +109,8 @@ class LoginStudentSelectFragment :
chooserTitle = requireContext().getString(R.string.login_email_intent_title),
email = "wulkanowyinc@gmail.com",
subject = requireContext().getString(R.string.login_email_subject),
body = requireContext().getString(R.string.login_email_text, appInfo.systemModel,
body = requireContext().getString(
R.string.login_email_text, appInfo.systemModel,
appInfo.systemVersion.toString(),
appInfo.versionName,
"Select users to log in",

View File

@ -65,7 +65,7 @@ class LuckyNumberHistoryFragment :
luckyNumberHistoryPreviousButton.setOnClickListener { presenter.onPreviousWeek() }
luckyNumberHistoryNextButton.setOnClickListener { presenter.onNextWeek() }
luckyNumberHistoryNavContainer.setElevationCompat(requireContext().dpToPx(8f))
luckyNumberHistoryNavContainer.elevation = requireContext().dpToPx(8f)
}
}

View File

@ -1,7 +1,6 @@
package io.github.wulkanowy.ui.modules.luckynumberwidget
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT
import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH
@ -19,7 +18,8 @@ import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
import io.github.wulkanowy.data.repositories.LuckyNumberRepository
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.PendingIntentCompat
import io.github.wulkanowy.utils.toFirstResult
import kotlinx.coroutines.runBlocking
import timber.log.Timber
@ -62,8 +62,8 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() {
val appIntent = PendingIntent.getActivity(
context,
LUCKY_NUMBER_PENDING_INTENT_ID,
MainActivity.getStartIntent(context, Destination.LuckyNumber, true),
FLAG_UPDATE_CURRENT
SplashActivity.getStartIntent(context, Destination.LuckyNumber, true),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
val remoteView =

View File

@ -3,8 +3,6 @@ package io.github.wulkanowy.ui.modules.main
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Build.VERSION_CODES.P
import android.os.Bundle
import android.view.Menu
@ -23,7 +21,6 @@ import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.databinding.ActivityMainBinding
import io.github.wulkanowy.services.shortcuts.ShortcutsHelper
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.account.accountquick.AccountQuickDialog
@ -59,9 +56,6 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
@Inject
lateinit var appInfo: AppInfo
@Inject
lateinit var shortcutsHelper: ShortcutsHelper
private var accountMenu: MenuItem? = null
private val overlayProvider by lazy { ElevationOverlayProvider(this) }
@ -76,13 +70,8 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
fun getStartIntent(
context: Context,
destination: Destination? = null,
startNewTask: Boolean = false
) = Intent(context, MainActivity::class.java).apply {
putExtra(EXTRA_START_DESTINATION, destination)
if (startNewTask) {
flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
}
}
}
@ -109,7 +98,6 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
updateHelper.messageContainer = binding.mainFragmentContainer
val destination = intent.getSerializableExtra(EXTRA_START_DESTINATION) as Destination?
?: shortcutsHelper.getDestination(intent)
presenter.onAttachView(this, destination)
updateHelper.checkAndInstallUpdates(this)

View File

@ -77,9 +77,8 @@ class MessageFragment : BaseFragment<FragmentMessageBinding>(R.layout.fragment_m
TabLayoutMediator(binding.messageTabLayout, binding.messageViewPager, this).attach()
}
with(binding.messageTabLayout) {
setElevationCompat(context.dpToPx(4f))
}
binding.messageTabLayout.elevation = requireContext().dpToPx(4f)
binding.openSendMessageButton.setOnClickListener { presenter.onSendMessageButtonClicked() }
}

View File

@ -1,6 +1,5 @@
package io.github.wulkanowy.ui.modules.message.preview
import android.os.Build
import android.os.Bundle
import android.print.PrintAttributes
import android.print.PrintManager
@ -13,7 +12,6 @@ import android.view.View.VISIBLE
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
@ -25,7 +23,6 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.shareText
import javax.inject.Inject
@ -40,9 +37,6 @@ class MessagePreviewFragment :
@Inject
lateinit var previewAdapter: MessagePreviewAdapter
@Inject
lateinit var appInfo: AppInfo
private var menuReplyButton: MenuItem? = null
private var menuForwardButton: MenuItem? = null
@ -140,7 +134,7 @@ class MessagePreviewFragment :
menuForwardButton?.isVisible = show
menuDeleteButton?.isVisible = show
menuShareButton?.isVisible = show
menuPrintButton?.isVisible = show && appInfo.systemVersion >= Build.VERSION_CODES.LOLLIPOP
menuPrintButton?.isVisible = show
}
override fun setDeletedOptionsLabels() {
@ -175,7 +169,6 @@ class MessagePreviewFragment :
context?.shareText(text, subject)
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun printDocument(html: String, jobName: String) {
val webView = WebView(requireContext())
webView.webViewClient = object : WebViewClient() {
@ -190,7 +183,6 @@ class MessagePreviewFragment :
webView.loadDataWithBaseURL("file:///android_asset/", html, "text/HTML", "UTF-8", null)
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private fun createWebPrintJob(webView: WebView, jobName: String) {
activity?.getSystemService<PrintManager>()?.let { printManager ->
val printAdapter = webView.createPrintDocumentAdapter(jobName)

View File

@ -1,7 +1,6 @@
package io.github.wulkanowy.ui.modules.message.preview
import android.annotation.SuppressLint
import android.os.Build
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageAttachment
@ -11,7 +10,6 @@ import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn
@ -24,8 +22,7 @@ class MessagePreviewPresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val messageRepository: MessageRepository,
private val analytics: AnalyticsHelper,
private var appInfo: AppInfo
private val analytics: AnalyticsHelper
) : BasePresenter<MessagePreviewView>(errorHandler, studentRepository) {
var message: Message? = null
@ -112,10 +109,11 @@ class MessagePreviewPresenter @Inject constructor(
fun onShare(): Boolean {
message?.let {
var text = "Temat: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}\n" + when (it.sender.isNotEmpty()) {
true -> "Od: ${it.sender}\n"
false -> "Do: ${it.recipient}\n"
} + "Data: ${it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}\n\n${it.content}"
var text =
"Temat: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}\n" + when (it.sender.isNotEmpty()) {
true -> "Od: ${it.sender}\n"
false -> "Do: ${it.recipient}\n"
} + "Data: ${it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}\n\n${it.content}"
attachments?.let { attachments ->
if (attachments.isNotEmpty()) {
@ -127,7 +125,10 @@ class MessagePreviewPresenter @Inject constructor(
}
}
view?.shareText(text, "FW: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}")
view?.shareText(
text,
"FW: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}"
)
return true
}
return false
@ -135,7 +136,6 @@ class MessagePreviewPresenter @Inject constructor(
@SuppressLint("NewApi")
fun onPrint(): Boolean {
if (appInfo.systemVersion < Build.VERSION_CODES.LOLLIPOP) return false
message?.let {
val dateString = it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")
val infoContent = "<div><h4>Data wysłania</h4>$dateString</div>" + when {
@ -154,7 +154,9 @@ class MessagePreviewPresenter @Inject constructor(
view?.apply {
val html = printHTML
.replace("%SUBJECT%", it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() })
.replace(
"%SUBJECT%",
it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() })
.replace("%CONTENT%", messageContent)
.replace("%INFO%", infoContent)
printDocument(html, jobName)

View File

@ -1,7 +1,5 @@
package io.github.wulkanowy.ui.modules.message.preview
import android.os.Build
import androidx.annotation.RequiresApi
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
import io.github.wulkanowy.ui.base.BaseView
@ -42,8 +40,7 @@ interface MessagePreviewView : BaseView {
fun shareText(text: String, subject: String)
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
fun printDocument(html: String, jobName: String)
fun popView()
fun printDocument(html: String, jobName: String)
}

View File

@ -127,10 +127,13 @@ class MessageTabPresenter @Inject constructor(
onlyUnread,
onlyWithAttachments
)
val newItems = listOf(MessageTabDataItem.Header) + filteredData.map {
MessageTabDataItem.MessageItem(it)
val messageItems = filteredData.map { message ->
MessageTabDataItem.MessageItem(message)
}
updateData(newItems, folder.id == MessageFolder.SENT.id)
val messageItemsWithHeader =
listOf(MessageTabDataItem.Header) + messageItems
updateData(messageItemsWithHeader, folder.id == MessageFolder.SENT.id)
notifyParentDataLoaded()
}
}

View File

@ -77,9 +77,7 @@ class SchoolAndTeachersFragment :
).attach()
}
with(binding.schoolandteachersTabLayout) {
setElevationCompat(context.dpToPx(4f))
}
binding.schoolandteachersTabLayout.elevation = requireContext().dpToPx(4f)
}
override fun showContent(show: Boolean) {

View File

@ -1,6 +1,5 @@
package io.github.wulkanowy.ui.modules.settings.notifications
import android.annotation.SuppressLint
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
@ -152,7 +151,6 @@ class NotificationsFragment : PreferenceFragmentCompat(),
.show()
}
@SuppressLint("InlinedApi")
override fun openSystemSettings() {
val intent = if (appInfo.systemVersion >= Build.VERSION_CODES.O) {
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {

View File

@ -1,29 +1,60 @@
package io.github.wulkanowy.ui.modules.splash
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.viewbinding.ViewBinding
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.services.shortcuts.ShortcutsHelper
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.modules.Destination
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.openInternetBrowser
import javax.inject.Inject
@SuppressLint("CustomSplashScreen")
@AndroidEntryPoint
class SplashActivity : BaseActivity<SplashPresenter, ViewBinding>(), SplashView {
@Inject
lateinit var appInfo: AppInfo
override lateinit var presenter: SplashPresenter
@Inject
override lateinit var presenter: SplashPresenter
lateinit var shortcutsHelper: ShortcutsHelper
companion object {
private const val EXTRA_START_DESTINATION = "start_destination"
private const val EXTRA_EXTERNAL_URL = "external_url"
fun getStartIntent(
context: Context,
destination: Destination? = null,
startNewTask: Boolean = false
) = Intent(context, SplashActivity::class.java).apply {
putExtra(EXTRA_START_DESTINATION, destination)
if (startNewTask) {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
presenter.onAttachView(this, intent?.getStringExtra("external_url"))
installSplashScreen().setKeepVisibleCondition { true }
val externalLink = intent?.getStringExtra(EXTRA_EXTERNAL_URL)
val startDestination = intent?.getSerializableExtra(EXTRA_START_DESTINATION) as Destination?
?: shortcutsHelper.getDestination(intent)
presenter.onAttachView(this, externalLink, startDestination)
}
override fun openLoginView() {
@ -31,8 +62,8 @@ class SplashActivity : BaseActivity<SplashPresenter, ViewBinding>(), SplashView
finish()
}
override fun openMainView() {
startActivity(MainActivity.getStartIntent(this))
override fun openMainView(destination: Destination?) {
startActivity(MainActivity.getStartIntent(this, destination))
finish()
}

View File

@ -1,12 +1,10 @@
package io.github.wulkanowy.ui.modules.splash
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.flowWithResource
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import io.github.wulkanowy.ui.modules.Destination
import kotlinx.coroutines.launch
import javax.inject.Inject
class SplashPresenter @Inject constructor(
@ -14,7 +12,7 @@ class SplashPresenter @Inject constructor(
studentRepository: StudentRepository,
) : BasePresenter<SplashView>(errorHandler, studentRepository) {
fun onAttachView(view: SplashView, externalUrl: String?) {
fun onAttachView(view: SplashView, externalUrl: String?, startDestination: Destination?) {
super.onAttachView(view)
if (!externalUrl.isNullOrBlank()) {
@ -22,15 +20,16 @@ class SplashPresenter @Inject constructor(
return
}
flowWithResource { studentRepository.isCurrentStudentSet() }.onEach {
when (it.status) {
Status.LOADING -> Timber.d("Is current user set check started")
Status.SUCCESS -> {
if (it.data!!) view.openMainView()
else view.openLoginView()
presenterScope.launch {
runCatching { studentRepository.isCurrentStudentSet() }
.onFailure(errorHandler::dispatch)
.onSuccess {
if (it) {
view.openMainView(startDestination)
} else {
view.openLoginView()
}
}
Status.ERROR -> errorHandler.dispatch(it.error!!)
}
}.launch()
}
}
}

View File

@ -1,12 +1,13 @@
package io.github.wulkanowy.ui.modules.splash
import io.github.wulkanowy.ui.base.BaseView
import io.github.wulkanowy.ui.modules.Destination
interface SplashView : BaseView {
fun openLoginView()
fun openMainView()
fun openMainView(destination: Destination?)
fun openExternalUrlAndFinish(url: String)
}

View File

@ -97,7 +97,7 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
timetableNavDate.setOnClickListener { presenter.onPickDate() }
timetableNextButton.setOnClickListener { presenter.onNextDay() }
timetableNavContainer.setElevationCompat(requireContext().dpToPx(8f))
timetableNavContainer.elevation = requireContext().dpToPx(8f)
}
}

View File

@ -72,7 +72,7 @@ class AdditionalLessonsFragment :
additionalLessonsNavDate.setOnClickListener { presenter.onPickDate() }
additionalLessonsNextButton.setOnClickListener { presenter.onNextDay() }
additionalLessonsNavContainer.setElevationCompat(requireContext().dpToPx(8f))
additionalLessonsNavContainer.elevation = requireContext().dpToPx(8f)
}
}

View File

@ -79,7 +79,7 @@ class CompletedLessonsFragment :
completedLessonsNavDate.setOnClickListener { presenter.onPickDate() }
completedLessonsNextButton.setOnClickListener { presenter.onNextDay() }
completedLessonsNavContainer.setElevationCompat(requireContext().dpToPx(8f))
completedLessonsNavContainer.elevation = requireContext().dpToPx(8f)
}
}

View File

@ -2,7 +2,6 @@ package io.github.wulkanowy.ui.modules.timetablewidget
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_DELETED
import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE
@ -25,8 +24,9 @@ import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.services.HiltBroadcastReceiver
import io.github.wulkanowy.services.widgets.TimetableWidgetService
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.PendingIntentCompat
import io.github.wulkanowy.utils.capitalise
import io.github.wulkanowy.utils.createNameInitialsDrawable
import io.github.wulkanowy.utils.getCompatColor
@ -167,18 +167,20 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() {
action = appWidgetId.toString()
}
val accountIntent = PendingIntent.getActivity(
context, -Int.MAX_VALUE + appWidgetId,
context,
-Int.MAX_VALUE + appWidgetId,
Intent(context, TimetableWidgetConfigureActivity::class.java).apply {
addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK)
putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
putExtra(EXTRA_FROM_PROVIDER, true)
}, FLAG_UPDATE_CURRENT
}, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
val appIntent = PendingIntent.getActivity(
context,
TIMETABLE_PENDING_INTENT_ID,
MainActivity.getStartIntent(context, Destination.Timetable(), true),
FLAG_UPDATE_CURRENT
SplashActivity.getStartIntent(context, Destination.Timetable(), true),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
val remoteView = RemoteViews(context.packageName, layoutId).apply {
@ -222,16 +224,16 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() {
code: Int,
appWidgetId: Int,
buttonType: String
): PendingIntent {
return PendingIntent.getBroadcast(
context, code,
Intent(context, TimetableWidgetProvider::class.java).apply {
action = ACTION_APPWIDGET_UPDATE
putExtra(EXTRA_BUTTON_TYPE, buttonType)
putExtra(EXTRA_TOGGLED_WIDGET_ID, appWidgetId)
}, FLAG_UPDATE_CURRENT
)
}
) = PendingIntent.getBroadcast(
context,
code,
Intent(context, TimetableWidgetProvider::class.java).apply {
action = ACTION_APPWIDGET_UPDATE
putExtra(EXTRA_BUTTON_TYPE, buttonType)
putExtra(EXTRA_TOGGLED_WIDGET_ID, appWidgetId)
},
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
private suspend fun getStudent(studentId: Long, appWidgetId: Int) = try {
val students = studentRepository.getSavedStudents(false)

View File

@ -3,17 +3,15 @@ package io.github.wulkanowy.ui.widgets
import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import com.google.android.material.tabs.TabLayout
/**
* @see <a href="https://stackoverflow.com/a/50382854">Tabs don't fit to screen with tabmode=scrollable, Even with a Custom Tab Layout</a>
*/
class FittedScrollableTabLayout : MaterialTabLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
class FittedScrollableTabLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : TabLayout(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec)

View File

@ -1,24 +1,19 @@
package io.github.wulkanowy.ui.widgets
import android.content.Context
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.LOLLIPOP
import android.util.AttributeSet
import android.widget.LinearLayout
import androidx.core.view.ViewCompat
import com.google.android.material.elevation.ElevationOverlayProvider
import com.google.android.material.shape.MaterialShapeDrawable
class MaterialLinearLayout : LinearLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attr: AttributeSet) : super(context, attr)
constructor(context: Context, attr: AttributeSet, defStyleAttr: Int) : super(context, attr, defStyleAttr)
class MaterialLinearLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : LinearLayout(context, attrs) {
init {
val drawable = MaterialShapeDrawable.createWithElevationOverlay(context, ViewCompat.getElevation(this))
val drawable =
MaterialShapeDrawable.createWithElevationOverlay(context, ViewCompat.getElevation(this))
ViewCompat.setBackground(this, drawable)
}
@ -28,12 +23,4 @@ class MaterialLinearLayout : LinearLayout {
(background as MaterialShapeDrawable).elevation = elevation
}
}
fun setElevationCompat(elevation: Float) {
if (SDK_INT >= LOLLIPOP) {
setElevation(elevation)
} else {
setBackgroundColor(ElevationOverlayProvider(context).compositeOverlayWithThemeSurfaceColorIfNeeded(elevation))
}
}
}

View File

@ -1,25 +0,0 @@
package io.github.wulkanowy.ui.widgets
import android.content.Context
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.LOLLIPOP
import android.util.AttributeSet
import com.google.android.material.elevation.ElevationOverlayProvider
import com.google.android.material.tabs.TabLayout
open class MaterialTabLayout : TabLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attr: AttributeSet) : super(context, attr)
constructor(context: Context, attr: AttributeSet, defStyleAttr: Int) : super(context, attr, defStyleAttr)
fun setElevationCompat(elevation: Float) {
if (SDK_INT >= LOLLIPOP) {
setElevation(elevation)
} else {
setBackgroundColor(ElevationOverlayProvider(context).compositeOverlayWithThemeSurfaceColorIfNeeded(elevation))
}
}
}

View File

@ -0,0 +1,11 @@
package io.github.wulkanowy.utils
import android.app.PendingIntent
import android.os.Build
object PendingIntentCompat {
val FLAG_IMMUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else 0
}

View File

@ -4,6 +4,4 @@ inline fun String?.ifNullOrBlank(defaultValue: () -> String) =
if (isNullOrBlank()) defaultValue() else this
fun String.capitalise() =
replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
fun String.decapitalise() = replaceFirstChar { it.lowercase() }
replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }

View File

@ -2,10 +2,8 @@
package io.github.wulkanowy.utils.security
import android.annotation.TargetApi
import android.content.Context
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.JELLY_BEAN_MR2
import android.os.Build.VERSION_CODES.M
import android.security.KeyPairGeneratorSpec
import android.security.keystore.KeyGenParameterSpec
@ -116,7 +114,6 @@ fun decrypt(cipherText: String): String {
}
}
@TargetApi(JELLY_BEAN_MR2)
private fun generateKeyPair(context: Context) {
(if (SDK_INT >= M) {
KeyGenParameterSpec.Builder(KEY_ALIAS, PURPOSE_DECRYPT or PURPOSE_ENCRYPT)