Исправлено отображение уведомления о просмотре устаревшего расписания.

Исправлен запуск сервиса постоянного уведомления.
This commit is contained in:
2024-10-26 18:32:33 +04:00
parent 2b2c202cfa
commit c4444ff2ca
17 changed files with 116 additions and 48 deletions

View File

@@ -17,6 +17,20 @@
</option>
<option name="signal" value="SIGNAL_UNSPECIFIED" />
<option name="timeIntervalDays" value="THIRTY_DAYS" />
<option name="versions">
<list>
<VersionSetting>
<option name="buildVersion" value="17" />
<option name="displayName" value="2.0.1 (17)" />
<option name="displayVersion" value="2.0.1" />
</VersionSetting>
<VersionSetting>
<option name="buildVersion" value="16" />
<option name="displayName" value="2.0.0prod (16)" />
<option name="displayVersion" value="2.0.0prod" />
</VersionSetting>
</list>
</option>
<option name="visibilityType" value="ALL" />
</InsightsFilterSettings>
</value>

View File

@@ -5,8 +5,12 @@
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>

View File

@@ -33,14 +33,13 @@ android {
applicationId = "ru.n08i40k.polytechnic.next"
minSdk = 26
targetSdk = 35
versionCode = 16
versionName = "2.0.0"
versionCode = 18
versionName = "2.0.2"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
versionNameSuffix = "prod"
}
buildTypes {

View File

@@ -1,5 +0,0 @@
package ru.n08i40k.polytechnic.next
object IntentRequestCodes {
const val ALARM_CLV = 1337
}

View File

@@ -7,7 +7,6 @@ import android.os.Build
import androidx.core.content.ContextCompat
import dagger.hilt.android.HiltAndroidApp
import ru.n08i40k.polytechnic.next.data.AppContainer
import ru.n08i40k.polytechnic.next.utils.or
import javax.inject.Inject
@HiltAndroidApp
@@ -18,7 +17,7 @@ class PolytechnicApplication : Application() {
fun getAppVersion(): String {
return applicationContext.packageManager
.getPackageInfo(this.packageName, 0)
.versionName or "1.0.0"
.versionName!!
}
fun hasNotificationPermission(): Boolean {

View File

@@ -4,8 +4,9 @@ import android.os.Parcelable
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDateTime
import kotlinx.parcelize.Parcelize
import kotlinx.parcelize.RawValue
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import ru.n08i40k.polytechnic.next.utils.InstantAsLongSerializer
import ru.n08i40k.polytechnic.next.utils.dateTime
import ru.n08i40k.polytechnic.next.utils.dayMinutes
import ru.n08i40k.polytechnic.next.utils.now
@@ -16,9 +17,18 @@ import ru.n08i40k.polytechnic.next.utils.now
@Serializable
class Day(
val name: String,
val date: @RawValue Instant,
@Serializable(with = InstantAsLongSerializer::class)
@SerialName("date")
private val dateMillis: Long,
val lessons: List<Lesson>
) : Parcelable {
constructor(name: String, date: Instant, lessons: List<Lesson>) : this(
name, date.toEpochMilliseconds(), lessons
)
val date: Instant
get() = Instant.fromEpochMilliseconds(dateMillis)
fun distanceToNextByLocalDateTime(from: LocalDateTime): Pair<Int, Int>? {
val toIdx = lessons
.map { it.time.start }

View File

@@ -6,19 +6,37 @@ import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.parcelize.Parcelize
import kotlinx.parcelize.RawValue
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import ru.n08i40k.polytechnic.next.utils.InstantAsLongSerializer
@Parcelize
@Serializable
data class LessonTime(
val start: @RawValue Instant,
val end: @RawValue Instant
@Serializable(with = InstantAsLongSerializer::class)
@SerialName("start")
private val startMillis: Long,
@Serializable(with = InstantAsLongSerializer::class)
@SerialName("end")
private val endMillis: Long
) : Parcelable {
constructor(start: Instant, end: Instant) : this(
start.toEpochMilliseconds(),
end.toEpochMilliseconds()
)
val start: Instant
get() = Instant.fromEpochMilliseconds(startMillis)
val end: Instant
get() = Instant.fromEpochMilliseconds(endMillis)
companion object {
fun fromLocalDateTime(start: LocalDateTime, end: LocalDateTime): LessonTime {
val timeZone = TimeZone.currentSystemDefault()
return LessonTime(start.toInstant(timeZone), end.toInstant(timeZone))
return LessonTime(
start.toInstant(timeZone),
end.toInstant(timeZone)
)
}
}
}

View File

@@ -17,7 +17,8 @@ fun PolytechnicApp() {
val navController = rememberNavController()
NavHost(
navController = navController, startDestination = "auth"
navController = navController,
startDestination = "auth"
) {
composable(route = "auth") {
AuthScreen(navController)

View File

@@ -157,7 +157,10 @@ private fun LinkButton(
verticalAlignment = Alignment.CenterVertically
) {
BadgedBox(badge = { if (badged) Badge() }) {
Icon(imageVector = icon, contentDescription = text)
Icon(
imageVector = icon,
contentDescription = text
)
}
Spacer(Modifier.width(5.dp))
Text(text)
@@ -189,7 +192,10 @@ private fun TopNavBar(
actions = {
IconButton(onClick = { dropdownExpanded = true }) {
BadgedBox(badge = { if (updateAvailable) Badge() }) {
Icon(imageVector = Icons.Filled.Menu, contentDescription = "TopAppBar Menu")
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "top app bar menu"
)
}
}
DropdownMenu(

View File

@@ -14,35 +14,23 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.lerp
import kotlinx.datetime.LocalDateTime
import ru.n08i40k.polytechnic.next.R
import ru.n08i40k.polytechnic.next.data.schedule.impl.FakeScheduleRepository
import ru.n08i40k.polytechnic.next.model.Group
import ru.n08i40k.polytechnic.next.ui.widgets.NotificationCard
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.time.temporal.WeekFields
import ru.n08i40k.polytechnic.next.utils.dateTime
import ru.n08i40k.polytechnic.next.utils.now
import java.util.Calendar
import java.util.Locale
import java.util.logging.Level
import kotlin.math.absoluteValue
private fun isCurrentWeek(group: Group): Boolean {
if (group.days.isEmpty())
return true
private fun isScheduleOutdated(group: Group): Boolean {
val nowDateTime = LocalDateTime.now()
val lastDay = group.days.lastOrNull() ?: return true
val lastLesson = lastDay.last ?: return true
val dateString = group.days[0].name
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale("ru"))
val datePart = dateString.split(" ").getOrNull(1) ?: return true
val date = LocalDate.parse(datePart, formatter)
val currentDate = LocalDate.now()
val weekField = WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear()
val currentWeek = currentDate.get(weekField)
val dateWeek = date.get(weekField)
return dateWeek >= currentWeek
return nowDateTime > lastLesson.time.end.dateTime
}
@Preview
@@ -57,7 +45,7 @@ fun DayPager(group: Group = FakeScheduleRepository.exampleGroup) {
pageCount = { group.days.size })
Column {
if (!isCurrentWeek(group)) {
if (isScheduleOutdated(group)) {
NotificationCard(
level = Level.WARNING,
title = stringResource(R.string.outdated_schedule)

View File

@@ -11,6 +11,9 @@ import ru.n08i40k.polytechnic.next.R
@Composable
internal fun PaskhalkoDialog() {
Dialog(onDismissRequest = {}) {
Image(painterResource(R.drawable.paskhalko), contentDescription = "Paskhalko")
Image(
painter = painterResource(R.drawable.paskhalko),
contentDescription = "paskhalko"
)
}
}

View File

@@ -147,7 +147,7 @@ private fun ExpandableCardArrow(
Icon(
modifier = Modifier.rotate(rotationDegree),
imageVector = Icons.Filled.ArrowDropDown,
contentDescription = "Expandable Arrow"
contentDescription = "expandable arrow"
)
}

View File

@@ -76,7 +76,7 @@ fun GroupSelector(
value = value ?: groups.getOrElse(1) { "TODO" }!!,
leadingIcon = {
Icon(
imageVector = Icons.Filled.Email,
Icons.Filled.Email,
contentDescription = "group"
)
},

View File

@@ -51,8 +51,14 @@ fun NotificationCard(
else -> AppIcons.Filled.Info
}
Icon(imageVector = icon, contentDescription = "Level")
Icon(imageVector = icon, contentDescription = "Level")
Icon(
imageVector = icon,
contentDescription = "level"
)
Icon(
imageVector = icon,
contentDescription = "level"
)
}
Text(
text = title,

View File

@@ -62,7 +62,12 @@ fun RoleSelector(
onDismissRequest = { expanded = false }) {
AcceptableUserRoles.forEach {
DropdownMenuItem(
leadingIcon = { Icon(it.icon, contentDescription = "Role icon") },
leadingIcon = {
Icon(
imageVector = it.icon,
contentDescription = "role icon"
)
},
text = { Text(stringResource(it.stringId)) },
onClick = {
expanded = false

View File

@@ -0,0 +1,22 @@
package ru.n08i40k.polytechnic.next.utils
import kotlinx.datetime.Instant
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
class InstantAsLongSerializer : KSerializer<Long> {
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("Instant", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Long) {
encoder.encodeString(Instant.fromEpochMilliseconds(value).toString())
}
override fun deserialize(decoder: Decoder): Long {
return Instant.parse(decoder.decodeString()).toEpochMilliseconds()
}
}

View File

@@ -16,8 +16,6 @@ class LinkUpdateWorker(context: Context, params: WorkerParameters) :
.getGroup()
}
// CurrentLessonViewService.startService(applicationContext)
return Result.success()
}
}