Skip to content

Commit 8b94caa

Browse files
author
alllexey
committed
Add new classes for better schedule widget data management
1 parent f3e87b1 commit 8b94caa

File tree

9 files changed

+245
-12
lines changed

9 files changed

+245
-12
lines changed

app/src/main/java/me/alllexey123/itmowidgets/ui/widgets/SingleLessonWidget.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ open class SingleLessonWidget : AppWidgetProvider() {
4848
teacher = lesson.teacherName ?: "",
4949
workTypeId = lesson.workTypeId,
5050
room = room,
51-
building = shortBuilding,
51+
building = shortBuilding ?: "",
5252
moreLessonsText = moreLessonsText,
5353
hideTeacher = lesson.teacherName == null || storage.getHideTeacherState(),
5454
hideLocation = false,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package me.alllexey123.itmowidgets.ui.widgets.data
2+
3+
class LessonListWidgetData(
4+
val entries: List<LessonListWidgetEntry>
5+
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package me.alllexey123.itmowidgets.ui.widgets.data
2+
3+
import me.alllexey123.itmowidgets.R
4+
5+
sealed class LessonListWidgetEntry(open val layoutId: Int) {
6+
object Error : LessonListWidgetEntry(R.layout.item_lesson_list_empty) // todo: Error
7+
object FullDayEmpty : LessonListWidgetEntry(R.layout.item_lesson_list_empty)
8+
object NoMoreLessons : LessonListWidgetEntry(R.layout.item_lesson_list_no_more)
9+
object LessonListEnd : LessonListWidgetEntry(R.layout.item_lesson_list_end)
10+
11+
// null to hide
12+
data class LessonData(
13+
val subject: String = "",
14+
val times: String? = null,
15+
val teacher: String? = null,
16+
val workTypeId: Int = 0,
17+
val room: String? = null,
18+
val building: String? = null,
19+
override val layoutId: Int,
20+
) : LessonListWidgetEntry(layoutId)
21+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package me.alllexey123.itmowidgets.ui.widgets.data
2+
3+
import api.myitmo.model.Lesson
4+
import me.alllexey123.itmowidgets.R
5+
import me.alllexey123.itmowidgets.data.repository.ScheduleRepository
6+
import me.alllexey123.itmowidgets.util.LINE_STYLE
7+
import me.alllexey123.itmowidgets.util.PreferencesStorage
8+
import me.alllexey123.itmowidgets.util.ScheduleUtils
9+
import java.time.LocalDate
10+
import java.time.LocalDateTime
11+
import kotlin.collections.map
12+
import kotlin.collections.orEmpty
13+
14+
const val RETRY_DELAY_SECONDS: Long = 7 * 60 // 7 minutes
15+
16+
private const val BEFOREHAND_SCHEDULING_OFFSET = 15L * 60 // 15 minutes
17+
18+
class LessonWidgetDataManager(
19+
private val scheduleRepository: ScheduleRepository,
20+
private val storage: PreferencesStorage
21+
) {
22+
23+
suspend fun getLessonWidgetsState(): LessonWidgetsState {
24+
var singleDataResult: SingleLessonWidgetData
25+
var listDataResult: LessonListWidgetData
26+
var nextUpdateAt: LocalDateTime
27+
try {
28+
val lessons = scheduleRepository.getDaySchedule(LocalDate.now()).lessons.orEmpty()
29+
singleDataResult = getSingleLessonData(lessons)
30+
listDataResult = getLessonListData(lessons)
31+
nextUpdateAt = getNextUpdateAt(lessons)
32+
} catch (e: Exception) {
33+
e.printStackTrace()
34+
singleDataResult = SingleLessonWidgetData.Error(getSingleLessonWidgetLayout())
35+
36+
listDataResult = LessonListWidgetData(
37+
listOf(LessonListWidgetEntry.Error)
38+
)
39+
40+
nextUpdateAt = LocalDateTime.now().plusSeconds(RETRY_DELAY_SECONDS)
41+
}
42+
43+
return LessonWidgetsState(
44+
singleDataResult,
45+
listDataResult,
46+
nextUpdateAt
47+
)
48+
}
49+
50+
private fun getSingleLessonData(lessons: List<Lesson>): SingleLessonWidgetData {
51+
val layoutId = getSingleLessonWidgetLayout()
52+
if (lessons.isEmpty()) return SingleLessonWidgetData.FullDayEmpty(layoutId)
53+
54+
val hideTeacher = storage.getHideTeacherState()
55+
val lesson = getLessonToShow(lessons)
56+
57+
return if (lesson == null) {
58+
SingleLessonWidgetData.NoMoreLessons(layoutId)
59+
} else {
60+
val last = lessons.last()
61+
val moreLessonsText = if (lesson == last) {
62+
"это последняя пара на сегодня"
63+
} else {
64+
val more = lessons.size - lessons.indexOf(lesson) - 1
65+
"и ещё $more ${ScheduleUtils.lessonDeclension(more)} до ${last.timeEnd}"
66+
}
67+
68+
SingleLessonWidgetData(
69+
subject = lesson.subject ?: "Неизвестный предмет",
70+
times = "${lesson.timeStart} - ${lesson.timeEnd}",
71+
teacher = if (hideTeacher) null else lesson.teacherName,
72+
workTypeId = lesson.workTypeId,
73+
room = ScheduleUtils.shortenRoom(lesson.room) ?: "нет кабинета",
74+
building = ScheduleUtils.shortenBuildingName(lesson.building),
75+
moreLessonsText = moreLessonsText,
76+
layoutId = layoutId
77+
)
78+
}
79+
}
80+
81+
private fun getLessonListData(lessons: List<Lesson>): LessonListWidgetData {
82+
if (lessons.isEmpty()) return LessonListWidgetData(listOf(LessonListWidgetEntry.FullDayEmpty))
83+
84+
val hidePrevious = storage.getHidePreviousLessonsState()
85+
val hideTeacher = storage.getHideTeacherState()
86+
87+
val lessonsToShow = if (hidePrevious) {
88+
val startFrom = getLessonToShow(lessons)
89+
lessons.drop(lessons.indexOf(startFrom))
90+
} else lessons
91+
92+
return if (lessonsToShow.isEmpty()) {
93+
LessonListWidgetData(
94+
listOf(LessonListWidgetEntry.NoMoreLessons)
95+
)
96+
} else {
97+
val layoutId = getListWidgetLessonLayout()
98+
val entries = lessonsToShow.map { lesson ->
99+
LessonListWidgetEntry.LessonData(
100+
subject = lesson.subject ?: "Неизвестный предмет",
101+
times = "${lesson.timeStart} - ${lesson.timeEnd}",
102+
teacher = if (hideTeacher) null else lesson.teacherName,
103+
workTypeId = lesson.workTypeId,
104+
room = ScheduleUtils.shortenRoom(lesson.room) ?: "нет кабинета",
105+
building = ScheduleUtils.shortenBuildingName(lesson.building),
106+
layoutId = layoutId
107+
)
108+
}.plus(LessonListWidgetEntry.LessonListEnd)
109+
110+
LessonListWidgetData(
111+
entries
112+
)
113+
}
114+
}
115+
116+
private fun getNextUpdateAt(lessons: List<Lesson>): LocalDateTime {
117+
val lesson = getLessonToShow(lessons)
118+
val now = LocalDate.now()
119+
if (lesson == null) return now.plusDays(1).atStartOfDay()
120+
121+
val beforehandScheduling = storage.getBeforehandSchedulingState()
122+
return if (lesson == lessons.last() || !beforehandScheduling) {
123+
ScheduleUtils.parseTime(now, lesson.timeEnd)
124+
} else {
125+
ScheduleUtils.parseTime(now, lesson.timeEnd).minusSeconds(BEFOREHAND_SCHEDULING_OFFSET)
126+
}
127+
}
128+
129+
fun getSingleLessonWidgetLayout(): Int {
130+
return if (storage.getSingleLessonWidgetStyle() == LINE_STYLE) {
131+
R.layout.single_lesson_widget_dash
132+
} else {
133+
R.layout.single_lesson_widget_dot
134+
}
135+
}
136+
137+
fun getListWidgetLessonLayout(): Int {
138+
return if (storage.getLessonListWidgetStyle() == LINE_STYLE) {
139+
R.layout.item_lesson_list_entry_dash
140+
} else {
141+
R.layout.item_lesson_list_entry_dot
142+
}
143+
}
144+
145+
fun getLessonToShow(lessons: List<Lesson>): Lesson? {
146+
val beforehandScheduling = storage.getBeforehandSchedulingState()
147+
val now = LocalDateTime.now()
148+
149+
val currOrNext = ScheduleUtils.findCurrentOrNextLesson(lessons, now)
150+
val lesson = if (beforehandScheduling) {
151+
val nowWithBeforehand = now.plusSeconds(BEFOREHAND_SCHEDULING_OFFSET)
152+
val currOrNextWithBeforehand =
153+
ScheduleUtils.findCurrentOrNextLesson(lessons, nowWithBeforehand)
154+
155+
currOrNextWithBeforehand ?: currOrNext
156+
} else {
157+
currOrNext
158+
}
159+
return lesson
160+
}
161+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package me.alllexey123.itmowidgets.ui.widgets.data
2+
3+
import java.time.LocalDateTime
4+
5+
data class LessonWidgetsState(
6+
val singleLessonData: SingleLessonWidgetData,
7+
val lessonListWidgetData: LessonListWidgetData,
8+
val nextUpdateAt: LocalDateTime
9+
)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package me.alllexey123.itmowidgets.ui.widgets.data
2+
3+
// null to hide
4+
data class SingleLessonWidgetData(
5+
val subject: String = "",
6+
val times: String? = null,
7+
val teacher: String? = null,
8+
val workTypeId: Int = 0,
9+
val room: String? = null,
10+
val building: String? = null,
11+
val moreLessonsText: String? = null,
12+
val layoutId: Int
13+
) {
14+
companion object {
15+
fun Error(layoutId: Int, errorMessage: String = "Ошибка загрузки данных"): SingleLessonWidgetData {
16+
return SingleLessonWidgetData(
17+
subject = errorMessage,
18+
workTypeId = 4,
19+
layoutId = layoutId
20+
)
21+
}
22+
23+
fun FullDayEmpty(layoutId: Int, message: String = "Сегодня нет пар"): SingleLessonWidgetData {
24+
return SingleLessonWidgetData(
25+
subject = message,
26+
workTypeId = -1,
27+
layoutId = layoutId
28+
)
29+
}
30+
31+
fun NoMoreLessons(layoutId: Int, message: String = "Сегодня больше нет пар"): SingleLessonWidgetData {
32+
return SingleLessonWidgetData(
33+
subject = message,
34+
workTypeId = -1,
35+
layoutId = layoutId
36+
)
37+
}
38+
}
39+
}

app/src/main/java/me/alllexey123/itmowidgets/util/PreferencesStorage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class PreferencesStorage(val prefs: SharedPreferences) : Storage {
7171
return prefs.getString(SINGLE_LESSON_WIDGET_STYLE, DOT_STYLE)
7272
}
7373

74-
fun getListLessonWidgetStyle(): String? {
74+
fun getLessonListWidgetStyle(): String? {
7575
return prefs.getString(LIST_LESSON_WIDGET_STYLE, DOT_STYLE)
7676
}
7777

app/src/main/java/me/alllexey123/itmowidgets/util/ScheduleUtils.kt

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import me.alllexey123.itmowidgets.R
55
import java.time.DayOfWeek
66
import java.time.LocalDate
77
import java.time.LocalDateTime
8+
import java.time.LocalTime
89
import java.time.format.DateTimeFormatter
910
import java.util.regex.Pattern
1011

@@ -47,12 +48,7 @@ object ScheduleUtils {
4748
}
4849

4950
fun parseTime(date: LocalDate, time: String): LocalDateTime {
50-
val hoursStr = time.substring(0, time.indexOf(":"))
51-
val minutesStr = time.substring(time.indexOf(":") + 1)
52-
53-
val hours = (if (hoursStr.startsWith('0')) hoursStr.substring(1) else hoursStr).toInt()
54-
val minutes = (if (minutesStr.startsWith('0')) minutesStr.substring(1) else minutesStr).toInt()
55-
return date.atTime(hours, minutes)
51+
return date.atTime(LocalTime.parse(time))
5652
}
5753

5854
fun lessonDeclension(count: Int): String {
@@ -61,7 +57,8 @@ object ScheduleUtils {
6157
else return "пары"
6258
}
6359

64-
fun shortenRoom(room: String): String {
60+
fun shortenRoom(room: String?): String? {
61+
if (room == null) return null
6562
val roomLow = room.lowercase()
6663
if (roomLow.contains("актовый")) return "Акт. зал"
6764
val m1 = Pattern.compile("[0-9]{4}/[0-9]").matcher(roomLow)
@@ -77,7 +74,8 @@ object ScheduleUtils {
7774
return room
7875
}
7976

80-
fun shortenBuildingName(building: String): String {
77+
fun shortenBuildingName(building: String?): String? {
78+
if (building == null) return null
8179
val name = building.lowercase()
8280
if (name.contains("кронв")) return "Кронва"
8381
if (name.contains("ломо")) return "Ломо"

app/src/main/java/me/alllexey123/itmowidgets/workers/LessonWidgetUpdateWorker.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class LessonWidgetUpdateWorker(
156156
else {
157157
val lessonEndTime = ScheduleUtils.parseTime(currentDate, l.timeEnd)
158158
val deadline: LocalDateTime
159-
if (i == lessons.size - 1 || !beforehandScheduling) { // no beforehand
159+
if (i == lessons.size - 1 || !beforehandScheduling) {
160160
deadline = now
161161
} else {
162162
deadline = now.plusSeconds(BEFOREHAND_SCHEDULING_OFFSET)
@@ -183,7 +183,7 @@ class LessonWidgetUpdateWorker(
183183
widgetIds.forEach { appWidgetId ->
184184
val providerInfo = appWidgetManager.getAppWidgetInfo(appWidgetId)
185185
val realLayoutId = providerInfo.initialLayout
186-
val rowLayoutId = if (storage.getListLessonWidgetStyle() == LINE_STYLE) {
186+
val rowLayoutId = if (storage.getLessonListWidgetStyle() == LINE_STYLE) {
187187
R.layout.item_lesson_list_entry_dash
188188
} else {
189189
R.layout.item_lesson_list_entry_dot

0 commit comments

Comments
 (0)