1
0

Compare commits

..

15 Commits
0.8.0 ... 0.8.3

Author SHA1 Message Date
153e026a8d Version 0.8.3 2019-05-20 00:21:30 +02:00
8731c2e1f2 Change help text when entering the symbol to a more precise one (#345) 2019-05-19 22:47:57 +02:00
0977282a4b Fix no current student in services after logout all accounts (#342) 2019-05-18 23:42:47 +02:00
667c4b6af7 Fix empty maybe when loading message content (#343) 2019-05-18 23:32:37 +02:00
1f5088cfc9 Don't copy teacher from previous lesson to completed (#341) 2019-05-18 13:03:38 +02:00
bf6b857a3e Fix null returns in widgets (#340) 2019-05-18 00:22:07 +02:00
80cb94c434 Version 0.8.2 2019-05-15 19:26:25 +02:00
0cb4eda32b Fix crash on reselecting fragment (#339) 2019-05-15 15:11:28 +02:00
d169f964f2 Fix crash when no webview activity (#338) 2019-05-14 11:45:27 +02:00
103ab95c80 Fix not attached fragment (#337)
* Add condition for error dialog
* Add safe call of forEach in LuckyNumberWidgetProvider
2019-05-09 22:06:11 +02:00
a191f03cdf Version 0.8.1 2019-04-30 23:56:22 +02:00
63404b8576 Fix entity list comparing (#335) 2019-04-30 19:04:05 +02:00
1b7760ff88 Fix dark theme background with custom theme engine (#334) 2019-04-30 17:45:37 +02:00
24f58835e7 Fix menu view initialization and restoration (#333) 2019-04-30 17:28:09 +02:00
b032c459d1 Fix theme on release build (#332) 2019-04-30 11:16:23 +02:00
61 changed files with 295 additions and 187 deletions

View File

@ -13,8 +13,8 @@ cache:
#branches: #branches:
# only: # only:
# - master # - master
# - 0.7.x # - 0.8.x
android: android:
licenses: licenses:

View File

@ -16,8 +16,8 @@ android {
testApplicationId "io.github.tests.wulkanowy" testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 15 minSdkVersion 15
targetSdkVersion 28 targetSdkVersion 28
versionCode 33 versionCode 36
versionName "0.8.0" versionName "0.8.3"
multiDexEnabled true multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@ -80,12 +80,12 @@ androidExtensions {
play { play {
serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf" serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf"
serviceAccountCredentials = file('key.p12') serviceAccountCredentials = file('key.p12')
defaultToAppBundles = true defaultToAppBundles = false
track = 'alpha' track = 'alpha'
} }
dependencies { dependencies {
implementation 'io.github.wulkanowy:api:0.8.0' implementation 'io.github.wulkanowy:api:0.8.3'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.legacy:legacy-support-v4:1.0.0"

View File

@ -22,6 +22,7 @@ import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.threeten.bp.LocalDate.of import org.threeten.bp.LocalDate.of
import org.threeten.bp.LocalDateTime import org.threeten.bp.LocalDateTime
import kotlin.test.assertEquals
import kotlin.test.assertFalse import kotlin.test.assertFalse
import kotlin.test.assertTrue import kotlin.test.assertTrue
import io.github.wulkanowy.api.grades.Grade as GradeApi import io.github.wulkanowy.api.grades.Grade as GradeApi
@ -109,4 +110,73 @@ class GradeRepositoryTest {
assertTrue { grades[2].isRead } assertTrue { grades[2].isRead }
assertTrue { grades[3].isRead } assertTrue { grades[3].isRead }
} }
@Test
fun subtractLocaleDuplicateGrades() {
gradeLocal.saveGrades(listOf(
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
))
every { mockApi.getGrades(1) } returns Single.just(listOf(
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
))
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
.getGrades(studentMock, semesterMock, true).blockingGet()
assertEquals(2, grades.size)
}
@Test
fun subtractRemoteDuplicateGrades() {
gradeLocal.saveGrades(listOf(
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
))
every { mockApi.getGrades(1) } returns Single.just(listOf(
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
))
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
.getGrades(studentMock, semesterMock, true).blockingGet()
assertEquals(3, grades.size)
}
@Test
fun emptyLocal() {
gradeLocal.saveGrades(listOf())
every { mockApi.getGrades(1) } returns Single.just(listOf(
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
))
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
.getGrades(studentMock, semesterMock, true).blockingGet()
assertEquals(3, grades.size)
}
@Test
fun emptyRemote() {
gradeLocal.saveGrades(listOf(
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
))
every { mockApi.getGrades(1) } returns Single.just(listOf())
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
.getGrades(studentMock, semesterMock, true).blockingGet()
assertEquals(0, grades.size)
}
} }

View File

@ -7,7 +7,7 @@ import org.threeten.bp.LocalDateTime.now
import io.github.wulkanowy.api.timetable.Timetable as TimetableRemote import io.github.wulkanowy.api.timetable.Timetable as TimetableRemote
import io.github.wulkanowy.data.db.entities.Timetable as TimetableLocal import io.github.wulkanowy.data.db.entities.Timetable as TimetableLocal
fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", subject: String = ""): TimetableLocal { fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", subject: String = "", teacher: String = ""): TimetableLocal {
return TimetableLocal( return TimetableLocal(
studentId = 1, studentId = 1,
diaryId = 2, diaryId = 2,
@ -20,7 +20,7 @@ fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", s
group = "", group = "",
room = room, room = room,
roomOld = "", roomOld = "",
teacher = "", teacher = teacher,
teacherOld = "", teacherOld = "",
info = "", info = "",
changes = false, changes = false,
@ -28,7 +28,7 @@ fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", s
) )
} }
fun createTimetableRemote(number: Int, start: LocalDateTime, room: String, subject: String = ""): TimetableRemote { fun createTimetableRemote(number: Int, start: LocalDateTime, room: String, subject: String = "", teacher: String = ""): TimetableRemote {
return TimetableRemote( return TimetableRemote(
number = number, number = number,
start = start.toDate(), start = start.toDate(),
@ -37,7 +37,7 @@ fun createTimetableRemote(number: Int, start: LocalDateTime, room: String, subje
subject = subject, subject = subject,
group = "", group = "",
room = room, room = room,
teacher = "", teacher = teacher,
info = "", info = "",
changes = false, changes = false,
canceled = false canceled = false

View File

@ -63,23 +63,27 @@ class TimetableRepositoryTest {
fun copyDetailsToCompletedFromPrevious() { fun copyDetailsToCompletedFromPrevious() {
timetableLocal.saveTimetable(listOf( timetableLocal.saveTimetable(listOf(
createTimetableLocal(1, of(2019, 3, 5, 8, 0), "123", "Przyroda"), createTimetableLocal(1, of(2019, 3, 5, 8, 0), "123", "Przyroda"),
createTimetableLocal(1, of(2019, 3, 5, 8, 50), "321", "Religia"), createTimetableLocal(2, of(2019, 3, 5, 8, 50), "321", "Religia"),
createTimetableLocal(1, of(2019, 3, 5, 9, 40), "213", "W-F") createTimetableLocal(3, of(2019, 3, 5, 9, 40), "213", "W-F"),
createTimetableLocal(4, of(2019, 3, 5, 10, 30), "213", "W-F", "Jan Kowalski")
)) ))
every { mockApi.getTimetable(any(), any()) } returns Single.just(listOf( every { mockApi.getTimetable(any(), any()) } returns Single.just(listOf(
createTimetableRemote(1, of(2019, 3, 5, 8, 0), "", "Przyroda"), createTimetableRemote(1, of(2019, 3, 5, 8, 0), "", "Przyroda"),
createTimetableRemote(1, of(2019, 3, 5, 8, 50), "", "Religia"), createTimetableRemote(2, of(2019, 3, 5, 8, 50), "", "Religia"),
createTimetableRemote(1, of(2019, 3, 5, 9, 40), "", "W-F") createTimetableRemote(3, of(2019, 3, 5, 9, 40), "", "W-F"),
createTimetableRemote(4, of(2019, 3, 5, 10, 30), "", "W-F")
)) ))
val lessons = TimetableRepository(settings, timetableLocal, timetableRemote) val lessons = TimetableRepository(settings, timetableLocal, timetableRemote)
.getTimetable(semesterMock, LocalDate.of(2019, 3, 5), LocalDate.of(2019, 3, 5), true) .getTimetable(semesterMock, LocalDate.of(2019, 3, 5), LocalDate.of(2019, 3, 5), true)
.blockingGet() .blockingGet()
assertEquals(3, lessons.size) assertEquals(4, lessons.size)
assertEquals("123", lessons[0].room) assertEquals("123", lessons[0].room)
assertEquals("321", lessons[1].room) assertEquals("321", lessons[1].room)
assertEquals("213", lessons[2].room) assertEquals("213", lessons[2].room)
assertEquals("", lessons[3].teacher)
} }
} }

View File

@ -48,8 +48,8 @@
android:theme="@style/WulkanowyTheme.NoActionBar" /> android:theme="@style/WulkanowyTheme.NoActionBar" />
<activity <activity
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity" android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
android:noHistory="true"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:noHistory="true"
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher"> android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
@ -57,8 +57,8 @@
</activity> </activity>
<activity <activity
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity" android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity"
android:noHistory="true"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:noHistory="true"
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher"> android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />

View File

@ -23,8 +23,8 @@ interface MessagesDao {
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC") @Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
fun loadAll(studentId: Int, folder: Int): Maybe<List<Message>> fun loadAll(studentId: Int, folder: Int): Maybe<List<Message>>
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND real_id = :id") @Query("SELECT * FROM Messages WHERE id = :id")
fun load(studentId: Int, id: Int): Maybe<Message> fun load(id: Long): Maybe<Message>
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC") @Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC")
fun loadDeleted(studentId: Int): Maybe<List<Message>> fun loadDeleted(studentId: Int): Maybe<List<Message>>

View File

@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.friday import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import java.net.UnknownHostException import java.net.UnknownHostException
@ -31,8 +32,8 @@ class AttendanceRepository @Inject constructor(
local.getAttendance(semester, dates.first, dates.second) local.getAttendance(semester, dates.first, dates.second)
.toSingle(emptyList()) .toSingle(emptyList())
.doOnSuccess { oldAttendance -> .doOnSuccess { oldAttendance ->
local.deleteAttendance(oldAttendance - newAttendance) local.deleteAttendance(oldAttendance.uniqueSubtract(newAttendance))
local.saveAttendance(newAttendance - oldAttendance) local.saveAttendance(newAttendance.uniqueSubtract(oldAttendance))
} }
}.flatMap { }.flatMap {
local.getAttendance(semester, dates.first, dates.second) local.getAttendance(semester, dates.first, dates.second)

View File

@ -4,6 +4,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.db.entities.AttendanceSummary import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import java.net.UnknownHostException import java.net.UnknownHostException
import javax.inject.Inject import javax.inject.Inject
@ -25,8 +26,8 @@ class AttendanceSummaryRepository @Inject constructor(
}.flatMap { new -> }.flatMap { new ->
local.getAttendanceSummary(semester, subjectId).toSingle(emptyList()) local.getAttendanceSummary(semester, subjectId).toSingle(emptyList())
.doOnSuccess { old -> .doOnSuccess { old ->
local.deleteAttendanceSummary(old - new) local.deleteAttendanceSummary(old.uniqueSubtract(new))
local.saveAttendanceSummary(new - old) local.saveAttendanceSummary(new.uniqueSubtract(old))
} }
}.flatMap { local.getAttendanceSummary(semester, subjectId).toSingle(emptyList()) }) }.flatMap { local.getAttendanceSummary(semester, subjectId).toSingle(emptyList()) })
} }

View File

@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.friday import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import java.net.UnknownHostException import java.net.UnknownHostException
@ -31,8 +32,8 @@ class CompletedLessonsRepository @Inject constructor(
local.getCompletedLessons(semester, dates.first, dates.second) local.getCompletedLessons(semester, dates.first, dates.second)
.toSingle(emptyList()) .toSingle(emptyList())
.doOnSuccess { old -> .doOnSuccess { old ->
local.deleteCompleteLessons(old - new) local.deleteCompleteLessons(old.uniqueSubtract(new))
local.saveCompletedLessons(new - old) local.saveCompletedLessons(new.uniqueSubtract(old))
} }
}.flatMap { }.flatMap {
local.getCompletedLessons(semester, dates.first, dates.second) local.getCompletedLessons(semester, dates.first, dates.second)

View File

@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.friday import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import java.net.UnknownHostException import java.net.UnknownHostException
@ -27,12 +28,12 @@ class ExamRepository @Inject constructor(
.flatMap { .flatMap {
if (it) remote.getExams(semester, dates.first, dates.second) if (it) remote.getExams(semester, dates.first, dates.second)
else Single.error(UnknownHostException()) else Single.error(UnknownHostException())
}.flatMap { newExams -> }.flatMap { new ->
local.getExams(semester, dates.first, dates.second) local.getExams(semester, dates.first, dates.second)
.toSingle(emptyList()) .toSingle(emptyList())
.doOnSuccess { oldExams -> .doOnSuccess { old ->
local.deleteExams(oldExams - newExams) local.deleteExams(old.uniqueSubtract(new))
local.saveExams(newExams - oldExams) local.saveExams(new.uniqueSubtract(old))
} }
}.flatMap { }.flatMap {
local.getExams(semester, dates.first, dates.second) local.getExams(semester, dates.first, dates.second)

View File

@ -5,6 +5,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Single import io.reactivex.Single
import java.net.UnknownHostException import java.net.UnknownHostException
@ -24,13 +25,12 @@ class GradeRepository @Inject constructor(
.flatMap { .flatMap {
if (it) remote.getGrades(semester) if (it) remote.getGrades(semester)
else Single.error(UnknownHostException()) else Single.error(UnknownHostException())
}.flatMap { newGrades -> }.flatMap { new ->
local.getGrades(semester).toSingle(emptyList()) local.getGrades(semester).toSingle(emptyList())
.doOnSuccess { oldGrades -> .doOnSuccess { old ->
val notifyBreakDate = oldGrades.maxBy { it.date }?.date val notifyBreakDate = old.maxBy { it.date }?.date ?: student.registrationDate.toLocalDate()
?: student.registrationDate.toLocalDate() local.deleteGrades(old.uniqueSubtract(new))
local.deleteGrades(oldGrades - newGrades) local.saveGrades(new.uniqueSubtract(old)
local.saveGrades((newGrades - oldGrades)
.onEach { .onEach {
if (it.date >= notifyBreakDate) it.apply { if (it.date >= notifyBreakDate) it.apply {
isRead = false isRead = false

View File

@ -4,6 +4,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import java.net.UnknownHostException import java.net.UnknownHostException
import javax.inject.Inject import javax.inject.Inject
@ -22,11 +23,11 @@ class GradeSummaryRepository @Inject constructor(
.flatMap { .flatMap {
if (it) remote.getGradeSummary(semester) if (it) remote.getGradeSummary(semester)
else Single.error(UnknownHostException()) else Single.error(UnknownHostException())
}.flatMap { newGradesSummary -> }.flatMap { new ->
local.getGradesSummary(semester).toSingle(emptyList()) local.getGradesSummary(semester).toSingle(emptyList())
.doOnSuccess { oldGradesSummary -> .doOnSuccess { old ->
local.deleteGradesSummary(oldGradesSummary - newGradesSummary) local.deleteGradesSummary(old.uniqueSubtract(new))
local.saveGradesSummary(newGradesSummary - oldGradesSummary) local.saveGradesSummary(new.uniqueSubtract(old))
} }
}.flatMap { local.getGradesSummary(semester).toSingle(emptyList()) }) }.flatMap { local.getGradesSummary(semester).toSingle(emptyList()) })
} }

View File

@ -4,6 +4,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import java.net.UnknownHostException import java.net.UnknownHostException
import javax.inject.Inject import javax.inject.Inject
@ -22,11 +23,11 @@ class GradeStatisticsRepository @Inject constructor(
.flatMap { .flatMap {
if (it) remote.getGradeStatistics(semester, isSemester) if (it) remote.getGradeStatistics(semester, isSemester)
else Single.error(UnknownHostException()) else Single.error(UnknownHostException())
}.flatMap { newGradesStats -> }.flatMap { new ->
local.getGradesStatistics(semester, isSemester).toSingle(emptyList()) local.getGradesStatistics(semester, isSemester).toSingle(emptyList())
.doOnSuccess { oldGradesStats -> .doOnSuccess { old ->
local.deleteGradesStatistics(oldGradesStats - newGradesStats) local.deleteGradesStatistics(old.uniqueSubtract(new))
local.saveGradesStatistics(newGradesStats - oldGradesStats) local.saveGradesStatistics(new.uniqueSubtract(old))
} }
}.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) }) }.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) })
} }

View File

@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Homework
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.utils.friday import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import java.net.UnknownHostException import java.net.UnknownHostException
@ -26,11 +27,11 @@ class HomeworkRepository @Inject constructor(
.flatMap { .flatMap {
if (it) remote.getHomework(semester, monday, friday) if (it) remote.getHomework(semester, monday, friday)
else Single.error(UnknownHostException()) else Single.error(UnknownHostException())
}.flatMap { newGrades -> }.flatMap { new ->
local.getHomework(semester, monday, friday).toSingle(emptyList()) local.getHomework(semester, monday, friday).toSingle(emptyList())
.doOnSuccess { oldGrades -> .doOnSuccess { old ->
local.deleteHomework(oldGrades - newGrades) local.deleteHomework(old.uniqueSubtract(new))
local.saveHomework(newGrades - oldGrades) local.saveHomework(new.uniqueSubtract(old))
} }
}.flatMap { local.getHomework(semester, monday, friday).toSingle(emptyList()) }) }.flatMap { local.getHomework(semester, monday, friday).toSingle(emptyList()) })
} }

View File

@ -23,8 +23,8 @@ class MessageLocal @Inject constructor(private val messagesDb: MessagesDao) {
messagesDb.deleteAll(messages) messagesDb.deleteAll(messages)
} }
fun getMessage(student: Student, id: Int): Maybe<Message> { fun getMessage(id: Long): Maybe<Message> {
return messagesDb.load(student.id.toInt(), id) return messagesDb.load(id)
} }
fun getMessages(student: Student, folder: MessageFolder): Maybe<List<Message>> { fun getMessages(student: Student, folder: MessageFolder): Maybe<List<Message>> {

View File

@ -8,6 +8,7 @@ import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Maybe import io.reactivex.Maybe
import io.reactivex.Single import io.reactivex.Single
@ -34,8 +35,8 @@ class MessageRepository @Inject constructor(
}.flatMap { new -> }.flatMap { new ->
local.getMessages(student, folder).toSingle(emptyList()) local.getMessages(student, folder).toSingle(emptyList())
.doOnSuccess { old -> .doOnSuccess { old ->
local.deleteMessages(old - new) local.deleteMessages(old.uniqueSubtract(new))
local.saveMessages((new - old) local.saveMessages(new.uniqueSubtract(old)
.onEach { .onEach {
it.isNotified = !notify it.isNotified = !notify
}) })
@ -45,14 +46,14 @@ class MessageRepository @Inject constructor(
} }
} }
fun getMessage(student: Student, messageId: Int, markAsRead: Boolean = false): Single<Message> { fun getMessage(student: Student, messageDbId: Long, markAsRead: Boolean = false): Single<Message> {
return Single.just(apiHelper.initApi(student)) return Single.just(apiHelper.initApi(student))
.flatMap { _ -> .flatMap { _ ->
local.getMessage(student, messageId) local.getMessage(messageDbId)
.filter { !it.content.isNullOrEmpty() } .filter { !it.content.isNullOrEmpty() }
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap { .flatMap {
if (it) local.getMessage(student, messageId).toSingle() if (it) local.getMessage(messageDbId).toSingle()
else Single.error(UnknownHostException()) else Single.error(UnknownHostException())
} }
.flatMap { dbMessage -> .flatMap { dbMessage ->
@ -63,7 +64,7 @@ class MessageRepository @Inject constructor(
})) }))
} }
}.flatMap { }.flatMap {
local.getMessage(student, messageId).toSingle() local.getMessage(messageDbId).toSingle()
} }
) )
} }

View File

@ -5,6 +5,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
import io.github.wulkanowy.data.db.entities.Note import io.github.wulkanowy.data.db.entities.Note
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Single import io.reactivex.Single
import java.net.UnknownHostException import java.net.UnknownHostException
@ -27,8 +28,8 @@ class NoteRepository @Inject constructor(
}.flatMap { new -> }.flatMap { new ->
local.getNotes(student).toSingle(emptyList()) local.getNotes(student).toSingle(emptyList())
.doOnSuccess { old -> .doOnSuccess { old ->
local.deleteNotes(old - new) local.deleteNotes(old.uniqueSubtract(new))
local.saveNotes((new - old) local.saveNotes(new.uniqueSubtract(old)
.onEach { .onEach {
if (it.date >= student.registrationDate.toLocalDate()) it.apply { if (it.date >= student.registrationDate.toLocalDate()) it.apply {
isRead = false isRead = false

View File

@ -7,6 +7,7 @@ import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import java.net.UnknownHostException import java.net.UnknownHostException
import javax.inject.Inject import javax.inject.Inject
@ -31,8 +32,8 @@ class RecipientRepository @Inject constructor(
}.flatMap { new -> }.flatMap { new ->
local.getRecipients(student, role, unit).toSingle(emptyList()) local.getRecipients(student, role, unit).toSingle(emptyList())
.doOnSuccess { old -> .doOnSuccess { old ->
local.deleteRecipients(old - new) local.deleteRecipients(old.uniqueSubtract(new))
local.saveRecipients(new - old) local.saveRecipients(new.uniqueSubtract(old))
} }
}.flatMap { }.flatMap {
local.getRecipients(student, role, unit).toSingle(emptyList()) local.getRecipients(student, role, unit).toSingle(emptyList())

View File

@ -5,6 +5,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
import io.github.wulkanowy.data.ApiHelper import io.github.wulkanowy.data.ApiHelper
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Maybe import io.reactivex.Maybe
import io.reactivex.Single import io.reactivex.Single
import java.net.UnknownHostException import java.net.UnknownHostException
@ -30,8 +31,8 @@ class ReportingUnitRepository @Inject constructor(
}.flatMap { new -> }.flatMap { new ->
local.getReportingUnits(student).toSingle(emptyList()) local.getReportingUnits(student).toSingle(emptyList())
.doOnSuccess { old -> .doOnSuccess { old ->
local.deleteReportingUnits(old - new) local.deleteReportingUnits(old.uniqueSubtract(new))
local.saveReportingUnits(new - old) local.saveReportingUnits(new.uniqueSubtract(old))
} }
}.flatMap { local.getReportingUnits(student).toSingle(emptyList()) } }.flatMap { local.getReportingUnits(student).toSingle(emptyList()) }
) )

View File

@ -5,6 +5,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
import io.github.wulkanowy.data.ApiHelper import io.github.wulkanowy.data.ApiHelper
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Maybe import io.reactivex.Maybe
import io.reactivex.Single import io.reactivex.Single
import timber.log.Timber import timber.log.Timber
@ -31,8 +32,8 @@ class SemesterRepository @Inject constructor(
if (currentSemesters.size == 1) { if (currentSemesters.size == 1) {
local.getSemesters(student).toSingle(emptyList()) local.getSemesters(student).toSingle(emptyList())
.doOnSuccess { old -> .doOnSuccess { old ->
local.deleteSemesters(old - new) local.deleteSemesters(old.uniqueSubtract(new))
local.saveSemesters(new - old) local.saveSemesters(new.uniqueSubtract(old))
} }
} else { } else {
Timber.i("Current semesters list:\n${currentSemesters.joinToString(separator = "\n")}") Timber.i("Current semesters list:\n${currentSemesters.joinToString(separator = "\n")}")

View File

@ -22,6 +22,8 @@ class StudentRepository @Inject constructor(
fun isStudentSaved(): Single<Boolean> = local.getStudents(false).isEmpty.map { !it } fun isStudentSaved(): Single<Boolean> = local.getStudents(false).isEmpty.map { !it }
fun isCurrentStudentSet(): Single<Boolean> = local.getCurrentStudent(false).isEmpty.map { !it }
fun getStudents(email: String, password: String, endpoint: String, symbol: String = ""): Single<List<Student>> { fun getStudents(email: String, password: String, endpoint: String, symbol: String = ""): Single<List<Student>> {
return ReactiveNetwork.checkInternetConnectivity(settings) return ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap { .flatMap {

View File

@ -4,6 +4,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Subject import io.github.wulkanowy.data.db.entities.Subject
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import java.net.UnknownHostException import java.net.UnknownHostException
import javax.inject.Inject import javax.inject.Inject
@ -26,8 +27,8 @@ class SubjectRepository @Inject constructor(
local.getSubjects(semester) local.getSubjects(semester)
.toSingle(emptyList()) .toSingle(emptyList())
.doOnSuccess { old -> .doOnSuccess { old ->
local.deleteSubjects(old - new) local.deleteSubjects(old.uniqueSubtract(new))
local.saveSubjects(new - old) local.saveSubjects(new.uniqueSubtract(old))
} }
}.flatMap { }.flatMap {
local.getSubjects(semester).toSingle(emptyList()) local.getSubjects(semester).toSingle(emptyList())

View File

@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.utils.friday import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.uniqueSubtract
import io.reactivex.Single import io.reactivex.Single
import org.threeten.bp.LocalDate import org.threeten.bp.LocalDate
import java.net.UnknownHostException import java.net.UnknownHostException
@ -25,17 +26,16 @@ class TimetableRepository @Inject constructor(
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap { .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
if (it) remote.getTimetable(semester, monday, friday) if (it) remote.getTimetable(semester, monday, friday)
else Single.error(UnknownHostException()) else Single.error(UnknownHostException())
}.flatMap { newTimetable -> }.flatMap { new ->
local.getTimetable(semester, monday, friday) local.getTimetable(semester, monday, friday)
.toSingle(emptyList()) .toSingle(emptyList())
.doOnSuccess { oldTimetable -> .doOnSuccess { old ->
local.deleteTimetable(oldTimetable - newTimetable) local.deleteTimetable(old.uniqueSubtract(new))
local.saveTimetable((newTimetable - oldTimetable).map { item -> local.saveTimetable(new.uniqueSubtract(old).map { item ->
item.apply { item.apply {
oldTimetable.singleOrNull { this.start == it.start }?.let { old.singleOrNull { this.start == it.start }?.let {
return@map copy( return@map copy(
room = if (room.isEmpty()) it.room else room, room = if (room.isEmpty()) it.room else room
teacher = if (teacher.isEmpty()) it.teacher else teacher
) )
} }
} }

View File

@ -35,7 +35,7 @@ class SyncWorker @AssistedInject constructor(
override fun createWork(): Single<Result> { override fun createWork(): Single<Result> {
Timber.i("SyncWorker is starting") Timber.i("SyncWorker is starting")
return studentRepository.isStudentSaved() return studentRepository.isCurrentStudentSet()
.filter { true } .filter { true }
.flatMap { studentRepository.getCurrentStudent().toMaybe() } .flatMap { studentRepository.getCurrentStudent().toMaybe() }
.flatMapCompletable { student -> .flatMapCompletable { student ->

View File

@ -15,8 +15,7 @@ import io.github.wulkanowy.data.repositories.grade.GradeRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU import io.github.wulkanowy.ui.modules.main.MainView.MenuView
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.getCompatColor
import io.reactivex.Completable import io.reactivex.Completable
import javax.inject.Inject import javax.inject.Inject
@ -48,8 +47,8 @@ class GradeWork @Inject constructor(
.setDefaults(DEFAULT_ALL) .setDefaults(DEFAULT_ALL)
.setColor(context.getCompatColor(R.color.colorPrimary)) .setColor(context.getCompatColor(R.color.colorPrimary))
.setContentIntent( .setContentIntent(
PendingIntent.getActivity(context, 0, PendingIntent.getActivity(context, MenuView.GRADE.id,
MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU, MainView.MenuView.GRADE), FLAG_UPDATE_CURRENT)) MainActivity.getStartIntent(context, MenuView.GRADE, true), FLAG_UPDATE_CURRENT))
.setStyle(NotificationCompat.InboxStyle().run { .setStyle(NotificationCompat.InboxStyle().run {
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size)) setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size))
grades.forEach { addLine("${it.subject}: ${it.entry}") } grades.forEach { addLine("${it.subject}: ${it.entry}") }

View File

@ -15,8 +15,7 @@ import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU import io.github.wulkanowy.ui.modules.main.MainView.MenuView
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.getCompatColor
import io.reactivex.Completable import io.reactivex.Completable
import javax.inject.Inject import javax.inject.Inject
@ -48,9 +47,8 @@ class LuckyNumberWork @Inject constructor(
.setPriority(PRIORITY_HIGH) .setPriority(PRIORITY_HIGH)
.setColor(context.getCompatColor(R.color.colorPrimary)) .setColor(context.getCompatColor(R.color.colorPrimary))
.setContentIntent( .setContentIntent(
PendingIntent.getActivity(context, MainView.MenuView.MESSAGE.id, PendingIntent.getActivity(context, MenuView.MESSAGE.id,
MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU, MainView.MenuView.LUCKY_NUMBER) MainActivity.getStartIntent(context, MenuView.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT))
, FLAG_UPDATE_CURRENT))
.build()) .build())
} }
} }

View File

@ -16,8 +16,7 @@ import io.github.wulkanowy.data.repositories.message.MessageRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU import io.github.wulkanowy.ui.modules.main.MainView.MenuView
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.getCompatColor
import io.reactivex.Completable import io.reactivex.Completable
import javax.inject.Inject import javax.inject.Inject
@ -49,8 +48,8 @@ class MessageWork @Inject constructor(
.setPriority(PRIORITY_HIGH) .setPriority(PRIORITY_HIGH)
.setColor(context.getCompatColor(R.color.colorPrimary)) .setColor(context.getCompatColor(R.color.colorPrimary))
.setContentIntent( .setContentIntent(
PendingIntent.getActivity(context, MainView.MenuView.MESSAGE.id, MainActivity.getStartIntent(context) PendingIntent.getActivity(context, MenuView.MESSAGE.id,
.putExtra(EXTRA_START_MENU, MainView.MenuView.MESSAGE), FLAG_UPDATE_CURRENT) MainActivity.getStartIntent(context, MenuView.MESSAGE, true), FLAG_UPDATE_CURRENT)
) )
.setStyle(NotificationCompat.InboxStyle().run { .setStyle(NotificationCompat.InboxStyle().run {
setSummaryText(context.resources.getQuantityString(R.plurals.message_number_item, messages.size, messages.size)) setSummaryText(context.resources.getQuantityString(R.plurals.message_number_item, messages.size, messages.size))

View File

@ -15,8 +15,7 @@ import io.github.wulkanowy.data.repositories.note.NoteRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU import io.github.wulkanowy.ui.modules.main.MainView.MenuView
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.getCompatColor
import io.reactivex.Completable import io.reactivex.Completable
import javax.inject.Inject import javax.inject.Inject
@ -48,9 +47,8 @@ class NoteWork @Inject constructor(
.setPriority(PRIORITY_HIGH) .setPriority(PRIORITY_HIGH)
.setColor(context.getCompatColor(R.color.colorPrimary)) .setColor(context.getCompatColor(R.color.colorPrimary))
.setContentIntent( .setContentIntent(
PendingIntent.getActivity(context, MainView.MenuView.NOTE.id, PendingIntent.getActivity(context, MenuView.NOTE.id,
MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU, MainView.MenuView.NOTE) MainActivity.getStartIntent(context, MenuView.NOTE, true), FLAG_UPDATE_CURRENT))
, FLAG_UPDATE_CURRENT))
.setStyle(NotificationCompat.InboxStyle().run { .setStyle(NotificationCompat.InboxStyle().run {
setSummaryText(context.resources.getQuantityString(R.plurals.note_number_item, notes.size, notes.size)) setSummaryText(context.resources.getQuantityString(R.plurals.note_number_item, notes.size, notes.size))
notes.forEach { addLine("${it.teacher}: ${it.category}") } notes.forEach { addLine("${it.teacher}: ${it.category}") }

View File

@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.base
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -25,7 +26,7 @@ abstract class BaseActivity : AppCompatActivity(), BaseView, HasSupportFragmentI
@Inject @Inject
lateinit var themeManager: ThemeManager lateinit var themeManager: ThemeManager
protected lateinit var messageContainer: View protected var messageContainer: View? = null
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this) AndroidInjection.inject(this)
@ -36,13 +37,18 @@ abstract class BaseActivity : AppCompatActivity(), BaseView, HasSupportFragmentI
} }
override fun showError(text: String, error: Throwable) { override fun showError(text: String, error: Throwable) {
Snackbar.make(messageContainer, text, LENGTH_LONG).setAction(R.string.all_details) { if (messageContainer != null) {
ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString()) Snackbar.make(messageContainer!!, text, LENGTH_LONG)
}.show() .setAction(R.string.all_details) {
ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString())
}
.show()
} else showMessage(text)
} }
override fun showMessage(text: String) { override fun showMessage(text: String) {
Snackbar.make(messageContainer, text, LENGTH_LONG).show() if (messageContainer != null) Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
else Toast.makeText(this, text, Toast.LENGTH_LONG).show()
} }
override fun onDestroy() { override fun onDestroy() {

View File

@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.base
import android.view.View import android.view.View
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import io.github.wulkanowy.R import io.github.wulkanowy.R
@ -10,16 +11,22 @@ abstract class BaseFragment : DaggerFragment(), BaseView {
protected var messageContainer: View? = null protected var messageContainer: View? = null
override fun showError(text: String, error: Throwable) { override fun showError(text: String, error: Throwable) {
if (messageContainer == null) (activity as? BaseActivity)?.showError(text, error) if (messageContainer != null) {
else messageContainer?.also { Snackbar.make(messageContainer!!, text, LENGTH_LONG)
Snackbar.make(it, text, Snackbar.LENGTH_LONG).setAction(R.string.all_details) { .setAction(R.string.all_details) {
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) if (isAdded) ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
}.show() }
.show()
} else {
(activity as? BaseActivity)?.showError(text, error)
} }
} }
override fun showMessage(text: String) { override fun showMessage(text: String) {
if (messageContainer == null) (activity as? BaseActivity)?.showMessage(text) if (messageContainer != null) {
else messageContainer?.also { Snackbar.make(it, text, Snackbar.LENGTH_LONG).show() } Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
} else {
(activity as? BaseActivity)?.showMessage(text)
}
} }
} }

View File

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

View File

@ -12,6 +12,7 @@ import io.github.wulkanowy.BuildConfig
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.openInternetBrowser
import io.github.wulkanowy.utils.withOnExtraListener import io.github.wulkanowy.utils.withOnExtraListener
import javax.inject.Inject import javax.inject.Inject
@ -57,11 +58,11 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
} }
override fun openDiscordInviteView() { override fun openDiscordInviteView() {
startActivity(Intent.parseUri("https://discord.gg/vccAQBr", 0)) context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
} }
override fun openHomepageWebView() { override fun openHomepageWebView() {
startActivity(Intent.parseUri("https://wulkanowy.github.io/", 0)) context?.openInternetBrowser("https://wulkanowy.github.io/", ::showMessage)
} }
override fun openEmailClientView() { override fun openEmailClientView() {
@ -80,7 +81,7 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
if (intent.resolveActivity(it.packageManager) != null) { if (intent.resolveActivity(it.packageManager) != null) {
startActivity(Intent.createChooser(intent, getString(R.string.about_feedback))) startActivity(Intent.createChooser(intent, getString(R.string.about_feedback)))
} else { } else {
startActivity(Intent.parseUri("https://github.com/wulkanowy/wulkanowy/issues", 0)) it.openInternetBrowser("https://github.com/wulkanowy/wulkanowy/issues", ::showMessage)
} }
} }
} }

View File

@ -15,7 +15,6 @@ import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.R import io.github.wulkanowy.R
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.setOnItemClickListener import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.dialog_account.* import kotlinx.android.synthetic.main.dialog_account.*
import javax.inject.Inject import javax.inject.Inject
@ -97,11 +96,8 @@ class AccountDialog : DaggerAppCompatDialogFragment(), AccountView {
} }
} }
override fun recreateView() { override fun recreateMainView() {
activity?.also { activity?.recreate()
startActivity(MainActivity.getStartIntent(it))
it.finish()
}
} }
override fun onDestroy() { override fun onDestroy() {

View File

@ -54,7 +54,7 @@ class AccountPresenter @Inject constructor(
openClearLoginView() openClearLoginView()
} else { } else {
Timber.i("Logout result: Switch to another student") Timber.i("Logout result: Switch to another student")
recreateView() recreateMainView()
} }
} }
}, { }, {
@ -73,9 +73,10 @@ class AccountPresenter @Inject constructor(
disposable.add(studentRepository.switchStudent(item.student) disposable.add(studentRepository.switchStudent(item.student)
.subscribeOn(schedulers.backgroundThread) .subscribeOn(schedulers.backgroundThread)
.observeOn(schedulers.mainThread) .observeOn(schedulers.mainThread)
.doFinally { view?.dismissView() }
.subscribe({ .subscribe({
Timber.i("Change a student result: Success") Timber.i("Change a student result: Success")
view?.recreateView() view?.recreateMainView()
}, { }, {
Timber.i("Change a student result: An exception occurred") Timber.i("Change a student result: An exception occurred")
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -16,6 +16,6 @@ interface AccountView : BaseView {
fun openClearLoginView() fun openClearLoginView()
fun recreateView() fun recreateMainView()
} }

View File

@ -103,7 +103,7 @@ class AttendanceFragment : BaseSessionFragment(), AttendanceView, MainView.MainC
} }
override fun onFragmentReselected() { override fun onFragmentReselected() {
presenter.onViewReselected() if (::presenter.isInitialized) presenter.onViewReselected()
} }
override fun popView() { override fun popView() {

View File

@ -88,7 +88,7 @@ class ExamFragment : BaseSessionFragment(), ExamView, MainView.MainChildView, Ma
} }
override fun onFragmentReselected() { override fun onFragmentReselected() {
presenter.onViewReselected() if (::presenter.isInitialized) presenter.onViewReselected()
} }
override fun showEmpty(show: Boolean) { override fun showEmpty(show: Boolean) {

View File

@ -88,7 +88,7 @@ class GradeFragment : BaseSessionFragment(), GradeView, MainView.MainChildView,
} }
override fun onFragmentReselected() { override fun onFragmentReselected() {
presenter.onViewReselected() if (::presenter.isInitialized) presenter.onViewReselected()
} }
override fun showContent(show: Boolean) { override fun showContent(show: Boolean) {

View File

@ -1,7 +1,6 @@
package io.github.wulkanowy.ui.modules.login.form package io.github.wulkanowy.ui.modules.login.form
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -17,6 +16,7 @@ import io.github.wulkanowy.data.db.entities.Student
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.utils.hideSoftInput import io.github.wulkanowy.utils.hideSoftInput
import io.github.wulkanowy.utils.openInternetBrowser
import io.github.wulkanowy.utils.setOnItemSelectedListener import io.github.wulkanowy.utils.setOnItemSelectedListener
import io.github.wulkanowy.utils.setOnTextChangedListener import io.github.wulkanowy.utils.setOnTextChangedListener
import io.github.wulkanowy.utils.showSoftInput import io.github.wulkanowy.utils.showSoftInput
@ -145,7 +145,7 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
} }
override fun openPrivacyPolicyPage() { override fun openPrivacyPolicyPage() {
startActivity(Intent.parseUri("https://wulkanowy.github.io/polityka-prywatnosci.html", 0)) context?.openInternetBrowser("https://wulkanowy.github.io/polityka-prywatnosci.html", ::showMessage)
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -1,7 +1,5 @@
package io.github.wulkanowy.ui.modules.login.studentselect package io.github.wulkanowy.ui.modules.login.studentselect
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -58,10 +56,7 @@ class LoginStudentSelectFragment : BaseFragment(), LoginStudentSelectView {
} }
override fun openMainView() { override fun openMainView() {
activity?.let { activity?.let { startActivity(MainActivity.getStartIntent(context = it, clear = true)) }
startActivity(MainActivity.getStartIntent(it)
.apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) })
}
} }
override fun showProgress(show: Boolean) { override fun showProgress(show: Boolean) {

View File

@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.luckynumberwidget
import android.annotation.TargetApi import android.annotation.TargetApi
import android.app.PendingIntent import android.app.PendingIntent
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_DELETED import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_DELETED
import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED
@ -26,8 +27,7 @@ import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
import io.github.wulkanowy.data.repositories.semester.SemesterRepository import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU import io.github.wulkanowy.ui.modules.main.MainView.MenuView
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.reactivex.Maybe import io.reactivex.Maybe
import timber.log.Timber import timber.log.Timber
@ -68,15 +68,14 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
} }
private fun onUpdate(context: Context, intent: Intent) { private fun onUpdate(context: Context, intent: Intent) {
intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS).forEach { appWidgetId -> intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS)?.forEach { appWidgetId ->
RemoteViews(context.packageName, R.layout.widget_luckynumber).apply { RemoteViews(context.packageName, R.layout.widget_luckynumber).apply {
setTextViewText(R.id.luckyNumberWidgetNumber, setTextViewText(R.id.luckyNumberWidgetNumber,
getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)?.luckyNumber?.toString() ?: "#" getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)?.luckyNumber?.toString() ?: "#"
) )
setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, setOnClickPendingIntent(R.id.luckyNumberWidgetContainer,
PendingIntent.getActivity(context, MainView.MenuView.LUCKY_NUMBER.id, MainActivity.getStartIntent(context).apply { PendingIntent.getActivity(context, MenuView.LUCKY_NUMBER.id,
putExtra(EXTRA_START_MENU, MainView.MenuView.LUCKY_NUMBER) MainActivity.getStartIntent(context, MenuView.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT))
}, PendingIntent.FLAG_UPDATE_CURRENT))
}.also { }.also {
setStyles(it, intent) setStyles(it, intent)
appWidgetManager.updateAppWidget(appWidgetId, it) appWidgetManager.updateAppWidget(appWidgetId, it)
@ -101,11 +100,12 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
when { when {
student != null -> Maybe.just(student) student != null -> Maybe.just(student)
studentId != 0L -> { studentId != 0L -> {
studentRepository.getCurrentStudent(false) studentRepository.isCurrentStudentSet()
.toMaybe() .filter { true }
.flatMap { studentRepository.getCurrentStudent(false).toMaybe() }
.doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) } .doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) }
} }
else -> null else -> Maybe.empty()
} }
} }
} }

View File

@ -5,7 +5,6 @@ import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
@ -46,7 +45,13 @@ class MainActivity : BaseActivity(), MainView {
companion object { companion object {
const val EXTRA_START_MENU = "extraStartMenu" const val EXTRA_START_MENU = "extraStartMenu"
fun getStartIntent(context: Context) = Intent(context, MainActivity::class.java) fun getStartIntent(context: Context, startMenu: MainView.MenuView? = null, clear: Boolean = false): Intent {
return Intent(context, MainActivity::class.java)
.apply {
if (clear) flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
startMenu?.let { putExtra(EXTRA_START_MENU, it) }
}
}
} }
override val isRootView: Boolean override val isRootView: Boolean
@ -91,7 +96,7 @@ class MainActivity : BaseActivity(), MainView {
override fun initView() { override fun initView() {
mainBottomNav.run { mainBottomNav.run {
addItems( addItems(
mutableListOf( listOf(
AHBottomNavigationItem(R.string.grade_title, R.drawable.ic_menu_main_grade_26dp, 0), AHBottomNavigationItem(R.string.grade_title, R.drawable.ic_menu_main_grade_26dp, 0),
AHBottomNavigationItem(R.string.attendance_title, R.drawable.ic_menu_main_attendance_24dp, 0), AHBottomNavigationItem(R.string.attendance_title, R.drawable.ic_menu_main_attendance_24dp, 0),
AHBottomNavigationItem(R.string.exam_title, R.drawable.ic_menu_main_exam_24dp, 0), AHBottomNavigationItem(R.string.exam_title, R.drawable.ic_menu_main_exam_24dp, 0),
@ -159,9 +164,7 @@ class MainActivity : BaseActivity(), MainView {
} }
override fun notifyMenuViewReselected() { override fun notifyMenuViewReselected() {
Handler().postDelayed({ (navController.currentStack?.getOrNull(0) as? MainView.MainChildView)?.onFragmentReselected()
(navController.currentStack?.get(0) as? MainView.MainChildView)?.onFragmentReselected()
}, 250)
} }
fun showDialogFragment(dialog: DialogFragment) { fun showDialogFragment(dialog: DialogFragment) {
@ -188,6 +191,7 @@ class MainActivity : BaseActivity(), MainView {
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
navController.onSaveInstanceState(outState) navController.onSaveInstanceState(outState)
intent.removeExtra(EXTRA_START_MENU)
} }
override fun onDestroy() { override fun onDestroy() {

View File

@ -27,7 +27,9 @@ class MessagePreviewFragment : BaseSessionFragment(), MessagePreviewView, MainVi
lateinit var presenter: MessagePreviewPresenter lateinit var presenter: MessagePreviewPresenter
private var menuReplyButton: MenuItem? = null private var menuReplyButton: MenuItem? = null
private var menuForwardButton: MenuItem? = null private var menuForwardButton: MenuItem? = null
private var menuDeleteButton: MenuItem? = null private var menuDeleteButton: MenuItem? = null
override val titleStringId: Int override val titleStringId: Int
@ -42,9 +44,9 @@ class MessagePreviewFragment : BaseSessionFragment(), MessagePreviewView, MainVi
companion object { companion object {
const val MESSAGE_ID_KEY = "message_id" const val MESSAGE_ID_KEY = "message_id"
fun newInstance(messageId: Int?): MessagePreviewFragment { fun newInstance(messageId: Long): MessagePreviewFragment {
return MessagePreviewFragment().apply { return MessagePreviewFragment().apply {
arguments = Bundle().apply { putInt(MESSAGE_ID_KEY, messageId ?: 0) } arguments = Bundle().apply { putLong(MESSAGE_ID_KEY, messageId) }
} }
} }
} }
@ -61,7 +63,7 @@ class MessagePreviewFragment : BaseSessionFragment(), MessagePreviewView, MainVi
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
messageContainer = messagePreviewContainer messageContainer = messagePreviewContainer
presenter.onAttachView(this, (savedInstanceState ?: arguments)?.getInt(MESSAGE_ID_KEY) ?: 0) presenter.onAttachView(this, (savedInstanceState ?: arguments)?.getLong(MESSAGE_ID_KEY) ?: 0L)
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
@ -145,7 +147,7 @@ class MessagePreviewFragment : BaseSessionFragment(), MessagePreviewView, MainVi
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putInt(MESSAGE_ID_KEY, presenter.messageId) outState.putLong(MESSAGE_ID_KEY, presenter.messageId)
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -20,16 +20,16 @@ class MessagePreviewPresenter @Inject constructor(
private val analytics: FirebaseAnalyticsHelper private val analytics: FirebaseAnalyticsHelper
) : BaseSessionPresenter<MessagePreviewView>(errorHandler) { ) : BaseSessionPresenter<MessagePreviewView>(errorHandler) {
var messageId: Int = 0 var messageId = 0L
private var message: Message? = null private var message: Message? = null
fun onAttachView(view: MessagePreviewView, id: Int) { fun onAttachView(view: MessagePreviewView, id: Long) {
super.onAttachView(view) super.onAttachView(view)
loadData(id) loadData(id)
} }
private fun loadData(id: Int) { private fun loadData(id: Long) {
Timber.i("Loading message $id preview started") Timber.i("Loading message $id preview started")
messageId = id messageId = id
disposable.apply { disposable.apply {

View File

@ -56,7 +56,7 @@ class MessageTabFragment : BaseSessionFragment(), MessageTabView {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
messageContainer = messageTabRecycler messageContainer = messageTabRecycler
presenter.onAttachView(this, MessageFolder.valueOf( presenter.onAttachView(this, MessageFolder.valueOf(
(savedInstanceState ?: arguments)?.getString(MessageTabFragment.MESSAGE_TAB_FOLDER_ID).orEmpty() (savedInstanceState ?: arguments)?.getString(MESSAGE_TAB_FOLDER_ID).orEmpty()
)) ))
} }
@ -106,7 +106,7 @@ class MessageTabFragment : BaseSessionFragment(), MessageTabView {
messageTabSwipe.isRefreshing = show messageTabSwipe.isRefreshing = show
} }
override fun openMessage(messageId: Int?) { override fun openMessage(messageId: Long) {
(activity as? MainActivity)?.pushView(MessagePreviewFragment.newInstance(messageId)) (activity as? MainActivity)?.pushView(MessagePreviewFragment.newInstance(messageId))
} }
@ -124,7 +124,7 @@ class MessageTabFragment : BaseSessionFragment(), MessageTabView {
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putString(MessageTabFragment.MESSAGE_TAB_FOLDER_ID, presenter.folder.name) outState.putString(MESSAGE_TAB_FOLDER_ID, presenter.folder.name)
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -44,9 +44,9 @@ class MessageTabPresenter @Inject constructor(
fun onMessageItemSelected(item: AbstractFlexibleItem<*>) { fun onMessageItemSelected(item: AbstractFlexibleItem<*>) {
if (item is MessageItem) { if (item is MessageItem) {
Timber.i("Select message ${item.message.realId} item") Timber.i("Select message ${item.message.id} item")
view?.run { view?.run {
openMessage(item.message.realId) openMessage(item.message.id)
if (item.message.unread) { if (item.message.unread) {
item.message.unread = false item.message.unread = false
updateItem(item) updateItem(item)
@ -90,13 +90,13 @@ class MessageTabPresenter @Inject constructor(
} }
private fun updateMessage(message: Message) { private fun updateMessage(message: Message) {
Timber.i("Attempt to update message ${message.realId}") Timber.i("Attempt to update message ${message.id}")
disposable.add(messageRepository.updateMessage(message) disposable.add(messageRepository.updateMessage(message)
.subscribeOn(schedulers.backgroundThread) .subscribeOn(schedulers.backgroundThread)
.observeOn(schedulers.mainThread) .observeOn(schedulers.mainThread)
.subscribe({ Timber.d("Update message ${message.realId} result: Success") }) .subscribe({ Timber.d("Update message ${message.id} result: Success") })
{ error -> { error ->
Timber.i("Update message ${message.realId} result: An exception occurred") Timber.i("Update message ${message.id} result: An exception occurred")
errorHandler.dispatch(error) errorHandler.dispatch(error)
}) })
} }

View File

@ -28,7 +28,7 @@ interface MessageTabView : BaseSessionView {
fun showRefresh(show: Boolean) fun showRefresh(show: Boolean)
fun openMessage(messageId: Int?) fun openMessage(messageId: Long)
fun notifyParentDataLoaded() fun notifyParentDataLoaded()
} }

View File

@ -104,7 +104,7 @@ class MoreFragment : BaseFragment(), MoreView, MainView.TitledView, MainView.Mai
} }
override fun onFragmentReselected() { override fun onFragmentReselected() {
presenter.onViewReselected() if (::presenter.isInitialized) presenter.onViewReselected()
} }
override fun updateData(data: List<MoreItem>) { override fun updateData(data: List<MoreItem>) {

View File

@ -14,7 +14,7 @@ class SplashPresenter @Inject constructor(
override fun onAttachView(view: SplashView) { override fun onAttachView(view: SplashView) {
super.onAttachView(view) super.onAttachView(view)
disposable.add(studentRepository.isStudentSaved() disposable.add(studentRepository.isCurrentStudentSet()
.subscribeOn(schedulers.backgroundThread) .subscribeOn(schedulers.backgroundThread)
.observeOn(schedulers.mainThread) .observeOn(schedulers.mainThread)
.subscribe({ .subscribe({

View File

@ -110,7 +110,7 @@ class TimetableFragment : BaseSessionFragment(), TimetableView, MainView.MainChi
} }
override fun onFragmentReselected() { override fun onFragmentReselected() {
presenter.onViewReselected() if (::presenter.isInitialized) presenter.onViewReselected()
} }
override fun popView() { override fun popView() {

View File

@ -20,8 +20,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.services.widgets.TimetableWidgetService import io.github.wulkanowy.services.widgets.TimetableWidgetService
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU import io.github.wulkanowy.ui.modules.main.MainView.MenuView
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.nextOrSameSchoolDay import io.github.wulkanowy.utils.nextOrSameSchoolDay
@ -131,9 +130,8 @@ class TimetableWidgetProvider : BroadcastReceiver() {
putExtra(EXTRA_FROM_PROVIDER, true) putExtra(EXTRA_FROM_PROVIDER, true)
}, FLAG_UPDATE_CURRENT)) }, FLAG_UPDATE_CURRENT))
setPendingIntentTemplate(R.id.timetableWidgetList, setPendingIntentTemplate(R.id.timetableWidgetList,
PendingIntent.getActivity(context, 1, MainActivity.getStartIntent(context).apply { PendingIntent.getActivity(context, MenuView.TIMETABLE.id,
putExtra(EXTRA_START_MENU, MainView.MenuView.TIMETABLE) MainActivity.getStartIntent(context, MenuView.TIMETABLE, true), FLAG_UPDATE_CURRENT))
}, FLAG_UPDATE_CURRENT))
}.also { }.also {
sharedPref.putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true) sharedPref.putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true)
appWidgetManager.apply { appWidgetManager.apply {
@ -163,11 +161,12 @@ class TimetableWidgetProvider : BroadcastReceiver() {
when { when {
student != null -> Maybe.just(student) student != null -> Maybe.just(student)
studentId != 0L -> { studentId != 0L -> {
studentRepository.getCurrentStudent(false) studentRepository.isCurrentStudentSet()
.toMaybe() .filter { true }
.flatMap { studentRepository.getCurrentStudent(false).toMaybe() }
.doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) } .doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) }
} }
else -> null else -> Maybe.empty()
} }
} }
} }

View File

@ -4,7 +4,6 @@ import android.app.Activity
import android.content.Context.INPUT_METHOD_SERVICE import android.content.Context.INPUT_METHOD_SERVICE
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
fun Activity.showSoftInput() { fun Activity.showSoftInput() {
(getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager?)?.run { (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager?)?.run {
if (currentFocus != null) showSoftInput(currentFocus, 0) if (currentFocus != null) showSoftInput(currentFocus, 0)

View File

@ -1,6 +1,7 @@
package io.github.wulkanowy.utils package io.github.wulkanowy.utils
import android.content.Context import android.content.Context
import android.content.Intent
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.annotation.ColorRes import androidx.annotation.ColorRes
@ -18,3 +19,10 @@ fun Context.getThemeAttrColor(@AttrRes colorAttr: Int): Int {
@ColorInt @ColorInt
fun Context.getCompatColor(@ColorRes colorRes: Int) = ContextCompat.getColor(this, colorRes) fun Context.getCompatColor(@ColorRes colorRes: Int) = ContextCompat.getColor(this, colorRes)
fun Context.openInternetBrowser(uri: String, onActivityNotFound: (uri: String) -> Unit) {
Intent.parseUri(uri, 0).let {
if (it.resolveActivity(packageManager) != null) startActivity(it)
else onActivityNotFound(uri)
}
}

View File

@ -0,0 +1,9 @@
package io.github.wulkanowy.utils
infix fun <T> List<T>.uniqueSubtract(other: List<T>): List<T> {
val list = toMutableList()
other.forEach {
list.remove(it)
}
return list.toList()
}

View File

@ -1,13 +1,10 @@
Wersja 0.8.0 Wersja 0.8.3
Uwaga! Po tej aktualizacji wymagane jest ponowne przypięcie widżetu planu lekcji! Naprawiliśmy:
- rzadkie problemy z wczytywaniem treści wiadomości
- rzadkie problemy z wyświetlaniem poprawnego nauczyciela przy zastępstwach
Dodaliśmy: Zmieniliśmy:
- możliwość przesyłania dalej i usuwania wiadomości - tekst wskazówki przy wprowadzaniu symbolu w formularzu logowania
- możliwość zmiany ucznia w widżecie
- opcję liczenia średniej ocen z całego roku
- tryb AMOLED
- logowanie wielu uczniów jednocześnie
- widżet szczęśliwego numerka
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.8.0 Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases

View File

@ -5,6 +5,7 @@
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorPrimary</item> <item name="colorAccent">@color/colorPrimary</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item> <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="android:windowBackground">@color/bottom_nav_background</item>
<item name="bottomNavBackground">@color/bottom_nav_background</item> <item name="bottomNavBackground">@color/bottom_nav_background</item>
<item name="android:navigationBarColor" tools:targetApi="21">@color/bottom_nav_background</item> <item name="android:navigationBarColor" tools:targetApi="21">@color/bottom_nav_background</item>
<item name="dividerColor">@color/divider_inverse</item> <item name="dividerColor">@color/divider_inverse</item>

View File

@ -21,7 +21,7 @@
<!--Login--> <!--Login-->
<string name="login_header_default">Zaloguj się za pomocą konta ucznia lub rodzica</string> <string name="login_header_default">Zaloguj się za pomocą konta ucznia lub rodzica</string>
<string name="login_header_symbol">Podaj symbol dziennika VULCAN</string> <string name="login_header_symbol">Podaj symbol</string>
<string name="login_nickname_hint">Email lub nick</string> <string name="login_nickname_hint">Email lub nick</string>
<string name="login_password_hint">Hasło</string> <string name="login_password_hint">Hasło</string>
<string name="login_host_hint">Dziennik</string> <string name="login_host_hint">Dziennik</string>
@ -32,7 +32,7 @@
<string name="login_incorrect_symbol">Nie znaleziono ucznia. Sprawdź symbol</string> <string name="login_incorrect_symbol">Nie znaleziono ucznia. Sprawdź symbol</string>
<string name="login_field_required">To pole jest wymagane</string> <string name="login_field_required">To pole jest wymagane</string>
<string name="login_duplicate_student">Wybrany uczeń jest już zalogowany</string> <string name="login_duplicate_student">Wybrany uczeń jest już zalogowany</string>
<string name="login_symbol_helper">Symbol znajduje się na stronie dziennika w zakładce Dostęp Mobilny</string> <string name="login_symbol_helper">Symbol znajdziesz na stronie dziennika w Uczeń -> Dostęp Mobilny -> Zarejestruj urządzenie mobilne</string>
<string name="login_select_student">Wybierz uczniów do zalogowania w aplikacji</string> <string name="login_select_student">Wybierz uczniów do zalogowania w aplikacji</string>
<string name="login_privacy_policy">Polityka prywatności</string> <string name="login_privacy_policy">Polityka prywatności</string>

View File

@ -21,7 +21,7 @@
<!--Login--> <!--Login-->
<string name="login_header_default">Sign in with the student or parent account</string> <string name="login_header_default">Sign in with the student or parent account</string>
<string name="login_header_symbol">Enter the VULCAN diary symbol</string> <string name="login_header_symbol">Enter the symbol</string>
<string name="login_nickname_hint">Email or nick</string> <string name="login_nickname_hint">Email or nick</string>
<string name="login_password_hint">Password</string> <string name="login_password_hint">Password</string>
<string name="login_host_hint">Register</string> <string name="login_host_hint">Register</string>
@ -32,7 +32,7 @@
<string name="login_incorrect_symbol">Student not found. Check the symbol</string> <string name="login_incorrect_symbol">Student not found. Check the symbol</string>
<string name="login_field_required">This field is required</string> <string name="login_field_required">This field is required</string>
<string name="login_duplicate_student">The selected student is already logged in</string> <string name="login_duplicate_student">The selected student is already logged in</string>
<string name="login_symbol_helper">The symbol is located on the register page in the Mobile Access tab</string> <string name="login_symbol_helper">The symbol can be found on the register page in Uczeń -> Dostęp Mobilny -> Zarejestruj urządzenie mobilne</string>
<string name="login_select_student">Select students to log in to the application</string> <string name="login_select_student">Select students to log in to the application</string>
<string name="login_privacy_policy">Privacy policy</string> <string name="login_privacy_policy">Privacy policy</string>

View File

@ -32,14 +32,14 @@ class SplashPresenterTest {
@Test @Test
fun testOpenLoginView() { fun testOpenLoginView() {
doReturn(Single.just(false)).`when`(studentRepository).isStudentSaved() doReturn(Single.just(false)).`when`(studentRepository).isCurrentStudentSet()
presenter.onAttachView(splashView) presenter.onAttachView(splashView)
verify(splashView).openLoginView() verify(splashView).openLoginView()
} }
@Test @Test
fun testMainMainView() { fun testMainMainView() {
doReturn(Single.just(true)).`when`(studentRepository).isStudentSaved() doReturn(Single.just(true)).`when`(studentRepository).isCurrentStudentSet()
presenter.onAttachView(splashView) presenter.onAttachView(splashView)
verify(splashView).openMainView() verify(splashView).openMainView()
} }

View File

@ -9,7 +9,7 @@ buildscript {
} }
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.android.tools.build:gradle:3.4.0' classpath 'com.android.tools.build:gradle:3.4.1'
classpath 'com.google.gms:google-services:4.2.0' classpath 'com.google.gms:google-services:4.2.0'
classpath "io.fabric.tools:gradle:1.28.1" classpath "io.fabric.tools:gradle:1.28.1"
classpath "com.github.triplet.gradle:play-publisher:2.2.0" classpath "com.github.triplet.gradle:play-publisher:2.2.0"