From 7900ad913f9f929b86095a3cb4d084c0ab53f6a3 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 11 Feb 2021 12:20:45 +0000 Subject: [PATCH 01/53] Bump kotlin_version from 1.4.21 to 1.4.30 (#1139) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5ab0182b..f67d2be9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - kotlin_version = '1.4.21' + kotlin_version = '1.4.30' about_libraries = '8.7.0' hilt_version = "2.31.2-alpha" } From 53584026dcdaa5a5557719de31d8b7fc02e1768d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 12 Feb 2021 09:11:52 +0000 Subject: [PATCH 02/53] Bump about_libraries from 8.7.0 to 8.8.2 (#1135) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f67d2be9..f9339997 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { kotlin_version = '1.4.30' - about_libraries = '8.7.0' + about_libraries = '8.8.2' hilt_version = "2.31.2-alpha" } repositories { From 6b8b7c9143a739b8ffea798f64f1132a0bedfd19 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 12 Feb 2021 10:12:35 +0100 Subject: [PATCH 03/53] Bump material from 1.3.0-rc01 to 1.3.0 (#1137) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index a822c367..d89cc2d5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -163,7 +163,7 @@ dependencies { implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" implementation "androidx.constraintlayout:constraintlayout:2.0.4" implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0" - implementation "com.google.android.material:material:1.3.0-rc01" + implementation "com.google.android.material:material:1.3.0" implementation "com.github.wulkanowy:material-chips-input:2.1.1" implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" From cac76857c4cd2b5b72e515888edf94fed6e1390e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 12 Feb 2021 18:05:33 +0000 Subject: [PATCH 04/53] Bump fragment-ktx from 1.2.5 to 1.3.0 (#1138) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index d89cc2d5..8e206f9d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -153,7 +153,7 @@ dependencies { implementation "androidx.activity:activity-ktx:1.1.0" implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat-resources:1.2.0" - implementation "androidx.fragment:fragment-ktx:1.2.5" + implementation "androidx.fragment:fragment-ktx:1.3.0" implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.multidex:multidex:2.0.1" From 4841a0439d72f0d3b1fd5afeeb98bf9dd4bbc4ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Fri, 12 Feb 2021 19:07:36 +0100 Subject: [PATCH 05/53] New Crowdin updates (#1131) --- app/src/main/res/values-cs-rCZ/strings.xml | 14 +-- app/src/main/res/values-sk-rSK/strings.xml | 116 ++++++++++----------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index cadf4145..874dbe28 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -19,7 +19,7 @@ Domácí úkoly Manažer účtů Vyberte účet - Manažer účtů + Detaily účtu Informace o žáku Semestr %1$d, %2$d/%3$d @@ -195,7 +195,7 @@ Musíte vybrat alespoň jednu nepřítomnost! Ospravedlnit - Účast + Docházka Společně Tento týden žádné testy @@ -228,8 +228,8 @@ %d zpráva %d zprávy - %d zprávy - %d zprávy + %d zpráv + %d zpráv Nová zpráva @@ -442,7 +442,7 @@ Výchozí zobrazení Výpočet koncoročního průměru Vynutit průměrný výpočet podle aplikace - Zobrazit přítomnost v účasti + Zobrazit přítomnost v docházce Motiv aplikace Rozbalit známky Označte aktuální lekci v plánu lekce @@ -454,7 +454,7 @@ Předměty seřazené v \"Známky\" Jazyk aplikace Oznámení - Ukázat notifikace + Ukázat oznámení Ukázat nadcházející oznámení o lekci Opravte problémy se synchronizací a upozorněním Ve vašem zařízení mohou nastat problémy se synchronizací dat a oznámenímii.\n\nChcete-li je opravit, přidejte Wulkanowy do funkce Autostart a vypněte optimalizaci/úsporu baterie v nastavení systému telefonu. @@ -491,7 +491,7 @@ Červený Modrý Zelený - Nachový + Fialový Žádná barva Zkopírováno diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index 1e85cfed..5ac7dcfc 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -17,10 +17,10 @@ Nová správa Poznámky a úspechy Domáce úlohy - Accounts manager - Select account - Account details - Student info + Manažér účtov + Vyberte účet + Detaily účtu + Informácie o žiakovi Semester %1$d, %2$d/%3$d @@ -81,7 +81,7 @@ Váha: %s Komentár Žiadne nové známky - Number of new ratings: %1$d + Počet nových známok %1$d Priemer: %1$.2f Body: %s Bez priemeru @@ -99,7 +99,7 @@ Semester Body Legenda - Average: %1$s + Priemer: %1$s Trieda Žiák @@ -152,7 +152,7 @@ Zmeny Žiadne lekcie tento deň %s min - %s sec + %s sek %1$s left in %1$s Lekcia skončila @@ -161,17 +161,17 @@ Later: %s Completed lessons - Show completed lessons - No info about completed lessons + Zobraziť dokončené lekcie + Žiadne informácie o dokončených lekciách Téma Neprítomnosť Zdroje Ďalší lekcie - Show additional lessons - No info about additional lessons + Zobraziť ďalšie lekcie + Žiadne informácie o ďalších lekciách - Attendance summary + Zhrnutie dochádzky Absent for school reasons Excused absence Unexcused absence @@ -193,49 +193,49 @@ Poslať Absence excused successfully! You must select at least one absence! - Excuse + Ospravedlniť Attendance Total No exams this week - Type + Typ Entry date Inbox - Sent - Trash + Odoslané + Kôš (no subject) - No messages + Žiadne správy An error occurred while downloading message content From: To: Date: %s - Reply - Forward - Delete - Move to trash + Odpoveď + Poslať ďalej + Vymazať + Presunúť do koša Delete permanently Message deleted successfully Share Print Subject - Content - Message sent successfully - Message does not exist + Obsah + Správa úspešne odoslaná + Správa neexistuje You need to choose at least 1 recipient The message content must be at least 3 characters - %d message - %d messages - %d messages - %d messages + %d správa + %d správy + %d správ + %d správ - New message - New messages - New messages - New messages + Nová správa + Nové správy + Nové správy + Nové správy You received %1$d message @@ -318,18 +318,18 @@ No devices Deregister Device removed - QR code + QR kód Token Symbol PIN School and teachers - School + Škola No info about school - School name - School address - Telephone + Názov školy + Adresa školy + Telefón Name of headmaster Name of pedagogue Show on map @@ -361,11 +361,11 @@ App version Contributors List of Wulkanowy developers - Report a bug + Nahlásiť chybu Send a bug report via e-mail FAQ Read Frequently Asked Questions - Discord server + Server Discord Join the Wulkanowy community Facebook fanpage Like our facebook fanpage @@ -398,8 +398,8 @@ Degree of kinship Address Phones - Male - Female + Muž + Žena Last name Nick @@ -416,12 +416,12 @@ Description No description Teacher - Date + Dátum Entry date - Color + Farba Details Category - Close + Zavrieť No data Subject Prev @@ -453,8 +453,8 @@ Grades color scheme Subjects sorting in \"Grades\" App language - Notifications - Show notifications + Oznámenia + Zobraziť upozornenia Show upcoming lesson notifications Fix synchronization & notifications issues Your device may have data synchronization issues and with notifications.\n\nTo fix them, you need to add Wulkanowy to the autostart and turn off battery optimization/saving in the phone settings. @@ -473,7 +473,7 @@ Manual sync doesn\'t refresh app views. \nTo see the synced data relaunch the app after syncing. - Other + Iné Value of the plus Value of the minus Reply with message history @@ -487,29 +487,29 @@ Upcoming lessons Debug - Black - Red - Blue - Green - Purple - No color + Čierny + Červený + Modrý + Zelený + Fialový + Žiadna farba - Copied + Skopírované Undo Download of updates has started… An update has just been downloaded. - Restart + Reštartovať Update failed! Wulkanowy may not function properly. Consider updating - No internet connection + Žiadne internetové pripojenie Connection to register failed. Servers can be overloaded. Please try again later Loading data failed. Please try again later Register password change required Maintenance underway UONET + register. Try again later Unknown UONET + register error. Try again later Unknown application error. Please try again later - An unexpected error occurred - Feature disabled by your school + Došlo k neočakávanej chybe + Funkcia deaktivovaná vašej školou Feature not available. Login in a mode other than Mobile API From bfe558d88727ffda22c26eb94fae7c06d368ff95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Fri, 12 Feb 2021 19:14:45 +0100 Subject: [PATCH 06/53] Update README (#1143) --- README.en.md | 11 +++++++++-- README.md | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/README.en.md b/README.en.md index accc3608..0f2885cf 100644 --- a/README.en.md +++ b/README.en.md @@ -12,7 +12,7 @@ Unofficial android VULCAN UONET+ register client for both students and their par ## Features -* logging in using the email and password OR using token and pin +* logging in using the email and password * functions from the register website: * grades * grade statistics @@ -25,15 +25,19 @@ Unofficial android VULCAN UONET+ register client for both students and their par * homework * notes * lucky number + * additional lessons + * school conferences + * student and school information * calculation of the average independently of school's preferences * notifications, e.g. about a new grade +* support for multiple accounts with the ability to rename students * dark and black (AMOLED) theme * offline mode * no ads ## Download -You can download the current beta version from the Google Play, F-Droid or Huawei AppGallery store +You can download the current version from the Google Play, F-Droid or Huawei AppGallery store [Get it on Google Play Date: Sat, 13 Feb 2021 11:58:01 +0100 Subject: [PATCH 07/53] Revert "Bump fragment-ktx from 1.2.5 to 1.3.0 (#1138)" (#1144) This reverts commit cac76857c4cd2b5b72e515888edf94fed6e1390e. --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 8e206f9d..d89cc2d5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -153,7 +153,7 @@ dependencies { implementation "androidx.activity:activity-ktx:1.1.0" implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat-resources:1.2.0" - implementation "androidx.fragment:fragment-ktx:1.3.0" + implementation "androidx.fragment:fragment-ktx:1.2.5" implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.multidex:multidex:2.0.1" From 5e3b89636fc3cb9c83720738549f9f493196f4e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 13 Feb 2021 12:33:53 +0100 Subject: [PATCH 08/53] Add checking vulcan average from both semesters (#1140) --- .../ui/modules/grade/GradeAverageProvider.kt | 35 +++++++++++-------- .../modules/grade/GradeAverageProviderTest.kt | 13 +++++++ gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt index 36c3c4f8..7e9b56b9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt @@ -86,7 +86,11 @@ class GradeAverageProvider @Inject constructor( return@combine firstSemesterGradeSubject } - val isAnyAverage = secondSemesterGradeSubject.data.orEmpty().any { it.average != .0 } + val isAnyVulcanAverageInFirstSemester = + firstSemesterGradeSubject.data.orEmpty().any { it.average != .0 } + val isAnyVulcanAverageInSecondSemester = + secondSemesterGradeSubject.data.orEmpty().any { it.average != .0 } + val updatedData = secondSemesterGradeSubject.data?.map { secondSemesterSubject -> val firstSemesterSubject = firstSemesterGradeSubject.data.orEmpty() .singleOrNull { it.subject == secondSemesterSubject.subject } @@ -94,7 +98,7 @@ class GradeAverageProvider @Inject constructor( val updatedAverage = if (averageMode == ALL_YEAR) { calculateAllYearAverage( student = student, - isAnyAverage = isAnyAverage, + isAnyVulcanAverage = isAnyVulcanAverageInFirstSemester || isAnyVulcanAverageInSecondSemester, gradeAverageForceCalc = gradeAverageForceCalc, secondSemesterSubject = secondSemesterSubject, firstSemesterSubject = firstSemesterSubject @@ -102,7 +106,7 @@ class GradeAverageProvider @Inject constructor( } else { calculateBothSemestersAverage( student = student, - isAnyAverage = isAnyAverage, + isAnyVulcanAverage = isAnyVulcanAverageInFirstSemester || isAnyVulcanAverageInSecondSemester, gradeAverageForceCalc = gradeAverageForceCalc, secondSemesterSubject = secondSemesterSubject, firstSemesterSubject = firstSemesterSubject @@ -116,11 +120,11 @@ class GradeAverageProvider @Inject constructor( private fun calculateAllYearAverage( student: Student, - isAnyAverage: Boolean, + isAnyVulcanAverage: Boolean, gradeAverageForceCalc: Boolean, secondSemesterSubject: GradeSubject, firstSemesterSubject: GradeSubject? - ) = if (!isAnyAverage || gradeAverageForceCalc) { + ) = if (!isAnyVulcanAverage || gradeAverageForceCalc) { val updatedSecondSemesterGrades = secondSemesterSubject.grades.updateModifiers(student) val updatedFirstSemesterGrades = @@ -133,20 +137,23 @@ class GradeAverageProvider @Inject constructor( private fun calculateBothSemestersAverage( student: Student, - isAnyAverage: Boolean, + isAnyVulcanAverage: Boolean, gradeAverageForceCalc: Boolean, secondSemesterSubject: GradeSubject, firstSemesterSubject: GradeSubject? - ) = if (!isAnyAverage || gradeAverageForceCalc) { - val secondSemesterAverage = - secondSemesterSubject.grades.updateModifiers(student).calcAverage() - val firstSemesterAverage = firstSemesterSubject?.grades?.updateModifiers(student) - ?.calcAverage() ?: secondSemesterAverage + ): Double { val divider = if (secondSemesterSubject.grades.any { it.weightValue > .0 }) 2 else 1 - (secondSemesterAverage + firstSemesterAverage) / divider - } else { - (secondSemesterSubject.average + (firstSemesterSubject?.average ?: secondSemesterSubject.average)) / 2 + return if (!isAnyVulcanAverage || gradeAverageForceCalc) { + val secondSemesterAverage = + secondSemesterSubject.grades.updateModifiers(student).calcAverage() + val firstSemesterAverage = firstSemesterSubject?.grades?.updateModifiers(student) + ?.calcAverage() ?: secondSemesterAverage + + (secondSemesterAverage + firstSemesterAverage) / divider + } else { + (secondSemesterSubject.average + (firstSemesterSubject?.average ?: secondSemesterSubject.average)) / divider + } } private fun getGradeSubjects( diff --git a/app/src/test/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProviderTest.kt b/app/src/test/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProviderTest.kt index 0da02cf5..f3d92d2e 100644 --- a/app/src/test/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProviderTest.kt +++ b/app/src/test/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProviderTest.kt @@ -198,6 +198,19 @@ class GradeAverageProviderTest { assertEquals(3.5, items.single { it.subject == "Język polski" }.average, .0) } + @Test + fun `calc both semesters average with no grade in second semester but with average in first semester`() { + every { preferencesRepository.gradeAverageForceCalc } returns false + every { preferencesRepository.gradeAverageMode } returns GradeAverageMode.BOTH_SEMESTERS + + coEvery { gradeRepository.getGrades(student, semesters[1], false) } returns flowWithResource { secondGradeWithModifier to secondSummariesWithModifier } + coEvery { gradeRepository.getGrades(student, semesters[2], false) } returns flowWithResource { emptyList() to listOf(getSummary(24, "Język polski", .0))} + + val items = runBlocking { gradeAverageProvider.getGradesDetailsWithAverage(student, semesters[2].semesterId, false).getResult() } + + assertEquals(3.49, items.single { it.subject == "Język polski" }.average, .0) + } + @Test fun `force calc average on no grades`() { every { preferencesRepository.gradeAverageForceCalc } returns true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1c4bcc29..25d32653 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 000cbd11a2247b63308d8be93b66ff4d03b22aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 13 Feb 2021 20:39:52 +0100 Subject: [PATCH 09/53] Fix EOF error in messages (#1145) --- .../34.json | 2142 +++++++++++++++++ .../github/wulkanowy/data/db/AppDatabase.kt | 6 +- .../data/db/migrations/Migration34.kt | 13 + 3 files changed, 2159 insertions(+), 2 deletions(-) create mode 100644 app/schemas/io.github.wulkanowy.data.db.AppDatabase/34.json create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/34.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/34.json new file mode 100644 index 00000000..6a56ac64 --- /dev/null +++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/34.json @@ -0,0 +1,2142 @@ +{ + "formatVersion": 1, + "database": { + "version": 34, + "identityHash": "c024cc4e19e009a03303e2bfe5c34b48", + "entities": [ + { + "tableName": "Students", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` 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": "nick", + "columnName": "nick", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "scrapperBaseUrl", + "columnName": "scrapper_base_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mobileBaseUrl", + "columnName": "mobile_base_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginType", + "columnName": "login_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginMode", + "columnName": "login_mode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "certificateKey", + "columnName": "certificate_key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "privateKey", + "columnName": "private_key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isParent", + "columnName": "is_parent", + "affinity": "INTEGER", + "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": "userLoginId", + "columnName": "user_login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userName", + "columnName": "user_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentName", + "columnName": "student_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolSymbol", + "columnName": "school_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolShortName", + "columnName": "school_short", + "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 IF NOT EXISTS `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, `is_current` INTEGER 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, `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": "current", + "columnName": "is_current", + "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": "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 IF NOT EXISTS `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, `student_plan` INTEGER 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": "isStudentPlan", + "columnName": "student_plan", + "affinity": "INTEGER", + "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, `time_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, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)", + "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": "timeId", + "columnName": "time_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 + }, + { + "fieldPath": "excusable", + "columnName": "excusable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excuseStatus", + "columnName": "excuse_status", + "affinity": "TEXT", + "notNull": false + } + ], + "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` REAL 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": "REAL", + "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, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPredictedGradeNotified", + "columnName": "is_predicted_grade_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isFinalGradeNotified", + "columnName": "is_final_grade_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "predictedGradeLastChange", + "columnName": "predicted_grade_last_change", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "finalGradeLastChange", + "columnName": "final_grade_last_change", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "predictedGrade", + "columnName": "predicted_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalGrade", + "columnName": "final_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "proposedPoints", + "columnName": "proposed_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalPoints", + "columnName": "final_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pointsSum", + "columnName": "points_sum", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "average", + "columnName": "average", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradePartialStatistics", + "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, `class_average` TEXT NOT NULL, `student_average` TEXT NOT NULL, `class_amounts` TEXT NOT NULL, `student_amounts` TEXT 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": "classAverage", + "columnName": "class_average", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentAverage", + "columnName": "student_average", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classAmounts", + "columnName": "class_amounts", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentAmounts", + "columnName": "student_amounts", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesPointsStatistics", + "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, `others` REAL NOT NULL, `student` REAL 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": "others", + "columnName": "others", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "student", + "columnName": "student", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradeSemesterStatistics", + "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, `amounts` TEXT NOT NULL, `student_grade` 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": "amounts", + "columnName": "amounts", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentGrade", + "columnName": "student_grade", + "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, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `content` TEXT NOT NULL, `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, `removed` INTEGER NOT NULL, `has_attachments` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unreadBy", + "columnName": "unread_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "readBy", + "columnName": "read_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "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": "removed", + "columnName": "removed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hasAttachments", + "columnName": "has_attachments", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MessageAttachments", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `one_drive_id` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))", + "fields": [ + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "oneDriveId", + "columnName": "one_drive_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "filename", + "columnName": "filename", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "real_id" + ], + "autoGenerate": false + }, + "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, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER 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": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "categoryType", + "columnName": "category_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPointsShow", + "columnName": "is_points_show", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "points", + "columnName": "points", + "affinity": "INTEGER", + "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, `is_done` INTEGER 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, `attachments` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isDone", + "columnName": "is_done", + "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 + }, + { + "fieldPath": "attachments", + "columnName": "attachments", + "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": "unitId", + "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": "userLoginId", + "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": [] + }, + { + "tableName": "MobileDevices", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userLoginId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deviceId", + "columnName": "device_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Teachers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short_name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "School", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "address", + "columnName": "address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contact", + "columnName": "contact", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "headmaster", + "columnName": "headmaster", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pedagogue", + "columnName": "pedagogue", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Conferences", + "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, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` 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": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "agenda", + "columnName": "agenda", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presentOnConference", + "columnName": "present_on_conference", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "conferenceId", + "columnName": "conference_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "TimetableAdditional", + "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, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` 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": "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 + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "StudentInfo", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "fullName", + "columnName": "full_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "firstName", + "columnName": "first_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "secondName", + "columnName": "second_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "surname", + "columnName": "surname", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "birthDate", + "columnName": "birth_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "birthPlace", + "columnName": "birth_place", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gender", + "columnName": "gender", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hasPolishCitizenship", + "columnName": "has_polish_citizenship", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "familyName", + "columnName": "family_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "parentsNames", + "columnName": "parents_names", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "address", + "columnName": "address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "registeredAddress", + "columnName": "registered_address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "correspondenceAddress", + "columnName": "correspondence_address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "phoneNumber", + "columnName": "phone_number", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "cellPhoneNumber", + "columnName": "cell_phone_number", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "firstGuardian.fullName", + "columnName": "first_guardian_full_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "firstGuardian.kinship", + "columnName": "first_guardian_kinship", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "firstGuardian.address", + "columnName": "first_guardian_address", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "firstGuardian.phones", + "columnName": "first_guardian_phones", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "firstGuardian.email", + "columnName": "first_guardian_email", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "secondGuardian.fullName", + "columnName": "second_guardian_full_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "secondGuardian.kinship", + "columnName": "second_guardian_kinship", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "secondGuardian.address", + "columnName": "second_guardian_address", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "secondGuardian.phones", + "columnName": "second_guardian_phones", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "secondGuardian.email", + "columnName": "second_guardian_email", + "affinity": "TEXT", + "notNull": false + } + ], + "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, 'c024cc4e19e009a03303e2bfe5c34b48')" + ] + } +} \ No newline at end of file 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 beec3ff7..ab89b84c 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 @@ -85,6 +85,7 @@ import io.github.wulkanowy.data.db.migrations.Migration30 import io.github.wulkanowy.data.db.migrations.Migration31 import io.github.wulkanowy.data.db.migrations.Migration32 import io.github.wulkanowy.data.db.migrations.Migration33 +import io.github.wulkanowy.data.db.migrations.Migration34 import io.github.wulkanowy.data.db.migrations.Migration4 import io.github.wulkanowy.data.db.migrations.Migration5 import io.github.wulkanowy.data.db.migrations.Migration6 @@ -130,7 +131,7 @@ import javax.inject.Singleton abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION_SCHEMA = 33 + const val VERSION_SCHEMA = 34 fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array { return arrayOf( @@ -165,7 +166,8 @@ abstract class AppDatabase : RoomDatabase() { Migration30(), Migration31(), Migration32(), - Migration33() + Migration33(), + Migration34() ) } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt new file mode 100644 index 00000000..2c57eb00 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt @@ -0,0 +1,13 @@ +package io.github.wulkanowy.data.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration34 : Migration(33, 34) { + + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DELETE FROM ReportingUnits") + database.execSQL("DELETE FROM Recipients") + } +} + From de8e9bde498714579d8cb11066c839addb568daf Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 14 Feb 2021 12:13:21 +0000 Subject: [PATCH 10/53] Bump mockk from 1.10.5 to 1.10.6 (#1149) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index d89cc2d5..b1501b22 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -137,7 +137,7 @@ ext { work_hilt = "1.0.0-alpha03" room = "2.3.0-beta01" chucker = "3.4.0" - mockk = "1.10.5" + mockk = "1.10.6" moshi = "1.11.0" } From c18302b81295d743f9d275dc9a19c5e3b419274f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 14 Feb 2021 12:14:28 +0000 Subject: [PATCH 11/53] Bump junit from 4.13.1 to 4.13.2 (#1150) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index b1501b22..6d4f40dd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -214,7 +214,7 @@ dependencies { debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker" debugImplementation "com.amitshekhar.android:debug-db:1.0.6" - testImplementation "junit:junit:4.13.1" + testImplementation "junit:junit:4.13.2" testImplementation "io.mockk:mockk:$mockk" testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2' testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" From 17aa77ad41d92311e507373ff7c5c8fd043e57a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Tue, 16 Feb 2021 12:12:35 +0100 Subject: [PATCH 12/53] New Crowdin updates (#1152) --- .../res/values-cs-rCZ/preferences_values.xml | 6 +- app/src/main/res/values-cs-rCZ/strings.xml | 138 ++--- app/src/main/res/values-de/strings.xml | 8 +- app/src/main/res/values-pl/strings.xml | 2 +- .../res/values-sk-rSK/preferences_values.xml | 6 +- app/src/main/res/values-sk-rSK/strings.xml | 506 +++++++++--------- 6 files changed, 333 insertions(+), 333 deletions(-) diff --git a/app/src/main/res/values-cs-rCZ/preferences_values.xml b/app/src/main/res/values-cs-rCZ/preferences_values.xml index bcb690e5..e70abcb1 100644 --- a/app/src/main/res/values-cs-rCZ/preferences_values.xml +++ b/app/src/main/res/values-cs-rCZ/preferences_values.xml @@ -45,8 +45,8 @@ Průměr známek z celého roku - Neukaž - Ukázat vše - Ukázat menší + Nezobrazovat + Zobrazit vše + Zobrazit menší diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 874dbe28..02ee382a 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -19,7 +19,7 @@ Domácí úkoly Manažer účtů Vyberte účet - Detaily účtu + Podrobnosti účtu Informace o žáku Semestr %1$d, %2$d/%3$d @@ -43,17 +43,17 @@ Přihlašovací údaje jsou nesprávné. Ujistěte se, že je v poli níže vybrána správná variace deníku UONET+ Neplatný PIN Neplatný token - Platnost tokenu vypršela + Token vypršel Neplatný e-mail Místo e-mailu použijte přiřazené přihlašovací údaje Neplatný symbol Žák nebyl nalezen. Zkontrolujte správnost symbolu a vybrané varianty deníku UONET+ Toto pole je povinné - Vybraný žák je již přihlášen - Symbol najdete na stránce deníku v  Uczeń →  Dostęp Mobilny →  Zarejestruj urządzenie mobilne.\n\nUjistěte se, že jste na předchozí obrazovce nastavili správnou variantu deníku do pole Variace deníku UONET+. Wulkanowy v tuto chvíli nezjistí předškolní studenty + Vybraný žák je už přihlášen + Symbol najdete na stránce deníku v  Uczeń → Dostęp Mobilny → Zarejestruj urządzenie mobilne.\n\nUjistěte se, že jste na předchozí obrazovce nastavili správnou variantu deníku do pole Variace deníku UONET+. Wulkanowy v tuto chvíli nezjistí předškolní żaków Vyberte žáky, kteří se mají do aplikace přihlásit Jiné možnosti - V tomto režimu nefungují následující: šťastné číslo, statistiky třídy, shrnutí docházky, ospravedlnění nepřítomnosti, absolvované lekce, informace o škole a prohlížení seznamu registrovaných zařízení + V tomto režimu nefungují následující: šťastné číslo, statistiky třídy, shrnutí docházky, ospravedlnění nepřítomnosti, dokončené lekce, informace o škole a prohlížení seznamu registrovaných zařízení Tento režim zobrazuje stejná data, která se zobrazují na webových stránkách deníka Kombinace nejlepších vlastností ostatních dvou režimů. Funguje rychleji než scraper a poskytuje funkce, které nejsou k dispozici v režimu Mobile API. Je to v experimentální fázi Zásady ochrany osobních údajů @@ -66,12 +66,12 @@ Zapomněl jsem své heslo Obnovte svůj účet Obnovit - Žák je již přihlášen + Žák je už přihlášen Manažer účtů Přihlásit se - Platnost relace vypršela - Vaše relace vypršela, přihlaste se prosím znovu + Relace vypršela + Relace vypršela. Přihlaste se prosím znovu Známka Semestr %d @@ -85,7 +85,7 @@ Průměr: %1$.2f Body: %s Bez průměru - Předpovězeno: %1$s + Předpokládaná: %1$s Konečná: %1$s Součet bodů Konečná známka @@ -129,20 +129,20 @@ Máte %1$d novou známku Máte %1$d nové známky - Máte %1$d nové známky - Máte %1$d nové známky + Máte %1$d nových známek + Máte %1$d nových známek Máte %1$d novou předpokládanou známku Máte %1$d nové předpokládané známky - Máte %1$d nové předpokládané známky - Máte %1$d nové předpokládané známky + Máte %1$d nových předpokládaných známek + Máte %1$d nových předpokládaných známek Máte %1$d novou konečnou známku Máte %1$d nové konečné známky - Máte %1$d nové konečné známky - Máte %1$d nové konečné známky + Máte %1$d nových konečných známek + Máte %1$d nových konečných známek Lekce @@ -153,11 +153,11 @@ Žádné lekce tento den %s min %s sek - dosud %1$s + ještě %1$s za %1$s - Lekce skončila - Nyní: %s - Okamžik: %s + Ukončila + Teď: %s + Za chvíli: %s Později: %s Dokončené lekce @@ -172,14 +172,14 @@ Žádné informace o dalších lekcích Shrnutí docházky - Nepřítomen ze školních důvodů + Neprítomnosť zo školských dôvodov Omluvená nepřítomnost Neomluvená nepřítomnost Osvobození Omluvené zpoždění Neomluvené zpoždění Přítomnost - Smazáno + Odstraněno Neznámý Číslo lekce Žádné položky @@ -205,7 +205,7 @@ Doručená pošta Odesláno Koš - (žádné téma) + (žádný předmět) Žádné zprávy Při stahování obsahu zprávy došlo k chybě Od: @@ -213,13 +213,13 @@ Datum: %s Odpověď Poslat dále - Vymazat + Odstranit Přesunout do koše - Trvale smazat - Zpráva byla úspěšně smazána - Podíl + Odstranit natrvalo + Zpráva byla úspěšně odstraněna + Sdílet Vytisknout - Téma + Předmět Obsah Zpráva úspěšně odeslána Zpráva neexistuje @@ -240,8 +240,8 @@ Máte %1$d novou zprávu Máte %1$d nové zprávy - Máte %1$d nové zprávy - Máte %1$d nové zprávy + Máte %1$d nových zpráv + Máte %1$d nových zpráv Žádné informace o poznámkách @@ -249,8 +249,8 @@ %d poznámka %d poznámky - %d poznámky - %d poznámky + %d poznámek + %d poznámek Nová poznámka @@ -261,15 +261,15 @@ Máte %1$d novou poznámku Máte %1$d nové poznámky - Máte %1$d nové poznámky - Máte %1$d nové poznámky + Máte %1$d nových poznámek + Máte %1$d nových poznámek %d chvála %d chvály - %d chvály - %d chvály + %d chvál + %d chvál Nová chvála @@ -280,8 +280,8 @@ Máte %1$d novou chválu Máte %1$d nové chvály - Máte %1$d nové chvály - Máte %1$d nové chvály + Máte %1$d nových chvál + Máte %1$d nových chvál @@ -297,10 +297,10 @@ Nové neutrální poznámky - Máte %1$d novou neutrální pozornost - Máte %1$d nové neutrální pozornosti - Máte %1$d nové neutrální pozornosti - Máte %1$d nové neutrální pozornosti + Máte %1$d novou neutrální poznámku + Máte %1$d nové neutrální poznámky + Máte %1$d nových neutrální poznámek + Máte %1$d nových neutrální poznámek Žádné informace o domácích úkolech @@ -317,7 +317,7 @@ Mobilní přístup Žádná zařízení Zrušit registraci - Zařízení odstraněno + Zařízení odstranění QR kód Token Symbol @@ -333,17 +333,17 @@ Jméno ředitele Jméno pedagoga Zobrazit na mapě - Volání + Volat Učitelé Žádné informace o učitelích Žádný předmět Setkání - Žádné informace o setkání + Žádné informace o setkáních Přidat účet - Odhlásit se + Odhlásit Chcete se odhlásit z aktivního žáka? Odhlášení žáků Žákův účet @@ -360,19 +360,19 @@ Verze aplikace Tvůrci - Seznam vývojářů Wulkanowy + Seznam vývojářů Wulkanového Nahlásit chybu Odeslat zprávu o chybě e-mailem FAQ Přečtěte si často kladené otázky Server Discord - Připojte se ke komunitě Wulkanowy + Připojte se ke komunitě Wulkanového Facebooková fanpage Stejně jako naše facebooková fanpage Zásady ochrany osobních údajů Pravidla pro shromažďování osobních údajů Domovská stránka - Navštivte web a pomozte s vývojem aplikace + Navštivte stránku a pomozte s vývojem aplikace Licence Licence knihoven použitých v aplikaci @@ -405,21 +405,21 @@ Přezdívka Přidat přezdívku - Sdílejte protokoly + Sdílet protokoly Obnovit Zkontrolovat aktualizace Před hlášením chyby zkontrolujte, zda je k dispozici aktualizace s opravou chyb Obsah - Zkuste to znovu + Zkusit znovu Popis - Bez popisu + Žádný popis Učitel Datum Datum vstupu Barva - Detaily + Podrobnosti Kategorie Zavřít Žádná data @@ -445,27 +445,27 @@ Zobrazit přítomnost v docházce Motiv aplikace Rozbalit známky - Označte aktuální lekci v plánu lekce - Ukázat skupiny vedle předmětů v plánu lekce - Ukázat seznam grafů ve třídních známkách - Ukázat lekce pro celou třídu - Ukázat předměty bez známek v \"Známky\" + Označit aktuální lekci v plánu lekce + Zobrazit skupiny vedle předmětů v plánu lekce + Zobrazit seznam grafů v známkách třídy + Zobrazit lekce pro celou třídu + Zobrazit předměty bez známek v \"Známky\" Známky barevné schéma - Předměty seřazené v \"Známky\" + Třídění předmětů v \"Známky\" Jazyk aplikace - Oznámení - Ukázat oznámení - Ukázat nadcházející oznámení o lekci + Upozornění + Zobrazit upozornění + Zobrazit upozornění o nadcházející lekci Opravte problémy se synchronizací a upozorněním - Ve vašem zařízení mohou nastat problémy se synchronizací dat a oznámenímii.\n\nChcete-li je opravit, přidejte Wulkanowy do funkce Autostart a vypněte optimalizaci/úsporu baterie v nastavení systému telefonu. + Vaše zařízení může mít problémy se synchronizací dat as upozorněními.\n\nChcete-li je opravit, přidejte Wulkanového do funkce Autostart a vypněte optimalizaci/úsporu baterie v nastavení systému telefonu. Přejít do nastavení - Ukázat oznámení o ladění + Zobrazit upozornění o ladění Synchronizace Automatická aktualizace Pozastaveno na dovolené Interval aktualizací Pouze Wi-Fi - Synchronizovat nyní + Synchronizovat teď Synchronizováno! Synchronizace selhala Probíhá synchronizace @@ -478,14 +478,14 @@ Hodnota mínusu Odpovědět s historií zpráv - Nové položky v deník + Nové položky v deníku Nové známky Šťastné číslo Nové zprávy Nové poznámky - Push oznámení + Push upozornění Nadcházející lekce - Debug + Ladění Černý Červený @@ -509,7 +509,7 @@ Probíhá údržba UONET+ deník. Zkuste to později znovu Neznámá chyba denika UONET+. Prosím zkuste to znovu později Neznámá chyba aplikace. Prosím zkuste to znovu později - Došlo k neočekávané chybě - Funkce deaktivována vaší školou + Vyskytla se neočekávaná chyba + Funkce je deaktivována přes vaší školou Funkce není k dispozici. Přihlaste se v jiném režimu než Mobile API diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 1acbdacb..0cf67fa4 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -383,7 +383,7 @@ Kategorie Schließ Keine Daten - Thema + Schulfach Zurück Nächste Suchen @@ -406,12 +406,12 @@ Thema der Anwendung Noten erweitern Aktuelle Lektion im Stundenplan markieren - Zeige Gruppen neben Themen im Zeitplan + Gruppen neben Schulfächer im Zeitplan anzeigen Liste der Diagramme in Klassenbewertungen anzeigen Unterricht der ganzen Klasse anzeigen - Zeigen Sie Themen ohne Noten in Noten + Schulfächer ohne Noten in \"Noten\" anzeigen Farbschema der Noten - Themen sortieren in \"Noten\" + Schulfächer sortieren in \"Noten\" App Sprache Benachrichtigungen Benachrichtigungen anzeigen diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 52134613..f45886b7 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -451,7 +451,7 @@ Pokazuj lekcje całej klasy Pokazuj przedmioty bez ocen w Ocenach Schemat kolorów ocen - Sortowanie przedmiotów w Ocenach + Sortowanie przedmiotów w \"Oceny\" Język aplikacji Powiadomienia Pokazuj powiadomienia diff --git a/app/src/main/res/values-sk-rSK/preferences_values.xml b/app/src/main/res/values-sk-rSK/preferences_values.xml index d57e603b..3275166d 100644 --- a/app/src/main/res/values-sk-rSK/preferences_values.xml +++ b/app/src/main/res/values-sk-rSK/preferences_values.xml @@ -45,8 +45,8 @@ Priemer známok z celého roka - Neukaz - Zobrazit vše - Zobrazit menší + Nezobrazovať + Zobraziť všetko + Zobraziť menšie diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index 5ac7dcfc..f0b8591a 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -11,7 +11,7 @@ Viac O aplikácii Prehliadač protokolov - Tvorcovia + Prispievatelia Licencie Správy Nová správa @@ -19,7 +19,7 @@ Domáce úlohy Manažér účtov Vyberte účet - Detaily účtu + Podrobnosti účtu Informácie o žiakovi Semester %1$d, %2$d/%3$d @@ -50,12 +50,12 @@ Žiak nebol nájdený. Skontrolujte správnosť symbolu a vybrané varianty denníka UONET+ Toto pole je povinné Vybraný žiak už je prihlásený - The symbol can be found on the register page in Uczeń → Dostęp Mobilny → Zarejestruj urządzenie mobilne.\n\nMake sure that you have set the appropriate register variant in the UONET+ register variant field on the previous screen. Wulkanowy does not detect pre-school students at the moment + Symbol nájdete na stránke denníka v  Uczeń→ Dostęp Mobilny → Zarejestruj urządzenie mobilne.\n\nUistite sa, že ste na predchádzajúcu obrazovke nastaviť správny variant denníka do poľa Variácie denníka UONET+. Wulkanowy v túto chvíľu nezistí predškolské żaków Vyberte žiakov, ktorí sa majú do aplikácie prihlásiť Iné možnosti - In this mode, a lucky number does not work, a class grade stats, summary of attendance, excuse for absence, completed lessons, school information and preview of the list of registered devices - This mode displays the same data as it appears on the register website - The combination of the best features of the other two modes. It works faster than scraper and provides features not available in the Mobile API mode. It is in the experimental phase + V tomto režime nefungujú nasledovné: šťastné číslo, štatistiky triedy, zhrnutie dochádzky, ospravedlnenie neprítomnosti, dokončené lekcie, informácie o škole a prezeranie zoznamu registrovaných zariadení + Tento režim zobrazuje rovnaké dáta, ktoré sa zobrazujú na webových stránkach denníka + Kombinácia najlepších vlastností ostatných dvoch režimov. Funguje rýchlejšie ako scraper a poskytuje funkcie, ktoré nie sú k dispozícii v režime Mobilne API. Je to v experimentálnej fáze Zásady ochrany osobných údajov Problémy s prihlásením? Napíšte nám! Email @@ -66,12 +66,12 @@ Zabudol som heslo Obnovte svoj účet Obnoviť - Študent je už prihlásený + Žiak je už prihlásený Manažér účtov Prihlásiť sa - Platnosť relácie vypršala - Vaša relácia vypršala, prihláste sa prosím znovu + Relácia vypršala + Relácia vypršala. Prihláste sa prosím znovu Známka Semester %d @@ -85,7 +85,7 @@ Priemer: %1$.2f Body: %s Bez priemeru - Predpovedané: %1$s + Predpokladaná: %1$s Konečná: %1$s Súčet bodov Konečná známka @@ -98,7 +98,7 @@ Čiastočné Semester Body - Legenda + Vysvetlivky Priemer: %1$s Trieda Žiák @@ -140,9 +140,9 @@ Máte %1$d novú konečnú známku - You received %1$d final grades - You received %1$d final grades - You received %1$d final grades + Máte %1$d nové konečnej známky + Máte %1$d nových konečných známok + Máte %1$d nových konečných známok Lekcia @@ -153,14 +153,14 @@ Žiadne lekcie tento deň %s min %s sek - %1$s left - in %1$s - Lekcia skončila - Now: %s - Next: %s - Later: %s + ešte %1$s + za %1$s + Ukončila + Teraz: %s + Za chvíľu: %s + Neskôr: %s - Completed lessons + Dokončené lekcie Zobraziť dokončené lekcie Žiadne informácie o dokončených lekciách Téma @@ -172,59 +172,59 @@ Žiadne informácie o ďalších lekciách Zhrnutie dochádzky - Absent for school reasons - Excused absence - Unexcused absence - Exemption - Excused lateness - Unexcused lateness + Neprítomnosť zo školských dôvodov + Ospravedlnená neprítomnosť + Neospravedlnená neprítomnosť + Oslobodenie + Ospravedlnenie meškanie + Neospravedlnenie meškanie Prítomnosť - Deleted + Odstránené Neznámy - Number of lesson + Číslo lekcie Žiadne položky - %1$d absence - %1$d absences - %1$d absences - %1$d absences + %1$d neprítomnosť + %1$d neprítomnosti + %1$d neprítomnosti + %1$d neprítomnosti - Absence reason (optional) + Dôvod neprítomnosti (voliteľný) Poslať - Absence excused successfully! - You must select at least one absence! + Neprítomnosť úspešne ospravedlnená! + Musíte vybrať aspoň jednu neprítomnosť! Ospravedlniť - Attendance - Total + Dochádzka + Spoločne - No exams this week + Tento týždeň žiadne testy Typ - Entry date + Dátum vstupu - Inbox + Doručená pošta Odoslané Kôš - (no subject) + (žiadny predmet) Žiadne správy - An error occurred while downloading message content - From: - To: - Date: %s + Pri sťahovaní obsahu správy došlo k chybe + Od: + Komu: + Dátum: %s Odpoveď Poslať ďalej - Vymazať + Odstrániť Presunúť do koša - Delete permanently - Message deleted successfully - Share - Print - Subject + Odstrániť natrvalo + Správa bola úspešne odstránená + Zdieľať + Vytlačiť + Predmet Obsah Správa úspešne odoslaná Správa neexistuje - You need to choose at least 1 recipient - The message content must be at least 3 characters + Musíte vybrať aspoň 1 príjemca + Obsah správy musí mať aspoň 3 znaky %d správa %d správy @@ -238,254 +238,254 @@ Nové správy - You received %1$d message - You received %1$d messages - You received %1$d messages - You received %1$d messages + Máte %1$d novú správu + Máte %1$d nové správy + Máte %1$d nových správ + Máte %1$d nových správ - No info about notes - Points + Žiadne informácie o poznámkach + Body - %d note - %d notes - %d notes - %d notes + %d poznámka + %d poznámky + %d poznámok + %d poznámok - New note - New notes - New notes - New notes + Nová poznámka + Nové poznámky + Nové poznámky + Nové poznámky - You received %1$d note - You received %1$d notes - You received %1$d notes - You received %1$d notes + Máte %1$d novú poznámku + Máte %1$d nové poznámky + Máte %1$d nových poznámok + Máte %1$d nových poznámok - %d praise - %d praises - %d praises - %d praises + %d chvála + %d chvály + %d chvál + %d chvál - New praise - New praises - New praises - New praises + Nová chvála + Nové chvály + Nové chvály + Nové chvály - You received %1$d praise - You received %1$d praises - You received %1$d praises - You received %1$d praises + Máte %1$d novú chválu + Máte %1$d nové chvály + Máte %1$d nových chvál + Máte %1$d nových chvál - %d neutral note - %d neutral notes - %d neutral notes - %d neutral notes + %d neutrálny poznámka + %d neutrálne poznámky + %d neutrálne poznámky + %d neutrálne poznámky - New neutral note - New neutral notes - New neutral notes - New neutral notes + Nová neutrálny poznámka + Nové neutrálne poznámky + Nové neutrálne poznámky + Nové neutrálne poznámky - You received %1$d neutral note - You received %1$d neutral notes - You received %1$d neutral notes - You received %1$d neutral notes + Máte %1$d novú neutrálny poznámku + Máte %1$d nové neutrálne poznámky + Máte %1$d nových neutrálne poznámok + Máte %1$d nových neutrálne poznámok - No info about homework - Mark as done - Mark as undone - Attachments + Žiadne informácie o domácich úlohách + Označiť ako hotové + Nevyrobené + Prílohy - Lucky number - Today\'s lucky number is - No info about the lucky number - Lucky number for today - Today\'s lucky number is: %d + Šťastné číslo + Dnešné šťastné číslo je + Žiadne informácie o šťastnom čísle + Šťastné číslo pre dnešok + Dnes je šťastným číslom: %d - Mobile devices - No devices - Deregister - Device removed + Mobilný prístup + Žiadne zariadenia + Zrušiť registráciu + Zariadenie odstránenie QR kód Token Symbol PIN - School and teachers + Škola a učitelia Škola - No info about school + Žiadne informácie o škole Názov školy Adresa školy Telefón - Name of headmaster - Name of pedagogue - Show on map - Call + Meno riaditeľa + Meno pedagóga + Zobraziť na mape + Volať - Teachers - No info about teachers - No subject + Učitelia + Žiadne informácie o učiteľoch + Žiadny predmet - Conferences - No info about conferences + Stretnutie + Žiadne informácie o stretnutiach - Add account - Logout - Do you want to log out this student? - Student logout - Student account - Parent account - Mobile API mode - Hybrid mode - Edit data - Accounts manager - Select student - Family - Contact - Residence details - Personal information + Pridať účet + Odhlásiť + Chcete sa odhlásiť z aktívneho žiaka? + Odhlásenie žiakov + Zakov účet + Rodičovský účet + Režim Mobilného API + Hybridný režim + Upraviť dáta + Manažér účtov + Vyberte žiaka + Rodina + Kontakt + Údaje o adresách + Osobné údaje - App version - Contributors - List of Wulkanowy developers + Verzia aplikácie + Prispievatelia + Zoznam vývojárov Wulkanového Nahlásiť chybu - Send a bug report via e-mail + Odoslať správu o chybe e-mailom FAQ - Read Frequently Asked Questions + Prečítajte si často kladené otázky Server Discord - Join the Wulkanowy community - Facebook fanpage - Like our facebook fanpage - Privacy policy - Rules for collecting personal data - Homepage - Visit the website and help develop the application - Licenses - Licenses of libraries used in the application + Pripojte sa ku komunite Wulkanového + Facebooková fanpage + Rovnako ako naše facebooková fanpage + Zásady ochrany osobných údajov + Pravidlá pre zhromažďovanie osobných údajov + Domovská stránka + Navštívte stránku a pomôžte s vývojom aplikácie + Licencie + Licencia knižníc použitých v aplikácii - License + Licencia Avatar - See more on GitHub + Zobraziť viac na GitHub - No info about student or student family - Name - Second name - Gender - Polish citizenship - Family name - Mother\'s and father\'s names - Phone - Cellphone + Žiadne informácie o žiakov alebo rodine žiaka + Meno + Druhé meno + Pohlavie + Poľské občianstvo + Rodinné meno + Mená matky a otca + Telefón + Mobilný telefón E-mail - Address of residence - Address of registration - Correspondence address - Surname and first name - Degree of kinship - Address - Phones + Adresa bydliska + Registrovaná adresa + Korešpondenčná adresa + Priezvisko a meno + Stupeň príbuznosti + Adresa + Telefóny Muž Žena - Last name + Priezvisko - Nick - Add nick + Prezývka + Pridať prezývku - Share logs - Refresh + Zdieľať protokoly + Obnoviť - Check for updates - Before reporting a bug, check first if an update with the bug fix is available + Skontrolovať aktualizácie + Pred hlásením chyby skontrolujte, či je k dispozícii aktualizácia s opravou chýb - Content - Retry - Description - No description - Teacher + Obsah + Skúsiť znova + Popis + Žiadny popis + Učiteľ Dátum - Entry date + Dátum vstupu Farba - Details - Category + Podrobnosti + Kategória Zavrieť - No data - Subject - Prev - Next - Search - Search… - Yes - No - Save + Žiadne údaje + Predmet + Vráť + Ďalej + Hľadať + Hledať… + Áno + Nie + Uložiť - No lessons - Choose theme - Light - Dark - System Theme + Žiadne lekcie + Vybrať motív + Svetlý + Tmavý + Motív systému - Appearance - Default view - Calculation of the end-of-year average - Force average calculation by app - Show presence in attendance - Application theme - Expand grades - Mark current lesson in timetable - Show groups next to subjects in timetable - Show chart list in class grades - Show whole class lessons - Show subjects without grades in Grades - Grades color scheme - Subjects sorting in \"Grades\" - App language - Oznámenia + Vzhľad + Predvolené zobrazenie + Výpočet koncoročního priemeru + Vynútiť priemerný výpočet podľa aplikácie + Zobraziť prítomnosť v dochádzke + Motív aplikácie + Rozbaliť známky + Označiť aktuálne lekciu v pláne lekcie + Zobraziť skupiny vedľa predmetov v pláne lekcie + Zobraziť zoznam grafov v známkach triedy + Zobraziť lekcie pre celú triedu + Zobraziť predmety bez známok v \"Známky\" + Známky farebnú schému + Triedenie predmetov v \"Známky\" + Jazyk aplikácie + Upozornenia Zobraziť upozornenia - Show upcoming lesson notifications - Fix synchronization & notifications issues - Your device may have data synchronization issues and with notifications.\n\nTo fix them, you need to add Wulkanowy to the autostart and turn off battery optimization/saving in the phone settings. - Go to settings - Show debug notifications - Synchronization - Automatic update - Suspended on holidays - Updates interval - Wi-Fi only - Sync now - Synced! - Sync failed - Sync in progress - Synchronization - Manual sync doesn\'t refresh app views. - \nTo see the synced data relaunch the app after syncing. + Zobraziť upozornenia o nadchádzajúcej lekciu + Opravte problémy so synchronizáciou a upozornením + Vaše zariadenie môže mať problémy so synchronizáciou dát as upozorneniami.\n\nAk ich chcete opraviť, pridajte Wulkanového do funkcie Autostart a vypnite optimalizáciu/úsporu batérie v nastavení systému telefóne. + Prejsť do nastavení + Zobraziť upozornenia o ladení + Synchronizácia + Automatická aktualizácia + Pozastavený počas dovolenky + Interval aktualizácií + Iba Wi-Fi + Synchronizovať teraz + Synchronizovano! + Synchronizácia zlyhala + Prebieha synchronizácia + Synchronizácia + Ručná synchronizácia neobnoví zobrazenie aplikácie. + \nAk chcete zobraziť synchronizované údaje, reštartujte aplikáciu po synchronizácii. Iné - Value of the plus - Value of the minus - Reply with message history + Hodnota plusu + Hodnota mínusu + Odpovedať s históriou správ - New entries in register - New grades - Lucky number - New messages - New notes - Push notifications - Upcoming lessons - Debug + Nové položky v denníku + Nové známky + Šťastné číslo + Nové správy + Nové poznámky + Push upozornenia + Nadchádzajúce lekcie + Ladenie Čierny Červený @@ -495,21 +495,21 @@ Žiadna farba Skopírované - Undo + Vrátiť - Download of updates has started… - An update has just been downloaded. + Sťahovanie aktualizácií začalo… + Aktualizácia bola stiahnutá. Reštartovať - Update failed! Wulkanowy may not function properly. Consider updating + Aktualizácia zlyhala! Wulkanowy nemusí fungovať správne. Zvážte aktualizáciu Žiadne internetové pripojenie - Connection to register failed. Servers can be overloaded. Please try again later - Loading data failed. Please try again later - Register password change required - Maintenance underway UONET + register. Try again later - Unknown UONET + register error. Try again later - Unknown application error. Please try again later - Došlo k neočakávanej chybe - Funkcia deaktivovaná vašej školou - Feature not available. Login in a mode other than Mobile API + Nedá sa pripojiť ku denníku. Servery môžu byť preťažené. Prosím skúste to znova neskôr + Načítanie údajov zlyhalo. Skúste neskôr prosím + Je vyžadovaná zmena hesla pre denník + Prebieha údržba UONET+ denník. Skúste to neskôr znova + Neznáma chyba dennika UONET+. Prosím skúste to znova neskôr + Neznáma chyba aplikácie. Prosím skúste to znova neskôr + Vyskytla sa neočakávaná chyba + Funkcia je deaktivovaná cez vašou školou + Funkcia nie je k dispozícii. Prihláste sa v inom režime než Mobile API From 44ba0d76de532474b2dbf443dd1f163ab75d1fa4 Mon Sep 17 00:00:00 2001 From: Faierbel Date: Tue, 16 Feb 2021 12:44:24 +0100 Subject: [PATCH 13/53] Version 1.0.1 --- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 10 +++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6d4f40dd..f59dff03 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 30 - versionCode 84 - versionName "1.0.0" + versionCode 85 + versionName "1.0.1" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -142,7 +142,7 @@ ext { } dependencies { - implementation "io.github.wulkanowy:sdk:1.0.0" + implementation "io.github.wulkanowy:sdk:1.0.1" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1' 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 1d18f575..3404b05b 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,10 +1,6 @@ -Wersja 1.0.0 +Wersja 1.0.1 -Pierwsza produkcyjna wersja Wulkanowego 🎉 - -Dziękujemy wszystkim użytkownikom za testowanie dotychczasowej wersji będącej we wczesnym dostępie -jak i programistom, którzy w wolnych chwilach pomagali rozwijać aplikację i naprawiać znalezione błędy. - -Bez was wszystkich niemożliwe byłoby to dzieło! +- naprawiliśmy błąd podczas wysyłania wiadomości +- poprawiliśmy błędy w tłumaczeniach Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases From 3c438757e318e0550e99005421a1af17db6b27b0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 17 Feb 2021 11:31:05 +0000 Subject: [PATCH 14/53] Bump firebase-bom from 26.4.0 to 26.5.0 (#1151) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index f59dff03..3810fd9b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -197,7 +197,7 @@ dependencies { implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation 'me.xdrop:fuzzywuzzy:1.3.1' - playImplementation platform('com.google.firebase:firebase-bom:26.4.0') + playImplementation platform('com.google.firebase:firebase-bom:26.5.0') playImplementation 'com.google.firebase:firebase-analytics-ktx' playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx' playImplementation "com.google.firebase:firebase-inappmessaging-ktx" From 021e9726c6d04f88431d980348872655466a7547 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 17 Feb 2021 11:38:33 +0000 Subject: [PATCH 15/53] Bump lifecycle-livedata-ktx from 2.2.0 to 2.3.0 (#1136) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3810fd9b..889fd923 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -170,7 +170,7 @@ dependencies { implementation "androidx.work:work-runtime-ktx:$work_manager" playImplementation "androidx.work:work-gcm:$work_manager" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.0" implementation "androidx.room:room-runtime:$room" implementation "androidx.room:room-ktx:$room" From 1ed0884dfd40d0e8989610d35be74e6b97824084 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 17 Feb 2021 11:38:51 +0000 Subject: [PATCH 16/53] Bump hilt_version from 2.31.2-alpha to 2.32-alpha (#1133) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f9339997..56b9504a 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { kotlin_version = '1.4.30' about_libraries = '8.8.2' - hilt_version = "2.31.2-alpha" + hilt_version = "2.32-alpha" } repositories { mavenCentral() From a320cf8f7c4c69a33db68abcae645571dae27402 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 17 Feb 2021 11:39:26 +0000 Subject: [PATCH 17/53] Bump fragment-ktx from 1.2.5 to 1.3.0 (#1148) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 889fd923..04f74564 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -153,7 +153,7 @@ dependencies { implementation "androidx.activity:activity-ktx:1.1.0" implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat-resources:1.2.0" - implementation "androidx.fragment:fragment-ktx:1.2.5" + implementation "androidx.fragment:fragment-ktx:1.3.0" implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.multidex:multidex:2.0.1" From 3adac154b44c385f4ea3bf0fd158ee480968138a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 17 Feb 2021 11:55:27 +0000 Subject: [PATCH 18/53] Bump firebase-crashlytics-gradle from 2.4.1 to 2.5.0 (#1147) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 56b9504a..93cf8ce7 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ buildscript { classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath 'com.google.gms:google-services:4.3.5' classpath 'com.huawei.agconnect:agcp:1.5.0.200' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.0' classpath "com.github.triplet.gradle:play-publisher:2.8.0" classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.1.1" classpath "gradle.plugin.com.star-zero.gradle:githook:1.2.0" From 4fceb854b31536697e490a0cbebb97f18ea3a245 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 17 Feb 2021 12:08:10 +0000 Subject: [PATCH 19/53] Bump activity-ktx from 1.1.0 to 1.2.0 (#1134) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 04f74564..82c1f3db 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -150,7 +150,7 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2' implementation "androidx.core:core-ktx:1.3.2" - implementation "androidx.activity:activity-ktx:1.1.0" + implementation "androidx.activity:activity-ktx:1.2.0" implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat-resources:1.2.0" implementation "androidx.fragment:fragment-ktx:1.3.0" From ff425d6d2bc52217e7ab168db76e21e5c29e9557 Mon Sep 17 00:00:00 2001 From: Damian Czupryn <60961958+Daxxxis@users.noreply.github.com> Date: Thu, 18 Feb 2021 00:05:27 +0100 Subject: [PATCH 20/53] Change background color of navigation and notification bars (#1120) --- app/src/main/AndroidManifest.xml | 4 +-- .../github/wulkanowy/ui/base/ThemeManager.kt | 22 ++++++++++--- .../wulkanowy/ui/modules/main/MainActivity.kt | 18 +++++++--- app/src/main/res/values-night/styles.xml | 33 +++++++++++++++++-- app/src/main/res/values-v23/styles.xml | 14 ++++++++ app/src/main/res/values-v26/styles.xml | 15 +++++++++ .../res/{values-v27 => values-v28}/styles.xml | 6 ++-- app/src/main/res/values-v29/styles.xml | 17 ++++++++++ app/src/main/res/values/colors.xml | 5 +++ app/src/main/res/values/styles.xml | 4 +++ 10 files changed, 123 insertions(+), 15 deletions(-) create mode 100644 app/src/main/res/values-v23/styles.xml create mode 100644 app/src/main/res/values-v26/styles.xml rename app/src/main/res/{values-v27 => values-v28}/styles.xml (75%) create mode 100644 app/src/main/res/values-v29/styles.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ac8d3be4..7b714fb2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -56,7 +56,7 @@ android:name=".ui.modules.login.LoginActivity" android:configChanges="orientation|screenSize" android:label="@string/login_title" - android:theme="@style/WulkanowyTheme.NoActionBar" + android:theme="@style/WulkanowyTheme.Login" android:windowSoftInputMode="adjustResize" /> activity.setTheme(R.style.WulkanowyTheme_Black) + is LoginActivity -> activity.setTheme(R.style.WulkanowyTheme_Login_Black) + is SendMessageActivity -> activity.setTheme(R.style.WulkanowyTheme_MessageSend_Black) + } + } } } @@ -33,8 +42,13 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer } private fun isThemeApplicable(activity: AppCompatActivity): Boolean { - return activity.packageManager.getPackageInfo(activity.packageName, GET_ACTIVITIES) - .activities.singleOrNull { it.name == activity::class.java.canonicalName }?.theme - .let { it == R.style.WulkanowyTheme_Black || it == R.style.WulkanowyTheme_NoActionBar } + return activity.packageManager + .getPackageInfo(activity.packageName, GET_ACTIVITIES) + .activities.singleOrNull { it.name == activity::class.java.canonicalName } + ?.theme.let { + it == R.style.WulkanowyTheme_Black || it == R.style.WulkanowyTheme_NoActionBar + || it == R.style.WulkanowyTheme_Login || it == R.style.WulkanowyTheme_Login_Black + || it == R.style.WulkanowyTheme_MessageSend || it == R.style.WulkanowyTheme_MessageSend_Black + } } } 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 5d93c594..da3863f4 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 @@ -11,6 +11,7 @@ import android.graphics.drawable.Icon import android.os.Build import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION_CODES.LOLLIPOP +import android.os.Build.VERSION_CODES.P import android.os.Bundle import android.view.Menu import android.view.MenuItem @@ -194,6 +195,7 @@ class MainActivity : BaseActivity(), MainVie return true } + @SuppressLint("NewApi") override fun initView() { with(binding.mainToolbar) { if (SDK_INT >= LOLLIPOP) stateListAnimator = null @@ -233,12 +235,18 @@ class MainActivity : BaseActivity(), MainVie with(navController) { setOnViewChangeListener { section, name -> - binding.mainBottomNav.visibility = - if (section == MainView.Section.ACCOUNT || section == MainView.Section.STUDENT_INFO) { - View.GONE - } else { - View.VISIBLE + if (section == MainView.Section.ACCOUNT || section == MainView.Section.STUDENT_INFO) { + binding.mainBottomNav.visibility = View.GONE + if (appInfo.systemVersion >= P) { + window.navigationBarColor = getThemeAttrColor(R.attr.colorSurface) } + } else { + binding.mainBottomNav.visibility = View.VISIBLE + if (appInfo.systemVersion >= P) { + window.navigationBarColor = + getThemeAttrColor(android.R.attr.navigationBarColor) + } + } analytics.setCurrentScreen(this@MainActivity, name) presenter.onViewChange(section) diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index bf5cd769..2641e713 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -10,14 +10,43 @@ @color/colorSwipeRefreshDark ?colorSurface ?android:textColorPrimary - @android:color/black + + @color/colorNavigationBarLight + + + @color/colorStatusBarLight - @android:color/black false true + false + + + + + + + + diff --git a/app/src/main/res/values-v23/styles.xml b/app/src/main/res/values-v23/styles.xml new file mode 100644 index 00000000..574e8488 --- /dev/null +++ b/app/src/main/res/values-v23/styles.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-v26/styles.xml b/app/src/main/res/values-v26/styles.xml new file mode 100644 index 00000000..55413c05 --- /dev/null +++ b/app/src/main/res/values-v26/styles.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/app/src/main/res/values-v27/styles.xml b/app/src/main/res/values-v28/styles.xml similarity index 75% rename from app/src/main/res/values-v27/styles.xml rename to app/src/main/res/values-v28/styles.xml index d33f6422..ee77091d 100644 --- a/app/src/main/res/values-v27/styles.xml +++ b/app/src/main/res/values-v28/styles.xml @@ -1,9 +1,10 @@ - + \ No newline at end of file diff --git a/app/src/main/res/values-v29/styles.xml b/app/src/main/res/values-v29/styles.xml new file mode 100644 index 00000000..ee77091d --- /dev/null +++ b/app/src/main/res/values-v29/styles.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 99456744..b8a0b098 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -6,6 +6,11 @@ #ff5722 #e84853 + #2E2E2E + #1E1E1E + + #1C1C1C + #ffd54f #ff8f00 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index cf587cbf..17550ae7 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -34,4 +34,8 @@ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index b8a0b098..b2e0dcef 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -6,10 +6,11 @@ #ff5722 #e84853 - #2E2E2E + #2D2D2D #1E1E1E #1C1C1C + #0D0D0D #ffd54f #ff8f00 From af8108a649cb2bcbbdc7a7a7bd54c63a9c5695a8 Mon Sep 17 00:00:00 2001 From: MRmlik12 <44818681+MRmlik12@users.noreply.github.com> Date: Sun, 7 Mar 2021 20:17:03 +0100 Subject: [PATCH 49/53] Add lucky number history (#1184) --- .../wulkanowy/data/db/dao/LuckyNumberDao.kt | 3 + .../repositories/LuckyNumberRepository.kt | 4 + .../luckynumber/LuckyNumberFragment.kt | 7 + .../ui/modules/luckynumber/LuckyNumberView.kt | 2 + .../history/LuckyNumberHistoryAdapter.kt | 36 +++++ .../history/LuckyNumberHistoryFragment.kt | 134 ++++++++++++++++ .../history/LuckyNumberHistoryPresenter.kt | 151 ++++++++++++++++++ .../history/LuckyNumberHistoryView.kt | 36 +++++ .../main/res/layout/fragment_lucky_number.xml | 20 +++ .../layout/fragment_lucky_number_history.xml | 149 +++++++++++++++++ .../res/layout/item_lucky_number_history.xml | 43 +++++ app/src/main/res/values/strings.xml | 5 + 12 files changed, 590 insertions(+) create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryAdapter.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryPresenter.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryView.kt create mode 100644 app/src/main/res/layout/fragment_lucky_number_history.xml create mode 100644 app/src/main/res/layout/item_lucky_number_history.xml diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt index 57f3005a..d9aa2436 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt @@ -13,4 +13,7 @@ interface LuckyNumberDao : BaseDao { @Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date") fun load(studentId: Int, date: LocalDate): Flow + + @Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date >= :start AND date <= :end") + fun getAll(studentId: Int, start: LocalDate, end: LocalDate): Flow> } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt index 801292b4..4f2dcc54 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt @@ -9,6 +9,7 @@ import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map +import java.time.LocalDate import java.time.LocalDate.now import javax.inject.Inject import javax.inject.Singleton @@ -33,6 +34,9 @@ class LuckyNumberRepository @Inject constructor( } ) + fun getLuckyNumberHistory(student: Student, start: LocalDate, end: LocalDate) = + luckyNumberDb.getAll(student.studentId, start, end) + suspend fun getNotNotifiedLuckyNumber(student: Student) = luckyNumberDb.load(student.studentId, now()).map { if (it?.isNotified == false) it else null }.first() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt index 3de23585..0a73fe15 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt @@ -9,6 +9,8 @@ import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.LuckyNumber import io.github.wulkanowy.databinding.FragmentLuckyNumberBinding import io.github.wulkanowy.ui.base.BaseFragment +import io.github.wulkanowy.ui.modules.luckynumber.history.LuckyNumberHistoryFragment +import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.utils.getThemeAttrColor import javax.inject.Inject @@ -42,6 +44,7 @@ class LuckyNumberFragment : luckyNumberSwipe.setOnRefreshListener(presenter::onSwipeRefresh) luckyNumberSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary)) luckyNumberSwipe.setProgressBackgroundColorSchemeColor(requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh)) + luckyNumberHistoryButton.setOnClickListener { openLuckyNumberHistory() } luckyNumberErrorRetry.setOnClickListener { presenter.onRetry() } luckyNumberErrorDetails.setOnClickListener { presenter.onDetailsClick() } } @@ -79,6 +82,10 @@ class LuckyNumberFragment : binding.luckyNumberContent.visibility = if (show) VISIBLE else GONE } + override fun openLuckyNumberHistory() { + (activity as? MainActivity)?.pushView(LuckyNumberHistoryFragment.newInstance()) + } + override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt index a680c83e..0c05a156 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt @@ -24,4 +24,6 @@ interface LuckyNumberView : BaseView { fun enableSwipe(enable: Boolean) fun showContent(show: Boolean) + + fun openLuckyNumberHistory() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryAdapter.kt new file mode 100644 index 00000000..7c09c96f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryAdapter.kt @@ -0,0 +1,36 @@ +package io.github.wulkanowy.ui.modules.luckynumber.history + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import io.github.wulkanowy.data.db.entities.LuckyNumber +import io.github.wulkanowy.databinding.ItemLuckyNumberHistoryBinding +import io.github.wulkanowy.utils.toFormattedString +import io.github.wulkanowy.utils.weekDayName +import java.util.Locale +import javax.inject.Inject + +class LuckyNumberHistoryAdapter @Inject constructor() : + RecyclerView.Adapter() { + + var items = emptyList() + + override fun getItemCount() = items.size + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( + ItemLuckyNumberHistoryBinding.inflate(LayoutInflater.from(parent.context), parent, false) + ) + + @SuppressLint("DefaultLocale") + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + val item = items[position] + with(holder.binding) { + luckyNumberHistoryWeekName.text = item.date.weekDayName.capitalize() + luckyNumberHistoryDate.text = item.date.toFormattedString() + luckyNumberHistory.text = item.luckyNumber.toString() + } + } + + class ItemViewHolder(val binding: ItemLuckyNumberHistoryBinding) : RecyclerView.ViewHolder(binding.root) +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt new file mode 100644 index 00000000..6e991ba1 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt @@ -0,0 +1,134 @@ +package io.github.wulkanowy.ui.modules.luckynumber.history + +import android.os.Bundle +import android.view.View +import android.view.View.GONE +import android.view.View.VISIBLE +import androidx.recyclerview.widget.LinearLayoutManager +import com.wdullaer.materialdatetimepicker.date.DatePickerDialog +import dagger.hilt.android.AndroidEntryPoint +import io.github.wulkanowy.R +import io.github.wulkanowy.data.db.entities.LuckyNumber +import io.github.wulkanowy.databinding.FragmentLuckyNumberHistoryBinding +import io.github.wulkanowy.ui.base.BaseFragment +import io.github.wulkanowy.ui.modules.main.MainView +import io.github.wulkanowy.ui.widgets.DividerItemDecoration +import io.github.wulkanowy.utils.SchooldaysRangeLimiter +import io.github.wulkanowy.utils.dpToPx +import io.github.wulkanowy.utils.getThemeAttrColor +import java.time.LocalDate +import javax.inject.Inject + +@AndroidEntryPoint +class LuckyNumberHistoryFragment : + BaseFragment(R.layout.fragment_lucky_number_history), LuckyNumberHistoryView, + MainView.TitledView { + + @Inject + lateinit var presenter: LuckyNumberHistoryPresenter + + @Inject + lateinit var luckyNumberHistoryAdapter: LuckyNumberHistoryAdapter + + companion object { + fun newInstance() = LuckyNumberHistoryFragment() + } + + override val titleStringId: Int + get() = R.string.lucky_number_history_title + + override val isViewEmpty get() = luckyNumberHistoryAdapter.items.isEmpty() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding = FragmentLuckyNumberHistoryBinding.bind(view) + messageContainer = binding.luckyNumberHistoryRecycler + presenter.onAttachView(this) + } + + override fun initView() { + with(binding.luckyNumberHistoryRecycler) { + layoutManager = LinearLayoutManager(context) + adapter = luckyNumberHistoryAdapter + addItemDecoration(DividerItemDecoration(context)) + } + + with(binding) { + luckyNumberHistoryNavDate.setOnClickListener { presenter.onPickDate() } + luckyNumberHistoryErrorRetry.setOnClickListener { presenter.onRetry() } + luckyNumberHistoryErrorDetails.setOnClickListener { presenter.onDetailsClick() } + + luckyNumberHistoryPreviousButton.setOnClickListener { presenter.onPreviousWeek() } + luckyNumberHistoryNextButton.setOnClickListener { presenter.onNextWeek() } + + luckyNumberHistoryNavContainer.setElevationCompat(requireContext().dpToPx(8f)) + } + } + + override fun updateData(data: List) { + with(luckyNumberHistoryAdapter) { + items = data + notifyDataSetChanged() + } + } + + override fun clearData() { + with(luckyNumberHistoryAdapter) { + items = emptyList() + notifyDataSetChanged() + } + } + + override fun showEmpty(show: Boolean) { + binding.luckyNumberHistoryEmpty.visibility = if (show) VISIBLE else GONE + } + + override fun showErrorView(show: Boolean) { + binding.luckyNumberHistoryError.visibility = if (show) VISIBLE else GONE + } + + override fun setErrorDetails(message: String) { + binding.luckyNumberHistoryErrorMessage.text = message + } + + override fun updateNavigationWeek(date: String) { + binding.luckyNumberHistoryNavDate.text = date + } + + override fun showProgress(show: Boolean) { + binding.luckyNumberHistoryProgress.visibility = if (show) VISIBLE else GONE + } + + override fun showPreButton(show: Boolean) { + binding.luckyNumberHistoryPreviousButton.visibility = if (show) VISIBLE else View.INVISIBLE + } + + override fun showNextButton(show: Boolean) { + binding.luckyNumberHistoryNextButton.visibility = if (show) VISIBLE else View.INVISIBLE + } + + override fun showDatePickerDialog(currentDate: LocalDate) { + val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth -> + presenter.onDateSet(year, month + 1, dayOfMonth) + } + val datePickerDialog = DatePickerDialog.newInstance(dateSetListener, + currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth) + + with(datePickerDialog) { + setDateRangeLimiter(SchooldaysRangeLimiter()) + version = DatePickerDialog.Version.VERSION_2 + scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL + vibrate(false) + show(this@LuckyNumberHistoryFragment.parentFragmentManager, null) + } + } + + override fun showContent(show: Boolean) { + binding.luckyNumberHistoryRecycler.visibility = if (show) VISIBLE else GONE + } + + override fun onDestroyView() { + presenter.onDetachView() + super.onDestroyView() + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryPresenter.kt new file mode 100644 index 00000000..556dda75 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryPresenter.kt @@ -0,0 +1,151 @@ +package io.github.wulkanowy.ui.modules.luckynumber.history + +import io.github.wulkanowy.data.Status +import io.github.wulkanowy.data.repositories.LuckyNumberRepository +import io.github.wulkanowy.data.repositories.StudentRepository +import io.github.wulkanowy.ui.base.BasePresenter +import io.github.wulkanowy.ui.base.ErrorHandler +import io.github.wulkanowy.utils.AnalyticsHelper +import io.github.wulkanowy.utils.afterLoading +import io.github.wulkanowy.utils.flowWithResource +import io.github.wulkanowy.utils.isHolidays +import io.github.wulkanowy.utils.monday +import io.github.wulkanowy.utils.previousOrSameSchoolDay +import io.github.wulkanowy.utils.sunday +import io.github.wulkanowy.utils.toFormattedString +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.onEach +import timber.log.Timber +import java.time.LocalDate +import javax.inject.Inject + +class LuckyNumberHistoryPresenter @Inject constructor( + errorHandler: ErrorHandler, + studentRepository: StudentRepository, + private val luckyNumberRepository: LuckyNumberRepository, + private val analytics: AnalyticsHelper +) : BasePresenter(errorHandler, studentRepository) { + + private lateinit var lastError: Throwable + + var currentDate: LocalDate = LocalDate.now().previousOrSameSchoolDay + + override fun onAttachView(view: LuckyNumberHistoryView) { + super.onAttachView(view) + view.run { + initView() + reloadNavigation() + showContent(false) + } + Timber.i("Lucky number history view was initialized") + errorHandler.showErrorMessage = ::showErrorViewOnError + loadData() + } + + private fun loadData() { + flowWithResource { + val student = studentRepository.getCurrentStudent() + luckyNumberRepository.getLuckyNumberHistory(student, currentDate.monday, currentDate.sunday) + }.onEach { + when (it.status) { + Status.LOADING -> Timber.i("Loading lucky number history started") + Status.SUCCESS -> { + if (!it.data?.first().isNullOrEmpty()) { + Timber.i("Loading lucky number result: Success") + view?.apply { + updateData(it.data!!.first()) + showContent(true) + showEmpty(false) + showErrorView(false) + showProgress(false) + } + analytics.logEvent( + "load_items", + "type" to "lucky_number_history", + "numbers" to it.data + ) + } else { + Timber.i("Loading lucky number history result: No lucky numbers found") + view?.run { + showContent(false) + showEmpty(true) + showErrorView(false) + } + } + } + Status.ERROR -> { + Timber.i("Loading lucky number history result: An exception occurred") + errorHandler.dispatch(it.error!!) + } + } + }.afterLoading { + view?.run { + showProgress(false) + } + }.launch() + } + + private fun showErrorViewOnError(message: String, error: Throwable) { + view?.run { + if (isViewEmpty) { + lastError = error + setErrorDetails(message) + showErrorView(true) + showEmpty(false) + } else showError(message, error) + } + } + + private fun reloadView(date: LocalDate) { + currentDate = date + Timber.i("Reload lucky number history view with the date ${currentDate.toFormattedString()}") + view?.apply { + showProgress(true) + showContent(false) + showEmpty(false) + showErrorView(false) + clearData() + reloadNavigation() + } + } + + fun onRetry() { + view?.run { + showErrorView(false) + showProgress(true) + } + loadData() + } + + fun onDetailsClick() { + view?.showErrorDetailsDialog(lastError) + } + + private fun reloadNavigation() { + view?.apply { + showPreButton(!currentDate.minusDays(7).isHolidays) + showNextButton(!currentDate.plusDays(7).isHolidays) + updateNavigationWeek("${currentDate.monday.toFormattedString("dd.MM")} - " + + currentDate.sunday.toFormattedString("dd.MM")) + } + } + + fun onDateSet(year: Int, month: Int, day: Int) { + reloadView(LocalDate.of(year, month, day)) + loadData() + } + + fun onPickDate() { + view?.showDatePickerDialog(currentDate) + } + + fun onPreviousWeek() { + reloadView(currentDate.minusDays(7)) + loadData() + } + + fun onNextWeek() { + reloadView(currentDate.plusDays(7)) + loadData() + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryView.kt new file mode 100644 index 00000000..331e4ff8 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryView.kt @@ -0,0 +1,36 @@ +package io.github.wulkanowy.ui.modules.luckynumber.history + +import io.github.wulkanowy.data.db.entities.LuckyNumber +import io.github.wulkanowy.ui.base.BaseView +import java.time.LocalDate + +interface LuckyNumberHistoryView : BaseView { + + val isViewEmpty: Boolean + + fun initView() + + fun updateData(data: List) + + fun clearData() + + fun showEmpty(show: Boolean) + + fun showErrorView(show: Boolean) + + fun setErrorDetails(message: String) + + fun updateNavigationWeek(date: String) + + fun showProgress(show: Boolean) + + fun showPreButton(show: Boolean) + + fun showNextButton(show: Boolean) + + fun showDatePickerDialog(currentDate: LocalDate) + + fun showContent(show: Boolean) + + fun onDestroyView() +} diff --git a/app/src/main/res/layout/fragment_lucky_number.xml b/app/src/main/res/layout/fragment_lucky_number.xml index f6de01e6..b2d4f40a 100644 --- a/app/src/main/res/layout/fragment_lucky_number.xml +++ b/app/src/main/res/layout/fragment_lucky_number.xml @@ -67,6 +67,26 @@ android:textSize="20sp" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_lucky_number_history.xml b/app/src/main/res/layout/item_lucky_number_history.xml new file mode 100644 index 00000000..79a0fcb2 --- /dev/null +++ b/app/src/main/res/layout/item_lucky_number_history.xml @@ -0,0 +1,43 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b42ba2e2..574c21b0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -306,6 +306,11 @@ No info about the lucky number Lucky number for today Today\'s lucky number is: %d + Show history + + + Lucky number history + No info about lucky numbers Mobile devices From f14346ff32b51355abda6e79a98a7dbfc53b38b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 7 Mar 2021 20:47:18 +0100 Subject: [PATCH 50/53] Fix duplicate items after running automatic and manual sync at the same time (#1197) --- .../data/repositories/AttendanceRepository.kt | 4 + .../AttendanceSummaryRepository.kt | 4 + .../CompletedLessonsRepository.kt | 4 + .../data/repositories/ConferenceRepository.kt | 4 + .../data/repositories/ExamRepository.kt | 4 + .../data/repositories/GradeRepository.kt | 31 ++- .../repositories/GradeStatisticsRepository.kt | 8 + .../data/repositories/HomeworkRepository.kt | 4 + .../repositories/LuckyNumberRepository.kt | 4 + .../data/repositories/MessageRepository.kt | 4 + .../repositories/MobileDeviceRepository.kt | 4 + .../data/repositories/NoteRepository.kt | 4 + .../data/repositories/SchoolRepository.kt | 4 + .../repositories/StudentInfoRepository.kt | 4 + .../data/repositories/SubjectRepository.kt | 4 + .../data/repositories/TeacherRepository.kt | 4 + .../data/repositories/TimetableRepository.kt | 4 + .../repositories/student/StudentRemote.kt | 0 .../io/github/wulkanowy/utils/FlowUtils.kt | 11 +- .../repositories/AttendanceRepositoryTest.kt | 2 + .../CompletedLessonsRepositoryTest.kt | 2 + .../data/repositories/ExamRemoteTest.kt | 2 + .../data/repositories/GradeRepositoryTest.kt | 9 +- .../repositories/LuckyNumberRemoteTest.kt | 2 + .../MobileDeviceRepositoryTest.kt | 2 + .../github/wulkanowy/utils/FlowUtilsKtTest.kt | 192 ++++++++++++++++++ 26 files changed, 308 insertions(+), 13 deletions(-) delete mode 100644 app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt create mode 100644 app/src/test/java/io/github/wulkanowy/utils/FlowUtilsKtTest.kt diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt index 9a6528f3..ffccb059 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt @@ -14,6 +14,7 @@ import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime @@ -27,9 +28,12 @@ class AttendanceRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "attendance" fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt index 4edb507b..cd4403c7 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt @@ -10,6 +10,7 @@ import io.github.wulkanowy.utils.getRefreshKey import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -20,9 +21,12 @@ class AttendanceSummaryRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "attendance_summary" fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt index 59aabdd5..99ef56f4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt @@ -12,6 +12,7 @@ import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject import javax.inject.Singleton @@ -23,9 +24,12 @@ class CompletedLessonsRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "completed" fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { completedLessonsDb.loadAll(semester.studentId, semester.diaryId, start.monday, end.sunday) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt index befcf9e6..0a839d27 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt @@ -10,6 +10,7 @@ import io.github.wulkanowy.utils.getRefreshKey import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -20,9 +21,12 @@ class ConferenceRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "conference" fun getConferences(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, query = { conferenceDb.loadAll(semester.diaryId, student.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt index bd6e7d2d..a8912f10 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt @@ -12,6 +12,7 @@ import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.startExamsDay import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject import javax.inject.Singleton @@ -23,9 +24,12 @@ class ExamRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "exam" fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { examDb.loadAll(semester.diaryId, semester.studentId, start.startExamsDay, start.endExamsDay) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt index bab290f3..9880e464 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt @@ -16,6 +16,7 @@ import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map +import kotlinx.coroutines.sync.Mutex import java.time.LocalDateTime import javax.inject.Inject import javax.inject.Singleton @@ -28,14 +29,20 @@ class GradeRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "grade" fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( - shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, + mutex = saveFetchResultMutex, + shouldFetch = { (details, summaries) -> + val isShouldBeRefreshed = refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) + details.isEmpty() || summaries.isEmpty() || forceRefresh || isShouldBeRefreshed + }, query = { - gradeDb.loadAll(semester.semesterId, semester.studentId).combine(gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)) { details, summaries -> - details to summaries - } + val detailsFlow = gradeDb.loadAll(semester.semesterId, semester.studentId) + val summaryFlow = gradeSummaryDb.loadAll(semester.semesterId, semester.studentId) + detailsFlow.combine(summaryFlow) { details, summaries -> details to summaries } }, fetch = { val (details, summary) = sdk.init(student) @@ -92,19 +99,27 @@ class GradeRepository @Inject constructor( } fun getUnreadGrades(semester: Semester): Flow> { - return gradeDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { grade -> !grade.isRead } } + return gradeDb.loadAll(semester.semesterId, semester.studentId).map { + it.filter { grade -> !grade.isRead } + } } fun getNotNotifiedGrades(semester: Semester): Flow> { - return gradeDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { grade -> !grade.isNotified } } + return gradeDb.loadAll(semester.semesterId, semester.studentId).map { + it.filter { grade -> !grade.isNotified } + } } fun getNotNotifiedPredictedGrades(semester: Semester): Flow> { - return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } } + return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { + it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } + } } fun getNotNotifiedFinalGrades(semester: Semester): Flow> { - return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } } + return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { + it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } + } } suspend fun updateGrade(grade: Grade) { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt index ab65fb14..9cd8e711 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt @@ -17,6 +17,7 @@ import io.github.wulkanowy.utils.getRefreshKey import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import java.util.Locale import javax.inject.Inject import javax.inject.Singleton @@ -30,11 +31,16 @@ class GradeStatisticsRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val partialMutex = Mutex() + private val semesterMutex = Mutex() + private val pointsMutex = Mutex() + private val partialCacheKey = "grade_stats_partial" private val semesterCacheKey = "grade_stats_semester" private val pointsCacheKey = "grade_stats_points" fun getGradesPartialStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( + mutex = partialMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(partialCacheKey, semester)) }, query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, fetch = { @@ -71,6 +77,7 @@ class GradeStatisticsRepository @Inject constructor( ) fun getGradesSemesterStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( + mutex = semesterMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(semesterCacheKey, semester)) }, query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, fetch = { @@ -112,6 +119,7 @@ class GradeStatisticsRepository @Inject constructor( ) fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( + mutex = pointsMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(pointsCacheKey, semester)) }, query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt index 7625dbbc..068fd9a5 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt @@ -13,6 +13,7 @@ import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject import javax.inject.Singleton @@ -24,9 +25,12 @@ class HomeworkRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "homework" fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { homeworkDb.loadAll(semester.semesterId, semester.studentId, start.monday, end.sunday) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt index 4f2dcc54..b904b7db 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt @@ -9,6 +9,7 @@ import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map +import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import java.time.LocalDate.now import javax.inject.Inject @@ -20,7 +21,10 @@ class LuckyNumberRepository @Inject constructor( private val sdk: Sdk ) { + private val saveFetchResultMutex = Mutex() + fun getLuckyNumber(student: Student, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it == null || forceRefresh }, query = { luckyNumberDb.load(student.studentId, now()) }, fetch = { sdk.init(student).getLuckyNumber(student.schoolShortName)?.mapToEntity(student) }, diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt index ea7b2b0e..5f555418 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt @@ -20,6 +20,7 @@ import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.sync.Mutex import timber.log.Timber import java.time.LocalDateTime.now import javax.inject.Inject @@ -33,10 +34,13 @@ class MessageRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "message" @Suppress("UNUSED_PARAMETER") fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student, folder)) }, query = { messagesDb.loadAll(student.id.toInt(), folder.id) }, fetch = { sdk.init(student).getMessages(Folder.valueOf(folder.name), now().minusMonths(3), now()).mapToEntities(student) }, diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt index 7e83ef7d..4b333bc6 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt @@ -13,6 +13,7 @@ import io.github.wulkanowy.utils.getRefreshKey import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -23,9 +24,12 @@ class MobileDeviceRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "devices" fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student)) }, query = { mobileDb.loadAll(student.userLoginId.takeIf { it != 0 } ?: student.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt index 85789f09..85339dfa 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt @@ -13,6 +13,7 @@ import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -23,9 +24,12 @@ class NoteRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "note" fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, query = { noteDb.loadAll(student.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt index 6b22b32c..8b59cb58 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt @@ -7,6 +7,7 @@ import io.github.wulkanowy.data.mappers.mapToEntity import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource +import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -16,8 +17,11 @@ class SchoolRepository @Inject constructor( private val sdk: Sdk ) { + private val saveFetchResultMutex = Mutex() + fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it == null || forceRefresh }, query = { schoolDb.load(semester.studentId, semester.classId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt index e3deb447..de66ad20 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt @@ -7,6 +7,7 @@ import io.github.wulkanowy.data.mappers.mapToEntity import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource +import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -16,8 +17,11 @@ class StudentInfoRepository @Inject constructor( private val sdk: Sdk ) { + private val saveFetchResultMutex = Mutex() + fun getStudentInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it == null || forceRefresh }, query = { studentInfoDao.loadStudentInfo(student.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt index ef07a1d4..b4bfef18 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt @@ -8,6 +8,7 @@ import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -17,7 +18,10 @@ class SubjectRepository @Inject constructor( private val sdk: Sdk ) { + private val saveFetchResultMutex = Mutex() + fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh }, query = { subjectDao.loadAll(semester.diaryId, semester.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt index 25da718c..7135edbe 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt @@ -8,6 +8,7 @@ import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -17,7 +18,10 @@ class TeacherRepository @Inject constructor( private val sdk: Sdk ) { + private val saveFetchResultMutex = Mutex() + fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh }, query = { teacherDb.loadAll(semester.studentId, semester.classId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt index fa1898f5..927565b5 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt @@ -18,6 +18,7 @@ import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map +import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject import javax.inject.Singleton @@ -31,9 +32,12 @@ class TimetableRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { + private val saveFetchResultMutex = Mutex() + private val cacheKey = "timetable" fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean, refreshAdditional: Boolean = false) = networkBoundResource( + mutex = saveFetchResultMutex, shouldFetch = { (timetable, additional) -> timetable.isEmpty() || (additional.isEmpty() && refreshAdditional) || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { timetableDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday) 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 deleted file mode 100644 index e69de29b..00000000 diff --git a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt index 049e1d42..5dd28967 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt @@ -13,8 +13,11 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.takeWhile +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock inline fun networkBoundResource( + mutex: Mutex = Mutex(), showSavedOnLoading: Boolean = true, crossinline query: () -> Flow, crossinline fetch: suspend (ResultType) -> RequestType, @@ -31,7 +34,7 @@ inline fun networkBoundResource( try { val newData = fetch(data) - saveFetchResult(data, newData) + mutex.withLock { saveFetchResult(query().first(), newData) } query().map { Resource.success(filterResult(it)) } } catch (throwable: Throwable) { onFetchFailed(throwable) @@ -44,11 +47,12 @@ inline fun networkBoundResource( @JvmName("networkBoundResourceWithMap") inline fun networkBoundResource( + mutex: Mutex = Mutex(), showSavedOnLoading: Boolean = true, crossinline query: () -> Flow, crossinline fetch: suspend (ResultType) -> RequestType, crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit, - crossinline onFetchFailed: (Throwable) -> Unit = { Unit }, + crossinline onFetchFailed: (Throwable) -> Unit = { }, crossinline shouldFetch: (ResultType) -> Boolean = { true }, crossinline mapResult: (ResultType) -> T ) = flow { @@ -59,7 +63,8 @@ inline fun networkBoundResource( if (showSavedOnLoading) emit(Resource.loading(mapResult(data))) try { - saveFetchResult(data, fetch(data)) + val newData = fetch(data) + mutex.withLock { saveFetchResult(query().first(), newData) } query().map { Resource.success(mapResult(it)) } } catch (throwable: Throwable) { onFetchFailed(throwable) diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/AttendanceRepositoryTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/AttendanceRepositoryTest.kt index 4c6a1172..1c592c09 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/AttendanceRepositoryTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/AttendanceRepositoryTest.kt @@ -87,6 +87,7 @@ class AttendanceRepositoryTest { coEvery { sdk.getAttendance(startDate, endDate, 1) } returns remoteList coEvery { attendanceDb.loadAll(1, 1, startDate, endDate) } returnsMany listOf( flowOf(remoteList.dropLast(1).mapToEntities(semester)), + flowOf(remoteList.dropLast(1).mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.mapToEntities(semester)) ) coEvery { attendanceDb.insertAll(any()) } returns listOf(1, 2, 3) @@ -114,6 +115,7 @@ class AttendanceRepositoryTest { coEvery { sdk.getAttendance(startDate, endDate, 1) } returns remoteList.dropLast(1) coEvery { attendanceDb.loadAll(1, 1, startDate, endDate) } returnsMany listOf( flowOf(remoteList.mapToEntities(semester)), + flowOf(remoteList.mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.dropLast(1).mapToEntities(semester)) ) coEvery { attendanceDb.insertAll(any()) } returns listOf(1, 2, 3) diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepositoryTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepositoryTest.kt index 461e1809..b116a623 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepositoryTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepositoryTest.kt @@ -87,6 +87,7 @@ class CompletedLessonsRepositoryTest { coEvery { sdk.getCompletedLessons(startDate, endDate) } returns remoteList coEvery { completedLessonDb.loadAll(1, 1, startDate, endDate) } returnsMany listOf( flowOf(remoteList.dropLast(1).mapToEntities(semester)), + flowOf(remoteList.dropLast(1).mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.mapToEntities(semester)) ) coEvery { completedLessonDb.insertAll(any()) } returns listOf(1, 2, 3) @@ -114,6 +115,7 @@ class CompletedLessonsRepositoryTest { coEvery { sdk.getCompletedLessons(startDate, endDate) } returns remoteList.dropLast(1) coEvery { completedLessonDb.loadAll(1, 1, startDate, endDate) } returnsMany listOf( flowOf(remoteList.mapToEntities(semester)), + flowOf(remoteList.mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.dropLast(1).mapToEntities(semester)) ) coEvery { completedLessonDb.insertAll(any()) } returns listOf(1, 2, 3) diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/ExamRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/ExamRemoteTest.kt index 42a89707..ead6dc5d 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/ExamRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/ExamRemoteTest.kt @@ -88,6 +88,7 @@ class ExamRemoteTest { coEvery { sdk.getExams(startDate, realEndDate, 1) } returns remoteList coEvery { examDb.loadAll(1, 1, startDate, realEndDate) } returnsMany listOf( flowOf(remoteList.dropLast(1).mapToEntities(semester)), + flowOf(remoteList.dropLast(1).mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.mapToEntities(semester)) ) coEvery { examDb.insertAll(any()) } returns listOf(1, 2, 3) @@ -115,6 +116,7 @@ class ExamRemoteTest { coEvery { sdk.getExams(startDate, realEndDate, 1) } returns remoteList.dropLast(1) coEvery { examDb.loadAll(1, 1, startDate, realEndDate) } returnsMany listOf( flowOf(remoteList.mapToEntities(semester)), + flowOf(remoteList.mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.dropLast(1).mapToEntities(semester)) ) coEvery { examDb.insertAll(any()) } returns listOf(1, 2, 3) diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/GradeRepositoryTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/GradeRepositoryTest.kt index 002c7ad7..8a19d633 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/GradeRepositoryTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/GradeRepositoryTest.kt @@ -57,7 +57,7 @@ class GradeRepositoryTest { coEvery { gradeDb.deleteAll(any()) } just Runs coEvery { gradeDb.insertAll(any()) } returns listOf() - coEvery { gradeSummaryDb.loadAll(1, 1) } returnsMany listOf(flowOf(listOf()), flowOf(listOf())) + coEvery { gradeSummaryDb.loadAll(1, 1) } returnsMany listOf(flowOf(listOf()), flowOf(listOf()), flowOf(listOf())) coEvery { gradeSummaryDb.deleteAll(any()) } just Runs coEvery { gradeSummaryDb.insertAll(any()) } returns listOf() } @@ -76,7 +76,8 @@ class GradeRepositoryTest { coEvery { gradeDb.loadAll(1, 1) } returnsMany listOf( flowOf(listOf()), // empty because it is new user - flowOf(remoteList.mapToEntities(semester)) + flowOf(listOf()), // empty again, after fetch end before save result + flowOf(remoteList.mapToEntities(semester)), ) // execute @@ -114,6 +115,7 @@ class GradeRepositoryTest { ) coEvery { gradeDb.loadAll(1, 1) } returnsMany listOf( flowOf(localList.mapToEntities(semester)), + flowOf(localList.mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.mapToEntities(semester)) ) @@ -155,6 +157,7 @@ class GradeRepositoryTest { ) coEvery { gradeDb.loadAll(1, 1) } returnsMany listOf( flowOf(localList.mapToEntities(semester)), + flowOf(localList.mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.mapToEntities(semester)) ) @@ -184,6 +187,7 @@ class GradeRepositoryTest { ) coEvery { gradeDb.loadAll(1, 1) } returnsMany listOf( flowOf(localList.mapToEntities(semester)), + flowOf(localList.mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.mapToEntities(semester)) ) @@ -209,6 +213,7 @@ class GradeRepositoryTest { coEvery { gradeDb.loadAll(1, 1) } returnsMany listOf( flowOf(listOf()), + flowOf(listOf()), // after fetch end before save result flowOf(remoteList.mapToEntities(semester)) ) diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/LuckyNumberRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/LuckyNumberRemoteTest.kt index 9cbad8ac..a89aad35 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/LuckyNumberRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/LuckyNumberRemoteTest.kt @@ -72,6 +72,7 @@ class LuckyNumberRemoteTest { coEvery { sdk.getLuckyNumber(student.schoolShortName) } returns luckyNumber coEvery { luckyNumberDb.load(1, date) } returnsMany listOf( flowOf(luckyNumber.mapToEntity(student).copy(luckyNumber = 6666)), + flowOf(luckyNumber.mapToEntity(student).copy(luckyNumber = 6666)), // after fetch end before save result flowOf(luckyNumber.mapToEntity(student)) ) coEvery { luckyNumberDb.insertAll(any()) } returns listOf(1, 2, 3) @@ -101,6 +102,7 @@ class LuckyNumberRemoteTest { coEvery { sdk.getLuckyNumber(student.schoolShortName) } returns luckyNumber coEvery { luckyNumberDb.load(1, date) } returnsMany listOf( flowOf(null), + flowOf(null), // after fetch end before save result flowOf(luckyNumber.mapToEntity(student)) ) coEvery { luckyNumberDb.insertAll(any()) } returns listOf(1, 2, 3) diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/MobileDeviceRepositoryTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/MobileDeviceRepositoryTest.kt index 4a4f2c76..e5b3d101 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/MobileDeviceRepositoryTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/MobileDeviceRepositoryTest.kt @@ -82,6 +82,7 @@ class MobileDeviceRepositoryTest { coEvery { sdk.getRegisteredDevices() } returns remoteList coEvery { mobileDeviceDb.loadAll(1) } returnsMany listOf( flowOf(remoteList.dropLast(1).mapToEntities(semester)), + flowOf(remoteList.dropLast(1).mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.mapToEntities(semester)) ) coEvery { mobileDeviceDb.insertAll(any()) } returns listOf(1, 2, 3) @@ -109,6 +110,7 @@ class MobileDeviceRepositoryTest { coEvery { sdk.getRegisteredDevices() } returns remoteList.dropLast(1) coEvery { mobileDeviceDb.loadAll(1) } returnsMany listOf( flowOf(remoteList.mapToEntities(semester)), + flowOf(remoteList.mapToEntities(semester)), // after fetch end before save result flowOf(remoteList.dropLast(1).mapToEntities(semester)) ) coEvery { mobileDeviceDb.insertAll(any()) } returns listOf(1, 2, 3) diff --git a/app/src/test/java/io/github/wulkanowy/utils/FlowUtilsKtTest.kt b/app/src/test/java/io/github/wulkanowy/utils/FlowUtilsKtTest.kt new file mode 100644 index 00000000..375a2403 --- /dev/null +++ b/app/src/test/java/io/github/wulkanowy/utils/FlowUtilsKtTest.kt @@ -0,0 +1,192 @@ +package io.github.wulkanowy.utils + +import io.mockk.Runs +import io.mockk.coEvery +import io.mockk.coVerifyOrder +import io.mockk.just +import io.mockk.mockk +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.test.TestCoroutineScope +import org.junit.Test +import kotlin.test.assertEquals + +@OptIn(ExperimentalCoroutinesApi::class) +class FlowUtilsKtTest { + + private val testScope = TestCoroutineScope() + + @Test + fun `fetch from two places with same remote data`() { + val repo = mockk() + coEvery { repo.query() } returnsMany listOf( + // initial data + flowOf(listOf(1, 2, 3)), + flowOf(listOf(1, 2, 3)), + + // for first + flowOf(listOf(1, 2, 3)), // before save + flowOf(listOf(2, 3, 4)), // after save + + // for second + flowOf(listOf(2, 3, 4)), // before save + flowOf(listOf(2, 3, 4)), // after save + ) + coEvery { repo.fetch() } returnsMany listOf( + listOf(2, 3, 4), + listOf(2, 3, 4), + ) + coEvery { repo.save(any(), any()) } just Runs + + // first + networkBoundResource( + showSavedOnLoading = false, + query = { repo.query() }, + fetch = { + val data = repo.fetch() + delay(2_000) + data + }, + saveFetchResult = { old, new -> repo.save(old, new) } + ).launchIn(testScope) + + testScope.advanceTimeBy(1_000) + + // second + networkBoundResource( + showSavedOnLoading = false, + query = { repo.query() }, + fetch = { + val data = repo.fetch() + delay(2_000) + data + }, + saveFetchResult = { old, new -> repo.save(old, new) } + ).launchIn(testScope) + + testScope.advanceTimeBy(3_000) + + coVerifyOrder { + // from first + repo.query() + repo.fetch() // hang for 2 sec + + // wait 1 sec + + // from second + repo.query() + repo.fetch() // hang for 2 sec + + // from first + repo.query() + repo.save(withArg { + assertEquals(listOf(1, 2, 3), it) + }, any()) + repo.query() + + // from second + repo.query() + repo.save(withArg { + assertEquals(listOf(2, 3, 4), it) + }, any()) + repo.query() + } + } + + @Test + fun `fetch from two places with same remote data and save at the same moment`() { + val repo = mockk() + coEvery { repo.query() } returnsMany listOf( + // initial data + flowOf(listOf(1, 2, 3)), + flowOf(listOf(1, 2, 3)), + + // for first + flowOf(listOf(1, 2, 3)), // before save + flowOf(listOf(2, 3, 4)), // after save + + // for second + flowOf(listOf(2, 3, 4)), // before save + flowOf(listOf(2, 3, 4)), // after save + ) + coEvery { repo.fetch() } returnsMany listOf( + listOf(2, 3, 4), + listOf(2, 3, 4), + ) + coEvery { repo.save(any(), any()) } just Runs + + val saveResultMutex = Mutex() + + // first + networkBoundResource( + mutex = saveResultMutex, + showSavedOnLoading = false, + query = { repo.query() }, + fetch = { + val data = repo.fetch() + delay(2_000) + data + }, + saveFetchResult = { old, new -> + delay(1_500) + repo.save(old, new) + } + ).launchIn(testScope) + + testScope.advanceTimeBy(1_000) + + // second + networkBoundResource( + mutex = saveResultMutex, + showSavedOnLoading = false, + query = { repo.query() }, + fetch = { + val data = repo.fetch() + delay(2_000) + data + }, + saveFetchResult = { old, new -> + repo.save(old, new) + } + ).launchIn(testScope) + + testScope.advanceTimeBy(3_000) + + coVerifyOrder { + // from first + repo.query() + repo.fetch() // hang for 2 sec + + // wait 1 sec + + // from second + repo.query() + repo.fetch() // hang for 2 sec + + // from first + repo.query() + repo.save(withArg { + assertEquals(listOf(1, 2, 3), it) + }, any()) + + // from second + repo.query() + repo.save(withArg { + assertEquals(listOf(2, 3, 4), it) + }, any()) + + repo.query() + repo.query() + } + } + + @Suppress("UNUSED_PARAMETER", "RedundantSuspendModifier") + private class TestRepo { + fun query() = flowOf>() + suspend fun fetch() = listOf() + suspend fun save(old: List, new: List) {} + } +} From cb1b467a2136d58b756cbc3fd9078651cfa81fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Studzi=C5=84ski?= <48914870+studzinskik@users.noreply.github.com> Date: Sun, 7 Mar 2021 21:31:14 +0100 Subject: [PATCH 51/53] Add studzinskik to contributors (#1198) --- app/src/main/assets/contributors.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/assets/contributors.json b/app/src/main/assets/contributors.json index d4346178..3b11c971 100644 --- a/app/src/main/assets/contributors.json +++ b/app/src/main/assets/contributors.json @@ -42,5 +42,9 @@ { "displayName": "Damian Czupryn", "githubUsername": "Daxxxis" + }, + { + "displayName": "Kamil Studziński", + "githubUsername": "studzinskik" } ] From c0e1a5b401a9b63f91490ef9f39326761a2f8790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sun, 7 Mar 2021 21:48:29 +0100 Subject: [PATCH 52/53] New Crowdin updates (#1167) --- .../main/res/layout/dialog_account_edit.xml | 6 +- .../preferences_values.xml | 0 .../preferences_values.xml | 0 .../{values-cs-rCZ => values-cs}/strings.xml | 46 +- app/src/main/res/values-de/strings.xml | 46 +- .../res/values-lt-v29/preferences_values.xml | 9 + .../main/res/values-lt/preferences_values.xml | 53 ++ app/src/main/res/values-lt/strings.xml | 535 ++++++++++++++++++ .../main/res/values-pl/preferences_values.xml | 2 +- app/src/main/res/values-pl/strings.xml | 46 +- app/src/main/res/values-ru/strings.xml | 46 +- .../preferences_values.xml | 0 .../preferences_values.xml | 0 .../{values-sk-rSK => values-sk}/strings.xml | 46 +- app/src/main/res/values-uk/strings.xml | 46 +- 15 files changed, 800 insertions(+), 81 deletions(-) rename app/src/main/res/{values-cs-rCZ-v29 => values-cs-v29}/preferences_values.xml (100%) rename app/src/main/res/{values-cs-rCZ => values-cs}/preferences_values.xml (100%) rename app/src/main/res/{values-cs-rCZ => values-cs}/strings.xml (93%) create mode 100644 app/src/main/res/values-lt-v29/preferences_values.xml create mode 100644 app/src/main/res/values-lt/preferences_values.xml create mode 100644 app/src/main/res/values-lt/strings.xml rename app/src/main/res/{values-sk-rSK-v29 => values-sk-v29}/preferences_values.xml (100%) rename app/src/main/res/{values-sk-rSK => values-sk}/preferences_values.xml (100%) rename app/src/main/res/{values-sk-rSK => values-sk}/strings.xml (93%) diff --git a/app/src/main/res/layout/dialog_account_edit.xml b/app/src/main/res/layout/dialog_account_edit.xml index ed64f25b..9f617e44 100644 --- a/app/src/main/res/layout/dialog_account_edit.xml +++ b/app/src/main/res/layout/dialog_account_edit.xml @@ -89,7 +89,7 @@ Token vypršel Neplatný e-mail Místo e-mailu použijte přiřazené přihlašovací údaje + Použijte přiřazené přihlašovací nebo e-mail v @%1$s Neplatný symbol Žák nebyl nalezen. Zkontrolujte správnost symbolu a vybrané varianty deníku UONET+ Toto pole je povinné @@ -313,6 +314,10 @@ Žádné informace o šťastném čísle Šťastné číslo pro dnešek Dnes je šťastným číslem: %d + Zobrazit historii + + Historie šťastných čísel + Žádné informace o šťastných číslech Mobilní přístup Žádná zařízení @@ -404,6 +409,7 @@ Přezdívka Přidat přezdívku + Vybrat barvu avataru Sdílet protokoly Obnovit @@ -438,21 +444,21 @@ Tmavý Motiv systému - Vzhled + Vzhled a chování aplikací Výchozí zobrazení Výpočet koncoročního průměru Vynutit průměrný výpočet podle aplikace - Zobrazit přítomnost v docházce - Motiv aplikace + Zobrazit přítomnost + Motiv Rozbalit známky - Označit aktuální lekci v plánu lekce - Zobrazit skupiny vedle předmětů v plánu lekce + Označit aktuální lekci + Zobrazit skupiny vedle předmětů Zobrazit seznam grafů v známkách třídy Zobrazit lekce pro celou třídu - Zobrazit předměty bez známek v \"Známky\" + Zobrazit předměty bez známek Známky barevné schéma - Třídění předmětů v \"Známky\" - Jazyk aplikace + Třídění předmětů + Jazyk Upozornění Zobrazit upozornění Zobrazit upozornění o nadcházející lekci @@ -460,6 +466,7 @@ Vaše zařízení může mít problémy se synchronizací dat as upozorněními.\n\nChcete-li je opravit, přidejte Wulkanového do funkce Autostart a vypněte optimalizaci/úsporu baterie v nastavení systému telefonu. Přejít do nastavení Zobrazit upozornění o ladění + Synchronizace je vypnutá Synchronizace Automatická aktualizace Pozastaveno na dovolené @@ -469,14 +476,27 @@ Synchronizováno! Synchronizace selhala Probíhá synchronizace - Synchronizace - Ruční synchronizace neobnoví zobrazení aplikace. - \nChcete-li zobrazit synchronizovaná data, restartujte aplikaci po synchronizaci. - - Jiné Hodnota plusu Hodnota mínusu Odpovědět s historií zpráv + Pokročilé + Vzhled a chování + Upozornění + Synchronizace + Známky + Docházka + Plán lekce + Známky + Zprávy + Vzhled a chování + Jazyky, motivy, třídění předmětů + Upozornění aplikace, oprava problémů + Upozornění + Synchronizace + Automatická aktualizace, interval aktualizací + Hodnota plusu a mínusu, výpočet průměru + Pokročilé + Verze aplikace, tvůrci, sociální portály, licence Nové položky v deníku Nové známky diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 0cf67fa4..a0994b42 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -46,6 +46,7 @@ Token ist nicht mehr gültig Ungültige email Den zugewiesenen Login anstelle von email verwenden + Benutze den zugewiesenen Login oder E-Mail in @%1$s Ungültige symbol Schüler nicht gefunden. Überprüfen Sie das Symbol und die gewählte Variation des UONET+ Registers Dieses Datenfeld ist erforderlich @@ -273,6 +274,10 @@ Keine Information über die Glücksnummer. Glücksnummer für heute Die heutige Glücksnummer ist: %d + Verlauf anzeigen + + Glücksnummerverlauf + Keine Information über die Glücksnummer Mobile Geräte Keine Geräte @@ -364,6 +369,7 @@ Nick Nick hinzufügen + Avatar-Farbe wählen Logs teilen Aktualisieren @@ -398,21 +404,21 @@ Dunkel Systemthema - Erscheinungsbild + Aussehen & Verhalten Standard Ansicht Berechnung des Jahresenddurchschnitts Mittelwertberechnung durch App erzwingen - Anwesenheit in Schulbesuch zeigen - Thema der Anwendung + Anwesendheit zeigen + Thema Noten erweitern - Aktuelle Lektion im Stundenplan markieren - Gruppen neben Schulfächer im Zeitplan anzeigen + Aktuelle Lektion markieren + Gruppen neben Schulfächen anzeigen Liste der Diagramme in Klassenbewertungen anzeigen Unterricht der ganzen Klasse anzeigen - Schulfächer ohne Noten in \"Noten\" anzeigen + Schulfächer ohne Noten anzeigen Farbschema der Noten - Schulfächer sortieren in \"Noten\" - App Sprache + Schulfachen sortieren + Sprache Benachrichtigungen Benachrichtigungen anzeigen Benachrichtigungen über bevorstehende Lektionen anzeigen @@ -420,6 +426,7 @@ Ihr Gerät hat möglicherweise Probleme mit der Datensynchronisierung und Benachrichtigungen.\n\nUm diese zu reparieren, fügen Sie Wulkanowy zum Autostart hinzu und deaktivieren Sie die Batterieoptimierung in den Systemeinstellungen des Geräts. Gehe zu den Einstellungen Debug-Benachrichtigungen anzeigen + Synchronisierung ist deaktiviert Synchronisierung Automatische Aktualisierung An Feiertagen suspendiert @@ -429,14 +436,27 @@ Synchronisiert! Synchronisierung fehlgeschlagen Synchronisierung läuft - Synchronisation - Die manuelle Synchronisierung aktualisiert die App-Ansichten nicht. - \nUm die synchronisierten Daten anzuzeigen, starten Sie die App nach der Synchronisierung neu. - - Andere Wert des Plus Wert des Minus Antwort mit Nachrichtenhistorie + Erweitert + Aussehen & Verhalten + Benachrichtigungen + Synchronisierung + Noten + Schulbesuch + Zeitplan + Noten + Nachrichten + Aussehen & Verhalten + Sprachen, Themen, Schulfachen sortieren + App-Benachrichtigungen, Probleme beheben + Benachrichtigungen + Synchronisierung + Automatisches Update, Synchronisierungsintervall + Plus und Minus Werte, Durchschnittsberechnung + Erweitert + App-Version, Mitarbeiter, soziale Portale, Lizenzen Neue Einträge im Klassenbuch Neue Noten diff --git a/app/src/main/res/values-lt-v29/preferences_values.xml b/app/src/main/res/values-lt-v29/preferences_values.xml new file mode 100644 index 00000000..18cbd4cf --- /dev/null +++ b/app/src/main/res/values-lt-v29/preferences_values.xml @@ -0,0 +1,9 @@ + + + + Sistemos tema + Šviesi + Tamsi + Juoda (AMOLED) + + diff --git a/app/src/main/res/values-lt/preferences_values.xml b/app/src/main/res/values-lt/preferences_values.xml new file mode 100644 index 00000000..fcb637d2 --- /dev/null +++ b/app/src/main/res/values-lt/preferences_values.xml @@ -0,0 +1,53 @@ + + + + Šviesi + Tamsi + Juoda (AMOLED) + + + Sistemos kalba + Polski + English + Pусский + Українська + Deutsch + Čeština + Slovenčina + + + 15 minučių + 30 minučių + 1 valandą + 2 valandas + 6 valandas + 12 valandas + 24 valandas + + + 0,00 + 0,25 + 0,33 + 0,5 + 0,75 + + + Pagal abėcėlę + Pagal datą + + + Dzienniczek+ + Wulkanowy + Laipsnio spalvos registre + + + Antrojo semestro laipsnių vidurkis + Abiejų semestrų laipsnių vidurkis + Visų metų laipsnių vidurkis + + + Nerodyti + Rodyti viską + Rodyti mažesnį + + diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml new file mode 100644 index 00000000..6542a5bc --- /dev/null +++ b/app/src/main/res/values-lt/strings.xml @@ -0,0 +1,535 @@ + + + + Login + Wulkanowy + Laipsnis + Attendance + Exams + Timetable + Nustatymai + Daugiau + Apie + Peržiūrėti žurnalą + Prisidėję + Licencijos + Žinutės + Nauja žinutė + Pastabos ir pasiekimai + Namų darbai + Paskyros valdymas + Pasirinkite paskyrą + Paskyros informacija + Studentų informacija + + Semestras %1$d, %2$d/%3$d + + Sign in with the student or parent account + Enter the symbol from the register page + Vartotojo vardas + El. paštas + Prisijunkite, PESEL arba el. paštas + Slaptažodis + UONET+ register variant + Mobile API + Scraper + Hibridas + Token + PIN + API raktas + Symbol + Prisijungti + Slaptažodis per trumpas + Login details are incorrect. Make sure the correct UONET+ register variation is selected in the field below + Netinkamas PIN kodas + Invalid token + Token expired + Neteisingas el. paštas + Use the assigned login instead of email + Use the assigned login or email in @%1$s + Netinkamas simbolis + Student not found. Validate the symbol and the chosen variation of the UONET+ register + This field is required + Selected student is already logged in + The symbol can be found on the register page in Uczeń → Dostęp Mobilny → Zarejestruj urządzenie mobilne.\n\nMake sure that you have set the appropriate register variant in the UONET+ register variant field on the previous screen. Wulkanowy does not detect pre-school students at the moment + Select students to log in to the application + Papildomi nustatymai + In this mode, a lucky number does not work, a class grade stats, summary of attendance, excuse for absence, completed lessons, school information and preview of the list of registered devices + This mode displays the same data as it appears on the register website + The combination of the best features of the other two modes. It works faster than scraper and provides features not available in the Mobile API mode. It is in the experimental phase + Privatumo politika + Trouble signing in? Contact us! + El. paštas + Discord + Send email + Describe details of problem: + Make sure you select the correct UONET+ register variation! + I forgot my password + Recover your account + Atkurti + Student is already signed in + + Paskyros valdymas + Prisijungti + Sesijos laikas baigėsi + Sesijos laikas baigėsi, prašome prisijungti iš naujo + + Laipsnis + Semestras %d + Keisti semestrą + Jokių laipsnių + Svoris + Svoris: %s + Pastabos + Jokių naujų laipsnių + Number of new ratings: %1$d + Vidurkis: %1$.2f + Puantai: %s + Jokiu vidurkis + Numatomas: %1$s + Galutinis: %1$s + Bendras punktų skaičius + Galutinis laipsnis + Numatomas laipsnis + Calculated average + Final average + Summary + Class + Mark as read + Partial + Semester + Points + Legend + Average: %1$s + Class + Student + + %d grade + %d grades + %d grades + %d grades + + + New grade + New grades + New grades + New grades + + + New predicted grade + New predicted grades + New predicted grades + New predicted grades + + + New final grade + New final grades + New final grades + New final grades + + + You received %1$d grade + You received %1$d grades + You received %1$d grades + You received %1$d grades + + + You received %1$d predicted grade + You received %1$d predicted grades + You received %1$d predicted grades + You received %1$d predicted grades + + + You received %1$d final grade + You received %1$d final grades + You received %1$d final grades + You received %1$d final grades + + + Lesson + Room + Group + Hours + Changes + No lessons this day + %s min + %s sec + %1$s left + in %1$s + Finished + Now: %s + Next: %s + Later: %s + + Completed lessons + Show completed lessons + No info about completed lessons + Topic + Absence + Resources + + Additional lessons + Show additional lessons + No info about additional lessons + + Attendance summary + Absent for school reasons + Excused absence + Unexcused absence + Exemption + Excused lateness + Unexcused lateness + Present + Deleted + Unknown + Number of lesson + No entries + + %1$d absence + %1$d absences + %1$d absences + %1$d absences + + Absence reason (optional) + Send + Absence excused successfully! + You must select at least one absence! + Excuse + + Attendance + Total + + No exams this week + Type + Entry date + + Inbox + Sent + Trash + (no subject) + No messages + An error occurred while downloading message content + From: + To: + Date: %s + Reply + Forward + Delete + Move to trash + Delete permanently + Message deleted successfully + Share + Print + Subject + Content + Message sent successfully + Message does not exist + You need to choose at least 1 recipient + The message content must be at least 3 characters + + %d message + %d messages + %d messages + %d messages + + + New message + New messages + New messages + New messages + + + You received %1$d message + You received %1$d messages + You received %1$d messages + You received %1$d messages + + + No info about notes + Points + + %d note + %d notes + %d notes + %d notes + + + New note + New notes + New notes + New notes + + + You received %1$d note + You received %1$d notes + You received %1$d notes + You received %1$d notes + + + + %d praise + %d praises + %d praises + %d praises + + + New praise + New praises + New praises + New praises + + + You received %1$d praise + You received %1$d praises + You received %1$d praises + You received %1$d praises + + + + %d neutral note + %d neutral notes + %d neutral notes + %d neutral notes + + + New neutral note + New neutral notes + New neutral notes + New neutral notes + + + You received %1$d neutral note + You received %1$d neutral notes + You received %1$d neutral notes + You received %1$d neutral notes + + + No info about homework + Mark as done + Mark as undone + Attachments + + Lucky number + Today\'s lucky number is + No info about the lucky number + Lucky number for today + Today\'s lucky number is: %d + Show history + + Lucky number history + No info about lucky numbers + + Mobile devices + No devices + Deregister + Device removed + QR code + Token + Symbol + PIN + + School and teachers + + School + No info about school + School name + School address + Telephone + Name of headmaster + Name of pedagogue + Show on map + Call + + Teachers + No info about teachers + No subject + + Conferences + No info about conferences + + Add account + Logout + Do you want to log out this student? + Student logout + Student account + Parent account + Mobile API mode + Hybrid mode + Edit data + Accounts manager + Select student + Family + Contact + Residence details + Personal information + + App version + Contributors + List of Wulkanowy developers + Report a bug + Send a bug report via e-mail + FAQ + Read Frequently Asked Questions + Discord server + Join the Wulkanowy community + Facebook fanpage + Like our facebook fanpage + Privacy policy + Rules for collecting personal data + Homepage + Visit the website and help develop the application + Licenses + Licenses of libraries used in the application + + License + + Avatar + See more on GitHub + + No info about student or student family + Name + Second name + Gender + Polish citizenship + Family name + Mother\'s and father\'s names + Phone + Cellphone + E-mail + Address of residence + Address of registration + Correspondence address + Surname and first name + Degree of kinship + Address + Phones + Male + Female + Last name + + Nick + Add nick + Choose avatar color + + Share logs + Refresh + + Check for updates + Before reporting a bug, check first if an update with the bug fix is available + + Content + Retry + Description + No description + Teacher + Date + Entry date + Color + Details + Category + Close + No data + Subject + Prev + Next + Search + Search… + Yes + No + Save + + No lessons + Choose theme + Light + Dark + System Theme + + App appearance & behavior + Default view + Calculation of the end-of-year average + Force average calculation by app + Show presence + Theme + Expand grades + Mark current lesson + Show groups next to subjects + Show chart list in class grades + Show whole class lessons + Show subjects without grades + Grades color scheme + Subjects sorting + Language + Notifications + Show notifications + Show upcoming lesson notifications + Fix synchronization & notifications issues + Your device may have data synchronization issues and with notifications.\n\nTo fix them, you need to add Wulkanowy to the autostart and turn off battery optimization/saving in the phone settings. + Go to settings + Show debug notifications + Synchronization is disabled + Synchronization + Automatic update + Suspended on holidays + Updates interval + Wi-Fi only + Sync now + Synced! + Sync failed + Sync in progress + Value of the plus + Value of the minus + Reply with message history + Advanced + Appearance & Behavior + Notifications + Synchronization + Grades + Attendance + Timetable + Grades + Messages + Appearance & Behavior + Languages, themes, subjects sorting + App notifications, fix problems + Notifications + Synchronization + Automatic update, synchronization interval + Plus and minus values, average calculation + Advanced + App version, contributors, social portals, licenses + + New entries in register + New grades + Lucky number + New messages + New notes + Push notifications + Upcoming lessons + Debug + + Black + Red + Blue + Green + Purple + No color + + Copied + Undo + + Download of updates has started… + An update has just been downloaded. + Restart + Update failed! Wulkanowy may not function properly. Consider updating + + No internet connection + Connection to register failed. Servers can be overloaded. Please try again later + Loading data failed. Please try again later + Register password change required + Maintenance underway UONET + register. Try again later + Unknown UONET + register error. Try again later + Unknown application error. Please try again later + An unexpected error occurred + Feature disabled by your school + Feature not available. Login in a mode other than Mobile API + diff --git a/app/src/main/res/values-pl/preferences_values.xml b/app/src/main/res/values-pl/preferences_values.xml index 20dd919e..b25dc3e5 100644 --- a/app/src/main/res/values-pl/preferences_values.xml +++ b/app/src/main/res/values-pl/preferences_values.xml @@ -25,7 +25,7 @@ 24 godziny - 0,0 + 0,00 0,25 0,33 0,5 diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index f45886b7..3f69d2a8 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -46,6 +46,7 @@ Token stracił ważność Niepoprawny adres email Użyj przydzielonego loginu zamiast emaila + Użyj przypisanego loginu lub adresu e-mail w @%1$s Niepoprawny symbol Nie znaleziono ucznia. Sprawdź poprawność symbolu i wybranej odmiany dziennika UONET+ To pole jest wymagane @@ -313,6 +314,10 @@ Brak informacji o szczęśliwym numerku Szczęśliwy numerek na dzisiaj Dziś szczęśliwym numerkiem jest: %d + Pokaż historię + + Historia numerków + Brak informacji o szczęśliwych numerach Dostęp mobilny Brak urządzeń @@ -404,6 +409,7 @@ Pseudonim Dodaj pseudonim + Wybierz kolor awatara Udostępnij logi Odśwież @@ -438,21 +444,21 @@ Ciemny Motyw systemu - Wygląd + Wygląd i zachowanie aplikacji Domyślny widok Obliczanie średniej końcoworocznej Wymuś obliczanie średniej przez aplikację - Pokazuj obecność we frekwencji - Motyw aplikacji + Pokazuj obecność + Motyw Rozwiń oceny - Oznaczaj bieżącą lekcję na planie - Pokazuj grupę obok przedmiotu na planie + Oznaczaj bieżącą lekcję + Pokazuj grupę obok przedmiotu Pokazuj listę wykresów w ocenach klasy Pokazuj lekcje całej klasy - Pokazuj przedmioty bez ocen w Ocenach + Pokazuj przedmioty bez ocen Schemat kolorów ocen - Sortowanie przedmiotów w \"Oceny\" - Język aplikacji + Sortowanie przedmiotów + Język Powiadomienia Pokazuj powiadomienia Pokazuj powiadomienia o nadchodzących lekcjach @@ -460,6 +466,7 @@ Na twoim urządzeniu mogą występować problemy z synchronizacją danych i powiadomieniami.\n\nBy je naprawić, dodaj Wulkanowego do autostartu i wyłącz optymalizację/oszczędzanie baterii w ustawieniach systemowych telefonu. Przejdź do ustawień Pokazuj powiadomienia debugowania + Synchronizacja jest wyłączona Synchronizacja Automatyczna aktualizacja Zawieszona na wakacjach @@ -469,14 +476,27 @@ Zsynchronizowano! Synchronizacja nie powiodła się Synchronizacja w trakcie - Synchronizacja - Ręczna synchronizacja nie odświeża widoków w aplikacji. - \nAby zobaczyć zsynchronizowane informacje, uruchom ponownie aplikację po zsynchronizowaniu. - - Inne Wartość plusa Wartość minusa Odpowiadaj z historią wiadomości + Zaawansowane + Wygląd i zachowanie + Powiadomienia + Synchronizacja + Oceny + Frekwencja + Plan lekcji + Oceny + Wiadomości + Wygląd i zachowanie + Języki, motywy, sortowanie przedmiotów + Powiadomienia aplikacji, naprawianie problemów + Powiadomienia + Synchronizacja + Automatyczna aktualizacja, interwał synchronizacji + Wartości plusa i minusa, obliczanie średniej + Zaawansowane + Wersja aplikacji, twórcy, media społecznościowe, licencje Nowe wpisy w dzienniku Nowe oceny diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 0de20ea9..02407bbd 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -46,6 +46,7 @@ Token просрочен Неверный адрес электронной почты Используйте назначенный логин вместо электронной почты + Использовать назначенный логин или email в @%1$s Неправильный символ Студент не найден. Подтвердите символ и выбранный вариант регистра UONET+ Это обязательное поле @@ -313,6 +314,10 @@ Нет данных о счастливом номере Сегодняшний счастливый номер Сегодняшний счастливый номер это: %d + Показать историю + + История удачных чисел + Нет информации о номерах удачи Мобильные устройства Нет устройств @@ -404,6 +409,7 @@ Ник Добавить ник + Выберите цвет аватара Поделиться логами Обновить @@ -438,21 +444,21 @@ Тёмная Тема системы - Вид + Внешний вид приложения & поведение Окно по умолчанию Способ определения средней годовой оценки Принудительно высчитать среднюю оценку через приложение - Показывать присутствия в посещаемости - Тема приложения + Показать присутствие + Тема Разворачивать оценки - Отмечать текущий урок в расписании - Показать группу возле предмета в расписании + Отметить текущий урок + Показать группы рядом с темами Показывать диаграммы в оценках класса Показать уроки всего класса - Показывать предметы без оценок в \"Оценках\" + Показать предметы без оценок Схема цветов оценок - Сортировка предметов в \"Оценках\" - Язык приложения + Сортировка уроков + Язык Уведомления Показывать уведомления Показывать уведомления о будущих уроках @@ -460,6 +466,7 @@ На вашем устройстве могут быть проблемы с синхронизацией данных и уведомлениями.\n\nЧтобы их исправить, вам необходимо добавить Wulkanowy в авто-старт и выключить оптимизацию/экономию батареи в настройках устройства. Перейти в настройски Показывать дебаг-уведомления + Синхронизация отключена Синхронизация Автоматическая синхронизация Приостановить синхронизации во время каникул @@ -469,14 +476,27 @@ Синхронизировано! Синхронизация не удалась Идёт синхронизация - Синхронизация - Ручная синхронизация не обновляет данные в приложении. - \nЧтобы увидеть обновлённые данные, перезапустите приложение. - - Другие Стоимость плюса Стоимость минуса Отвечать с историей сообщений + Расширенные + Внешний вид & Поведение + Уведомления + Синхронизация + Оценки + Посещаемость + Расписание + Оценки + Сообщения + Внешний вид & Поведение + Языки, темы, темы сортировки темы + Уведомления приложений, проблемы с устранением + Уведомления + Синхронизация + Автоматическое обновление, интервал синхронизации + Значения плюс и минус, средний расчет + Расширенные + Версия приложения, участники, социальные порталы, лицензии Новые данные в дневнике Новые оценки diff --git a/app/src/main/res/values-sk-rSK-v29/preferences_values.xml b/app/src/main/res/values-sk-v29/preferences_values.xml similarity index 100% rename from app/src/main/res/values-sk-rSK-v29/preferences_values.xml rename to app/src/main/res/values-sk-v29/preferences_values.xml diff --git a/app/src/main/res/values-sk-rSK/preferences_values.xml b/app/src/main/res/values-sk/preferences_values.xml similarity index 100% rename from app/src/main/res/values-sk-rSK/preferences_values.xml rename to app/src/main/res/values-sk/preferences_values.xml diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk/strings.xml similarity index 93% rename from app/src/main/res/values-sk-rSK/strings.xml rename to app/src/main/res/values-sk/strings.xml index f0b8591a..32bd8067 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -46,6 +46,7 @@ Platnosť tokenu vypršala Neplatný e-mail Namiesto e-mailu použite priradené prihlasovacie údaje + Použite priradené prihlasovacie alebo e-mail v @%1$s Neplatný symbol Žiak nebol nájdený. Skontrolujte správnosť symbolu a vybrané varianty denníka UONET+ Toto pole je povinné @@ -313,6 +314,10 @@ Žiadne informácie o šťastnom čísle Šťastné číslo pre dnešok Dnes je šťastným číslom: %d + Zobraziť históriu + + História šťastných čísel + Žiadne informácie o šťastných číslach Mobilný prístup Žiadne zariadenia @@ -404,6 +409,7 @@ Prezývka Pridať prezývku + Vybrať farbu avataru Zdieľať protokoly Obnoviť @@ -438,21 +444,21 @@ Tmavý Motív systému - Vzhľad + Vzhľad a správanie aplikácií Predvolené zobrazenie Výpočet koncoročního priemeru Vynútiť priemerný výpočet podľa aplikácie - Zobraziť prítomnosť v dochádzke - Motív aplikácie + Zobraziť prítomnosť + Motív Rozbaliť známky - Označiť aktuálne lekciu v pláne lekcie - Zobraziť skupiny vedľa predmetov v pláne lekcie + Označiť aktuálne lekciu + Zobraziť skupiny vedľa predmetov Zobraziť zoznam grafov v známkach triedy Zobraziť lekcie pre celú triedu - Zobraziť predmety bez známok v \"Známky\" + Zobraziť predmety bez známok Známky farebnú schému - Triedenie predmetov v \"Známky\" - Jazyk aplikácie + Triedenie predmetov + Jazyk Upozornenia Zobraziť upozornenia Zobraziť upozornenia o nadchádzajúcej lekciu @@ -460,6 +466,7 @@ Vaše zariadenie môže mať problémy so synchronizáciou dát as upozorneniami.\n\nAk ich chcete opraviť, pridajte Wulkanového do funkcie Autostart a vypnite optimalizáciu/úsporu batérie v nastavení systému telefóne. Prejsť do nastavení Zobraziť upozornenia o ladení + Synchronizácia je vypnutá Synchronizácia Automatická aktualizácia Pozastavený počas dovolenky @@ -469,14 +476,27 @@ Synchronizovano! Synchronizácia zlyhala Prebieha synchronizácia - Synchronizácia - Ručná synchronizácia neobnoví zobrazenie aplikácie. - \nAk chcete zobraziť synchronizované údaje, reštartujte aplikáciu po synchronizácii. - - Iné Hodnota plusu Hodnota mínusu Odpovedať s históriou správ + Pokročilé + Vzhľad a správanie + Upozornenia + Synchronizácia + Známky + Dochádzka + Plán lekcie + Známky + Správy + Vzhľad a správanie + Jazyky, motívy, triedenie predmetov + Upozornenia aplikácie, oprava problémov + Upozornenia + Synchronizácia + Automatická aktualizácia, interval aktualizácií + Hodnota plusu a mínusu, výpočet priemeru + Pokročilé + Verzia aplikácie, prispievatelia, sociálne portály, licencie Nové položky v denníku Nové známky diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 843c3616..64e147e7 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -46,6 +46,7 @@ Минув термін дії токену Недійсна адреса електронної пошти Використовуйте призначений логін замість електронної пошти + Використовуйте призначений логін або електронну адресу в @% 1 $ s Неправильний симбвол Студента не знайдено Перевірте символ та обраний варіант реєстру UONET+ Обов\'язкове поле @@ -313,6 +314,10 @@ Брак інформації о щасливому номері Сьогоднішній щасливий номер Сьогоднішнім щасливим номером є %d + Показати історію + + Історія щасливих чисел + Немає інформації про щасливі номери Мобільні пристрої Брак пристроїв @@ -404,6 +409,7 @@ Псевдонім Додати псевдонім + Оберіть колір аватара Поділитися логами Оновити @@ -438,21 +444,21 @@ Темна Тема системи - Вигляд + Поява додатка & amp; поведінки Вікно за замовчуванням Спосіб облічування оцінки на кінець року Примусово розрахувати середню оцінку через додаток - Показувати присутність у відвідуваності - Тема додатку + Показати присутність + Тема Більше оцінок - Позначити поточний урок у розкладі - Покажіть групи поруч із предметами в розкладі + Позначити поточний урок + Показувати групи поруч з темами Показувати діаграми в оцінках класу Показати уроки всього класу - Показуйте предмети без оцінок у оцінках + Показати предмети без оцінок Схема кольорів оцінок - Сортування предметів за \"Оцінками\" - Мова додатку + Сортування предметів + Мова Повідомлення Показувати повідомлення Показувати повідомлення о наступних уроках @@ -460,6 +466,7 @@ На вашому пристрої можуть бути помилки з синхронізацією і повідомленнями\n\nЩоб виправити іх, вам необхідно додати Wulkanowy в авто-старт и вимкнути оптимізацію/экономію батареї в налаштуваннях пристрою. Перейти до налаштувань Показувати дебаг-повідомлення + Синхронізація вимкнена Синхронізація Автоматична синхронізація Призупинено на час канікул @@ -469,14 +476,27 @@ Синхронізовано! Синхронізація не вдалася Триває синхронізація - Синхронізація - Ручна синхронізація не оновлює дані в додатку. - \nЩоб побачити оновлені дані, перезавантажте додаток. - - Інші Вартість плюсу Вага мінуса Відповісти з історією повідомлень + Додатково + Вигляд & Поведінка + Повідомлення + Синхронізація + Оцінки + Відвідуваність + Розклад + Класи + Повідомлення + Вигляд & Поведінка + Мови, теми, тема сортування + Сповіщення додатку, виправляти проблеми + Повідомлення + Синхронізація + Автоматичне оновлення, інтервал синхронізації + Плюс і мінус значення, середні обчислення + Додатково + Версія програми, учасники, соціальні портали, ліцензії Нові дані в щоденнику Нові оцінки From be48791d51d1d0c03d1b0080dd673ce5493081d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 7 Mar 2021 21:58:14 +0100 Subject: [PATCH 53/53] Version 1.1.0 --- app/build.gradle | 8 ++++---- app/src/main/play/release-notes/pl-PL/default.txt | 11 ++++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index dfbc26b2..6af83ab0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 30 - versionCode 85 - versionName "1.0.1" + versionCode 86 + versionName "1.1.0" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -133,7 +133,7 @@ play { serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf" serviceAccountCredentials = file('key.p12') defaultToAppBundles = false - track = 'alpha' + track = 'production' updatePriority = 3 } @@ -147,7 +147,7 @@ ext { } dependencies { - implementation "io.github.wulkanowy:sdk:1.0.1" + implementation "io.github.wulkanowy:sdk:1.1.0" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' 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 3404b05b..35320c1e 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 1.0.1 +Wersja 1.1.0 -- naprawiliśmy błąd podczas wysyłania wiadomości -- poprawiliśmy błędy w tłumaczeniach +- dodaliśmy wyświetlanie inicjałów imienia ucznia jako awatar widoczny w aplikacji +- dodaliśmy historię szczęśliwego numerka +- dodaliśmy język słowacki +- zmieniliśmy kolor górnego i dolnego paska systemowego lepiej dostosowując je do aplikacji +- zmieniliśmy wygląd ustawień dzieląc je na sekcje +- naprawiliśmy problem dublujących się czasem ocen +- naprawiliśmy kilka innych błędów i poprawiliśmy stabilność aplikacji Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases