From 040857ba20ce34aef3aa5cbda7f59db172f5a385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 19 Mar 2019 13:23:52 +0100 Subject: [PATCH 01/33] Change grade weightValue type to double (#285) --- .travis.yml | 6 ++-- app/build.gradle | 2 +- .../data/repositories/grade/GradeLocalTest.kt | 6 ++-- .../repositories/grade/GradeRepositoryTest.kt | 22 ++++++------ .../grade/TestGradeEntityCreator.kt | 4 +-- .../github/wulkanowy/data/db/AppDatabase.kt | 6 ++-- .../wulkanowy/data/db/entities/Grade.kt | 2 +- .../data/db/migrations/Migration11.kt | 34 +++++++++++++++++++ .../wulkanowy/utils/GradeExtensionTest.kt | 24 ++++++------- 9 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt diff --git a/.travis.yml b/.travis.yml index e1d86ee3..8920018e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,9 +11,9 @@ cache: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ -#branches: -# only: -# - master +branches: + only: + - master android: licenses: diff --git a/app/build.gradle b/app/build.gradle index b18a22cc..f7fd82c0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('io.github.wulkanowy:api:0.7.0') { exclude module: "threetenbp" } + implementation('com.github.wulkanowy:api:0aea843800') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt index e50a52ff..36238f1b 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt @@ -34,9 +34,9 @@ class GradeLocalTest { @Test fun saveAndReadTest() { gradeLocal.saveGrades(listOf( - createGradeLocal(5, 3, LocalDate.of(2018, 9, 10), "", 1), - createGradeLocal(4, 4, LocalDate.of(2019, 2, 27), "", 2), - createGradeLocal(3, 5, LocalDate.of(2019, 2, 28), "", 2) + createGradeLocal(5, 3.0, LocalDate.of(2018, 9, 10), "", 1), + createGradeLocal(4, 4.0, LocalDate.of(2019, 2, 27), "", 2), + createGradeLocal(3, 5.0, LocalDate.of(2019, 2, 28), "", 2) )) val grades = gradeLocal diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt index 7da2d455..17e788fc 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt @@ -71,10 +71,10 @@ class GradeRepositoryTest { @Test fun markOlderThanRegisterDateAsRead() { every { mockApi.getGrades(1) } returns Single.just(listOf( - createGradeApi(5, 4, of(2019, 2, 25), "Ocena pojawiła się"), - createGradeApi(5, 4, of(2019, 2, 26), "przed zalogowanie w aplikacji"), - createGradeApi(5, 4, of(2019, 2, 27), "Ocena z dnia logowania"), - createGradeApi(5, 4, of(2019, 2, 28), "Ocena jeszcze nowsza") + createGradeApi(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"), + createGradeApi(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"), + createGradeApi(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"), + createGradeApi(5, 4.0, of(2019, 2, 28), "Ocena jeszcze nowsza") )) val grades = GradeRepository(settings, gradeLocal, gradeRemote) @@ -89,16 +89,16 @@ class GradeRepositoryTest { @Test fun mitigateOldGradesNotifications() { gradeLocal.saveGrades(listOf( - createGradeLocal(5, 3, of(2019, 2, 25), "Jedna ocena"), - createGradeLocal(4, 4, of(2019, 2, 26), "Druga"), - createGradeLocal(3, 5, of(2019, 2, 27), "Trzecia") + createGradeLocal(5, 3.0, of(2019, 2, 25), "Jedna ocena"), + createGradeLocal(4, 4.0, of(2019, 2, 26), "Druga"), + createGradeLocal(3, 5.0, of(2019, 2, 27), "Trzecia") )) every { mockApi.getGrades(1) } returns Single.just(listOf( - createGradeApi(5, 2, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"), - createGradeApi(4, 3, of(2019, 2, 26), "starszą niż ostatnia lokalnie"), - createGradeApi(3, 4, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"), - createGradeApi(2, 5, of(2019, 2, 28), "Ta jest już w ogóle nowa") + createGradeApi(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"), + createGradeApi(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"), + createGradeApi(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"), + createGradeApi(2, 5.0, of(2019, 2, 28), "Ta jest już w ogóle nowa") )) val grades = GradeRepository(settings, gradeLocal, gradeRemote) diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt index 485e5692..e0fd05a8 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt @@ -5,7 +5,7 @@ import org.threeten.bp.LocalDate import io.github.wulkanowy.api.grades.Grade as GradeRemote import io.github.wulkanowy.data.db.entities.Grade as GradeLocal -fun createGradeLocal(value: Int, weight: Int, date: LocalDate, desc: String, semesterId: Int = 1): GradeLocal { +fun createGradeLocal(value: Int, weight: Double, date: LocalDate, desc: String, semesterId: Int = 1): GradeLocal { return GradeLocal( semesterId = semesterId, studentId = 1, @@ -24,7 +24,7 @@ fun createGradeLocal(value: Int, weight: Int, date: LocalDate, desc: String, sem ) } -fun createGradeApi(value: Int, weight: Int, date: LocalDate, desc: String): GradeRemote { +fun createGradeApi(value: Int, weight: Double, date: LocalDate, desc: String): GradeRemote { return GradeRemote().apply { this.value = value this.weightValue = weight diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt index 1601c91a..4fefd9c9 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt @@ -41,6 +41,7 @@ import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Subject import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.migrations.Migration10 +import io.github.wulkanowy.data.db.migrations.Migration11 import io.github.wulkanowy.data.db.migrations.Migration2 import io.github.wulkanowy.data.db.migrations.Migration3 import io.github.wulkanowy.data.db.migrations.Migration4 @@ -79,7 +80,7 @@ import javax.inject.Singleton abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION_SCHEMA = 10 + const val VERSION_SCHEMA = 11 fun newInstance(context: Context): AppDatabase { return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database") @@ -95,7 +96,8 @@ abstract class AppDatabase : RoomDatabase() { Migration7(), Migration8(), Migration9(), - Migration10() + Migration10(), + Migration11() ) .build() } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt index fdf25c9e..1221a7aa 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt @@ -34,7 +34,7 @@ data class Grade( val weight: String, - val weightValue: Int, + val weightValue: Double, val date: LocalDate, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt new file mode 100644 index 00000000..cb437c0e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt @@ -0,0 +1,34 @@ +package io.github.wulkanowy.data.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration11 : Migration(10, 11) { + + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" + CREATE TABLE IF NOT EXISTS Grades_temp ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + is_read INTEGER NOT NULL, + is_notified INTEGER NOT NULL, + semester_id INTEGER NOT NULL, + student_id INTEGER NOT NULL, + subject TEXT NOT NULL, + entry TEXT NOT NULL, + value INTEGER NOT NULL, + modifier REAL NOT NULL, + comment TEXT NOT NULL, + color TEXT NOT NULL, + grade_symbol TEXT NOT NULL, + description TEXT NOT NULL, + weight TEXT NOT NULL, + weightValue REAL NOT NULL, + date INTEGER NOT NULL, + teacher TEXT NOT NULL + ) + """) + database.execSQL("INSERT INTO Grades_temp SELECT * FROM Grades") + database.execSQL("DROP TABLE Grades") + database.execSQL("ALTER TABLE Grades_temp RENAME TO Grades") + } +} diff --git a/app/src/test/java/io/github/wulkanowy/utils/GradeExtensionTest.kt b/app/src/test/java/io/github/wulkanowy/utils/GradeExtensionTest.kt index 12a086ed..3b1ab648 100644 --- a/app/src/test/java/io/github/wulkanowy/utils/GradeExtensionTest.kt +++ b/app/src/test/java/io/github/wulkanowy/utils/GradeExtensionTest.kt @@ -22,11 +22,11 @@ class GradeExtensionTest { @Test fun calcWeightedAverage() { assertEquals(3.47, listOf( - createGrade(5, 6, 0.33), - createGrade(5, 5, -0.33), - createGrade(4, 1, 0.0), - createGrade(1, 9, 0.5), - createGrade(0, 0, 0.0) + createGrade(5, 6.0, 0.33), + createGrade(5, 5.0, -0.33), + createGrade(4, 1.0, 0.0), + createGrade(1, 9.0, 0.5), + createGrade(0, .0, 0.0) ).calcAverage(), 0.005) } @@ -42,23 +42,23 @@ class GradeExtensionTest { @Test fun changeModifier_default() { - assertEquals(.33, createGrade(5, 0, .33).changeModifier(.0, .0).modifier, .0) - assertEquals(-.33, createGrade(5, 0, -.33).changeModifier(.0, .0).modifier, .0) + assertEquals(.33, createGrade(5, .0, .33).changeModifier(.0, .0).modifier, .0) + assertEquals(-.33, createGrade(5, .0, -.33).changeModifier(.0, .0).modifier, .0) } @Test fun changeModifier_plus() { - assertEquals(.33, createGrade(5, 0, .25).changeModifier(.33, .50).modifier, .0) - assertEquals(.25, createGrade(5, 0, .33).changeModifier(.25, .0).modifier, .0) + assertEquals(.33, createGrade(5, .0, .25).changeModifier(.33, .50).modifier, .0) + assertEquals(.25, createGrade(5, .0, .33).changeModifier(.25, .0).modifier, .0) } @Test fun changeModifier_minus() { - assertEquals(-.33, createGrade(5, 0, -.25).changeModifier(.25, .33).modifier, .0) - assertEquals(-.25, createGrade(5, 0, -.33).changeModifier(.0, .25).modifier, .0) + assertEquals(-.33, createGrade(5, .0, -.25).changeModifier(.25, .33).modifier, .0) + assertEquals(-.25, createGrade(5, .0, -.33).changeModifier(.0, .25).modifier, .0) } - private fun createGrade(value: Int, weightValue: Int = 0, modifier: Double = 0.25): Grade { + private fun createGrade(value: Int, weightValue: Double = .0, modifier: Double = 0.25): Grade { return Grade( semesterId = 1, studentId = 1, From 8db73e94596a1a269b088cfc1c0844bdb6bc688f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Tue, 19 Mar 2019 18:14:55 +0100 Subject: [PATCH 02/33] Fix the application finish after selecting an account (#286) --- app/src/main/AndroidManifest.xml | 8 +------- .../ui/modules/message/send/SendMessageActivity.kt | 4 ++++ .../ui/modules/message/send/SendMessagePresenter.kt | 5 +++++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 43b94805..352b6d2b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,18 +39,12 @@ android:name=".ui.modules.main.MainActivity" android:configChanges="orientation|screenSize" android:label="@string/main_title" - android:launchMode="singleTop" android:theme="@style/WulkanowyTheme.NoActionBar" /> - - + android:theme="@style/WulkanowyTheme.NoActionBar" /> = emptyList() From 575e244b3a82e2cccc60d2caa737df787b6cc7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Wed, 20 Mar 2019 20:45:26 +0100 Subject: [PATCH 03/33] Add swipe refresh to grade fragment (#287) --- .travis.yml | 1 + app/build.gradle | 2 +- .../ui/modules/grade/GradeFragment.kt | 21 +++++++++++++++++-- .../ui/modules/grade/GradePresenter.kt | 20 ++++++++++++++++-- .../wulkanowy/ui/modules/grade/GradeView.kt | 8 ++++++- app/src/main/res/layout/fragment_grade.xml | 16 +++++++++----- 6 files changed, 57 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8920018e..b3261931 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ cache: branches: only: - master + - 0.7.x android: licenses: diff --git a/app/build.gradle b/app/build.gradle index f7fd82c0..f581ba51 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('com.github.wulkanowy:api:0aea843800') { exclude module: "threetenbp" } + implementation('com.github.wulkanowy:api:bc60169383') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt index 8fdecda2..20d3fad7 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt @@ -29,6 +29,8 @@ class GradeFragment : BaseSessionFragment(), GradeView, MainView.MainChildView, @Inject lateinit var pagerAdapter: BaseFragmentPagerAdapter + private var semesterSwitchMenu: MenuItem? = null + companion object { private const val SAVED_SEMESTER_KEY = "CURRENT_SEMESTER" @@ -57,6 +59,8 @@ class GradeFragment : BaseSessionFragment(), GradeView, MainView.MainChildView, override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { inflater?.inflate(R.menu.action_menu_grade, menu) + semesterSwitchMenu = menu?.findItem(R.id.gradeMenuSemester) + presenter.onCreateMenu() } override fun initView() { @@ -75,6 +79,7 @@ class GradeFragment : BaseSessionFragment(), GradeView, MainView.MainChildView, setOnSelectPageListener { presenter.onPageSelected(it) } } gradeTabLayout.setupWithViewPager(gradeViewPager) + gradeSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } } override fun onOptionsItemSelected(item: MenuItem?): Boolean { @@ -95,8 +100,20 @@ class GradeFragment : BaseSessionFragment(), GradeView, MainView.MainChildView, gradeProgress.visibility = if (show) VISIBLE else INVISIBLE } - override fun showEmpty() { - gradeEmpty.visibility = VISIBLE + override fun showEmpty(show: Boolean) { + gradeEmpty.visibility = if (show) VISIBLE else INVISIBLE + } + + override fun showRefresh(show: Boolean) { + gradeSwipe.isRefreshing = show + } + + override fun showSemesterSwitch(show: Boolean) { + semesterSwitchMenu?.isVisible = show + } + + override fun enableSwipe(enable: Boolean) { + gradeSwipe.isEnabled = enable } override fun showSemesterDialog(selectedIndex: Int) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt index cc127a90..98eb2a9f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt @@ -33,11 +33,18 @@ class GradePresenter @Inject constructor( disposable.add(Completable.timer(150, MILLISECONDS, schedulers.mainThread) .subscribe { selectedIndex = savedIndex ?: 0 - view.initView() + view.run { + initView() + enableSwipe(false) + } loadData() }) } + fun onCreateMenu() { + if (semesters.isEmpty()) view?.showSemesterSwitch(false) + } + fun onViewReselected() { Timber.i("Grade view is reselected") view?.run { notifyChildParentReselected(currentPageIndex) } @@ -69,6 +76,7 @@ class GradePresenter @Inject constructor( view?.apply { showContent(true) showProgress(false) + showEmpty(false) loadedSemesterId[currentPageIndex] = semesterId } } @@ -77,6 +85,10 @@ class GradePresenter @Inject constructor( loadChild(index) } + fun onSwipeRefresh() { + loadData() + } + private fun loadData() { Timber.i("Loading grade data started") disposable.add(studentRepository.getCurrentStudent() @@ -89,17 +101,21 @@ class GradePresenter @Inject constructor( } .subscribeOn(schedulers.backgroundThread) .observeOn(schedulers.mainThread) + .doFinally { view?.showRefresh(false) } .subscribe({ view?.run { Timber.i("Loading grade result: Attempt load index $currentPageIndex") loadChild(currentPageIndex) + enableSwipe(false) + showSemesterSwitch(true) } }) { Timber.i("Loading grade result: An exception occurred") errorHandler.dispatch(it) view?.run { showProgress(false) - showEmpty() + showEmpty(true) + enableSwipe(true) } }) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt index 3f1a197c..9fdd46b1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt @@ -12,10 +12,16 @@ interface GradeView : BaseSessionView { fun showProgress(show: Boolean) - fun showEmpty() + fun showEmpty(show: Boolean) + + fun showRefresh(show: Boolean) + + fun showSemesterSwitch(show: Boolean) fun showSemesterDialog(selectedIndex: Int) + fun enableSwipe(enable: Boolean) + fun notifyChildLoadData(index: Int, semesterId: Int, forceRefresh: Boolean) fun notifyChildParentReselected(index: Int) diff --git a/app/src/main/res/layout/fragment_grade.xml b/app/src/main/res/layout/fragment_grade.xml index 6cd22636..bf805175 100644 --- a/app/src/main/res/layout/fragment_grade.xml +++ b/app/src/main/res/layout/fragment_grade.xml @@ -17,13 +17,19 @@ app:tabTextColor="@android:color/white" tools:visibility="visible" /> - + android:layout_marginTop="48dp"> + + + Date: Wed, 20 Mar 2019 20:52:51 +0100 Subject: [PATCH 04/33] Version 0.7.1 --- .travis.yml | 8 ++++---- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index b3261931..56c64858 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,10 @@ cache: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ -branches: - only: - - master - - 0.7.x +#branches: +# only: +# - master +# - 0.7.x android: licenses: diff --git a/app/build.gradle b/app/build.gradle index f581ba51..4b471bdc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 15 targetSdkVersion 28 - versionCode 26 - versionName "0.7.0" + versionCode 27 + versionName "0.7.1" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -77,7 +77,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('com.github.wulkanowy:api:bc60169383') { exclude module: "threetenbp" } + implementation('io.github.wulkanowy:api:0.7.1') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt index 2d079ff9..6f8a6b0a 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,5 +1,3 @@ -Wersja 0.7.0 - Dodaliśmy: - szczęśliwy numerek - lekcje zrealizowane From 20d0abba29d4b7644574e818d9dd568c1d97f789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Thu, 21 Mar 2019 22:34:41 +0100 Subject: [PATCH 05/33] Fix empty container id in grade fragemnt adapter (#289) --- .../ui/modules/grade/GradePresenter.kt | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt index 98eb2a9f..1251ee2d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt @@ -7,9 +7,7 @@ import io.github.wulkanowy.ui.base.session.BaseSessionPresenter import io.github.wulkanowy.ui.base.session.SessionErrorHandler import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.SchedulersProvider -import io.reactivex.Completable import timber.log.Timber -import java.util.concurrent.TimeUnit.MILLISECONDS import javax.inject.Inject class GradePresenter @Inject constructor( @@ -30,15 +28,12 @@ class GradePresenter @Inject constructor( fun onAttachView(view: GradeView, savedIndex: Int?) { super.onAttachView(view) Timber.i("Grade view is attached") - disposable.add(Completable.timer(150, MILLISECONDS, schedulers.mainThread) - .subscribe { - selectedIndex = savedIndex ?: 0 - view.run { - initView() - enableSwipe(false) - } - loadData() - }) + selectedIndex = savedIndex ?: 0 + view.run { + initView() + enableSwipe(false) + } + loadData() } fun onCreateMenu() { From 4b78862486c960a16a60250cc3232d6c0cd4cccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Fri, 22 Mar 2019 23:41:41 +0100 Subject: [PATCH 06/33] Remove retry sync work when completed lessons is disabled (#294) --- .../main/java/io/github/wulkanowy/services/sync/SyncWorker.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt index ec753b7e..86a3dd61 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt @@ -11,6 +11,7 @@ import androidx.work.WorkerParameters import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import io.github.wulkanowy.R +import io.github.wulkanowy.api.interceptor.FeatureDisabledException import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.semester.SemesterRepository import io.github.wulkanowy.data.repositories.student.StudentRepository @@ -43,7 +44,8 @@ class SyncWorker @AssistedInject constructor( .toSingleDefault(Result.success()) .onErrorReturn { Timber.e(it, "There was an error during synchronization") - Result.retry() + if (it is FeatureDisabledException) Result.success() + else Result.retry() } .doOnSuccess { if (preferencesRepository.isDebugNotificationEnable) notify(it) } } From 36785f019a4a04c1907aef1713f3ba6fca63d056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Fri, 22 Mar 2019 23:54:58 +0100 Subject: [PATCH 07/33] Fix restoring the grade fragment (#293) --- .../io/github/wulkanowy/ui/modules/grade/GradePresenter.kt | 2 +- .../java/io/github/wulkanowy/ui/modules/main/MainActivity.kt | 4 +++- .../java/io/github/wulkanowy/ui/modules/main/MainModule.kt | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt index 1251ee2d..2357e063 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt @@ -77,7 +77,7 @@ class GradePresenter @Inject constructor( } fun onPageSelected(index: Int) { - loadChild(index) + if (semesters.isNotEmpty()) loadChild(index) } fun onSwipeRefresh() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt index 5e0ed2b2..0d9a6351 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt @@ -2,6 +2,8 @@ package io.github.wulkanowy.ui.modules.main import android.content.Context import android.content.Intent +import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK +import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.os.Bundle import android.view.Menu import android.view.MenuItem @@ -165,7 +167,7 @@ class MainActivity : BaseActivity(), MainView { override fun openLoginView() { startActivity(LoginActivity.getStartIntent(this) - .apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) }) + .apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) }) } override fun onSaveInstanceState(outState: Bundle?) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt index d1afd9c0..de4405b7 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt @@ -5,7 +5,6 @@ import dagger.Module import dagger.Provides import dagger.android.ContributesAndroidInjector import io.github.wulkanowy.R -import io.github.wulkanowy.di.scopes.PerActivity import io.github.wulkanowy.di.scopes.PerFragment import io.github.wulkanowy.ui.modules.about.AboutFragment import io.github.wulkanowy.ui.modules.about.AboutModule @@ -33,7 +32,6 @@ abstract class MainModule { companion object { @JvmStatic - @PerActivity @Provides fun provideFragNavController(activity: MainActivity): FragNavController { return FragNavController(activity.supportFragmentManager, R.id.mainFragmentContainer) From 316cd2f7f9b9f74973d2b02fb669eb295b78cb8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 23 Mar 2019 00:37:13 +0100 Subject: [PATCH 08/33] Add checking current student in background services (#295) --- .travis.yml | 8 ++++---- .../wulkanowy/services/sync/SyncWorker.kt | 17 +++++++++++------ .../widgets/timetable/TimetableWidgetFactory.kt | 11 ++++++++--- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 56c64858..b3261931 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,10 @@ cache: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ -#branches: -# only: -# - master -# - 0.7.x +branches: + only: + - master + - 0.7.x android: licenses: diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt index 86a3dd61..a6e44b42 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt @@ -34,12 +34,17 @@ class SyncWorker @AssistedInject constructor( ) : RxWorker(appContext, workerParameters) { override fun createWork(): Single { - return studentRepository.getCurrentStudent() - .flatMapCompletable { student -> - semesterRepository.getCurrentSemester(student, true) - .flatMapCompletable { semester -> - Completable.mergeDelayError(works.map { it.create(student, semester) }) - } + return studentRepository.isStudentSaved() + .flatMapCompletable { isSaved -> + if (isSaved) { + studentRepository.getCurrentStudent() + .flatMapCompletable { student -> + semesterRepository.getCurrentSemester(student) + .flatMapCompletable { semester -> + Completable.mergeDelayError(works.map { it.create(student, semester) }) + } + } + } else Completable.complete() } .toSingleDefault(Result.success()) .onErrorReturn { diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetFactory.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetFactory.kt index 63560807..f2d40ba7 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetFactory.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetFactory.kt @@ -17,6 +17,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.timetable.TimetableRepository import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.toFormattedString +import io.reactivex.Single import org.threeten.bp.LocalDate import timber.log.Timber @@ -51,9 +52,13 @@ class TimetableWidgetFactory( ?.let { date -> try { lessons = studentRepository.isStudentSaved() - .flatMap { studentRepository.getCurrentStudent() } - .flatMap { semesterRepository.getCurrentSemester(it) } - .flatMap { timetableRepository.getTimetable(it, date, date) } + .flatMap { isSaved -> + if (isSaved) { + studentRepository.getCurrentStudent() + .flatMap { semesterRepository.getCurrentSemester(it) } + .flatMap { timetableRepository.getTimetable(it, date, date) } + } else Single.just(emptyList()) + } .map { item -> item.sortedBy { it.number } } .subscribeOn(schedulers.backgroundThread) .blockingGet() From 2d6610e05c807f0c9aa52e5cd0ab4da310b766be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 23 Mar 2019 01:12:17 +0100 Subject: [PATCH 09/33] Set max concurrency in sync worker (#296) --- .../main/java/io/github/wulkanowy/services/sync/SyncWorker.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt index a6e44b42..5d0162f1 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt @@ -19,6 +19,7 @@ import io.github.wulkanowy.services.sync.channels.DebugChannel import io.github.wulkanowy.services.sync.works.Work import io.github.wulkanowy.utils.getCompatColor import io.reactivex.Completable +import io.reactivex.Flowable import io.reactivex.Single import timber.log.Timber import kotlin.random.Random @@ -41,7 +42,7 @@ class SyncWorker @AssistedInject constructor( .flatMapCompletable { student -> semesterRepository.getCurrentSemester(student) .flatMapCompletable { semester -> - Completable.mergeDelayError(works.map { it.create(student, semester) }) + Completable.mergeDelayError(Flowable.fromIterable(works.map { it.create(student, semester) }), 3) } } } else Completable.complete() From fc9981aa5d0ce863362491841068cead74aaf367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 23 Mar 2019 13:01:01 +0100 Subject: [PATCH 10/33] Fix issues when loading lucky number (#297) --- .../ui/modules/luckynumber/LuckyNumberPresenter.kt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt index 92ee4e25..74ab0d1f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt @@ -22,7 +22,11 @@ class LuckyNumberPresenter @Inject constructor( override fun onAttachView(view: LuckyNumberView) { super.onAttachView(view) Timber.i("Lucky number view is attached") - view.initView() + view.run { + initView() + showContent(false) + enableSwipe(false) + } loadData() } @@ -35,12 +39,6 @@ class LuckyNumberPresenter @Inject constructor( .flatMapMaybe { luckyNumberRepository.getLuckyNumber(it, forceRefresh) } .subscribeOn(schedulers.backgroundThread) .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.run { - showContent(false) - enableSwipe(false) - } - } .doFinally { view?.run { hideRefresh() From e1a83927c481c7465374358de0697ad1b8d8849a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 23 Mar 2019 14:44:52 +0100 Subject: [PATCH 11/33] Fix reset button in timetable widget (#298) --- app/src/main/AndroidManifest.xml | 1 + .../wulkanowy/ui/widgets/timetable/TimetableWidgetProvider.kt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 352b6d2b..0c6edab4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -52,6 +52,7 @@ diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetProvider.kt index 290007e4..402366ec 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetProvider.kt @@ -62,7 +62,7 @@ class TimetableWidgetProvider : BroadcastReceiver() { private fun onUpdate(context: Context, intent: Intent) { if (intent.getStringExtra(EXTRA_BUTTON_TYPE) === null) { - intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS).forEach { appWidgetId -> + intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS)?.forEach { appWidgetId -> updateWidget(context, appWidgetId, now().nextOrSameSchoolDay) } } else { @@ -95,7 +95,7 @@ class TimetableWidgetProvider : BroadcastReceiver() { .apply { action = createWidgetKey(appWidgetId) }) setOnClickPendingIntent(R.id.timetableWidgetNext, createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT)) setOnClickPendingIntent(R.id.timetableWidgetPrev, createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV)) - createNavIntent(context, Int.MAX_VALUE, appWidgetId, BUTTON_RESET).also { + createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET).also { setOnClickPendingIntent(R.id.timetableWidgetDate, it) setOnClickPendingIntent(R.id.timetableWidgetDay, it) } From 68b98479273e3c61ac2d46d76399d557b09ad1af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 23 Mar 2019 16:35:33 +0100 Subject: [PATCH 12/33] Fix reselecting root fragments (#299) --- .../java/io/github/wulkanowy/ui/modules/main/MainActivity.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt index 0d9a6351..85aa94a1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.os.Bundle +import android.os.Handler import android.view.Menu import android.view.MenuItem import androidx.appcompat.app.AlertDialog @@ -146,7 +147,9 @@ class MainActivity : BaseActivity(), MainView { } override fun notifyMenuViewReselected() { - (navController.currentStack?.get(0) as? MainView.MainChildView)?.onFragmentReselected() + Handler().postDelayed({ + (navController.currentStack?.get(0) as? MainView.MainChildView)?.onFragmentReselected() + }, 250) } fun showDialogFragment(dialog: DialogFragment) { From 6bb03b3be8487ce16209e178719df490e7639814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 23 Mar 2019 17:29:34 +0100 Subject: [PATCH 13/33] Fix day navigation unevenition (#301) --- app/build.gradle | 2 +- .../wulkanowy/ui/modules/attendance/AttendancePresenter.kt | 2 +- .../github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt | 2 +- .../ui/modules/timetable/completed/CompletedLessonsPresenter.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4b471bdc..c0f7e085 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('io.github.wulkanowy:api:0.7.1') { exclude module: "threetenbp" } + implementation('com.github.wulkanowy:api:f60d2b8') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt index 988681b1..ec471c16 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt @@ -135,7 +135,7 @@ class AttendancePresenter @Inject constructor( clearData() showNextButton(!currentDate.plusDays(1).isHolidays) showPreButton(!currentDate.minusDays(1).isHolidays) - updateNavigationDay(currentDate.toFormattedString("EEEE \n dd.MM.YYYY").capitalize()) + updateNavigationDay(currentDate.toFormattedString("EEEE\ndd.MM.YYYY").capitalize()) } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt index 3786a362..ebda3931 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt @@ -128,7 +128,7 @@ class TimetablePresenter @Inject constructor( clearData() showNextButton(!currentDate.plusDays(1).isHolidays) showPreButton(!currentDate.minusDays(1).isHolidays) - updateNavigationDay(currentDate.toFormattedString("EEEE \n dd.MM.YYYY").capitalize()) + updateNavigationDay(currentDate.toFormattedString("EEEE\ndd.MM.YYYY").capitalize()) } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt index ddc81818..6a14acda 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt @@ -112,7 +112,7 @@ class CompletedLessonsPresenter @Inject constructor( clearData() showNextButton(!currentDate.plusDays(1).isHolidays) showPreButton(!currentDate.minusDays(1).isHolidays) - updateNavigationDay(currentDate.toFormattedString("EEEE \n dd.MM.YYYY").capitalize()) + updateNavigationDay(currentDate.toFormattedString("EEEE\ndd.MM.YYYY").capitalize()) } } } From 1f65b8465e76232a76c25e62e09f5359f6fd0d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 23 Mar 2019 18:35:56 +0100 Subject: [PATCH 14/33] Add logging to sync worker (#300) --- .../io/github/wulkanowy/di/BuilderModule.kt | 4 --- .../wulkanowy/services/ServicesModule.kt | 5 ++++ .../wulkanowy/services/sync/SyncWorker.kt | 28 +++++++++++-------- .../services/sync/works/RecipientWork.kt | 4 +-- .../ui/modules/about/AboutFragment.kt | 5 ++-- .../statistics/GradeStatisticsPresenter.kt | 4 +-- .../ui/modules/main/MainPresenter.kt | 2 +- 7 files changed, 30 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/di/BuilderModule.kt b/app/src/main/java/io/github/wulkanowy/di/BuilderModule.kt index 2616acc3..7f477630 100644 --- a/app/src/main/java/io/github/wulkanowy/di/BuilderModule.kt +++ b/app/src/main/java/io/github/wulkanowy/di/BuilderModule.kt @@ -3,7 +3,6 @@ package io.github.wulkanowy.di import dagger.Module import dagger.android.ContributesAndroidInjector import io.github.wulkanowy.di.scopes.PerActivity -import io.github.wulkanowy.services.widgets.TimetableWidgetService import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.login.LoginModule import io.github.wulkanowy.ui.modules.main.MainActivity @@ -30,9 +29,6 @@ internal abstract class BuilderModule { @ContributesAndroidInjector abstract fun bindMessageSendActivity(): SendMessageActivity - @ContributesAndroidInjector - abstract fun bindTimetableWidgetService(): TimetableWidgetService - @ContributesAndroidInjector abstract fun bindTimetableWidgetProvider(): TimetableWidgetProvider } diff --git a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt b/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt index 70cbf84c..84409a84 100644 --- a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt +++ b/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt @@ -9,6 +9,7 @@ import com.squareup.inject.assisted.dagger2.AssistedModule import dagger.Binds import dagger.Module import dagger.Provides +import dagger.android.ContributesAndroidInjector import dagger.multibindings.IntoSet import io.github.wulkanowy.services.sync.works.AttendanceSummaryWork import io.github.wulkanowy.services.sync.works.AttendanceWork @@ -24,6 +25,7 @@ import io.github.wulkanowy.services.sync.works.NoteWork import io.github.wulkanowy.services.sync.works.RecipientWork import io.github.wulkanowy.services.sync.works.TimetableWork import io.github.wulkanowy.services.sync.works.Work +import io.github.wulkanowy.services.widgets.TimetableWidgetService import javax.inject.Singleton @AssistedModule @@ -48,6 +50,9 @@ abstract class ServicesModule { fun provideNotificationManager(context: Context) = context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager } + @ContributesAndroidInjector + abstract fun bindTimetableWidgetService(): TimetableWidgetService + @Binds @IntoSet abstract fun provideGradeWork(work: GradeWork): Work diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt index 5d0162f1..36593966 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt @@ -35,17 +35,20 @@ class SyncWorker @AssistedInject constructor( ) : RxWorker(appContext, workerParameters) { override fun createWork(): Single { + Timber.i("SyncWorker is starting") return studentRepository.isStudentSaved() - .flatMapCompletable { isSaved -> - if (isSaved) { - studentRepository.getCurrentStudent() - .flatMapCompletable { student -> - semesterRepository.getCurrentSemester(student) - .flatMapCompletable { semester -> - Completable.mergeDelayError(Flowable.fromIterable(works.map { it.create(student, semester) }), 3) - } - } - } else Completable.complete() + .filter { true } + .flatMap { studentRepository.getCurrentStudent().toMaybe() } + .flatMapCompletable { student -> + semesterRepository.getCurrentSemester(student, true) + .flatMapCompletable { semester -> + Completable.mergeDelayError(Flowable.fromIterable(works.map { work -> + work.create(student, semester) + .doOnSubscribe { Timber.i("${work::class.java.simpleName} is starting") } + .doOnError { Timber.i("${work::class.java.simpleName} result: An exception occurred") } + .doOnComplete { Timber.i("${work::class.java.simpleName} result: Success") } + }), 3) + } } .toSingleDefault(Result.success()) .onErrorReturn { @@ -53,7 +56,10 @@ class SyncWorker @AssistedInject constructor( if (it is FeatureDisabledException) Result.success() else Result.retry() } - .doOnSuccess { if (preferencesRepository.isDebugNotificationEnable) notify(it) } + .doOnSuccess { + if (preferencesRepository.isDebugNotificationEnable) notify(it) + Timber.i("SyncWorker result: $it") + } } private fun notify(result: Result) { diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt index af8de434..fa610dee 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt @@ -13,10 +13,10 @@ class RecipientWork @Inject constructor( ) : Work { override fun create(student: Student, semester: Semester): Completable { - return reportingUnitRepository.getReportingUnits(student) + return reportingUnitRepository.getReportingUnits(student, true) .flatMapCompletable { units -> Completable.mergeDelayError(units.map { - recipientRepository.getRecipients(student, 2, it).ignoreElement() + recipientRepository.getRecipients(student, 2, it, true).ignoreElement() }) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt index 1002f914..52caf731 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt @@ -43,7 +43,8 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView { .withAboutSpecial3(getString(R.string.about_feedback)) .withFields(R.string::class.java.fields) .withCheckCachedDetection(false) - .withExcludedLibraries("fastadapter", "AndroidIconics", "gson", "Jsoup", "Retrofit", "okio", "OkHttp") + .withExcludedLibraries("fastadapter", "AndroidIconics", "Jsoup", "Retrofit", "okio", + "OkHttp", "Butterknife", "CircleImageView") .withOnExtraListener { presenter.onExtraSelect(it) }) }.let { fragmentCompat.onCreateView(inflater.context, inflater, container, savedInstanceState, it) @@ -68,7 +69,7 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView { data = Uri.parse("mailto:") putExtra(Intent.EXTRA_EMAIL, Array(1) { "wulkanowyinc@gmail.com" }) putExtra(Intent.EXTRA_SUBJECT, "Zgłoszenie błędu") - putExtra(Intent.EXTRA_TEXT,"Tu umieść treść zgłoszenia\n\n" + "-".repeat(40) + "\n" + """ + putExtra(Intent.EXTRA_TEXT, "Tu umieść treść zgłoszenia\n\n" + "-".repeat(40) + "\n" + """ Build: ${BuildConfig.VERSION_CODE} SDK: ${android.os.Build.VERSION.SDK_INT} Device: ${android.os.Build.MANUFACTURER} ${android.os.Build.MODEL} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt index 5111420d..5dd485cd 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt @@ -63,7 +63,7 @@ class GradeStatisticsPresenter @Inject constructor( } fun onSubjectSelected(name: String) { - Timber.i("Select attendance stats subject $name") + Timber.i("Select grade stats subject $name") view?.run { showContent(false) showProgress(true) @@ -77,7 +77,7 @@ class GradeStatisticsPresenter @Inject constructor( } fun onTypeChange(isSemester: Boolean) { - Timber.i("Select attendance stats semester: $isSemester") + Timber.i("Select grade stats semester: $isSemester") disposable.clear() view?.run { showContent(false) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt index a2a973c6..30f3b920 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt @@ -24,9 +24,9 @@ class MainPresenter @Inject constructor( fun onAttachView(view: MainView, initMenuIndex: Int) { super.onAttachView(view) - Timber.i("Main view is attached with $initMenuIndex menu index") view.run { startMenuIndex = if (initMenuIndex != -1) initMenuIndex else prefRepository.startMenuIndex + Timber.i("Main view is attached with $startMenuIndex menu index") initView() } From d178c15d2f71491b6dfbbdb9e76ab8ad8d6130e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sun, 24 Mar 2019 16:03:51 +0100 Subject: [PATCH 15/33] Update dependencies (#302) --- app/build.gradle | 26 +++++++++---------- .../wulkanowy/ui/modules/main/MainActivity.kt | 5 ---- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c0f7e085..453765fd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -86,10 +86,14 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.multidex:multidex:2.0.1' - implementation 'com.takisoft.preferencex:preferencex:1.0.0' + implementation "androidx.work:work-runtime:2.0.0" + implementation "androidx.work:work-rxjava2:2.0.0" - implementation "android.arch.work:work-rxjava2:1.0.0" - implementation "android.arch.work:work-runtime:1.0.0" + implementation "androidx.room:room-runtime:2.1.0-alpha06" + implementation "androidx.room:room-rxjava2:2.1.0-alpha06" + kapt "androidx.room:room-compiler:2.1.0-alpha06" + + implementation 'com.takisoft.preferencex:preferencex:1.0.0' implementation 'com.squareup.inject:assisted-inject-annotations-dagger2:0.3.3' kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.3.3' @@ -98,17 +102,13 @@ dependencies { kapt "com.google.dagger:dagger-compiler:2.21" kapt "com.google.dagger:dagger-android-processor:2.21" - implementation "androidx.room:room-runtime:2.1.0-alpha05" - implementation "androidx.room:room-rxjava2:2.1.0-alpha05" - kapt "androidx.room:room-compiler:2.1.0-alpha05" - implementation "eu.davidea:flexible-adapter:5.1.0" implementation "eu.davidea:flexible-adapter-ui:1.0.0" implementation "com.aurelhubert:ahbottomnavigation:2.3.4" - implementation 'com.ncapdevi:frag-nav:3.1.0' + implementation 'com.ncapdevi:frag-nav:3.2.0' implementation 'com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f' - implementation 'com.github.PhilJay:MPAndroidChart:971640b29d' + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' implementation 'com.github.pwittchen:reactivenetwork-rx2:3.0.2' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' @@ -128,15 +128,15 @@ dependencies { debugImplementation "com.amitshekhar.android:debug-db:1.0.6" testImplementation "junit:junit:4.12" - testImplementation "io.mockk:mockk:1.9.1" - testImplementation "org.mockito:mockito-inline:2.25.0" + testImplementation "io.mockk:mockk:1.9.2" + testImplementation "org.mockito:mockito-inline:2.25.1" testImplementation 'org.threeten:threetenbp:1.3.8' - androidTestImplementation "io.mockk:mockk-android:1.9.1" androidTestImplementation 'androidx.test:core:1.1.0' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.0' - androidTestImplementation 'org.mockito:mockito-android:2.25.0' + androidTestImplementation "io.mockk:mockk-android:1.9.2" + androidTestImplementation 'org.mockito:mockito-android:2.25.1' androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt index 85aa94a1..4448e556 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt @@ -71,11 +71,6 @@ class MainActivity : BaseActivity(), MainView { return true } - override fun onStart() { - super.onStart() - presenter.onViewChange() - } - override fun initView() { mainBottomNav.run { addItems( From 3656d3161f1d5ae3c160f37526ad4e33cfd423fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 24 Mar 2019 17:31:39 +0100 Subject: [PATCH 16/33] Fix crash on duplicate items (#303) --- .../ui/modules/account/AccountItem.kt | 17 ++++++------- .../ui/modules/attendance/AttendanceItem.kt | 16 ++++++------ .../summary/AttendanceSummaryItem.kt | 12 ++++----- .../wulkanowy/ui/modules/exam/ExamItem.kt | 11 ++++---- .../modules/grade/details/GradeDetailsItem.kt | 9 ++----- .../modules/grade/summary/GradeSummaryItem.kt | 15 ++++------- .../ui/modules/homework/HomeworkItem.kt | 18 ++++++------- .../studentselect/LoginStudentSelectItem.kt | 25 +++++++------------ .../ui/modules/message/MessageItem.kt | 11 +++----- .../wulkanowy/ui/modules/more/MoreItem.kt | 11 ++++---- .../wulkanowy/ui/modules/note/NoteItem.kt | 10 +++----- .../ui/modules/timetable/TimetableItem.kt | 21 ++++++++-------- 12 files changed, 70 insertions(+), 106 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt index a564306d..cb7aabda 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt @@ -14,12 +14,12 @@ class AccountItem(val student: Student) : AbstractFlexibleItem>?): ViewHolder { + override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { return ViewHolder(view, adapter) } - override fun bindViewHolder(adapter: FlexibleAdapter>?, holder: ViewHolder?, position: Int, payloads: MutableList?) { - holder?.apply { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { + holder.apply { accountItemName.text = student.studentName accountItemSchool.text = student.schoolName accountItemImage.setBackgroundResource(if (student.isCurrent) R.drawable.ic_account_circular_border else 0) @@ -38,14 +38,13 @@ class AccountItem(val student: Student) : AbstractFlexibleItem>?) : FlexibleViewHolder(view, adapter), - LayoutContainer { - - override val containerView: View? + class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { + override val containerView: View get() = contentView } } - diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceItem.kt index c2698ebb..16a140cb 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceItem.kt @@ -14,14 +14,13 @@ import kotlinx.android.synthetic.main.item_attendance.* class AttendanceItem(val attendance: Attendance) : AbstractFlexibleItem() { + override fun getLayoutRes() = R.layout.item_attendance + override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { return ViewHolder(view, adapter) } - override fun getLayoutRes(): Int = R.layout.item_attendance - - override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, - position: Int, payloads: MutableList?) { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { holder.apply { attendanceItemNumber.text = attendance.number.toString() attendanceItemSubject.text = attendance.subject @@ -37,16 +36,17 @@ class AttendanceItem(val attendance: Attendance) : AbstractFlexibleItem) : FlexibleViewHolder(view, adapter), - LayoutContainer { - + class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { override val containerView: View get() = contentView } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryItem.kt index 3102ce11..265d6ce4 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryItem.kt @@ -23,12 +23,12 @@ class AttendanceSummaryItem( override fun getLayoutRes() = R.layout.item_attendance_summary - override fun createViewHolder(view: View?, adapter: FlexibleAdapter>?): ViewHolder { + override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { return ViewHolder(view, adapter) } - override fun bindViewHolder(adapter: FlexibleAdapter>?, holder: ViewHolder?, position: Int, payloads: MutableList?) { - holder?.apply { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { + holder.apply { attendanceSummaryMonth.text = month attendanceSummaryPercentage.text = percentage attendanceSummaryPresent.text = present @@ -73,10 +73,8 @@ class AttendanceSummaryItem( return result } - class ViewHolder(view: View?, adapter: FlexibleAdapter>?) : FlexibleViewHolder(view, adapter), - LayoutContainer { - - override val containerView: View? + class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { + override val containerView: View get() = contentView } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamItem.kt index 318685e9..8971b4df 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamItem.kt @@ -18,8 +18,7 @@ class ExamItem(header: ExamHeader, val exam: Exam) : AbstractSectionableItem>, holder: ViewHolder, - position: Int, payloads: MutableList?) { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { holder.run { examItemSubject.text = exam.subject examItemTeacher.text = exam.teacher @@ -39,12 +38,12 @@ class ExamItem(header: ExamHeader, val exam: Exam) : AbstractSectionableItem) : FlexibleViewHolder(view, adapter), - LayoutContainer { - + class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { override val containerView: View get() = contentView } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsItem.kt index de1d88f7..1e47eca5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsItem.kt @@ -28,10 +28,7 @@ class GradeDetailsItem( } @SuppressLint("SetTextI18n") - override fun bindViewHolder( - adapter: FlexibleAdapter>, holder: ViewHolder, - position: Int, payloads: MutableList? - ) { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { holder.run { gradeItemValue.run { text = grade.entry @@ -70,9 +67,7 @@ class GradeDetailsItem( return result } - class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), - LayoutContainer { - + class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { override val containerView: View get() = contentView } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryItem.kt index 0daf0665..5737a832 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryItem.kt @@ -18,15 +18,12 @@ class GradeSummaryItem( override fun getLayoutRes() = R.layout.item_grade_summary - override fun createViewHolder(view: View?, adapter: FlexibleAdapter>?): ViewHolder { + override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { return ViewHolder(view, adapter) } - override fun bindViewHolder( - adapter: FlexibleAdapter>?, holder: ViewHolder?, - position: Int, payloads: MutableList? - ) { - holder?.run { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { + holder.run { gradeSummaryItemTitle.text = title gradeSummaryItemAverage.text = average gradeSummaryItemPredicted.text = predictedGrade @@ -56,10 +53,8 @@ class GradeSummaryItem( return result } - class ViewHolder(view: View?, adapter: FlexibleAdapter>?) : FlexibleViewHolder(view, adapter), - LayoutContainer { - - override val containerView: View? + class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { + override val containerView: View get() = contentView } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkItem.kt index a2b8cc0a..2de9233f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkItem.kt @@ -10,9 +10,8 @@ import io.github.wulkanowy.data.db.entities.Homework import kotlinx.android.extensions.LayoutContainer import kotlinx.android.synthetic.main.item_homework.* -class HomeworkItem( - header: HomeworkHeader, val homework: Homework -) : AbstractSectionableItem(header) { +class HomeworkItem(header: HomeworkHeader, val homework: Homework) : + AbstractSectionableItem(header) { override fun getLayoutRes() = R.layout.item_homework @@ -20,10 +19,7 @@ class HomeworkItem( return ViewHolder(view, adapter) } - override fun bindViewHolder( - adapter: FlexibleAdapter>, holder: ViewHolder, - position: Int, payloads: MutableList? - ) { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { holder.apply { homeworkItemSubject.text = homework.subject homeworkItemTeacher.text = homework.teacher @@ -42,12 +38,12 @@ class HomeworkItem( } override fun hashCode(): Int { - return homework.hashCode() + var result = homework.hashCode() + result = 31 * result + homework.id.toInt() + return result } - class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), - LayoutContainer { - + class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { override val containerView: View get() = contentView } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt index c206a499..71a7d681 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt @@ -8,19 +8,21 @@ import eu.davidea.viewholders.FlexibleViewHolder import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Student import kotlinx.android.extensions.LayoutContainer -import kotlinx.android.synthetic.main.item_login_student_select.view.* +import kotlinx.android.synthetic.main.item_login_student_select.* class LoginStudentSelectItem(val student: Student) : AbstractFlexibleItem() { override fun getLayoutRes(): Int = R.layout.item_login_student_select - override fun createViewHolder(view: View?, adapter: FlexibleAdapter>?): ItemViewHolder { + override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ItemViewHolder { return ItemViewHolder(view, adapter) } - override fun bindViewHolder(adapter: FlexibleAdapter>?, holder: ItemViewHolder?, - position: Int, payloads: MutableList?) { - holder?.bind(student) + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ItemViewHolder, position: Int, payloads: MutableList?) { + holder.run { + loginItemName.text = student.studentName + loginItemSchool.text = student.schoolName + } } override fun equals(other: Any?): Boolean { @@ -38,17 +40,8 @@ class LoginStudentSelectItem(val student: Student) : AbstractFlexibleItem?) - : FlexibleViewHolder(view, adapter), LayoutContainer { - - override val containerView: View? + class ItemViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { + override val containerView: View get() = itemView - - fun bind(item: Student) { - itemView.run { - loginItemName.text = item.studentName - loginItemSchool.text = item.schoolName - } - } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageItem.kt index ec725a38..26568e22 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageItem.kt @@ -20,12 +20,9 @@ class MessageItem(val message: Message, private val noSubjectString: String) : return ViewHolder(view, adapter) } - override fun getLayoutRes(): Int = R.layout.item_message + override fun getLayoutRes() = R.layout.item_message - override fun bindViewHolder( - adapter: FlexibleAdapter>, holder: ViewHolder, - position: Int, payloads: MutableList? - ) { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { holder.apply { val style = if (message.unread) BOLD else NORMAL @@ -58,9 +55,7 @@ class MessageItem(val message: Message, private val noSubjectString: String) : return message.hashCode() } - class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), - LayoutContainer { - + class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { override val containerView: View get() = contentView } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt index e8571a8c..85b604e7 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt @@ -14,12 +14,12 @@ class MoreItem(val title: String, private val drawable: Drawable?) : AbstractFle override fun getLayoutRes() = R.layout.item_more - override fun createViewHolder(view: View?, adapter: FlexibleAdapter>?): ViewHolder { + override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { return ViewHolder(view, adapter) } - override fun bindViewHolder(adapter: FlexibleAdapter>?, holder: ViewHolder?, position: Int, payloads: MutableList?) { - holder?.apply { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { + holder.apply { moreItemTitle.text = title moreItemImage.setImageDrawable(drawable) } @@ -40,9 +40,8 @@ class MoreItem(val title: String, private val drawable: Drawable?) : AbstractFle return title.hashCode() } - class ViewHolder(view: View?, adapter: FlexibleAdapter<*>?) : FlexibleViewHolder(view, adapter), LayoutContainer { - - override val containerView: View? + class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { + override val containerView: View get() = contentView } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteItem.kt index 71562fc4..dabeef74 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteItem.kt @@ -15,16 +15,13 @@ import kotlinx.android.synthetic.main.item_note.* class NoteItem(val note: Note) : AbstractFlexibleItem() { + override fun getLayoutRes() = R.layout.item_note + override fun createViewHolder(view: View, adapter: FlexibleAdapter>): NoteItem.ViewHolder { return NoteItem.ViewHolder(view, adapter) } - override fun getLayoutRes(): Int = R.layout.item_note - - override fun bindViewHolder( - adapter: FlexibleAdapter>, - holder: NoteItem.ViewHolder, position: Int, payloads: MutableList? - ) { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: NoteItem.ViewHolder, position: Int, payloads: MutableList?) { holder.apply { noteItemDate.apply { text = note.date.toFormattedString() @@ -57,7 +54,6 @@ class NoteItem(val note: Note) : AbstractFlexibleItem() { } class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { - override val containerView: View get() = contentView } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableItem.kt index f37c0f51..c721401f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableItem.kt @@ -15,18 +15,17 @@ import io.github.wulkanowy.utils.toFormattedString import kotlinx.android.extensions.LayoutContainer import kotlinx.android.synthetic.main.item_timetable.* -class TimetableItem(val lesson: Timetable, private val roomText: String) - : AbstractFlexibleItem() { +class TimetableItem(val lesson: Timetable, private val roomText: String) : + AbstractFlexibleItem() { - override fun getLayoutRes(): Int = R.layout.item_timetable + override fun getLayoutRes() = R.layout.item_timetable override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { return ViewHolder(view, adapter) } @SuppressLint("SetTextI18n") - override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, - position: Int, payloads: MutableList?) { + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: ViewHolder, position: Int, payloads: MutableList?) { holder.apply { timetableItemNumber.text = lesson.number.toString() timetableItemSubject.text = lesson.subject @@ -34,8 +33,8 @@ class TimetableItem(val lesson: Timetable, private val roomText: String) timetableItemTime.text = "${lesson.start.toFormattedString("HH:mm")} - ${lesson.end.toFormattedString("HH:mm")}" timetableItemAlert.visibility = if (lesson.changes || lesson.canceled) VISIBLE else GONE timetableItemSubject.paintFlags = - if (lesson.canceled) timetableItemSubject.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG - else timetableItemSubject.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv() + if (lesson.canceled) timetableItemSubject.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG + else timetableItemSubject.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv() } } @@ -50,12 +49,12 @@ class TimetableItem(val lesson: Timetable, private val roomText: String) } override fun hashCode(): Int { - return lesson.hashCode() + var result = lesson.hashCode() + result = 31 * result + lesson.id.toInt() + return result } - class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), - LayoutContainer { - + class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer { override val containerView: View get() = contentView } From ed9458d9a5ef34a09147dc02528c03e9248d624a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sun, 24 Mar 2019 20:21:05 +0100 Subject: [PATCH 17/33] Fix more than one current semester in database (#304) --- .../wulkanowy/data/db/dao/SemesterDao.kt | 13 ++-- .../repositories/semester/SemesterLocal.kt | 13 ++-- .../semester/SemesterRepository.kt | 16 +++- .../UnitTestInternetObservingStrategy.kt | 19 +++++ .../AttendanceRemoteTest.kt | 3 +- .../CompletedLessonsRemoteTest.kt | 3 +- .../{remote => exam}/ExamRemoteTest.kt | 3 +- .../GradeStatisticsRemoteTest.kt | 3 +- .../LuckyNumberRemoteTest.kt | 2 +- .../semester/SemesterRepositoryTest.kt | 74 +++++++++++++++++++ .../semester/TestSemesterEnityCreator.kt | 16 ++++ .../{remote => student}/StudentRemoteTest.kt | 3 +- .../TimetableRemoteTest.kt | 2 +- 13 files changed, 138 insertions(+), 32 deletions(-) create mode 100644 app/src/test/java/io/github/wulkanowy/data/repositories/UnitTestInternetObservingStrategy.kt rename app/src/test/java/io/github/wulkanowy/data/repositories/{remote => attendance}/AttendanceRemoteTest.kt (92%) rename app/src/test/java/io/github/wulkanowy/data/repositories/{remote => completedlessons}/CompletedLessonsRemoteTest.kt (91%) rename app/src/test/java/io/github/wulkanowy/data/repositories/{remote => exam}/ExamRemoteTest.kt (93%) rename app/src/test/java/io/github/wulkanowy/data/repositories/{remote => gradestatistics}/GradeStatisticsRemoteTest.kt (91%) rename app/src/test/java/io/github/wulkanowy/data/repositories/{remote => luckynumber}/LuckyNumberRemoteTest.kt (95%) create mode 100644 app/src/test/java/io/github/wulkanowy/data/repositories/semester/SemesterRepositoryTest.kt create mode 100644 app/src/test/java/io/github/wulkanowy/data/repositories/semester/TestSemesterEnityCreator.kt rename app/src/test/java/io/github/wulkanowy/data/repositories/{remote => student}/StudentRemoteTest.kt (87%) rename app/src/test/java/io/github/wulkanowy/data/repositories/{remote => timetable}/TimetableRemoteTest.kt (96%) diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt index 44de31d8..608a6663 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt @@ -1,8 +1,8 @@ package io.github.wulkanowy.data.db.dao import androidx.room.Dao +import androidx.room.Delete import androidx.room.Insert -import androidx.room.OnConflictStrategy.IGNORE import androidx.room.Query import io.github.wulkanowy.data.db.entities.Semester import io.reactivex.Maybe @@ -12,15 +12,12 @@ import javax.inject.Singleton @Dao interface SemesterDao { - @Insert(onConflict = IGNORE) + @Insert fun insertAll(semester: List) + @Delete + fun deleteAll(semester: List) + @Query("SELECT * FROM Semesters WHERE student_id = :studentId") fun loadAll(studentId: Int): Maybe> - - @Query("UPDATE Semesters SET is_current = 1 WHERE semester_id = :semesterId AND diary_id = :diaryId") - fun updateCurrent(semesterId: Int, diaryId: Int) - - @Query("UPDATE Semesters SET is_current = 0 WHERE student_id = :studentId") - fun resetCurrent(studentId: Int) } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt index 5be82d7f..37d4a268 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt @@ -11,17 +11,14 @@ import javax.inject.Singleton class SemesterLocal @Inject constructor(private val semesterDb: SemesterDao) { fun saveSemesters(semesters: List) { - return semesterDb.insertAll(semesters) + semesterDb.insertAll(semesters) + } + + fun deleteSemesters(semesters: List) { + semesterDb.deleteAll(semesters) } fun getSemesters(student: Student): Maybe> { return semesterDb.loadAll(student.studentId).filter { !it.isEmpty() } } - - fun setCurrentSemester(semester: Semester) { - semesterDb.run { - resetCurrent(semester.studentId) - updateCurrent(semester.semesterId, semester.diaryId) - } - } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt index 975868a2..9735f029 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt @@ -7,6 +7,7 @@ import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student import io.reactivex.Maybe import io.reactivex.Single +import timber.log.Timber import java.net.UnknownHostException import javax.inject.Inject import javax.inject.Singleton @@ -25,10 +26,17 @@ class SemesterRepository @Inject constructor( .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) .flatMap { if (it) remote.getSemesters(student) else Single.error(UnknownHostException()) - }.map { newSemesters -> - local.apply { - saveSemesters(newSemesters) - setCurrentSemester(newSemesters.single { it.isCurrent }) + }.flatMap { new -> + val currentSemesters = new.filter { it.isCurrent } + if (currentSemesters.size == 1) { + local.getSemesters(student).toSingle(emptyList()) + .doOnSuccess { old -> + local.deleteSemesters(old - new) + local.saveSemesters(new - old) + } + } else { + Timber.i("Current semesters list:\n${currentSemesters.joinToString(separator = "\n")}") + throw IllegalArgumentException("Current semester can be only one.") } }.flatMap { local.getSemesters(student).toSingle(emptyList()) }) } diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/UnitTestInternetObservingStrategy.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/UnitTestInternetObservingStrategy.kt new file mode 100644 index 00000000..28abbb99 --- /dev/null +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/UnitTestInternetObservingStrategy.kt @@ -0,0 +1,19 @@ +package io.github.wulkanowy.data.repositories + +import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingStrategy +import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.error.ErrorHandler +import io.reactivex.Observable +import io.reactivex.Single + +class UnitTestInternetObservingStrategy : InternetObservingStrategy { + + override fun checkInternetConnectivity(host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Single { + return Single.just(true) + } + + override fun observeInternetConnectivity(initialIntervalInMs: Int, intervalInMs: Int, host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Observable { + return Observable.just(true) + } + + override fun getDefaultPingHost() = "localhost" +} diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/AttendanceRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemoteTest.kt similarity index 92% rename from app/src/test/java/io/github/wulkanowy/data/repositories/remote/AttendanceRemoteTest.kt rename to app/src/test/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemoteTest.kt index 4842d305..8adfa83b 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/AttendanceRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemoteTest.kt @@ -1,9 +1,8 @@ -package io.github.wulkanowy.data.repositories.remote +package io.github.wulkanowy.data.repositories.attendance import io.github.wulkanowy.api.Api import io.github.wulkanowy.api.attendance.Attendance import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.attendance.AttendanceRemote import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.impl.annotations.MockK diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/CompletedLessonsRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemoteTest.kt similarity index 91% rename from app/src/test/java/io/github/wulkanowy/data/repositories/remote/CompletedLessonsRemoteTest.kt rename to app/src/test/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemoteTest.kt index f4c161bc..bb9f5294 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/CompletedLessonsRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemoteTest.kt @@ -1,9 +1,8 @@ -package io.github.wulkanowy.data.repositories.remote +package io.github.wulkanowy.data.repositories.completedlessons import io.github.wulkanowy.api.Api import io.github.wulkanowy.api.timetable.CompletedLesson import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsRemote import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.impl.annotations.MockK diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/ExamRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/exam/ExamRemoteTest.kt similarity index 93% rename from app/src/test/java/io/github/wulkanowy/data/repositories/remote/ExamRemoteTest.kt rename to app/src/test/java/io/github/wulkanowy/data/repositories/exam/ExamRemoteTest.kt index 0cc78548..0c83bed0 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/ExamRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/exam/ExamRemoteTest.kt @@ -1,9 +1,8 @@ -package io.github.wulkanowy.data.repositories.remote +package io.github.wulkanowy.data.repositories.exam import io.github.wulkanowy.api.Api import io.github.wulkanowy.api.exams.Exam import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.exam.ExamRemote import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.impl.annotations.MockK diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/GradeStatisticsRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemoteTest.kt similarity index 91% rename from app/src/test/java/io/github/wulkanowy/data/repositories/remote/GradeStatisticsRemoteTest.kt rename to app/src/test/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemoteTest.kt index 14381791..37d3f2ad 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/GradeStatisticsRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemoteTest.kt @@ -1,9 +1,8 @@ -package io.github.wulkanowy.data.repositories.remote +package io.github.wulkanowy.data.repositories.gradestatistics import io.github.wulkanowy.api.Api import io.github.wulkanowy.api.grades.GradeStatistics import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.gradestatistics.GradeStatisticsRemote import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.impl.annotations.MockK diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/LuckyNumberRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemoteTest.kt similarity index 95% rename from app/src/test/java/io/github/wulkanowy/data/repositories/remote/LuckyNumberRemoteTest.kt rename to app/src/test/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemoteTest.kt index 054f8890..67e6c2ef 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/LuckyNumberRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemoteTest.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.remote +package io.github.wulkanowy.data.repositories.luckynumber import io.github.wulkanowy.api.Api import io.github.wulkanowy.data.db.entities.Semester diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/semester/SemesterRepositoryTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/semester/SemesterRepositoryTest.kt new file mode 100644 index 00000000..7856b937 --- /dev/null +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/semester/SemesterRepositoryTest.kt @@ -0,0 +1,74 @@ +package io.github.wulkanowy.data.repositories.semester + +import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings +import io.github.wulkanowy.data.ApiHelper +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.repositories.UnitTestInternetObservingStrategy +import io.reactivex.Maybe +import io.reactivex.Single +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito.doNothing +import org.mockito.Mockito.doReturn +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +class SemesterRepositoryTest { + + @Mock + private lateinit var semesterRemote: SemesterRemote + + @Mock + private lateinit var semesterLocal: SemesterLocal + + @Mock + private lateinit var apiHelper: ApiHelper + + @Mock + private lateinit var student: Student + + private lateinit var semesterRepository: SemesterRepository + + private val settings = InternetObservingSettings.builder() + .strategy(UnitTestInternetObservingStrategy()) + .build() + + @Before + fun initTest() { + MockitoAnnotations.initMocks(this) + semesterRepository = SemesterRepository(semesterRemote, semesterLocal, settings, apiHelper) + } + + @Test + fun singleCurrentSemesterTest() { + val semesters = listOf( + createSemesterEntity(false), + createSemesterEntity(true) + ) + + doNothing().`when`(apiHelper).initApi(student) + doReturn(Maybe.empty()).`when`(semesterLocal).getSemesters(student) + doReturn(Single.just(semesters)).`when`(semesterRemote).getSemesters(student) + + semesterRepository.getSemesters(student).blockingGet() + + verify(semesterLocal).deleteSemesters(emptyList()) + verify(semesterLocal).saveSemesters(semesters) + } + + @Test(expected = IllegalArgumentException::class) + fun twoCurrentSemesterTest() { + val semesters = listOf( + createSemesterEntity(true), + createSemesterEntity(true) + ) + + doNothing().`when`(apiHelper).initApi(student) + doReturn(Maybe.empty()).`when`(semesterLocal).getSemesters(student) + doReturn(Single.just(semesters)).`when`(semesterRemote).getSemesters(student) + + semesterRepository.getSemesters(student).blockingGet() + } +} diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/semester/TestSemesterEnityCreator.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/semester/TestSemesterEnityCreator.kt new file mode 100644 index 00000000..c3377ac5 --- /dev/null +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/semester/TestSemesterEnityCreator.kt @@ -0,0 +1,16 @@ +package io.github.wulkanowy.data.repositories.semester + +import io.github.wulkanowy.data.db.entities.Semester + +fun createSemesterEntity(current: Boolean): Semester { + return Semester( + studentId = 0, + diaryId = 0, + semesterId = 0, + diaryName = "", + classId = 0, + isCurrent = current, + semesterName = 0, + unitId = 0 + ) +} diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/StudentRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt similarity index 87% rename from app/src/test/java/io/github/wulkanowy/data/repositories/remote/StudentRemoteTest.kt rename to app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt index 3a26836d..1244239e 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/StudentRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt @@ -1,8 +1,7 @@ -package io.github.wulkanowy.data.repositories.remote +package io.github.wulkanowy.data.repositories.student import io.github.wulkanowy.api.Api import io.github.wulkanowy.api.register.Student -import io.github.wulkanowy.data.repositories.student.StudentRemote import io.reactivex.Single import org.junit.Assert.assertEquals import org.junit.Before diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/TimetableRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemoteTest.kt similarity index 96% rename from app/src/test/java/io/github/wulkanowy/data/repositories/remote/TimetableRemoteTest.kt rename to app/src/test/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemoteTest.kt index 942b28ed..4bb4091f 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/remote/TimetableRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemoteTest.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.remote +package io.github.wulkanowy.data.repositories.timetable import io.github.wulkanowy.api.Api import io.github.wulkanowy.api.timetable.Timetable From 5a997dacb7a2fdd0f7de7a88b3f8d8e14f75af14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 24 Mar 2019 22:42:09 +0100 Subject: [PATCH 18/33] Version 0.7.2 --- .travis.yml | 8 ++++---- app/build.gradle | 6 +++--- .../main/play/release-notes/pl-PL/default.txt | 20 ++++--------------- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index b3261931..56c64858 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,10 @@ cache: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ -branches: - only: - - master - - 0.7.x +#branches: +# only: +# - master +# - 0.7.x android: licenses: diff --git a/app/build.gradle b/app/build.gradle index 453765fd..ce21cf44 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 15 targetSdkVersion 28 - versionCode 27 - versionName "0.7.1" + versionCode 28 + versionName "0.7.2" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -77,7 +77,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('com.github.wulkanowy:api:f60d2b8') { exclude module: "threetenbp" } + implementation('io.github.wulkanowy:api:0.7.2') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt index 6f8a6b0a..bdf045f5 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,18 +1,6 @@ -Dodaliśmy: -- szczęśliwy numerek -- lekcje zrealizowane -- wysyłanie wiadomości -- ucznia na tle klasy -- opcję zmiany kolorów ocen - -Zmieniliśmy: -- wygląd ekranu logowania -- sposób wyświetlania zastępstw -- widok zadań domowych na tygodniowy - Naprawiliśmy: -- automatyczne przełączanie widżetu na nowy dzień -- wyświetlanie powiadomień o starych ocenach -- znikające numery sal w planie lekcji +- problemy ze stabilnością podczas przełączania zakładek +- nierówność w nawigacji między dniami w planie lekcji i frekwencji +- zły wygląd odświeżania w szczęśliwym numerku -Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.0 +Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.2 From b3cd7e8ac131f0c838e39d5e565954ef65b3aba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Tue, 26 Mar 2019 14:32:23 +0100 Subject: [PATCH 19/33] Fix undeliverable network exceptions (#306) * Remove unnecessary this --- app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt index 68fc7c64..e427647f 100644 --- a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt +++ b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt @@ -19,7 +19,11 @@ import io.github.wulkanowy.di.DaggerAppComponent import io.github.wulkanowy.services.sync.SyncWorkerFactory import io.github.wulkanowy.utils.CrashlyticsTree import io.github.wulkanowy.utils.DebugLogTree +import io.reactivex.exceptions.UndeliverableException +import io.reactivex.plugins.RxJavaPlugins import timber.log.Timber +import java.io.IOException +import java.lang.Exception import javax.inject.Inject class WulkanowyApp : DaggerApplication() { @@ -42,6 +46,7 @@ class WulkanowyApp : DaggerApplication() { if (DEBUG) enableDebugLog() AppCompatDelegate.setDefaultNightMode(prefRepository.currentTheme) WorkManager.initialize(this, Configuration.Builder().setWorkerFactory(workerFactory).build()) + RxJavaPlugins.setErrorHandler(::onError) } private fun enableDebugLog() { @@ -56,6 +61,12 @@ class WulkanowyApp : DaggerApplication() { Timber.plant(CrashlyticsTree()) } + private fun onError(t: Throwable) { + if (t is UndeliverableException && t.cause is IOException || t.cause is InterruptedException) { + Timber.e(t.cause, "An undeliverable error occurred") + } else throw t + } + override fun applicationInjector(): AndroidInjector { return DaggerAppComponent.builder().create(this) } From 87268b3ef68f3c734a28562287cc2ed73479a336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Tue, 26 Mar 2019 16:47:14 +0100 Subject: [PATCH 20/33] Fix rejected execution in sync worker (#305) --- .../java/io/github/wulkanowy/services/sync/SyncWorker.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt index 36593966..134fb034 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt @@ -19,7 +19,6 @@ import io.github.wulkanowy.services.sync.channels.DebugChannel import io.github.wulkanowy.services.sync.works.Work import io.github.wulkanowy.utils.getCompatColor import io.reactivex.Completable -import io.reactivex.Flowable import io.reactivex.Single import timber.log.Timber import kotlin.random.Random @@ -42,12 +41,12 @@ class SyncWorker @AssistedInject constructor( .flatMapCompletable { student -> semesterRepository.getCurrentSemester(student, true) .flatMapCompletable { semester -> - Completable.mergeDelayError(Flowable.fromIterable(works.map { work -> + Completable.mergeDelayError(works.map { work -> work.create(student, semester) .doOnSubscribe { Timber.i("${work::class.java.simpleName} is starting") } .doOnError { Timber.i("${work::class.java.simpleName} result: An exception occurred") } .doOnComplete { Timber.i("${work::class.java.simpleName} result: Success") } - }), 3) + }) } } .toSingleDefault(Result.success()) From c2ab53cfeb8ff1b2a222951a3f271d1bc2061063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 26 Mar 2019 19:46:59 +0100 Subject: [PATCH 21/33] Version 0.7.3 --- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index ce21cf44..509e146f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 15 targetSdkVersion 28 - versionCode 28 - versionName "0.7.2" + versionCode 29 + versionName "0.7.3" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -77,7 +77,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('io.github.wulkanowy:api:0.7.2') { exclude module: "threetenbp" } + implementation('io.github.wulkanowy:api:0.7.3') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt index bdf045f5..6cf59d4b 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,6 +1,6 @@ -Naprawiliśmy: -- problemy ze stabilnością podczas przełączania zakładek -- nierówność w nawigacji między dniami w planie lekcji i frekwencji -- zły wygląd odświeżania w szczęśliwym numerku +Wersja 0.7.3 -Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.2 +Naprawiliśmy: +- naprawiono problemy ze stabilnością podczas odświeżania danych + +Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.3 From c6c7357623a1040afaddc8a7631e7a6fca15e0a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Thu, 28 Mar 2019 18:27:17 +0100 Subject: [PATCH 22/33] Fix black spinner in login form (#308) --- app/src/main/res/drawable/ic_login_outlined_border.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/drawable/ic_login_outlined_border.xml b/app/src/main/res/drawable/ic_login_outlined_border.xml index ec62251e..359bea5e 100644 --- a/app/src/main/res/drawable/ic_login_outlined_border.xml +++ b/app/src/main/res/drawable/ic_login_outlined_border.xml @@ -1,4 +1,5 @@ + From b97b94ae29aac599214cb449582cfa2878bff36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Thu, 28 Mar 2019 23:07:59 +0100 Subject: [PATCH 23/33] Fix more than one current student (#311) Fix #309 --- .travis.yml | 8 ++++---- .../java/io/github/wulkanowy/data/db/dao/StudentDao.kt | 4 ++-- .../wulkanowy/data/repositories/student/StudentLocal.kt | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 56c64858..b3261931 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,10 @@ cache: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ -#branches: -# only: -# - master -# - 0.7.x +branches: + only: + - master + - 0.7.x android: licenses: diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt index c0c054c8..8110bb69 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt @@ -25,8 +25,8 @@ interface StudentDao { @Query("SELECT * FROM Students") fun loadAll(): Maybe> - @Query("UPDATE Students SET is_current = 1 WHERE student_id = :studentId") - fun updateCurrent(studentId: Int) + @Query("UPDATE Students SET is_current = 1 WHERE id = :id") + fun updateCurrent(id: Long) @Query("UPDATE Students SET is_current = 0") fun resetCurrent() diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt index e05e7223..7bbd283f 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt @@ -35,7 +35,7 @@ class StudentLocal @Inject constructor( return Completable.fromCallable { studentDb.run { resetCurrent() - updateCurrent(student.studentId) + updateCurrent(student.id) } } } From 8601093725c6912189ae3038247686c6abd6bc5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Thu, 28 Mar 2019 23:30:30 +0100 Subject: [PATCH 24/33] Again fix rejected execution in sync worker (#310) --- app/build.gradle | 4 ++-- .../java/io/github/wulkanowy/services/sync/SyncManager.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 509e146f..935710c5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -86,8 +86,8 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.multidex:multidex:2.0.1' - implementation "androidx.work:work-runtime:2.0.0" - implementation "androidx.work:work-rxjava2:2.0.0" + implementation "android.arch.work:work-runtime:1.0.0" + implementation "android.arch.work:work-rxjava2:1.0.0" implementation "androidx.room:room-runtime:2.1.0-alpha06" implementation "androidx.room:room-rxjava2:2.1.0-alpha06" diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt index 7a9a9956..c1820afb 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt @@ -40,7 +40,7 @@ class SyncManager @Inject constructor( fun startSyncWorker(restart: Boolean = false) { if (preferencesRepository.isServiceEnabled && !now().isHolidays) { workManager.enqueueUniquePeriodicWork(SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP, - PeriodicWorkRequest.Builder(SyncWorker::class.java, preferencesRepository.servicesInterval, MINUTES) + PeriodicWorkRequest.Builder(SyncWorker::class.java, preferencesRepository.servicesInterval, MINUTES, 10, MINUTES) .setBackoffCriteria(EXPONENTIAL, 30, MINUTES) .setConstraints(Constraints.Builder() .setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) METERED else UNMETERED) From 4e3864f26ff01cc6d2f3289d737869a58f2f02f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 30 Mar 2019 09:31:30 +0100 Subject: [PATCH 25/33] Add opening login view on no current student (#312) --- .../wulkanowy/data/exceptions/NoCurrentStudent.kt | 3 +++ .../data/repositories/student/StudentRepository.kt | 3 ++- .../wulkanowy/ui/base/session/BaseSessionFragment.kt | 10 ++++++++++ .../wulkanowy/ui/base/session/BaseSessionPresenter.kt | 5 ++++- .../wulkanowy/ui/base/session/BaseSessionView.kt | 2 ++ .../wulkanowy/ui/base/session/SessionErrorHandler.kt | 5 +++++ 6 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/io/github/wulkanowy/data/exceptions/NoCurrentStudent.kt diff --git a/app/src/main/java/io/github/wulkanowy/data/exceptions/NoCurrentStudent.kt b/app/src/main/java/io/github/wulkanowy/data/exceptions/NoCurrentStudent.kt new file mode 100644 index 00000000..58a2396e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/exceptions/NoCurrentStudent.kt @@ -0,0 +1,3 @@ +package io.github.wulkanowy.data.exceptions + +class NoCurrentStudentException : Exception("There no set current student in database") diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt index 7ddff0aa..b4b7c828 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt @@ -4,6 +4,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import io.github.wulkanowy.data.ApiHelper import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.exceptions.NoCurrentStudentException import io.reactivex.Completable import io.reactivex.Maybe import io.reactivex.Single @@ -36,7 +37,7 @@ class StudentRepository @Inject constructor( fun getCurrentStudent(decryptPass: Boolean = true): Single { return local.getCurrentStudent(decryptPass) - .switchIfEmpty(Maybe.error(NoSuchElementException("No current student"))) + .switchIfEmpty(Maybe.error(NoCurrentStudentException())) .toSingle() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionFragment.kt index 42622b50..110729d4 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionFragment.kt @@ -1,6 +1,9 @@ package io.github.wulkanowy.ui.base.session +import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK +import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import io.github.wulkanowy.ui.base.BaseFragment +import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.main.MainActivity open class BaseSessionFragment : BaseFragment(), BaseSessionView { @@ -8,4 +11,11 @@ open class BaseSessionFragment : BaseFragment(), BaseSessionView { override fun showExpiredDialog() { (activity as? MainActivity)?.showExpiredDialog() } + + override fun openLoginView() { + activity?.also { + startActivity(LoginActivity.getStartIntent(it) + .apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) }) + } + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionPresenter.kt index 17ed6537..2c9f50ea 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionPresenter.kt @@ -7,6 +7,9 @@ open class BaseSessionPresenter(private val errorHandler: S override fun onAttachView(view: T) { super.onAttachView(view) - errorHandler.onDecryptionFail = { view.showExpiredDialog() } + errorHandler.apply { + onDecryptionFail = { view.showExpiredDialog() } + onNoCurrentStudent = { view.openLoginView() } + } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionView.kt b/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionView.kt index 81ce4d8f..619c2863 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/session/BaseSessionView.kt @@ -5,4 +5,6 @@ import io.github.wulkanowy.ui.base.BaseView interface BaseSessionView : BaseView { fun showExpiredDialog() + + fun openLoginView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/session/SessionErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/base/session/SessionErrorHandler.kt index 1d81e932..017eabba 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/session/SessionErrorHandler.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/session/SessionErrorHandler.kt @@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.base.session import android.content.res.Resources import com.readystatesoftware.chuck.api.ChuckCollector +import io.github.wulkanowy.data.exceptions.NoCurrentStudentException import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.security.ScramblerException import javax.inject.Inject @@ -13,9 +14,12 @@ open class SessionErrorHandler @Inject constructor( var onDecryptionFail: () -> Unit = {} + var onNoCurrentStudent: () -> Unit = {} + override fun proceed(error: Throwable) { when (error) { is ScramblerException -> onDecryptionFail() + is NoCurrentStudentException -> onNoCurrentStudent() else -> super.proceed(error) } } @@ -23,5 +27,6 @@ open class SessionErrorHandler @Inject constructor( override fun clear() { super.clear() onDecryptionFail = {} + onNoCurrentStudent = {} } } From e71dd5506624b4de66e2847fb2ac459ed5753419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 30 Mar 2019 18:28:37 +0100 Subject: [PATCH 26/33] Fix more than one current semester (#307) --- app/build.gradle | 12 +- .../11.json | 1325 ++++++++++++++++ .../12.json | 1332 +++++++++++++++++ .../data/db/migrations/Migration12Test.kt | 159 ++ .../recipient/RecipientLocalTest.kt | 2 +- .../repositories/student/StudentLocalTest.kt | 2 +- .../io/github/wulkanowy/data/ApiHelper.kt | 2 + .../github/wulkanowy/data/db/AppDatabase.kt | 8 +- .../wulkanowy/data/db/dao/SemesterDao.kt | 4 +- .../wulkanowy/data/db/entities/Student.kt | 5 +- .../data/db/migrations/Migration12.kt | 69 + .../repositories/semester/SemesterLocal.kt | 2 +- .../repositories/student/StudentRemote.kt | 1 + .../repositories/student/StudentRemoteTest.kt | 2 +- .../login/form/LoginFormPresenterTest.kt | 2 +- .../LoginStudentSelectPresenterTest.kt | 2 +- 16 files changed, 2916 insertions(+), 13 deletions(-) create mode 100644 app/schemas/io.github.wulkanowy.data.db.AppDatabase/11.json create mode 100644 app/schemas/io.github.wulkanowy.data.db.AppDatabase/12.json create mode 100644 app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt diff --git a/app/build.gradle b/app/build.gradle index 935710c5..84f4fd87 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,6 +25,15 @@ android { fabric_api_key: System.getenv("FABRIC_API_KEY") ?: "null", crashlytics_enabled: project.hasProperty("enableCrashlytics") ] + javaCompileOptions { + annotationProcessorOptions { + arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] + } + } + } + + sourceSets { + androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) } signingConfigs { @@ -77,7 +86,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('io.github.wulkanowy:api:0.7.3') { exclude module: "threetenbp" } + implementation('com.github.wulkanowy:api:f1152ae') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" @@ -137,6 +146,7 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.0' androidTestImplementation "io.mockk:mockk-android:1.9.2" androidTestImplementation 'org.mockito:mockito-android:2.25.1' + androidTestImplementation "androidx.room:room-testing:2.1.0-alpha06" androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" } diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/11.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/11.json new file mode 100644 index 00000000..e42a4a71 --- /dev/null +++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/11.json @@ -0,0 +1,1325 @@ +{ + "formatVersion": 1, + "database": { + "version": 11, + "identityHash": "478af7daed6ac4563e71826fb70cc8c8", + "entities": [ + { + "tableName": "Students", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_name` TEXT NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "endpoint", + "columnName": "endpoint", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginType", + "columnName": "loginType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "symbol", + "columnName": "symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentName", + "columnName": "student_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolSymbol", + "columnName": "school_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolName", + "columnName": "school_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "registrationDate", + "columnName": "registration_date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Students_email_symbol_student_id_school_id", + "unique": true, + "columnNames": [ + "email", + "symbol", + "student_id", + "school_id" + ], + "createSql": "CREATE UNIQUE INDEX `index_Students_email_symbol_student_id_school_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Semesters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryName", + "columnName": "diary_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterName", + "columnName": "semester_name", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Semesters_student_id_diary_id_semester_id", + "unique": true, + "columnNames": [ + "student_id", + "diary_id", + "semester_id" + ], + "createSql": "CREATE UNIQUE INDEX `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Exams", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Timetable", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subjectOld", + "columnName": "subjectOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "room", + "columnName": "room", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roomOld", + "columnName": "roomOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherOld", + "columnName": "teacherOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "info", + "columnName": "info", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "changes", + "columnName": "changes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "canceled", + "columnName": "canceled", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Attendance", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excused", + "columnName": "excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deleted", + "columnName": "deleted", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "AttendanceSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subjectId", + "columnName": "subject_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "month", + "columnName": "month", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceExcused", + "columnName": "absence_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceForSchoolReasons", + "columnName": "absence_for_school_reasons", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "latenessExcused", + "columnName": "lateness_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Grades", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` INTEGER NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entry", + "columnName": "entry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "modifier", + "columnName": "modifier", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gradeSymbol", + "columnName": "grade_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weightValue", + "columnName": "weightValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predictedGrade` TEXT NOT NULL, `finalGrade` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "predictedGrade", + "columnName": "predictedGrade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalGrade", + "columnName": "finalGrade", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "grade", + "columnName": "grade", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semester", + "columnName": "is_semester", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Messages", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recipient", + "columnName": "recipient_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "folderId", + "columnName": "folder_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unreadBy", + "columnName": "unread_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "readBy", + "columnName": "read_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "removed", + "columnName": "removed", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Notes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `category` TEXT NOT NULL, `content` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Homework", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Subjects", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "LuckyNumbers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "luckyNumber", + "columnName": "lucky_number", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CompletedLesson", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "topic", + "columnName": "topic", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "substitution", + "columnName": "substitution", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "resources", + "columnName": "resources", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ReportingUnits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderName", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roles", + "columnName": "roles", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Recipients", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "realName", + "columnName": "real_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginId", + "columnName": "login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "role", + "columnName": "role", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"478af7daed6ac4563e71826fb70cc8c8\")" + ] + } +} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/12.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/12.json new file mode 100644 index 00000000..32f94355 --- /dev/null +++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/12.json @@ -0,0 +1,1332 @@ +{ + "formatVersion": 1, + "database": { + "version": 12, + "identityHash": "972ad26e6488d9a8239f6bd8597af61d", + "entities": [ + { + "tableName": "Students", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "endpoint", + "columnName": "endpoint", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginType", + "columnName": "loginType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "symbol", + "columnName": "symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentName", + "columnName": "student_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolSymbol", + "columnName": "school_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolName", + "columnName": "school_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "registrationDate", + "columnName": "registration_date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Students_email_symbol_student_id_school_id_class_id", + "unique": true, + "columnNames": [ + "email", + "symbol", + "student_id", + "school_id", + "class_id" + ], + "createSql": "CREATE UNIQUE INDEX `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Semesters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryName", + "columnName": "diary_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterName", + "columnName": "semester_name", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Semesters_student_id_diary_id_semester_id", + "unique": true, + "columnNames": [ + "student_id", + "diary_id", + "semester_id" + ], + "createSql": "CREATE UNIQUE INDEX `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Exams", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Timetable", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subjectOld", + "columnName": "subjectOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "room", + "columnName": "room", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roomOld", + "columnName": "roomOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherOld", + "columnName": "teacherOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "info", + "columnName": "info", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "changes", + "columnName": "changes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "canceled", + "columnName": "canceled", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Attendance", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excused", + "columnName": "excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deleted", + "columnName": "deleted", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "AttendanceSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subjectId", + "columnName": "subject_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "month", + "columnName": "month", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceExcused", + "columnName": "absence_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceForSchoolReasons", + "columnName": "absence_for_school_reasons", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "latenessExcused", + "columnName": "lateness_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Grades", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` INTEGER NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entry", + "columnName": "entry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "modifier", + "columnName": "modifier", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gradeSymbol", + "columnName": "grade_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weightValue", + "columnName": "weightValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predictedGrade` TEXT NOT NULL, `finalGrade` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "predictedGrade", + "columnName": "predictedGrade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalGrade", + "columnName": "finalGrade", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "grade", + "columnName": "grade", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semester", + "columnName": "is_semester", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Messages", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recipient", + "columnName": "recipient_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "folderId", + "columnName": "folder_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unreadBy", + "columnName": "unread_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "readBy", + "columnName": "read_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "removed", + "columnName": "removed", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Notes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `category` TEXT NOT NULL, `content` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Homework", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Subjects", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "LuckyNumbers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "luckyNumber", + "columnName": "lucky_number", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CompletedLesson", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "topic", + "columnName": "topic", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "substitution", + "columnName": "substitution", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "resources", + "columnName": "resources", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ReportingUnits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderName", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roles", + "columnName": "roles", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Recipients", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "realName", + "columnName": "real_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginId", + "columnName": "login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "role", + "columnName": "role", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"972ad26e6488d9a8239f6bd8597af61d\")" + ] + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt new file mode 100644 index 00000000..c61e9305 --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt @@ -0,0 +1,159 @@ +package io.github.wulkanowy.data.db.migrations + +import android.content.ContentValues +import android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL +import androidx.room.Room +import androidx.room.testing.MigrationTestHelper +import androidx.sqlite.db.SupportSQLiteDatabase +import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import io.github.wulkanowy.data.db.AppDatabase +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import kotlin.test.assertEquals + +@RunWith(AndroidJUnit4::class) +class Migration12Test { + + private val dbName = "migration-test" + + @get:Rule + val helper: MigrationTestHelper = MigrationTestHelper( + InstrumentationRegistry.getInstrumentation(), + AppDatabase::class.java.canonicalName, + FrameworkSQLiteOpenHelperFactory() + ) + + @Test + fun migrate11To12_twoNotRelatedStudents() { + helper.createDatabase(dbName, 11).apply { + // user 1 + createStudent(this, 1, true) + createSemester(this, 1, false, 5, 1) + createSemester(this, 1, true, 5, 2) + + // user 2 + createStudent(this, 2, true) + createSemester(this, 2, false, 6, 1) + createSemester(this, 2, true, 6, 2) + close() + } + + helper.runMigrationsAndValidate(dbName, 12, true, Migration12()) + + val db = getMigratedRoomDatabase() + val students = db.studentDao.loadAll().blockingGet() + + assertEquals(2, students.size) + + students[0].run { + assertEquals(1, studentId) + assertEquals(5, classId) + } + + students[1].run { + assertEquals(2, studentId) + assertEquals(6, classId) + } + } + + @Test + fun migrate11To12_removeStudentsWithoutClassId() { + helper.createDatabase(dbName, 11).apply { + // user 1 + createStudent(this, 1, true) + createSemester(this, 1, false, 0, 2) + createStudent(this, 2, true) + createSemester(this, 2, true, 1, 2) + close() + } + + helper.runMigrationsAndValidate(dbName, 12, true, Migration12()) + + val db = getMigratedRoomDatabase() + val students = db.studentDao.loadAll().blockingGet() + + assertEquals(1, students.size) + + students[0].run { + assertEquals(2, studentId) + assertEquals(1, classId) + } + } + + @Test + fun migrate11To12_ensureThereIsOnlyOneCurrentStudent() { + helper.createDatabase(dbName, 11).apply { + // user 1 + createStudent(this, 1, true) + createSemester(this, 1, true, 5, 2) + createStudent(this, 2, true) + createSemester(this, 2, true, 6, 2) + createStudent(this, 3, true) + createSemester(this, 3, false, 7, 2) + close() + } + + helper.runMigrationsAndValidate(dbName, 12, true, Migration12()) + + val db = getMigratedRoomDatabase() + val students = db.studentDao.loadAll().blockingGet() + + assertEquals(3, students.size) + + students[0].run { + assertEquals(studentId, 1) + assertEquals(false, isCurrent) + } + students[1].run { + assertEquals(studentId, 2) + assertEquals(false, isCurrent) + } + students[2].run { + assertEquals(studentId, 3) + assertEquals(true, isCurrent) + } + } + + private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, isCurrent: Boolean) { + db.insert("Students", CONFLICT_FAIL, ContentValues().apply { + put("endpoint", "https://fakelog.cf") + put("loginType", "STANDARD") + put("email", "jan@fakelog.cf") + put("password", "******") + put("symbol", "Default") + put("student_id", studentId) + put("student_name", "Jan Kowalski") + put("school_id", "000123") + put("school_name", "") + put("is_current", isCurrent) + put("registration_date", "0") + }) + } + + private fun createSemester(db: SupportSQLiteDatabase, studentId: Int, isCurrent: Boolean, classId: Int, diaryId: Int) { + db.insert("Semesters", CONFLICT_FAIL, ContentValues().apply { + put("student_id", studentId) + put("diary_id", diaryId) + put("diary_name", "IA") + put("semester_id", diaryId * 5) + put("semester_name", "1") + put("is_current", isCurrent) + put("class_id", classId) + put("unit_id", "99") + }) + } + + private fun getMigratedRoomDatabase(): AppDatabase { + val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(), + AppDatabase::class.java, dbName) + .addMigrations(Migration12()) + .build() + // close the database and release any stream resources when the test finishes + helper.closeWhenFinished(database) + return database + } +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt index 1f6562a2..cc4dd9f3 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt @@ -42,7 +42,7 @@ class RecipientLocalTest { )) val recipients = recipientLocal.getRecipients( - Student("fakelog.cf", "AUTO", "", "", "", 1, "", "", "", true, LocalDateTime.now()), + Student("fakelog.cf", "AUTO", "", "", "", 1, "", "", "", 1, true, LocalDateTime.now()), 2, ReportingUnit(1, 4, "", 0, "", emptyList()) ).blockingGet() diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt index c31bc806..f61c6374 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt @@ -39,7 +39,7 @@ class StudentLocalTest { @Test fun saveAndReadTest() { - studentLocal.saveStudent(Student(email = "test", password = "test123", schoolSymbol = "23", endpoint = "fakelog.cf", loginType = "AUTO", isCurrent = true, studentName = "", schoolName = "", studentId = 0, symbol = "", registrationDate = now())) + studentLocal.saveStudent(Student(email = "test", password = "test123", schoolSymbol = "23", endpoint = "fakelog.cf", loginType = "AUTO", isCurrent = true, studentName = "", schoolName = "", studentId = 0, classId = 1, symbol = "", registrationDate = now())) .blockingGet() val student = studentLocal.getCurrentStudent(true).blockingGet() diff --git a/app/src/main/java/io/github/wulkanowy/data/ApiHelper.kt b/app/src/main/java/io/github/wulkanowy/data/ApiHelper.kt index 5ef40ce8..b6eee316 100644 --- a/app/src/main/java/io/github/wulkanowy/data/ApiHelper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/ApiHelper.kt @@ -14,6 +14,7 @@ class ApiHelper @Inject constructor(private val api: Api) { symbol = student.symbol schoolSymbol = student.schoolSymbol studentId = student.studentId + classId = student.classId host = URL(student.endpoint).run { host + ":$port".removeSuffix(":-1") } ssl = student.endpoint.startsWith("https") loginType = Api.LoginType.valueOf(student.loginType) @@ -28,6 +29,7 @@ class ApiHelper @Inject constructor(private val api: Api) { this.symbol = symbol host = URL(endpoint).run { host + ":$port".removeSuffix(":-1") } ssl = endpoint.startsWith("https") + useNewStudent = true } } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt index 4fefd9c9..9ce62b18 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt @@ -42,6 +42,7 @@ import io.github.wulkanowy.data.db.entities.Subject import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.migrations.Migration10 import io.github.wulkanowy.data.db.migrations.Migration11 +import io.github.wulkanowy.data.db.migrations.Migration12 import io.github.wulkanowy.data.db.migrations.Migration2 import io.github.wulkanowy.data.db.migrations.Migration3 import io.github.wulkanowy.data.db.migrations.Migration4 @@ -74,13 +75,13 @@ import javax.inject.Singleton Recipient::class ], version = AppDatabase.VERSION_SCHEMA, - exportSchema = false + exportSchema = true ) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION_SCHEMA = 11 + const val VERSION_SCHEMA = 12 fun newInstance(context: Context): AppDatabase { return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database") @@ -97,7 +98,8 @@ abstract class AppDatabase : RoomDatabase() { Migration8(), Migration9(), Migration10(), - Migration11() + Migration11(), + Migration12() ) .build() } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt index 608a6663..01841fb6 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt @@ -18,6 +18,6 @@ interface SemesterDao { @Delete fun deleteAll(semester: List) - @Query("SELECT * FROM Semesters WHERE student_id = :studentId") - fun loadAll(studentId: Int): Maybe> + @Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId") + fun loadAll(studentId: Int, classId: Int): Maybe> } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt index 261b35fb..9cacf835 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt @@ -7,7 +7,7 @@ import androidx.room.PrimaryKey import org.threeten.bp.LocalDateTime import java.io.Serializable -@Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id"], unique = true)]) +@Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id", "class_id"], unique = true)]) data class Student( val endpoint: String, @@ -32,6 +32,9 @@ data class Student( @ColumnInfo(name = "school_name") val schoolName: String, + @ColumnInfo(name = "class_id") + val classId: Int, + @ColumnInfo(name = "is_current") val isCurrent: Boolean, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt new file mode 100644 index 00000000..1dc38e14 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt @@ -0,0 +1,69 @@ +package io.github.wulkanowy.data.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration12 : Migration(11, 12) { + + override fun migrate(database: SupportSQLiteDatabase) { + createTempStudentsTable(database) + replaceStudentTable(database) + updateStudentsWithClassId(database, getStudentsIds(database)) + removeStudentsWithNoClassId(database) + ensureThereIsOnlyOneCurrentStudent(database) + } + + private fun createTempStudentsTable(database: SupportSQLiteDatabase) { + database.execSQL(""" + CREATE TABLE IF NOT EXISTS Students_tmp ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + endpoint TEXT NOT NULL, + loginType TEXT NOT NULL, + email TEXT NOT NULL, + password TEXT NOT NULL, + symbol TEXT NOT NULL, + student_id INTEGER NOT NULL, + student_name TEXT NOT NULL, + school_id TEXT NOT NULL, + school_name TEXT NOT NULL, + is_current INTEGER NOT NULL, + registration_date INTEGER NOT NULL, + class_id INTEGER NOT NULL + ) + """) + database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students_tmp (email, symbol, student_id, school_id, class_id)") + } + + private fun replaceStudentTable(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Students ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL") + database.execSQL("INSERT INTO Students_tmp SELECT * FROM Students") + database.execSQL("DROP TABLE Students") + database.execSQL("ALTER TABLE Students_tmp RENAME TO Students") + } + + private fun getStudentsIds(database: SupportSQLiteDatabase): List { + val students = mutableListOf() + val studentsCursor = database.query("SELECT student_id FROM Students") + if (studentsCursor.moveToFirst()) { + do { + students.add(studentsCursor.getInt(0)) + } while (studentsCursor.moveToNext()) + } + return students + } + + private fun updateStudentsWithClassId(database: SupportSQLiteDatabase, students: List) { + students.forEach { + database.execSQL("UPDATE Students SET class_id = IFNULL((SELECT class_id FROM Semesters WHERE student_id = $it), 0) WHERE student_id = $it") + } + } + + private fun removeStudentsWithNoClassId(database: SupportSQLiteDatabase) { + database.execSQL("DELETE FROM Students WHERE class_id = 0") + } + + private fun ensureThereIsOnlyOneCurrentStudent(database: SupportSQLiteDatabase) { + database.execSQL("UPDATE Students SET is_current = 0") + database.execSQL("UPDATE Students SET is_current = 1 WHERE id = (SELECT MAX(id) FROM Students)") + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt index 37d4a268..b9750e7d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt @@ -19,6 +19,6 @@ class SemesterLocal @Inject constructor(private val semesterDb: SemesterDao) { } fun getSemesters(student: Student): Maybe> { - return semesterDb.loadAll(student.studentId).filter { !it.isEmpty() } + return semesterDb.loadAll(student.studentId, student.classId).filter { !it.isEmpty() } } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt index 7a504cca..f0692a53 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt @@ -21,6 +21,7 @@ class StudentRemote @Inject constructor(private val api: Api) { studentName = student.studentName, schoolSymbol = student.schoolSymbol, schoolName = student.schoolName, + classId = student.classId, endpoint = endpoint, loginType = student.loginType.name, isCurrent = false, diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt index 1244239e..8bd819e2 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt @@ -22,7 +22,7 @@ class StudentRemoteTest { @Test fun testRemoteAll() { - doReturn(Single.just(listOf(Student("", "", 1, "test", "", "", Api.LoginType.AUTO)))) + doReturn(Single.just(listOf(Student("", "", 1, "test", "", "", 1, Api.LoginType.AUTO)))) .`when`(mockApi).getStudents() val students = StudentRemote(mockApi).getStudents("", "", "").blockingGet() diff --git a/app/src/test/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenterTest.kt b/app/src/test/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenterTest.kt index e2d910a9..f1113f7b 100644 --- a/app/src/test/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenterTest.kt +++ b/app/src/test/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenterTest.kt @@ -86,7 +86,7 @@ class LoginFormPresenterTest { @Test fun loginTest() { - val studentTest = Student(email = "test@", password = "123", endpoint = "https://fakelog.cf", loginType = "AUTO", studentName = "", schoolSymbol = "", schoolName = "", studentId = 0, isCurrent = false, symbol = "", registrationDate = now()) + val studentTest = Student(email = "test@", password = "123", endpoint = "https://fakelog.cf", loginType = "AUTO", studentName = "", schoolSymbol = "", schoolName = "", studentId = 0, classId = 1, isCurrent = false, symbol = "", registrationDate = now()) doReturn(Single.just(listOf(studentTest))) .`when`(repository).getStudents(anyString(), anyString(), anyString(), anyString()) diff --git a/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt b/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt index 1059e0ac..2de4e43a 100644 --- a/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt +++ b/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt @@ -32,7 +32,7 @@ class LoginStudentSelectPresenterTest { private lateinit var presenter: LoginStudentSelectPresenter - private val testStudent by lazy { Student(email = "test", password = "test123", endpoint = "https://fakelog.cf", loginType = "AUTO", symbol = "", isCurrent = false, studentId = 0, schoolName = "", schoolSymbol = "", studentName = "", registrationDate = now()) } + private val testStudent by lazy { Student(email = "test", password = "test123", endpoint = "https://fakelog.cf", loginType = "AUTO", symbol = "", isCurrent = false, studentId = 0, schoolName = "", schoolSymbol = "", classId = 1, studentName = "", registrationDate = now()) } private val testException by lazy { RuntimeException("Problem") } From 935bec3f5bd8b225bee1976bd92659fb25b64420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 30 Mar 2019 19:26:19 +0100 Subject: [PATCH 27/33] Add 0,75 grade modifier (#313) --- app/src/main/res/values-pl/value_prefernces.xml | 1 + app/src/main/res/values/value_prefernces.xml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/app/src/main/res/values-pl/value_prefernces.xml b/app/src/main/res/values-pl/value_prefernces.xml index 05f2ed50..2231cc0b 100644 --- a/app/src/main/res/values-pl/value_prefernces.xml +++ b/app/src/main/res/values-pl/value_prefernces.xml @@ -22,6 +22,7 @@ 0,25 0,33 0,5 + 0,75 diff --git a/app/src/main/res/values/value_prefernces.xml b/app/src/main/res/values/value_prefernces.xml index 1a1dceca..661615e1 100644 --- a/app/src/main/res/values/value_prefernces.xml +++ b/app/src/main/res/values/value_prefernces.xml @@ -50,12 +50,14 @@ 0,25 0,33 0,5 + 0,75 0.0 0.25 0.33 0.5 + 0.75 From 297a2909ba13a2a92fa77e9cfdd7226ac476c00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 30 Mar 2019 19:44:27 +0100 Subject: [PATCH 28/33] Version 0.7.4 --- .travis.yml | 8 ++++---- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 11 ++++++++--- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index b3261931..56c64858 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,10 @@ cache: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ -branches: - only: - - master - - 0.7.x +#branches: +# only: +# - master +# - 0.7.x android: licenses: diff --git a/app/build.gradle b/app/build.gradle index 84f4fd87..22af6e6b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 15 targetSdkVersion 28 - versionCode 29 - versionName "0.7.3" + versionCode 30 + versionName "0.7.4" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -86,7 +86,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('com.github.wulkanowy:api:f1152ae') { exclude module: "threetenbp" } + implementation('io.github.wulkanowy:api:0.7.4') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt index 6cf59d4b..c85a155b 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,6 +1,11 @@ -Wersja 0.7.3 +Wersja 0.7.4 Naprawiliśmy: -- naprawiono problemy ze stabilnością podczas odświeżania danych +- problem ze stabilnością na androidach 4 i 5 +- problem z przełączaniem kont, jeśli zalogowany był jednocześnie uczeń i rodzic +- problem z odświeżaniem danych, jeśli uczeń przeniósł się z klasy do klasy w bieżącym roku szkolnym -Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.3 +Dodaliśmy: +- nową opcję zmiany wartości plusa i minusa na 0.75 + +Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.4 From 8daea5c90074772c2dc74372e3cb7773c6406717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Thu, 4 Apr 2019 13:00:07 +0200 Subject: [PATCH 29/33] Add class name to student (#315) --- .travis.yml | 8 +- app/build.gradle | 2 +- .../13.json | 1356 +++++++++++++++++ .../db/migrations/AbstractMigrationTest.kt | 31 + .../data/db/migrations/Migration12Test.kt | 34 +- .../data/db/migrations/Migration13Test.kt | 171 +++ .../attendance/AttendanceLocalTest.kt | 3 +- .../CompletedLessonsLocalTest.kt | 2 +- .../data/repositories/exam/ExamLocalTest.kt | 2 +- .../data/repositories/grade/GradeLocalTest.kt | 5 +- .../GradeStatisticsLocalTest.kt | 5 +- .../luckynumber/LuckyNumberLocalTest.kt | 2 +- .../recipient/RecipientLocalTest.kt | 2 +- .../repositories/student/StudentLocalTest.kt | 2 +- .../timetable/TimetableLocalTest.kt | 2 +- .../github/wulkanowy/data/db/AppDatabase.kt | 6 +- .../wulkanowy/data/db/entities/Semester.kt | 8 + .../wulkanowy/data/db/entities/Student.kt | 3 + .../data/db/migrations/Migration13.kt | 59 + .../repositories/semester/SemesterRemote.kt | 3 + .../repositories/student/StudentRemote.kt | 1 + .../ui/modules/account/AccountItem.kt | 4 +- .../studentselect/LoginStudentSelectItem.kt | 4 +- app/src/main/res/layout/item_account.xml | 10 +- .../semester/TestSemesterEnityCreator.kt | 6 +- .../repositories/student/StudentRemoteTest.kt | 2 +- .../login/form/LoginFormPresenterTest.kt | 2 +- .../LoginStudentSelectPresenterTest.kt | 2 +- 28 files changed, 1680 insertions(+), 57 deletions(-) create mode 100644 app/schemas/io.github.wulkanowy.data.db.AppDatabase/13.json create mode 100644 app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt create mode 100644 app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt diff --git a/.travis.yml b/.travis.yml index 56c64858..b3261931 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,10 @@ cache: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ -#branches: -# only: -# - master -# - 0.7.x +branches: + only: + - master + - 0.7.x android: licenses: diff --git a/app/build.gradle b/app/build.gradle index 22af6e6b..6b6a1301 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -86,7 +86,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('io.github.wulkanowy:api:0.7.4') { exclude module: "threetenbp" } + implementation('com.github.wulkanowy:api:383ff93') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/13.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/13.json new file mode 100644 index 00000000..ab554665 --- /dev/null +++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/13.json @@ -0,0 +1,1356 @@ +{ + "formatVersion": 1, + "database": { + "version": 13, + "identityHash": "18643bb64804b8268ec9395e3dd55ecb", + "entities": [ + { + "tableName": "Students", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "endpoint", + "columnName": "endpoint", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginType", + "columnName": "loginType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "symbol", + "columnName": "symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentName", + "columnName": "student_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolSymbol", + "columnName": "school_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolName", + "columnName": "school_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "className", + "columnName": "class_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "registrationDate", + "columnName": "registration_date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Students_email_symbol_student_id_school_id_class_id", + "unique": true, + "columnNames": [ + "email", + "symbol", + "student_id", + "school_id", + "class_id" + ], + "createSql": "CREATE UNIQUE INDEX `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Semesters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryName", + "columnName": "diary_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolYear", + "columnName": "school_year", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterName", + "columnName": "semester_name", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Semesters_student_id_diary_id_semester_id", + "unique": true, + "columnNames": [ + "student_id", + "diary_id", + "semester_id" + ], + "createSql": "CREATE UNIQUE INDEX `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Exams", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Timetable", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subjectOld", + "columnName": "subjectOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "room", + "columnName": "room", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roomOld", + "columnName": "roomOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherOld", + "columnName": "teacherOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "info", + "columnName": "info", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "changes", + "columnName": "changes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "canceled", + "columnName": "canceled", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Attendance", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excused", + "columnName": "excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deleted", + "columnName": "deleted", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "AttendanceSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subjectId", + "columnName": "subject_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "month", + "columnName": "month", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceExcused", + "columnName": "absence_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceForSchoolReasons", + "columnName": "absence_for_school_reasons", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "latenessExcused", + "columnName": "lateness_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Grades", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` INTEGER NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entry", + "columnName": "entry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "modifier", + "columnName": "modifier", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gradeSymbol", + "columnName": "grade_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weightValue", + "columnName": "weightValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predictedGrade` TEXT NOT NULL, `finalGrade` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "predictedGrade", + "columnName": "predictedGrade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalGrade", + "columnName": "finalGrade", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "grade", + "columnName": "grade", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semester", + "columnName": "is_semester", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Messages", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recipient", + "columnName": "recipient_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "folderId", + "columnName": "folder_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unreadBy", + "columnName": "unread_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "readBy", + "columnName": "read_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "removed", + "columnName": "removed", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Notes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `category` TEXT NOT NULL, `content` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Homework", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Subjects", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "LuckyNumbers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "luckyNumber", + "columnName": "lucky_number", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CompletedLesson", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "topic", + "columnName": "topic", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "substitution", + "columnName": "substitution", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "resources", + "columnName": "resources", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ReportingUnits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderName", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roles", + "columnName": "roles", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Recipients", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "realName", + "columnName": "real_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginId", + "columnName": "login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "role", + "columnName": "role", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"18643bb64804b8268ec9395e3dd55ecb\")" + ] + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt new file mode 100644 index 00000000..507105f6 --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt @@ -0,0 +1,31 @@ +package io.github.wulkanowy.data.db.migrations + +import androidx.room.Room +import androidx.room.testing.MigrationTestHelper +import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory +import androidx.test.core.app.ApplicationProvider +import androidx.test.platform.app.InstrumentationRegistry +import io.github.wulkanowy.data.db.AppDatabase +import org.junit.Rule + +abstract class AbstractMigrationTest { + + val dbName = "migration-test" + + @get:Rule + val helper: MigrationTestHelper = MigrationTestHelper( + InstrumentationRegistry.getInstrumentation(), + AppDatabase::class.java.canonicalName, + FrameworkSQLiteOpenHelperFactory() + ) + + fun getMigratedRoomDatabase(): AppDatabase { + val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(), + AppDatabase::class.java, dbName) + .addMigrations(Migration12(), Migration13()) + .build() + // close the database and release any stream resources when the test finishes + helper.closeWhenFinished(database) + return database + } +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt index c61e9305..0bbcc427 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt @@ -2,33 +2,17 @@ package io.github.wulkanowy.data.db.migrations import android.content.ContentValues import android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL -import androidx.room.Room -import androidx.room.testing.MigrationTestHelper import androidx.sqlite.db.SupportSQLiteDatabase -import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory -import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import io.github.wulkanowy.data.db.AppDatabase -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import kotlin.test.assertEquals @RunWith(AndroidJUnit4::class) -class Migration12Test { - - private val dbName = "migration-test" - - @get:Rule - val helper: MigrationTestHelper = MigrationTestHelper( - InstrumentationRegistry.getInstrumentation(), - AppDatabase::class.java.canonicalName, - FrameworkSQLiteOpenHelperFactory() - ) +class Migration12Test : AbstractMigrationTest() { @Test - fun migrate11To12_twoNotRelatedStudents() { + fun twoNotRelatedStudents() { helper.createDatabase(dbName, 11).apply { // user 1 createStudent(this, 1, true) @@ -61,7 +45,7 @@ class Migration12Test { } @Test - fun migrate11To12_removeStudentsWithoutClassId() { + fun removeStudentsWithoutClassId() { helper.createDatabase(dbName, 11).apply { // user 1 createStudent(this, 1, true) @@ -85,7 +69,7 @@ class Migration12Test { } @Test - fun migrate11To12_ensureThereIsOnlyOneCurrentStudent() { + fun ensureThereIsOnlyOneCurrentStudent() { helper.createDatabase(dbName, 11).apply { // user 1 createStudent(this, 1, true) @@ -146,14 +130,4 @@ class Migration12Test { put("unit_id", "99") }) } - - private fun getMigratedRoomDatabase(): AppDatabase { - val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(), - AppDatabase::class.java, dbName) - .addMigrations(Migration12()) - .build() - // close the database and release any stream resources when the test finishes - helper.closeWhenFinished(database) - return database - } } diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt new file mode 100644 index 00000000..eb9d02a5 --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt @@ -0,0 +1,171 @@ +package io.github.wulkanowy.data.db.migrations + +import android.content.ContentValues +import android.database.sqlite.SQLiteDatabase +import androidx.sqlite.db.SupportSQLiteDatabase +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Test +import org.threeten.bp.LocalDate.of +import kotlin.test.assertTrue + +class Migration13Test : AbstractMigrationTest() { + + @Test + fun studentsWithSchoolNameWithClassName() { + helper.createDatabase(dbName, 12).apply { + createStudent(this, 1, "Klasa A - Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", 1, 1) + createStudent(this, 2, "Klasa B - Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", 2, 1) + createStudent(this, 2, "Klasa C - Publiczna szkoła Wulkanowego-fejka nr 2 w fakelog.cf", 1, 2) + close() + } + + helper.runMigrationsAndValidate(dbName, 13, true, Migration13()) + + val db = getMigratedRoomDatabase() + val students = db.studentDao.loadAll().blockingGet() + + assertEquals(3, students.size) + + students[0].run { + assertEquals(1, studentId) + assertEquals("A", className) + assertEquals("Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", schoolName) + } + + students[1].run { + assertEquals(2, studentId) + assertEquals("B", className) + assertEquals("Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", schoolName) + } + + students[2].run { + assertEquals(2, studentId) + assertEquals("C", className) + assertEquals("Publiczna szkoła Wulkanowego-fejka nr 2 w fakelog.cf", schoolName) + } + } + + @Test + fun studentsWithSchoolNameWithoutClassName() { + helper.createDatabase(dbName, 12).apply { + createStudent(this, 1, "Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", 1) + createStudent(this, 2, "Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", 1) + close() + } + + helper.runMigrationsAndValidate(dbName, 13, true, Migration13()) + + val db = getMigratedRoomDatabase() + val students = db.studentDao.loadAll().blockingGet() + + assertEquals(2, students.size) + + students[0].run { + assertEquals(1, studentId) + assertEquals("", className) + assertEquals("Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", schoolName) + } + + students[1].run { + assertEquals(2, studentId) + assertEquals("", className) + assertEquals("Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", schoolName) + } + } + + @Test + fun markAtLeastAndOnlyOneSemesterAtCurrent() { + helper.createDatabase(dbName, 12).apply { + createStudent(this, 1, "", 5) + createSemester(this, 1, 5, 1, 1, false) + createSemester(this, 1, 5, 2, 1, false) + createSemester(this, 1, 5, 3, 2, false) + createSemester(this, 1, 5, 4, 2, false) + + createStudent(this, 2, "", 5) + createSemester(this, 2, 5, 5, 5, true) + createSemester(this, 2, 5, 6, 5, true) + createSemester(this, 2, 5, 7, 55, true) + createSemester(this, 2, 5, 8, 55, true) + + createStudent(this, 3, "", 5) + createSemester(this, 3, 5, 11, 99, false) + createSemester(this, 3, 5, 12, 99, false) + createSemester(this, 3, 5, 13, 100, false) + createSemester(this, 3, 5, 14, 100, true) + close() + } + + helper.runMigrationsAndValidate(dbName, 13, true, Migration13()) + + val db = getMigratedRoomDatabase() + + val semesters1 = db.semesterDao.loadAll(1, 5).blockingGet() + assertTrue { semesters1.single { it.isCurrent }.isCurrent } + semesters1[0].run { + assertFalse(isCurrent) + assertEquals(1, semesterId) + assertEquals(1, diaryId) + } + semesters1[2].run { + assertFalse(isCurrent) + assertEquals(3, semesterId) + assertEquals(2, diaryId) + } + semesters1[3].run { + assertTrue(isCurrent) + assertEquals(4, semesterId) + assertEquals(2, diaryId) + } + + db.semesterDao.loadAll(2, 5).blockingGet().let { + assertTrue { it.single { it.isCurrent }.isCurrent } + assertEquals(1970, it[0].schoolYear) + assertEquals(of(1970, 1, 1), it[0].end) + assertEquals(of(1970, 1, 1), it[0].start) + assertFalse(it[0].isCurrent) + assertFalse(it[1].isCurrent) + assertFalse(it[2].isCurrent) + assertTrue(it[3].isCurrent) + } + + db.semesterDao.loadAll(2, 5).blockingGet().let { + assertTrue { it.single { it.isCurrent }.isCurrent } + assertFalse(it[0].isCurrent) + assertFalse(it[1].isCurrent) + assertFalse(it[2].isCurrent) + assertTrue(it[3].isCurrent) + } + } + + private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, schoolName: String = "", classId: Int = -1, schoolId: Int = 123) { + db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { + put("endpoint", "https://fakelog.cf") + put("loginType", "STANDARD") + put("email", "jan@fakelog.cf") + put("password", "******") + put("symbol", "Default") + put("student_id", studentId) + put("class_id", classId) + put("student_name", "Jan Kowalski") + put("school_id", schoolId) + put("school_name", schoolName) + put("is_current", false) + put("registration_date", "0") + }) + } + + private fun createSemester(db: SupportSQLiteDatabase, studentId: Int, classId: Int, semesterId: Int, diaryId: Int, isCurrent: Boolean = false) { + db.insert("Semesters", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { + put("student_id", studentId) + put("diary_id", diaryId) + put("diary_name", "IA") + put("semester_id", semesterId) + put("semester_name", "1") + put("is_current", isCurrent) + put("class_id", classId) + put("unit_id", "99") + }) + } +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt index ee65cf84..69502e74 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt @@ -11,6 +11,7 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.threeten.bp.LocalDate +import org.threeten.bp.LocalDate.now import kotlin.test.assertEquals @RunWith(AndroidJUnit4::class) @@ -40,7 +41,7 @@ class AttendanceLocalTest { )) val attendance = attendanceLocal - .getAttendance(Semester(1, 2, "", 1, 3, true, 1, 1), + .getAttendance(Semester(1, 2, "", 1, 3, 2019, true, now(), now(), 1, 1), LocalDate.of(2018, 9, 10), LocalDate.of(2018, 9, 14) ) diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt index 014f0b8b..356073e8 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt @@ -41,7 +41,7 @@ class CompletedLessonsLocalTest { )) val completed = completedLessonsLocal - .getCompletedLessons(Semester(1, 2, "", 1, 3, true, 1, 1), + .getCompletedLessons(Semester(1, 2, "", 1, 3, 2019, true, LocalDate.now(), LocalDate.now(), 1, 1), LocalDate.of(2018, 9, 10), LocalDate.of(2018, 9, 14) ) diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt index dc66fa42..fb76306d 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt @@ -40,7 +40,7 @@ class ExamLocalTest { )) val exams = examLocal - .getExams(Semester(1, 2, "", 1, 3, true, 1, 1), + .getExams(Semester(1, 2, "", 1, 3, 2019, true, LocalDate.now(), LocalDate.now(), 1, 1), LocalDate.of(2018, 9, 10), LocalDate.of(2018, 9, 14) ) diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt index 36238f1b..954d0eea 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt @@ -10,6 +10,7 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.threeten.bp.LocalDate +import org.threeten.bp.LocalDate.now import kotlin.test.assertEquals @RunWith(AndroidJUnit4::class) @@ -39,8 +40,10 @@ class GradeLocalTest { createGradeLocal(3, 5.0, LocalDate.of(2019, 2, 28), "", 2) )) + val semester = Semester(1, 2, "", 2019, 2, 1, true, now(), now(), 1, 1) + val grades = gradeLocal - .getGrades(Semester(1, 2, "", 2, 3, true, 1, 1)) + .getGrades(semester) .blockingGet() assertEquals(2, grades.size) diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt index 5c0590e7..0057a26e 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt @@ -10,6 +10,7 @@ import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.threeten.bp.LocalDate import kotlin.test.assertEquals @RunWith(AndroidJUnit4::class) @@ -39,7 +40,7 @@ class GradeStatisticsLocalTest { )) val stats = gradeStatisticsLocal.getGradesStatistics( - Semester(2, 2, "", 1, 2, true, 1, 1), false, + Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1), false, "Matematyka" ).blockingGet() assertEquals(1, stats.size) @@ -55,7 +56,7 @@ class GradeStatisticsLocalTest { )) val stats = gradeStatisticsLocal.getGradesStatistics( - Semester(2, 2, "", 1, 2, true, 1, 1), false, + Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1), false, "Wszystkie" ).blockingGet() assertEquals(1, stats.size) diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt index a656ac05..77ddafb9 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt @@ -36,7 +36,7 @@ class LuckyNumberLocalTest { fun saveAndReadTest() { luckyNumberLocal.saveLuckyNumber(LuckyNumber(1, LocalDate.of(2019, 1, 20), 14)) - val luckyNumber = luckyNumberLocal.getLuckyNumber(Semester(1, 1, "", 1, 3, true, 1, 1), + val luckyNumber = luckyNumberLocal.getLuckyNumber(Semester(1, 1, "", 1, 3, 2019, true, LocalDate.now(), LocalDate.now(), 1, 1), LocalDate.of(2019, 1, 20) ).blockingGet() diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt index cc4dd9f3..6edaccdb 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt @@ -42,7 +42,7 @@ class RecipientLocalTest { )) val recipients = recipientLocal.getRecipients( - Student("fakelog.cf", "AUTO", "", "", "", 1, "", "", "", 1, true, LocalDateTime.now()), + Student("fakelog.cf", "AUTO", "", "", "", 1, "", "", "", "", 1, true, LocalDateTime.now()), 2, ReportingUnit(1, 4, "", 0, "", emptyList()) ).blockingGet() diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt index f61c6374..b27446fa 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt @@ -39,7 +39,7 @@ class StudentLocalTest { @Test fun saveAndReadTest() { - studentLocal.saveStudent(Student(email = "test", password = "test123", schoolSymbol = "23", endpoint = "fakelog.cf", loginType = "AUTO", isCurrent = true, studentName = "", schoolName = "", studentId = 0, classId = 1, symbol = "", registrationDate = now())) + studentLocal.saveStudent(Student(email = "test", password = "test123", schoolSymbol = "23", endpoint = "fakelog.cf", loginType = "AUTO", isCurrent = true, studentName = "", schoolName = "", studentId = 0, classId = 1, symbol = "", registrationDate = now(), className = "")) .blockingGet() val student = studentLocal.getCurrentStudent(true).blockingGet() diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt index 0ecbcf92..fe25e4e9 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt @@ -41,7 +41,7 @@ class TimetableLocalTest { )) val exams = timetableDb.getTimetable( - Semester(1, 2, "", 1, 1, true, 1, 1), + Semester(1, 2, "", 1, 1, 2019, true, LocalDate.now(), LocalDate.now(), 1, 1), LocalDate.of(2018, 9, 10), LocalDate.of(2018, 9, 14) ).blockingGet() diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt index 9ce62b18..d867583e 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt @@ -43,6 +43,7 @@ import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.migrations.Migration10 import io.github.wulkanowy.data.db.migrations.Migration11 import io.github.wulkanowy.data.db.migrations.Migration12 +import io.github.wulkanowy.data.db.migrations.Migration13 import io.github.wulkanowy.data.db.migrations.Migration2 import io.github.wulkanowy.data.db.migrations.Migration3 import io.github.wulkanowy.data.db.migrations.Migration4 @@ -81,7 +82,7 @@ import javax.inject.Singleton abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION_SCHEMA = 12 + const val VERSION_SCHEMA = 13 fun newInstance(context: Context): AppDatabase { return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database") @@ -99,7 +100,8 @@ abstract class AppDatabase : RoomDatabase() { Migration9(), Migration10(), Migration11(), - Migration12() + Migration12(), + Migration13() ) .build() } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt index 0f44fa2d..6c06be11 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt @@ -4,6 +4,7 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey +import org.threeten.bp.LocalDate @Entity(tableName = "Semesters", indices = [Index(value = ["student_id", "diary_id", "semester_id"], unique = true)]) data class Semester( @@ -17,6 +18,9 @@ data class Semester( @ColumnInfo(name = "diary_name") val diaryName: String, + @ColumnInfo(name = "school_year") + val schoolYear: Int, + @ColumnInfo(name = "semester_id") val semesterId: Int, @@ -26,6 +30,10 @@ data class Semester( @ColumnInfo(name = "is_current") val isCurrent: Boolean, + val start: LocalDate, + + val end: LocalDate, + @ColumnInfo(name = "class_id") val classId: Int, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt index 9cacf835..13c5ee08 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt @@ -32,6 +32,9 @@ data class Student( @ColumnInfo(name = "school_name") val schoolName: String, + @ColumnInfo(name = "class_name") + val className: String, + @ColumnInfo(name = "class_id") val classId: Int, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt new file mode 100644 index 00000000..83ab8609 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt @@ -0,0 +1,59 @@ +package io.github.wulkanowy.data.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration13 : Migration(12, 13) { + + override fun migrate(database: SupportSQLiteDatabase) { + addClassNameToStudents(database, getStudentsIds(database)) + updateSemestersTable(database) + markAtLeastAndOnlyOneSemesterAtCurrent(database, getStudentsAndClassIds(database)) + } + + private fun addClassNameToStudents(database: SupportSQLiteDatabase, students: List>) { + database.execSQL("ALTER TABLE Students ADD COLUMN class_name TEXT DEFAULT \"\" NOT NULL") + + students.forEach { (id, name) -> + val schoolName = name.substringAfter(" - ") + val className = name.substringBefore(" - ", "").replace("Klasa ", "") + database.execSQL("UPDATE Students SET class_name = '$className' WHERE id = '$id'") + database.execSQL("UPDATE Students SET school_name = '$schoolName' WHERE id = '$id'") + } + } + + private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList> { + val students = mutableListOf>() + val studentsCursor = database.query("SELECT id, school_name FROM Students") + if (studentsCursor.moveToFirst()) { + do { + students.add(studentsCursor.getInt(0) to studentsCursor.getString(1)) + } while (studentsCursor.moveToNext()) + } + return students + } + + private fun updateSemestersTable(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Semesters ADD COLUMN school_year INTEGER DEFAULT 1970 NOT NULL") + database.execSQL("ALTER TABLE Semesters ADD COLUMN start INTEGER DEFAULT 0 NOT NULL") + database.execSQL("ALTER TABLE Semesters ADD COLUMN `end` INTEGER DEFAULT 0 NOT NULL") + } + + private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List> { + val students = mutableListOf>() + val studentsCursor = database.query("SELECT student_id, class_id FROM Students") + if (studentsCursor.moveToFirst()) { + do { + students.add(studentsCursor.getInt(0) to studentsCursor.getInt(1)) + } while (studentsCursor.moveToNext()) + } + return students + } + + private fun markAtLeastAndOnlyOneSemesterAtCurrent(database: SupportSQLiteDatabase, students: List>) { + students.forEach { (studentId, classId) -> + database.execSQL("UPDATE Semesters SET is_current = 0 WHERE student_id = '$studentId' AND class_id = '$classId'") + database.execSQL("UPDATE Semesters SET is_current = 1 WHERE id = (SELECT id FROM Semesters WHERE student_id = '$studentId' AND class_id = '$classId' ORDER BY semester_id DESC)") + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt index b25c8881..c199c16c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt @@ -17,9 +17,12 @@ class SemesterRemote @Inject constructor(private val api: Api) { studentId = student.studentId, diaryId = semester.diaryId, diaryName = semester.diaryName, + schoolYear = semester.schoolYear, semesterId = semester.semesterId, semesterName = semester.semesterNumber, isCurrent = semester.current, + start = semester.start, + end = semester.end, classId = semester.classId, unitId = semester.unitId ) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt index f0692a53..251d3834 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt @@ -21,6 +21,7 @@ class StudentRemote @Inject constructor(private val api: Api) { studentName = student.studentName, schoolSymbol = student.schoolSymbol, schoolName = student.schoolName, + className = student.className, classId = student.classId, endpoint = endpoint, loginType = student.loginType.name, diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt index cb7aabda..972d10a2 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.ui.modules.account +import android.annotation.SuppressLint import android.view.View import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.AbstractFlexibleItem @@ -18,9 +19,10 @@ class AccountItem(val student: Student) : AbstractFlexibleItem>, holder: ViewHolder, position: Int, payloads: MutableList?) { holder.apply { - accountItemName.text = student.studentName + accountItemName.text = "${student.studentName} ${student.className}" accountItemSchool.text = student.schoolName accountItemImage.setBackgroundResource(if (student.isCurrent) R.drawable.ic_account_circular_border else 0) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt index 71a7d681..65940a98 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.ui.modules.login.studentselect +import android.annotation.SuppressLint import android.view.View import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.AbstractFlexibleItem @@ -18,9 +19,10 @@ class LoginStudentSelectItem(val student: Student) : AbstractFlexibleItem>, holder: ItemViewHolder, position: Int, payloads: MutableList?) { holder.run { - loginItemName.text = student.studentName + loginItemName.text = "${student.studentName} ${student.className}" loginItemSchool.text = student.schoolName } } diff --git a/app/src/main/res/layout/item_account.xml b/app/src/main/res/layout/item_account.xml index 844dd2c9..56f553e5 100644 --- a/app/src/main/res/layout/item_account.xml +++ b/app/src/main/res/layout/item_account.xml @@ -30,8 +30,10 @@ android:layout_marginLeft="20dp" android:layout_toEndOf="@id/accountItemImage" android:layout_toRightOf="@id/accountItemImage" - android:text="@string/app_name" - android:textSize="16sp" /> + android:ellipsize="end" + android:maxLines="1" + android:textSize="16sp" + tools:text="@tools:sample/lorem/random" /> + android:textSize="12sp" + tools:text="@tools:sample/lorem/random" /> diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/semester/TestSemesterEnityCreator.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/semester/TestSemesterEnityCreator.kt index c3377ac5..f628710f 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/semester/TestSemesterEnityCreator.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/semester/TestSemesterEnityCreator.kt @@ -1,6 +1,7 @@ package io.github.wulkanowy.data.repositories.semester import io.github.wulkanowy.data.db.entities.Semester +import org.threeten.bp.LocalDate.now fun createSemesterEntity(current: Boolean): Semester { return Semester( @@ -8,9 +9,12 @@ fun createSemesterEntity(current: Boolean): Semester { diaryId = 0, semesterId = 0, diaryName = "", + schoolYear = 1970, classId = 0, isCurrent = current, semesterName = 0, - unitId = 0 + unitId = 0, + start = now(), + end = now() ) } diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt index 8bd819e2..4d7b23eb 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/student/StudentRemoteTest.kt @@ -22,7 +22,7 @@ class StudentRemoteTest { @Test fun testRemoteAll() { - doReturn(Single.just(listOf(Student("", "", 1, "test", "", "", 1, Api.LoginType.AUTO)))) + doReturn(Single.just(listOf(Student("", "", 1, "test", "", "", "", 1, Api.LoginType.AUTO)))) .`when`(mockApi).getStudents() val students = StudentRemote(mockApi).getStudents("", "", "").blockingGet() diff --git a/app/src/test/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenterTest.kt b/app/src/test/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenterTest.kt index f1113f7b..83047e02 100644 --- a/app/src/test/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenterTest.kt +++ b/app/src/test/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenterTest.kt @@ -86,7 +86,7 @@ class LoginFormPresenterTest { @Test fun loginTest() { - val studentTest = Student(email = "test@", password = "123", endpoint = "https://fakelog.cf", loginType = "AUTO", studentName = "", schoolSymbol = "", schoolName = "", studentId = 0, classId = 1, isCurrent = false, symbol = "", registrationDate = now()) + val studentTest = Student(email = "test@", password = "123", endpoint = "https://fakelog.cf", loginType = "AUTO", studentName = "", schoolSymbol = "", schoolName = "", studentId = 0, classId = 1, isCurrent = false, symbol = "", registrationDate = now(), className = "") doReturn(Single.just(listOf(studentTest))) .`when`(repository).getStudents(anyString(), anyString(), anyString(), anyString()) diff --git a/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt b/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt index 2de4e43a..192602b7 100644 --- a/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt +++ b/app/src/test/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenterTest.kt @@ -32,7 +32,7 @@ class LoginStudentSelectPresenterTest { private lateinit var presenter: LoginStudentSelectPresenter - private val testStudent by lazy { Student(email = "test", password = "test123", endpoint = "https://fakelog.cf", loginType = "AUTO", symbol = "", isCurrent = false, studentId = 0, schoolName = "", schoolSymbol = "", classId = 1, studentName = "", registrationDate = now()) } + private val testStudent by lazy { Student(email = "test", password = "test123", endpoint = "https://fakelog.cf", loginType = "AUTO", symbol = "", isCurrent = false, studentId = 0, schoolName = "", schoolSymbol = "", classId = 1, studentName = "", registrationDate = now(), className = "") } private val testException by lazy { RuntimeException("Problem") } From 7d97d710668c4e68cfbcddbd936f83c7ff267cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Fri, 5 Apr 2019 19:35:21 +0200 Subject: [PATCH 30/33] Fix message loading if student and parent are logged in (#319) Fixes #316 --- .../io/github/wulkanowy/data/db/migrations/Migration13.kt | 5 +++++ .../wulkanowy/data/repositories/message/MessageLocal.kt | 6 +++--- .../wulkanowy/data/repositories/message/MessageRemote.kt | 5 +++-- .../data/repositories/message/MessageRepository.kt | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt index 83ab8609..0cf8cd9b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt @@ -9,6 +9,7 @@ class Migration13 : Migration(12, 13) { addClassNameToStudents(database, getStudentsIds(database)) updateSemestersTable(database) markAtLeastAndOnlyOneSemesterAtCurrent(database, getStudentsAndClassIds(database)) + clearMessagesTable(database) } private fun addClassNameToStudents(database: SupportSQLiteDatabase, students: List>) { @@ -56,4 +57,8 @@ class Migration13 : Migration(12, 13) { database.execSQL("UPDATE Semesters SET is_current = 1 WHERE id = (SELECT id FROM Semesters WHERE student_id = '$studentId' AND class_id = '$classId' ORDER BY semester_id DESC)") } } + + private fun clearMessagesTable(database: SupportSQLiteDatabase) { + database.execSQL("DELETE FROM Messages") + } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt index e9ab7297..411cca39 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt @@ -24,13 +24,13 @@ class MessageLocal @Inject constructor(private val messagesDb: MessagesDao) { } fun getMessage(student: Student, id: Int): Maybe { - return messagesDb.load(student.studentId, id) + return messagesDb.load(student.id.toInt(), id) } fun getMessages(student: Student, folder: MessageFolder): Maybe> { return when (folder) { - TRASHED -> messagesDb.loadDeleted(student.studentId) - else -> messagesDb.loadAll(student.studentId, folder.id) + TRASHED -> messagesDb.loadDeleted(student.id.toInt()) + else -> messagesDb.loadAll(student.id.toInt(), folder.id) }.filter { it.isNotEmpty() } } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt index 3fb01d30..d50c40f3 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt @@ -5,6 +5,7 @@ import io.github.wulkanowy.api.messages.Folder import io.github.wulkanowy.api.messages.SentMessage import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Recipient +import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.utils.toLocalDateTime import io.reactivex.Single import org.threeten.bp.LocalDateTime.now @@ -16,11 +17,11 @@ import io.github.wulkanowy.api.messages.Recipient as ApiRecipient @Singleton class MessageRemote @Inject constructor(private val api: Api) { - fun getMessages(studentId: Int, folder: MessageFolder): Single> { + fun getMessages(student: Student, folder: MessageFolder): Single> { return api.getMessages(Folder.valueOf(folder.name)).map { messages -> messages.map { Message( - studentId = studentId, + studentId = student.id.toInt(), realId = it.id ?: 0, messageId = it.messageId ?: 0, sender = it.sender.orEmpty(), diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt index d319689e..3b4f9582 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt @@ -28,7 +28,7 @@ class MessageRepository @Inject constructor( local.getMessages(student, folder).filter { !forceRefresh } .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) .flatMap { - if (it) remote.getMessages(student.studentId, folder) + if (it) remote.getMessages(student, folder) else Single.error(UnknownHostException()) }.flatMap { new -> local.getMessages(student, folder).toSingle(emptyList()) From f2fa04105d343c3076a72b69b602f19f53418331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 6 Apr 2019 00:21:51 +0200 Subject: [PATCH 31/33] Version 0.7.5 --- .travis.yml | 8 ++++---- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 14 ++++++-------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index b3261931..56c64858 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,10 @@ cache: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ -branches: - only: - - master - - 0.7.x +#branches: +# only: +# - master +# - 0.7.x android: licenses: diff --git a/app/build.gradle b/app/build.gradle index 6b6a1301..c58c1e33 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 15 targetSdkVersion 28 - versionCode 30 - versionName "0.7.4" + versionCode 31 + versionName "0.7.5" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -86,7 +86,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('com.github.wulkanowy:api:383ff93') { exclude module: "threetenbp" } + implementation('io.github.wulkanowy:api:0.7.5') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt index c85a155b..78576903 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,11 +1,9 @@ -Wersja 0.7.4 +Wersja 0.7.5 Naprawiliśmy: -- problem ze stabilnością na androidach 4 i 5 -- problem z przełączaniem kont, jeśli zalogowany był jednocześnie uczeń i rodzic -- problem z odświeżaniem danych, jeśli uczeń przeniósł się z klasy do klasy w bieżącym roku szkolnym +- problem z brakiem aktywnego semestru (jeśli doświadczysz jakichś problemów - wyloguj i zaloguj się ponownie) +- logowanie w niestandardowych dziennikach na vulcan.net.pl +- oznaczanie lekcji w planie jako odwołanej, jeśli brak opisu tej zmiany +- ładowanie wiadomości, jeśli byli zalogowani jednocześnie uczeń i rodzic -Dodaliśmy: -- nową opcję zmiany wartości plusa i minusa na 0.75 - -Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.4 +Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.5 From 333f7bfa162f9f6b34c3a09dbd10bb4f3ee8ab1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 7 Apr 2019 10:59:27 +0200 Subject: [PATCH 32/33] Add privacy policy link (#320) --- .../ui/modules/login/form/LoginFormFragment.kt | 2 ++ app/src/main/res/layout/fragment_login_form.xml | 12 +++++++++++- app/src/main/res/values-pl/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt index 54fd0704..5c0a6ed8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt @@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.login.form import android.annotation.SuppressLint import android.os.Bundle +import android.text.method.LinkMovementMethod import android.view.LayoutInflater import android.view.View import android.view.View.GONE @@ -53,6 +54,7 @@ class LoginFormFragment : BaseFragment(), LoginFormView { loginFormName.setOnTextChangedListener { presenter.onNameTextChanged() } loginFormPass.setOnTextChangedListener { presenter.onPassTextChanged() } loginFormHost.setOnItemSelectedListener { presenter.onHostSelected() } + loginFormPrivacyPolicyLink.movementMethod = LinkMovementMethod.getInstance() loginFormSignIn.setOnClickListener { presenter.attemptLogin() } loginFormPass.setOnEditorActionListener { _, id, _ -> diff --git a/app/src/main/res/layout/fragment_login_form.xml b/app/src/main/res/layout/fragment_login_form.xml index 81baf4af..7a82eaf7 100644 --- a/app/src/main/res/layout/fragment_login_form.xml +++ b/app/src/main/res/layout/fragment_login_form.xml @@ -124,7 +124,8 @@ + android:layout_height="56dp" + android:entries="@array/endpoints_keys" /> + + Hasło Dziennik Symbol + Polityka prywatności Zaloguj To hasło jest za krótkie Dane logowania są niepoprawne diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1debed7b..e12d94fd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,6 +26,7 @@ Password Register Symbol + Privacy policy Sign in This password is too short Login details are incorrect From 6cd6cae1e0fa7f6f4b08c50ba212a82862efe2b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 7 Apr 2019 11:08:46 +0200 Subject: [PATCH 33/33] Version 0.7.6 --- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c58c1e33..48f0e65c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 15 targetSdkVersion 28 - versionCode 31 - versionName "0.7.5" + versionCode 32 + versionName "0.7.6" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -86,7 +86,7 @@ play { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation('io.github.wulkanowy:api:0.7.5') { exclude module: "threetenbp" } + implementation('io.github.wulkanowy:api:0.7.6') { exclude module: "threetenbp" } implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.appcompat:appcompat:1.0.2" diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt index 78576903..d0f12e55 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,7 +1,9 @@ Wersja 0.7.5 +Uwaga! Jeżeli w aplikacji przestały wyświetlać się oceny, prosimy o wylogowanie i zalogowanie się ponownie! + Naprawiliśmy: -- problem z brakiem aktywnego semestru (jeśli doświadczysz jakichś problemów - wyloguj i zaloguj się ponownie) +- problem z brakiem aktywnego semestru - logowanie w niestandardowych dziennikach na vulcan.net.pl - oznaczanie lekcji w planie jako odwołanej, jeśli brak opisu tej zmiany - ładowanie wiadomości, jeśli byli zalogowani jednocześnie uczeń i rodzic