1
0

Compare commits

...

50 Commits

Author SHA1 Message Date
afee97a706 Merge branch 'release/0.23.0' 2020-12-06 22:21:36 +01:00
73a92497ed Version 0.23.0 2020-12-06 22:12:18 +01:00
67cef0f6d9 Add register variant auto-matching based on email (#1041) 2020-12-06 21:23:02 +01:00
6ca5e11371 Fix HMS analytics and crashlytics (#1042) 2020-12-06 19:31:35 +01:00
05a597313b Bump hilt_version from 2.29.1-alpha to 2.30.1-alpha (#1035) 2020-12-06 17:54:09 +00:00
33d540e1c9 Bump desugar_jdk_libs from 1.0.10 to 1.1.1 (#1039) 2020-12-06 15:04:43 +00:00
d115372c3b Bump coil from 1.0.0 to 1.1.0 (#1040) 2020-12-06 14:57:50 +00:00
e637896ad3 Bump firebase-crashlytics from 17.2.2 to 17.3.0 (#1038) 2020-12-06 14:50:57 +00:00
ce802cc737 Bump about_libraries from 8.6.2 to 8.6.3 (#1037) 2020-12-06 14:43:48 +00:00
bf342ed289 Bump kotlinx-coroutines-test from 1.4.0 to 1.4.2-native-mt (#1031) 2020-12-06 14:32:08 +00:00
40ec5bbe86 Bump kotlinx-coroutines-android from 1.4.0 to 1.4.2-native-mt (#1032) 2020-12-06 14:29:32 +00:00
41dbd2d25f New Crowdin updates (#1033) 2020-12-06 15:14:58 +01:00
f263b5534a Bump mockk from 1.10.2 to 1.10.3-jdk8 (#1034) 2020-12-06 14:08:26 +00:00
7ed4787496 Bump chucker from 3.3.0 to 3.4.0 (#1027) 2020-12-03 14:19:21 +00:00
1428887204 Bump agconnect-crash from 1.4.1.300 to 1.4.2.301 (#1030) 2020-12-03 13:57:37 +00:00
0fc828f006 Bump agcp from 1.4.1.300 to 1.4.2.301 (#1024) 2020-12-03 13:48:25 +00:00
13906a7d62 Bump about_libraries from 8.4.3 to 8.6.2 (#1025) 2020-12-03 13:47:26 +00:00
3c0dda9a82 Bump hianalytics from 5.0.4.301 to 5.0.5.301 (#1023) 2020-12-03 13:29:49 +00:00
c42333cd35 Bump firebase-crashlytics-gradle from 2.3.0 to 2.4.1 (#1029) 2020-12-03 13:28:10 +00:00
c675dc8b84 Bump kotlin_version from 1.4.10 to 1.4.20 (#1026) 2020-12-03 13:27:47 +00:00
5e9853b043 New Crowdin updates (#1022) 2020-11-21 15:50:18 +01:00
c7fdcc2bbd Add facebook link to about (#1021) 2020-11-17 16:58:24 +01:00
8a00ae95b8 Update contributor's username (#1020) 2020-11-13 23:59:45 +01:00
a1ebf6c6ad Add average in class grades statistics (#1017) 2020-11-11 16:03:52 +01:00
ada5854d10 New Crowdin updates (#1013) 2020-11-02 17:54:02 +01:00
fe191bb0df Bump firebase-analytics from 17.6.0 to 18.0.0 (#1009) 2020-11-01 18:36:55 +00:00
9eb091fbf4 Bump kotlinx-coroutines-android from 1.3.9 to 1.4.0 (#1005) 2020-11-01 18:16:21 +00:00
57e760844f Bump kotlinx-coroutines-test from 1.3.9 to 1.4.0 (#1012) 2020-11-01 18:15:52 +00:00
20644a7a67 Update english strings (#1014) 2020-11-01 19:05:05 +01:00
b3109aed0b Bump firebase-messaging from 20.3.0 to 21.0.0 (#1008) 2020-11-01 16:40:39 +00:00
9ba999feb0 Bump about_libraries from 8.4.2 to 8.4.3 (#1011) 2020-11-01 16:28:32 +00:00
7c9e85793b Bump firebase-inappmessaging-display-ktx from 19.1.1 to 19.1.2 (#1007) 2020-11-01 16:15:17 +00:00
6af8263952 Bump firebase-inappmessaging-ktx from 19.1.1 to 19.1.2 (#1010) 2020-11-01 15:55:51 +00:00
83d1d860a6 Bump coil from 1.0.0-rc3 to 1.0.0 (#1006) 2020-11-01 15:55:36 +00:00
8830240182 Add conferences (#1004) 2020-11-01 16:53:31 +01:00
c3061e75b5 Merge branch 'release/0.22.2' into develop 2020-10-30 12:31:58 +01:00
5f1bb7c1d0 Merge branch 'release/0.22.2' into master 2020-10-30 12:31:50 +01:00
c6f4c868b2 Version 0.22.2 2020-10-30 12:31:41 +01:00
c634c64e70 Update hianalytics to 5.0.4.301 (#1003) 2020-10-30 12:24:00 +01:00
da2b7dbf7e Merge branch 'release/0.22.1' into develop 2020-10-30 01:49:56 +01:00
26267507eb Merge branch 'release/0.22.1' into master 2020-10-30 01:49:42 +01:00
24d0c5057b Version 0.22.1 2020-10-30 01:49:30 +01:00
b05026a6e6 New Crowdin updates (#1002) 2020-10-30 00:54:35 +01:00
8036f3d7f7 Add HMS flavor (#998) 2020-10-29 13:58:56 +01:00
23e309d38e New Crowdin updates (#993) 2020-10-26 11:54:27 +01:00
bf92c6b2e9 Fix grade header item object comparision (#999) 2020-10-25 12:16:19 +01:00
c00b5edaf7 Make AppGallery badge background transparent. (#997) 2020-10-22 16:17:52 +02:00
cb09ca13dc Bump junit from 4.13 to 4.13.1 (#995) 2020-10-15 18:36:31 +00:00
3d68b8e629 Bump gradle from 4.0.2 to 4.1.0 (#996) 2020-10-15 18:36:13 +00:00
b3173581e5 Merge tag '0.22.0' into develop
Version 0.22.0
2020-10-15 17:54:27 +02:00
108 changed files with 5404 additions and 488 deletions

3
.gitignore vendored
View File

@ -113,3 +113,6 @@ Thumbs.db
!/gradle/wrapper/gradle-wrapper.jar !/gradle/wrapper/gradle-wrapper.jar
.idea/jarRepositories.xml .idea/jarRepositories.xml
app/src/release/agconnect-services.json

View File

@ -14,7 +14,7 @@ cache:
branches: branches:
only: only:
- develop - develop
- 0.22.0 - 0.23.0
android: android:
licenses: licenses:
@ -58,6 +58,7 @@ script:
- | - |
if [ $TRAVIS_TAG ]; then if [ $TRAVIS_TAG ]; then
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg; gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg;
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/agconnect-services.json.gpg;
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg; gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg;
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg; gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg;
./gradlew publishPlayRelease -PenableFirebase --stacktrace; ./gradlew publishPlayRelease -PenableFirebase --stacktrace;

View File

@ -18,8 +18,8 @@ android {
testApplicationId "io.github.tests.wulkanowy" testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 30 targetSdkVersion 30
versionCode 73 versionCode 76
versionName "0.22.0" versionName "0.23.0"
multiDexEnabled true multiDexEnabled true
resValue "string", "app_name", "Wulkanowy" resValue "string", "app_name", "Wulkanowy"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -69,12 +69,26 @@ android {
flavorDimensions "platform" flavorDimensions "platform"
productFlavors { productFlavors {
hms {
dimension "platform"
minSdkVersion 19
manifestPlaceholders = [
install_channel: "AppGallery"
]
}
play { play {
dimension "platform" dimension "platform"
manifestPlaceholders = [
install_channel: "Google Play"
]
} }
fdroid { fdroid {
dimension "platform" dimension "platform"
manifestPlaceholders = [
install_channel: "F-Droid"
]
} }
} }
@ -112,14 +126,14 @@ play {
serviceAccountCredentials = file('key.p12') serviceAccountCredentials = file('key.p12')
defaultToAppBundles = false defaultToAppBundles = false
track = 'alpha' track = 'alpha'
updatePriority = 0 updatePriority = 3
} }
ext { ext {
work_manager = "2.4.0" work_manager = "2.4.0"
room = "2.2.5" room = "2.2.5"
chucker = "3.3.0" chucker = "3.4.0"
mockk = "1.10.2" mockk = "1.10.3-jdk8"
moshi = "1.11.0" moshi = "1.11.0"
} }
@ -128,12 +142,12 @@ configurations.all {
} }
dependencies { dependencies {
implementation "io.github.wulkanowy:sdk:0.22.0" implementation "io.github.wulkanowy:sdk:0.23.0"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'
implementation "androidx.core:core-ktx:1.3.2" implementation "androidx.core:core-ktx:1.3.2"
implementation "androidx.activity:activity-ktx:1.1.0" implementation "androidx.activity:activity-ktx:1.1.0"
@ -180,26 +194,29 @@ dependencies {
implementation "fr.bipi.treessence:treessence:0.3.2" implementation "fr.bipi.treessence:treessence:0.3.2"
implementation "com.mikepenz:aboutlibraries-core:$about_libraries" implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
implementation 'com.wdullaer:materialdatetimepicker:4.2.3' implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
implementation "io.coil-kt:coil:1.0.0-rc3" implementation "io.coil-kt:coil:1.1.0"
implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
implementation 'me.xdrop:fuzzywuzzy:1.3.1' implementation 'me.xdrop:fuzzywuzzy:1.3.1'
playImplementation 'com.google.firebase:firebase-analytics:17.6.0' playImplementation 'com.google.firebase:firebase-analytics:18.0.0'
playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.1' playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.2'
playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.1" playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.2"
playImplementation 'com.google.firebase:firebase-messaging:20.3.0' playImplementation 'com.google.firebase:firebase-messaging:21.0.0'
playImplementation 'com.google.firebase:firebase-crashlytics:17.2.2' playImplementation 'com.google.firebase:firebase-crashlytics:17.3.0'
playImplementation 'com.google.android.play:core-ktx:1.8.1' playImplementation 'com.google.android.play:core-ktx:1.8.1'
playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
hmsImplementation 'com.huawei.hms:hianalytics:5.0.5.301'
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.4.2.301'
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker" releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker" debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
debugImplementation "com.amitshekhar.android:debug-db:1.0.6" debugImplementation "com.amitshekhar.android:debug-db:1.0.6"
testImplementation "junit:junit:4.13" testImplementation "junit:junit:4.13.1"
testImplementation "io.mockk:mockk:$mockk" testImplementation "io.mockk:mockk:$mockk"
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9' testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2'
androidTestImplementation "androidx.test:core:1.3.0" androidTestImplementation "androidx.test:core:1.3.0"
androidTestImplementation "androidx.test:runner:1.3.0" androidTestImplementation "androidx.test:runner:1.3.0"
@ -210,3 +227,4 @@ dependencies {
} }
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.huawei.agconnect'

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,8 @@ import androidx.room.Room
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -27,7 +27,7 @@ class GradeStatisticsLocalTest {
fun createDb() { fun createDb() {
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
.build() .build()
gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics, testDb.gradePointsStatistics) gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradePartialStatisticsDao, testDb.gradePointsStatisticsDao, testDb.gradeSemesterStatisticsDao)
} }
@After @After
@ -41,9 +41,9 @@ class GradeStatisticsLocalTest {
getGradeStatistics("Matematyka", 2, 1), getGradeStatistics("Matematyka", 2, 1),
getGradeStatistics("Fizyka", 1, 2) getGradeStatistics("Fizyka", 1, 2)
) )
runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) } runBlocking { gradeStatisticsLocal.saveGradePartialStatistics(list) }
val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() } val stats = runBlocking { gradeStatisticsLocal.getGradePartialStatistics(getSemester()).first() }
assertEquals(1, stats.size) assertEquals(1, stats.size)
assertEquals(stats[0].subject, "Matematyka") assertEquals(stats[0].subject, "Matematyka")
} }
@ -55,12 +55,10 @@ class GradeStatisticsLocalTest {
getGradeStatistics("Chemia", 2, 1), getGradeStatistics("Chemia", 2, 1),
getGradeStatistics("Fizyka", 1, 2) getGradeStatistics("Fizyka", 1, 2)
) )
runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) } runBlocking { gradeStatisticsLocal.saveGradePartialStatistics(list) }
val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() } val stats = runBlocking { gradeStatisticsLocal.getGradePartialStatistics(getSemester()).first() }
assertEquals(2, stats.size) assertEquals(2, stats.size)
// assertEquals(3, stats.size)
// assertEquals(stats[0].subject, "Wszystkie") // now in main repo
assertEquals(stats[0].subject, "Matematyka") assertEquals(stats[0].subject, "Matematyka")
assertEquals(stats[1].subject, "Chemia") assertEquals(stats[1].subject, "Chemia")
} }
@ -72,9 +70,9 @@ class GradeStatisticsLocalTest {
getGradePointsStatistics("Chemia", 2, 1), getGradePointsStatistics("Chemia", 2, 1),
getGradePointsStatistics("Fizyka", 1, 2) getGradePointsStatistics("Fizyka", 1, 2)
) )
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(list) } runBlocking { gradeStatisticsLocal.saveGradePointsStatistics(list) }
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() } val stats = runBlocking { gradeStatisticsLocal.getGradePointsStatistics(getSemester()).first() }
with(stats[0]) { with(stats[0]) {
assertEquals(subject, "Matematyka") assertEquals(subject, "Matematyka")
assertEquals(others, 5.0) assertEquals(others, 5.0)
@ -84,17 +82,17 @@ class GradeStatisticsLocalTest {
@Test @Test
fun saveAndRead_subjectEmpty() { fun saveAndRead_subjectEmpty() {
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) } runBlocking { gradeStatisticsLocal.saveGradePointsStatistics(listOf()) }
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() } val stats = runBlocking { gradeStatisticsLocal.getGradePointsStatistics(getSemester()).first() }
assertEquals(emptyList(), stats) assertEquals(emptyList(), stats)
} }
@Test @Test
fun saveAndRead_allEmpty() { fun saveAndRead_allEmpty() {
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) } runBlocking { gradeStatisticsLocal.saveGradePointsStatistics(listOf()) }
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() } val stats = runBlocking { gradeStatisticsLocal.getGradePointsStatistics(getSemester()).first() }
assertEquals(emptyList(), stats) assertEquals(emptyList(), stats)
} }
@ -102,8 +100,8 @@ class GradeStatisticsLocalTest {
return Semester(2, 2, "", 2019, 1, 2, now(), now(), 1, 1) return Semester(2, 2, "", 2019, 1, 2, now(), now(), 1, 1)
} }
private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics { private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradePartialStatistics {
return GradeStatistics(studentId, semesterId, subject, 5, 5, false) return GradePartialStatistics(studentId, semesterId, subject, "", "", listOf(5), listOf(5))
} }
private fun getGradePointsStatistics(subject: String, studentId: Int, semesterId: Int): GradePointsStatistics { private fun getGradePointsStatistics(subject: String, studentId: Int, semesterId: Int): GradePointsStatistics {

View File

@ -0,0 +1,33 @@
{
"agcgw":{
"backurl":"connect-dre.dbankcloud.cn",
"url":"connect-dre.hispace.hicloud.com"
},
"client":{
"cp_id":"890048000024105546",
"product_id":"",
"client_id":"",
"client_secret":"",
"app_id":"101440411",
"package_name":"io.github.wulkanowy.dev",
"api_key":""
},
"service":{
"analytics":{
"collector_url":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
"resource_id":"p1",
"channel_id":""
},
"search":{
"url":"https://search-dre.cloud.huawei.com"
},
"cloudstorage":{
"storage_url":"https://ops-dre.agcstorage.link"
},
"ml":{
"mlservice_url":"ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
}
},
"region":"DE",
"configuration_version":"1.0"
}

View File

@ -6,7 +6,7 @@ import javax.inject.Singleton
@Singleton @Singleton
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
class FirebaseAnalyticsHelper @Inject constructor() { class AnalyticsHelper @Inject constructor() {
fun logEvent(name: String, vararg params: Pair<String, Any?>) { fun logEvent(name: String, vararg params: Pair<String, Any?>) {
// do nothing // do nothing
@ -15,4 +15,8 @@ class FirebaseAnalyticsHelper @Inject constructor() {
fun setCurrentScreen(activity: Activity, name: String?) { fun setCurrentScreen(activity: Activity, name: String?) {
// do nothing // do nothing
} }
fun popCurrentScreen(name: String?) {
// do nothing
}
} }

View File

@ -8,6 +8,6 @@ open class TimberTreeNoOp : Timber.Tree() {
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {} override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {}
} }
class CrashlyticsTree : TimberTreeNoOp() class CrashLogTree : TimberTreeNoOp()
class CrashlyticsExceptionTree : TimberTreeNoOp() class CrashLogExceptionTree : TimberTreeNoOp()

View File

@ -0,0 +1,39 @@
package io.github.wulkanowy.utils
import android.app.Activity
import android.content.Context
import android.os.Bundle
import com.huawei.hms.analytics.HiAnalytics
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class AnalyticsHelper @Inject constructor(
@ApplicationContext private val context: Context
) {
private val analytics by lazy { HiAnalytics.getInstance(context) }
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
Bundle().apply {
params.forEach {
if (it.second == null) return@forEach
when (it.second) {
is String, is String? -> putString(it.first, it.second as String)
is Int, is Int? -> putInt(it.first, it.second as Int)
is Boolean, is Boolean? -> putBoolean(it.first, it.second as Boolean)
}
}
analytics.onEvent(name, this)
}
}
fun setCurrentScreen(activity: Activity, name: String?) {
analytics.pageStart(name, activity::class.simpleName)
}
fun popCurrentScreen(name: String?) {
analytics.pageEnd(name)
}
}

View File

@ -0,0 +1,52 @@
package io.github.wulkanowy.utils
import android.util.Log
import com.huawei.agconnect.crash.AGConnectCrash
import fr.bipi.tressence.base.FormatterPriorityTree
import fr.bipi.tressence.common.StackTraceRecorder
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
import java.io.InterruptedIOException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
private val connectCrash by lazy { AGConnectCrash.getInstance() }
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
if (skipLog(priority, tag, message, t)) return
connectCrash.log(format(priority, tag, message))
}
}
class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR) {
private val connectCrash by lazy { AGConnectCrash.getInstance() }
override fun skipLog(priority: Int, tag: String?, message: String, t: Throwable?): Boolean {
return when (t) {
is FeatureDisabledException,
is FeatureNotAvailableException,
is UnknownHostException,
is SocketTimeoutException,
is InterruptedIOException -> true
else -> super.skipLog(priority, tag, message, t)
}
}
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
if (skipLog(priority, tag, message, t)) return
connectCrash.setCustomKey("priority", priority)
connectCrash.setCustomKey("tag", tag.orEmpty())
connectCrash.setCustomKey("message", message)
if (t != null) {
connectCrash.recordException(t)
} else {
connectCrash.recordException(StackTraceRecorder(format(priority, tag, message)))
}
}
}

View File

@ -0,0 +1,17 @@
package io.github.wulkanowy.utils
import android.app.Activity
import android.view.View
import javax.inject.Inject
@Suppress("UNUSED_PARAMETER")
class UpdateHelper @Inject constructor() {
lateinit var messageContainer: View
fun checkAndInstallUpdates(activity: Activity) {}
fun onActivityResult(requestCode: Int, resultCode: Int) {}
fun onResume(activity: Activity) {}
}

View File

@ -110,6 +110,11 @@
android:resource="@xml/provider_paths" /> android:resource="@xml/provider_paths" />
</provider> </provider>
<meta-data
android:name="install_channel"
android:value="${install_channel}">
</meta-data>
<!-- workaround for https://github.com/firebase/firebase-android-sdk/issues/473 enabled:false --> <!-- workaround for https://github.com/firebase/firebase-android-sdk/issues/473 enabled:false -->
<!-- https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html --> <!-- https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html -->
<provider <provider

View File

@ -33,6 +33,6 @@
}, },
{ {
"displayName": "Mateusz Idziejczak", "displayName": "Mateusz Idziejczak",
"githubUsername": "PanTajemnic" "githubUsername": "Luncenok"
} }
] ]

View File

@ -14,8 +14,8 @@ import fr.bipi.tressence.file.FileLoggerTree
import io.github.wulkanowy.ui.base.ThemeManager import io.github.wulkanowy.ui.base.ThemeManager
import io.github.wulkanowy.utils.ActivityLifecycleLogger import io.github.wulkanowy.utils.ActivityLifecycleLogger
import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.CrashlyticsExceptionTree import io.github.wulkanowy.utils.CrashLogExceptionTree
import io.github.wulkanowy.utils.CrashlyticsTree import io.github.wulkanowy.utils.CrashLogTree
import io.github.wulkanowy.utils.DebugLogTree import io.github.wulkanowy.utils.DebugLogTree
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -56,8 +56,8 @@ class WulkanowyApp : Application(), Configuration.Provider {
.build() .build()
) )
} else { } else {
Timber.plant(CrashlyticsExceptionTree()) Timber.plant(CrashLogExceptionTree())
Timber.plant(CrashlyticsTree()) Timber.plant(CrashLogTree())
} }
registerActivityLifecycleCallbacks(ActivityLifecycleLogger()) registerActivityLifecycleCallbacks(ActivityLifecycleLogger())
} }

View File

@ -11,8 +11,8 @@ import com.chuckerteam.chucker.api.RetentionManager
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
@ -21,7 +21,7 @@ import timber.log.Timber
import javax.inject.Singleton import javax.inject.Singleton
@Module @Module
@InstallIn(ApplicationComponent::class) @InstallIn(SingletonComponent::class)
internal class RepositoryModule { internal class RepositoryModule {
@Singleton @Singleton
@ -85,11 +85,15 @@ internal class RepositoryModule {
@Singleton @Singleton
@Provides @Provides
fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics fun provideGradePartialStatisticsDao(database: AppDatabase) = database.gradePartialStatisticsDao
@Singleton @Singleton
@Provides @Provides
fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatistics fun provideGradeSemesterStatisticsDao(database: AppDatabase) = database.gradeSemesterStatisticsDao
@Singleton
@Provides
fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatisticsDao
@Singleton @Singleton
@Provides @Provides
@ -154,4 +158,8 @@ internal class RepositoryModule {
@Singleton @Singleton
@Provides @Provides
fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao
@Singleton
@Provides
fun provideConferenceDao(database: AppDatabase) = database.conferenceDao
} }

View File

@ -10,10 +10,12 @@ import androidx.room.migration.Migration
import io.github.wulkanowy.data.db.dao.AttendanceDao import io.github.wulkanowy.data.db.dao.AttendanceDao
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
import io.github.wulkanowy.data.db.dao.ConferenceDao
import io.github.wulkanowy.data.db.dao.ExamDao import io.github.wulkanowy.data.db.dao.ExamDao
import io.github.wulkanowy.data.db.dao.GradeDao import io.github.wulkanowy.data.db.dao.GradeDao
import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeSummaryDao import io.github.wulkanowy.data.db.dao.GradeSummaryDao
import io.github.wulkanowy.data.db.dao.HomeworkDao import io.github.wulkanowy.data.db.dao.HomeworkDao
import io.github.wulkanowy.data.db.dao.LuckyNumberDao import io.github.wulkanowy.data.db.dao.LuckyNumberDao
@ -32,10 +34,12 @@ import io.github.wulkanowy.data.db.dao.TimetableDao
import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.data.db.entities.AttendanceSummary import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.db.entities.CompletedLesson import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Homework import io.github.wulkanowy.data.db.entities.Homework
import io.github.wulkanowy.data.db.entities.LuckyNumber import io.github.wulkanowy.data.db.entities.LuckyNumber
@ -70,6 +74,8 @@ import io.github.wulkanowy.data.db.migrations.Migration24
import io.github.wulkanowy.data.db.migrations.Migration25 import io.github.wulkanowy.data.db.migrations.Migration25
import io.github.wulkanowy.data.db.migrations.Migration26 import io.github.wulkanowy.data.db.migrations.Migration26
import io.github.wulkanowy.data.db.migrations.Migration27 import io.github.wulkanowy.data.db.migrations.Migration27
import io.github.wulkanowy.data.db.migrations.Migration28
import io.github.wulkanowy.data.db.migrations.Migration29
import io.github.wulkanowy.data.db.migrations.Migration3 import io.github.wulkanowy.data.db.migrations.Migration3
import io.github.wulkanowy.data.db.migrations.Migration4 import io.github.wulkanowy.data.db.migrations.Migration4
import io.github.wulkanowy.data.db.migrations.Migration5 import io.github.wulkanowy.data.db.migrations.Migration5
@ -90,8 +96,9 @@ import javax.inject.Singleton
AttendanceSummary::class, AttendanceSummary::class,
Grade::class, Grade::class,
GradeSummary::class, GradeSummary::class,
GradeStatistics::class, GradePartialStatistics::class,
GradePointsStatistics::class, GradePointsStatistics::class,
GradeSemesterStatistics::class,
Message::class, Message::class,
MessageAttachment::class, MessageAttachment::class,
Note::class, Note::class,
@ -103,7 +110,8 @@ import javax.inject.Singleton
Recipient::class, Recipient::class,
MobileDevice::class, MobileDevice::class,
Teacher::class, Teacher::class,
School::class School::class,
Conference::class,
], ],
version = AppDatabase.VERSION_SCHEMA, version = AppDatabase.VERSION_SCHEMA,
exportSchema = true exportSchema = true
@ -112,7 +120,7 @@ import javax.inject.Singleton
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
companion object { companion object {
const val VERSION_SCHEMA = 27 const val VERSION_SCHEMA = 29
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> { fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
return arrayOf( return arrayOf(
@ -142,6 +150,8 @@ abstract class AppDatabase : RoomDatabase() {
Migration25(), Migration25(),
Migration26(), Migration26(),
Migration27(), Migration27(),
Migration28(),
Migration29()
) )
} }
@ -171,9 +181,11 @@ abstract class AppDatabase : RoomDatabase() {
abstract val gradeSummaryDao: GradeSummaryDao abstract val gradeSummaryDao: GradeSummaryDao
abstract val gradeStatistics: GradeStatisticsDao abstract val gradePartialStatisticsDao: GradePartialStatisticsDao
abstract val gradePointsStatistics: GradePointsStatisticsDao abstract val gradePointsStatisticsDao: GradePointsStatisticsDao
abstract val gradeSemesterStatisticsDao: GradeSemesterStatisticsDao
abstract val messagesDao: MessagesDao abstract val messagesDao: MessagesDao
@ -198,4 +210,6 @@ abstract class AppDatabase : RoomDatabase() {
abstract val teacherDao: TeacherDao abstract val teacherDao: TeacherDao
abstract val schoolDao: SchoolDao abstract val schoolDao: SchoolDao
abstract val conferenceDao: ConferenceDao
} }

View File

@ -0,0 +1,15 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Conference
import kotlinx.coroutines.flow.Flow
import javax.inject.Singleton
@Dao
@Singleton
interface ConferenceDao : BaseDao<Conference> {
@Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId")
fun loadAll(diaryId: Int, studentId: Int): Flow<List<Conference>>
}

View File

@ -0,0 +1,13 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import kotlinx.coroutines.flow.Flow
@Dao
interface GradePartialStatisticsDao : BaseDao<GradePartialStatistics> {
@Query("SELECT * FROM GradePartialStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
fun loadAll(semesterId: Int, studentId: Int): Flow<List<GradePartialStatistics>>
}

View File

@ -0,0 +1,13 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import kotlinx.coroutines.flow.Flow
@Dao
interface GradeSemesterStatisticsDao : BaseDao<GradeSemesterStatistics> {
@Query("SELECT * FROM GradeSemesterStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
fun loadAll(semesterId: Int, studentId: Int): Flow<List<GradeSemesterStatistics>>
}

View File

@ -1,18 +0,0 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradeStatistics
import kotlinx.coroutines.flow.Flow
import javax.inject.Singleton
@Singleton
@Dao
interface GradeStatisticsDao : BaseDao<GradeStatistics> {
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester")
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Flow<List<GradeStatistics>>
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND is_semester = :isSemester")
fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): Flow<List<GradeStatistics>>
}

View File

@ -0,0 +1,35 @@
package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.io.Serializable
import java.time.LocalDateTime
@Entity(tableName = "Conferences")
data class Conference(
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "diary_id")
val diaryId: Int,
val title: String,
val subject: String,
val agenda: String,
@ColumnInfo(name = "present_on_conference")
val presentOnConference: String,
@ColumnInfo(name = "conference_id")
val conferenceId: Int,
val date: LocalDateTime
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -0,0 +1,33 @@
package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "GradePartialStatistics")
data class GradePartialStatistics(
@ColumnInfo(name = "student_id")
val studentId: Int,
@ColumnInfo(name = "semester_id")
val semesterId: Int,
val subject: String,
@ColumnInfo(name = "class_average")
val classAverage: String,
@ColumnInfo(name = "student_average")
val studentAverage: String,
@ColumnInfo(name = "class_amounts")
val classAmounts: List<Int>,
@ColumnInfo(name = "student_amounts")
val studentAmounts: List<Int>
) {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

View File

@ -4,8 +4,8 @@ import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
@Entity(tableName = "GradesStatistics") @Entity(tableName = "GradeSemesterStatistics")
data class GradeStatistics( data class GradeSemesterStatistics(
@ColumnInfo(name = "student_id") @ColumnInfo(name = "student_id")
val studentId: Int, val studentId: Int,
@ -15,13 +15,14 @@ data class GradeStatistics(
val subject: String, val subject: String,
val grade: Int, val amounts: List<Int>,
val amount: Int, @ColumnInfo(name = "student_grade")
val studentGrade: Int
@ColumnInfo(name = "is_semester")
val semester: Boolean
) { ) {
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
var id: Long = 0 var id: Long = 0
@Transient
var average: String = ""
} }

View File

@ -0,0 +1,23 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration28 : Migration(27, 28) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("""
CREATE TABLE IF NOT EXISTS Conferences (
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
)
""")
}
}

View File

@ -0,0 +1,33 @@
package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration29 : Migration(28, 29) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE IF EXISTS GradesStatistics")
database.execSQL("""
CREATE TABLE IF NOT EXISTS GradeSemesterStatistics (
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
)
""")
database.execSQL("""
CREATE TABLE IF NOT EXISTS GradePartialStatistics (
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
)
""")
}
}

View File

@ -1,14 +1,19 @@
package io.github.wulkanowy.data.pojos package io.github.wulkanowy.data.pojos
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import io.github.wulkanowy.ui.modules.grade.statistics.ViewType import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
data class GradeStatisticsItem( data class GradeStatisticsItem(
val type: ViewType, val type: ViewType,
val partial: List<GradeStatistics>, val average: String,
val partial: GradePartialStatistics?,
val semester: GradeSemesterStatistics?,
val points: GradePointsStatistics? val points: GradePointsStatistics?
) )

View File

@ -0,0 +1,25 @@
package io.github.wulkanowy.data.repositories.conference
import io.github.wulkanowy.data.db.dao.ConferenceDao
import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class ConferenceLocal @Inject constructor(private val conferenceDb: ConferenceDao) {
fun getConferences(student: Student, semester: Semester): Flow<List<Conference>> {
return conferenceDb.loadAll(semester.diaryId, student.studentId)
}
suspend fun saveConferences(items: List<Conference>) {
conferenceDb.insertAll(items)
}
suspend fun deleteConferences(items: List<Conference>) {
conferenceDb.deleteAll(items)
}
}

View File

@ -0,0 +1,31 @@
package io.github.wulkanowy.data.repositories.conference
import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.init
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class ConferenceRemote @Inject constructor(private val sdk: Sdk) {
suspend fun getConferences(student: Student, semester: Semester): List<Conference> {
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
.getConferences()
.map {
it.agenda
Conference(
studentId = student.studentId,
diaryId = semester.diaryId,
agenda = it.agenda,
conferenceId = it.id,
date = it.date,
presentOnConference = it.presentOnConference,
subject = it.subject,
title = it.title
)
}
}
}

View File

@ -0,0 +1,25 @@
package io.github.wulkanowy.data.repositories.conference
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.networkBoundResource
import io.github.wulkanowy.utils.uniqueSubtract
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class ConferenceRepository @Inject constructor(
private val local: ConferenceLocal,
private val remote: ConferenceRemote
) {
fun getConferences(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
shouldFetch = { it.isEmpty() || forceRefresh },
query = { local.getConferences(student, semester) },
fetch = { remote.getConferences(student, semester) },
saveFetchResult = { old, new ->
local.deleteConferences(old uniqueSubtract new)
local.saveConferences(new uniqueSubtract old)
}
)
}

View File

@ -1,9 +1,11 @@
package io.github.wulkanowy.data.repositories.gradestatistics package io.github.wulkanowy.data.repositories.gradestatistics
import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import javax.inject.Inject import javax.inject.Inject
@ -11,31 +13,47 @@ import javax.inject.Singleton
@Singleton @Singleton
class GradeStatisticsLocal @Inject constructor( class GradeStatisticsLocal @Inject constructor(
private val gradeStatisticsDb: GradeStatisticsDao, private val gradePartialStatisticsDb: GradePartialStatisticsDao,
private val gradePointsStatisticsDb: GradePointsStatisticsDao private val gradePointsStatisticsDb: GradePointsStatisticsDao,
private val gradeSemesterStatisticsDb: GradeSemesterStatisticsDao
) { ) {
fun getGradesStatistics(semester: Semester, isSemester: Boolean): Flow<List<GradeStatistics>> { // partial
return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester) fun getGradePartialStatistics(semester: Semester): Flow<List<GradePartialStatistics>> {
return gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId)
} }
fun getGradesPointsStatistics(semester: Semester): Flow<List<GradePointsStatistics>> { suspend fun saveGradePartialStatistics(items: List<GradePartialStatistics>) {
gradePartialStatisticsDb.insertAll(items)
}
suspend fun deleteGradePartialStatistics(items: List<GradePartialStatistics>) {
gradePartialStatisticsDb.deleteAll(items)
}
// points
fun getGradePointsStatistics(semester: Semester): Flow<List<GradePointsStatistics>> {
return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId)
} }
suspend fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) { suspend fun saveGradePointsStatistics(gradePointsStatistics: List<GradePointsStatistics>) {
gradeStatisticsDb.insertAll(gradesStatistics)
}
suspend fun saveGradesPointsStatistics(gradePointsStatistics: List<GradePointsStatistics>) {
gradePointsStatisticsDb.insertAll(gradePointsStatistics) gradePointsStatisticsDb.insertAll(gradePointsStatistics)
} }
suspend fun deleteGradesStatistics(gradesStatistics: List<GradeStatistics>) { suspend fun deleteGradePointsStatistics(gradesPointsStatistics: List<GradePointsStatistics>) {
gradeStatisticsDb.deleteAll(gradesStatistics)
}
suspend fun deleteGradesPointsStatistics(gradesPointsStatistics: List<GradePointsStatistics>) {
gradePointsStatisticsDb.deleteAll(gradesPointsStatistics) gradePointsStatisticsDb.deleteAll(gradesPointsStatistics)
} }
// semester
fun getGradeSemesterStatistics(semester: Semester): Flow<List<GradeSemesterStatistics>> {
return gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId)
}
suspend fun saveGradeSemesterStatistics(items: List<GradeSemesterStatistics>) {
gradeSemesterStatisticsDb.insertAll(items)
}
suspend fun deleteGradeSemesterStatistics(items: List<GradeSemesterStatistics>) {
gradeSemesterStatisticsDb.deleteAll(items)
}
} }

View File

@ -1,7 +1,8 @@
package io.github.wulkanowy.data.repositories.gradestatistics package io.github.wulkanowy.data.repositories.gradestatistics
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.Sdk
@ -12,20 +13,38 @@ import javax.inject.Singleton
@Singleton @Singleton
class GradeStatisticsRemote @Inject constructor(private val sdk: Sdk) { class GradeStatisticsRemote @Inject constructor(private val sdk: Sdk) {
suspend fun getGradeStatistics(student: Student, semester: Semester, isSemester: Boolean): List<GradeStatistics> { suspend fun getGradePartialStatistics(student: Student, semester: Semester): List<GradePartialStatistics> {
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).let { return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
if (isSemester) it.getGradesAnnualStatistics(semester.semesterId) .getGradesPartialStatistics(semester.semesterId)
else it.getGradesPartialStatistics(semester.semesterId) .map {
}.map { GradePartialStatistics(
GradeStatistics( semesterId = semester.semesterId,
semesterId = semester.semesterId, studentId = student.studentId,
studentId = semester.studentId, subject = it.subject,
subject = it.subject, classAverage = it.classAverage,
grade = it.gradeValue, studentAverage = it.studentAverage,
amount = it.amount, classAmounts = it.classItems
semester = isSemester .sortedBy { item -> item.grade }
) .map { item -> item.amount },
} studentAmounts = it.studentItems.map { item -> item.amount }
)
}
}
suspend fun getGradeSemesterStatistics(student: Student, semester: Semester): List<GradeSemesterStatistics> {
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
.getGradesSemesterStatistics(semester.semesterId)
.map {
GradeSemesterStatistics(
semesterId = semester.semesterId,
studentId = semester.studentId,
subject = it.subject,
amounts = it.items
.sortedBy { item -> item.grade }
.map { item -> item.amount },
studentGrade = it.items.singleOrNull { item -> item.isStudentHere }?.grade ?: 0
)
}
} }
suspend fun getGradePointsStatistics(student: Student, semester: Semester): List<GradePointsStatistics> { suspend fun getGradePointsStatistics(student: Student, semester: Semester): List<GradePointsStatistics> {

View File

@ -1,13 +1,15 @@
package io.github.wulkanowy.data.repositories.gradestatistics package io.github.wulkanowy.data.repositories.gradestatistics
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.pojos.GradeStatisticsItem import io.github.wulkanowy.data.pojos.GradeStatisticsItem
import io.github.wulkanowy.ui.modules.grade.statistics.ViewType import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.networkBoundResource
import io.github.wulkanowy.utils.uniqueSubtract import io.github.wulkanowy.utils.uniqueSubtract
import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -17,55 +19,125 @@ class GradeStatisticsRepository @Inject constructor(
private val remote: GradeStatisticsRemote private val remote: GradeStatisticsRemote
) { ) {
fun getGradesStatistics(student: Student, semester: Semester, subjectName: String, isSemester: Boolean, forceRefresh: Boolean) = networkBoundResource( fun getGradesPartialStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
shouldFetch = { it.isEmpty() || forceRefresh }, shouldFetch = { it.isEmpty() || forceRefresh },
query = { local.getGradesStatistics(semester, isSemester) }, query = { local.getGradePartialStatistics(semester) },
fetch = { remote.getGradeStatistics(student, semester, isSemester) }, fetch = { remote.getGradePartialStatistics(student, semester) },
saveFetchResult = { old, new -> saveFetchResult = { old, new ->
local.deleteGradesStatistics(old uniqueSubtract new) local.deleteGradePartialStatistics(old uniqueSubtract new)
local.saveGradesStatistics(new uniqueSubtract old) local.saveGradePartialStatistics(new uniqueSubtract old)
}, },
mapResult = { items -> mapResult = { items ->
when (subjectName) { when (subjectName) {
"Wszystkie" -> items.groupBy { it.grade }.map { "Wszystkie" -> {
GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key, val numerator = items.map {
it.value.fold(0) { acc, e -> acc + e.amount }, false) it.classAverage.replace(",", ".").toDoubleOrNull() ?: .0
} + items }.filterNot { it == .0 }
(items.reversed() + GradePartialStatistics(
studentId = semester.studentId,
semesterId = semester.semesterId,
subject = subjectName,
classAverage = if (numerator.isEmpty()) "" else numerator.average().let {
"%.2f".format(Locale.FRANCE, it)
},
studentAverage = "",
classAmounts = items.map { it.classAmounts }.sumGradeAmounts(),
studentAmounts = items.map { it.studentAmounts }.sumGradeAmounts()
)).reversed()
}
else -> items.filter { it.subject == subjectName } else -> items.filter { it.subject == subjectName }
}.mapToStatisticItems() }.mapPartialToStatisticItems()
}
)
fun getGradesSemesterStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
shouldFetch = { it.isEmpty() || forceRefresh },
query = { local.getGradeSemesterStatistics(semester) },
fetch = { remote.getGradeSemesterStatistics(student, semester) },
saveFetchResult = { old, new ->
local.deleteGradeSemesterStatistics(old uniqueSubtract new)
local.saveGradeSemesterStatistics(new uniqueSubtract old)
},
mapResult = { items ->
val itemsWithAverage = items.map { item ->
item.copy().apply {
val denominator = item.amounts.sum()
average = if (denominator == 0) "" else (item.amounts.mapIndexed { gradeValue, amount ->
(gradeValue + 1) * amount
}.sum().toDouble() / denominator).let {
"%.2f".format(Locale.FRANCE, it)
}
}
}
when (subjectName) {
"Wszystkie" -> (itemsWithAverage.reversed() + GradeSemesterStatistics(
studentId = semester.studentId,
semesterId = semester.semesterId,
subject = subjectName,
amounts = itemsWithAverage.map { it.amounts }.sumGradeAmounts(),
studentGrade = 0
).apply {
average = itemsWithAverage.mapNotNull { it.average.replace(",", ".").toDoubleOrNull() }.average().let {
"%.2f".format(Locale.FRANCE, it)
}
}).reversed()
else -> itemsWithAverage.filter { it.subject == subjectName }
}.mapSemesterToStatisticItems()
} }
) )
fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
shouldFetch = { it.isEmpty() || forceRefresh }, shouldFetch = { it.isEmpty() || forceRefresh },
query = { local.getGradesPointsStatistics(semester) }, query = { local.getGradePointsStatistics(semester) },
fetch = { remote.getGradePointsStatistics(student, semester) }, fetch = { remote.getGradePointsStatistics(student, semester) },
saveFetchResult = { old, new -> saveFetchResult = { old, new ->
local.deleteGradesPointsStatistics(old uniqueSubtract new) local.deleteGradePointsStatistics(old uniqueSubtract new)
local.saveGradesPointsStatistics(new uniqueSubtract old) local.saveGradePointsStatistics(new uniqueSubtract old)
}, },
mapResult = { items -> mapResult = { items ->
when (subjectName) { when (subjectName) {
"Wszystkie" -> items "Wszystkie" -> items
else -> items.filter { it.subject == subjectName } else -> items.filter { it.subject == subjectName }
}.mapToStatisticsItem() }.mapPointsToStatisticsItems()
} }
) )
private fun List<GradeStatistics>.mapToStatisticItems() = groupBy { it.subject }.map { private fun List<List<Int>>.sumGradeAmounts(): List<Int> {
val result = mutableListOf(0, 0, 0, 0, 0, 0)
forEach {
it.forEachIndexed { grade, amount ->
result[grade] += amount
}
}
return result
}
private fun List<GradePartialStatistics>.mapPartialToStatisticItems() = filterNot { it.classAmounts.isEmpty() }.map {
GradeStatisticsItem( GradeStatisticsItem(
type = ViewType.PARTIAL, type = ViewType.PARTIAL,
partial = it.value average = it.classAverage,
.sortedByDescending { item -> item.grade } partial = it,
.filter { item -> item.amount != 0 }, points = null,
points = null semester = null
) )
} }
private fun List<GradePointsStatistics>.mapToStatisticsItem() = map { private fun List<GradeSemesterStatistics>.mapSemesterToStatisticItems() = filterNot { it.amounts.isEmpty() }.map {
GradeStatisticsItem(
type = ViewType.SEMESTER,
partial = null,
points = null,
average = "",
semester = it
)
}
private fun List<GradePointsStatistics>.mapPointsToStatisticsItems() = map {
GradeStatisticsItem( GradeStatisticsItem(
type = ViewType.POINTS, type = ViewType.POINTS,
partial = emptyList(), partial = null,
semester = null,
average = "",
points = it points = it
) )
} }

View File

@ -14,7 +14,7 @@ class TimetableRemote @Inject constructor(private val sdk: Sdk) {
suspend fun getTimetable(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List<Timetable> { suspend fun getTimetable(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List<Timetable> {
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
.getTimetable(startDate, endDate) .getTimetable(startDate, endDate).first
.map { .map {
Timetable( Timetable(
studentId = semester.studentId, studentId = semester.studentId,

View File

@ -6,13 +6,13 @@ import com.yariksoffice.lingver.Lingver
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import io.github.wulkanowy.utils.DispatchersProvider import io.github.wulkanowy.utils.DispatchersProvider
import javax.inject.Singleton import javax.inject.Singleton
@Module @Module
@InstallIn(ApplicationComponent::class) @InstallIn(SingletonComponent::class)
internal class AppModule { internal class AppModule {
@Singleton @Singleton

View File

@ -9,8 +9,8 @@ import dagger.Binds
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.IntoSet import dagger.multibindings.IntoSet
import io.github.wulkanowy.services.sync.channels.Channel import io.github.wulkanowy.services.sync.channels.Channel
import io.github.wulkanowy.services.sync.channels.DebugChannel import io.github.wulkanowy.services.sync.channels.DebugChannel
@ -38,7 +38,7 @@ import javax.inject.Singleton
@Suppress("unused") @Suppress("unused")
@Module @Module
@InstallIn(ApplicationComponent::class) @InstallIn(SingletonComponent::class)
abstract class ServicesModule { abstract class ServicesModule {
companion object { companion object {

View File

@ -12,8 +12,8 @@ class GradeStatisticsWork @Inject constructor(
override suspend fun doWork(student: Student, semester: Semester) { override suspend fun doWork(student: Student, semester: Semester) {
with(gradeStatisticsRepository) { with(gradeStatisticsRepository) {
getGradesStatistics(student, semester, "Wszystkie", isSemester = true, forceRefresh = true).waitForResult() getGradesPartialStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
getGradesStatistics(student, semester, "Wszystkie", isSemester = false, forceRefresh = true).waitForResult() getGradesSemesterStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
getGradesPointsStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult() getGradesPointsStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
} }
} }

View File

@ -3,10 +3,15 @@ package io.github.wulkanowy.ui.base
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.lifecycleAwareVariable import io.github.wulkanowy.utils.lifecycleAwareVariable
import javax.inject.Inject
abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment(), BaseView { abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment(), BaseView {
@Inject
lateinit var analyticsHelper: AnalyticsHelper
protected var binding: VB by lifecycleAwareVariable() protected var binding: VB by lifecycleAwareVariable()
override fun showError(text: String, error: Throwable) { override fun showError(text: String, error: Throwable) {
@ -28,4 +33,14 @@ abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment(), BaseView
override fun showErrorDetailsDialog(error: Throwable) { override fun showErrorDetailsDialog(error: Throwable) {
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
} }
override fun onResume() {
super.onResume()
analyticsHelper.setCurrentScreen(requireActivity(), this::class.simpleName)
}
override fun onPause() {
super.onPause()
analyticsHelper.popCurrentScreen(this::class.simpleName)
}
} }

View File

@ -58,6 +58,11 @@ class AboutFragment : BaseFragment<FragmentAboutBinding>(R.layout.fragment_about
Triple(getString(R.string.about_discord), getString(R.string.about_discord_summary), getCompatDrawable(R.drawable.ic_about_discord)) Triple(getString(R.string.about_discord), getString(R.string.about_discord_summary), getCompatDrawable(R.drawable.ic_about_discord))
} }
override val facebookRes: Triple<String, String, Drawable?>?
get() = context?.run {
Triple(getString(R.string.about_facebook), getString(R.string.about_facebook_summary), getCompatDrawable(R.drawable.ic_about_facebook))
}
override val homepageRes: Triple<String, String, Drawable?>? override val homepageRes: Triple<String, String, Drawable?>?
get() = context?.run { get() = context?.run {
Triple(getString(R.string.about_homepage), getString(R.string.about_homepage_summary), getCompatDrawable(R.drawable.ic_about_homepage)) Triple(getString(R.string.about_homepage), getString(R.string.about_homepage_summary), getCompatDrawable(R.drawable.ic_about_homepage))
@ -113,6 +118,10 @@ class AboutFragment : BaseFragment<FragmentAboutBinding>(R.layout.fragment_about
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
} }
override fun openFacebookPage() {
context?.openInternetBrowser("https://www.facebook.com/wulkanowy", ::showMessage)
}
override fun openHomepage() { override fun openHomepage() {
context?.openInternetBrowser("https://wulkanowy.github.io/", ::showMessage) context?.openInternetBrowser("https://wulkanowy.github.io/", ::showMessage)
} }

View File

@ -3,8 +3,8 @@ package io.github.wulkanowy.ui.modules.about
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -12,7 +12,7 @@ class AboutPresenter @Inject constructor(
errorHandler: ErrorHandler, errorHandler: ErrorHandler,
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val appInfo: AppInfo, private val appInfo: AppInfo,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<AboutView>(errorHandler, studentRepository) { ) : BasePresenter<AboutView>(errorHandler, studentRepository) {
override fun onAttachView(view: AboutView) { override fun onAttachView(view: AboutView) {
@ -46,6 +46,11 @@ class AboutPresenter @Inject constructor(
openDiscordInvite() openDiscordInvite()
analytics.logEvent("about_open", "name" to "discord") analytics.logEvent("about_open", "name" to "discord")
} }
facebookRes?.first -> {
Timber.i("Opening facebook")
openFacebookPage()
analytics.logEvent("about_open", "name" to "facebook")
}
homepageRes?.first -> { homepageRes?.first -> {
Timber.i("Opening homepage") Timber.i("Opening homepage")
openHomepage() openHomepage()
@ -78,6 +83,7 @@ class AboutPresenter @Inject constructor(
feedbackRes, feedbackRes,
faqRes, faqRes,
discordRes, discordRes,
facebookRes,
homepageRes, homepageRes,
licensesRes, licensesRes,
privacyRes privacyRes

View File

@ -15,6 +15,8 @@ interface AboutView : BaseView {
val discordRes: Triple<String, String, Drawable?>? val discordRes: Triple<String, String, Drawable?>?
val facebookRes: Triple<String, String, Drawable?>?
val homepageRes: Triple<String, String, Drawable?>? val homepageRes: Triple<String, String, Drawable?>?
val licensesRes: Triple<String, String, Drawable?>? val licensesRes: Triple<String, String, Drawable?>?
@ -31,6 +33,8 @@ interface AboutView : BaseView {
fun openDiscordInvite() fun openDiscordInvite()
fun openFacebookPage()
fun openEmailClient() fun openEmailClient()
fun openFaqPage() fun openFaqPage()

View File

@ -9,7 +9,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
@ -34,7 +34,7 @@ class AttendancePresenter @Inject constructor(
private val attendanceRepository: AttendanceRepository, private val attendanceRepository: AttendanceRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val prefRepository: PreferencesRepository, private val prefRepository: PreferencesRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<AttendanceView>(errorHandler, studentRepository) { ) : BasePresenter<AttendanceView>(errorHandler, studentRepository) {
private var baseDate: LocalDate = now().previousOrSameSchoolDay private var baseDate: LocalDate = now().previousOrSameSchoolDay

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.data.repositories.subject.SubjectRepository import io.github.wulkanowy.data.repositories.subject.SubjectRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -22,7 +22,7 @@ class AttendanceSummaryPresenter @Inject constructor(
private val attendanceSummaryRepository: AttendanceSummaryRepository, private val attendanceSummaryRepository: AttendanceSummaryRepository,
private val subjectRepository: SubjectRepository, private val subjectRepository: SubjectRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<AttendanceSummaryView>(errorHandler, studentRepository) { ) : BasePresenter<AttendanceSummaryView>(errorHandler, studentRepository) {
private var subjects = emptyList<Subject>() private var subjects = emptyList<Subject>()

View File

@ -0,0 +1,36 @@
package io.github.wulkanowy.ui.modules.conference
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.databinding.ItemConferenceBinding
import io.github.wulkanowy.utils.toFormattedString
import javax.inject.Inject
class ConferenceAdapter @Inject constructor() :
RecyclerView.Adapter<ConferenceAdapter.ItemViewHolder>() {
var items = emptyList<Conference>()
override fun getItemCount() = items.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
ItemConferenceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = items[position]
with(holder.binding) {
conferenceItemDate.text = item.date.toFormattedString("dd.MM.yyyy HH:mm")
conferenceItemName.text = item.presentOnConference
conferenceItemTitle.text = item.title
conferenceItemSubject.text = item.subject
conferenceItemContent.text = item.agenda
conferenceItemContent.visibility = if (item.agenda.isBlank()) View.GONE else View.VISIBLE
}
}
class ItemViewHolder(val binding: ItemConferenceBinding) : RecyclerView.ViewHolder(binding.root)
}

View File

@ -0,0 +1,102 @@
package io.github.wulkanowy.ui.modules.conference
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.databinding.FragmentConferenceBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.widgets.DividerItemDecoration
import javax.inject.Inject
@AndroidEntryPoint
class ConferenceFragment : BaseFragment<FragmentConferenceBinding>(R.layout.fragment_conference),
ConferenceView, MainView.TitledView {
@Inject
lateinit var presenter: ConferencePresenter
@Inject
lateinit var conferencesAdapter: ConferenceAdapter
companion object {
fun newInstance() = ConferenceFragment()
}
override val isViewEmpty: Boolean
get() = conferencesAdapter.items.isEmpty()
override val titleStringId: Int
get() = R.string.conferences_title
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentConferenceBinding.bind(view)
messageContainer = binding.conferenceRecycler
presenter.onAttachView(this)
}
override fun initView() {
with(binding.conferenceRecycler) {
layoutManager = LinearLayoutManager(context)
adapter = conferencesAdapter
addItemDecoration(DividerItemDecoration(context))
}
with(binding) {
conferenceSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
conferenceErrorRetry.setOnClickListener { presenter.onRetry() }
conferenceErrorDetails.setOnClickListener { presenter.onDetailsClick() }
}
}
override fun updateData(data: List<Conference>) {
with(conferencesAdapter) {
items = data
notifyDataSetChanged()
}
}
override fun clearData() {
with(conferencesAdapter) {
items = emptyList()
notifyDataSetChanged()
}
}
override fun hideRefresh() {
binding.conferenceSwipe.isRefreshing = false
}
override fun showProgress(show: Boolean) {
binding.conferenceProgress.visibility = if (show) View.VISIBLE else View.GONE
}
override fun showEmpty(show: Boolean) {
binding.conferenceEmpty.visibility = if (show) View.VISIBLE else View.GONE
}
override fun showErrorView(show: Boolean) {
binding.conferenceError.visibility = if (show) View.VISIBLE else View.GONE
}
override fun setErrorDetails(message: String) {
binding.conferenceErrorMessage.text = message
}
override fun enableSwipe(enable: Boolean) {
binding.conferenceSwipe.isEnabled = enable
}
override fun showContent(show: Boolean) {
binding.conferenceRecycler.visibility = if (show) View.VISIBLE else View.GONE
}
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
}
}

View File

@ -0,0 +1,96 @@
package io.github.wulkanowy.ui.modules.conference
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.repositories.conference.ConferenceRepository
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.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.flowWithResourceIn
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import javax.inject.Inject
class ConferencePresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository,
private val conferenceRepository: ConferenceRepository,
private val analytics: AnalyticsHelper
) : BasePresenter<ConferenceView>(errorHandler, studentRepository) {
private lateinit var lastError: Throwable
override fun onAttachView(view: ConferenceView) {
super.onAttachView(view)
view.initView()
Timber.i("Conferences view was initialized")
errorHandler.showErrorMessage = ::showErrorViewOnError
loadData()
}
fun onSwipeRefresh() {
loadData(true)
}
fun onRetry() {
view?.run {
showErrorView(false)
showProgress(true)
}
loadData(true)
}
fun onDetailsClick() {
view?.showErrorDetailsDialog(lastError)
}
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 loadData(forceRefresh: Boolean = false) {
flowWithResourceIn {
val student = studentRepository.getCurrentStudent()
val semester = semesterRepository.getCurrentSemester(student)
conferenceRepository.getConferences(student, semester, forceRefresh)
}.onEach {
when (it.status) {
Status.LOADING -> Timber.i("Loading conference data started")
Status.SUCCESS -> {
Timber.i("Loading conference result: Success")
view?.run {
updateData(it.data!!.sortedByDescending { conference -> conference.date })
showContent(it.data.isNotEmpty())
showEmpty(it.data.isEmpty())
showErrorView(false)
}
analytics.logEvent(
"load_data",
"type" to "conferences",
"items" to it.data!!.size
)
}
Status.ERROR -> {
Timber.i("Loading conference result: An exception occurred")
errorHandler.dispatch(it.error!!)
}
}
}.afterLoading {
view?.run {
hideRefresh()
showProgress(false)
enableSwipe(true)
}
}.launch()
}
}

View File

@ -0,0 +1,29 @@
package io.github.wulkanowy.ui.modules.conference
import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.ui.base.BaseView
interface ConferenceView : BaseView {
val isViewEmpty: Boolean
fun initView()
fun updateData(data: List<Conference>)
fun clearData()
fun hideRefresh()
fun showEmpty(show: Boolean)
fun showErrorView(show: Boolean)
fun setErrorDetails(message: String)
fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean)
fun showContent(show: Boolean)
}

View File

@ -7,7 +7,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
@ -30,7 +30,7 @@ class ExamPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val examRepository: ExamRepository, private val examRepository: ExamRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<ExamView>(errorHandler, studentRepository) { ) : BasePresenter<ExamView>(errorHandler, studentRepository) {
private var baseDate: LocalDate = now().nextOrSameSchoolDay private var baseDate: LocalDate = now().nextOrSameSchoolDay

View File

@ -6,7 +6,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.getCurrentOrLast import io.github.wulkanowy.utils.getCurrentOrLast
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -18,7 +18,7 @@ class GradePresenter @Inject constructor(
errorHandler: ErrorHandler, errorHandler: ErrorHandler,
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<GradeView>(errorHandler, studentRepository) { ) : BasePresenter<GradeView>(errorHandler, studentRepository) {
var selectedIndex = 0 var selectedIndex = 0

View File

@ -40,10 +40,6 @@ class GradeDetailsAdapter @Inject constructor() : BaseExpandableAdapter<Recycler
} }
fun updateDetailsItem(position: Int, grade: Grade) { fun updateDetailsItem(position: Int, grade: Grade) {
if (items.getOrNull(position)?.viewType != ViewType.ITEM) {
Timber.e("Trying to update item $position on list ${items.size} size, expanded position: $expandedPosition")
return
}
items[position] = GradeDetailsItem(grade, ViewType.ITEM) items[position] = GradeDetailsItem(grade, ViewType.ITEM)
notifyItemChanged(position) notifyItemChanged(position)
} }
@ -62,10 +58,6 @@ class GradeDetailsAdapter @Inject constructor() : BaseExpandableAdapter<Recycler
val headerPosition = headers.indexOf(item) val headerPosition = headers.indexOf(item)
val itemPosition = items.indexOf(item) val itemPosition = items.indexOf(item)
if (headerPosition == NO_POSITION || itemPosition == NO_POSITION) {
Timber.e("Invalid update header positions! Header: $headerPosition, item: $itemPosition")
}
headers[headerPosition] = item headers[headerPosition] = item
items[itemPosition] = item items[itemPosition] = item
notifyItemChanged(itemPosition) notifyItemChanged(itemPosition)

View File

@ -14,6 +14,7 @@ data class GradeDetailsHeader(
val subject: String, val subject: String,
val average: Double?, val average: Double?,
val pointsSum: String?, val pointsSum: String?,
var newGrades: Int,
val grades: List<GradeDetailsItem> val grades: List<GradeDetailsItem>
) ) {
var newGrades = 0
}

View File

@ -13,7 +13,7 @@ import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider
import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage
import io.github.wulkanowy.ui.modules.grade.GradeSortingMode.ALPHABETIC import io.github.wulkanowy.ui.modules.grade.GradeSortingMode.ALPHABETIC
import io.github.wulkanowy.ui.modules.grade.GradeSortingMode.DATE import io.github.wulkanowy.ui.modules.grade.GradeSortingMode.DATE
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
@ -29,7 +29,7 @@ class GradeDetailsPresenter @Inject constructor(
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val preferencesRepository: PreferencesRepository, private val preferencesRepository: PreferencesRepository,
private val averageProvider: GradeAverageProvider, private val averageProvider: GradeAverageProvider,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<GradeDetailsView>(errorHandler, studentRepository) { ) : BasePresenter<GradeDetailsView>(errorHandler, studentRepository) {
private var newGradesAmount: Int = 0 private var newGradesAmount: Int = 0
@ -213,9 +213,10 @@ class GradeDetailsPresenter @Inject constructor(
subject = subject, subject = subject,
average = average, average = average,
pointsSum = points, pointsSum = points,
newGrades = grades.filter { grade -> !grade.isRead }.size,
grades = subItems grades = subItems
), ViewType.HEADER)) + if (preferencesRepository.isGradeExpandable) emptyList() else subItems ).apply {
newGrades = grades.filter { grade -> !grade.isRead }.size
}, ViewType.HEADER)) + if (preferencesRepository.isGradeExpandable) emptyList() else subItems
}.flatten() }.flatten()
} }

View File

@ -17,8 +17,9 @@ import com.github.mikephil.charting.data.PieDataSet
import com.github.mikephil.charting.data.PieEntry import com.github.mikephil.charting.data.PieEntry
import com.github.mikephil.charting.formatter.ValueFormatter import com.github.mikephil.charting.formatter.ValueFormatter
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import io.github.wulkanowy.data.pojos.GradeStatisticsItem import io.github.wulkanowy.data.pojos.GradeStatisticsItem
import io.github.wulkanowy.databinding.ItemGradeStatisticsBarBinding import io.github.wulkanowy.databinding.ItemGradeStatisticsBarBinding
import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding
@ -68,22 +69,32 @@ class GradeStatisticsAdapter @Inject constructor() :
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context) val inflater = LayoutInflater.from(parent.context)
return when (viewType) { return when (viewType) {
ViewType.PARTIAL.id, ViewType.SEMESTER.id -> PieViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false)) ViewType.PARTIAL.id -> PartialViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false))
ViewType.POINTS.id -> BarViewHolder(ItemGradeStatisticsBarBinding.inflate(inflater, parent, false)) ViewType.SEMESTER.id -> SemesterViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false))
ViewType.POINTS.id -> PointsViewHolder(ItemGradeStatisticsBarBinding.inflate(inflater, parent, false))
else -> throw IllegalStateException() else -> throw IllegalStateException()
} }
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) { when (holder) {
is PieViewHolder -> bindPieChart(holder, items[position].partial) is PartialViewHolder -> bindPartialChart(holder, items[position].partial!!)
is BarViewHolder -> bindBarChart(holder, items[position].points!!) is SemesterViewHolder -> bindSemesterChart(holder, items[position].semester!!)
is PointsViewHolder -> bindBarChart(holder, items[position].points!!)
} }
} }
private fun bindPieChart(holder: PieViewHolder, partials: List<GradeStatistics>) { private fun bindPartialChart(holder: PartialViewHolder, partials: GradePartialStatistics) {
with(holder.binding.gradeStatisticsPieTitle) { bindPieChart(holder.binding, partials.subject, partials.classAverage, partials.classAmounts)
text = partials.firstOrNull()?.subject }
private fun bindSemesterChart(holder: SemesterViewHolder, semester: GradeSemesterStatistics) {
bindPieChart(holder.binding, semester.subject, semester.average, semester.amounts)
}
private fun bindPieChart(binding: ItemGradeStatisticsPieBinding, subject: String, average: String, amounts: List<Int>) {
with(binding.gradeStatisticsPieTitle) {
text = subject
visibility = if (items.size == 1 || !showAllSubjectsOnList) GONE else VISIBLE visibility = if (items.size == 1 || !showAllSubjectsOnList) GONE else VISIBLE
} }
@ -92,22 +103,23 @@ class GradeStatisticsAdapter @Inject constructor() :
else -> materialGradeColors else -> materialGradeColors
} }
val dataset = PieDataSet(partials.map { val dataset = PieDataSet(amounts.mapIndexed { grade, amount ->
PieEntry(it.amount.toFloat(), it.grade.toString()) PieEntry(amount.toFloat(), (grade + 1).toString())
}, "Legenda") }.reversed().filterNot { it.value == 0f }, "Legenda")
with(dataset) { with(dataset) {
valueTextSize = 12f valueTextSize = 12f
sliceSpace = 1f sliceSpace = 1f
valueTextColor = Color.WHITE valueTextColor = Color.WHITE
setColors(partials.map { val grades = amounts.mapIndexed { grade, amount -> (grade + 1) to amount }.filterNot { it.second == 0 }
gradeColors.single { color -> color.first == it.grade }.second setColors(grades.reversed().map { (grade, _) ->
}.toIntArray(), holder.binding.root.context) gradeColors.single { color -> color.first == grade }.second
}.toIntArray(), binding.root.context)
} }
with(holder.binding.gradeStatisticsPie) { with(binding.gradeStatisticsPie) {
setTouchEnabled(false) setTouchEnabled(false)
if (partials.size == 1) animateXY(1000, 1000) if (amounts.size == 1) animateXY(1000, 1000)
data = PieData(dataset).apply { data = PieData(dataset).apply {
setValueFormatter(object : ValueFormatter() { setValueFormatter(object : ValueFormatter() {
override fun getPieLabel(value: Float, pieEntry: PieEntry): String { override fun getPieLabel(value: Float, pieEntry: PieEntry): String {
@ -128,8 +140,9 @@ class GradeStatisticsAdapter @Inject constructor() :
minAngleForSlices = 25f minAngleForSlices = 25f
description.isEnabled = false description.isEnabled = false
centerText = partials.fold(0) { acc, it -> acc + it.amount } centerText = amounts.fold(0) { acc, it -> acc + it }
.let { resources.getQuantityString(R.plurals.grade_number_item, it, it) } .let { resources.getQuantityString(R.plurals.grade_number_item, it, it) } +
("\n\nŚrednia: $average").takeIf { average.isNotBlank() }.orEmpty()
setHoleColor(context.getThemeAttrColor(android.R.attr.windowBackground)) setHoleColor(context.getThemeAttrColor(android.R.attr.windowBackground))
setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary)) setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary))
@ -137,7 +150,7 @@ class GradeStatisticsAdapter @Inject constructor() :
} }
} }
private fun bindBarChart(holder: BarViewHolder, points: GradePointsStatistics) { private fun bindBarChart(holder: PointsViewHolder, points: GradePointsStatistics) {
with(holder.binding.gradeStatisticsBarTitle) { with(holder.binding.gradeStatisticsBarTitle) {
text = points.subject text = points.subject
visibility = if (items.size == 1) GONE else VISIBLE visibility = if (items.size == 1) GONE else VISIBLE
@ -200,9 +213,12 @@ class GradeStatisticsAdapter @Inject constructor() :
} }
} }
private class PieViewHolder(val binding: ItemGradeStatisticsPieBinding) : private class PartialViewHolder(val binding: ItemGradeStatisticsPieBinding) :
RecyclerView.ViewHolder(binding.root) RecyclerView.ViewHolder(binding.root)
private class BarViewHolder(val binding: ItemGradeStatisticsBarBinding) : private class SemesterViewHolder(val binding: ItemGradeStatisticsPieBinding) :
RecyclerView.ViewHolder(binding.root)
private class PointsViewHolder(val binding: ItemGradeStatisticsBarBinding) :
RecyclerView.ViewHolder(binding.root) RecyclerView.ViewHolder(binding.root)
} }

View File

@ -9,7 +9,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.data.repositories.subject.SubjectRepository import io.github.wulkanowy.data.repositories.subject.SubjectRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -23,7 +23,7 @@ class GradeStatisticsPresenter @Inject constructor(
private val subjectRepository: SubjectRepository, private val subjectRepository: SubjectRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val preferencesRepository: PreferencesRepository, private val preferencesRepository: PreferencesRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<GradeStatisticsView>(errorHandler, studentRepository) { ) : BasePresenter<GradeStatisticsView>(errorHandler, studentRepository) {
private var subjects = emptyList<Subject>() private var subjects = emptyList<Subject>()
@ -153,8 +153,8 @@ class GradeStatisticsPresenter @Inject constructor(
with(gradeStatisticsRepository) { with(gradeStatisticsRepository) {
when (type) { when (type) {
ViewType.SEMESTER -> getGradesStatistics(student, semester, currentSubjectName, true, forceRefresh) ViewType.PARTIAL -> getGradesPartialStatistics(student, semester, currentSubjectName, forceRefresh)
ViewType.PARTIAL -> getGradesStatistics(student, semester, currentSubjectName, false, forceRefresh) ViewType.SEMESTER -> getGradesSemesterStatistics(student, semester, currentSubjectName, forceRefresh)
ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh) ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh)
} }
} }
@ -164,8 +164,15 @@ class GradeStatisticsPresenter @Inject constructor(
Status.SUCCESS -> { Status.SUCCESS -> {
Timber.i("Loading grade stats result: Success") Timber.i("Loading grade stats result: Success")
view?.run { view?.run {
showEmpty(it.data!!.isEmpty() || it.data.first().partial.isEmpty()) val isNoContent = it.data!!.isEmpty() || when (type) {
showContent(it.data.isNotEmpty() && it.data.first().partial.isNotEmpty()) ViewType.SEMESTER -> it.data.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0
ViewType.PARTIAL -> it.data.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0
ViewType.POINTS -> it.data.firstOrNull()?.points?.let { points ->
points.student == .0 && points.others == .0
} ?: false
}
showEmpty(isNoContent)
showContent(!isNoContent)
showErrorView(false) showErrorView(false)
updateData(it.data, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList) updateData(it.data, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList)
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList) showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)

View File

@ -7,7 +7,7 @@ import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider
import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -18,7 +18,7 @@ class GradeSummaryPresenter @Inject constructor(
errorHandler: ErrorHandler, errorHandler: ErrorHandler,
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val averageProvider: GradeAverageProvider, private val averageProvider: GradeAverageProvider,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<GradeSummaryView>(errorHandler, studentRepository) { ) : BasePresenter<GradeSummaryView>(errorHandler, studentRepository) {
private lateinit var lastError: Throwable private lateinit var lastError: Throwable

View File

@ -7,7 +7,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
@ -29,7 +29,7 @@ class HomeworkPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val homeworkRepository: HomeworkRepository, private val homeworkRepository: HomeworkRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<HomeworkView>(errorHandler, studentRepository) { ) : BasePresenter<HomeworkView>(errorHandler, studentRepository) {
private var baseDate: LocalDate = LocalDate.now().nextOrSameSchoolDay private var baseDate: LocalDate = LocalDate.now().nextOrSameSchoolDay

View File

@ -7,7 +7,7 @@ import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import timber.log.Timber import timber.log.Timber
@ -17,7 +17,7 @@ class HomeworkDetailsPresenter @Inject constructor(
errorHandler: ErrorHandler, errorHandler: ErrorHandler,
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val homeworkRepository: HomeworkRepository, private val homeworkRepository: HomeworkRepository,
private val analytics: FirebaseAnalyticsHelper, private val analytics: AnalyticsHelper,
private val preferencesRepository: PreferencesRepository private val preferencesRepository: PreferencesRepository
) : BasePresenter<HomeworkDetailsView>(errorHandler, studentRepository) { ) : BasePresenter<HomeworkDetailsView>(errorHandler, studentRepository) {

View File

@ -6,7 +6,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank import io.github.wulkanowy.utils.ifNullOrBlank
@ -17,7 +17,7 @@ import javax.inject.Inject
class LoginAdvancedPresenter @Inject constructor( class LoginAdvancedPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler, private val loginErrorHandler: LoginErrorHandler,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<LoginAdvancedView>(loginErrorHandler, studentRepository) { ) : BasePresenter<LoginAdvancedView>(loginErrorHandler, studentRepository) {
override fun onAttachView(view: LoginAdvancedView) { override fun onAttachView(view: LoginAdvancedView) {

View File

@ -89,6 +89,8 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
} }
} }
override fun getHostsValues(): List<String> = hostValues.toList()
override fun setCredentials(username: String, pass: String) { override fun setCredentials(username: String, pass: String) {
with(binding) { with(binding) {
loginFormUsername.setText(username) loginFormUsername.setText(username)
@ -96,6 +98,12 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
} }
} }
override fun setHost(host: String) {
binding.loginFormHost.setText(
hostKeys.getOrNull(hostValues.indexOf(host)).orEmpty()
)
}
override fun setUsernameLabel(label: String) { override fun setUsernameLabel(label: String) {
binding.loginFormUsernameLayout.hint = label binding.loginFormUsernameLayout.hint = label
} }

View File

@ -1,10 +1,11 @@
package io.github.wulkanowy.ui.modules.login.form package io.github.wulkanowy.ui.modules.login.form
import androidx.core.net.toUri
import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank import io.github.wulkanowy.utils.ifNullOrBlank
@ -15,7 +16,7 @@ import javax.inject.Inject
class LoginFormPresenter @Inject constructor( class LoginFormPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler, private val loginErrorHandler: LoginErrorHandler,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<LoginFormView>(loginErrorHandler, studentRepository) { ) : BasePresenter<LoginFormView>(loginErrorHandler, studentRepository) {
private var lastError: Throwable? = null private var lastError: Throwable? = null
@ -56,7 +57,7 @@ class LoginFormPresenter @Inject constructor(
fun updateUsernameLabel() { fun updateUsernameLabel() {
view?.run { view?.run {
setUsernameLabel(if ("standard" in formHostValue) emailLabel else nicknameLabel) setUsernameLabel(if ("login" in formHostValue) nicknameLabel else emailLabel)
} }
} }
@ -66,6 +67,16 @@ class LoginFormPresenter @Inject constructor(
fun onUsernameTextChanged() { fun onUsernameTextChanged() {
view?.clearUsernameError() view?.clearUsernameError()
val username = view?.formUsernameValue.orEmpty().trim()
if ("@" in username && "@vulcan" !in username) {
val hosts = view?.getHostsValues().orEmpty().map { it.toUri().host to it }.toMap()
val usernameHost = username.substringAfter("@")
hosts[usernameHost]?.let {
view?.setHost(it)
}
}
} }
fun onSignInClick() { fun onSignInClick() {
@ -135,12 +146,12 @@ class LoginFormPresenter @Inject constructor(
view?.setErrorUsernameRequired() view?.setErrorUsernameRequired()
isCorrect = false isCorrect = false
} else { } else {
if ("@" in login && "standard" !in host) { if ("@" in login && "login" in host) {
view?.setErrorLoginRequired() view?.setErrorLoginRequired()
isCorrect = false isCorrect = false
} }
if ("@" !in login && "standard" in host) { if ("@" !in login && "email" in host) {
view?.setErrorEmailRequired() view?.setErrorEmailRequired()
isCorrect = false isCorrect = false
} }

View File

@ -19,8 +19,12 @@ interface LoginFormView : BaseView {
val emailLabel: String val emailLabel: String
fun getHostsValues(): List<String>
fun setCredentials(username: String, pass: String) fun setCredentials(username: String, pass: String)
fun setHost(host: String)
fun setUsernameLabel(label: String) fun setUsernameLabel(label: String)
fun setErrorUsernameRequired() fun setErrorUsernameRequired()

View File

@ -4,7 +4,7 @@ import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.repositories.recover.RecoverRepository import io.github.wulkanowy.data.repositories.recover.RecoverRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank import io.github.wulkanowy.utils.ifNullOrBlank
@ -15,7 +15,7 @@ import javax.inject.Inject
class LoginRecoverPresenter @Inject constructor( class LoginRecoverPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val loginErrorHandler: RecoverErrorHandler, private val loginErrorHandler: RecoverErrorHandler,
private val analytics: FirebaseAnalyticsHelper, private val analytics: AnalyticsHelper,
private val recoverRepository: RecoverRepository private val recoverRepository: RecoverRepository
) : BasePresenter<LoginRecoverView>(loginErrorHandler, studentRepository) { ) : BasePresenter<LoginRecoverView>(loginErrorHandler, studentRepository) {

View File

@ -6,7 +6,7 @@ import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank import io.github.wulkanowy.utils.ifNullOrBlank
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -17,7 +17,7 @@ import javax.inject.Inject
class LoginStudentSelectPresenter @Inject constructor( class LoginStudentSelectPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler, private val loginErrorHandler: LoginErrorHandler,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<LoginStudentSelectView>(loginErrorHandler, studentRepository) { ) : BasePresenter<LoginStudentSelectView>(loginErrorHandler, studentRepository) {
private var lastError: Throwable? = null private var lastError: Throwable? = null

View File

@ -4,7 +4,7 @@ import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank import io.github.wulkanowy.utils.ifNullOrBlank
@ -16,7 +16,7 @@ import javax.inject.Inject
class LoginSymbolPresenter @Inject constructor( class LoginSymbolPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler, private val loginErrorHandler: LoginErrorHandler,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<LoginSymbolView>(loginErrorHandler, studentRepository) { ) : BasePresenter<LoginSymbolView>(loginErrorHandler, studentRepository) {
private var lastError: Throwable? = null private var lastError: Throwable? = null

View File

@ -5,7 +5,7 @@ import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -16,7 +16,7 @@ class LuckyNumberPresenter @Inject constructor(
errorHandler: ErrorHandler, errorHandler: ErrorHandler,
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val luckyNumberRepository: LuckyNumberRepository, private val luckyNumberRepository: LuckyNumberRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<LuckyNumberView>(errorHandler, studentRepository) { ) : BasePresenter<LuckyNumberView>(errorHandler, studentRepository) {
private lateinit var lastError: Throwable private lateinit var lastError: Throwable

View File

@ -38,8 +38,8 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment
import io.github.wulkanowy.ui.modules.more.MoreFragment import io.github.wulkanowy.ui.modules.more.MoreFragment
import io.github.wulkanowy.ui.modules.note.NoteFragment import io.github.wulkanowy.ui.modules.note.NoteFragment
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.UpdateHelper import io.github.wulkanowy.utils.UpdateHelper
import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.getThemeAttrColor
@ -55,7 +55,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
override lateinit var presenter: MainPresenter override lateinit var presenter: MainPresenter
@Inject @Inject
lateinit var analytics: FirebaseAnalyticsHelper lateinit var analytics: AnalyticsHelper
@Inject @Inject
lateinit var updateHelper: UpdateHelper lateinit var updateHelper: UpdateHelper
@ -182,7 +182,10 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
} }
with(navController) { with(navController) {
setOnViewChangeListener(presenter::onViewChange) setOnViewChangeListener { section, name ->
analytics.setCurrentScreen(this@MainActivity, name)
presenter.onViewChange(section)
}
fragmentHideStrategy = HIDE fragmentHideStrategy = HIDE
rootFragments = listOf( rootFragments = listOf(
GradeFragment.newInstance(), GradeFragment.newInstance(),
@ -194,10 +197,6 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
} }
} }
override fun setCurrentScreen(name: String?) {
analytics.setCurrentScreen(this, name)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == R.id.mainMenuAccount) presenter.onAccountManagerSelected() return if (item.itemId == R.id.mainMenuAccount) presenter.onAccountManagerSelected()
else false else false
@ -208,6 +207,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
} }
override fun switchMenuView(position: Int) { override fun switchMenuView(position: Int) {
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.switchTab(position) navController.switchTab(position)
} }
@ -245,10 +245,12 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
} }
fun pushView(fragment: Fragment) { fun pushView(fragment: Fragment) {
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.pushFragment(fragment) navController.pushFragment(fragment)
} }
override fun popView(depth: Int) { override fun popView(depth: Int) {
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.safelyPopFragments(depth) navController.safelyPopFragments(depth)
} }

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.main.MainView.Section.GRADE import io.github.wulkanowy.ui.modules.main.MainView.Section.GRADE
import io.github.wulkanowy.ui.modules.main.MainView.Section.MESSAGE import io.github.wulkanowy.ui.modules.main.MainView.Section.MESSAGE
import io.github.wulkanowy.ui.modules.main.MainView.Section.SCHOOL import io.github.wulkanowy.ui.modules.main.MainView.Section.SCHOOL
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -17,7 +17,7 @@ class MainPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val prefRepository: PreferencesRepository, private val prefRepository: PreferencesRepository,
private val syncManager: SyncManager, private val syncManager: SyncManager,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<MainView>(errorHandler, studentRepository) { ) : BasePresenter<MainView>(errorHandler, studentRepository) {
fun onAttachView(view: MainView, initMenu: MainView.Section?) { fun onAttachView(view: MainView, initMenu: MainView.Section?) {
@ -35,9 +35,8 @@ class MainPresenter @Inject constructor(
analytics.logEvent("app_open", "destination" to initMenu?.name) analytics.logEvent("app_open", "destination" to initMenu?.name)
} }
fun onViewChange(section: MainView.Section?, name: String?) { fun onViewChange(section: MainView.Section?) {
view?.apply { view?.apply {
setCurrentScreen(name)
showActionBarElevation(section != GRADE && section != MESSAGE && section != SCHOOL) showActionBarElevation(section != GRADE && section != MESSAGE && section != SCHOOL)
currentViewTitle?.let { setViewTitle(it) } currentViewTitle?.let { setViewTitle(it) }
currentViewSubtitle?.let { setViewSubTitle(it.ifBlank { null }) } currentViewSubtitle?.let { setViewSubTitle(it.ifBlank { null }) }

View File

@ -24,8 +24,6 @@ interface MainView : BaseView {
fun showAccountPicker() fun showAccountPicker()
fun setCurrentScreen(name: String?)
fun showActionBarElevation(show: Boolean) fun showActionBarElevation(show: Boolean)
fun notifyMenuViewReselected() fun notifyMenuViewReselected()

View File

@ -11,7 +11,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
@ -24,7 +24,7 @@ class MessagePreviewPresenter @Inject constructor(
errorHandler: ErrorHandler, errorHandler: ErrorHandler,
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val messageRepository: MessageRepository, private val messageRepository: MessageRepository,
private val analytics: FirebaseAnalyticsHelper, private val analytics: AnalyticsHelper,
private var appInfo: AppInfo private var appInfo: AppInfo
) : BasePresenter<MessagePreviewView>(errorHandler, studentRepository) { ) : BasePresenter<MessagePreviewView>(errorHandler, studentRepository) {

View File

@ -11,7 +11,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.toFormattedString import io.github.wulkanowy.utils.toFormattedString
@ -27,7 +27,7 @@ class SendMessagePresenter @Inject constructor(
private val reportingUnitRepository: ReportingUnitRepository, private val reportingUnitRepository: ReportingUnitRepository,
private val recipientRepository: RecipientRepository, private val recipientRepository: RecipientRepository,
private val preferencesRepository: PreferencesRepository, private val preferencesRepository: PreferencesRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<SendMessageView>(errorHandler, studentRepository) { ) : BasePresenter<SendMessageView>(errorHandler, studentRepository) {
fun onAttachView(view: SendMessageView, message: Message?, reply: Boolean?) { fun onAttachView(view: SendMessageView, message: Message?, reply: Boolean?) {

View File

@ -8,7 +8,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import io.github.wulkanowy.utils.toFormattedString import io.github.wulkanowy.utils.toFormattedString
@ -32,7 +32,7 @@ class MessageTabPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val messageRepository: MessageRepository, private val messageRepository: MessageRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<MessageTabView>(errorHandler, studentRepository) { ) : BasePresenter<MessageTabView>(errorHandler, studentRepository) {
lateinit var folder: MessageFolder lateinit var folder: MessageFolder

View File

@ -7,7 +7,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
@ -21,7 +21,7 @@ class MobileDevicePresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val mobileDeviceRepository: MobileDeviceRepository, private val mobileDeviceRepository: MobileDeviceRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<MobileDeviceView>(errorHandler, studentRepository) { ) : BasePresenter<MobileDeviceView>(errorHandler, studentRepository) {
private lateinit var lastError: Throwable private lateinit var lastError: Throwable

View File

@ -6,7 +6,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -18,7 +18,7 @@ class MobileDeviceTokenPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val mobileDeviceRepository: MobileDeviceRepository, private val mobileDeviceRepository: MobileDeviceRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<MobileDeviceTokenVIew>(errorHandler, studentRepository) { ) : BasePresenter<MobileDeviceTokenVIew>(errorHandler, studentRepository) {
override fun onAttachView(view: MobileDeviceTokenVIew) { override fun onAttachView(view: MobileDeviceTokenVIew) {

View File

@ -9,6 +9,7 @@ import io.github.wulkanowy.R
import io.github.wulkanowy.databinding.FragmentMoreBinding import io.github.wulkanowy.databinding.FragmentMoreBinding
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.about.AboutFragment import io.github.wulkanowy.ui.modules.about.AboutFragment
import io.github.wulkanowy.ui.modules.conference.ConferenceFragment
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
@ -53,6 +54,9 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
override val mobileDevicesRes: Pair<String, Drawable?>? override val mobileDevicesRes: Pair<String, Drawable?>?
get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) } get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) }
override val conferencesRes: Pair<String, Drawable?>?
get() = context?.run { getString(R.string.conferences_title) to getCompatDrawable(R.drawable.ic_more_conferences) }
override val schoolAndTeachersRes: Pair<String, Drawable?>? override val schoolAndTeachersRes: Pair<String, Drawable?>?
get() = context?.run { getString(R.string.schoolandteachers_title) to getCompatDrawable((R.drawable.ic_more_schoolandteachers)) } get() = context?.run { getString(R.string.schoolandteachers_title) to getCompatDrawable((R.drawable.ic_more_schoolandteachers)) }
@ -108,6 +112,10 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
(activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance()) (activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance())
} }
override fun openConferencesView() {
(activity as? MainActivity)?.pushView(ConferenceFragment.newInstance())
}
override fun openSchoolAndTeachersView() { override fun openSchoolAndTeachersView() {
(activity as? MainActivity)?.pushView(SchoolAndTeachersFragment.newInstance()) (activity as? MainActivity)?.pushView(SchoolAndTeachersFragment.newInstance())
} }

View File

@ -27,6 +27,7 @@ class MorePresenter @Inject constructor(
noteRes?.first -> openNoteView() noteRes?.first -> openNoteView()
luckyNumberRes?.first -> openLuckyNumberView() luckyNumberRes?.first -> openLuckyNumberView()
mobileDevicesRes?.first -> openMobileDevicesView() mobileDevicesRes?.first -> openMobileDevicesView()
conferencesRes?.first -> openConferencesView()
schoolAndTeachersRes?.first -> openSchoolAndTeachersView() schoolAndTeachersRes?.first -> openSchoolAndTeachersView()
settingsRes?.first -> openSettingsView() settingsRes?.first -> openSettingsView()
aboutRes?.first -> openAboutView() aboutRes?.first -> openAboutView()
@ -48,6 +49,7 @@ class MorePresenter @Inject constructor(
noteRes, noteRes,
luckyNumberRes, luckyNumberRes,
mobileDevicesRes, mobileDevicesRes,
conferencesRes,
schoolAndTeachersRes, schoolAndTeachersRes,
settingsRes, settingsRes,
aboutRes aboutRes

View File

@ -15,6 +15,8 @@ interface MoreView : BaseView {
val mobileDevicesRes: Pair<String, Drawable?>? val mobileDevicesRes: Pair<String, Drawable?>?
val conferencesRes: Pair<String, Drawable?>?
val schoolAndTeachersRes: Pair<String, Drawable?>? val schoolAndTeachersRes: Pair<String, Drawable?>?
val settingsRes: Pair<String, Drawable?>? val settingsRes: Pair<String, Drawable?>?
@ -41,5 +43,7 @@ interface MoreView : BaseView {
fun openMobileDevicesView() fun openMobileDevicesView()
fun openConferencesView()
fun openSchoolAndTeachersView() fun openSchoolAndTeachersView()
} }

View File

@ -7,7 +7,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
@ -21,7 +21,7 @@ class NotePresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val noteRepository: NoteRepository, private val noteRepository: NoteRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<NoteView>(errorHandler, studentRepository) { ) : BasePresenter<NoteView>(errorHandler, studentRepository) {
private lateinit var lastError: Throwable private lateinit var lastError: Throwable

View File

@ -6,7 +6,7 @@ import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -18,7 +18,7 @@ class SchoolPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val schoolRepository: SchoolRepository, private val schoolRepository: SchoolRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<SchoolView>(errorHandler, studentRepository) { ) : BasePresenter<SchoolView>(errorHandler, studentRepository) {
private var address: String? = null private var address: String? = null

View File

@ -6,7 +6,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.data.repositories.teacher.TeacherRepository import io.github.wulkanowy.data.repositories.teacher.TeacherRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -18,7 +18,7 @@ class TeacherPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val teacherRepository: TeacherRepository, private val teacherRepository: TeacherRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<TeacherView>(errorHandler, studentRepository) { ) : BasePresenter<TeacherView>(errorHandler, studentRepository) {
private lateinit var lastError: Throwable private lateinit var lastError: Throwable

View File

@ -9,7 +9,7 @@ import io.github.wulkanowy.services.sync.SyncManager
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.isHolidays import io.github.wulkanowy.utils.isHolidays
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -22,7 +22,7 @@ class SettingsPresenter @Inject constructor(
studentRepository: StudentRepository, studentRepository: StudentRepository,
private val preferencesRepository: PreferencesRepository, private val preferencesRepository: PreferencesRepository,
private val timetableNotificationHelper: TimetableNotificationSchedulerHelper, private val timetableNotificationHelper: TimetableNotificationSchedulerHelper,
private val analytics: FirebaseAnalyticsHelper, private val analytics: AnalyticsHelper,
private val syncManager: SyncManager, private val syncManager: SyncManager,
private val chuckerCollector: ChuckerCollector, private val chuckerCollector: ChuckerCollector,
private val appInfo: AppInfo private val appInfo: AppInfo

View File

@ -9,7 +9,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.data.repositories.timetable.TimetableRepository import io.github.wulkanowy.data.repositories.timetable.TimetableRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
@ -34,7 +34,7 @@ class TimetablePresenter @Inject constructor(
private val timetableRepository: TimetableRepository, private val timetableRepository: TimetableRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val prefRepository: PreferencesRepository, private val prefRepository: PreferencesRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<TimetableView>(errorHandler, studentRepository) { ) : BasePresenter<TimetableView>(errorHandler, studentRepository) {
private var baseDate: LocalDate = now().nextOrSameSchoolDay private var baseDate: LocalDate = now().nextOrSameSchoolDay

View File

@ -7,7 +7,7 @@ import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsRe
import io.github.wulkanowy.data.repositories.semester.SemesterRepository import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
@ -30,7 +30,7 @@ class CompletedLessonsPresenter @Inject constructor(
private val completedLessonsErrorHandler: CompletedLessonsErrorHandler, private val completedLessonsErrorHandler: CompletedLessonsErrorHandler,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val completedLessonsRepository: CompletedLessonsRepository, private val completedLessonsRepository: CompletedLessonsRepository,
private val analytics: FirebaseAnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<CompletedLessonsView>(completedLessonsErrorHandler, studentRepository) { ) : BasePresenter<CompletedLessonsView>(completedLessonsErrorHandler, studentRepository) {
private var baseDate: LocalDate = now().nextOrSameSchoolDay private var baseDate: LocalDate = now().nextOrSameSchoolDay

View File

@ -24,7 +24,7 @@ import io.github.wulkanowy.services.HiltBroadcastReceiver
import io.github.wulkanowy.services.widgets.TimetableWidgetService import io.github.wulkanowy.services.widgets.TimetableWidgetService
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.nextOrSameSchoolDay import io.github.wulkanowy.utils.nextOrSameSchoolDay
import io.github.wulkanowy.utils.nextSchoolDay import io.github.wulkanowy.utils.nextSchoolDay
import io.github.wulkanowy.utils.previousSchoolDay import io.github.wulkanowy.utils.previousSchoolDay
@ -49,7 +49,7 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() {
lateinit var sharedPref: SharedPrefProvider lateinit var sharedPref: SharedPrefProvider
@Inject @Inject
lateinit var analytics: FirebaseAnalyticsHelper lateinit var analytics: AnalyticsHelper
companion object { companion object {

View File

@ -1,7 +1,7 @@
Wersja 0.22 Wersja 0.23.0
- naprawiliśmy krytyczny błąd ze stabilnością przy ładowaniu danych - naprawiliśmy logowanie do dziennika Gdańskiej i Koszalińskiej Platformy Edukacyjnej
- naprawiliśmy skalowanie tekstu przy bardzo dużych jego rozmiarach - przy logowaniu odpowiednia odmiana dziennika jest ustawiana automatycznie na podstawie wpisanego adresu email
- naprawiliśmy wyświetlanie powiadomień o odwołanych lekcjach (nie powinny się już pokazywać) - dodaliśmy wyświetlanie średniej w ocenach klasy (jeśli włączone przez szkołę)
- dodaliśmy informowanie o dostępności aktualizacji w aplikacji - dodaliśmy wyświetlanie zebrań
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFF"
android:fillType="nonZero"
android:pathData="M12,2C6.4883,2 2,6.4883 2,12C2,17.5117 6.4883,22 12,22C17.5117,22 22,17.5117 22,12C22,6.4883 17.5117,2 12,2ZM12,4C16.4297,4 20,7.5703 20,12C20,16.0156 17.0664,19.3125 13.2188,19.8984L13.2188,14.3828L15.5469,14.3828L15.9102,12.0195L13.2188,12.0195L13.2188,10.7266C13.2188,9.7422 13.5391,8.8711 14.457,8.8711L15.9336,8.8711L15.9336,6.8047C15.6758,6.7734 15.125,6.6953 14.0898,6.6953C11.9258,6.6953 10.6523,7.8398 10.6523,10.4453L10.6523,12.0195L8.4258,12.0195L8.4258,14.3828L10.6523,14.3828L10.6523,19.8789C6.8711,19.2422 4,15.9688 4,12C4,7.5703 7.5703,4 12,4ZM12,4" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M9,13.75c-2.34,0 -7,1.17 -7,3.5L2,19h14v-1.75c0,-2.33 -4.66,-3.5 -7,-3.5zM4.34,17c0.84,-0.58 2.87,-1.25 4.66,-1.25s3.82,0.67 4.66,1.25L4.34,17zM9,12c1.93,0 3.5,-1.57 3.5,-3.5S10.93,5 9,5 5.5,6.57 5.5,8.5 7.07,12 9,12zM9,7c0.83,0 1.5,0.67 1.5,1.5S9.83,10 9,10s-1.5,-0.67 -1.5,-1.5S8.17,7 9,7zM16.04,13.81c1.16,0.84 1.96,1.96 1.96,3.44L18,19h4v-1.75c0,-2.02 -3.5,-3.17 -5.96,-3.44zM15,12c1.93,0 3.5,-1.57 3.5,-3.5S16.93,5 15,5c-0.54,0 -1.04,0.13 -1.5,0.35 0.63,0.89 1,1.98 1,3.15s-0.37,2.26 -1,3.15c0.46,0.22 0.96,0.35 1.5,0.35z" />
</vector>

View File

@ -0,0 +1,104 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.modules.conference.ConferenceFragment">
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/conferenceProgress"
style="@style/Widget.MaterialProgressBar.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminate="true" />
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/conferenceSwipe"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/conferenceRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/item_conference" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<LinearLayout
android:id="@+id/conferenceEmpty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
app:srcCompat="@drawable/ic_more_conferences"
app:tint="?colorOnBackground"
tools:ignore="contentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="@string/conference_no_items"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/conferenceError"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="invisible"
tools:ignore="UseCompoundDrawables"
tools:visibility="invisible">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
app:srcCompat="@drawable/ic_error"
app:tint="?colorOnBackground"
tools:ignore="contentDescription" />
<TextView
android:id="@+id/conferenceErrorMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:padding="8dp"
android:text="@string/error_unknown"
android:textSize="20sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/conferenceErrorDetails"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/all_details" />
<com.google.android.material.button.MaterialButton
android:id="@+id/conferenceErrorRetry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/all_retry" />
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,87 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/conference_item_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
tools:context=".ui.modules.conference.ConferenceAdapter">
<TextView
android:id="@+id/conferenceItemDate"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:textColor="?android:textColorSecondary"
android:textSize="15sp"
app:layout_constraintRight_toLeftOf="@+id/conferenceItemName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/date/ddmmyy" />
<TextView
android:id="@+id/conferenceItemName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="15dp"
android:ellipsize="end"
android:gravity="end"
android:singleLine="true"
android:textSize="13sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/conferenceItemDate"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
<TextView
android:id="@+id/conferenceItemTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:ellipsize="end"
android:maxLines="2"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="@id/conferenceItemName"
app:layout_constraintStart_toStartOf="@id/conferenceItemDate"
app:layout_constraintTop_toBottomOf="@id/conferenceItemDate"
app:layout_goneMarginEnd="0dp"
tools:text="@tools:sample/lorem" />
<TextView
android:id="@+id/conferenceItemSubject"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:ellipsize="end"
android:maxLines="2"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@id/conferenceItemContent"
app:layout_constraintEnd_toEndOf="@id/conferenceItemTitle"
app:layout_constraintStart_toStartOf="@id/conferenceItemTitle"
app:layout_constraintTop_toBottomOf="@id/conferenceItemTitle"
app:layout_goneMarginBottom="15dp"
app:layout_goneMarginEnd="0dp"
tools:text="@tools:sample/lorem" />
<TextView
android:id="@+id/conferenceItemContent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="15dp"
android:ellipsize="end"
android:lineSpacingMultiplier="1.2"
android:maxLines="2"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/conferenceItemName"
app:layout_constraintStart_toStartOf="@id/conferenceItemDate"
app:layout_constraintTop_toBottomOf="@id/conferenceItemSubject"
tools:text="@tools:sample/lorem/random"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!--Activity/Fragment title--> <!--Activity/Fragment title-->
<string name="login_title">Přihlásit se</string> <string name="login_title">Přihlášení</string>
<string name="main_title">Wulkanowy</string> <string name="main_title">Wulkanowy</string>
<string name="grade_title">Známky</string> <string name="grade_title">Známky</string>
<string name="attendance_title">Prezence</string> <string name="attendance_title">Docházka</string>
<string name="exam_title">Zkoušky</string> <string name="exam_title">Zkoušky</string>
<string name="timetable_title">Plán lekce</string> <string name="timetable_title">Plán lekce</string>
<string name="settings_title">Nastavení</string> <string name="settings_title">Nastavení</string>
@ -16,18 +16,18 @@
<string name="message_title">Zprávy</string> <string name="message_title">Zprávy</string>
<string name="send_message_title">Nová zpráva</string> <string name="send_message_title">Nová zpráva</string>
<string name="note_title">Poznámky a úspěchy</string> <string name="note_title">Poznámky a úspěchy</string>
<string name="homework_title">Domácí práce</string> <string name="homework_title">Domácí úkoly</string>
<string name="account_title">Vyberte účet</string> <string name="account_title">Vyberte účet</string>
<!--Subtitles--> <!--Subtitles-->
<string name="grade_subtitle">Semestr %1$d, %2$d/%3$d</string> <string name="grade_subtitle">Semestr %1$d, %2$d/%3$d</string>
<!--Login--> <!--Login-->
<string name="login_header_default">Přihlaste se pomocí studentského nebo nadřazeného účtu</string> <string name="login_header_default">Přihlaste se pomocí studentského nebo rodičovského účtu</string>
<string name="login_header_symbol">Zadejte symbol</string> <string name="login_header_symbol">Zadejte symbol ze stránky deníku</string>
<string name="login_nickname_hint">Uživatelské jméno</string> <string name="login_nickname_hint">Uživatelské jméno</string>
<string name="login_email_hint">Email</string> <string name="login_email_hint">Email</string>
<string name="login_login_pesel_email_hint">Přihlášení, číslo PESEL nebo e-mail</string> <string name="login_login_pesel_email_hint">Přihlášení, číslo PESEL nebo e-mail</string>
<string name="login_password_hint">Heslo</string> <string name="login_password_hint">Heslo</string>
<string name="login_host_hint">Deník UONET+</string> <string name="login_host_hint">Variace deníku UONET+</string>
<string name="login_type_api">Mobile API</string> <string name="login_type_api">Mobile API</string>
<string name="login_type_scrapper">Scraper</string> <string name="login_type_scrapper">Scraper</string>
<string name="login_type_hybrid">Hybridní</string> <string name="login_type_hybrid">Hybridní</string>
@ -37,18 +37,18 @@
<string name="login_symbol_hint">Symbol</string> <string name="login_symbol_hint">Symbol</string>
<string name="login_sign_in">Přihlásit</string> <string name="login_sign_in">Přihlásit</string>
<string name="login_invalid_password">Toto heslo je příliš krátké</string> <string name="login_invalid_password">Toto heslo je příliš krátké</string>
<string name="login_incorrect_password">Přihlašovací údaje jsou nesprávné. Zkontrolujte, zda je v poli níže vybrán správný deník UONET+</string> <string name="login_incorrect_password">Přihlašovací údaje jsou nesprávné. Ujistěte se, že je v poli níže vybrána správná variace deníku UONET+</string>
<string name="login_invalid_pin">Neplatný PIN</string> <string name="login_invalid_pin">Neplatný PIN</string>
<string name="login_invalid_token">Neplatný token</string> <string name="login_invalid_token">Neplatný token</string>
<string name="login_expired_token">Platnost tokenu vypršela</string> <string name="login_expired_token">Platnost tokenu vypršela</string>
<string name="login_invalid_email">Nesprávná e-mailová adresa</string> <string name="login_invalid_email">Neplatný e-mail</string>
<string name="login_invalid_login">Neplatné přihlášení</string> <string name="login_invalid_login">Místo e-mailu použijte přiřazené přihlašovací údaje</string>
<string name="login_invalid_symbol">Neplatný symbol</string> <string name="login_invalid_symbol">Neplatný symbol</string>
<string name="login_incorrect_symbol">Student nebyl nalezen. Zkontrolujte symbol</string> <string name="login_incorrect_symbol">Student nebyl nalezen. Zkontrolujte správnost symbolu a vybrané varianty deníku UONET+</string>
<string name="login_field_required">Toto pole je povinné</string> <string name="login_field_required">Toto pole je povinné</string>
<string name="login_duplicate_student">Vybraný student je již přihlášen</string> <string name="login_duplicate_student">Vybraný student je již přihlášen</string>
<string name="login_symbol_helper">Symbol najdete na stránce deníku v&#160;<b>Uczeń</b>&#160;<b>Dostęp Mobilny</b>&#160;<b>Zarejestruj urządzenie mobilne</b></string> <string name="login_symbol_helper">Symbol najdete na stránce deníku v &#160;<b>Uczeń</b> &#160;<b>Dostęp Mobilny</b> &#160;<b>Zarejestruj urządzenie mobilne</b>.\n\nUjistěte se, že jste na předchozí obrazovce nastavili správnou variantu deníku do pole <b>Variace deníku UONET+</b>. Wulkanowy v tuto chvíli nezjistí předškolní studenty</string>
<string name="login_select_student">Vyberte studenty k přihlášení do aplikace</string> <string name="login_select_student">Vyberte studenty, kteří se mají do aplikace přihlásit</string>
<string name="login_advanced">Jiné možnosti</string> <string name="login_advanced">Jiné možnosti</string>
<string name="login_advanced_warning_mobile_api">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í</string> <string name="login_advanced_warning_mobile_api">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í</string>
<string name="login_advanced_warning_scraper">Tento režim zobrazuje stejná data, která se zobrazují na webových stránkách deníka</string> <string name="login_advanced_warning_scraper">Tento režim zobrazuje stejná data, která se zobrazují na webových stránkách deníka</string>
@ -59,13 +59,13 @@
<string name="login_contact_discord">Discord</string> <string name="login_contact_discord">Discord</string>
<string name="login_email_intent_title">Poslat e-mail</string> <string name="login_email_intent_title">Poslat e-mail</string>
<string name="login_email_details">Popište podrobnosti problému:</string> <string name="login_email_details">Popište podrobnosti problému:</string>
<string name="login_recover_warning">Ujistěte se, že je vybrán správný UONET+ deník!</string> <string name="login_recover_warning">Ujistěte se, že jste vybrali správnou variantu deníku UONET+!</string>
<string name="login_recover_button">Zapomněl jsem své heslo</string> <string name="login_recover_button">Zapomněl jsem své heslo</string>
<string name="login_recover_title">Obnovte svůj účet</string> <string name="login_recover_title">Obnovte svůj účet</string>
<string name="login_recover">Obnovit</string> <string name="login_recover">Obnovit</string>
<string name="login_signed_in">Student je již přihlášen</string> <string name="login_signed_in">Student je již přihlášen</string>
<!--Main--> <!--Main-->
<string name="main_account_picker">Správce účtu</string> <string name="main_account_picker">Manažer účtů</string>
<string name="main_log_in">Přihlásit se</string> <string name="main_log_in">Přihlásit se</string>
<string name="main_session_expired">Platnost relace vypršela</string> <string name="main_session_expired">Platnost relace vypršela</string>
<string name="main_session_relogin">Vaše relace vypršela, přihlaste se prosím znovu</string> <string name="main_session_relogin">Vaše relace vypršela, přihlaste se prosím znovu</string>
@ -79,9 +79,9 @@
<string name="grade_comment">Komentář</string> <string name="grade_comment">Komentář</string>
<string name="grade_no_new_items">Žádné nové známky</string> <string name="grade_no_new_items">Žádné nové známky</string>
<string name="grade_number_new_items">Počet nových známek: %1$d</string> <string name="grade_number_new_items">Počet nových známek: %1$d</string>
<string name="grade_average">Průměr: %1$.2f</string> <string name="grade_average">Průměr: %1$.2f</string>
<string name="grade_points_sum">Body: %s</string> <string name="grade_points_sum">Body: %s</string>
<string name="grade_no_average">Žádný průměr</string> <string name="grade_no_average">Bez průměru</string>
<string name="grade_predicted">Předpovězeno: %1$s</string> <string name="grade_predicted">Předpovězeno: %1$s</string>
<string name="grade_final">Konečná: %1$s</string> <string name="grade_final">Konečná: %1$s</string>
<string name="grade_summary_points">Celkem bodů</string> <string name="grade_summary_points">Celkem bodů</string>
@ -126,10 +126,10 @@
<item quantity="other">Máte %1$d nové známky</item> <item quantity="other">Máte %1$d nové známky</item>
</plurals> </plurals>
<plurals name="grade_notify_new_items_predicted"> <plurals name="grade_notify_new_items_predicted">
<item quantity="one">Máte %1$d novou konečnou známku</item> <item quantity="one">Máte %1$d novou předpokládanou známku</item>
<item quantity="few">Máte %1$d nové konečné známky</item> <item quantity="few">Máte %1$d nové předpokládané známky</item>
<item quantity="many">Máte %1$d nové konečné známky</item> <item quantity="many">Máte %1$d nové předpokládané známky</item>
<item quantity="other">Máte %1$d nové konečné známky</item> <item quantity="other">Máte %1$d nové předpokládané známky</item>
</plurals> </plurals>
<plurals name="grade_notify_new_items_final"> <plurals name="grade_notify_new_items_final">
<item quantity="one">Máte %1$d novou konečnou známku</item> <item quantity="one">Máte %1$d novou konečnou známku</item>
@ -143,7 +143,7 @@
<string name="timetable_group">Skupina</string> <string name="timetable_group">Skupina</string>
<string name="timetable_time">Hodiny</string> <string name="timetable_time">Hodiny</string>
<string name="timetable_changes">Změny</string> <string name="timetable_changes">Změny</string>
<string name="timetable_no_items">Dnes žádné lekce</string> <string name="timetable_no_items">Žádné lekce tento den</string>
<string name="timetable_minutes">%s min</string> <string name="timetable_minutes">%s min</string>
<string name="timetable_seconds">%s sek</string> <string name="timetable_seconds">%s sek</string>
<string name="timetable_time_left">dosud %1$s</string> <string name="timetable_time_left">dosud %1$s</string>
@ -155,32 +155,32 @@
<!--Completed lessons--> <!--Completed lessons-->
<string name="completed_lessons_title">Dokončené lekce</string> <string name="completed_lessons_title">Dokončené lekce</string>
<string name="completed_lessons_button">Zobrazit dokončené lekce</string> <string name="completed_lessons_button">Zobrazit dokončené lekce</string>
<string name="completed_lessons_no_items">Žádné informace o absolvovaných lekcích</string> <string name="completed_lessons_no_items">Žádné informace o dokončených lekcích</string>
<string name="completed_lessons_topic">Téma</string> <string name="completed_lessons_topic">Téma</string>
<string name="completed_lessons_absence">Absence</string> <string name="completed_lessons_absence">Nepřítomnost</string>
<string name="completed_lessons_resources">Zdroje</string> <string name="completed_lessons_resources">Zdroje</string>
<!--Attendance--> <!--Attendance-->
<string name="attendance_summary_button">Souhrn docházky</string> <string name="attendance_summary_button">Souhrn docházky</string>
<string name="attendance_absence_school">Nepřítomen ze školních důvodů</string> <string name="attendance_absence_school">Nepřítomen ze školních důvodů</string>
<string name="attendance_absence_excused">Omluvená absence</string> <string name="attendance_absence_excused">Omluvená nepřítomnost</string>
<string name="attendance_absence_unexcused">Neomluvená absence</string> <string name="attendance_absence_unexcused">Neomluvená absence</string>
<string name="attendance_exemption">Osvobození</string> <string name="attendance_exemption">Osvobození</string>
<string name="attendance_excused_lateness">Oprávněné zpoždění</string> <string name="attendance_excused_lateness">Omluvené zpoždění</string>
<string name="attendance_unexcused_lateness">Neomluvená zpoždění</string> <string name="attendance_unexcused_lateness">Neomluvené zpoždění</string>
<string name="attendance_present">Přítomnost</string> <string name="attendance_present">Přítomnost</string>
<string name="attendance_deleted">Smazáno</string> <string name="attendance_deleted">Smazáno</string>
<string name="attendance_unknown">Neznámý</string> <string name="attendance_unknown">Neznámý</string>
<string name="attendance_number">Číslo lekce</string> <string name="attendance_number">Číslo lekce</string>
<string name="attendance_no_items">Žádné položky</string> <string name="attendance_no_items">Žádné položky</string>
<plurals name="attendance_number_absences"> <plurals name="attendance_number_absences">
<item quantity="one">%1$d absence</item> <item quantity="one">%1$d nepřítomnost</item>
<item quantity="few">%1$d absence</item> <item quantity="few">%1$d nepřítomnosti</item>
<item quantity="many">%1$d absence</item> <item quantity="many">%1$d nepřítomnosti</item>
<item quantity="other">%1$d absence</item> <item quantity="other">%1$d nepřítomnosti</item>
</plurals> </plurals>
<string name="attendance_excuse_dialog_reason">Důvod absence (volitelný)</string> <string name="attendance_excuse_dialog_reason">Důvod nepřítomnosti (volitelný)</string>
<string name="attendance_excuse_dialog_submit">Poslat</string> <string name="attendance_excuse_dialog_submit">Poslat</string>
<string name="attendance_excuse_success">Absence úspěšně omluvena!</string> <string name="attendance_excuse_success">Nepřítomnost úspěšně omluvena!</string>
<string name="attendance_excuse_no_selection">Musíte vybrat alespoň jednu nepřítomnost!</string> <string name="attendance_excuse_no_selection">Musíte vybrat alespoň jednu nepřítomnost!</string>
<string name="attendance_excuse_title">Ospravedlnit</string> <string name="attendance_excuse_title">Ospravedlnit</string>
<!--Attendance summary--> <!--Attendance summary-->
@ -198,7 +198,7 @@
<string name="message_no_items">Žádné zprávy</string> <string name="message_no_items">Žádné zprávy</string>
<string name="message_preview_error">Při stahování obsahu zprávy došlo k chybě</string> <string name="message_preview_error">Při stahování obsahu zprávy došlo k chybě</string>
<string name="message_from">Od:</string> <string name="message_from">Od:</string>
<string name="message_to">Do:</string> <string name="message_to">Komu:</string>
<string name="message_date">Datum: %s</string> <string name="message_date">Datum: %s</string>
<string name="message_reply">Odpověď</string> <string name="message_reply">Odpověď</string>
<string name="message_forward">Poslat dále</string> <string name="message_forward">Poslat dále</string>
@ -226,10 +226,10 @@
<item quantity="other">Nové zprávy</item> <item quantity="other">Nové zprávy</item>
</plurals> </plurals>
<plurals name="message_notify_new_items"> <plurals name="message_notify_new_items">
<item quantity="one">Obdrželi jste %1$d zprávu</item> <item quantity="one">te %1$d novou zprávu</item>
<item quantity="few">Obdrželi jste %1$d zpráv</item> <item quantity="few">te %1$d nové zprávy</item>
<item quantity="many">Obdrželi jste %1$d zpráv</item> <item quantity="many">te %1$d nové zprávy</item>
<item quantity="other">Obdrželi jste %1$d zpráv</item> <item quantity="other">te %1$d nové zprávy</item>
</plurals> </plurals>
<!--Note--> <!--Note-->
<string name="note_no_items">Žádné informace o poznámkách</string> <string name="note_no_items">Žádné informace o poznámkách</string>
@ -286,12 +286,12 @@
</plurals> </plurals>
<plurals name="neutral_note_notify_new_items"> <plurals name="neutral_note_notify_new_items">
<item quantity="one">Máte %1$d novou neutrální pozornost</item> <item quantity="one">Máte %1$d novou neutrální pozornost</item>
<item quantity="few">Máte %1$d nové neutrální komentáře</item> <item quantity="few">Máte %1$d nové neutrální pozornosti</item>
<item quantity="many">Máte %1$d nové neutrální komentáře</item> <item quantity="many">Máte %1$d nové neutrální pozornosti</item>
<item quantity="other">Máte %1$d nové neutrální komentáře</item> <item quantity="other">Máte %1$d nové neutrální pozornosti</item>
</plurals> </plurals>
<!--Homework--> <!--Homework-->
<string name="homework_no_items">Žádný domácí úkol</string> <string name="homework_no_items">Žádné informace o domácím úkolu</string>
<string name="homework_mark_as_done">Označit jako hotové</string> <string name="homework_mark_as_done">Označit jako hotové</string>
<string name="homework_mark_as_undone">Neudělané</string> <string name="homework_mark_as_undone">Neudělané</string>
<string name="homework_attachments">Přílohy</string> <string name="homework_attachments">Přílohy</string>
@ -315,7 +315,7 @@
<!--School--> <!--School-->
<string name="school_title">Škola</string> <string name="school_title">Škola</string>
<string name="school_no_info">Žádné informace o škole</string> <string name="school_no_info">Žádné informace o škole</string>
<string name="school_name">Školní jméno</string> <string name="school_name">Název školy</string>
<string name="school_address">Adresa školy</string> <string name="school_address">Adresa školy</string>
<string name="school_telephone">Telefon</string> <string name="school_telephone">Telefon</string>
<string name="school_headmaster">Jméno ředitele</string> <string name="school_headmaster">Jméno ředitele</string>
@ -326,6 +326,9 @@
<string name="teachers_title">Učitelé</string> <string name="teachers_title">Učitelé</string>
<string name="teacher_no_items">Žádné informace o učitelích</string> <string name="teacher_no_items">Žádné informace o učitelích</string>
<string name="teacher_no_subject">Žádný předmět</string> <string name="teacher_no_subject">Žádný předmět</string>
<!--Conference-->
<string name="conferences_title">Setkání</string>
<string name="conference_no_items">Žádné informace o setkání</string>
<!--Account--> <!--Account-->
<string name="account_add_new">Přidat účet</string> <string name="account_add_new">Přidat účet</string>
<string name="account_logout">Odhlásit se</string> <string name="account_logout">Odhlásit se</string>
@ -333,18 +336,20 @@
<string name="account_logout_student">Odhlášení studentů</string> <string name="account_logout_student">Odhlášení studentů</string>
<string name="account_type_student">Studentský účet</string> <string name="account_type_student">Studentský účet</string>
<string name="account_type_parent">Rodičovský účet</string> <string name="account_type_parent">Rodičovský účet</string>
<string name="account_login_mobile_api">Režimu Mobíle API</string> <string name="account_login_mobile_api">Režim Mobilního API</string>
<string name="account_login_hybrid">Hybridní režim</string> <string name="account_login_hybrid">Hybridní režim</string>
<!--About--> <!--About-->
<string name="about_version">Verze aplikace</string> <string name="about_version">Verze aplikace</string>
<string name="about_contributor">Tvůrci</string> <string name="about_contributor">Tvůrci</string>
<string name="about_contributor_summary">Seznam vývojářů Wulkanowy</string> <string name="about_contributor_summary">Seznam vývojářů Wulkanowy</string>
<string name="about_feedback">Nahlásit chybu</string> <string name="about_feedback">Nahlásit chybu</string>
<string name="about_feedback_summary">Pošlete hlášení o chybě e-mailem</string> <string name="about_feedback_summary">Odeslat zprávu o chybě e-mailem</string>
<string name="about_faq">FAQ</string> <string name="about_faq">FAQ</string>
<string name="about_faq_summary">Přečtěte si často kladené otázky</string> <string name="about_faq_summary">Přečtěte si často kladené otázky</string>
<string name="about_discord">Server Discord</string> <string name="about_discord">Server Discord</string>
<string name="about_discord_summary">Připojte se ke komunitě Wulkanowy</string> <string name="about_discord_summary">Připojte se ke komunitě Wulkanowy</string>
<string name="about_facebook">Facebooková fanpage</string>
<string name="about_facebook_summary">Stejně jako naše facebooková fanpage</string>
<string name="about_privacy">Zásady ochrany osobních údajů</string> <string name="about_privacy">Zásady ochrany osobních údajů</string>
<string name="about_privacy_summary">Pravidla pro shromažďování osobních údajů</string> <string name="about_privacy_summary">Pravidla pro shromažďování osobních údajů</string>
<string name="about_homepage">Domovská stránka</string> <string name="about_homepage">Domovská stránka</string>
@ -360,8 +365,8 @@
<string name="logviewer_share">Sdílejte protokoly</string> <string name="logviewer_share">Sdílejte protokoly</string>
<string name="logviewer_refresh">Obnovit</string> <string name="logviewer_refresh">Obnovit</string>
<!--Error dialog--> <!--Error dialog-->
<string name="dialog_error_check_update">Kontrola aktualizací</string> <string name="dialog_error_check_update">Zkontrolovat aktualizace</string>
<string name="dialog_error_check_update_message">Před nahlášením chyby nejprve zkontrolujte, zda je k dispozici aktualizace s opravou chyby</string> <string name="dialog_error_check_update_message">Před hlášením chyby zkontrolujte, zda je k dispozici aktualizace s opravou chyb</string>
<!--Generic--> <!--Generic-->
<string name="all_content">Obsah</string> <string name="all_content">Obsah</string>
<string name="all_retry">Zkuste to znovu</string> <string name="all_retry">Zkuste to znovu</string>
@ -378,21 +383,21 @@
<string name="all_subject">Předmět</string> <string name="all_subject">Předmět</string>
<string name="all_prev">Předchozí</string> <string name="all_prev">Předchozí</string>
<string name="all_next">Další</string> <string name="all_next">Další</string>
<string name="all_search">Vyhledávání</string> <string name="all_search">Hledat</string>
<string name="all_search_hint">Vyhledávání</string> <string name="all_search_hint">Hledat</string>
<!--Timetable Widget--> <!--Timetable Widget-->
<string name="widget_timetable_no_items">Žádné lekce</string> <string name="widget_timetable_no_items">Žádné lekce</string>
<string name="widget_timetable_theme_title">Vyberte téma</string> <string name="widget_timetable_theme_title">Vybrat motiv</string>
<string name="widget_timetable_theme_light">Světlý</string> <string name="widget_timetable_theme_light">Světlý</string>
<string name="widget_timetable_theme_dark">Tmavý</string> <string name="widget_timetable_theme_dark">Tmavý</string>
<string name="widget_timetable_theme_system">Téma systému</string> <string name="widget_timetable_theme_system">Motiv systému</string>
<!--Preferences--> <!--Preferences-->
<string name="pref_view_header">Vzhled</string> <string name="pref_view_header">Vzhled</string>
<string name="pref_view_list">Výchozí zobrazení</string> <string name="pref_view_list">Výchozí zobrazení</string>
<string name="pref_view_grade_average_mode">Výpočet koncoročního průměru</string> <string name="pref_view_grade_average_mode">Výpočet koncoročního průměru</string>
<string name="pref_view_grade_average_force_calc">Vynutit průměrný výpočet podle aplikace</string> <string name="pref_view_grade_average_force_calc">Vynutit průměrný výpočet podle aplikace</string>
<string name="pref_view_present">Zobrazit přítomnost v účasti</string> <string name="pref_view_present">Zobrazit přítomnost v účasti</string>
<string name="pref_view_app_theme">Téma aplikace</string> <string name="pref_view_app_theme">Motiv aplikace</string>
<string name="pref_view_expand_grade">Rozbalit známky</string> <string name="pref_view_expand_grade">Rozbalit známky</string>
<string name="pref_view_timetable_show_timers">Označte aktuální lekci v plánu lekce</string> <string name="pref_view_timetable_show_timers">Označte aktuální lekci v plánu lekce</string>
<string name="pref_view_timetable_show_groups">Ukázat skupiny vedle předmětů v plánu lekce</string> <string name="pref_view_timetable_show_groups">Ukázat skupiny vedle předmětů v plánu lekce</string>
@ -407,22 +412,22 @@
<string name="pref_notify_upcoming_lessons_switch">Ukázat nadcházející oznámení o lekci</string> <string name="pref_notify_upcoming_lessons_switch">Ukázat nadcházející oznámení o lekci</string>
<string name="pref_notify_fix_sync_issues">Opravte problémy se synchronizací a upozorněním</string> <string name="pref_notify_fix_sync_issues">Opravte problémy se synchronizací a upozorněním</string>
<string name="pref_notify_fix_sync_issues_message">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.</string> <string name="pref_notify_fix_sync_issues_message">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.</string>
<string name="pref_notify_fix_sync_issues_settings_button">Jdi do nastavení</string> <string name="pref_notify_fix_sync_issues_settings_button">Přejít do nastavení</string>
<string name="pref_notify_debug_switch">Ukázat oznámení o ladění</string> <string name="pref_notify_debug_switch">Ukázat oznámení o ladění</string>
<string name="pref_services_header">Synchronizace</string> <string name="pref_services_header">Synchronizace</string>
<string name="pref_services_switch">Automatická aktualizace</string> <string name="pref_services_switch">Automatická aktualizace</string>
<string name="pref_services_suspended">Pozastaveno na dovolené</string> <string name="pref_services_suspended">Pozastaveno na dovolené</string>
<string name="pref_services_interval">Interval aktualizací</string> <string name="pref_services_interval">Interval aktualizací</string>
<string name="pref_services_wifi">Pouze Wi-Fi</string> <string name="pref_services_wifi">Pouze Wi-Fi</string>
<string name="pref_services_force_sync">Nyní synchronizovat</string> <string name="pref_services_force_sync">Synchronizovat nyní</string>
<string name="pref_services_message_sync_success">Synchronizováno!</string> <string name="pref_services_message_sync_success">Synchronizováno!</string>
<string name="pref_services_message_sync_failed">Synchronizace se nezdařila</string> <string name="pref_services_message_sync_failed">Synchronizace selhala</string>
<string name="pref_services_sync_in_progress">Probíhá synchronizace</string> <string name="pref_services_sync_in_progress">Probíhá synchronizace</string>
<string name="pref_services_dialog_force_sync_title">Synchronizace</string> <string name="pref_services_dialog_force_sync_title">Synchronizace</string>
<string name="pref_services_dialog_force_sync_summary"> Ruční synchronizace neobnoví zobrazení aplikace. <string name="pref_services_dialog_force_sync_summary"> Ruční synchronizace neobnoví zobrazení aplikace.
\nChcete-li zobrazit synchronizovaná data, restartujte aplikaci po synchronizaci. \nChcete-li zobrazit synchronizovaná data, restartujte aplikaci po synchronizaci.
</string> </string>
<string name="pref_other_header">Jiný</string> <string name="pref_other_header">Jiné</string>
<string name="pref_other_grade_modifier_plus">Hodnota plusu</string> <string name="pref_other_grade_modifier_plus">Hodnota plusu</string>
<string name="pref_other_grade_modifier_minus">Hodnota mínusu</string> <string name="pref_other_grade_modifier_minus">Hodnota mínusu</string>
<string name="pref_other_fill_message_content">Odpovědět s historií zpráv</string> <string name="pref_other_fill_message_content">Odpovědět s historií zpráv</string>
@ -432,9 +437,9 @@
<string name="channel_lucky_number">Šťastné číslo</string> <string name="channel_lucky_number">Šťastné číslo</string>
<string name="channel_new_message">Nové zprávy</string> <string name="channel_new_message">Nové zprávy</string>
<string name="channel_new_notes">Nové poznámky</string> <string name="channel_new_notes">Nové poznámky</string>
<string name="channel_push">Oznámení push</string> <string name="channel_push">Push oznámení</string>
<string name="channel_upcoming_lessons">Nadcházející lekce</string> <string name="channel_upcoming_lessons">Nadcházející lekce</string>
<string name="channel_debug">Ladění</string> <string name="channel_debug">Debug</string>
<!--Colors--> <!--Colors-->
<string name="all_black">Černý</string> <string name="all_black">Černý</string>
<string name="all_red">Červený</string> <string name="all_red">Červený</string>
@ -445,12 +450,19 @@
<!--Others--> <!--Others-->
<string name="all_copied">Zkopírováno</string> <string name="all_copied">Zkopírováno</string>
<string name="all_undo">Vrátit</string> <string name="all_undo">Vrátit</string>
<!--Update helper-->
<string name="update_download_started">Stahování aktualizací začalo…</string>
<string name="update_download_success">Aktualizace byla stažena.</string>
<string name="update_download_success_button">Restartovat</string>
<string name="update_failed">Aktualizace selhala! Wulkanowy nemusí fungovat správně. Zvažte aktualizaci</string>
<!--Errors--> <!--Errors-->
<string name="error_no_internet">Žádné internetové připojení</string> <string name="error_no_internet">Žádné internetové připojení</string>
<string name="error_timeout">Vypršel časový limit připojení k denik</string> <string name="error_timeout">Nelze se připojit ke deníku. Servery mohou být přetíženy. Prosím zkuste to znovu později</string>
<string name="error_login_failed">Přihlášení selhalo. Zkuste to znovu nebo restartujte aplikaci</string> <string name="error_login_failed">Načítání dat se nezdařilo. Prosím zkuste to znovu později</string>
<string name="error_password_change_required">Je vyžadována změna hesla</string> <string name="error_password_change_required">Je vyžadována změna hesla pro deník</string>
<string name="error_service_unavailable">Probíhá údržba UONET+ deník. Zkuste to později znovu</string> <string name="error_service_unavailable">Probíhá údržba UONET+ deník. Zkuste to později znovu</string>
<string name="error_unknown_uonet">Neznámá chyba denika UONET+. Prosím zkuste to znovu později</string>
<string name="error_unknown_app">Neznámá chyba aplikace. Prosím zkuste to znovu později</string>
<string name="error_unknown">Došlo k neočekávané chybě</string> <string name="error_unknown">Došlo k neočekávané chybě</string>
<string name="error_feature_disabled">Funkce deaktivována vaší školou</string> <string name="error_feature_disabled">Funkce deaktivována vaší školou</string>
<string name="error_feature_not_available">Funkce není k dispozici. Přihlaste se v jiném režimu než Mobile API</string> <string name="error_feature_not_available">Funkce není k dispozici. Přihlaste se v jiném režimu než Mobile API</string>

View File

@ -31,8 +31,8 @@
<item>0,75</item> <item>0,75</item>
</string-array> </string-array>
<string-array name="grade_sorting_mode_entries"> <string-array name="grade_sorting_mode_entries">
<item>Alphabetic</item> <item>Alphabetisch</item>
<item>By date</item> <item>Nach Datum</item>
</string-array> </string-array>
<string-array name="grade_color_scheme_entries"> <string-array name="grade_color_scheme_entries">
<item>Dzienniczek+</item> <item>Dzienniczek+</item>

View File

@ -22,12 +22,12 @@
<string name="grade_subtitle">Semester %1$d, %2$d/%3$d</string> <string name="grade_subtitle">Semester %1$d, %2$d/%3$d</string>
<!--Login--> <!--Login-->
<string name="login_header_default">Melden Sie sich mit dem Studenten- oder Elternkonto an</string> <string name="login_header_default">Melden Sie sich mit dem Studenten- oder Elternkonto an</string>
<string name="login_header_symbol">Geben Sie das Symbol</string> <string name="login_header_symbol">Geben Sie das Symbol von der Registerseite ein</string>
<string name="login_nickname_hint">Benutzername</string> <string name="login_nickname_hint">Benutzername</string>
<string name="login_email_hint">Email</string> <string name="login_email_hint">Email</string>
<string name="login_login_pesel_email_hint">Anmeldung, PESEL oder e-mail</string> <string name="login_login_pesel_email_hint">Anmeldung, PESEL oder e-mail</string>
<string name="login_password_hint">Passwort</string> <string name="login_password_hint">Passwort</string>
<string name="login_host_hint">UONET+ Klassenbuch</string> <string name="login_host_hint">UONET+ Registervariante</string>
<string name="login_type_api">Mobile API</string> <string name="login_type_api">Mobile API</string>
<string name="login_type_scrapper">Scraper</string> <string name="login_type_scrapper">Scraper</string>
<string name="login_type_hybrid">Hybride</string> <string name="login_type_hybrid">Hybride</string>
@ -37,17 +37,17 @@
<string name="login_symbol_hint">Symbol</string> <string name="login_symbol_hint">Symbol</string>
<string name="login_sign_in">Anmelden</string> <string name="login_sign_in">Anmelden</string>
<string name="login_invalid_password">Passwort ist zu kurz</string> <string name="login_invalid_password">Passwort ist zu kurz</string>
<string name="login_incorrect_password">Anmeldedaten sind falsch. Stellen Sie sicher, dass das richtige UONET+-Register ausgewählt ist</string> <string name="login_incorrect_password">Anmeldedaten sind falsch. Stellen Sie sicher, dass die richtige UONET+ Registervariation im unteren Feld ausgewählt ist</string>
<string name="login_invalid_pin">Ungültige PIN</string> <string name="login_invalid_pin">Ungültige PIN</string>
<string name="login_invalid_token">Ungültige token</string> <string name="login_invalid_token">Ungültige token</string>
<string name="login_expired_token">Token ist nicht mehr gültig</string> <string name="login_expired_token">Token ist nicht mehr gültig</string>
<string name="login_invalid_email">Ungültige email</string> <string name="login_invalid_email">Ungültige email</string>
<string name="login_invalid_login">Ungültige login</string> <string name="login_invalid_login">Den zugewiesenen Login anstelle von email verwenden</string>
<string name="login_invalid_symbol">Ungültige symbol</string> <string name="login_invalid_symbol">Ungültige symbol</string>
<string name="login_incorrect_symbol">Student nicht gefunden. Überprüfen Sie das Symbol</string> <string name="login_incorrect_symbol">Schüler nicht gefunden. Überprüfen Sie das Symbol und die gewählte Variation des UONET+ Registers</string>
<string name="login_field_required">Dieses Datenfeld ist erforderlich</string> <string name="login_field_required">Dieses Datenfeld ist erforderlich</string>
<string name="login_duplicate_student">Ausgewählter Student ist bereits angemeldet.</string> <string name="login_duplicate_student">Ausgewählter Student ist bereits angemeldet.</string>
<string name="login_symbol_helper">Das Symbol finden Sie auf der Registerseite unter&#160;<b>Uczeń</b> &#160;<b>Dostęp Mobilny</b>&#160;<b>Zarejestruj urządzenie mobilne</b></string> <string name="login_symbol_helper">Das Symbol kann auf der Registerseite in&#160;<b>Uczeń</b>&#160;<b>Dostęp Mobilny</b>&#160;<b>Zarejestruj urządzenie mobilne</b>gefunden werden.\n\nStellen Sie sicher, dass Sie die entsprechende Registervariante im Feld <b>UONET+ Registervariante</b> auf dem vorherigen Bildschirm festgelegt haben. Wulkanowy erkennt zur Zeit keine Vorschulstudenten</string>
<string name="login_select_student">Wählen Sie die Studenten aus, die sich bei der Anwendung anmelden sollen.</string> <string name="login_select_student">Wählen Sie die Studenten aus, die sich bei der Anwendung anmelden sollen.</string>
<string name="login_advanced">Andere Optionen</string> <string name="login_advanced">Andere Optionen</string>
<string name="login_advanced_warning_mobile_api">In diesem Modus funktioniert eine Glücknummer, eine Klassenstatistik, eine Zusammenfassung der Anwesenheit, eine Entschuldigung für die Abwesenheit, abgeschlossene Lektionen, Schulinformationen und eine Vorschau der Liste der registrierten Geräte nicht</string> <string name="login_advanced_warning_mobile_api">In diesem Modus funktioniert eine Glücknummer, eine Klassenstatistik, eine Zusammenfassung der Anwesenheit, eine Entschuldigung für die Abwesenheit, abgeschlossene Lektionen, Schulinformationen und eine Vorschau der Liste der registrierten Geräte nicht</string>
@ -59,7 +59,7 @@
<string name="login_contact_discord">Discord</string> <string name="login_contact_discord">Discord</string>
<string name="login_email_intent_title">email senden</string> <string name="login_email_intent_title">email senden</string>
<string name="login_email_details">Beschreiben Sie die Details des Problems:</string> <string name="login_email_details">Beschreiben Sie die Details des Problems:</string>
<string name="login_recover_warning">Stellen Sie sicher, dass das richtige UONET + Klassenbuch ausgewählt ist!</string> <string name="login_recover_warning">Stellen Sie sicher, dass Sie die richtige UONET+ Registervariation wählen!</string>
<string name="login_recover_button">Ich habe mein Passwort vergessen.</string> <string name="login_recover_button">Ich habe mein Passwort vergessen.</string>
<string name="login_recover_title">Ihr Konto wiederherstellen</string> <string name="login_recover_title">Ihr Konto wiederherstellen</string>
<string name="login_recover">Wiederherstellen</string> <string name="login_recover">Wiederherstellen</string>
@ -154,8 +154,8 @@
<string name="attendance_excused_lateness">Entschuldigte Verspätung</string> <string name="attendance_excused_lateness">Entschuldigte Verspätung</string>
<string name="attendance_unexcused_lateness">Unentschuldigte Verspätung</string> <string name="attendance_unexcused_lateness">Unentschuldigte Verspätung</string>
<string name="attendance_present">Anwesend</string> <string name="attendance_present">Anwesend</string>
<string name="attendance_deleted">Deleted</string> <string name="attendance_deleted">Entfernt</string>
<string name="attendance_unknown">Unknown</string> <string name="attendance_unknown">Unbekannt</string>
<string name="attendance_number">Lektion Nummer</string> <string name="attendance_number">Lektion Nummer</string>
<string name="attendance_no_items">Keine Einträgen</string> <string name="attendance_no_items">Keine Einträgen</string>
<plurals name="attendance_number_absences"> <plurals name="attendance_number_absences">
@ -226,29 +226,29 @@
</plurals> </plurals>
<!--Praise--> <!--Praise-->
<plurals name="praise_number_item"> <plurals name="praise_number_item">
<item quantity="one">%d praise</item> <item quantity="one">%d Lob</item>
<item quantity="other">%d praises</item> <item quantity="other">%d Lob</item>
</plurals> </plurals>
<plurals name="praise_new_items"> <plurals name="praise_new_items">
<item quantity="one">New praise</item> <item quantity="one">Neues Lob</item>
<item quantity="other">New praises</item> <item quantity="other">Neues Lob</item>
</plurals> </plurals>
<plurals name="praise_notify_new_items"> <plurals name="praise_notify_new_items">
<item quantity="one">You received %1$d praise</item> <item quantity="one">Du hast %1$d Lob erhalten</item>
<item quantity="other">You received %1$d praises</item> <item quantity="other">Du hast %1$d Lob erhalten</item>
</plurals> </plurals>
<!--Neutral notes--> <!--Neutral notes-->
<plurals name="neutral_note_number_item"> <plurals name="neutral_note_number_item">
<item quantity="one">%d neutral note</item> <item quantity="one">%d neutrale Notiz</item>
<item quantity="other">%d neutral notes</item> <item quantity="other">%d neutrale Notizen</item>
</plurals> </plurals>
<plurals name="neutral_note_new_items"> <plurals name="neutral_note_new_items">
<item quantity="one">New neutral note</item> <item quantity="one">Neue neutrale Notiz</item>
<item quantity="other">New neutral notes</item> <item quantity="other">Neue neutrale Notizen</item>
</plurals> </plurals>
<plurals name="neutral_note_notify_new_items"> <plurals name="neutral_note_notify_new_items">
<item quantity="one">You received %1$d neutral note</item> <item quantity="one">Du hast %1$d neutrale Notiz erhalten</item>
<item quantity="other">You received %1$d neutral notes</item> <item quantity="other">Du hast %1$d neutrale Notizen erhalten</item>
</plurals> </plurals>
<!--Homework--> <!--Homework-->
<string name="homework_no_items">Keine Informationen über Hausaufgaben</string> <string name="homework_no_items">Keine Informationen über Hausaufgaben</string>
@ -286,6 +286,9 @@
<string name="teachers_title">Lehrerinnen und Lehrer</string> <string name="teachers_title">Lehrerinnen und Lehrer</string>
<string name="teacher_no_items">Keine Informationen über Lehrer</string> <string name="teacher_no_items">Keine Informationen über Lehrer</string>
<string name="teacher_no_subject">Kein Thema</string> <string name="teacher_no_subject">Kein Thema</string>
<!--Conference-->
<string name="conferences_title">Sitzungen</string>
<string name="conference_no_items">Keine Informationen über Sitzungen</string>
<!--Account--> <!--Account-->
<string name="account_add_new">Konto hinzufügen</string> <string name="account_add_new">Konto hinzufügen</string>
<string name="account_logout">Abmelden</string> <string name="account_logout">Abmelden</string>
@ -305,6 +308,8 @@
<string name="about_faq_summary">Lesen Sie Häufig gestellte Fragen</string> <string name="about_faq_summary">Lesen Sie Häufig gestellte Fragen</string>
<string name="about_discord">Discord server</string> <string name="about_discord">Discord server</string>
<string name="about_discord_summary">Treten Sie der Wulkanowy-Gemeinschaft bei</string> <string name="about_discord_summary">Treten Sie der Wulkanowy-Gemeinschaft bei</string>
<string name="about_facebook">Facebook fanpage</string>
<string name="about_facebook_summary">Gefällt unsere Facebook-Fanpage</string>
<string name="about_privacy">Datenschutzerklärung</string> <string name="about_privacy">Datenschutzerklärung</string>
<string name="about_privacy_summary">Regeln für die Sammlung persönlicher Daten</string> <string name="about_privacy_summary">Regeln für die Sammlung persönlicher Daten</string>
<string name="about_homepage">Startseite</string> <string name="about_homepage">Startseite</string>
@ -355,12 +360,12 @@
<string name="pref_view_app_theme">Thema der Anwendung</string> <string name="pref_view_app_theme">Thema der Anwendung</string>
<string name="pref_view_expand_grade">Noten erweitern</string> <string name="pref_view_expand_grade">Noten erweitern</string>
<string name="pref_view_timetable_show_timers">Aktuelle Lektion im Stundenplan markieren</string> <string name="pref_view_timetable_show_timers">Aktuelle Lektion im Stundenplan markieren</string>
<string name="pref_view_timetable_show_groups">Show groups next to subjects in timetable</string> <string name="pref_view_timetable_show_groups">Zeige Gruppen neben Themen im Zeitplan</string>
<string name="pref_view_grade_statistics_list">Liste der Diagramme in Klassenbewertungen anzeigen</string> <string name="pref_view_grade_statistics_list">Liste der Diagramme in Klassenbewertungen anzeigen</string>
<string name="pref_view_timetable_show_whole_class">Unterricht der ganzen Klasse anzeigen</string> <string name="pref_view_timetable_show_whole_class">Unterricht der ganzen Klasse anzeigen</string>
<string name="pref_view_subjects_without_grades">Show subjects without grades in Grades</string> <string name="pref_view_subjects_without_grades">Zeigen Sie Themen ohne Noten in Noten</string>
<string name="pref_view_grade_color_scheme">Farbschema der Noten</string> <string name="pref_view_grade_color_scheme">Farbschema der Noten</string>
<string name="pref_view_grade_sorting_mode">Subjects sorting in \"Grades\"</string> <string name="pref_view_grade_sorting_mode">Themen sortieren in \"Noten\"</string>
<string name="pref_view_app_language">App Sprache</string> <string name="pref_view_app_language">App Sprache</string>
<string name="pref_notify_header">Benachrichtigungen</string> <string name="pref_notify_header">Benachrichtigungen</string>
<string name="pref_notify_switch">Benachrichtigungen anzeigen</string> <string name="pref_notify_switch">Benachrichtigungen anzeigen</string>
@ -405,12 +410,19 @@
<!--Others--> <!--Others-->
<string name="all_copied">Kopiert</string> <string name="all_copied">Kopiert</string>
<string name="all_undo">lösen</string> <string name="all_undo">lösen</string>
<!--Update helper-->
<string name="update_download_started">Download der Updates wurde gestartet…</string>
<string name="update_download_success">Ein Update wurde gerade heruntergeladen.</string>
<string name="update_download_success_button">Neustart</string>
<string name="update_failed">Update fehlgeschlagen! Wulkanowy funktioniert möglicherweise nicht richtig. Überlegen Sie die Aktualisierung</string>
<!--Errors--> <!--Errors-->
<string name="error_no_internet">Keine Internetverbindung</string> <string name="error_no_internet">Keine Internetverbindung</string>
<string name="error_timeout">Das Zeitlimit für die Verbindung zum Klassenbuch ist abgelaufen</string> <string name="error_timeout">Registrierungsverbindung fehlgeschlagen. Server können überlastet sein. Bitte versuchen Sie es später noch einmal</string>
<string name="error_login_failed">Anmeldung fehlgeschlagen. Versuchen Sie es noch einmal oder starten Sie die Anwendung neu.</string> <string name="error_login_failed">Das Laden der Daten ist fehlgeschlagen. Bitte versuchen Sie es später noch einmal</string>
<string name="error_password_change_required">Passwortänderung erforderlich</string> <string name="error_password_change_required">Passwortänderung für Registrierung erforderlich</string>
<string name="error_service_unavailable">Wartung im Gange UONET + Klassenbuch. Versuchen Sie es später noch einmal</string> <string name="error_service_unavailable">Wartung im Gange UONET + Klassenbuch. Versuchen Sie es später noch einmal</string>
<string name="error_unknown_uonet">Unbekannter UONET + Registerfehler. Versuchen Sie es später erneut</string>
<string name="error_unknown_app">Unbekannter Anwendungsfehler. Bitte versuchen Sie es später noch einmal</string>
<string name="error_unknown">Ein unerwarteter Fehler ist aufgetreten</string> <string name="error_unknown">Ein unerwarteter Fehler ist aufgetreten</string>
<string name="error_feature_disabled">Funktion, die von Ihrer Schule deaktiviert wurde</string> <string name="error_feature_disabled">Funktion, die von Ihrer Schule deaktiviert wurde</string>
<string name="error_feature_not_available">Feature in diesem Modus nicht verfügbar</string> <string name="error_feature_not_available">Feature in diesem Modus nicht verfügbar</string>

View File

@ -22,12 +22,12 @@
<string name="grade_subtitle">Semestr %1$d, %2$d/%3$d</string> <string name="grade_subtitle">Semestr %1$d, %2$d/%3$d</string>
<!--Login--> <!--Login-->
<string name="login_header_default">Zaloguj się za pomocą konta ucznia lub rodzica</string> <string name="login_header_default">Zaloguj się za pomocą konta ucznia lub rodzica</string>
<string name="login_header_symbol">Podaj symbol</string> <string name="login_header_symbol">Podaj symbol ze strony dziennika</string>
<string name="login_nickname_hint">Nazwa użytkownika</string> <string name="login_nickname_hint">Nazwa użytkownika</string>
<string name="login_email_hint">Email</string> <string name="login_email_hint">Email</string>
<string name="login_login_pesel_email_hint">Login, PESEL lub e-mail</string> <string name="login_login_pesel_email_hint">Login, PESEL lub e-mail</string>
<string name="login_password_hint">Hasło</string> <string name="login_password_hint">Hasło</string>
<string name="login_host_hint">Dziennik UONET+</string> <string name="login_host_hint">Odmiana dziennika UONET+</string>
<string name="login_type_api">Mobilne API</string> <string name="login_type_api">Mobilne API</string>
<string name="login_type_scrapper">Scraper</string> <string name="login_type_scrapper">Scraper</string>
<string name="login_type_hybrid">Hybrydowe</string> <string name="login_type_hybrid">Hybrydowe</string>
@ -37,17 +37,17 @@
<string name="login_symbol_hint">Symbol</string> <string name="login_symbol_hint">Symbol</string>
<string name="login_sign_in">Zaloguj</string> <string name="login_sign_in">Zaloguj</string>
<string name="login_invalid_password">To hasło jest za krótkie</string> <string name="login_invalid_password">To hasło jest za krótkie</string>
<string name="login_incorrect_password">Dane logowania są niepoprawne. Upewnij się, że został wybrany odpowiedni dziennik UONET+ w polu poniżej</string> <string name="login_incorrect_password">Dane logowania są niepoprawne. Upewnij się, że została wybrana odpowiednia odmiana dziennika UONET+ w polu poniżej</string>
<string name="login_invalid_pin">Nieprawidłowy PIN</string> <string name="login_invalid_pin">Nieprawidłowy PIN</string>
<string name="login_invalid_token">Nieprawidłowy token</string> <string name="login_invalid_token">Nieprawidłowy token</string>
<string name="login_expired_token">Token stracił ważność</string> <string name="login_expired_token">Token stracił ważność</string>
<string name="login_invalid_email">Niepoprawny adres email</string> <string name="login_invalid_email">Niepoprawny adres email</string>
<string name="login_invalid_login">Niepoprawny login</string> <string name="login_invalid_login">Użyj przydzielonego loginu zamiast emaila</string>
<string name="login_invalid_symbol">Niepoprawny symbol</string> <string name="login_invalid_symbol">Niepoprawny symbol</string>
<string name="login_incorrect_symbol">Nie znaleziono ucznia. Sprawdź symbol</string> <string name="login_incorrect_symbol">Nie znaleziono ucznia. Sprawdź poprawność symbolu i wybranej odmiany dziennika UONET+</string>
<string name="login_field_required">To pole jest wymagane</string> <string name="login_field_required">To pole jest wymagane</string>
<string name="login_duplicate_student">Wybrany uczeń jest już zalogowany</string> <string name="login_duplicate_student">Wybrany uczeń jest już zalogowany</string>
<string name="login_symbol_helper">Symbol znajdziesz na stronie dziennika w&#160;<b>Uczeń</b>&#160;<b>Dostęp Mobilny</b>&#160;<b>Zarejestruj urządzenie mobilne</b>.\n\nUpewnij się, że w polu <b>Dziennik UONET+</b> na poprzednim ekranie został ustawiony odpowiedni dziennik</string> <string name="login_symbol_helper">Symbol znajdziesz na stronie dziennika w&#160;<b>Uczeń</b>&#160;<b>Dostęp Mobilny</b>&#160;<b>Zarejestruj urządzenie mobilne</b>.\n\nUpewnij się, że w polu <b>Dziennik UONET+</b> na poprzednim ekranie została ustawiona odpowiednia odmiana dziennika. Wulkanowy na chwilę obecną nie wykrywa uczniów przedszkolnych</string>
<string name="login_select_student">Wybierz uczniów do zalogowania w aplikacji</string> <string name="login_select_student">Wybierz uczniów do zalogowania w aplikacji</string>
<string name="login_advanced">Inne opcje</string> <string name="login_advanced">Inne opcje</string>
<string name="login_advanced_warning_mobile_api">W tym trybie nie działa szczęśliwy numerek, uczeń na tle klasy, podsumowanie frekwencji, usprawiedliwianie nieobecności, lekcje zrealizowane, informacje o szkole i podgląd listy zarejestrowanych urządzeń</string> <string name="login_advanced_warning_mobile_api">W tym trybie nie działa szczęśliwy numerek, uczeń na tle klasy, podsumowanie frekwencji, usprawiedliwianie nieobecności, lekcje zrealizowane, informacje o szkole i podgląd listy zarejestrowanych urządzeń</string>
@ -59,7 +59,7 @@
<string name="login_contact_discord">Discord</string> <string name="login_contact_discord">Discord</string>
<string name="login_email_intent_title">Wyślij email</string> <string name="login_email_intent_title">Wyślij email</string>
<string name="login_email_details">Opisz problem:</string> <string name="login_email_details">Opisz problem:</string>
<string name="login_recover_warning">Upewnij się, że został wybrany odpowiedni dziennik UONET+!</string> <string name="login_recover_warning">Upewnij się, że została wybrana odpowiednia odmiana dziennika UONET+!</string>
<string name="login_recover_button">Nie pamiętam hasła</string> <string name="login_recover_button">Nie pamiętam hasła</string>
<string name="login_recover_title">Przywróć swoje konto</string> <string name="login_recover_title">Przywróć swoje konto</string>
<string name="login_recover">Przywróć</string> <string name="login_recover">Przywróć</string>
@ -168,7 +168,7 @@
<string name="attendance_excused_lateness">Spóźnienie usprawiedliwione</string> <string name="attendance_excused_lateness">Spóźnienie usprawiedliwione</string>
<string name="attendance_unexcused_lateness">Spóźnienie nieusprawiedliwione</string> <string name="attendance_unexcused_lateness">Spóźnienie nieusprawiedliwione</string>
<string name="attendance_present">Obecność</string> <string name="attendance_present">Obecność</string>
<string name="attendance_deleted">Usunięty</string> <string name="attendance_deleted">Usunięto</string>
<string name="attendance_unknown">Nieznany</string> <string name="attendance_unknown">Nieznany</string>
<string name="attendance_number">Numer lekcji</string> <string name="attendance_number">Numer lekcji</string>
<string name="attendance_no_items">Brak wpisów</string> <string name="attendance_no_items">Brak wpisów</string>
@ -326,6 +326,9 @@
<string name="teachers_title">Nauczyciele</string> <string name="teachers_title">Nauczyciele</string>
<string name="teacher_no_items">Brak informacji o nauczycielach</string> <string name="teacher_no_items">Brak informacji o nauczycielach</string>
<string name="teacher_no_subject">Brak przedmiotu</string> <string name="teacher_no_subject">Brak przedmiotu</string>
<!--Conference-->
<string name="conferences_title">Zebrania</string>
<string name="conference_no_items">Brak informacji o zebraniach</string>
<!--Account--> <!--Account-->
<string name="account_add_new">Dodaj konto</string> <string name="account_add_new">Dodaj konto</string>
<string name="account_logout">Wyloguj</string> <string name="account_logout">Wyloguj</string>
@ -345,6 +348,8 @@
<string name="about_faq_summary">Zobacz Najczęściej Zadawane Pytania</string> <string name="about_faq_summary">Zobacz Najczęściej Zadawane Pytania</string>
<string name="about_discord">Serwer Discord</string> <string name="about_discord">Serwer Discord</string>
<string name="about_discord_summary">Dołącz do społeczności Wulkanowego</string> <string name="about_discord_summary">Dołącz do społeczności Wulkanowego</string>
<string name="about_facebook">Fanpage na Facebooku</string>
<string name="about_facebook_summary">Polub nasz fanpage na Facebooku</string>
<string name="about_privacy">Polityka prywatności</string> <string name="about_privacy">Polityka prywatności</string>
<string name="about_privacy_summary">Zasady zbierania danych osobowych</string> <string name="about_privacy_summary">Zasady zbierania danych osobowych</string>
<string name="about_homepage">Strona domowa</string> <string name="about_homepage">Strona domowa</string>
@ -398,9 +403,9 @@
<string name="pref_view_timetable_show_groups">Pokazuj grupę obok przedmiotu na planie</string> <string name="pref_view_timetable_show_groups">Pokazuj grupę obok przedmiotu na planie</string>
<string name="pref_view_grade_statistics_list">Pokazuj listę wykresów w ocenach klasy</string> <string name="pref_view_grade_statistics_list">Pokazuj listę wykresów w ocenach klasy</string>
<string name="pref_view_timetable_show_whole_class">Pokazuj lekcje całej klasy</string> <string name="pref_view_timetable_show_whole_class">Pokazuj lekcje całej klasy</string>
<string name="pref_view_subjects_without_grades">Pokazuj przedmioty bez ocen w Oceny</string> <string name="pref_view_subjects_without_grades">Pokazuj przedmioty bez ocen w Ocenach</string>
<string name="pref_view_grade_color_scheme">Schemat kolorów ocen</string> <string name="pref_view_grade_color_scheme">Schemat kolorów ocen</string>
<string name="pref_view_grade_sorting_mode">Sortowanie przedmiotów w \"Oceny\"</string> <string name="pref_view_grade_sorting_mode">Sortowanie przedmiotów w Ocenach</string>
<string name="pref_view_app_language">Język aplikacji</string> <string name="pref_view_app_language">Język aplikacji</string>
<string name="pref_notify_header">Powiadomienia</string> <string name="pref_notify_header">Powiadomienia</string>
<string name="pref_notify_switch">Pokazuj powiadomienia</string> <string name="pref_notify_switch">Pokazuj powiadomienia</string>
@ -445,14 +450,19 @@
<!--Others--> <!--Others-->
<string name="all_copied">Skopiowano</string> <string name="all_copied">Skopiowano</string>
<string name="all_undo">Cofnij</string> <string name="all_undo">Cofnij</string>
<!--Update helper-->
<string name="update_download_started">Rozpoczęto pobieranie aktualizacji…</string>
<string name="update_download_success">Aktualizacja została pobrana.</string>
<string name="update_download_success_button">Uruchom ponownie</string>
<string name="update_failed">Aktualizacja nie powiodła się! Wulkanowy może nie działać prawidłowo. Rozważ aktualizację</string>
<!--Errors--> <!--Errors-->
<string name="error_no_internet">Brak połączenia z internetem</string> <string name="error_no_internet">Brak połączenia z internetem</string>
<string name="error_timeout">Upłynął limit czasu na połączenie z dziennikiem</string> <string name="error_timeout">Nie udało się połączyć z dziennikiem. Serwery mogą być przeciążone. Spróbuj ponownie później</string>
<string name="error_login_failed">Logowanie nie powiodło się. Spróbuj ponownie</string> <string name="error_login_failed">Ładowanie danych nie powiodło się. Spróbuj ponownie później</string>
<string name="error_password_change_required">Wymagana zmiana hasła</string> <string name="error_password_change_required">Wymagana zmiana hasła do dziennika</string>
<string name="error_service_unavailable">Trwa przerwa techniczna dziennika UONET+. Spróbuj ponownie później</string> <string name="error_service_unavailable">Trwa przerwa techniczna dziennika UONET+. Spróbuj ponownie później</string>
<string name="error_unknown_uonet">Wystąpił nieznany błąd dziennika UONET+. Spróbuj ponownie później</string> <string name="error_unknown_uonet">Nieznany błąd dziennika UONET+. Spróbuj ponownie później</string>
<string name="error_unknown_app">Wystąpił nieznany błąd aplikacji</string> <string name="error_unknown_app">Nieznany błąd aplikacji. Spróbuj ponownie później</string>
<string name="error_unknown">Wystąpił nieoczekiwany błąd</string> <string name="error_unknown">Wystąpił nieoczekiwany błąd</string>
<string name="error_feature_disabled">Funkcja wyłączona przez szkołę</string> <string name="error_feature_disabled">Funkcja wyłączona przez szkołę</string>
<string name="error_feature_not_available">Funkcja niedostępna. Zaloguj się w trybie innym niż Mobilne API</string> <string name="error_feature_not_available">Funkcja niedostępna. Zaloguj się w trybie innym niż Mobilne API</string>

View File

@ -22,12 +22,12 @@
<string name="grade_subtitle">%1$d семестр, %2$d/%3$d</string> <string name="grade_subtitle">%1$d семестр, %2$d/%3$d</string>
<!--Login--> <!--Login-->
<string name="login_header_default">Авторизируйтесь при помощи аккаунта ученика или родителя</string> <string name="login_header_default">Авторизируйтесь при помощи аккаунта ученика или родителя</string>
<string name="login_header_symbol">Впишите \"symbol\"</string> <string name="login_header_symbol">Введите символ со страницы регистрации</string>
<string name="login_nickname_hint">Имя пользователя</string> <string name="login_nickname_hint">Имя пользователя</string>
<string name="login_email_hint">Электронная почта</string> <string name="login_email_hint">Электронная почта</string>
<string name="login_login_pesel_email_hint">Логин, PESEL или электронная почта</string> <string name="login_login_pesel_email_hint">Логин, PESEL или электронная почта</string>
<string name="login_password_hint">Пароль</string> <string name="login_password_hint">Пароль</string>
<string name="login_host_hint">Дневник UONET+</string> <string name="login_host_hint">Разновидностью бревна UONET+</string>
<string name="login_type_api">Mobile API</string> <string name="login_type_api">Mobile API</string>
<string name="login_type_scrapper">Scraper</string> <string name="login_type_scrapper">Scraper</string>
<string name="login_type_hybrid">Hybrid</string> <string name="login_type_hybrid">Hybrid</string>
@ -37,17 +37,17 @@
<string name="login_symbol_hint">Symbol</string> <string name="login_symbol_hint">Symbol</string>
<string name="login_sign_in">Войти</string> <string name="login_sign_in">Войти</string>
<string name="login_invalid_password">Слишком короткий пароль</string> <string name="login_invalid_password">Слишком короткий пароль</string>
<string name="login_incorrect_password">Указаны неверные данные. Убедитесь, что вы выбрали нужный дневник</string> <string name="login_incorrect_password">Данные для входа неверны. Убедитесь, что в поле ниже выбран правильный вариант регистра UONET+</string>
<string name="login_invalid_pin">Неправильный PIN</string> <string name="login_invalid_pin">Неправильный PIN</string>
<string name="login_invalid_token">Неправильный token</string> <string name="login_invalid_token">Неправильный token</string>
<string name="login_expired_token">Токен просрочен</string> <string name="login_expired_token">Токен просрочен</string>
<string name="login_invalid_email">Неверный адрес электронной почты</string> <string name="login_invalid_email">Неверный адрес электронной почты</string>
<string name="login_invalid_login">Неправильный логин</string> <string name="login_invalid_login">Используйте назначенный логин вместо электронной почты</string>
<string name="login_invalid_symbol">Неправильный symbol</string> <string name="login_invalid_symbol">Неправильный symbol</string>
<string name="login_incorrect_symbol">Не удалось найти ученика. Проверьте \"symbol\"</string> <string name="login_incorrect_symbol">Студент не найден. Подтвердите символ и выбранный вариант регистра UONET+</string>
<string name="login_field_required">Обязательное поле</string> <string name="login_field_required">Обязательное поле</string>
<string name="login_duplicate_student">Данный ученик уже авторизован</string> <string name="login_duplicate_student">Данный ученик уже авторизован</string>
<string name="login_symbol_helper">Вы можете найти \"symbol\" на странице VULCAN по пути <b>Uczeń</b> →&#160;<b>Dostęp Mobilny</b>&#160;<b>Zarejestruj urządzenie mobilne</b></string> <string name="login_symbol_helper">Этот символ можно найти на странице регистрации в &#160;<b>Uczeń</b>&#160;<b>Dostęp Mobilny</b> &#160;<b>Zarejestruj urządzenie mobilne</b>.\n\nУбедитесь, что вы установили соответствующий вариант регистра в поле <b>Разновидностью бревна UONET+</b> на предыдущем экране. Wulkanowy на данный момент не обнаруживает дошкольников</string>
<string name="login_select_student">Выберите учеников для авторизации в приложении</string> <string name="login_select_student">Выберите учеников для авторизации в приложении</string>
<string name="login_advanced">Другие варианты</string> <string name="login_advanced">Другие варианты</string>
<string name="login_advanced_warning_mobile_api">В этом режиме не работают: счастливый номер, статистика класса по оценкам, статистика посещаемости и уроков, информация о школе и список зарегистрированных устройств</string> <string name="login_advanced_warning_mobile_api">В этом режиме не работают: счастливый номер, статистика класса по оценкам, статистика посещаемости и уроков, информация о школе и список зарегистрированных устройств</string>
@ -59,7 +59,7 @@
<string name="login_contact_discord">Discord</string> <string name="login_contact_discord">Discord</string>
<string name="login_email_intent_title">Отправить письмо</string> <string name="login_email_intent_title">Отправить письмо</string>
<string name="login_email_details">Опишите детали проблемы:</string> <string name="login_email_details">Опишите детали проблемы:</string>
<string name="login_recover_warning">Убедитесь, что выбран нужный дневник!</string> <string name="login_recover_warning">Убедитесь, что вы выбрали правильный вариант регистра UONET+!</string>
<string name="login_recover_button">Забыли пароль?</string> <string name="login_recover_button">Забыли пароль?</string>
<string name="login_recover_title">Восстановите свой аккаунт</string> <string name="login_recover_title">Восстановите свой аккаунт</string>
<string name="login_recover">Восстановить</string> <string name="login_recover">Восстановить</string>
@ -326,6 +326,9 @@
<string name="teachers_title">Учителя</string> <string name="teachers_title">Учителя</string>
<string name="teacher_no_items">Нет информации о учителях</string> <string name="teacher_no_items">Нет информации о учителях</string>
<string name="teacher_no_subject">Нет предмета</string> <string name="teacher_no_subject">Нет предмета</string>
<!--Conference-->
<string name="conferences_title">Встречи</string>
<string name="conference_no_items">Нет информации о встречах</string>
<!--Account--> <!--Account-->
<string name="account_add_new">Добавить аккаунт</string> <string name="account_add_new">Добавить аккаунт</string>
<string name="account_logout">Выйти</string> <string name="account_logout">Выйти</string>
@ -345,6 +348,8 @@
<string name="about_faq_summary">Часто задаваемые вопросы</string> <string name="about_faq_summary">Часто задаваемые вопросы</string>
<string name="about_discord">Сервер Discord</string> <string name="about_discord">Сервер Discord</string>
<string name="about_discord_summary">Присоединиться к сообществу приложения</string> <string name="about_discord_summary">Присоединиться к сообществу приложения</string>
<string name="about_facebook">Facebook фан-страница</string>
<string name="about_facebook_summary">Поставьте лайк на нашей странице в Facebook</string>
<string name="about_privacy">Политика приватности</string> <string name="about_privacy">Политика приватности</string>
<string name="about_privacy_summary">Правила хранения личных данных</string> <string name="about_privacy_summary">Правила хранения личных данных</string>
<string name="about_homepage">Домашняя страница</string> <string name="about_homepage">Домашняя страница</string>
@ -445,12 +450,19 @@
<!--Others--> <!--Others-->
<string name="all_copied">Скопировано</string> <string name="all_copied">Скопировано</string>
<string name="all_undo">Отменить</string> <string name="all_undo">Отменить</string>
<!--Update helper-->
<string name="update_download_started">Загрузка обновлений началась…</string>
<string name="update_download_success">Только что было скачано обновление.</string>
<string name="update_download_success_button">Перезапустить</string>
<string name="update_failed">Не удалось обновить! Wulkanowy может работать некорректно. Рассмотрите возможность обновления</string>
<!--Errors--> <!--Errors-->
<string name="error_no_internet">Нет интернет-подключения</string> <string name="error_no_internet">Нет интернет-подключения</string>
<string name="error_timeout">Слишком долгое ожидание соединения с дневником</string> <string name="error_timeout">Не удалось подключиться к регистрации. Серверы могут быть перегружены. Пожалуйста, повторите попытку позже</string>
<string name="error_login_failed">Авторизация не удалась. Попробуйте ещё раз или перезапустите дневник</string> <string name="error_login_failed">Не удалось загрузить данные. Пожалуйста, повторите попытку позже</string>
<string name="error_password_change_required">Требуется смена пароля</string> <string name="error_password_change_required">Необходимо изменить пароль реестра</string>
<string name="error_service_unavailable">Технический перерыв в журнале UONET + продолжается. Попробуйте позже</string> <string name="error_service_unavailable">Технический перерыв в журнале UONET + продолжается. Попробуйте позже</string>
<string name="error_unknown_uonet">Неизвестная ошибка UONET + регистр. Попробуйте позже</string>
<string name="error_unknown_app">Неизвестная ошибка приложения. Пожалуйста, повторите попытку позже</string>
<string name="error_unknown">Произошла неожиданная ошибка</string> <string name="error_unknown">Произошла неожиданная ошибка</string>
<string name="error_feature_disabled">Функция была выключена школой</string> <string name="error_feature_disabled">Функция была выключена школой</string>
<string name="error_feature_not_available">Функция не доступна в этом режиме</string> <string name="error_feature_not_available">Функция не доступна в этом режиме</string>

View File

@ -31,8 +31,8 @@
<item>0,75</item> <item>0,75</item>
</string-array> </string-array>
<string-array name="grade_sorting_mode_entries"> <string-array name="grade_sorting_mode_entries">
<item>Alphabetic</item> <item>За алфавітом</item>
<item>By date</item> <item>За датою</item>
</string-array> </string-array>
<string-array name="grade_color_scheme_entries"> <string-array name="grade_color_scheme_entries">
<item>Dzienniczek+</item> <item>Dzienniczek+</item>
@ -41,8 +41,8 @@
</string-array> </string-array>
<string-array name="grade_average_mode_entries"> <string-array name="grade_average_mode_entries">
<item>Середня оцінка з 2 семестру</item> <item>Середня оцінка з 2 семестру</item>
<item>Average of grades from both semesters</item> <item>Середнє оцінювання за обидва семестри</item>
<item>Average of grades from the whole year</item> <item>Середнє оцінювання за весь рік</item>
</string-array> </string-array>
<string-array name="timetable_show_whole_class_entries"> <string-array name="timetable_show_whole_class_entries">
<item>Не показувати</item> <item>Не показувати</item>

View File

@ -22,12 +22,12 @@
<string name="grade_subtitle">%1$d семестр, %2$d/%3$d</string> <string name="grade_subtitle">%1$d семестр, %2$d/%3$d</string>
<!--Login--> <!--Login-->
<string name="login_header_default">Авторизуйтеся за допомогою аккаунта учня або батька</string> <string name="login_header_default">Авторизуйтеся за допомогою аккаунта учня або батька</string>
<string name="login_header_symbol">Впишіть \"symbol\"</string> <string name="login_header_symbol">Введіть символ зі сторінки реєстру</string>
<string name="login_nickname_hint">Ім\'я користувача</string> <string name="login_nickname_hint">Ім\'я користувача</string>
<string name="login_email_hint">Електронна пошта</string> <string name="login_email_hint">Електронна пошта</string>
<string name="login_login_pesel_email_hint">Логін, PESEL або електронна пошта</string> <string name="login_login_pesel_email_hint">Логін, PESEL або електронна пошта</string>
<string name="login_password_hint">Пароль</string> <string name="login_password_hint">Пароль</string>
<string name="login_host_hint">Щоденник</string> <string name="login_host_hint">UONET + варіант реєстрації</string>
<string name="login_type_api">Мobile API</string> <string name="login_type_api">Мobile API</string>
<string name="login_type_scrapper">Scraper</string> <string name="login_type_scrapper">Scraper</string>
<string name="login_type_hybrid">Hybrid</string> <string name="login_type_hybrid">Hybrid</string>
@ -37,17 +37,17 @@
<string name="login_symbol_hint">Symbol</string> <string name="login_symbol_hint">Symbol</string>
<string name="login_sign_in">Увійти</string> <string name="login_sign_in">Увійти</string>
<string name="login_invalid_password">Занадто короткий пароль</string> <string name="login_invalid_password">Занадто короткий пароль</string>
<string name="login_incorrect_password">Вказані невірні дані. Впевніться, що ви увібрали потрібний щоденник</string> <string name="login_incorrect_password">Дані для входу неправильні. Переконайтеся, що у полі нижче вказано правильний варіант реєстрації UONET+</string>
<string name="login_invalid_pin">Неправильний PIN</string> <string name="login_invalid_pin">Неправильний PIN</string>
<string name="login_invalid_token">Неправильний token</string> <string name="login_invalid_token">Неправильний token</string>
<string name="login_expired_token">Минув термін дії токену</string> <string name="login_expired_token">Минув термін дії токену</string>
<string name="login_invalid_email">Недійсна адреса електронної пошти</string> <string name="login_invalid_email">Недійсна адреса електронної пошти</string>
<string name="login_invalid_login">Неправильний логін</string> <string name="login_invalid_login">Використовуйте призначений логін замість електронної пошти</string>
<string name="login_invalid_symbol">Неправильний symbol</string> <string name="login_invalid_symbol">Неправильний symbol</string>
<string name="login_incorrect_symbol">Не вдалося знайти учня. Будь ласка, перевірте \"symbol\"</string> <string name="login_incorrect_symbol">Студента не знайдено Перевірте символ та обраний варіант реєстру UONET+</string>
<string name="login_field_required">Обов\'язкове поле</string> <string name="login_field_required">Обов\'язкове поле</string>
<string name="login_duplicate_student">Даного учня вже авторизовано</string> <string name="login_duplicate_student">Даного учня вже авторизовано</string>
<string name="login_symbol_helper">Ви можете знайти \"symbol\" на сторінцi VULCAN стежкою <b>Uczeń</b> →&#160;<b>Dostęp Mobilny</b>&#160;<b>Zarejestruj urządzenie mobilne</b></string> <string name="login_symbol_helper">Символ можна знайти на сторінці реєстру в &#160; <b> Uczeń </b>&#160; <b> Dostęp Mobilny </b> &#160; <b> Zarejestruj urządzenie mobilne </b>.\n\nПереконайтесь, що ви встановили відповідний варіант реєстру в полі <b> UONET + варіант реєстрації </b> на попередньому екрані. На даний момент Wulkanowy не виявляє учнів дошкільних закладів</string>
<string name="login_select_student">Виберіть учнів для авторизації в додатку</string> <string name="login_select_student">Виберіть учнів для авторизації в додатку</string>
<string name="login_advanced">Інші варіанти</string> <string name="login_advanced">Інші варіанти</string>
<string name="login_advanced_warning_mobile_api">У цьому режимі не працюють: щасливий номер, статистика класу по оцінкам, статистика відвідуваності і уроків, інформація про школу і список зареєстрованних пристроїв</string> <string name="login_advanced_warning_mobile_api">У цьому режимі не працюють: щасливий номер, статистика класу по оцінкам, статистика відвідуваності і уроків, інформація про школу і список зареєстрованних пристроїв</string>
@ -59,7 +59,7 @@
<string name="login_contact_discord">Discord</string> <string name="login_contact_discord">Discord</string>
<string name="login_email_intent_title">Відправити лист</string> <string name="login_email_intent_title">Відправити лист</string>
<string name="login_email_details">Опишіть деталі помилки:</string> <string name="login_email_details">Опишіть деталі помилки:</string>
<string name="login_recover_warning">Переконайтесь, що обрано потрібний щоденник!</string> <string name="login_recover_warning">Переконайтеся, що ви вибрали правильний варіант реєстрації UONET+!</string>
<string name="login_recover_button">Забули пароль?</string> <string name="login_recover_button">Забули пароль?</string>
<string name="login_recover_title">Відновіть свій аккаунт</string> <string name="login_recover_title">Відновіть свій аккаунт</string>
<string name="login_recover">Відновити</string> <string name="login_recover">Відновити</string>
@ -108,16 +108,16 @@
<item quantity="other">Нові оцінки</item> <item quantity="other">Нові оцінки</item>
</plurals> </plurals>
<plurals name="grade_new_items_predicted"> <plurals name="grade_new_items_predicted">
<item quantity="one">New predicted grade</item> <item quantity="one">Нова прогнозована оцінка</item>
<item quantity="few">New predicted grades</item> <item quantity="few">Нові прогнозовані оцінки</item>
<item quantity="many">New predicted grades</item> <item quantity="many">Нові прогнозовані оцінки</item>
<item quantity="other">New predicted grades</item> <item quantity="other">Нові прогнозовані оцінки</item>
</plurals> </plurals>
<plurals name="grade_new_items_final"> <plurals name="grade_new_items_final">
<item quantity="one">New final grade</item> <item quantity="one">Нова підсумкова оцінка</item>
<item quantity="few">New final grades</item> <item quantity="few">Нові підсумкові оцінки</item>
<item quantity="many">New final grades</item> <item quantity="many">Нові підсумкові оцінки</item>
<item quantity="other">New final grades</item> <item quantity="other">Нові підсумкові оцінки</item>
</plurals> </plurals>
<plurals name="grade_notify_new_items"> <plurals name="grade_notify_new_items">
<item quantity="one">Ви отримали %1$d оцінку</item> <item quantity="one">Ви отримали %1$d оцінку</item>
@ -126,16 +126,16 @@
<item quantity="other">Ви отримали %1$d оцінок</item> <item quantity="other">Ви отримали %1$d оцінок</item>
</plurals> </plurals>
<plurals name="grade_notify_new_items_predicted"> <plurals name="grade_notify_new_items_predicted">
<item quantity="one">You received %1$d predicted grade</item> <item quantity="one">Ви отримали %1$d нову прогнозовану оцінку</item>
<item quantity="few">You received %1$d predicted grades</item> <item quantity="few">Ви отримали %1$d нові прогнозовані оцінки</item>
<item quantity="many">You received %1$d predicted grades</item> <item quantity="many">Ви отримали %1$d нових прогнозованих оцінок</item>
<item quantity="other">You received %1$d predicted grades</item> <item quantity="other">Ви отримали %1$d нових прогнозованих оцінок</item>
</plurals> </plurals>
<plurals name="grade_notify_new_items_final"> <plurals name="grade_notify_new_items_final">
<item quantity="one">You received %1$d final grade</item> <item quantity="one">Ви отримали %1$d нову підсумкову оцінку</item>
<item quantity="few">You received %1$d final grades</item> <item quantity="few">Ви отримали %1$d нові підсумкові оцінки</item>
<item quantity="many">You received %1$d final grades</item> <item quantity="many">Ви отримали %1$d нових підсумкових оцінок</item>
<item quantity="other">You received %1$d final grades</item> <item quantity="other">Ви отримали %1$d нових підсумкових оцінок</item>
</plurals> </plurals>
<!--Timetable--> <!--Timetable-->
<string name="timetable_lesson">Урок</string> <string name="timetable_lesson">Урок</string>
@ -168,8 +168,8 @@
<string name="attendance_excused_lateness">Спізнення з поважних причин</string> <string name="attendance_excused_lateness">Спізнення з поважних причин</string>
<string name="attendance_unexcused_lateness">Спізнення з не поважних причин</string> <string name="attendance_unexcused_lateness">Спізнення з не поважних причин</string>
<string name="attendance_present">Присутність</string> <string name="attendance_present">Присутність</string>
<string name="attendance_deleted">Deleted</string> <string name="attendance_deleted">Вилучено</string>
<string name="attendance_unknown">Unknown</string> <string name="attendance_unknown">Невідомо</string>
<string name="attendance_number">Номер уроку</string> <string name="attendance_number">Номер уроку</string>
<string name="attendance_no_items">Брак записів</string> <string name="attendance_no_items">Брак записів</string>
<plurals name="attendance_number_absences"> <plurals name="attendance_number_absences">
@ -206,8 +206,8 @@
<string name="message_move_to_bin">Перемістити у кошик</string> <string name="message_move_to_bin">Перемістити у кошик</string>
<string name="message_delete_forever">Видалити назавжди</string> <string name="message_delete_forever">Видалити назавжди</string>
<string name="message_delete_success">Повідомлення було успішно видалено</string> <string name="message_delete_success">Повідомлення було успішно видалено</string>
<string name="message_share">Share</string> <string name="message_share">Поділіться</string>
<string name="message_print">Print</string> <string name="message_print">Друк</string>
<string name="message_subject">Тема</string> <string name="message_subject">Тема</string>
<string name="message_content">Зміст</string> <string name="message_content">Зміст</string>
<string name="message_send_successful">Повідомлення було успішно відправлено</string> <string name="message_send_successful">Повідомлення було успішно відправлено</string>
@ -254,41 +254,41 @@
</plurals> </plurals>
<!--Praise--> <!--Praise-->
<plurals name="praise_number_item"> <plurals name="praise_number_item">
<item quantity="one">%d praise</item> <item quantity="one">%d похвалили</item>
<item quantity="few">%d praises</item> <item quantity="few">%d похвали</item>
<item quantity="many">%d praises</item> <item quantity="many">%d похвал</item>
<item quantity="other">%d praises</item> <item quantity="other">%d похвал</item>
</plurals> </plurals>
<plurals name="praise_new_items"> <plurals name="praise_new_items">
<item quantity="one">New praise</item> <item quantity="one">Нова похвала</item>
<item quantity="few">New praises</item> <item quantity="few">Нові похвали</item>
<item quantity="many">New praises</item> <item quantity="many">Нові похвали</item>
<item quantity="other">New praises</item> <item quantity="other">Нові похвали</item>
</plurals> </plurals>
<plurals name="praise_notify_new_items"> <plurals name="praise_notify_new_items">
<item quantity="one">You received %1$d praise</item> <item quantity="one">Ви отримали %1$d нову похвалу</item>
<item quantity="few">You received %1$d praises</item> <item quantity="few">Ви отримали %1$d нові похвали</item>
<item quantity="many">You received %1$d praises</item> <item quantity="many">Ви отримали %1$d нових похвал</item>
<item quantity="other">You received %1$d praises</item> <item quantity="other">Ви отримали %1$d нових похвал</item>
</plurals> </plurals>
<!--Neutral notes--> <!--Neutral notes-->
<plurals name="neutral_note_number_item"> <plurals name="neutral_note_number_item">
<item quantity="one">%d neutral note</item> <item quantity="one">%d нейтральна нота</item>
<item quantity="few">%d neutral notes</item> <item quantity="few">%d нейтральні ноти</item>
<item quantity="many">%d neutral notes</item> <item quantity="many">%d нейтральних нот</item>
<item quantity="other">%d neutral notes</item> <item quantity="other">%d нейтральних нот</item>
</plurals> </plurals>
<plurals name="neutral_note_new_items"> <plurals name="neutral_note_new_items">
<item quantity="one">New neutral note</item> <item quantity="one">Нова нейтральна нота</item>
<item quantity="few">New neutral notes</item> <item quantity="few">Нова нейтральна нота</item>
<item quantity="many">New neutral notes</item> <item quantity="many">Нова нейтральна нота</item>
<item quantity="other">New neutral notes</item> <item quantity="other">Нові нейтральні ноти</item>
</plurals> </plurals>
<plurals name="neutral_note_notify_new_items"> <plurals name="neutral_note_notify_new_items">
<item quantity="one">You received %1$d neutral note</item> <item quantity="one">Ви отримали %1$d нову нейтральну ноту</item>
<item quantity="few">You received %1$d neutral notes</item> <item quantity="few">Ви отримали %1$d нові нейтральні ноти</item>
<item quantity="many">You received %1$d neutral notes</item> <item quantity="many">Ви отримали %1$d нових нейтральних нот</item>
<item quantity="other">You received %1$d neutral notes</item> <item quantity="other">Ви отримали %1$d нових нейтральних нот</item>
</plurals> </plurals>
<!--Homework--> <!--Homework-->
<string name="homework_no_items">Брак домашніх завдань</string> <string name="homework_no_items">Брак домашніх завдань</string>
@ -326,15 +326,18 @@
<string name="teachers_title">Вчителі</string> <string name="teachers_title">Вчителі</string>
<string name="teacher_no_items">Брак інформації про вчителів</string> <string name="teacher_no_items">Брак інформації про вчителів</string>
<string name="teacher_no_subject">Брак предмету</string> <string name="teacher_no_subject">Брак предмету</string>
<!--Conference-->
<string name="conferences_title">Зустрічі</string>
<string name="conference_no_items">Немає інформації про зустрічі</string>
<!--Account--> <!--Account-->
<string name="account_add_new">Додати аккаунт</string> <string name="account_add_new">Додати аккаунт</string>
<string name="account_logout">Вийти</string> <string name="account_logout">Вийти</string>
<string name="account_confirm">Ви впевнені, що хочете вийти з цього аккаунту?</string> <string name="account_confirm">Ви впевнені, що хочете вийти з цього аккаунту?</string>
<string name="account_logout_student">Вийти з аккаунту учня</string> <string name="account_logout_student">Вийти з аккаунту учня</string>
<string name="account_type_student">Student account</string> <string name="account_type_student">Студентський рахунок</string>
<string name="account_type_parent">Parent account</string> <string name="account_type_parent">Головний рахунок</string>
<string name="account_login_mobile_api">Mobile API mode</string> <string name="account_login_mobile_api">Режим мобільного API</string>
<string name="account_login_hybrid">Hybrid mode</string> <string name="account_login_hybrid">Гібридний режим</string>
<!--About--> <!--About-->
<string name="about_version">Версія додатка</string> <string name="about_version">Версія додатка</string>
<string name="about_contributor">Розробники</string> <string name="about_contributor">Розробники</string>
@ -345,6 +348,8 @@
<string name="about_faq_summary">Запитання, які часто задають</string> <string name="about_faq_summary">Запитання, які часто задають</string>
<string name="about_discord">Сервер Discord</string> <string name="about_discord">Сервер Discord</string>
<string name="about_discord_summary">Приєднатися до спільноти додатка</string> <string name="about_discord_summary">Приєднатися до спільноти додатка</string>
<string name="about_facebook">Фен-сторінка Facebook</string>
<string name="about_facebook_summary">Вподобати нашу фансторінку у Facebook</string>
<string name="about_privacy">Політика конфіденційності</string> <string name="about_privacy">Політика конфіденційності</string>
<string name="about_privacy_summary">Правила зберігання особистих даних</string> <string name="about_privacy_summary">Правила зберігання особистих даних</string>
<string name="about_homepage">Домашня сторінка</string> <string name="about_homepage">Домашня сторінка</string>
@ -395,12 +400,12 @@
<string name="pref_view_app_theme">Тема додатку</string> <string name="pref_view_app_theme">Тема додатку</string>
<string name="pref_view_expand_grade">Більше оцінок</string> <string name="pref_view_expand_grade">Більше оцінок</string>
<string name="pref_view_timetable_show_timers">Позначити поточний урок у розкладі</string> <string name="pref_view_timetable_show_timers">Позначити поточний урок у розкладі</string>
<string name="pref_view_timetable_show_groups">Show groups next to subjects in timetable</string> <string name="pref_view_timetable_show_groups">Покажіть групи поруч із предметами в розкладі</string>
<string name="pref_view_grade_statistics_list">Показувати діаграми в оцінках класу</string> <string name="pref_view_grade_statistics_list">Показувати діаграми в оцінках класу</string>
<string name="pref_view_timetable_show_whole_class">Показати уроки всього класу</string> <string name="pref_view_timetable_show_whole_class">Показати уроки всього класу</string>
<string name="pref_view_subjects_without_grades">Show subjects without grades in Grades</string> <string name="pref_view_subjects_without_grades">Показуйте предмети без оцінок у оцінках</string>
<string name="pref_view_grade_color_scheme">Схема кольорів оцінок</string> <string name="pref_view_grade_color_scheme">Схема кольорів оцінок</string>
<string name="pref_view_grade_sorting_mode">Subjects sorting in \"Grades\"</string> <string name="pref_view_grade_sorting_mode">Сортування предметів за \"Оцінками\"</string>
<string name="pref_view_app_language">Мова додатку</string> <string name="pref_view_app_language">Мова додатку</string>
<string name="pref_notify_header">Повідомлення</string> <string name="pref_notify_header">Повідомлення</string>
<string name="pref_notify_switch">Показувати повідомлення</string> <string name="pref_notify_switch">Показувати повідомлення</string>
@ -445,12 +450,19 @@
<!--Others--> <!--Others-->
<string name="all_copied">Скопійовано</string> <string name="all_copied">Скопійовано</string>
<string name="all_undo">Відмінити</string> <string name="all_undo">Відмінити</string>
<!--Update helper-->
<string name="update_download_started">Завантаження оновлень розпочато…</string>
<string name="update_download_success">Щойно завантажено оновлення.</string>
<string name="update_download_success_button">Перезапустити</string>
<string name="update_failed">Помилка оновлення! Wulkanowy може не працювати належним чином. Подумайте про оновлення</string>
<!--Errors--> <!--Errors-->
<string name="error_no_internet">Брак з\'єднання з інтернетом</string> <string name="error_no_internet">Брак з\'єднання з інтернетом</string>
<string name="error_timeout">Занадто довге очікування з\'єднання з щоденником</string> <string name="error_timeout">Помилка підключення до реєстрації. Сервери можуть бути перевантажені. Будь-ласка спробуйте пізніше</string>
<string name="error_login_failed">Аутентифікація не вдалася. Спробуйте ще раз або запустіть додаток знову</string> <string name="error_login_failed">Помилка завантаження даних. Будь-ласка спробуйте пізніше</string>
<string name="error_password_change_required">Потрібно змінити пароль</string> <string name="error_password_change_required">Потрібна реєстрація зміни пароля</string>
<string name="error_service_unavailable">Технічна перерва в журналі UONET + продовжується. Спробуйте пізніше</string> <string name="error_service_unavailable">Технічна перерва в журналі UONET + продовжується. Спробуйте пізніше</string>
<string name="error_unknown_uonet">Невідома помилка реєстру UONET+. Спробуйте ще раз пізніше</string>
<string name="error_unknown_app">Невідома помилка програми. Будь-ласка спробуйте пізніше</string>
<string name="error_unknown">Відбулася несподівана помилка</string> <string name="error_unknown">Відбулася несподівана помилка</string>
<string name="error_feature_disabled">Функція вимкнена школою</string> <string name="error_feature_disabled">Функція вимкнена школою</string>
<string name="error_feature_not_available">Функція не доступна в цьому режимі</string> <string name="error_feature_not_available">Функція не доступна в цьому режимі</string>

View File

@ -22,25 +22,25 @@
<item>Fakelog</item> <item>Fakelog</item>
</string-array> </string-array>
<string-array name="hosts_values"> <string-array name="hosts_values">
<item>https://vulcan.net.pl/?standard</item> <item>https://vulcan.net.pl/?email</item>
<item>https://eszkola.opolskie.pl</item> <item>https://eszkola.opolskie.pl</item>
<item>https://edu.gdansk.pl</item> <item>https://edu.gdansk.pl</item>
<item>https://edu.lublin.eu</item> <item>https://edu.lublin.eu</item>
<item>https://umt.tarnow.pl</item> <item>https://umt.tarnow.pl</item>
<item>https://resman.pl</item> <item>https://resman.pl</item>
<item>https://eduportal.koszalin.pl</item> <item>https://eduportal.koszalin.pl</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>https://vulcan.net.pl/</item> <item>https://vulcan.net.pl/?login</item>
<item>http://fakelog.tk/?standard</item> <item>http://fakelog.cf/?email</item>
</string-array> </string-array>
<string-array name="hosts_symbols"> <string-array name="hosts_symbols">
<item>Default</item> <item>Default</item>

View File

@ -78,7 +78,7 @@
</string-array> </string-array>
<string-array name="grade_sorting_mode_entries"> <string-array name="grade_sorting_mode_entries">
<item>Alphabetic</item> <item>Alphabetically</item>
<item>By date</item> <item>By date</item>
</string-array> </string-array>
<string-array name="grade_sorting_mode_values" translatable="false"> <string-array name="grade_sorting_mode_values" translatable="false">

View File

@ -26,12 +26,12 @@
<!--Login--> <!--Login-->
<string name="login_header_default">Sign in with the student or parent account</string> <string name="login_header_default">Sign in with the student or parent account</string>
<string name="login_header_symbol">Enter the symbol</string> <string name="login_header_symbol">Enter the symbol from the register page</string>
<string name="login_nickname_hint">Username</string> <string name="login_nickname_hint">Username</string>
<string name="login_email_hint">Email</string> <string name="login_email_hint">Email</string>
<string name="login_login_pesel_email_hint">Login, PESEL or e-mail</string> <string name="login_login_pesel_email_hint">Login, PESEL or e-mail</string>
<string name="login_password_hint">Password</string> <string name="login_password_hint">Password</string>
<string name="login_host_hint">UONET+ Register</string> <string name="login_host_hint">UONET+ register variant</string>
<string name="login_type_api">Mobile API</string> <string name="login_type_api">Mobile API</string>
<string name="login_type_scrapper">Scraper</string> <string name="login_type_scrapper">Scraper</string>
<string name="login_type_hybrid">Hybrid</string> <string name="login_type_hybrid">Hybrid</string>
@ -41,17 +41,17 @@
<string name="login_symbol_hint">Symbol</string> <string name="login_symbol_hint">Symbol</string>
<string name="login_sign_in">Sign in</string> <string name="login_sign_in">Sign in</string>
<string name="login_invalid_password">Password too short</string> <string name="login_invalid_password">Password too short</string>
<string name="login_incorrect_password">Login details are incorrect. Make sure the correct UONET+ register is selected</string> <string name="login_incorrect_password">Login details are incorrect. Make sure the correct UONET+ register variation is selected in the field below</string>
<string name="login_invalid_pin">Invalid PIN</string> <string name="login_invalid_pin">Invalid PIN</string>
<string name="login_invalid_token">Invalid token</string> <string name="login_invalid_token">Invalid token</string>
<string name="login_expired_token">Token expired</string> <string name="login_expired_token">Token expired</string>
<string name="login_invalid_email">Invalid email</string> <string name="login_invalid_email">Invalid email</string>
<string name="login_invalid_login">Invalid login</string> <string name="login_invalid_login">Use the assigned login instead of email</string>
<string name="login_invalid_symbol">Invalid symbol</string> <string name="login_invalid_symbol">Invalid symbol</string>
<string name="login_incorrect_symbol">Student not found. Check the symbol</string> <string name="login_incorrect_symbol">Student not found. Validate the symbol and the chosen variation of the UONET+ register</string>
<string name="login_field_required">This field is required</string> <string name="login_field_required">This field is required</string>
<string name="login_duplicate_student">Selected student is already logged in</string> <string name="login_duplicate_student">Selected student is already logged in</string>
<string name="login_symbol_helper">The symbol can be found on the register page in&#160;<b>Uczeń</b> →&#160;<b>Dostęp Mobilny</b>&#160;<b>Zarejestruj urządzenie mobilne</b></string> <string name="login_symbol_helper">The symbol can be found on the register page in&#160;<b>Uczeń</b> →&#160;<b>Dostęp Mobilny</b>&#160;<b>Zarejestruj urządzenie mobilne</b>.\n\nMake sure that you have set the appropriate register variant in the <b>UONET+ register variant</b> field on the previous screen. Wulkanowy does not detect pre-school students at the moment</string>
<string name="login_select_student">Select students to log in to the application</string> <string name="login_select_student">Select students to log in to the application</string>
<string name="login_advanced">Other options</string> <string name="login_advanced">Other options</string>
<string name="login_advanced_warning_mobile_api">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</string> <string name="login_advanced_warning_mobile_api">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</string>
@ -65,7 +65,7 @@
<string name="login_email_details">Describe details of problem:</string> <string name="login_email_details">Describe details of problem:</string>
<string name="login_email_subject" translatable="false">Zgłoszenie: Problemy z logowaniem</string> <string name="login_email_subject" translatable="false">Zgłoszenie: Problemy z logowaniem</string>
<string name="login_email_text" translatable="false">Informacje o aplikacji:\n\nUrządzenie: %1$s\nWersja SDK: %2$s\nWersja aplikacji: %3$s\nDodatkowe informacje: %4$s\nOstatni błąd: %5$s\n\nOpis problemu: </string> <string name="login_email_text" translatable="false">Informacje o aplikacji:\n\nUrządzenie: %1$s\nWersja SDK: %2$s\nWersja aplikacji: %3$s\nDodatkowe informacje: %4$s\nOstatni błąd: %5$s\n\nOpis problemu: </string>
<string name="login_recover_warning">Make sure the correct UONET+ register is selected!</string> <string name="login_recover_warning">Make sure you select the correct UONET+ register variation!</string>
<string name="login_recover_button">I forgot my password</string> <string name="login_recover_button">I forgot my password</string>
<string name="login_recover_title">Recover your account</string> <string name="login_recover_title">Recover your account</string>
<string name="login_recover">Recover</string> <string name="login_recover">Recover</string>
@ -325,6 +325,11 @@
<string name="teacher_no_subject">No subject</string> <string name="teacher_no_subject">No subject</string>
<!--Conference-->
<string name="conferences_title">Conferences</string>
<string name="conference_no_items">No info about conferences</string>
<!--Account--> <!--Account-->
<string name="account_add_new">Add account</string> <string name="account_add_new">Add account</string>
<string name="account_logout">Logout</string> <string name="account_logout">Logout</string>
@ -346,6 +351,8 @@
<string name="about_faq_summary">Read Frequently Asked Questions</string> <string name="about_faq_summary">Read Frequently Asked Questions</string>
<string name="about_discord">Discord server</string> <string name="about_discord">Discord server</string>
<string name="about_discord_summary">Join the Wulkanowy community</string> <string name="about_discord_summary">Join the Wulkanowy community</string>
<string name="about_facebook">Facebook fanpage</string>
<string name="about_facebook_summary">Like our facebook fanpage</string>
<string name="about_privacy">Privacy policy</string> <string name="about_privacy">Privacy policy</string>
<string name="about_privacy_summary">Rules for collecting personal data</string> <string name="about_privacy_summary">Rules for collecting personal data</string>
<string name="about_homepage">Homepage</string> <string name="about_homepage">Homepage</string>
@ -473,7 +480,7 @@
<string name="all_undo">Undo</string> <string name="all_undo">Undo</string>
<!--Update helper--> <!--Update helper-->
<string name="update_download_started">Start downloading update…</string> <string name="update_download_started">Download of updates has started</string>
<string name="update_download_success">An update has just been downloaded.</string> <string name="update_download_success">An update has just been downloaded.</string>
<string name="update_download_success_button">Restart</string> <string name="update_download_success_button">Restart</string>
<string name="update_failed">Update failed! Wulkanowy may not function properly. Consider updating</string> <string name="update_failed">Update failed! Wulkanowy may not function properly. Consider updating</string>
@ -481,12 +488,12 @@
<!--Errors--> <!--Errors-->
<string name="error_no_internet">No internet connection</string> <string name="error_no_internet">No internet connection</string>
<string name="error_timeout">Connection to the register timed out</string> <string name="error_timeout">Connection to register failed. Servers can be overloaded. Please try again later</string>
<string name="error_login_failed">Login failed. Try again</string> <string name="error_login_failed">Loading data failed. Please try again later</string>
<string name="error_password_change_required">Password change required</string> <string name="error_password_change_required">Register password change required</string>
<string name="error_service_unavailable">Maintenance underway UONET + register. Try again later</string> <string name="error_service_unavailable">Maintenance underway UONET + register. Try again later</string>
<string name="error_unknown_uonet">Unknown UONET + register error. Try again later</string> <string name="error_unknown_uonet">Unknown UONET + register error. Try again later</string>
<string name="error_unknown_app">Unknown application error</string> <string name="error_unknown_app">Unknown application error. Please try again later</string>
<string name="error_unknown">An unexpected error occurred</string> <string name="error_unknown">An unexpected error occurred</string>
<string name="error_feature_disabled">Feature disabled by your school</string> <string name="error_feature_disabled">Feature disabled by your school</string>
<string name="error_feature_not_available">Feature not available. Login in a mode other than Mobile API</string> <string name="error_feature_not_available">Feature not available. Login in a mode other than Mobile API</string>

View File

@ -9,7 +9,7 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class FirebaseAnalyticsHelper @Inject constructor( class AnalyticsHelper @Inject constructor(
@ApplicationContext private val context: Context @ApplicationContext private val context: Context
) { ) {
@ -30,6 +30,13 @@ class FirebaseAnalyticsHelper @Inject constructor(
} }
fun setCurrentScreen(activity: Activity, name: String?) { fun setCurrentScreen(activity: Activity, name: String?) {
analytics.setCurrentScreen(activity, name, null) analytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, Bundle().apply {
putString(FirebaseAnalytics.Param.SCREEN_NAME, name)
putString(FirebaseAnalytics.Param.SCREEN_CLASS, activity::class.simpleName)
})
}
@Suppress("UNUSED_PARAMETER")
fun popCurrentScreen(name: String?) {
} }
} }

View File

@ -10,7 +10,7 @@ import java.io.InterruptedIOException
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
import java.net.UnknownHostException import java.net.UnknownHostException
class CrashlyticsTree : FormatterPriorityTree(Log.VERBOSE) { class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
private val crashlytics by lazy { FirebaseCrashlytics.getInstance() } private val crashlytics by lazy { FirebaseCrashlytics.getInstance() }
@ -21,7 +21,7 @@ class CrashlyticsTree : FormatterPriorityTree(Log.VERBOSE) {
} }
} }
class CrashlyticsExceptionTree : FormatterPriorityTree(Log.ERROR) { class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR) {
private val crashlytics by lazy { FirebaseCrashlytics.getInstance() } private val crashlytics by lazy { FirebaseCrashlytics.getInstance() }

Some files were not shown because too many files have changed in this diff Show More