forked from github/wulkanowy-mirror
Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
90a5b9e20f | |||
3cf6c295b0 | |||
e757585bd3 | |||
736d16a7ab | |||
6f4a8d5534 | |||
b5e17c4ff7 | |||
cc01525f16 | |||
c2ec05662b | |||
b99ba48d2c | |||
2d4a1bff83 | |||
cd853e4d57 | |||
8183d7d5a0 | |||
3f199cb610 | |||
22f72981cb | |||
bce92b7347 | |||
ed5166333a | |||
a05f1f70f7 | |||
e58a60410c | |||
fc91936884 | |||
88043569ac | |||
10add8a70e | |||
098af9884a | |||
554c1b1261 | |||
496695162d | |||
dc59f4ffa3 | |||
e0f4cad7fb | |||
a51a54dc7a | |||
7cdac6ede1 | |||
9dfb282e88 | |||
725668f855 | |||
e58c155961 | |||
05a5047a70 | |||
1fe464a289 | |||
497acf9d68 | |||
976eb5a772 | |||
9ececeb4e9 | |||
096fe359e7 | |||
a98e8398fd | |||
d8c4926a97 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -65,6 +65,8 @@ captures/
|
||||
.idea/uiDesigner.xml
|
||||
.idea/runConfigurations.xml
|
||||
.idea/discord.xml
|
||||
.idea/migrations.xml
|
||||
.idea/androidTestResultsUserPreferences.xml
|
||||
|
||||
# Keystore files
|
||||
*.jks
|
||||
|
10
.idea/migrations.xml
generated
10
.idea/migrations.xml
generated
@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -27,8 +27,8 @@ android {
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 34
|
||||
versionCode 143
|
||||
versionName "2.3.3"
|
||||
versionCode 147
|
||||
versionName "2.4.1"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
resValue "string", "app_name", "Wulkanowy"
|
||||
@ -142,7 +142,9 @@ android {
|
||||
packagingOptions {
|
||||
resources {
|
||||
excludes += ['META-INF/library_release.kotlin_module',
|
||||
'META-INF/library-core_release.kotlin_module']
|
||||
'META-INF/library-core_release.kotlin_module',
|
||||
'META-INF/LICENSE.md',
|
||||
'META-INF/LICENSE-notice.md']
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,8 +164,8 @@ play {
|
||||
defaultToAppBundles = false
|
||||
track = 'production'
|
||||
releaseStatus = ReleaseStatus.IN_PROGRESS
|
||||
userFraction = 0.99d
|
||||
updatePriority = 3
|
||||
userFraction = 0.50d
|
||||
updatePriority = 1
|
||||
enabled.set(false)
|
||||
}
|
||||
|
||||
@ -193,7 +195,7 @@ ext {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'io.github.wulkanowy:sdk:2.3.5'
|
||||
implementation 'io.github.wulkanowy:sdk:2.4.1'
|
||||
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
|
||||
|
||||
@ -221,7 +223,7 @@ dependencies {
|
||||
implementation "androidx.work:work-runtime:$work_manager"
|
||||
playImplementation "androidx.work:work-gcm:$work_manager"
|
||||
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.7.0"
|
||||
|
||||
implementation "androidx.room:room-runtime:$room"
|
||||
implementation "androidx.room:room-ktx:$room"
|
||||
@ -238,6 +240,7 @@ dependencies {
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:4.12.0"
|
||||
implementation "com.squareup.okhttp3:okhttp-urlconnection:4.12.0"
|
||||
|
||||
implementation "com.jakewharton.timber:timber:5.0.1"
|
||||
implementation 'com.github.Faierbel:slf4j-timber:2.0'
|
||||
@ -249,7 +252,7 @@ dependencies {
|
||||
implementation 'com.fredporciuncula:flow-preferences:1.9.1'
|
||||
implementation 'org.apache.commons:commons-text:1.11.0'
|
||||
|
||||
playImplementation platform('com.google.firebase:firebase-bom:32.7.0')
|
||||
playImplementation platform('com.google.firebase:firebase-bom:32.7.2')
|
||||
playImplementation 'com.google.firebase:firebase-analytics'
|
||||
playImplementation 'com.google.firebase:firebase-messaging'
|
||||
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
||||
@ -259,9 +262,9 @@ dependencies {
|
||||
playImplementation "com.google.android.play:integrity:1.3.0"
|
||||
playImplementation 'com.google.android.play:app-update-ktx:2.1.0'
|
||||
playImplementation 'com.google.android.play:review-ktx:2.0.1'
|
||||
playImplementation "com.google.android.ump:user-messaging-platform:2.1.0"
|
||||
playImplementation "com.google.android.ump:user-messaging-platform:2.2.0"
|
||||
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.12.0.300'
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.12.0.301'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.9.1.303'
|
||||
|
||||
releaseImplementation "com.github.chuckerteam.chucker:library-no-op:$chucker"
|
||||
|
2451
app/schemas/io.github.wulkanowy.data.db.AppDatabase/58.json
Normal file
2451
app/schemas/io.github.wulkanowy.data.db.AppDatabase/58.json
Normal file
File diff suppressed because it is too large
Load Diff
2501
app/schemas/io.github.wulkanowy.data.db.AppDatabase/59.json
Normal file
2501
app/schemas/io.github.wulkanowy.data.db.AppDatabase/59.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,34 +14,37 @@ import kotlin.test.assertFailsWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ScramblerTest {
|
||||
|
||||
private val scrambler = Scrambler(ApplicationProvider.getApplicationContext())
|
||||
|
||||
@Test
|
||||
fun encryptDecryptTest() {
|
||||
assertEquals("TEST", decrypt(encrypt("TEST",
|
||||
ApplicationProvider.getApplicationContext())))
|
||||
assertEquals(
|
||||
"TEST", scrambler.decrypt(scrambler.encrypt("TEST"))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun emptyTextEncryptTest() {
|
||||
assertFailsWith<ScramblerException> {
|
||||
decrypt("")
|
||||
scrambler.decrypt("")
|
||||
}
|
||||
|
||||
assertFailsWith<ScramblerException> {
|
||||
encrypt("", ApplicationProvider.getApplicationContext())
|
||||
scrambler.encrypt("")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SdkSuppress(minSdkVersion = 18)
|
||||
fun emptyKeyStoreTest() {
|
||||
val text = encrypt("test", ApplicationProvider.getApplicationContext())
|
||||
val text = scrambler.encrypt("test")
|
||||
|
||||
val keyStore = KeyStore.getInstance("AndroidKeyStore")
|
||||
keyStore.load(null)
|
||||
keyStore.deleteEntry("wulkanowy_password")
|
||||
|
||||
assertFailsWith<ScramblerException> {
|
||||
decrypt(text)
|
||||
scrambler.decrypt(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:supportsRtl="false"
|
||||
android:theme="@style/WulkanowyTheme"
|
||||
android:resizeableActivity="true"
|
||||
tools:ignore="DataExtractionRules,UnusedAttribute">
|
||||
<activity
|
||||
android:name=".ui.modules.splash.SplashActivity"
|
||||
|
@ -21,6 +21,7 @@ import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.RemoteConfigHelper
|
||||
import io.github.wulkanowy.utils.WebkitCookieManagerProxy
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
@ -43,6 +44,7 @@ internal class DataModule {
|
||||
buildTag = android.os.Build.MODEL
|
||||
userAgentTemplate = remoteConfig.userAgentTemplate
|
||||
setSimpleHttpLogger { Timber.d(it) }
|
||||
setAdditionalCookieManager(WebkitCookieManagerProxy())
|
||||
|
||||
// for debug only
|
||||
addInterceptor(chuckerInterceptor, network = true)
|
||||
@ -251,4 +253,8 @@ internal class DataModule {
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideAdminMessageDao(database: AppDatabase) = database.adminMessagesDao
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideGradeDescriptiveDao(database: AppDatabase) = database.gradeDescriptiveDao
|
||||
}
|
||||
|
@ -1,6 +1,16 @@
|
||||
package io.github.wulkanowy.data
|
||||
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import timber.log.Timber
|
||||
@ -131,7 +141,7 @@ inline fun <ResultType, RequestType> networkBoundResource(
|
||||
query().map { Resource.Success(filterResult(it)) }
|
||||
} catch (throwable: Throwable) {
|
||||
onFetchFailed(throwable)
|
||||
query().map { Resource.Error(throwable) }
|
||||
flowOf(Resource.Error(throwable))
|
||||
}
|
||||
} else {
|
||||
query().map { Resource.Success(filterResult(it)) }
|
||||
@ -165,7 +175,7 @@ inline fun <ResultType, RequestType, T> networkBoundResource(
|
||||
query().map { Resource.Success(mapResult(it)) }
|
||||
} catch (throwable: Throwable) {
|
||||
onFetchFailed(throwable)
|
||||
query().map { Resource.Error(throwable) }
|
||||
flowOf(Resource.Error(throwable))
|
||||
}
|
||||
} else {
|
||||
query().map { Resource.Success(mapResult(it)) }
|
||||
|
@ -1,11 +1,126 @@
|
||||
package io.github.wulkanowy.data.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.*
|
||||
import androidx.room.AutoMigration
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
||||
import io.github.wulkanowy.data.db.dao.*
|
||||
import io.github.wulkanowy.data.db.entities.*
|
||||
import io.github.wulkanowy.data.db.migrations.*
|
||||
import androidx.room.TypeConverters
|
||||
import io.github.wulkanowy.data.db.dao.AdminMessageDao
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
||||
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.GradeDao
|
||||
import io.github.wulkanowy.data.db.dao.GradeDescriptiveDao
|
||||
import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao
|
||||
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
|
||||
import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao
|
||||
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
||||
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
||||
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
|
||||
import io.github.wulkanowy.data.db.dao.MailboxDao
|
||||
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
|
||||
import io.github.wulkanowy.data.db.dao.MessagesDao
|
||||
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
||||
import io.github.wulkanowy.data.db.dao.NoteDao
|
||||
import io.github.wulkanowy.data.db.dao.NotificationDao
|
||||
import io.github.wulkanowy.data.db.dao.RecipientDao
|
||||
import io.github.wulkanowy.data.db.dao.SchoolAnnouncementDao
|
||||
import io.github.wulkanowy.data.db.dao.SchoolDao
|
||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||
import io.github.wulkanowy.data.db.dao.StudentInfoDao
|
||||
import io.github.wulkanowy.data.db.dao.SubjectDao
|
||||
import io.github.wulkanowy.data.db.dao.TeacherDao
|
||||
import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao
|
||||
import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||
import io.github.wulkanowy.data.db.dao.TimetableHeaderDao
|
||||
import io.github.wulkanowy.data.db.entities.AdminMessage
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||
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.Grade
|
||||
import io.github.wulkanowy.data.db.entities.GradeDescriptive
|
||||
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
|
||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||
import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import io.github.wulkanowy.data.db.entities.Note
|
||||
import io.github.wulkanowy.data.db.entities.Notification
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
import io.github.wulkanowy.data.db.entities.School
|
||||
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.db.entities.StudentInfo
|
||||
import io.github.wulkanowy.data.db.entities.Subject
|
||||
import io.github.wulkanowy.data.db.entities.Teacher
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||
import io.github.wulkanowy.data.db.entities.TimetableHeader
|
||||
import io.github.wulkanowy.data.db.migrations.Migration10
|
||||
import io.github.wulkanowy.data.db.migrations.Migration11
|
||||
import io.github.wulkanowy.data.db.migrations.Migration12
|
||||
import io.github.wulkanowy.data.db.migrations.Migration13
|
||||
import io.github.wulkanowy.data.db.migrations.Migration14
|
||||
import io.github.wulkanowy.data.db.migrations.Migration15
|
||||
import io.github.wulkanowy.data.db.migrations.Migration16
|
||||
import io.github.wulkanowy.data.db.migrations.Migration17
|
||||
import io.github.wulkanowy.data.db.migrations.Migration18
|
||||
import io.github.wulkanowy.data.db.migrations.Migration19
|
||||
import io.github.wulkanowy.data.db.migrations.Migration2
|
||||
import io.github.wulkanowy.data.db.migrations.Migration20
|
||||
import io.github.wulkanowy.data.db.migrations.Migration21
|
||||
import io.github.wulkanowy.data.db.migrations.Migration22
|
||||
import io.github.wulkanowy.data.db.migrations.Migration23
|
||||
import io.github.wulkanowy.data.db.migrations.Migration24
|
||||
import io.github.wulkanowy.data.db.migrations.Migration25
|
||||
import io.github.wulkanowy.data.db.migrations.Migration26
|
||||
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.Migration30
|
||||
import io.github.wulkanowy.data.db.migrations.Migration31
|
||||
import io.github.wulkanowy.data.db.migrations.Migration32
|
||||
import io.github.wulkanowy.data.db.migrations.Migration33
|
||||
import io.github.wulkanowy.data.db.migrations.Migration34
|
||||
import io.github.wulkanowy.data.db.migrations.Migration35
|
||||
import io.github.wulkanowy.data.db.migrations.Migration36
|
||||
import io.github.wulkanowy.data.db.migrations.Migration37
|
||||
import io.github.wulkanowy.data.db.migrations.Migration38
|
||||
import io.github.wulkanowy.data.db.migrations.Migration39
|
||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||
import io.github.wulkanowy.data.db.migrations.Migration40
|
||||
import io.github.wulkanowy.data.db.migrations.Migration41
|
||||
import io.github.wulkanowy.data.db.migrations.Migration42
|
||||
import io.github.wulkanowy.data.db.migrations.Migration43
|
||||
import io.github.wulkanowy.data.db.migrations.Migration44
|
||||
import io.github.wulkanowy.data.db.migrations.Migration46
|
||||
import io.github.wulkanowy.data.db.migrations.Migration49
|
||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||
import io.github.wulkanowy.data.db.migrations.Migration50
|
||||
import io.github.wulkanowy.data.db.migrations.Migration51
|
||||
import io.github.wulkanowy.data.db.migrations.Migration53
|
||||
import io.github.wulkanowy.data.db.migrations.Migration54
|
||||
import io.github.wulkanowy.data.db.migrations.Migration55
|
||||
import io.github.wulkanowy.data.db.migrations.Migration57
|
||||
import io.github.wulkanowy.data.db.migrations.Migration58
|
||||
import io.github.wulkanowy.data.db.migrations.Migration6
|
||||
import io.github.wulkanowy.data.db.migrations.Migration7
|
||||
import io.github.wulkanowy.data.db.migrations.Migration8
|
||||
import io.github.wulkanowy.data.db.migrations.Migration9
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -41,7 +156,8 @@ import javax.inject.Singleton
|
||||
TimetableHeader::class,
|
||||
SchoolAnnouncement::class,
|
||||
Notification::class,
|
||||
AdminMessage::class
|
||||
AdminMessage::class,
|
||||
GradeDescriptive::class,
|
||||
],
|
||||
autoMigrations = [
|
||||
AutoMigration(from = 44, to = 45),
|
||||
@ -51,6 +167,8 @@ import javax.inject.Singleton
|
||||
AutoMigration(from = 54, to = 55, spec = Migration55::class),
|
||||
AutoMigration(from = 55, to = 56),
|
||||
AutoMigration(from = 56, to = 57, spec = Migration57::class),
|
||||
AutoMigration(from = 57, to = 58, spec = Migration58::class),
|
||||
AutoMigration(from = 58, to = 59),
|
||||
],
|
||||
version = AppDatabase.VERSION_SCHEMA,
|
||||
exportSchema = true
|
||||
@ -59,7 +177,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 57
|
||||
const val VERSION_SCHEMA = 59
|
||||
|
||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
||||
Migration2(),
|
||||
@ -184,4 +302,6 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
abstract val notificationDao: NotificationDao
|
||||
|
||||
abstract val adminMessagesDao: AdminMessageDao
|
||||
|
||||
abstract val gradeDescriptiveDao: GradeDescriptiveDao
|
||||
}
|
||||
|
@ -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.GradeDescriptive
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Dao
|
||||
interface GradeDescriptiveDao : BaseDao<GradeDescriptive> {
|
||||
|
||||
@Query("SELECT * FROM GradesDescriptive WHERE semester_id = :semesterId AND student_id = :studentId")
|
||||
fun loadAll(semesterId: Int, studentId: Int): Flow<List<GradeDescriptive>>
|
||||
}
|
@ -37,6 +37,9 @@ data class AdminMessage(
|
||||
@ColumnInfo(name = "types", defaultValue = "[]")
|
||||
val types: List<MessageType> = emptyList(),
|
||||
|
||||
@ColumnInfo(name = "is_dismissible")
|
||||
val isDismissible: Boolean = false
|
||||
@ColumnInfo(name = "is_ok_visible", defaultValue = "0")
|
||||
val isOkVisible: Boolean = false,
|
||||
|
||||
@ColumnInfo(name = "is_x_visible", defaultValue = "0")
|
||||
val isXVisible: Boolean = false
|
||||
)
|
||||
|
@ -0,0 +1,27 @@
|
||||
package io.github.wulkanowy.data.db.entities
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
|
||||
@Entity(tableName = "GradesDescriptive")
|
||||
data class GradeDescriptive(
|
||||
|
||||
@ColumnInfo(name = "semester_id")
|
||||
val semesterId: Int,
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
val studentId: Int,
|
||||
|
||||
val subject: String,
|
||||
|
||||
val description: String,
|
||||
) : Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0
|
||||
|
||||
@ColumnInfo(name = "is_notified")
|
||||
var isNotified: Boolean = true
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.DeleteColumn
|
||||
import androidx.room.migration.AutoMigrationSpec
|
||||
|
||||
@DeleteColumn(
|
||||
tableName = "AdminMessages",
|
||||
columnName = "is_dismissible",
|
||||
)
|
||||
class Migration58 : AutoMigrationSpec
|
@ -1,10 +1,12 @@
|
||||
package io.github.wulkanowy.data.mappers
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.GradeDescriptive
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.sdk.pojo.GradeSummary as SdkGradeSummary
|
||||
import io.github.wulkanowy.sdk.pojo.Grade as SdkGrade
|
||||
import io.github.wulkanowy.sdk.pojo.GradeDescriptive as SdkGradeDescriptive
|
||||
import io.github.wulkanowy.sdk.pojo.GradeSummary as SdkGradeSummary
|
||||
|
||||
fun List<SdkGrade>.mapToEntities(semester: Semester) = map {
|
||||
Grade(
|
||||
@ -40,3 +42,15 @@ fun List<SdkGradeSummary>.mapToEntities(semester: Semester) = map {
|
||||
average = it.average
|
||||
)
|
||||
}
|
||||
|
||||
@JvmName("mapGradeDescriptiveToEntities")
|
||||
fun List<SdkGradeDescriptive>.mapToEntities(semester: Semester) = map {
|
||||
GradeDescriptive(
|
||||
semesterId = semester.semesterId,
|
||||
studentId = semester.studentId,
|
||||
subject = it.subject,
|
||||
description = it.description
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,7 +9,13 @@ import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.data.networkBoundResource
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.Absent
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
@ -58,7 +64,7 @@ class AttendanceRepository @Inject constructor(
|
||||
)
|
||||
}
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getAttendance(start.monday, end.sunday)
|
||||
.mapToEntities(semester, lessons)
|
||||
},
|
||||
@ -97,7 +103,7 @@ class AttendanceRepository @Inject constructor(
|
||||
)
|
||||
}
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.excuseForAbsence(items, reason)
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import javax.inject.Inject
|
||||
@ -40,7 +41,7 @@ class AttendanceSummaryRepository @Inject constructor(
|
||||
query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getAttendanceSummary(subjectId)
|
||||
.mapToEntities(semester, subjectId)
|
||||
},
|
||||
|
@ -48,7 +48,7 @@ class CompletedLessonsRepository @Inject constructor(
|
||||
},
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getCompletedLessons(start.monday, end.sunday)
|
||||
.mapToEntities(semester)
|
||||
},
|
||||
|
@ -10,6 +10,7 @@ import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
@ -46,7 +47,7 @@ class ConferenceRepository @Inject constructor(
|
||||
},
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getConferences()
|
||||
.mapToEntities(semester)
|
||||
.filter { it.date >= startDate }
|
||||
|
@ -7,7 +7,13 @@ import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.data.networkBoundResource
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.endExamsDay
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.startExamsDay
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import java.time.LocalDate
|
||||
@ -51,7 +57,7 @@ class ExamRepository @Inject constructor(
|
||||
},
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getExams(start.startExamsDay, start.endExamsDay)
|
||||
.mapToEntities(semester)
|
||||
},
|
||||
@ -67,14 +73,16 @@ class ExamRepository @Inject constructor(
|
||||
filterResult = { it.filter { item -> item.date in start..end } }
|
||||
)
|
||||
|
||||
fun getExamsFromDatabase(semester: Semester, start: LocalDate): Flow<List<Exam>> {
|
||||
return examDb.loadAll(
|
||||
diaryId = semester.diaryId,
|
||||
studentId = semester.studentId,
|
||||
from = start.startExamsDay,
|
||||
end = start.endExamsDay
|
||||
)
|
||||
}
|
||||
fun getExamsFromDatabase(
|
||||
semester: Semester,
|
||||
start: LocalDate,
|
||||
end: LocalDate
|
||||
): Flow<List<Exam>> = examDb.loadAll(
|
||||
diaryId = semester.diaryId,
|
||||
studentId = semester.studentId,
|
||||
from = start,
|
||||
end = end,
|
||||
)
|
||||
|
||||
suspend fun updateExam(exam: List<Exam>) = examDb.updateAll(exam)
|
||||
}
|
||||
|
@ -1,15 +1,22 @@
|
||||
package io.github.wulkanowy.data.repositories
|
||||
|
||||
import io.github.wulkanowy.data.db.dao.GradeDao
|
||||
import io.github.wulkanowy.data.db.dao.GradeDescriptiveDao
|
||||
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.GradeDescriptive
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.data.networkBoundResource
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.toLocalDate
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.map
|
||||
@ -22,14 +29,13 @@ import javax.inject.Singleton
|
||||
class GradeRepository @Inject constructor(
|
||||
private val gradeDb: GradeDao,
|
||||
private val gradeSummaryDb: GradeSummaryDao,
|
||||
private val gradeDescriptiveDb: GradeDescriptiveDao,
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val saveFetchResultMutex = Mutex()
|
||||
|
||||
private val cacheKey = "grade"
|
||||
|
||||
fun getGrades(
|
||||
student: Student,
|
||||
semester: Semester,
|
||||
@ -41,30 +47,52 @@ class GradeRepository @Inject constructor(
|
||||
//When details is empty and summary is not, app will not use summary cache - edge case
|
||||
it.first.isEmpty()
|
||||
},
|
||||
shouldFetch = { (details, summaries) ->
|
||||
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester))
|
||||
details.isEmpty() || summaries.isEmpty() || forceRefresh || isExpired
|
||||
shouldFetch = { (details, summaries, descriptive) ->
|
||||
val isExpired =
|
||||
refreshHelper.shouldBeRefreshed(getRefreshKey(GRADE_CACHE_KEY, semester))
|
||||
details.isEmpty() || (summaries.isEmpty() && descriptive.isEmpty()) || forceRefresh || isExpired
|
||||
},
|
||||
query = {
|
||||
val detailsFlow = gradeDb.loadAll(semester.semesterId, semester.studentId)
|
||||
val summaryFlow = gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)
|
||||
detailsFlow.combine(summaryFlow) { details, summaries -> details to summaries }
|
||||
val descriptiveFlow =
|
||||
gradeDescriptiveDb.loadAll(semester.semesterId, semester.studentId)
|
||||
|
||||
combine(detailsFlow, summaryFlow, descriptiveFlow) { details, summaries, descriptive ->
|
||||
Triple(details, summaries, descriptive)
|
||||
}
|
||||
},
|
||||
fetch = {
|
||||
val (details, summary) = sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
val (details, summary, descriptive) = sdk.init(student)
|
||||
.switchSemester(semester)
|
||||
.getGrades(semester.semesterId)
|
||||
|
||||
details.mapToEntities(semester) to summary.mapToEntities(semester)
|
||||
Triple(
|
||||
details.mapToEntities(semester),
|
||||
summary.mapToEntities(semester),
|
||||
descriptive.mapToEntities(semester)
|
||||
)
|
||||
},
|
||||
saveFetchResult = { (oldDetails, oldSummary), (newDetails, newSummary) ->
|
||||
saveFetchResult = { (oldDetails, oldSummary, oldDescriptive), (newDetails, newSummary, newDescriptive) ->
|
||||
refreshGradeDetails(student, oldDetails, newDetails, notify)
|
||||
refreshGradeSummaries(oldSummary, newSummary, notify)
|
||||
refreshGradeDescriptions(oldDescriptive, newDescriptive, notify)
|
||||
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester))
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(GRADE_CACHE_KEY, semester))
|
||||
}
|
||||
)
|
||||
|
||||
private suspend fun refreshGradeDescriptions(
|
||||
old: List<GradeDescriptive>,
|
||||
new: List<GradeDescriptive>,
|
||||
notify: Boolean
|
||||
) {
|
||||
gradeDescriptiveDb.deleteAll(old uniqueSubtract new)
|
||||
gradeDescriptiveDb.insertAll((new uniqueSubtract old).onEach {
|
||||
if (notify) it.isNotified = false
|
||||
})
|
||||
}
|
||||
|
||||
private suspend fun refreshGradeDetails(
|
||||
student: Student,
|
||||
oldGrades: List<Grade>,
|
||||
@ -132,6 +160,10 @@ class GradeRepository @Inject constructor(
|
||||
return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)
|
||||
}
|
||||
|
||||
fun getGradesDescriptiveFromDatabase(semester: Semester): Flow<List<GradeDescriptive>> {
|
||||
return gradeDescriptiveDb.loadAll(semester.semesterId, semester.studentId)
|
||||
}
|
||||
|
||||
suspend fun updateGrade(grade: Grade) {
|
||||
return gradeDb.updateAll(listOf(grade))
|
||||
}
|
||||
@ -143,4 +175,13 @@ class GradeRepository @Inject constructor(
|
||||
suspend fun updateGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||
return gradeSummaryDb.updateAll(gradesSummary)
|
||||
}
|
||||
|
||||
suspend fun updateGradesDescriptive(gradesDescriptive: List<GradeDescriptive>) {
|
||||
return gradeDescriptiveDb.updateAll(gradesDescriptive)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
private const val GRADE_CACHE_KEY = "grade"
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import java.util.*
|
||||
@ -56,7 +57,7 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getGradesPartialStatistics(semester.semesterId)
|
||||
.mapToEntities(semester)
|
||||
},
|
||||
@ -101,7 +102,7 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getGradesSemesterStatistics(semester.semesterId)
|
||||
.mapToEntities(semester)
|
||||
},
|
||||
@ -157,7 +158,7 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getGradesPointsStatistics(semester.semesterId)
|
||||
.mapToEntities(semester)
|
||||
},
|
||||
|
@ -7,7 +7,13 @@ import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.data.networkBoundResource
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
@ -50,7 +56,7 @@ class HomeworkRepository @Inject constructor(
|
||||
},
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getHomework(start.monday, end.sunday)
|
||||
.mapToEntities(semester)
|
||||
},
|
||||
|
@ -12,6 +12,7 @@ import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import javax.inject.Inject
|
||||
@ -42,7 +43,7 @@ class MobileDeviceRepository @Inject constructor(
|
||||
query = { mobileDb.loadAll(student.userLoginId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getRegisteredDevices()
|
||||
.mapToEntities(student)
|
||||
},
|
||||
@ -56,7 +57,7 @@ class MobileDeviceRepository @Inject constructor(
|
||||
|
||||
suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.unregisterDevice(device.deviceId)
|
||||
|
||||
mobileDb.deleteAll(listOf(device))
|
||||
@ -64,7 +65,7 @@ class MobileDeviceRepository @Inject constructor(
|
||||
|
||||
suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken {
|
||||
return sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getToken()
|
||||
.mapToMobileDeviceToken()
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class NoteRepository @Inject constructor(
|
||||
query = { noteDb.loadAll(student.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getNotes()
|
||||
.mapToEntities(semester)
|
||||
},
|
||||
|
@ -9,6 +9,7 @@ import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -40,7 +41,7 @@ class SchoolRepository @Inject constructor(
|
||||
query = { schoolDb.load(semester.studentId, semester.classId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getSchool()
|
||||
.mapToEntity(semester)
|
||||
},
|
||||
|
@ -11,6 +11,7 @@ import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.utils.IntegrityHelper
|
||||
import io.github.wulkanowy.utils.getCurrentOrLast
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
@ -42,11 +43,7 @@ class SchoolsRepository @Inject constructor(
|
||||
|
||||
val schoolInfo = sdk
|
||||
.init(student.copy(password = loginData.password))
|
||||
.switchDiary(
|
||||
diaryId = semester.diaryId,
|
||||
kindergartenDiaryId = semester.kindergartenDiaryId,
|
||||
schoolYear = semester.schoolYear
|
||||
)
|
||||
.switchSemester(semester)
|
||||
.getSchool()
|
||||
|
||||
schoolsService.logLoginEvent(
|
||||
|
@ -7,6 +7,7 @@ import io.github.wulkanowy.data.mappers.mapToEntity
|
||||
import io.github.wulkanowy.data.networkBoundResource
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -30,7 +31,7 @@ class StudentInfoRepository @Inject constructor(
|
||||
query = { studentInfoDao.loadStudentInfo(student.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getStudentInfo().mapToEntity(semester)
|
||||
},
|
||||
saveFetchResult = { old, new ->
|
||||
|
@ -16,6 +16,7 @@ import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.DispatchersProvider
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.security.Scrambler
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -149,12 +150,12 @@ class StudentRepository @Inject constructor(
|
||||
|
||||
suspend fun authorizePermission(student: Student, semester: Semester, pesel: String) =
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.authorizePermission(pesel)
|
||||
|
||||
suspend fun refreshStudentName(student: Student, semester: Semester) {
|
||||
val newCurrentApiStudent = sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getCurrentStudent() ?: return
|
||||
|
||||
val studentName = StudentName(
|
||||
|
@ -9,6 +9,7 @@ import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import javax.inject.Inject
|
||||
@ -39,8 +40,9 @@ class SubjectRepository @Inject constructor(
|
||||
query = { subjectDao.loadAll(semester.diaryId, semester.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.getSubjects().mapToEntities(semester)
|
||||
.switchSemester(semester)
|
||||
.getSubjects()
|
||||
.mapToEntities(semester)
|
||||
},
|
||||
saveFetchResult = { old, new ->
|
||||
subjectDao.deleteAll(old uniqueSubtract new)
|
||||
|
@ -9,6 +9,7 @@ import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.switchSemester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import javax.inject.Inject
|
||||
@ -39,7 +40,7 @@ class TeacherRepository @Inject constructor(
|
||||
query = { teacherDb.loadAll(semester.studentId, semester.classId) },
|
||||
fetch = {
|
||||
sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getTeachers()
|
||||
.mapToEntities(semester)
|
||||
},
|
||||
|
@ -65,7 +65,7 @@ class TimetableRepository @Inject constructor(
|
||||
query = { getFullTimetableFromDatabase(student, semester, start, end) },
|
||||
fetch = {
|
||||
val timetableFull = sdk.init(student)
|
||||
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||
.switchSemester(semester)
|
||||
.getTimetable(start.monday, end.sunday)
|
||||
|
||||
timetableFull.mapToEntities(semester)
|
||||
|
@ -0,0 +1,33 @@
|
||||
package io.github.wulkanowy.domain.timetable
|
||||
|
||||
import io.github.wulkanowy.data.dataOrNull
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||
import io.github.wulkanowy.data.toFirstResult
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
class IsStudentHasLessonsOnWeekendUseCase @Inject constructor(
|
||||
private val timetableRepository: TimetableRepository,
|
||||
private val isWeekendHasLessonsUseCase: IsWeekendHasLessonsUseCase,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
student: Student,
|
||||
semester: Semester,
|
||||
currentDate: LocalDate = LocalDate.now(),
|
||||
): Boolean {
|
||||
val lessons = timetableRepository.getTimetable(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = currentDate.monday,
|
||||
end = currentDate.sunday,
|
||||
forceRefresh = false,
|
||||
timetableType = TimetableRepository.TimetableType.NORMAL
|
||||
).toFirstResult().dataOrNull?.lessons.orEmpty()
|
||||
return isWeekendHasLessonsUseCase(lessons)
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package io.github.wulkanowy.domain.timetable
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import java.time.DayOfWeek
|
||||
import javax.inject.Inject
|
||||
|
||||
class IsWeekendHasLessonsUseCase @Inject constructor() {
|
||||
|
||||
operator fun invoke(
|
||||
lessons: List<Timetable>,
|
||||
): Boolean = lessons.any {
|
||||
it.date.dayOfWeek in listOf(
|
||||
DayOfWeek.SATURDAY,
|
||||
DayOfWeek.SUNDAY,
|
||||
)
|
||||
}
|
||||
}
|
@ -65,8 +65,6 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
|
||||
range = lesson.start..lesson.end,
|
||||
requestCode = getRequestCode(lesson.start, studentId)
|
||||
)
|
||||
|
||||
Timber.d("TimetableNotification canceled: type 1 & 2, subject: ${lesson.subject}, start: ${lesson.start}, student: $studentId")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,12 @@ import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.GradeDescriptive
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.pojos.GroupNotificationData
|
||||
import io.github.wulkanowy.data.pojos.NotificationData
|
||||
import io.github.wulkanowy.ui.modules.Destination
|
||||
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
||||
import io.github.wulkanowy.utils.getPlural
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -88,4 +88,28 @@ class NewGradeNotification @Inject constructor(
|
||||
|
||||
appNotificationManager.sendMultipleNotifications(groupNotificationData, student)
|
||||
}
|
||||
|
||||
suspend fun notifyDescriptive(items: List<GradeDescriptive>, student: Student) {
|
||||
val notificationDataList = items.map {
|
||||
NotificationData(
|
||||
title = context.getPlural(R.plurals.grade_new_items_descriptive, 1),
|
||||
content = "${it.subject}: ${it.description}",
|
||||
destination = Destination.Grade,
|
||||
)
|
||||
}
|
||||
|
||||
val groupNotificationData = GroupNotificationData(
|
||||
notificationDataList = notificationDataList,
|
||||
title = context.getPlural(R.plurals.grade_new_items_descriptive, items.size),
|
||||
content = context.getPlural(
|
||||
R.plurals.grade_notify_new_items_descriptive,
|
||||
items.size,
|
||||
items.size
|
||||
),
|
||||
destination = Destination.Grade,
|
||||
type = NotificationType.NEW_GRADE_DESCRIPTIVE
|
||||
)
|
||||
|
||||
appNotificationManager.sendMultipleNotifications(groupNotificationData, student)
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,10 @@ enum class NotificationType(
|
||||
channel = NewGradesChannel.CHANNEL_ID,
|
||||
icon = R.drawable.ic_stat_grade,
|
||||
),
|
||||
NEW_GRADE_DESCRIPTIVE(
|
||||
channel = NewGradesChannel.CHANNEL_ID,
|
||||
icon = R.drawable.ic_stat_grade,
|
||||
),
|
||||
NEW_HOMEWORK(
|
||||
channel = NewHomeworkChannel.CHANNEL_ID,
|
||||
icon = R.drawable.ic_more_homework,
|
||||
|
@ -16,17 +16,24 @@ class AttendanceWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||
val startDate = now().previousOrSameSchoolDay
|
||||
val endDate = startDate.plusDays(7)
|
||||
|
||||
attendanceRepository.getAttendance(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = now().previousOrSameSchoolDay,
|
||||
end = now().previousOrSameSchoolDay,
|
||||
start = startDate,
|
||||
end = endDate,
|
||||
forceRefresh = true,
|
||||
notify = notify,
|
||||
)
|
||||
.waitForResult()
|
||||
|
||||
attendanceRepository.getAttendanceFromDatabase(semester, now().minusDays(7), now())
|
||||
attendanceRepository.getAttendanceFromDatabase(
|
||||
semester = semester,
|
||||
start = startDate,
|
||||
end = endDate,
|
||||
)
|
||||
.first()
|
||||
.filterNot { it.isNotified }
|
||||
.let {
|
||||
|
@ -5,6 +5,8 @@ import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.ExamRepository
|
||||
import io.github.wulkanowy.data.waitForResult
|
||||
import io.github.wulkanowy.services.sync.notifications.NewExamNotification
|
||||
import io.github.wulkanowy.utils.endExamsDay
|
||||
import io.github.wulkanowy.utils.startExamsDay
|
||||
import kotlinx.coroutines.flow.first
|
||||
import java.time.LocalDate.now
|
||||
import javax.inject.Inject
|
||||
@ -15,16 +17,24 @@ class ExamWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||
val startDate = now().startExamsDay
|
||||
val endDate = startDate.endExamsDay
|
||||
|
||||
examRepository.getExams(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = now(),
|
||||
end = now(),
|
||||
start = startDate,
|
||||
end = endDate,
|
||||
forceRefresh = true,
|
||||
notify = notify,
|
||||
).waitForResult()
|
||||
|
||||
examRepository.getExamsFromDatabase(semester, now()).first()
|
||||
examRepository.getExamsFromDatabase(
|
||||
semester = semester,
|
||||
start = startDate,
|
||||
end = endDate,
|
||||
)
|
||||
.first()
|
||||
.filter { !it.isNotified }.let {
|
||||
if (it.isNotEmpty()) newExamNotification.notify(it, student)
|
||||
|
||||
|
@ -45,5 +45,15 @@ class GradeWork @Inject constructor(
|
||||
grade.isFinalGradeNotified = true
|
||||
})
|
||||
}
|
||||
|
||||
gradeRepository.getGradesDescriptiveFromDatabase(semester).first()
|
||||
.filter { !it.isNotified }
|
||||
.let {
|
||||
if (it.isNotEmpty()) newGradeNotification.notifyDescriptive(it, student)
|
||||
|
||||
gradeRepository.updateGradesDescriptive(it.onEach { grade ->
|
||||
grade.isNotified = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,9 @@ import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.HomeworkRepository
|
||||
import io.github.wulkanowy.data.waitForResult
|
||||
import io.github.wulkanowy.services.sync.notifications.NewHomeworkNotification
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import kotlinx.coroutines.flow.first
|
||||
import java.time.LocalDate.now
|
||||
import javax.inject.Inject
|
||||
@ -16,16 +18,24 @@ class HomeworkWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||
val startDate = now().nextOrSameSchoolDay.monday
|
||||
val endDate = startDate.sunday
|
||||
|
||||
homeworkRepository.getHomework(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = now().nextOrSameSchoolDay,
|
||||
end = now().nextOrSameSchoolDay,
|
||||
start = startDate,
|
||||
end = endDate,
|
||||
forceRefresh = true,
|
||||
notify = notify,
|
||||
).waitForResult()
|
||||
|
||||
homeworkRepository.getHomeworkFromDatabase(semester, now(), now().plusDays(7)).first()
|
||||
homeworkRepository.getHomeworkFromDatabase(
|
||||
semester = semester,
|
||||
start = startDate,
|
||||
end = endDate
|
||||
)
|
||||
.first()
|
||||
.filter { !it.isNotified }.let {
|
||||
if (it.isNotEmpty()) newHomeworkNotification.notify(it, student)
|
||||
|
||||
|
@ -16,17 +16,24 @@ class TimetableWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||
val startDate = now().nextOrSameSchoolDay
|
||||
val endDate = startDate.plusDays(7)
|
||||
|
||||
timetableRepository.getTimetable(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = now().nextOrSameSchoolDay,
|
||||
end = now().nextOrSameSchoolDay,
|
||||
start = startDate,
|
||||
end = endDate,
|
||||
forceRefresh = true,
|
||||
notify = notify,
|
||||
)
|
||||
.waitForResult()
|
||||
|
||||
timetableRepository.getTimetableFromDatabase(semester, now(), now().plusDays(7))
|
||||
timetableRepository.getTimetableFromDatabase(
|
||||
semester = semester,
|
||||
from = startDate,
|
||||
end = endDate,
|
||||
)
|
||||
.first()
|
||||
.filterNot { it.isNotified }
|
||||
.let {
|
||||
|
@ -11,6 +11,7 @@ import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.ui.modules.captcha.CaptchaDialog
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.utils.FragmentLifecycleLogger
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
@ -77,6 +78,10 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>, VB : ViewBinding> :
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onCaptchaVerificationRequired(url: String?) {
|
||||
CaptchaDialog.newInstance(url).show(supportFragmentManager, "captcha_dialog")
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.main_session_expired)
|
||||
|
@ -8,7 +8,6 @@ import android.widget.Toast
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.google.android.material.elevation.SurfaceColors
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||
import javax.inject.Inject
|
||||
@ -32,6 +31,10 @@ abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment(), BaseView
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog()
|
||||
}
|
||||
|
||||
override fun onCaptchaVerificationRequired(url: String?) {
|
||||
(activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url)
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog()
|
||||
}
|
||||
@ -45,7 +48,7 @@ abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment(), BaseView
|
||||
}
|
||||
|
||||
override fun showAuthDialog() {
|
||||
AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
|
||||
(activity as? BaseActivity<*, *>)?.showAuthDialog()
|
||||
}
|
||||
|
||||
override fun showErrorDetailsDialog(error: Throwable) {
|
||||
|
@ -7,7 +7,6 @@ import androidx.viewbinding.ViewBinding
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||
|
||||
abstract class BaseFragment<VB : ViewBinding>(@LayoutRes layoutId: Int) : Fragment(layoutId),
|
||||
@ -43,12 +42,16 @@ abstract class BaseFragment<VB : ViewBinding>(@LayoutRes layoutId: Int) : Fragme
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog()
|
||||
}
|
||||
|
||||
override fun onCaptchaVerificationRequired(url: String?) {
|
||||
(activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url)
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog()
|
||||
}
|
||||
|
||||
override fun showAuthDialog() {
|
||||
AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
|
||||
(activity as? BaseActivity<*, *>)?.showAuthDialog()
|
||||
}
|
||||
|
||||
override fun openClearLoginView() {
|
||||
|
@ -29,6 +29,7 @@ open class BasePresenter<T : BaseView>(
|
||||
errorHandler.apply {
|
||||
showErrorMessage = view::showError
|
||||
onExpiredCredentials = view::showExpiredCredentialsDialog
|
||||
onCaptchaVerificationRequired = view::onCaptchaVerificationRequired
|
||||
onDecryptionFailed = view::showDecryptionFailedDialog
|
||||
onNoCurrentStudent = view::openClearLoginView
|
||||
onPasswordChangeRequired = view::showChangePasswordSnackbar
|
||||
|
@ -8,6 +8,8 @@ interface BaseView {
|
||||
|
||||
fun showExpiredCredentialsDialog()
|
||||
|
||||
fun onCaptchaVerificationRequired(url: String?)
|
||||
|
||||
fun showDecryptionFailedDialog()
|
||||
|
||||
fun showAuthDialog()
|
||||
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.AuthorizationRequiredException
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.CloudflareVerificationException
|
||||
import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
|
||||
import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException
|
||||
import io.github.wulkanowy.utils.getErrorString
|
||||
@ -25,6 +26,8 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
|
||||
|
||||
var onAuthorizationRequired: () -> Unit = {}
|
||||
|
||||
var onCaptchaVerificationRequired: (url: String?) -> Unit = {}
|
||||
|
||||
fun dispatch(error: Throwable) {
|
||||
Timber.e(error, "An exception occurred while the Wulkanowy was running")
|
||||
proceed(error)
|
||||
@ -38,6 +41,7 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
|
||||
is BadCredentialsException -> onExpiredCredentials()
|
||||
is NoCurrentStudentException -> onNoCurrentStudent()
|
||||
is AuthorizationRequiredException -> onAuthorizationRequired()
|
||||
is CloudflareVerificationException -> onCaptchaVerificationRequired(error.originalUrl)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -10,6 +11,7 @@ import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.enums.SentExcuseStatus
|
||||
import io.github.wulkanowy.databinding.ItemAttendanceBinding
|
||||
import io.github.wulkanowy.utils.descriptionRes
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.isExcusableOrNotExcused
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -39,7 +41,33 @@ class AttendanceAdapter @Inject constructor() :
|
||||
root.context.getString(R.string.all_no_data)
|
||||
}
|
||||
attendanceItemDescription.setText(item.descriptionRes)
|
||||
attendanceItemAlert.isVisible = item.let { it.absence && !it.excused }
|
||||
|
||||
attendanceItemDescription.setTextColor(
|
||||
root.context.getThemeAttrColor(
|
||||
when {
|
||||
item.absence && !item.excused -> R.attr.colorAttendanceAbsence
|
||||
item.lateness && !item.excused -> R.attr.colorAttendanceLateness
|
||||
else -> android.R.attr.textColorSecondary
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
if (item.exemption || item.excused) {
|
||||
attendanceItemDescription.setTypeface(null, Typeface.BOLD)
|
||||
} else {
|
||||
attendanceItemDescription.setTypeface(null, Typeface.NORMAL)
|
||||
}
|
||||
|
||||
attendanceItemAlert.isVisible =
|
||||
item.let { (it.absence && !it.excused) || (it.lateness && !it.excused) }
|
||||
|
||||
attendanceItemAlert.setColorFilter(root.context.getThemeAttrColor(
|
||||
when{
|
||||
item.absence && !item.excused -> R.attr.colorAttendanceAbsence
|
||||
item.lateness && !item.excused -> R.attr.colorAttendanceLateness
|
||||
else -> android.R.attr.colorPrimary
|
||||
}
|
||||
))
|
||||
attendanceItemNumber.visibility = View.GONE
|
||||
attendanceItemExcuseInfo.visibility = View.GONE
|
||||
attendanceItemExcuseCheckbox.visibility = View.GONE
|
||||
@ -54,10 +82,12 @@ class AttendanceAdapter @Inject constructor() :
|
||||
attendanceItemExcuseInfo.visibility = View.VISIBLE
|
||||
attendanceItemAlert.visibility = View.INVISIBLE
|
||||
}
|
||||
|
||||
SentExcuseStatus.DENIED -> {
|
||||
attendanceItemExcuseInfo.setImageResource(R.drawable.ic_excuse_denied)
|
||||
attendanceItemExcuseInfo.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (item.isExcusableOrNotExcused && excuseActionMode) {
|
||||
attendanceItemNumber.visibility = View.GONE
|
||||
|
@ -6,10 +6,12 @@ import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.databinding.DialogAttendanceBinding
|
||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||
import io.github.wulkanowy.utils.descriptionRes
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
|
||||
@ -44,6 +46,16 @@ class AttendanceDialog : BaseDialogFragment<DialogAttendanceBinding>() {
|
||||
with(binding) {
|
||||
attendanceDialogSubjectValue.text = attendance.subject
|
||||
attendanceDialogDescriptionValue.setText(attendance.descriptionRes)
|
||||
attendanceDialogDescriptionValue.setTextColor(
|
||||
root.context.getThemeAttrColor(
|
||||
when {
|
||||
attendance.absence && !attendance.excused -> R.attr.colorAttendanceAbsence
|
||||
attendance.lateness && !attendance.excused -> R.attr.colorAttendanceLateness
|
||||
else -> android.R.attr.textColorSecondary
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
attendanceDialogDateValue.text = attendance.date.toFormattedString()
|
||||
attendanceDialogNumberValue.text = attendance.number.toString()
|
||||
attendanceDialogClose.setOnClickListener { dismiss() }
|
||||
|
@ -0,0 +1,86 @@
|
||||
package io.github.wulkanowy.ui.modules.captcha
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.core.os.bundleOf
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.databinding.DialogCaptchaBinding
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class CaptchaDialog : BaseDialogFragment<DialogCaptchaBinding>() {
|
||||
|
||||
@Inject
|
||||
lateinit var sdk: Sdk
|
||||
|
||||
private var webView: WebView? = null
|
||||
|
||||
companion object {
|
||||
const val CAPTCHA_SUCCESS = "captcha_success"
|
||||
private const val CAPTCHA_URL = "captcha_url"
|
||||
private const val CAPTCHA_CHECK_JS = "document.getElementById('challenge-running') == null"
|
||||
|
||||
fun newInstance(url: String?): CaptchaDialog {
|
||||
return CaptchaDialog().apply {
|
||||
arguments = bundleOf(CAPTCHA_URL to url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View = DialogCaptchaBinding.inflate(inflater).apply { binding = this }.root
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
isCancelable = false
|
||||
binding.captchaRefresh.setOnClickListener {
|
||||
binding.captchaWebview.loadUrl(arguments?.getString(CAPTCHA_URL).orEmpty())
|
||||
}
|
||||
binding.captchaClose.setOnClickListener { dismiss() }
|
||||
|
||||
with(binding.captchaWebview) {
|
||||
webView = this
|
||||
with(settings) {
|
||||
javaScriptEnabled = true
|
||||
userAgentString = sdk.userAgent
|
||||
}
|
||||
|
||||
webViewClient = object : WebViewClient() {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
view?.evaluateJavascript(CAPTCHA_CHECK_JS) {
|
||||
if (it == "true") {
|
||||
onChallengeAccepted()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadUrl(arguments?.getString(CAPTCHA_URL).orEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
private fun onChallengeAccepted() {
|
||||
runCatching { parentFragmentManager.setFragmentResult(CAPTCHA_SUCCESS, bundleOf()) }
|
||||
.onFailure { Timber.e(it) }
|
||||
showMessage(getString(R.string.captcha_verified_message))
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
webView?.destroy()
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
@ -18,8 +18,10 @@ import io.github.wulkanowy.databinding.FragmentDashboardBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.account.accountdetails.AccountDetailsFragment
|
||||
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
|
||||
import io.github.wulkanowy.ui.modules.captcha.CaptchaDialog.Companion.CAPTCHA_SUCCESS
|
||||
import io.github.wulkanowy.ui.modules.conference.ConferenceFragment
|
||||
import io.github.wulkanowy.ui.modules.dashboard.adapters.DashboardAdapter
|
||||
import io.github.wulkanowy.ui.modules.dashboard.viewholders.AdminMessageViewHolder
|
||||
import io.github.wulkanowy.ui.modules.exam.ExamFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
|
||||
@ -62,6 +64,9 @@ class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragme
|
||||
return ((recyclerWidth - margin) / resources.displayMetrics.density).toInt()
|
||||
}
|
||||
|
||||
override val isViewEmpty
|
||||
get() = dashboardAdapter.itemCount == 0
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance() = DashboardFragment()
|
||||
@ -77,6 +82,13 @@ class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragme
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentDashboardBinding.bind(view)
|
||||
presenter.onAttachView(this)
|
||||
initializeCaptchaResultObserver()
|
||||
}
|
||||
|
||||
private fun initializeCaptchaResultObserver() {
|
||||
childFragmentManager.setFragmentResultListener(CAPTCHA_SUCCESS, this) { _, _ ->
|
||||
presenter.onRetryAfterCaptcha()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
@ -187,8 +199,17 @@ class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragme
|
||||
binding.dashboardRecycler.isVisible = show
|
||||
}
|
||||
|
||||
override fun showErrorView(show: Boolean) {
|
||||
override fun showErrorView(show: Boolean, adminMessageItem: DashboardItem.AdminMessages?) {
|
||||
binding.dashboardErrorContainer.isVisible = show
|
||||
binding.dashboardErrorAdminMessage.root.isVisible = adminMessageItem != null
|
||||
|
||||
if (adminMessageItem != null) {
|
||||
AdminMessageViewHolder(
|
||||
binding = binding.dashboardErrorAdminMessage,
|
||||
onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed,
|
||||
onAdminMessageClickListener = presenter::onAdminMessageSelected,
|
||||
).bind(adminMessageItem.adminMessage)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setErrorDetails(error: Throwable) {
|
||||
|
@ -24,11 +24,13 @@ import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||
import io.github.wulkanowy.domain.adminmessage.GetAppropriateAdminMessageUseCase
|
||||
import io.github.wulkanowy.domain.timetable.IsStudentHasLessonsOnWeekendUseCase
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.AdsHelper
|
||||
import io.github.wulkanowy.utils.calculatePercentage
|
||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
@ -56,6 +58,7 @@ class DashboardPresenter @Inject constructor(
|
||||
private val messageRepository: MessageRepository,
|
||||
private val attendanceSummaryRepository: AttendanceSummaryRepository,
|
||||
private val timetableRepository: TimetableRepository,
|
||||
private val isStudentHasLessonsOnWeekendUseCase: IsStudentHasLessonsOnWeekendUseCase,
|
||||
private val homeworkRepository: HomeworkRepository,
|
||||
private val examRepository: ExamRepository,
|
||||
private val conferenceRepository: ConferenceRepository,
|
||||
@ -239,6 +242,14 @@ class DashboardPresenter @Inject constructor(
|
||||
loadData(selectedDashboardTiles, forceRefresh = true)
|
||||
}
|
||||
|
||||
fun onRetryAfterCaptcha() {
|
||||
view?.run {
|
||||
showErrorView(false)
|
||||
showProgress(true)
|
||||
}
|
||||
loadData(selectedDashboardTiles, forceRefresh = true)
|
||||
}
|
||||
|
||||
fun onViewReselected() {
|
||||
Timber.i("Dashboard view is reselected")
|
||||
view?.run {
|
||||
@ -316,7 +327,7 @@ class DashboardPresenter @Inject constructor(
|
||||
) { luckyNumberResource, messageResource, attendanceResource ->
|
||||
val resList = listOf(luckyNumberResource, messageResource, attendanceResource)
|
||||
|
||||
DashboardItem.HorizontalGroup(
|
||||
resList to DashboardItem.HorizontalGroup(
|
||||
isLoading = resList.any { it is Resource.Loading },
|
||||
error = resList.map { it.errorOrNull }.let { errors ->
|
||||
if (errors.all { it != null }) {
|
||||
@ -341,9 +352,9 @@ class DashboardPresenter @Inject constructor(
|
||||
)
|
||||
})
|
||||
}
|
||||
.filterNot { it.isLoading && forceRefresh }
|
||||
.filterNot { (_, it) -> it.isLoading && forceRefresh }
|
||||
.distinctUntilChanged()
|
||||
.onEach {
|
||||
.onEach { (_, it) ->
|
||||
updateData(it, forceRefresh)
|
||||
|
||||
if (it.isLoading) {
|
||||
@ -361,7 +372,7 @@ class DashboardPresenter @Inject constructor(
|
||||
)
|
||||
errorHandler.dispatch(it)
|
||||
}
|
||||
.launch("horizontal_group ${if (forceRefresh) "-forceRefresh" else ""}")
|
||||
.launchWithUniqueRefreshJob("horizontal_group", forceRefresh)
|
||||
}
|
||||
|
||||
private fun loadGrades(student: Student, forceRefresh: Boolean) {
|
||||
@ -395,7 +406,7 @@ class DashboardPresenter @Inject constructor(
|
||||
subjectWithGrades = it.dataOrNull,
|
||||
gradeTheme = preferencesRepository.gradeColorTheme,
|
||||
isLoading = true
|
||||
), forceRefresh
|
||||
), false
|
||||
)
|
||||
|
||||
if (!it.dataOrNull.isNullOrEmpty()) {
|
||||
@ -427,14 +438,17 @@ class DashboardPresenter @Inject constructor(
|
||||
private fun loadLessons(student: Student, forceRefresh: Boolean) {
|
||||
flatResourceFlow {
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
val date = LocalDate.now()
|
||||
val date = when (isStudentHasLessonsOnWeekendUseCase(student, semester)) {
|
||||
true -> LocalDate.now()
|
||||
else -> LocalDate.now().nextOrSameSchoolDay
|
||||
}
|
||||
|
||||
timetableRepository.getTimetable(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = date,
|
||||
end = date.plusDays(1),
|
||||
forceRefresh = forceRefresh
|
||||
end = date.sunday,
|
||||
forceRefresh = forceRefresh,
|
||||
)
|
||||
}
|
||||
.onEach {
|
||||
@ -444,7 +458,7 @@ class DashboardPresenter @Inject constructor(
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(
|
||||
DashboardItem.Lessons(it.dataOrNull, isLoading = true),
|
||||
forceRefresh
|
||||
false
|
||||
)
|
||||
|
||||
if (!it.dataOrNull?.lessons.isNullOrEmpty()) {
|
||||
@ -501,7 +515,7 @@ class DashboardPresenter @Inject constructor(
|
||||
val data = it.dataOrNull.orEmpty()
|
||||
updateData(
|
||||
DashboardItem.Homework(data, isLoading = true),
|
||||
forceRefresh
|
||||
false
|
||||
)
|
||||
|
||||
if (data.isNotEmpty()) {
|
||||
@ -535,7 +549,7 @@ class DashboardPresenter @Inject constructor(
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(
|
||||
DashboardItem.Announcements(it.dataOrNull.orEmpty(), isLoading = true),
|
||||
forceRefresh
|
||||
false
|
||||
)
|
||||
|
||||
if (!it.dataOrNull.isNullOrEmpty()) {
|
||||
@ -578,7 +592,7 @@ class DashboardPresenter @Inject constructor(
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(
|
||||
DashboardItem.Exams(it.dataOrNull.orEmpty(), isLoading = true),
|
||||
forceRefresh
|
||||
false
|
||||
)
|
||||
|
||||
if (!it.dataOrNull.isNullOrEmpty()) {
|
||||
@ -619,7 +633,7 @@ class DashboardPresenter @Inject constructor(
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(
|
||||
DashboardItem.Conferences(it.dataOrNull.orEmpty(), isLoading = true),
|
||||
forceRefresh
|
||||
false
|
||||
)
|
||||
|
||||
if (!it.dataOrNull.isNullOrEmpty()) {
|
||||
@ -654,7 +668,7 @@ class DashboardPresenter @Inject constructor(
|
||||
is Resource.Loading -> {
|
||||
Timber.i("Loading dashboard admin message data started")
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(DashboardItem.AdminMessages(), forceRefresh)
|
||||
updateData(DashboardItem.AdminMessages(), false)
|
||||
}
|
||||
|
||||
is Resource.Success -> {
|
||||
@ -684,7 +698,7 @@ class DashboardPresenter @Inject constructor(
|
||||
private fun loadAds(forceRefresh: Boolean) {
|
||||
presenterScope.launch {
|
||||
if (!forceRefresh) {
|
||||
updateData(DashboardItem.Ads(), forceRefresh)
|
||||
updateData(DashboardItem.Ads(), false)
|
||||
}
|
||||
|
||||
val dashboardAdItem =
|
||||
@ -805,6 +819,8 @@ class DashboardPresenter @Inject constructor(
|
||||
val filteredItems = itemsLoadedList.filterNot {
|
||||
it.type == DashboardItem.Type.ACCOUNT || it.type == DashboardItem.Type.ADMIN_MESSAGE
|
||||
}
|
||||
val dataLoadedAdminMessageItem =
|
||||
itemsLoadedList.find { it.type == DashboardItem.Type.ADMIN_MESSAGE && it.isDataLoaded } as DashboardItem.AdminMessages?
|
||||
val isAccountItemError =
|
||||
itemsLoadedList.find { it.type == DashboardItem.Type.ACCOUNT }?.error != null
|
||||
val isGeneralError =
|
||||
@ -826,7 +842,7 @@ class DashboardPresenter @Inject constructor(
|
||||
showRefresh(false)
|
||||
if ((forceRefresh && wasGeneralError) || !forceRefresh) {
|
||||
showContent(false)
|
||||
showErrorView(true)
|
||||
showErrorView(true, dataLoadedAdminMessageItem)
|
||||
setErrorDetails(lastError)
|
||||
}
|
||||
}
|
||||
@ -854,6 +870,28 @@ class DashboardPresenter @Inject constructor(
|
||||
onEach {
|
||||
if (it is Resource.Success) {
|
||||
cancelJobs(jobName)
|
||||
} else if (it is Resource.Error) {
|
||||
cancelJobs(jobName)
|
||||
}
|
||||
}.launch(jobName)
|
||||
} else {
|
||||
launch(jobName)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmName("launchWithUniqueRefreshJobHorizontalGroup")
|
||||
private fun Flow<Pair<List<Resource<*>>, *>>.launchWithUniqueRefreshJob(
|
||||
name: String,
|
||||
forceRefresh: Boolean
|
||||
) {
|
||||
val jobName = if (forceRefresh) "$name-forceRefresh" else name
|
||||
|
||||
if (forceRefresh) {
|
||||
onEach { (resources, _) ->
|
||||
if (resources.all { it is Resource.Success<*> }) {
|
||||
cancelJobs(jobName)
|
||||
} else if (resources.any { it is Resource.Error<*> }) {
|
||||
cancelJobs(jobName)
|
||||
}
|
||||
}.launch(jobName)
|
||||
} else {
|
||||
|
@ -6,6 +6,8 @@ interface DashboardView : BaseView {
|
||||
|
||||
val tileWidth: Int
|
||||
|
||||
val isViewEmpty: Boolean
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<DashboardItem>)
|
||||
@ -18,7 +20,7 @@ interface DashboardView : BaseView {
|
||||
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showErrorView(show: Boolean)
|
||||
fun showErrorView(show: Boolean, adminMessageItem: DashboardItem.AdminMessages? = null)
|
||||
|
||||
fun setErrorDetails(error: Throwable)
|
||||
|
||||
|
@ -7,7 +7,6 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.AdminMessage
|
||||
import io.github.wulkanowy.databinding.ItemDashboardAdminMessageBinding
|
||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
|
||||
class AdminMessageViewHolder(
|
||||
@ -25,9 +24,11 @@ class AdminMessageViewHolder(
|
||||
context.getThemeAttrColor(R.attr.colorMessageHigh) to
|
||||
context.getThemeAttrColor(R.attr.colorOnMessageHigh)
|
||||
}
|
||||
|
||||
"MEDIUM" -> {
|
||||
context.getThemeAttrColor(R.attr.colorMessageMedium) to Color.BLACK
|
||||
}
|
||||
|
||||
else -> null to context.getThemeAttrColor(R.attr.colorOnSurface)
|
||||
}
|
||||
|
||||
@ -37,11 +38,16 @@ class AdminMessageViewHolder(
|
||||
dashboardAdminMessageItemDescription.text = item.content
|
||||
dashboardAdminMessageItemDescription.setTextColor(textColor)
|
||||
dashboardAdminMessageItemIcon.setColorFilter(textColor)
|
||||
dashboardAdminMessageItemDismiss.isVisible = item.isDismissible
|
||||
dashboardAdminMessageItemDismiss.isVisible = item.isOkVisible
|
||||
dashboardAdminMessageItemClose.isVisible = item.isXVisible
|
||||
dashboardAdminMessageItemDismiss.setTextColor(textColor)
|
||||
dashboardAdminMessageItemClose.imageTintList = ColorStateList.valueOf(textColor)
|
||||
dashboardAdminMessageItemDismiss.setOnClickListener {
|
||||
onAdminMessageDismissClickListener(item)
|
||||
}
|
||||
dashboardAdminMessageItemClose.setOnClickListener {
|
||||
onAdminMessageDismissClickListener(item)
|
||||
}
|
||||
|
||||
root.setCardBackgroundColor(backgroundColor?.let { ColorStateList.valueOf(it) })
|
||||
item.destinationUrl?.let { url ->
|
||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.debug
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.webkit.CookieManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
@ -58,6 +59,10 @@ class DebugFragment : BaseFragment<FragmentDebugBinding>(R.layout.fragment_debug
|
||||
(activity as? MainActivity)?.pushView(NotificationDebugFragment.newInstance())
|
||||
}
|
||||
|
||||
override fun clearWebkitCookies() {
|
||||
CookieManager.getInstance().removeAllCookies(null)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
presenter.onDetachView()
|
||||
super.onDestroyView()
|
||||
|
@ -15,6 +15,7 @@ class DebugPresenter @Inject constructor(
|
||||
val items = listOf(
|
||||
DebugItem(R.string.logviewer_title),
|
||||
DebugItem(R.string.notification_debug_title),
|
||||
DebugItem(R.string.debug_cookies_clear),
|
||||
)
|
||||
|
||||
override fun onAttachView(view: DebugView) {
|
||||
@ -31,6 +32,7 @@ class DebugPresenter @Inject constructor(
|
||||
when (item.title) {
|
||||
R.string.logviewer_title -> view?.openLogViewer()
|
||||
R.string.notification_debug_title -> view?.openNotificationsDebug()
|
||||
R.string.debug_cookies_clear -> view?.clearWebkitCookies()
|
||||
else -> Timber.d("Unknown debug item: $item")
|
||||
}
|
||||
}
|
||||
|
@ -11,4 +11,6 @@ interface DebugView : BaseView {
|
||||
fun openLogViewer()
|
||||
|
||||
fun openNotificationsDebug()
|
||||
|
||||
fun clearWebkitCookies()
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.ui.modules.debug.notification.mock.debugAttendanceItems
|
||||
import io.github.wulkanowy.ui.modules.debug.notification.mock.debugConferenceItems
|
||||
import io.github.wulkanowy.ui.modules.debug.notification.mock.debugExamItems
|
||||
import io.github.wulkanowy.ui.modules.debug.notification.mock.debugGradeDescriptiveItems
|
||||
import io.github.wulkanowy.ui.modules.debug.notification.mock.debugGradeDetailsItems
|
||||
import io.github.wulkanowy.ui.modules.debug.notification.mock.debugGradeSummaryItems
|
||||
import io.github.wulkanowy.ui.modules.debug.notification.mock.debugHomeworkItems
|
||||
@ -55,6 +56,14 @@ class NotificationDebugPresenter @Inject constructor(
|
||||
NotificationDebugItem(R.string.grade_summary_final_grade) { n ->
|
||||
withStudent { newGradeNotification.notifyFinal(debugGradeSummaryItems.take(n), it) }
|
||||
},
|
||||
NotificationDebugItem(R.string.grade_summary_descriptive) { n ->
|
||||
withStudent {
|
||||
newGradeNotification.notifyDescriptive(
|
||||
debugGradeDescriptiveItems.take(n),
|
||||
it
|
||||
)
|
||||
}
|
||||
},
|
||||
NotificationDebugItem(R.string.homework_title) { n ->
|
||||
withStudent { newHomeworkNotification.notify(debugHomeworkItems.take(n), it) }
|
||||
},
|
||||
|
@ -0,0 +1,48 @@
|
||||
package io.github.wulkanowy.ui.modules.debug.notification.mock
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.GradeDescriptive
|
||||
|
||||
val debugGradeDescriptiveItems = listOf(
|
||||
generateGradeDescriptive(
|
||||
"Matematyka",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
),
|
||||
generateGradeDescriptive("Fizyka", "Lorem ipsum dolor sit amet, consectetur adipiscing elit."),
|
||||
generateGradeDescriptive(
|
||||
"Geografia",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
),
|
||||
generateGradeDescriptive(
|
||||
"Sieci komputerowe",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
),
|
||||
generateGradeDescriptive(
|
||||
"Systemy operacyjne",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
),
|
||||
generateGradeDescriptive(
|
||||
"Język polski",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
),
|
||||
generateGradeDescriptive(
|
||||
"Język angielski",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
),
|
||||
generateGradeDescriptive("Religia", "Lorem ipsum dolor sit amet, consectetur adipiscing elit."),
|
||||
generateGradeDescriptive(
|
||||
"Język niemiecki",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
),
|
||||
generateGradeDescriptive(
|
||||
"Wychowanie fizyczne",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
),
|
||||
)
|
||||
|
||||
private fun generateGradeDescriptive(subject: String, description: String) =
|
||||
GradeDescriptive(
|
||||
semesterId = 0,
|
||||
studentId = 0,
|
||||
subject = subject,
|
||||
description = description
|
||||
)
|
@ -1,15 +1,23 @@
|
||||
package io.github.wulkanowy.ui.modules.grade
|
||||
|
||||
import io.github.wulkanowy.data.*
|
||||
import io.github.wulkanowy.data.Resource
|
||||
import io.github.wulkanowy.data.dataOrNull
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.GradeDescriptive
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.errorOrNull
|
||||
import io.github.wulkanowy.data.flatResourceFlow
|
||||
import io.github.wulkanowy.data.mapData
|
||||
import io.github.wulkanowy.data.mapResourceData
|
||||
import io.github.wulkanowy.data.repositories.GradeRepository
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.*
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.ALL_YEAR
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.BOTH_SEMESTERS
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.ONE_SEMESTER
|
||||
import io.github.wulkanowy.utils.calcAverage
|
||||
import io.github.wulkanowy.utils.changeModifier
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@ -62,6 +70,7 @@ class GradeAverageProvider @Inject constructor(
|
||||
forceRefresh = forceRefresh,
|
||||
params = params,
|
||||
)
|
||||
|
||||
BOTH_SEMESTERS -> calculateCombinedAverage(
|
||||
student = student,
|
||||
semesters = semesters,
|
||||
@ -69,6 +78,7 @@ class GradeAverageProvider @Inject constructor(
|
||||
forceRefresh = forceRefresh,
|
||||
config = params,
|
||||
)
|
||||
|
||||
ALL_YEAR -> calculateCombinedAverage(
|
||||
student = student,
|
||||
semesters = semesters,
|
||||
@ -189,36 +199,73 @@ class GradeAverageProvider @Inject constructor(
|
||||
): Flow<Resource<List<GradeSubject>>> {
|
||||
return gradeRepository.getGrades(student, semester, forceRefresh = forceRefresh)
|
||||
.mapResourceData { res ->
|
||||
val (details, summaries) = res
|
||||
val (details, summaries, descriptives) = res
|
||||
val isAnyAverage = summaries.any { it.average != .0 }
|
||||
val allGrades = details.groupBy { it.subject }
|
||||
val descriptiveGradesBySubject = descriptives.associateBy { it.subject }
|
||||
|
||||
val items = summaries.emulateEmptySummaries(
|
||||
student = student,
|
||||
semester = semester,
|
||||
grades = allGrades.toList(),
|
||||
calcAverage = isAnyAverage,
|
||||
params = params,
|
||||
).map { summary ->
|
||||
val grades = allGrades[summary.subject].orEmpty()
|
||||
GradeSubject(
|
||||
subject = summary.subject,
|
||||
average = if (!isAnyAverage || params.forceAverageCalc) {
|
||||
grades.updateModifiers(student, params)
|
||||
.calcAverage(params.isOptionalArithmeticAverage)
|
||||
} else summary.average,
|
||||
points = summary.pointsSum,
|
||||
summary = summary,
|
||||
grades = grades,
|
||||
isVulcanAverage = isAnyAverage
|
||||
val items = summaries
|
||||
.createEmptySummariesByGradesIfNeeded(
|
||||
student = student,
|
||||
semester = semester,
|
||||
grades = allGrades.toList(),
|
||||
calcAverage = isAnyAverage,
|
||||
params = params,
|
||||
)
|
||||
}
|
||||
.createEmptySummariesByDescriptiveGradesIfNeeded(
|
||||
student = student,
|
||||
semester = semester,
|
||||
descriptives = descriptives,
|
||||
)
|
||||
.map { summary ->
|
||||
val grades = allGrades[summary.subject].orEmpty()
|
||||
val descriptiveGrade = descriptiveGradesBySubject[summary.subject]
|
||||
|
||||
GradeSubject(
|
||||
subject = summary.subject,
|
||||
average = if (!isAnyAverage || params.forceAverageCalc) {
|
||||
grades.updateModifiers(student, params)
|
||||
.calcAverage(params.isOptionalArithmeticAverage)
|
||||
} else summary.average,
|
||||
points = summary.pointsSum,
|
||||
summary = summary,
|
||||
grades = grades,
|
||||
descriptive = descriptiveGrade,
|
||||
isVulcanAverage = isAnyAverage
|
||||
)
|
||||
}
|
||||
|
||||
items
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<GradeSummary>.emulateEmptySummaries(
|
||||
private fun List<GradeSummary>.createEmptySummariesByDescriptiveGradesIfNeeded(
|
||||
student: Student,
|
||||
semester: Semester,
|
||||
descriptives: List<GradeDescriptive>
|
||||
): List<GradeSummary> {
|
||||
val summarySubjects = this.map { it.subject }
|
||||
val gradeSummaryToAdd = descriptives.mapNotNull { gradeDescriptive ->
|
||||
if (gradeDescriptive.subject in summarySubjects) return@mapNotNull null
|
||||
|
||||
GradeSummary(
|
||||
studentId = student.studentId,
|
||||
semesterId = semester.semesterId,
|
||||
position = 0,
|
||||
subject = gradeDescriptive.subject,
|
||||
predictedGrade = "",
|
||||
finalGrade = "",
|
||||
proposedPoints = "",
|
||||
finalPoints = "",
|
||||
pointsSum = "",
|
||||
average = .0
|
||||
)
|
||||
}
|
||||
|
||||
return this + gradeSummaryToAdd
|
||||
}
|
||||
|
||||
private fun List<GradeSummary>.createEmptySummariesByGradesIfNeeded(
|
||||
student: Student,
|
||||
semester: Semester,
|
||||
grades: List<Pair<String, List<Grade>>>,
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.github.wulkanowy.ui.modules.grade
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.GradeDescriptive
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
|
||||
data class GradeSubject(
|
||||
@ -8,6 +9,7 @@ data class GradeSubject(
|
||||
val average: Double,
|
||||
val points: String,
|
||||
val summary: GradeSummary,
|
||||
val descriptive: GradeDescriptive?,
|
||||
val grades: List<Grade>,
|
||||
val isVulcanAverage: Boolean
|
||||
)
|
||||
|
@ -1,13 +1,22 @@
|
||||
package io.github.wulkanowy.ui.modules.grade.details
|
||||
|
||||
import io.github.wulkanowy.data.*
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.enums.GradeExpandMode
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode.*
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode.ALPHABETIC
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode.AVERAGE
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode.DATE
|
||||
import io.github.wulkanowy.data.flatResourceFlow
|
||||
import io.github.wulkanowy.data.logResourceStatus
|
||||
import io.github.wulkanowy.data.onResourceData
|
||||
import io.github.wulkanowy.data.onResourceError
|
||||
import io.github.wulkanowy.data.onResourceIntermediate
|
||||
import io.github.wulkanowy.data.onResourceNotLoading
|
||||
import io.github.wulkanowy.data.onResourceSuccess
|
||||
import io.github.wulkanowy.data.repositories.GradeRepository
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.resourceFlow
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider
|
||||
@ -207,20 +216,20 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
AVERAGE -> gradeSubjects.sortedByDescending { it.average }
|
||||
}
|
||||
}
|
||||
.map { (subject, average, points, _, grades) ->
|
||||
val subItems = grades
|
||||
.map { gradeSubject ->
|
||||
val subItems = gradeSubject.grades
|
||||
.sortedByDescending { it.date }
|
||||
.map { GradeDetailsItem(it, ViewType.ITEM) }
|
||||
|
||||
val gradeDetailsItems = listOf(
|
||||
GradeDetailsItem(
|
||||
GradeDetailsHeader(
|
||||
subject = subject,
|
||||
average = average,
|
||||
pointsSum = points,
|
||||
subject = gradeSubject.subject,
|
||||
average = gradeSubject.average,
|
||||
pointsSum = gradeSubject.points,
|
||||
grades = subItems
|
||||
).apply {
|
||||
newGrades = grades.filter { grade -> !grade.isRead }.size
|
||||
newGrades = gradeSubject.grades.filter { grade -> !grade.isRead }.size
|
||||
}, ViewType.HEADER
|
||||
)
|
||||
)
|
||||
|
@ -2,16 +2,16 @@ package io.github.wulkanowy.ui.modules.grade.summary
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.databinding.ItemGradeSummaryBinding
|
||||
import io.github.wulkanowy.databinding.ScrollableHeaderGradeSummaryBinding
|
||||
import io.github.wulkanowy.sdk.scrapper.grades.isGradeValid
|
||||
import io.github.wulkanowy.utils.calcFinalAverage
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -24,7 +24,7 @@ class GradeSummaryAdapter @Inject constructor(
|
||||
ITEM(2)
|
||||
}
|
||||
|
||||
var items = emptyList<GradeSummary>()
|
||||
var items = emptyList<GradeSummaryItem>()
|
||||
|
||||
var onCalculatedHelpClickListener: () -> Unit = {}
|
||||
|
||||
@ -44,9 +44,11 @@ class GradeSummaryAdapter @Inject constructor(
|
||||
ViewType.HEADER.id -> HeaderViewHolder(
|
||||
ScrollableHeaderGradeSummaryBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
|
||||
ViewType.ITEM.id -> ItemViewHolder(
|
||||
ItemGradeSummaryBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
@ -60,19 +62,23 @@ class GradeSummaryAdapter @Inject constructor(
|
||||
|
||||
private fun bindHeaderViewHolder(binding: ScrollableHeaderGradeSummaryBinding) {
|
||||
if (items.isEmpty()) return
|
||||
val gradeSummaries = items
|
||||
.filter { it.gradeDescriptive == null }
|
||||
.map { it.gradeSummary }
|
||||
|
||||
val context = binding.root.context
|
||||
val finalItemsCount = items.count { isGradeValid(it.finalGrade) }
|
||||
val calculatedItemsCount = items.count { value -> value.average != 0.0 }
|
||||
val allItemsCount = items.count { !it.subject.equals("zachowanie", true) }
|
||||
val finalAverage = items.calcFinalAverage(
|
||||
val finalItemsCount = gradeSummaries.count { isGradeValid(it.finalGrade) }
|
||||
val calculatedItemsCount = gradeSummaries.count { value -> value.average != 0.0 }
|
||||
val allItemsCount = gradeSummaries.count { !it.subject.equals("zachowanie", true) }
|
||||
val finalAverage = gradeSummaries.calcFinalAverage(
|
||||
preferencesRepository.gradePlusModifier,
|
||||
preferencesRepository.gradeMinusModifier
|
||||
)
|
||||
val calculatedAverage = items.filter { value -> value.average != 0.0 }
|
||||
val calculatedAverage = gradeSummaries.filter { value -> value.average != 0.0 }
|
||||
.map { values -> values.average }
|
||||
.reversed() // fix average precision
|
||||
.average()
|
||||
.let { if (it.isNaN()) 0.0 else it }
|
||||
|
||||
with(binding) {
|
||||
gradeSummaryScrollableHeaderFinal.text = formatAverage(finalAverage)
|
||||
@ -95,16 +101,28 @@ class GradeSummaryAdapter @Inject constructor(
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun bindItemViewHolder(binding: ItemGradeSummaryBinding, item: GradeSummary) {
|
||||
with(binding) {
|
||||
gradeSummaryItemTitle.text = item.subject
|
||||
gradeSummaryItemPoints.text = item.pointsSum
|
||||
gradeSummaryItemAverage.text = formatAverage(item.average, "")
|
||||
gradeSummaryItemPredicted.text = "${item.predictedGrade} ${item.proposedPoints}".trim()
|
||||
gradeSummaryItemFinal.text = "${item.finalGrade} ${item.finalPoints}".trim()
|
||||
private fun bindItemViewHolder(binding: ItemGradeSummaryBinding, item: GradeSummaryItem) {
|
||||
val (gradeSummary, gradeDescriptive) = item
|
||||
|
||||
gradeSummaryItemPointsContainer.visibility =
|
||||
if (item.pointsSum.isBlank()) View.GONE else View.VISIBLE
|
||||
with(binding) {
|
||||
gradeSummaryItemTitle.text = gradeSummary.subject
|
||||
gradeSummaryItemPoints.text = gradeSummary.pointsSum
|
||||
gradeSummaryItemAverage.text = formatAverage(gradeSummary.average, "")
|
||||
gradeSummaryItemPredicted.text =
|
||||
"${gradeSummary.predictedGrade} ${gradeSummary.proposedPoints}".trim()
|
||||
gradeSummaryItemFinal.text =
|
||||
"${gradeSummary.finalGrade} ${gradeSummary.finalPoints}".trim()
|
||||
gradeSummaryItemDescriptive.text = gradeDescriptive?.description.ifNullOrBlank {
|
||||
root.context.getString(R.string.all_no_data)
|
||||
}
|
||||
|
||||
gradeSummaryItemFinalDivider.isVisible = gradeDescriptive == null
|
||||
gradeSummaryItemPredictedDivider.isVisible = gradeDescriptive == null
|
||||
gradeSummaryItemPointsDivider.isVisible = gradeDescriptive == null
|
||||
gradeSummaryItemPredictedContainer.isVisible = gradeDescriptive == null
|
||||
gradeSummaryItemFinalContainer.isVisible = gradeDescriptive == null
|
||||
gradeSummaryItemDescriptiveContainer.isVisible = gradeDescriptive != null
|
||||
gradeSummaryItemPointsContainer.isVisible = gradeSummary.pointsSum.isNotBlank()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,10 @@ import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.INVISIBLE
|
||||
import android.view.View.VISIBLE
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.databinding.FragmentGradeSummaryBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||
@ -72,7 +70,7 @@ class GradeSummaryFragment :
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateData(data: List<GradeSummary>) {
|
||||
override fun updateData(data: List<GradeSummaryItem>) {
|
||||
with(gradeSummaryAdapter) {
|
||||
items = data
|
||||
notifyDataSetChanged()
|
||||
|
@ -0,0 +1,9 @@
|
||||
package io.github.wulkanowy.ui.modules.grade.summary
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.GradeDescriptive
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
|
||||
data class GradeSummaryItem(
|
||||
val gradeSummary: GradeSummary,
|
||||
val gradeDescriptive: GradeDescriptive?
|
||||
)
|
@ -1,9 +1,16 @@
|
||||
package io.github.wulkanowy.ui.modules.grade.summary
|
||||
|
||||
import io.github.wulkanowy.data.*
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode.*
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode.ALPHABETIC
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode.AVERAGE
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode.DATE
|
||||
import io.github.wulkanowy.data.flatResourceFlow
|
||||
import io.github.wulkanowy.data.logResourceStatus
|
||||
import io.github.wulkanowy.data.mapResourceData
|
||||
import io.github.wulkanowy.data.onResourceData
|
||||
import io.github.wulkanowy.data.onResourceError
|
||||
import io.github.wulkanowy.data.onResourceIntermediate
|
||||
import io.github.wulkanowy.data.onResourceNotLoading
|
||||
import io.github.wulkanowy.data.onResourceSuccess
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
@ -128,7 +135,7 @@ class GradeSummaryPresenter @Inject constructor(
|
||||
view?.showFinalAverageHelpDialog()
|
||||
}
|
||||
|
||||
private fun createGradeSummaryItems(items: List<GradeSubject>): List<GradeSummary> {
|
||||
private fun createGradeSummaryItems(items: List<GradeSubject>): List<GradeSummaryItem> {
|
||||
return items
|
||||
.filter { !checkEmpty(it) }
|
||||
.let { gradeSubjects ->
|
||||
@ -136,21 +143,32 @@ class GradeSummaryPresenter @Inject constructor(
|
||||
DATE -> gradeSubjects.sortedByDescending { gradeDetailsWithAverage ->
|
||||
gradeDetailsWithAverage.grades.maxByOrNull { it.date }?.date
|
||||
}
|
||||
|
||||
ALPHABETIC -> gradeSubjects.sortedBy { gradeDetailsWithAverage ->
|
||||
gradeDetailsWithAverage.subject.lowercase()
|
||||
}
|
||||
|
||||
AVERAGE -> gradeSubjects.sortedByDescending { it.average }
|
||||
}
|
||||
}
|
||||
.map { it.summary.copy(average = it.average) }
|
||||
.map {
|
||||
val gradeSummary = it.summary.copy(average = it.average)
|
||||
val descriptive = it.descriptive
|
||||
GradeSummaryItem(
|
||||
gradeSummary = gradeSummary,
|
||||
gradeDescriptive = descriptive,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun checkEmpty(gradeSummary: GradeSubject): Boolean {
|
||||
return gradeSummary.run {
|
||||
summary.finalGrade.isBlank()
|
||||
&& summary.predictedGrade.isBlank()
|
||||
&& average == .0
|
||||
&& points.isBlank()
|
||||
&& summary.predictedGrade.isBlank()
|
||||
&& average == .0
|
||||
&& points.isBlank()
|
||||
&& descriptive == null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package io.github.wulkanowy.ui.modules.grade.summary
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface GradeSummaryView : BaseView {
|
||||
@ -13,7 +12,7 @@ interface GradeSummaryView : BaseView {
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<GradeSummary>)
|
||||
fun updateData(data: List<GradeSummaryItem>)
|
||||
|
||||
fun resetView()
|
||||
|
||||
|
@ -7,5 +7,6 @@ data class LoginData(
|
||||
val password: String,
|
||||
val baseUrl: String,
|
||||
val domainSuffix: String,
|
||||
val symbol: String?,
|
||||
val defaultSymbol: String,
|
||||
val userEnteredSymbol: String? = null,
|
||||
) : Serializable
|
||||
|
@ -71,7 +71,7 @@ class LoginAdvancedPresenter @Inject constructor(
|
||||
|
||||
fun updateUsernameLabel() {
|
||||
view?.apply {
|
||||
setUsernameLabel(if ("vulcan" in formHostValue || "fakelog" in formHostValue) emailLabel else nicknameLabel)
|
||||
setUsernameLabel(if ("vulcan" in formHostValue || "wulkanowy" in formHostValue) emailLabel else nicknameLabel)
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ class LoginAdvancedPresenter @Inject constructor(
|
||||
view?.apply {
|
||||
clearPassError()
|
||||
clearUsernameError()
|
||||
if (formHostValue.contains("fakelog")) {
|
||||
if (formHostValue.contains("wulkanowy")) {
|
||||
setDefaultCredentials(
|
||||
"jan@fakelog.cf", "jan123", "powiatwulkanowy", "FK100000", "999999"
|
||||
)
|
||||
@ -155,7 +155,7 @@ class LoginAdvancedPresenter @Inject constructor(
|
||||
password = view?.formPassValue.orEmpty().trim(),
|
||||
baseUrl = view?.formHostValue.orEmpty().trim(),
|
||||
domainSuffix = view?.formDomainSuffix.orEmpty().trim(),
|
||||
symbol = view?.formSymbolValue.orEmpty().trim().getNormalizedSymbol(),
|
||||
defaultSymbol = view?.formSymbolValue.orEmpty().trim().getNormalizedSymbol(),
|
||||
)
|
||||
when (it.data.symbols.size) {
|
||||
0 -> view?.navigateToSymbol(loginData)
|
||||
|
@ -7,6 +7,7 @@ import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.setFragmentResultListener
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.AdminMessage
|
||||
@ -14,6 +15,7 @@ import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.databinding.FragmentLoginFormBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.captcha.CaptchaDialog
|
||||
import io.github.wulkanowy.ui.modules.dashboard.viewholders.AdminMessageViewHolder
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
@ -72,6 +74,13 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentLoginFormBinding.bind(view)
|
||||
presenter.onAttachView(this)
|
||||
initializeCaptchaResultObserver()
|
||||
}
|
||||
|
||||
private fun initializeCaptchaResultObserver() {
|
||||
setFragmentResultListener(CaptchaDialog.CAPTCHA_SUCCESS) { _, _ ->
|
||||
presenter.onRetryAfterCaptcha()
|
||||
}
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
@ -85,6 +94,7 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
loginFormUsername.doOnTextChanged { _, _, _, _ -> presenter.onUsernameTextChanged() }
|
||||
loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() }
|
||||
loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() }
|
||||
loginFormDomainSuffix.doOnTextChanged { _, _, _, _ -> presenter.onDomainSuffixChanged() }
|
||||
loginFormSignIn.setOnClickListener { presenter.onSignInClick() }
|
||||
loginFormAdvancedButton.setOnClickListener { presenter.onAdvancedLoginClick() }
|
||||
loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() }
|
||||
@ -179,6 +189,12 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
}
|
||||
}
|
||||
|
||||
override fun setDomainSuffixInvalid() {
|
||||
with(binding.loginFormDomainSuffixLayout) {
|
||||
error = getString(R.string.login_invalid_domain_suffix)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearUsernameError() {
|
||||
binding.loginFormUsernameLayout.error = null
|
||||
binding.loginFormErrorBox.isVisible = false
|
||||
@ -197,6 +213,10 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
binding.loginFormErrorBox.isVisible = false
|
||||
}
|
||||
|
||||
override fun clearDomainSuffixError() {
|
||||
binding.loginFormDomainSuffixLayout.error = null
|
||||
}
|
||||
|
||||
override fun showSoftKeyboard() {
|
||||
activity?.showSoftInput()
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class LoginFormPresenter @Inject constructor(
|
||||
clearPassError()
|
||||
clearUsernameError()
|
||||
clearHostError()
|
||||
if (formHostValue.contains("fakelog")) {
|
||||
if (formHostValue.contains("wulkanowy")) {
|
||||
setCredentials("jan@fakelog.cf", "jan123")
|
||||
} else if (formUsernameValue == "jan@fakelog.cf" && formPassValue == "jan123") {
|
||||
setCredentials("", "")
|
||||
@ -101,6 +101,12 @@ class LoginFormPresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun onDomainSuffixChanged() {
|
||||
view?.apply {
|
||||
clearDomainSuffixError()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateCustomDomainSuffixVisibility() {
|
||||
view?.run {
|
||||
showDomainSuffixInput("customSuffix" in formHostValue)
|
||||
@ -148,14 +154,18 @@ class LoginFormPresenter @Inject constructor(
|
||||
password = password,
|
||||
baseUrl = host,
|
||||
domainSuffix = domainSuffix,
|
||||
symbol = symbol
|
||||
defaultSymbol = symbol
|
||||
)
|
||||
}
|
||||
|
||||
fun onRetryAfterCaptcha() {
|
||||
onSignInClick()
|
||||
}
|
||||
|
||||
fun onSignInClick() {
|
||||
val loginData = getLoginData()
|
||||
|
||||
if (!validateCredentials(loginData.login, loginData.password, loginData.baseUrl)) return
|
||||
if (!validateCredentials(loginData)) return
|
||||
|
||||
resourceFlow {
|
||||
studentRepository.getUserSubjectsFromScrapper(
|
||||
@ -163,7 +173,7 @@ class LoginFormPresenter @Inject constructor(
|
||||
password = loginData.password,
|
||||
scrapperBaseUrl = loginData.baseUrl,
|
||||
domainSuffix = loginData.domainSuffix,
|
||||
symbol = loginData.symbol.orEmpty(),
|
||||
symbol = loginData.defaultSymbol,
|
||||
)
|
||||
}
|
||||
.logResourceStatus("login")
|
||||
@ -225,24 +235,29 @@ class LoginFormPresenter @Inject constructor(
|
||||
view?.onRecoverClick()
|
||||
}
|
||||
|
||||
private fun validateCredentials(login: String, password: String, host: String): Boolean {
|
||||
private fun validateCredentials(loginData: LoginData): Boolean {
|
||||
var isCorrect = true
|
||||
|
||||
if (login.isEmpty()) {
|
||||
if (loginData.login.isEmpty()) {
|
||||
view?.setErrorUsernameRequired()
|
||||
isCorrect = false
|
||||
} else {
|
||||
if ("@" in login && "login" in host) {
|
||||
if ("@" in loginData.login && "login" in loginData.baseUrl) {
|
||||
view?.setErrorLoginRequired()
|
||||
isCorrect = false
|
||||
}
|
||||
if ("@" !in login && "email" in host) {
|
||||
if ("@" !in loginData.login && "email" in loginData.baseUrl) {
|
||||
view?.setErrorEmailRequired()
|
||||
isCorrect = false
|
||||
}
|
||||
if ("@" in login && "||" !in login && "login" !in host && "email" !in host) {
|
||||
val emailHost = login.substringAfter("@")
|
||||
val emailDomain = URL(host).host
|
||||
|
||||
val isEmailLogin = "@" in loginData.login
|
||||
val isEmailWithLogin = "||" !in loginData.login
|
||||
val isLoginNotRequired = "login" !in loginData.baseUrl
|
||||
val isEmailNotRequired = "email" !in loginData.baseUrl
|
||||
if (isEmailLogin && isEmailWithLogin && isLoginNotRequired && isEmailNotRequired) {
|
||||
val emailHost = loginData.login.substringAfter("@")
|
||||
val emailDomain = URL(loginData.baseUrl).host
|
||||
if (!emailHost.equals(emailDomain, true)) {
|
||||
view?.setErrorEmailInvalid(domain = emailDomain)
|
||||
isCorrect = false
|
||||
@ -250,16 +265,21 @@ class LoginFormPresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
if (password.isEmpty()) {
|
||||
if (loginData.password.isEmpty()) {
|
||||
view?.setErrorPassRequired(focus = isCorrect)
|
||||
isCorrect = false
|
||||
}
|
||||
|
||||
if (password.length < 6 && password.isNotEmpty()) {
|
||||
if (loginData.password.length < 6 && loginData.password.isNotEmpty()) {
|
||||
view?.setErrorPassInvalid(focus = isCorrect)
|
||||
isCorrect = false
|
||||
}
|
||||
|
||||
if (loginData.domainSuffix !in listOf("", "rc", "kurs")) {
|
||||
view?.setDomainSuffixInvalid()
|
||||
isCorrect = false
|
||||
}
|
||||
|
||||
return isCorrect
|
||||
}
|
||||
}
|
||||
|
@ -46,12 +46,16 @@ interface LoginFormView : BaseView {
|
||||
|
||||
fun setErrorEmailInvalid(domain: String)
|
||||
|
||||
fun setDomainSuffixInvalid()
|
||||
|
||||
fun clearUsernameError()
|
||||
|
||||
fun clearPassError()
|
||||
|
||||
fun clearHostError()
|
||||
|
||||
fun clearDomainSuffixError()
|
||||
|
||||
fun showSoftKeyboard()
|
||||
|
||||
fun hideSoftKeyboard()
|
||||
|
@ -38,7 +38,7 @@ class LoginRecoverPresenter @Inject constructor(
|
||||
|
||||
fun onHostSelected() {
|
||||
view?.run {
|
||||
if ("fakelog" in recoverHostValue) setDefaultCredentials("jan@fakelog.cf")
|
||||
if ("wulkanowy" in recoverHostValue) setDefaultCredentials("jan@fakelog.cf")
|
||||
clearUsernameError()
|
||||
updateFields()
|
||||
}
|
||||
@ -60,7 +60,7 @@ class LoginRecoverPresenter @Inject constructor(
|
||||
resourceFlow {
|
||||
recoverRepository.getReCaptchaSiteKey(
|
||||
host,
|
||||
symbol.ifBlank { "Default" })
|
||||
symbol.ifBlank { "default" })
|
||||
}.onEach {
|
||||
when (it) {
|
||||
is Resource.Loading -> view?.run {
|
||||
@ -103,7 +103,7 @@ class LoginRecoverPresenter @Inject constructor(
|
||||
fun onReCaptchaVerified(reCaptchaResponse: String) {
|
||||
val username = view?.recoverNameValue.orEmpty()
|
||||
val host = view?.recoverHostValue.orEmpty()
|
||||
val symbol = view?.formHostSymbol.ifNullOrBlank { "Default" }
|
||||
val symbol = view?.formHostSymbol.ifNullOrBlank { "default" }
|
||||
|
||||
resourceFlow {
|
||||
recoverRepository.sendRecoverRequest(
|
||||
|
@ -10,13 +10,11 @@ import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportDialog
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.openEmailClient
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import javax.inject.Inject
|
||||
|
@ -111,8 +111,8 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
val notEmptySymbols = registerUser.symbols.filter { it.schools.isNotEmpty() }
|
||||
val emptySymbols = registerUser.symbols.filter { it.schools.isEmpty() }
|
||||
|
||||
if (emptySymbols.isNotEmpty() && notEmptySymbols.isNotEmpty() && emptySymbols.any { it.symbol == loginData.symbol }) {
|
||||
add(createEmptySymbolItem(emptySymbols.first { it.symbol == loginData.symbol }))
|
||||
if (emptySymbols.isNotEmpty() && notEmptySymbols.isNotEmpty() && emptySymbols.any { it.symbol == loginData.userEnteredSymbol }) {
|
||||
add(createEmptySymbolItem(emptySymbols.first { it.symbol == loginData.userEnteredSymbol }))
|
||||
}
|
||||
|
||||
addAll(createNotEmptySymbolItems(notEmptySymbols, students))
|
||||
@ -317,7 +317,7 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
loginData = loginData,
|
||||
registerUser = registerUser,
|
||||
lastErrorMessage = lastError?.message,
|
||||
enteredSymbol = loginData.symbol,
|
||||
enteredSymbol = loginData.userEnteredSymbol,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ class LoginSupportDialog : BaseDialogFragment<DialogLoginSupportBinding>() {
|
||||
"${appInfo.systemManufacturer} ${appInfo.systemModel}",
|
||||
appInfo.systemVersion.toString(),
|
||||
"${appInfo.versionName}-${appInfo.buildFlavor}",
|
||||
supportInfo.loginData.baseUrl + "/" + supportInfo.loginData.symbol,
|
||||
supportInfo.loginData.let { "${it.baseUrl}/${it.defaultSymbol}/${it.userEnteredSymbol}" },
|
||||
preferencesRepository.installationId,
|
||||
getLastErrorFromStudentSelectScreen(),
|
||||
dialogLoginSupportSchoolInput.text.takeIf { !it.isNullOrBlank() }
|
||||
|
@ -60,7 +60,7 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
loginData = loginData.copy(
|
||||
symbol = view?.symbolValue?.getNormalizedSymbol(),
|
||||
userEnteredSymbol = view?.symbolValue?.getNormalizedSymbol(),
|
||||
)
|
||||
resourceFlow {
|
||||
studentRepository.getUserSubjectsFromScrapper(
|
||||
@ -68,7 +68,7 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
password = loginData.password,
|
||||
scrapperBaseUrl = loginData.baseUrl,
|
||||
domainSuffix = loginData.domainSuffix,
|
||||
symbol = loginData.symbol.orEmpty(),
|
||||
symbol = loginData.userEnteredSymbol.orEmpty(),
|
||||
)
|
||||
}.onEach { user ->
|
||||
registerUser = user.dataOrNull
|
||||
@ -93,13 +93,10 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
else -> {
|
||||
val enteredSymbolDetails = user.data.symbols
|
||||
.firstOrNull()
|
||||
?.takeIf { it.symbol == loginData.symbol }
|
||||
?.takeIf { it.symbol == loginData.userEnteredSymbol }
|
||||
|
||||
if (enteredSymbolDetails?.error is InvalidSymbolException) {
|
||||
view?.run {
|
||||
setErrorSymbolInvalid()
|
||||
showContact(true)
|
||||
}
|
||||
showInvalidSymbolError()
|
||||
} else {
|
||||
Timber.i("Login with symbol result: Success")
|
||||
view?.navigateToStudentSelect(loginData, requireNotNull(user.data))
|
||||
@ -128,6 +125,9 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
loginErrorHandler.dispatch(user.error)
|
||||
lastError = user.error
|
||||
view?.showContact(true)
|
||||
if (user.error is InvalidSymbolException) {
|
||||
showInvalidSymbolError()
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onResourceNotLoading {
|
||||
@ -145,6 +145,13 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
return normalizedSymbol in definitelyInvalidSymbols
|
||||
}
|
||||
|
||||
private fun showInvalidSymbolError() {
|
||||
view?.run {
|
||||
setErrorSymbolInvalid()
|
||||
showContact(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun onFaqClick() {
|
||||
view?.openFaqPage()
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -30,6 +31,8 @@ import io.github.wulkanowy.databinding.ActivityMainBinding
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.modules.Destination
|
||||
import io.github.wulkanowy.ui.modules.account.accountquick.AccountQuickDialog
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.ui.modules.captcha.CaptchaDialog
|
||||
import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
@ -40,10 +43,17 @@ import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.nickOrName
|
||||
import io.github.wulkanowy.utils.safelyPopFragments
|
||||
import io.github.wulkanowy.utils.setOnViewChangeListener
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainView,
|
||||
@ -73,6 +83,8 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
private val navController =
|
||||
FragNavController(supportFragmentManager, R.id.main_fragment_container)
|
||||
|
||||
private val captchaVerificationEvent = MutableSharedFlow<String?>()
|
||||
|
||||
companion object {
|
||||
|
||||
private const val EXTRA_START_DESTINATION = "start_destination_json"
|
||||
@ -144,6 +156,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
initializeToolbar()
|
||||
initializeBottomNavigation(startMenuIndex, rootAppMenuItems)
|
||||
initializeNavController(startMenuIndex, rootUpdatedDestinations)
|
||||
initializeCaptchaVerificationEvent()
|
||||
}
|
||||
|
||||
private fun initializeNavController(
|
||||
@ -323,6 +336,27 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
.show()
|
||||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
private fun initializeCaptchaVerificationEvent() {
|
||||
captchaVerificationEvent
|
||||
.debounce(1.seconds)
|
||||
.onEach { url ->
|
||||
Timber.d("Showing captcha dialog for: $url")
|
||||
showDialogFragment(CaptchaDialog.newInstance(url))
|
||||
}
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
||||
override fun onCaptchaVerificationRequired(url: String?) {
|
||||
lifecycleScope.launch {
|
||||
captchaVerificationEvent.emit(url)
|
||||
}
|
||||
}
|
||||
|
||||
override fun showAuthDialog() {
|
||||
showDialogFragment(AuthDialog.newInstance())
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
navController.onSaveInstanceState(outState)
|
||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.ui.modules.settings
|
||||
import android.os.Bundle
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import timber.log.Timber
|
||||
|
||||
@ -26,6 +27,8 @@ class SettingsFragment : PreferenceFragmentCompat(), MainView.TitledView, Settin
|
||||
|
||||
override fun showExpiredCredentialsDialog() {}
|
||||
|
||||
override fun onCaptchaVerificationRequired(url: String?) = Unit
|
||||
|
||||
override fun showDecryptionFailedDialog() {}
|
||||
|
||||
override fun openClearLoginView() {}
|
||||
|
@ -8,7 +8,6 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.base.ErrorDialog
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import javax.inject.Inject
|
||||
@ -51,6 +50,10 @@ class AdvancedFragment : PreferenceFragmentCompat(),
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog()
|
||||
}
|
||||
|
||||
override fun onCaptchaVerificationRequired(url: String?) {
|
||||
(activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url)
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog()
|
||||
}
|
||||
@ -68,7 +71,7 @@ class AdvancedFragment : PreferenceFragmentCompat(),
|
||||
}
|
||||
|
||||
override fun showAuthDialog() {
|
||||
AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
|
||||
(activity as? BaseActivity<*, *>)?.showAuthDialog()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -9,7 +9,6 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.base.ErrorDialog
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import javax.inject.Inject
|
||||
@ -67,6 +66,10 @@ class AppearanceFragment : PreferenceFragmentCompat(),
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog()
|
||||
}
|
||||
|
||||
override fun onCaptchaVerificationRequired(url: String?) {
|
||||
(activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url)
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog()
|
||||
}
|
||||
@ -84,7 +87,7 @@ class AppearanceFragment : PreferenceFragmentCompat(),
|
||||
}
|
||||
|
||||
override fun showAuthDialog() {
|
||||
AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
|
||||
(activity as? BaseActivity<*, *>)?.showAuthDialog()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -21,7 +21,6 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.base.ErrorDialog
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
@ -137,6 +136,10 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog()
|
||||
}
|
||||
|
||||
override fun onCaptchaVerificationRequired(url: String?) {
|
||||
(activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url)
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog()
|
||||
}
|
||||
@ -154,7 +157,7 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
||||
}
|
||||
|
||||
override fun showAuthDialog() {
|
||||
AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
|
||||
(activity as? BaseActivity<*, *>)?.showAuthDialog()
|
||||
}
|
||||
|
||||
override fun showFixSyncDialog() {
|
||||
|
@ -10,7 +10,6 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.base.ErrorDialog
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -88,6 +87,10 @@ class SyncFragment : PreferenceFragmentCompat(),
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog()
|
||||
}
|
||||
|
||||
override fun onCaptchaVerificationRequired(url: String?) {
|
||||
(activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url)
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog()
|
||||
}
|
||||
@ -105,7 +108,7 @@ class SyncFragment : PreferenceFragmentCompat(),
|
||||
}
|
||||
|
||||
override fun showAuthDialog() {
|
||||
AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
|
||||
(activity as? BaseActivity<*, *>)?.showAuthDialog()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -2,7 +2,6 @@ package io.github.wulkanowy.ui.modules.timetable
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import io.github.wulkanowy.data.dataOrNull
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
@ -20,8 +19,8 @@ import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||
import io.github.wulkanowy.data.toFirstResult
|
||||
import io.github.wulkanowy.data.waitForResult
|
||||
import io.github.wulkanowy.domain.timetable.IsStudentHasLessonsOnWeekendUseCase
|
||||
import io.github.wulkanowy.domain.timetable.IsWeekendHasLessonsUseCase
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
@ -31,16 +30,12 @@ import io.github.wulkanowy.utils.isHolidays
|
||||
import io.github.wulkanowy.utils.isJustFinished
|
||||
import io.github.wulkanowy.utils.isShowTimeUntil
|
||||
import io.github.wulkanowy.utils.left
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||
import io.github.wulkanowy.utils.nextSchoolDay
|
||||
import io.github.wulkanowy.utils.previousSchoolDay
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import io.github.wulkanowy.utils.until
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import timber.log.Timber
|
||||
import java.time.DayOfWeek
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDate.now
|
||||
@ -54,6 +49,8 @@ class TimetablePresenter @Inject constructor(
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val timetableRepository: TimetableRepository,
|
||||
private val isStudentHasLessonsOnWeekendUseCase: IsStudentHasLessonsOnWeekendUseCase,
|
||||
private val isWeekendHasLessonsUseCase: IsWeekendHasLessonsUseCase,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val prefRepository: PreferencesRepository,
|
||||
private val analytics: AnalyticsHelper,
|
||||
@ -165,7 +162,7 @@ class TimetablePresenter @Inject constructor(
|
||||
}
|
||||
.logResourceStatus("load timetable data")
|
||||
.onResourceData {
|
||||
isWeekendHasLessons = isWeekendHasLessons || isWeekendHasLessons(it.lessons)
|
||||
isWeekendHasLessons = isWeekendHasLessons || isWeekendHasLessonsUseCase(it.lessons)
|
||||
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
@ -199,15 +196,7 @@ class TimetablePresenter @Inject constructor(
|
||||
|
||||
private suspend fun checkInitialAndCurrentDate(student: Student, semester: Semester) {
|
||||
if (initialDate == null) {
|
||||
val lessons = timetableRepository.getTimetable(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = now().monday,
|
||||
end = now().sunday,
|
||||
forceRefresh = false,
|
||||
timetableType = TimetableRepository.TimetableType.NORMAL
|
||||
).toFirstResult().dataOrNull?.lessons.orEmpty()
|
||||
isWeekendHasLessons = isWeekendHasLessons(lessons)
|
||||
isWeekendHasLessons = isStudentHasLessonsOnWeekendUseCase(student, semester)
|
||||
initialDate = getInitialDate(semester)
|
||||
}
|
||||
|
||||
@ -216,15 +205,6 @@ class TimetablePresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun isWeekendHasLessons(
|
||||
lessons: List<Timetable>,
|
||||
): Boolean = lessons.any {
|
||||
it.date.dayOfWeek in listOf(
|
||||
DayOfWeek.SATURDAY,
|
||||
DayOfWeek.SUNDAY,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getInitialDate(semester: Semester): LocalDate {
|
||||
val now = now()
|
||||
|
||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.utils
|
||||
import android.content.res.Resources
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.CloudflareVerificationException
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.ScrapperException
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.ServiceUnavailableException
|
||||
@ -34,6 +35,7 @@ fun Resources.getErrorString(error: Throwable): String = when (error) {
|
||||
is FeatureNotAvailableException -> R.string.error_feature_not_available
|
||||
is VulcanException -> R.string.error_unknown_uonet
|
||||
is ScrapperException -> R.string.error_unknown_app
|
||||
is CloudflareVerificationException -> R.string.error_cloudflare_captcha
|
||||
is SSLHandshakeException -> when {
|
||||
error.isCausedByCertificateNotValidNow() -> R.string.error_invalid_device_datetime
|
||||
else -> R.string.error_timeout
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import timber.log.Timber
|
||||
@ -30,3 +31,12 @@ fun Sdk.init(student: Student): Sdk {
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
fun Sdk.switchSemester(semester: Semester): Sdk {
|
||||
return switchDiary(
|
||||
diaryId = semester.diaryId,
|
||||
kindergartenDiaryId = semester.kindergartenDiaryId,
|
||||
schoolYear = semester.schoolYear,
|
||||
unitId = semester.unitId,
|
||||
)
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.util.AndroidRuntimeException
|
||||
import java.net.CookiePolicy
|
||||
import java.net.CookieStore
|
||||
import java.net.HttpCookie
|
||||
import java.net.URI
|
||||
import android.webkit.CookieManager as WebkitCookieManager
|
||||
import java.net.CookieManager as JavaCookieManager
|
||||
|
||||
class WebkitCookieManagerProxy : JavaCookieManager(null, CookiePolicy.ACCEPT_ALL) {
|
||||
|
||||
private val webkitCookieManager: WebkitCookieManager? = getWebkitCookieManager()
|
||||
|
||||
/**
|
||||
* @see [https://stackoverflow.com/a/70354583/6695449]
|
||||
*/
|
||||
private fun getWebkitCookieManager(): WebkitCookieManager? {
|
||||
return try {
|
||||
WebkitCookieManager.getInstance()
|
||||
} catch (e: AndroidRuntimeException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun put(uri: URI?, responseHeaders: Map<String?, List<String?>>?) {
|
||||
if (uri == null || responseHeaders == null) return
|
||||
val url = uri.toString()
|
||||
for (headerKey in responseHeaders.keys) {
|
||||
if (headerKey == null || !(
|
||||
headerKey.equals("Set-Cookie2", ignoreCase = true) ||
|
||||
headerKey.equals("Set-Cookie", ignoreCase = true)
|
||||
)
|
||||
) continue
|
||||
|
||||
// process each of the headers
|
||||
for (headerValue in responseHeaders[headerKey].orEmpty()) {
|
||||
webkitCookieManager?.setCookie(url, headerValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun get(
|
||||
uri: URI?,
|
||||
requestHeaders: Map<String?, List<String?>?>?
|
||||
): Map<String, List<String>> {
|
||||
require(!(uri == null || requestHeaders == null)) { "Argument is null" }
|
||||
val res = mutableMapOf<String, List<String>>()
|
||||
val cookie = webkitCookieManager?.getCookie(uri.toString())
|
||||
if (cookie != null) res["Cookie"] = listOf(cookie)
|
||||
return res
|
||||
}
|
||||
|
||||
override fun getCookieStore(): CookieStore {
|
||||
val cookies = super.getCookieStore()
|
||||
return object : CookieStore {
|
||||
override fun add(uri: URI?, cookie: HttpCookie?) = cookies.add(uri, cookie)
|
||||
override fun get(uri: URI?): List<HttpCookie> = cookies.get(uri)
|
||||
override fun getCookies(): List<HttpCookie> = cookies.cookies
|
||||
override fun getURIs(): List<URI> = cookies.urIs
|
||||
override fun remove(uri: URI?, cookie: HttpCookie?): Boolean =
|
||||
cookies.remove(uri, cookie)
|
||||
|
||||
override fun removeAll(): Boolean {
|
||||
webkitCookieManager?.removeAllCookies(null) ?: return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
Wersja 2.3.3
|
||||
Wersja 2.4.1
|
||||
|
||||
— poprawiliśmy kolejne usterki przy odświeżaniu danych (teraz to powinno działać już dużo lepiej)
|
||||
- drobne poprawki stabilności aplikacji i odświeżania danych
|
||||
|
||||
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
||||
|
10
app/src/main/res/drawable/ic_close.xml
Normal file
10
app/src/main/res/drawable/ic_close.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector android:height="24dp"
|
||||
android:tint="#000000"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
|
||||
</vector>
|
51
app/src/main/res/layout/dialog_captcha.xml
Normal file
51
app/src/main/res/layout/dialog_captcha.xml
Normal file
@ -0,0 +1,51 @@
|
||||
<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:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="350dp"
|
||||
tools:context=".ui.modules.captcha.CaptchaDialog">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/captcha_dialog_title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/captcha_close"
|
||||
app:layout_constraintEnd_toStartOf="@id/captcha_refresh"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/captcha_refresh"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:contentDescription="@string/logviewer_refresh"
|
||||
app:icon="@drawable/ic_refresh"
|
||||
app:iconTint="?colorOnSurface"
|
||||
app:layout_constraintEnd_toStartOf="@id/captcha_close"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/captcha_close"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:contentDescription="@string/all_close"
|
||||
app:icon="@drawable/ic_all_close_circle"
|
||||
app:iconTint="?colorOnSurface"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<WebView
|
||||
android:id="@+id/captcha_webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/captcha_close" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -18,7 +18,8 @@
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/dashboard_swipe"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
tools:visibility="gone">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/dashboard_recycler"
|
||||
@ -30,19 +31,33 @@
|
||||
tools:listitem="@layout/item_dashboard_grades" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<LinearLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/dashboard_error_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
tools:ignore="UseCompoundDrawables"
|
||||
tools:visibility="visible">
|
||||
|
||||
<include
|
||||
android:id="@+id/dashboard_error_admin_message"
|
||||
layout="@layout/item_dashboard_admin_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dashboard_error_image"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/dashboard_error_message"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/dashboard_error_admin_message"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:srcCompat="@drawable/ic_error"
|
||||
app:tint="?colorOnBackground"
|
||||
tools:ignore="contentDescription" />
|
||||
@ -55,14 +70,21 @@
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/error_unknown"
|
||||
android:textSize="20sp" />
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/dashboard_error_buttons"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/dashboard_error_image" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dashboard_error_buttons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/dashboard_error_message">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/dashboard_error_details"
|
||||
@ -79,5 +101,5 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/all_retry" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -261,6 +261,7 @@
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:hint="@string/login_domain_suffix_hint"
|
||||
app:errorEnabled="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginFormHostLayout"
|
||||
|
@ -34,11 +34,24 @@
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/dashboard_admin_message_item_close"
|
||||
app:layout_constraintStart_toEndOf="@id/dashboard_admin_message_item_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dashboard_admin_message_item_close"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:padding="12dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_close"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dashboard_admin_message_item_description"
|
||||
android:layout_width="0dp"
|
||||
|
@ -64,10 +64,12 @@
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/ic_all_divider"
|
||||
android:layout_height="1dp" />
|
||||
android:layout_height="1dp"
|
||||
android:id="@+id/gradeSummaryItemPointsDivider"
|
||||
android:background="@drawable/ic_all_divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gradeSummaryItemPredictedContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="35dp"
|
||||
@ -96,10 +98,12 @@
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/ic_all_divider"
|
||||
android:layout_height="1dp" />
|
||||
android:id="@+id/gradeSummaryItemPredictedDivider"
|
||||
android:layout_height="1dp"
|
||||
android:background="@drawable/ic_all_divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gradeSummaryItemFinalContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="35dp"
|
||||
@ -128,6 +132,36 @@
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/ic_all_divider"
|
||||
android:layout_height="1dp" />
|
||||
android:layout_height="1dp"
|
||||
android:id="@+id/gradeSummaryItemFinalDivider"
|
||||
android:background="@drawable/ic_all_divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gradeSummaryItemDescriptiveContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="35dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="7dp"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:text="@string/grade_summary_descriptive"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/gradeSummaryItemDescriptive"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="7dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="7dp"
|
||||
android:textSize="14sp"
|
||||
tools:maxLines="4"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
@ -13,6 +13,7 @@
|
||||
<string name="logviewer_title">Prohlížeč protokolů</string>
|
||||
<string name="debug_title">Ladění</string>
|
||||
<string name="notification_debug_title">Ladění oznámení</string>
|
||||
<string name="debug_cookies_clear">Vymazat soubory cookie webview</string>
|
||||
<string name="contributors_title">Tvůrci</string>
|
||||
<string name="license_title">Licence</string>
|
||||
<string name="message_title">Zprávy</string>
|
||||
@ -55,6 +56,7 @@
|
||||
<string name="login_invalid_email">Neplatný e-mail</string>
|
||||
<string name="login_invalid_login">Místo e-mailu použijte přiřazené přihlašovací údaje</string>
|
||||
<string name="login_invalid_custom_email">Použijte přiřazené přihlašovací nebo e-mail v @%1$s</string>
|
||||
<string name="login_invalid_domain_suffix">Invalid domain suffix</string>
|
||||
<string name="login_invalid_symbol">Neplatný symbol. Pokud jej nemůžete najít, kontaktujte školu</string>
|
||||
<string name="login_invalid_symbol_definitely">Nevymýšlejte si! Pokud symbol nemůžete najít, kontaktujte školu</string>
|
||||
<string name="login_incorrect_symbol">Žák nebyl nalezen. Zkontrolujte správnost symbolu a vybrané varianty deníku UONET+</string>
|
||||
@ -116,6 +118,7 @@
|
||||
<string name="grade_summary_points">Součet bodů</string>
|
||||
<string name="grade_summary_final_grade">Konečná známka</string>
|
||||
<string name="grade_summary_predicted_grade">Předpokládaná známka</string>
|
||||
<string name="grade_summary_descriptive">Popisná známka</string>
|
||||
<string name="grade_summary_calculated_average">Vypočítaný průměr</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_title">Jak funguje vypočítaný průměr?</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_message">Vypočítaný průměr je aritmetický průměr vypočítaný z průměrů předmětů. Umožňuje vám to znát přibližný konečný průměr. Vypočítává se způsobem zvoleným uživatelem v nastavení aplikaci. Doporučuje se vybrat příslušnou možnost. Důvodem je rozdílný výpočet školních průměrů. Pokud vaše škola navíc uvádí průměr předmětů na stránce deníku Vulcan, aplikace si je stáhne a tyto průměry nepočítá. To lze změnit vynucením výpočtu průměru v nastavení aplikaci.\n\n<b>Průměr známek pouze z vybraného semestru</b>:\n1. Výpočet váženého průměru pro každý předmět v daném semestru\n2. Sčítání vypočítaných průměrů\n3. Výpočet aritmetického průměru součtených průměrů\n\n<b>Průměr průměrů z obou semestrů</b>:\n1. Výpočet váženého průměru pro každý předmět v semestru 1 a 2\n2. Výpočet aritmetického průměru vypočítaných průměrů za semestry 1 a 2 pro každý předmět.\n3. Sčítání vypočítaných průměrů\n4. Výpočet aritmetického průměru sečtených průměrů\n\n<b>Průměr známek z celého roku:</b>\n1. Výpočet váženého průměru za rok pro každý předmět. Konečný průměr v 1. semestru je nepodstatný.\n2. Sčítání vypočítaných průměrů\n3. Výpočet aritmetického průměru součtených průměrů</string>
|
||||
@ -159,6 +162,12 @@
|
||||
<item quantity="many">Nové konečné známky</item>
|
||||
<item quantity="other">Nové konečné známky</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_descriptive">
|
||||
<item quantity="one">Nová popisná známka</item>
|
||||
<item quantity="few">Nové popisné známky</item>
|
||||
<item quantity="many">Nové popisné známky</item>
|
||||
<item quantity="other">Nové popisné známky</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items">
|
||||
<item quantity="one">Máte %1$d novou známku</item>
|
||||
<item quantity="few">Máte %1$d nové známky</item>
|
||||
@ -177,6 +186,12 @@
|
||||
<item quantity="many">Máte %1$d nových konečných známek</item>
|
||||
<item quantity="other">Máte %1$d nových konečných známek</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_descriptive">
|
||||
<item quantity="one">Máte %1$d novou popisnou známku</item>
|
||||
<item quantity="few">Máte %1$d nové popisné známky</item>
|
||||
<item quantity="many">Máte %1$d nových popisných známek</item>
|
||||
<item quantity="other">Máte %1$d nových popisných známek</item>
|
||||
</plurals>
|
||||
<!--Timetable-->
|
||||
<string name="timetable_lesson">Lekce</string>
|
||||
<string name="timetable_room">Učebna</string>
|
||||
@ -833,6 +848,9 @@
|
||||
<string name="auth_title">Autorizace</string>
|
||||
<string name="auth_description">Pro provoz aplikace potřebujeme potvrdit vaši identitu. Zadejte PESEL žáka <b>%1$s</b> v níže uvedeném poli</string>
|
||||
<string name="auth_button_skip">Zatím přeskočit</string>
|
||||
<!--Captcha-->
|
||||
<string name="captcha_dialog_title">Probíhá ověřování. Počkejte…</string>
|
||||
<string name="captcha_verified_message">Úspěšně ověřeno</string>
|
||||
<!--Errors-->
|
||||
<string name="error_no_internet">Žádné internetové připojení</string>
|
||||
<string name="error_invalid_device_datetime">Vyskytla se chyba. Zkontrolujte hodiny svého zařízení</string>
|
||||
@ -842,6 +860,7 @@
|
||||
<string name="error_service_unavailable">Probíhá údržba deníku UONET+. Zkuste to později znovu</string>
|
||||
<string name="error_unknown_uonet">Neznámá chyba deniku 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_cloudflare_captcha">Vyžadováno ověření Captcha</string>
|
||||
<string name="error_unknown">Vyskytla se neočekávaná chyba</string>
|
||||
<string name="error_feature_disabled">Funkce je deaktivována přes 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>
|
||||
|
@ -1,759 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!--Activity/Fragment title-->
|
||||
<string name="login_title">Login</string>
|
||||
<string name="main_title">Wulkanowy</string>
|
||||
<string name="grade_title">Grades</string>
|
||||
<string name="attendance_title">Attendance</string>
|
||||
<string name="exam_title">Exams</string>
|
||||
<string name="timetable_title">Timetable</string>
|
||||
<string name="settings_title">Settings</string>
|
||||
<string name="more_title">More</string>
|
||||
<string name="about_title">About</string>
|
||||
<string name="logviewer_title">Log viewer</string>
|
||||
<string name="debug_title">Debug</string>
|
||||
<string name="notification_debug_title">Notification debug</string>
|
||||
<string name="contributors_title">Contributors</string>
|
||||
<string name="license_title">Licenses</string>
|
||||
<string name="message_title">Messages</string>
|
||||
<string name="send_message_title">New message</string>
|
||||
<string name="add_homework_title">New homework</string>
|
||||
<string name="note_title">Notes and achievements</string>
|
||||
<string name="homework_title">Homework</string>
|
||||
<string name="account_title">Accounts manager</string>
|
||||
<string name="account_quick_title">Select account</string>
|
||||
<string name="account_details_title">Account details</string>
|
||||
<string name="student_info_title">Student info</string>
|
||||
<string name="dashboard_title">Dashboard</string>
|
||||
<string name="notifications_center_title">Notifications center</string>
|
||||
<string name="menu_order_title">Menu configuartion</string>
|
||||
<!--Subtitles-->
|
||||
<string name="grade_subtitle">Semester %1$d, %2$d/%3$d</string>
|
||||
<!--Login-->
|
||||
<string name="login_header_default">Sign in with the student or parent account</string>
|
||||
<string name="login_header_symbol">Enter the symbol from the register page for account: <b>%1$s</b></string>
|
||||
<string name="login_nickname_hint">Username</string>
|
||||
<string name="login_email_hint">Email</string>
|
||||
<string name="login_login_pesel_email_hint">Login, PESEL or e-mail</string>
|
||||
<string name="login_password_hint">Password</string>
|
||||
<string name="login_host_hint">UONET+ register variant</string>
|
||||
<string name="login_domain_suffix_hint">Custom domain suffix</string>
|
||||
<string name="login_type_api">Mobile API</string>
|
||||
<string name="login_type_scrapper">Scraper</string>
|
||||
<string name="login_type_hybrid">Hybrid</string>
|
||||
<string name="login_token_hint">Token</string>
|
||||
<string name="login_pin_hint">PIN</string>
|
||||
<string name="login_symbol_hint">Symbol</string>
|
||||
<string name="login_symbol_placeholder">E.g. \"lodz\" or \"powiatjaroslawski\"</string>
|
||||
<string name="login_sign_in">Sign in</string>
|
||||
<string name="login_invalid_password">Password too short</string>
|
||||
<string name="login_incorrect_password_default">Login details are incorrect</string>
|
||||
<string name="login_incorrect_password">%1$s. Make sure the correct UONET+ register variation is selected below</string>
|
||||
<string name="login_invalid_pin">Invalid PIN</string>
|
||||
<string name="login_invalid_token">Invalid token</string>
|
||||
<string name="login_expired_token">Token expired</string>
|
||||
<string name="login_invalid_email">Invalid email</string>
|
||||
<string name="login_invalid_login">Use the assigned login instead of email</string>
|
||||
<string name="login_invalid_custom_email">Use the assigned login or email in @%1$s</string>
|
||||
<string name="login_invalid_symbol">Invalid symbol. If you cannot find it, please contact the school</string>
|
||||
<string name="login_invalid_symbol_definitely">Don\'t make this up! If you cannot find it, please contact the school</string>
|
||||
<string name="login_incorrect_symbol">Student not found. Validate the symbol and the chosen variation of the UONET+ register</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 <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Wygeneruj kod dostępu</b>.\n\nMake sure that you have set the appropriate register variant in the <b>UONET+ register variant</b> field on the first login screen</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_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_scraper">This mode displays the same data as it appears on the register website</string>
|
||||
<string name="login_advanced_warning_hybrid">The combination of the best features of the other two modes. It works faster than scraper and provides features not available in the Mobile API mode. It is in the experimental phase</string>
|
||||
<string name="login_privacy_policy">Privacy policy</string>
|
||||
<string name="login_contact_header">Trouble signing in? Contact us!</string>
|
||||
<string name="login_contact_email">Email</string>
|
||||
<string name="login_contact_discord">Discord</string>
|
||||
<string name="login_email_intent_title">Send email</string>
|
||||
<string name="login_recover_warning">Make sure you select the correct UONET+ register variation!</string>
|
||||
<string name="login_recover_button">Reset password</string>
|
||||
<string name="login_recover_title">Recover your account</string>
|
||||
<string name="login_recover">Recover</string>
|
||||
<string name="login_signed_in">Student is already signed in</string>
|
||||
<string name="login_host_standard">Standard</string>
|
||||
<string name="login_other_search_locations">Other search locations</string>
|
||||
<string name="login_no_active_student">No active students found</string>
|
||||
<string name="login_symbol_enter">Enter a different symbol</string>
|
||||
<string name="login_support_title">Get help</string>
|
||||
<string name="login_support_school_hint">Full school name with the town (required)</string>
|
||||
<string name="login_support_school_placeholder">Np. ZSTiO Jarosław lub SP nr 99 w Łodzi</string>
|
||||
<string name="login_support_school_invalid">Enter correct name of the school</string>
|
||||
<string name="login_support_additional_hint">Additional information in Polish (optional)</string>
|
||||
<string name="login_support_additional_placeholder">Np. \"Ostatnio zmieniłem szkołę i…\" albo \"Jestem rodzicem i nie widzę drugiego dziecka…\"</string>
|
||||
<string name="login_support_submit">Submit</string>
|
||||
<!--Notifications-->
|
||||
<string name="notifications_header_title">Enable notifications</string>
|
||||
<string name="notifications_header_description">Enable notifications so you don\'t miss message from teacher or new grade</string>
|
||||
<string name="notifications_skip">Skip</string>
|
||||
<string name="notifications_enable">Enable</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Account manager</string>
|
||||
<string name="main_log_in">Log in</string>
|
||||
<string name="main_session_expired">Session expired</string>
|
||||
<string name="main_session_relogin">Session expired, log in again</string>
|
||||
<string name="main_expired_credentials_description">Your account password has been changed. You need to log in to Wulkanowy again</string>
|
||||
<string name="main_expired_credentials_title">Password changed</string>
|
||||
<string name="main_support_title">Application support</string>
|
||||
<string name="main_support_description">Do you like this app? Support its development by enabling non-invasive ads that you can disable at any time</string>
|
||||
<string name="main_support_positive">Enable ads</string>
|
||||
<!--Grade-->
|
||||
<string name="grade_header">Grade</string>
|
||||
<string name="grade_semester">Semester %d</string>
|
||||
<string name="grade_switch_semester">Change semester</string>
|
||||
<string name="grade_no_items">No grades</string>
|
||||
<string name="grade_weight">Weight</string>
|
||||
<string name="grade_weight_value">Weight: %s</string>
|
||||
<string name="grade_comment">Comment</string>
|
||||
<string name="grade_number_new_items">Number of new ratings: %1$d</string>
|
||||
<string name="grade_average">Average: %1$.2f</string>
|
||||
<string name="grade_points_sum">Points: %s</string>
|
||||
<string name="grade_no_average">No average</string>
|
||||
<string name="grade_summary_points">Total points</string>
|
||||
<string name="grade_summary_final_grade">Final grade</string>
|
||||
<string name="grade_summary_predicted_grade">Predicted grade</string>
|
||||
<string name="grade_summary_calculated_average">Calculated average</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_title">How does Calculated Average work?</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_message">The Calculated Average is the arithmetic average calculated from the subjects averages. It allows you to know the approximate final average. It is calculated in a way selected by the user in the application settings. It is recommended that you choose the appropriate option. This is because the calculation of school averages differs. Additionally, if your school reports the average of the subjects on the Vulcan page, the application downloads them and does not calculate these averages. This can be changed by forcing the calculation of the average in the application settings.\n\n<b>Average of grades only from selected semester</b>:\n1. Calculating the weighted average for each subject in a given semester\n2.Adding calculated averages\n3. Calculation of the arithmetic average of the summed averages\n\n<b>Average of averages from both semesters</b>:\n1.Calculating the weighted average for each subject in semester 1 and 2\n2. Calculating the arithmetic average of the calculated averages for semesters 1 and 2 for each subject.\n3. Adding calculated averages\n4. Calculation of the arithmetic average of the summed averages\n\n<b>Average of grades from the whole year:</b>\n1. Calculating weighted average over the year for each subject. The final average in the 1st semester is irrelevant.\n2. Adding calculated averages\n3. Calculating the arithmetic average of summed averages</string>
|
||||
<string name="grade_summary_final_average_help_dialog_title">How does the Final Average work?</string>
|
||||
<string name="grade_summary_final_average_help_dialog_message">The Final Average is the arithmetic average calculated from all currently available final grades in the given semester.\n\nThe calculation scheme consists of the following steps:\n1. Summing up the final grades given by teachers\n2. Divide by the number of subjects that have already been graded</string>
|
||||
<string name="grade_summary_final_average">Final average</string>
|
||||
<string name="grade_summary_from_subjects">from %1$d of %2$d subjects</string>
|
||||
<string name="grade_menu_summary">Summary</string>
|
||||
<string name="grade_menu_statistics">Class</string>
|
||||
<string name="grade_menu_read">Mark as read</string>
|
||||
<string name="grade_statistics_partial">Partial</string>
|
||||
<string name="grade_statistics_semester">Semester</string>
|
||||
<string name="grade_statistics_points">Points</string>
|
||||
<string name="grade_statistics_legend">Legend</string>
|
||||
<string name="grade_statistics_class_average">Class average: %1$s</string>
|
||||
<string name="grade_statistics_student_average">Your average: %1$s</string>
|
||||
<string name="grade_statistics_student_grade">Your grade: %1$s</string>
|
||||
<string name="grade_statistics_average_class">Class</string>
|
||||
<string name="grade_statistics_average_student">Student</string>
|
||||
<plurals name="grade_number_item">
|
||||
<item quantity="one">%d grade</item>
|
||||
<item quantity="other">%d grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items">
|
||||
<item quantity="one">New grade</item>
|
||||
<item quantity="other">New grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_predicted">
|
||||
<item quantity="one">New predicted grade</item>
|
||||
<item quantity="other">New predicted grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_final">
|
||||
<item quantity="one">New final grade</item>
|
||||
<item quantity="other">New final grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items">
|
||||
<item quantity="one">You received %1$d grade</item>
|
||||
<item quantity="other">You received %1$d grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_predicted">
|
||||
<item quantity="one">You received %1$d predicted grade</item>
|
||||
<item quantity="other">You received %1$d predicted grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_final">
|
||||
<item quantity="one">You received %1$d final grade</item>
|
||||
<item quantity="other">You received %1$d final grades</item>
|
||||
</plurals>
|
||||
<!--Timetable-->
|
||||
<string name="timetable_lesson">Lesson</string>
|
||||
<string name="timetable_room">Room</string>
|
||||
<string name="timetable_group">Group</string>
|
||||
<string name="timetable_time">Hours</string>
|
||||
<string name="timetable_changes">Changes</string>
|
||||
<string name="timetable_no_items">No lessons this day</string>
|
||||
<string name="timetable_minutes">%s min</string>
|
||||
<string name="timetable_seconds">%s sec</string>
|
||||
<string name="timetable_time_left">%1$s left</string>
|
||||
<string name="timetable_time_until">in %1$s</string>
|
||||
<string name="timetable_finished">Finished</string>
|
||||
<string name="timetable_now">Now: %s</string>
|
||||
<string name="timetable_next">Next: %s</string>
|
||||
<string name="timetable_later">Later: %s</string>
|
||||
<string name="timetable_notify_lesson">%1$s lesson %2$d - %3$s</string>
|
||||
<string name="timetable_notify_change_room">Change of room from %1$s to %2$s</string>
|
||||
<string name="timetable_notify_change_teacher">Change of teacher from %1$s to %2$s</string>
|
||||
<string name="timetable_notify_change_subject">Change of subject from %1$s to %2$s</string>
|
||||
<plurals name="timetable_no_lesson">
|
||||
<item quantity="one">No lesson</item>
|
||||
<item quantity="other">No lessons</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_notify_new_items_title">
|
||||
<item quantity="one">Timetable change</item>
|
||||
<item quantity="other">Timetable changes</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_notify_new_items">
|
||||
<item quantity="one">%1$s - %2$d change in timetable</item>
|
||||
<item quantity="other">%1$s - %2$d changes in timetable</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_notify_new_items_group">
|
||||
<item quantity="one">%1$d change in timetable</item>
|
||||
<item quantity="other">%1$d changes in timetable</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_number_item">
|
||||
<item quantity="one">%d change</item>
|
||||
<item quantity="other">%d changes</item>
|
||||
</plurals>
|
||||
<!--Completed lessons-->
|
||||
<string name="completed_lessons_title">Completed lessons</string>
|
||||
<string name="completed_lessons_button">Show completed lessons</string>
|
||||
<string name="completed_lessons_no_items">No info about completed lessons</string>
|
||||
<string name="completed_lessons_topic">Topic</string>
|
||||
<string name="completed_lessons_absence">Absence</string>
|
||||
<string name="completed_lessons_resources">Resources</string>
|
||||
<!--Additional lessons-->
|
||||
<string name="additional_lessons_title">Additional lessons</string>
|
||||
<string name="additional_lessons_button">Show additional lessons</string>
|
||||
<string name="additional_lessons_no_items">No info about additional lessons</string>
|
||||
<string name="additional_lessons_add">New lesson</string>
|
||||
<string name="additional_lessons_add_title">New additional lesson</string>
|
||||
<string name="additional_lessons_add_success">Additional lesson added successfully</string>
|
||||
<string name="additional_lessons_delete_success">Additional lesson deleted successfully</string>
|
||||
<string name="additional_lessons_repeat">Repeat weekly</string>
|
||||
<string name="additional_lessons_delete_title">Delete additional lesson</string>
|
||||
<string name="additional_lessons_delete_one">Just this lesson</string>
|
||||
<string name="additional_lessons_delete_series">All in the series</string>
|
||||
<string name="additional_lessons_start">Start time</string>
|
||||
<string name="additional_lessons_end">End time</string>
|
||||
<string name="additional_lessons_end_time_error">End time must be greater than start time</string>
|
||||
<!--Attendance-->
|
||||
<string name="attendance_summary_button">Attendance summary</string>
|
||||
<string name="attendance_absence_school">Absent for school reasons</string>
|
||||
<string name="attendance_absence_excused">Excused absence</string>
|
||||
<string name="attendance_absence_unexcused">Unexcused absence</string>
|
||||
<string name="attendance_exemption">Exemption</string>
|
||||
<string name="attendance_excused_lateness">Excused lateness</string>
|
||||
<string name="attendance_unexcused_lateness">Unexcused lateness</string>
|
||||
<string name="attendance_present">Present</string>
|
||||
<string name="attendance_deleted">Deleted</string>
|
||||
<string name="attendance_unknown">Unknown</string>
|
||||
<string name="attendance_number">Number of lesson</string>
|
||||
<string name="attendance_no_items">No entries</string>
|
||||
<string name="attendance_excuse_dialog_reason">Absence reason (optional)</string>
|
||||
<string name="attendance_excuse_dialog_submit">Send</string>
|
||||
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
|
||||
<string name="attendance_excuse_no_selection">You must select at least one absence!</string>
|
||||
<string name="attendance_excuse_title">Excuse</string>
|
||||
<plurals name="attendance_notify_new_items_title">
|
||||
<item quantity="one">New attendance</item>
|
||||
<item quantity="other">New attendance</item>
|
||||
</plurals>
|
||||
<plurals name="attendance_notify_new_items">
|
||||
<item quantity="one">%1$d new attendance</item>
|
||||
<item quantity="other">%1$d attendance</item>
|
||||
</plurals>
|
||||
<plurals name="attendance_number_item">
|
||||
<item quantity="one">%d attendance</item>
|
||||
<item quantity="other">%d attendance</item>
|
||||
</plurals>
|
||||
<!--Attendance summary-->
|
||||
<string name="attendance_summary_total">Total</string>
|
||||
<!--Exam-->
|
||||
<string name="exam_no_items">No exams this week</string>
|
||||
<string name="exam_type">Type</string>
|
||||
<string name="exam_entry_date">Entry date</string>
|
||||
<plurals name="exam_notify_new_item_title">
|
||||
<item quantity="one">New exam</item>
|
||||
<item quantity="other">New exams</item>
|
||||
</plurals>
|
||||
<plurals name="exam_notify_new_item_content">
|
||||
<item quantity="one">%d new exam</item>
|
||||
<item quantity="other">%d new exams</item>
|
||||
</plurals>
|
||||
<plurals name="exam_number_item">
|
||||
<item quantity="one">%d exam</item>
|
||||
<item quantity="other">%d exams</item>
|
||||
</plurals>
|
||||
<!--Message-->
|
||||
<string name="message_inbox">Inbox</string>
|
||||
<string name="message_sent">Sent</string>
|
||||
<string name="message_trash">Trash</string>
|
||||
<string name="message_no_subject">(no subject)</string>
|
||||
<string name="message_no_items">No messages</string>
|
||||
<string name="message_from">From:</string>
|
||||
<string name="message_to">To:</string>
|
||||
<string name="message_date">Date: %1$s</string>
|
||||
<string name="message_reply">Reply</string>
|
||||
<string name="message_forward">Forward</string>
|
||||
<string name="message_select_all">Select all</string>
|
||||
<string name="message_unselect_all">Unselect all</string>
|
||||
<string name="message_move_to_trash">Move to trash</string>
|
||||
<string name="message_delete_forever">Delete permanently</string>
|
||||
<string name="message_delete_success">Message deleted successfully</string>
|
||||
<string name="message_mailbox_type_student">student</string>
|
||||
<string name="message_mailbox_type_parent">parent</string>
|
||||
<string name="message_mailbox_type_guardian">guardian</string>
|
||||
<string name="message_mailbox_type_employee">employee</string>
|
||||
<string name="message_share">Share</string>
|
||||
<string name="message_print">Print</string>
|
||||
<string name="message_subject">Subject</string>
|
||||
<string name="message_content">Content</string>
|
||||
<string name="message_send_successful">Message sent successfully</string>
|
||||
<string name="message_not_exists">Message does not exist</string>
|
||||
<string name="message_required_recipients">You need to choose at least 1 recipient</string>
|
||||
<string name="message_content_min_length">The message content must be at least 3 characters</string>
|
||||
<string name="message_chip_all_mailboxes">All mailboxes</string>
|
||||
<string name="message_chip_only_unread">Only unread</string>
|
||||
<string name="message_chip_only_with_attachments">Only with attachments</string>
|
||||
<string name="message_read">Read: %s</string>
|
||||
<string name="message_read_by">Read by: %1$d of %2$d people</string>
|
||||
<plurals name="message_number_item">
|
||||
<item quantity="one">%1$d message</item>
|
||||
<item quantity="other">%1$d messages</item>
|
||||
</plurals>
|
||||
<plurals name="message_new_items">
|
||||
<item quantity="one">New message</item>
|
||||
<item quantity="other">New messages</item>
|
||||
</plurals>
|
||||
<string name="message_restore_dialog">Do you want to restore draft message?</string>
|
||||
<string name="message_restore_dialog_with_recipients">Do you want to restore draft message with recipients: %s?</string>
|
||||
<plurals name="message_notify_new_items">
|
||||
<item quantity="one">You received %1$d message</item>
|
||||
<item quantity="other">You received %1$d messages</item>
|
||||
</plurals>
|
||||
<plurals name="message_selected_messages_count">
|
||||
<item quantity="one">%1$d selected</item>
|
||||
<item quantity="other">%1$d selected</item>
|
||||
</plurals>
|
||||
<string name="message_messages_deleted">Messages deleted</string>
|
||||
<string name="message_mailbox_chooser_title">Choose mailbox</string>
|
||||
<string name="message_incognito_mode_on">Incognito mode is on</string>
|
||||
<string name="message_incognito_description">Thanks to incognito mode sender is not notified when you read the message</string>
|
||||
<!--Note-->
|
||||
<string name="note_no_items">No info about notes</string>
|
||||
<string name="note_points">Points</string>
|
||||
<plurals name="note_number_item">
|
||||
<item quantity="one">%d note</item>
|
||||
<item quantity="other">%d notes</item>
|
||||
</plurals>
|
||||
<plurals name="note_new_items">
|
||||
<item quantity="one">New note</item>
|
||||
<item quantity="other">New notes</item>
|
||||
</plurals>
|
||||
<plurals name="note_notify_new_items">
|
||||
<item quantity="one">You received %1$d note</item>
|
||||
<item quantity="other">You received %1$d notes</item>
|
||||
</plurals>
|
||||
<!--Praise-->
|
||||
<plurals name="praise_number_item">
|
||||
<item quantity="one">%d praise</item>
|
||||
<item quantity="other">%d praises</item>
|
||||
</plurals>
|
||||
<plurals name="praise_new_items">
|
||||
<item quantity="one">New praise</item>
|
||||
<item quantity="other">New praises</item>
|
||||
</plurals>
|
||||
<plurals name="praise_notify_new_items">
|
||||
<item quantity="one">You received %1$d praise</item>
|
||||
<item quantity="other">You received %1$d praises</item>
|
||||
</plurals>
|
||||
<!--Neutral notes-->
|
||||
<plurals name="neutral_note_number_item">
|
||||
<item quantity="one">%d neutral note</item>
|
||||
<item quantity="other">%d neutral notes</item>
|
||||
</plurals>
|
||||
<plurals name="neutral_note_new_items">
|
||||
<item quantity="one">New neutral note</item>
|
||||
<item quantity="other">New neutral notes</item>
|
||||
</plurals>
|
||||
<plurals name="neutral_note_notify_new_items">
|
||||
<item quantity="one">You received %1$d neutral note</item>
|
||||
<item quantity="other">You received %1$d neutral notes</item>
|
||||
</plurals>
|
||||
<!--Homework-->
|
||||
<string name="homework_no_items">No info about homework</string>
|
||||
<string name="homework_mark_as_done">Mark as done</string>
|
||||
<string name="homework_mark_as_undone">Mark as undone</string>
|
||||
<string name="homework_add">Add homework</string>
|
||||
<string name="homework_add_success">Homework added successfully</string>
|
||||
<string name="homework_delete_success">Homework deleted successfully</string>
|
||||
<string name="homework_attachments">Attachments</string>
|
||||
<plurals name="homework_notify_new_item_title">
|
||||
<item quantity="one">New homework</item>
|
||||
<item quantity="other">New homework</item>
|
||||
</plurals>
|
||||
<plurals name="homework_notify_new_item_content">
|
||||
<item quantity="one">You received %d new homework</item>
|
||||
<item quantity="other">You received %d new homework</item>
|
||||
</plurals>
|
||||
<plurals name="homework_number_item">
|
||||
<item quantity="one">%d homework</item>
|
||||
<item quantity="other">%d homework</item>
|
||||
</plurals>
|
||||
<!--Lucky number-->
|
||||
<string name="lucky_number_title">Lucky number</string>
|
||||
<string name="lucky_number_header">Today\'s lucky number is</string>
|
||||
<string name="lucky_number_empty">No info about the lucky number</string>
|
||||
<string name="lucky_number_notify_new_item_title">Lucky number for today</string>
|
||||
<string name="lucky_number_notify_new_item">Today\'s lucky number is: %s</string>
|
||||
<string name="lucky_number_history_button">Show history</string>
|
||||
<!--Lucky number history-->
|
||||
<string name="lucky_number_history_title">Lucky number history</string>
|
||||
<string name="lucky_number_history_empty">No info about lucky numbers</string>
|
||||
<!--Mobile devices-->
|
||||
<string name="mobile_devices_title">Mobile devices</string>
|
||||
<string name="mobile_devices_no_items">No devices</string>
|
||||
<string name="mobile_devices_unregister">Deregister</string>
|
||||
<string name="mobile_device_removed">Device removed</string>
|
||||
<string name="mobile_device_qr">QR code</string>
|
||||
<string name="mobile_device_token">Token</string>
|
||||
<string name="mobile_device_symbol">Symbol</string>
|
||||
<string name="mobile_device_pin">PIN</string>
|
||||
<!--School and teachers-->
|
||||
<string name="schoolandteachers_title">School and teachers</string>
|
||||
<!--School-->
|
||||
<string name="school_title">School</string>
|
||||
<string name="school_no_info">No info about school</string>
|
||||
<string name="school_name">School name</string>
|
||||
<string name="school_address">School address</string>
|
||||
<string name="school_telephone">Telephone</string>
|
||||
<string name="school_headmaster">Name of headmaster</string>
|
||||
<string name="school_pedagogue">Name of pedagogue</string>
|
||||
<string name="school_address_button">Show on map</string>
|
||||
<string name="school_telephone_button">Call</string>
|
||||
<!--Teacher-->
|
||||
<string name="teachers_title">Teachers</string>
|
||||
<string name="teacher_no_items">No info about teachers</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>
|
||||
<plurals name="conference_number_item">
|
||||
<item quantity="one">%d conference</item>
|
||||
<item quantity="other">%d conferences</item>
|
||||
</plurals>
|
||||
<plurals name="conference_notify_new_item_title">
|
||||
<item quantity="one">New conference</item>
|
||||
<item quantity="other">New conferences</item>
|
||||
</plurals>
|
||||
<plurals name="conference_notify_new_items">
|
||||
<item quantity="one">You have %1$d new conference</item>
|
||||
<item quantity="other">You have %1$d new conferences</item>
|
||||
</plurals>
|
||||
<string name="conferences_present">Present at conference</string>
|
||||
<string name="conference_agenda">Agenda</string>
|
||||
<string name="conference_place">Place</string>
|
||||
<string name="conference_topic">Topic</string>
|
||||
<!--Director information-->
|
||||
<string name="school_announcement_title">School announcements</string>
|
||||
<string name="school_announcement_no_items">No school announcements</string>
|
||||
<plurals name="school_announcement_number_item">
|
||||
<item quantity="one">%d school announcement</item>
|
||||
<item quantity="other">%d school announcements</item>
|
||||
</plurals>
|
||||
<plurals name="school_announcement_notify_new_item_title">
|
||||
<item quantity="one">New school announcement</item>
|
||||
<item quantity="other">New school announcements</item>
|
||||
</plurals>
|
||||
<plurals name="school_announcement_notify_new_items">
|
||||
<item quantity="one">You have %1$d new school announcement</item>
|
||||
<item quantity="other">You have %1$d new school announcements</item>
|
||||
</plurals>
|
||||
<!--Account-->
|
||||
<string name="account_add_new">Add account</string>
|
||||
<string name="account_logout">Logout</string>
|
||||
<string name="account_confirm">Do you want to log out this student?</string>
|
||||
<string name="account_logout_student">Student logout</string>
|
||||
<string name="account_type_student">Student account</string>
|
||||
<string name="account_type_parent">Parent account</string>
|
||||
<string name="account_details_edit">Edit data</string>
|
||||
<string name="account_quick_manager">Accounts manager</string>
|
||||
<string name="account_select_student">Select student</string>
|
||||
<string name="account_family">Family</string>
|
||||
<string name="account_contact">Contact</string>
|
||||
<string name="account_address">Residence details</string>
|
||||
<string name="account_personal_data">Personal information</string>
|
||||
<!--About-->
|
||||
<string name="about_version">App version</string>
|
||||
<string name="about_contributor">Contributors</string>
|
||||
<string name="about_contributor_summary">List of Wulkanowy developers</string>
|
||||
<string name="about_feedback">Report a bug</string>
|
||||
<string name="about_feedback_summary">Send a bug report via e-mail</string>
|
||||
<string name="about_faq">FAQ</string>
|
||||
<string name="about_faq_summary">Read Frequently Asked Questions</string>
|
||||
<string name="about_discord">Discord server</string>
|
||||
<string name="about_discord_summary">Join the Wulkanowy community</string>
|
||||
<string name="about_facebook">Facebook fanpage</string>
|
||||
<string name="about_twitter">Twitter page</string>
|
||||
<string name="about_twitter_summary">Follow us on twitter</string>
|
||||
<string name="about_facebook_summary">Like our facebook fanpage</string>
|
||||
<string name="about_privacy">Privacy policy</string>
|
||||
<string name="about_privacy_summary">Rules for collecting personal data</string>
|
||||
<string name="about_system">System settings</string>
|
||||
<string name="about_system_summary">Open system settings</string>
|
||||
<string name="about_homepage">Homepage</string>
|
||||
<string name="about_homepage_summary">Visit the website and help develop the application</string>
|
||||
<string name="about_licenses">Licenses</string>
|
||||
<string name="about_licenses_summary">Licenses of libraries used in the application</string>
|
||||
<!--Licenses-->
|
||||
<string name="license_dialog_title">License</string>
|
||||
<!--Contributor-->
|
||||
<string name="contributor_avatar_description">Avatar</string>
|
||||
<string name="contributor_see_more">See more on GitHub</string>
|
||||
<!--Student info-->
|
||||
<string name="student_info_empty">No info about student or student family</string>
|
||||
<string name="student_info_first_name">Name</string>
|
||||
<string name="student_info_second_name">Second name</string>
|
||||
<string name="student_info_gender">Gender</string>
|
||||
<string name="student_info_polish_citizenship">Polish citizenship</string>
|
||||
<string name="student_info_family_name">Family name</string>
|
||||
<string name="student_info_parents_name">Mother\'s and father\'s names</string>
|
||||
<string name="student_info_phone">Phone</string>
|
||||
<string name="student_info_cellphone">Cellphone</string>
|
||||
<string name="student_info_email">E-mail</string>
|
||||
<string name="student_info_address">Address of residence</string>
|
||||
<string name="student_info_registered_address">Address of registration</string>
|
||||
<string name="student_info_correspondence_address">Correspondence address</string>
|
||||
<string name="student_info_full_name">Surname and first name</string>
|
||||
<string name="student_info_kinship">Degree of kinship</string>
|
||||
<string name="student_info_guardian_address">Address</string>
|
||||
<string name="student_info_phones">Phones</string>
|
||||
<string name="student_info_male">Male</string>
|
||||
<string name="student_info_female">Female</string>
|
||||
<string name="student_info_last_name">Last name</string>
|
||||
<string name="student_info_guardian">Guardian</string>
|
||||
<!--Account edit-->
|
||||
<string name="account_edit_nick_hint">Nick</string>
|
||||
<string name="account_edit_header">Add nick</string>
|
||||
<string name="account_edit_avatar_title">Choose avatar color</string>
|
||||
<!--Log viewer-->
|
||||
<string name="logviewer_share">Share logs</string>
|
||||
<string name="logviewer_refresh">Refresh</string>
|
||||
<!--Dashboard-->
|
||||
<string name="dashboard_timetable_title">Lessons</string>
|
||||
<string name="dashboard_timetable_title_tomorrow">(Tomorrow)</string>
|
||||
<string name="dashboard_timetable_title_today_and_tomorrow">(Today and tomorrow)</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_moment">In a moment:</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_soon">Soon:</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_first">First:</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_now">Now:</string>
|
||||
<string name="dashboard_timetable_second_lesson_value_end">End of lessons</string>
|
||||
<string name="dashboard_timetable_second_lessons_title">Next:</string>
|
||||
<string name="dashboard_timetable_third_title">Later:</string>
|
||||
<plurals name="dashboard_timetable_third_value">
|
||||
<item quantity="one">%1$d more lesson</item>
|
||||
<item quantity="other">%1$d more lessons</item>
|
||||
</plurals>
|
||||
<string name="dashboard_timetable_third_time">until %1$s</string>
|
||||
<string name="dashboard_timetable_no_lessons">No upcoming lessons</string>
|
||||
<string name="dashboard_timetable_error">An error occurred while loading the lessons</string>
|
||||
<string name="dashboard_homework_title">Homework</string>
|
||||
<string name="dashboard_homework_no_homework">No homework to do</string>
|
||||
<string name="dashboard_homework_error">An error occurred while loading the homework</string>
|
||||
<plurals name="dashboard_homework_more">
|
||||
<item quantity="one">%1$d more homework</item>
|
||||
<item quantity="other">%1$d more homework</item>
|
||||
</plurals>
|
||||
<string name="dashboard_homework_time">due %1$s</string>
|
||||
<string name="dashboard_grade_title">Last grades</string>
|
||||
<string name="dashboard_grade_no_grade">No new grades</string>
|
||||
<string name="dashboard_grade_error">An error occurred while loading the grades</string>
|
||||
<string name="dashboard_announcements_title">School announcements</string>
|
||||
<string name="dashboard_announcements_no_announcements">No current announcements</string>
|
||||
<string name="dashboard_announcements_error">An error occurred while loading the announcements</string>
|
||||
<plurals name="dashboard_announcements_more">
|
||||
<item quantity="one">%1$d more announcement</item>
|
||||
<item quantity="other">%1$d more announcements</item>
|
||||
</plurals>
|
||||
<string name="dashboard_exams_title">Exams</string>
|
||||
<string name="dashboard_exams_no_exams">No upcoming exams</string>
|
||||
<string name="dashboard_exams_error">An error occurred while loading the exams</string>
|
||||
<plurals name="dashboard_exams_more">
|
||||
<item quantity="one">%1$d more exam</item>
|
||||
<item quantity="other">%1$d more exams</item>
|
||||
</plurals>
|
||||
<string name="dashboard_conferences_title">Conferences</string>
|
||||
<string name="dashboard_conferences_no_conferences">No upcoming conferences</string>
|
||||
<string name="dashboard_conferences_error">An error occurred while loading the conferences</string>
|
||||
<plurals name="dashboard_conference_more">
|
||||
<item quantity="one">%1$d more conference</item>
|
||||
<item quantity="other">%1$d more conferences</item>
|
||||
</plurals>
|
||||
<string name="dashboard_horizontal_group_error">An error occurred while loading data</string>
|
||||
<string name="dashboard_horizontal_group_no_data">None</string>
|
||||
<!--Error dialog-->
|
||||
<string name="dialog_error_check_update">Check for updates</string>
|
||||
<string name="dialog_error_check_update_message">Before reporting a bug, check first if an update with the bug fix is available</string>
|
||||
<!--Generic-->
|
||||
<string name="all_content">Content</string>
|
||||
<string name="all_retry">Retry</string>
|
||||
<string name="all_description">Description</string>
|
||||
<string name="all_no_description">No description</string>
|
||||
<string name="all_teacher">Teacher</string>
|
||||
<string name="all_date">Date</string>
|
||||
<string name="all_entry_date">Entry date</string>
|
||||
<string name="all_color">Color</string>
|
||||
<string name="all_details">Details</string>
|
||||
<string name="all_category">Category</string>
|
||||
<string name="all_close">Close</string>
|
||||
<string name="all_no_data">No data</string>
|
||||
<string name="all_subject">Subject</string>
|
||||
<string name="all_prev">Prev</string>
|
||||
<string name="all_next">Next</string>
|
||||
<string name="all_search">Search</string>
|
||||
<string name="all_search_hint">Search…</string>
|
||||
<string name="all_yes">Yes</string>
|
||||
<string name="all_no">No</string>
|
||||
<string name="all_save">Save</string>
|
||||
<string name="all_title">Title</string>
|
||||
<string name="all_add">Add</string>
|
||||
<string name="all_copied">Copied</string>
|
||||
<string name="all_undo">Undo</string>
|
||||
<string name="all_change">Change</string>
|
||||
<string name="all_add_to_calendar">Add to calendar</string>
|
||||
<string name="all_cancel">Cancel</string>
|
||||
<!--Timetable Widget-->
|
||||
<string name="widget_timetable_no_items">No lessons</string>
|
||||
<string name="widget_timetable_last_synchronization">Synchronized on %1$s at %2$s</string>
|
||||
<string name="widget_timetable_theme_title">Choose theme</string>
|
||||
<string name="widget_timetable_theme_light">Light</string>
|
||||
<string name="widget_timetable_theme_dark">Dark</string>
|
||||
<string name="widget_timetable_theme_system">System Theme</string>
|
||||
<!--Preferences-->
|
||||
<string name="pref_view_header">App</string>
|
||||
<string name="pref_view_list">Default view</string>
|
||||
<string name="pref_view_grade_average_mode">Calculated average options</string>
|
||||
<string name="pref_view_grade_average_force_calc">Force average calculation by app</string>
|
||||
<string name="pref_view_present">Show presence</string>
|
||||
<string name="pref_view_app_theme">Theme</string>
|
||||
<string name="pref_view_expand_grade">Grades expanding</string>
|
||||
<string name="pref_view_timetable_show_groups">Show groups next to subjects</string>
|
||||
<string name="pref_view_timetable_show_gaps">Show empty tiles where there\'s no lesson</string>
|
||||
<string name="pref_view_grade_statistics_list">Show chart list in class grades</string>
|
||||
<string name="pref_view_subjects_without_grades">Show subjects without grades</string>
|
||||
<string name="pref_view_grade_color_scheme">Grades color scheme</string>
|
||||
<string name="pref_view_grade_sorting_mode">Subjects sorting</string>
|
||||
<string name="pref_view_app_language">Language</string>
|
||||
<string name="pref_view_menu_order_title">Menu configuration</string>
|
||||
<string name="pref_view_menu_order_summary">Set the order of functions in the menu</string>
|
||||
<string name="pref_notify_header">Notifications</string>
|
||||
<string name="pref_notify_header_other">Other</string>
|
||||
<string name="pref_notify_switch">Show notifications</string>
|
||||
<string name="pref_notify_upcoming_lessons_switch">Show upcoming lesson notifications</string>
|
||||
<string name="pref_notify_upcoming_lessons_persistent_switch">Make upcoming lesson notification persistent</string>
|
||||
<string name="pref_notify_upcoming_lessons_persistent_summary">Turn off when notification is not showing in your watch/band</string>
|
||||
<string name="pref_notify_open_system_settings">Open system notification settings</string>
|
||||
<string name="pref_notify_fix_sync_issues">Fix synchronization & notifications issues</string>
|
||||
<string name="pref_notify_fix_sync_issues_message">Your device may have data synchronization issues and with notifications.\n\nTo fix them, you need to add Wulkanowy to the autostart and turn off battery optimization/saving in the phone settings.</string>
|
||||
<string name="pref_notify_debug_switch">Show debug notifications</string>
|
||||
<string name="pref_notify_disabled_summary">Synchronization is disabled</string>
|
||||
<string name="pref_notify_notifications_piggyback_header">Official app notifications</string>
|
||||
<string name="pref_notify_notifications_piggyback">Capture official app notifications</string>
|
||||
<string name="pref_notify_notifications_piggyback_cancel_original">Remove official app notifications after capture</string>
|
||||
<string name="pref_notification_piggyback_popup_title">Capture notifications</string>
|
||||
<string name="pref_notification_piggyback_popup_description">With this feature you can gain a substitute of push notifications like in the official app. All you need to do is allow Wulkanowy to receive all notifications in your system settings.\n\nHow it works?\nWhen you get a notification in Dziennik VULCAN, Wulkanowy will be notified (that\'s what these extra permissions are for) and will trigger a sync so that can send its own notification.\n\nFOR ADVANCED USERS ONLY</string>
|
||||
<string name="pref_notification_exact_alarm_popup_title">Upcoming lesson notifications</string>
|
||||
<string name="pref_notification_exact_alarm_popup_descriptions">You must allow the Wulkanowy app to set alarms and reminders in your system settings to use this feature.</string>
|
||||
<string name="pref_notification_go_to_settings">Go to settings</string>
|
||||
<string name="pref_services_header">Synchronization</string>
|
||||
<string name="pref_services_switch">Automatic update</string>
|
||||
<string name="pref_services_suspended">Suspended on holidays</string>
|
||||
<string name="pref_services_interval">Updates interval</string>
|
||||
<string name="pref_services_wifi">Wi-Fi only</string>
|
||||
<string name="pref_services_force_sync">Sync now</string>
|
||||
<string name="pref_services_message_sync_success">Synced!</string>
|
||||
<string name="pref_services_message_sync_failed">Sync failed</string>
|
||||
<string name="pref_services_sync_in_progress">Sync in progress</string>
|
||||
<string name="pref_services_last_full_sync_date">Last full sync: %s</string>
|
||||
<string name="pref_other_grade_modifier_plus">Value of the plus</string>
|
||||
<string name="pref_other_grade_modifier_minus">Value of the minus</string>
|
||||
<string name="pref_other_fill_message_content">Reply with message history</string>
|
||||
<string name="pref_other_optional_arithmetic_average">Show arithmetic average when no weights provided</string>
|
||||
<string name="pref_other_incognito_mode">Incognito mode</string>
|
||||
<string name="pref_other_incognito_mode_summary">Do not inform about reading the message</string>
|
||||
<string name="pref_ads_support_category_name">Support</string>
|
||||
<string name="pref_ads_privacy_policy">Privacy Policy</string>
|
||||
<string name="pref_ads_agreements">Agreements</string>
|
||||
<string name="pref_ads_consent">Show consent to data processing</string>
|
||||
<string name="pref_ads_show_in_app">Show ads in app</string>
|
||||
<string name="pref_ads_support">Watch single ad to support project</string>
|
||||
<string name="pref_ads_privacy_title">Consent to data processing</string>
|
||||
<string name="pref_ads_privacy_description">To view an advertisement you must agree to the data processing terms of our Privacy Policy</string>
|
||||
<string name="pref_ads_privacy_agree">Agree</string>
|
||||
<string name="pref_ads_privacy_link">Privacy policy</string>
|
||||
<string name="pref_ads_loading">Ad is loading</string>
|
||||
<string name="pref_ads_once_per_visit">Thank you for your support, come back later for more ads</string>
|
||||
<string name="pref_settings_advanced_title">Advanced</string>
|
||||
<string name="pref_settings_appearance_title">Appearance & Behavior</string>
|
||||
<string name="pref_settings_notifications_title">Notifications</string>
|
||||
<string name="pref_settings_sync_title">Synchronization</string>
|
||||
<string name="pref_settings_ads_title">Advertisements</string>
|
||||
<string name="pref_grades_appearance_header">Grades</string>
|
||||
<string name="pref_dashboard_appearance_header">Dashboard</string>
|
||||
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</string>
|
||||
<string name="pref_attendance_appearance_view">Attendance</string>
|
||||
<string name="pref_timetable_appearance_view">Timetable</string>
|
||||
<string name="pref_grades_advanced_header">Grades</string>
|
||||
<string name="pref_counted_average_advanced_header">Calculated average</string>
|
||||
<string name="pref_messages_advanced_header">Messages</string>
|
||||
<string name="pref_appearance_category">Appearance & Behavior</string>
|
||||
<string name="pref_appearance_category_summary">Languages, themes, subjects sorting</string>
|
||||
<string name="pref_notifications_category_summary">App notifications, fix problems</string>
|
||||
<string name="pref_notifications_category">Notifications</string>
|
||||
<string name="pref_sync_category">Synchronization</string>
|
||||
<string name="pref_sync_category_summary">Automatic update, synchronization interval</string>
|
||||
<string name="pref_advanced_category_summary">Plus and minus values, average calculation</string>
|
||||
<string name="pref_advanced_category">Advanced</string>
|
||||
<string name="pref_about_category_summary">App version, contributors, social portals</string>
|
||||
<string name="pref_ads_category_summary">Displaying advertisements, project support</string>
|
||||
<!--Notification Channels-->
|
||||
<string name="channel_new_grades">New grades</string>
|
||||
<string name="channel_new_homework">New homework</string>
|
||||
<string name="channel_new_conference">New conferences</string>
|
||||
<string name="channel_new_exam">New exams</string>
|
||||
<string name="channel_lucky_number">Lucky number</string>
|
||||
<string name="channel_new_message">New messages</string>
|
||||
<string name="channel_new_notes">New notes</string>
|
||||
<string name="channel_new_school_announcement">New school announcements</string>
|
||||
<string name="channel_push">Push notifications</string>
|
||||
<string name="channel_upcoming_lessons">Upcoming lessons</string>
|
||||
<string name="channel_debug">Debug</string>
|
||||
<string name="channel_change_timetable">Timetable change</string>
|
||||
<string name="channel_new_attendance">New attendance</string>
|
||||
<!--Colors-->
|
||||
<string name="all_black">Black</string>
|
||||
<string name="all_red">Red</string>
|
||||
<string name="all_blue">Blue</string>
|
||||
<string name="all_green">Green</string>
|
||||
<string name="all_purple">Purple</string>
|
||||
<string name="all_empty_color">No color</string>
|
||||
<!--Update helper-->
|
||||
<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_button">Restart</string>
|
||||
<string name="update_failed">Update failed! Wulkanowy may not function properly. Consider updating</string>
|
||||
<!--Menu order-->
|
||||
<string name="menu_order_confirm_title">Application restart</string>
|
||||
<string name="menu_order_confirm_content">The application must restart for the changes to be saved</string>
|
||||
<string name="menu_order_confirm_restart">Restart</string>
|
||||
<!--Auth-->
|
||||
<string name="auth_api_error">Authorization has been rejected. The data provided does not match the records in the secretary\'s office.</string>
|
||||
<string name="auth_invalid_error">Invalid PESEL</string>
|
||||
<string name="auth_pesel">PESEL</string>
|
||||
<string name="auth_button">Authorize</string>
|
||||
<string name="auth_success">Authorization completed successfully</string>
|
||||
<string name="auth_title">Authorization</string>
|
||||
<string name="auth_description">To operate the application, we need to confirm your identity. Please enter the student\'s PESEL <b>%1$s</b> in the field below</string>
|
||||
<string name="auth_button_skip">Skip for now</string>
|
||||
<!--Errors-->
|
||||
<string name="error_no_internet">No internet connection</string>
|
||||
<string name="error_invalid_device_datetime">An error occurred. Check your device clock</string>
|
||||
<string name="error_timeout">Connection to register failed. Servers can be overloaded. Please try again later</string>
|
||||
<string name="error_login_failed">Loading data failed. Please try again later</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_unknown_uonet">Unknown UONET + register error. Try again later</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_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_field_required">This field is required</string>
|
||||
</resources>
|
@ -10,9 +10,10 @@
|
||||
<string name="settings_title">Einstellungen</string>
|
||||
<string name="more_title">Mehr</string>
|
||||
<string name="about_title">Über die Applikation</string>
|
||||
<string name="logviewer_title">Log Viewer</string>
|
||||
<string name="logviewer_title">Log viewer</string>
|
||||
<string name="debug_title">Debuggen</string>
|
||||
<string name="notification_debug_title">Benachrichtigungen debuggen</string>
|
||||
<string name="debug_cookies_clear">Clear webview cookies</string>
|
||||
<string name="contributors_title">Mitarbeiter</string>
|
||||
<string name="license_title">Lizenzen</string>
|
||||
<string name="message_title">Nachrichten</string>
|
||||
@ -55,6 +56,7 @@
|
||||
<string name="login_invalid_email">Ungültige email</string>
|
||||
<string name="login_invalid_login">Den zugewiesenen Login anstelle von email verwenden</string>
|
||||
<string name="login_invalid_custom_email">Benutze den zugewiesenen Login oder E-Mail in @%1$s</string>
|
||||
<string name="login_invalid_domain_suffix">Invalid domain suffix</string>
|
||||
<string name="login_invalid_symbol">Invalid symbol. If you cannot find it, please contact the school</string>
|
||||
<string name="login_invalid_symbol_definitely">Don\'t make this up! If you cannot find it, please contact the school</string>
|
||||
<string name="login_incorrect_symbol">Schüler nicht gefunden. Überprüfen Sie das Symbol und die gewählte Variation des UONET+ Registers</string>
|
||||
@ -116,6 +118,7 @@
|
||||
<string name="grade_summary_points">Gesamtpunkte</string>
|
||||
<string name="grade_summary_final_grade">Finaler Note</string>
|
||||
<string name="grade_summary_predicted_grade">Vorhergesagte Note</string>
|
||||
<string name="grade_summary_descriptive">Descriptive grade</string>
|
||||
<string name="grade_summary_calculated_average">Berechnender Durchschnitt</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_title">Wie funktioniert der berechnete Durchschnitt?</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_message">Der berechnete Mittelwert ist das arithmetische Mittel, das aus den Durchschnittswerten der Probanden errechnet wird. Es erlaubt Ihnen, den ungefähre endgültigen Durchschnitt zu kennen. Sie wird auf eine vom Anwender in den Anwendungseinstellungen gewählte Weise berechnet. Es wird empfohlen, die entsprechende Option zu wählen. Das liegt daran, dass die Berechnung der Schuldurchschnitte unterschiedlich ist. Wenn Ihre Schule den Durchschnitt der Fächer auf der Vulcan-Seite angibt, lädt die Anwendung diese Fächer herunter und berechnet nicht den Durchschnitt. Dies kann geändert werden, indem die Berechnung des Durchschnitts in den Anwendungseinstellungen erzwungen wird. \n\n<b>Durchschnitt der Noten nur aus dem ausgewählten Semester </b>:\n1. Berechnung des gewichteten Durchschnitts für jedes Fach in einem bestimmten Semester\n2. Addition der berechneten Durchschnittswerte\n3. Berechnung des arithmetischen Mittels der summierten Durchschnitte\n<b>Durchschnitt der Durchschnitte aus beiden Semestern</b>:\n1. Berechnung des gewichteten Durchschnitts für jedes Fach in Semester 1 und 2\n2. Berechnung des arithmetischen Mittels der berechneten Durchschnitte für Semester 1 und 2 für jedes Fach. \n3. Hinzufügen von berechneten Durchschnittswerten\n4. Berechnung des arithmetischen Mittels der summierten Durchschnitte\n<b>Durchschnitt der Noten aus dem ganzen Jahr:</b>\n1. Berechnung des gewichteten Jahresdurchschnitts für jedes Fach. Der Abschlussdurchschnitt im 1. Semester ist irrelevant. \n2. Addition der berechneten Durchschnittswerte\n3. Berechnung des arithmetischen Mittels der summierten Mittelwerte</string>
|
||||
@ -151,6 +154,10 @@
|
||||
<item quantity="one">Neue Abschlussnote</item>
|
||||
<item quantity="other">Neue Abschlussnoten</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_descriptive">
|
||||
<item quantity="one">New descriptive grade</item>
|
||||
<item quantity="other">New descriptive grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items">
|
||||
<item quantity="one">Du hast %1$d Note bekommen</item>
|
||||
<item quantity="other">Du hast %1$d Noten bekommen</item>
|
||||
@ -163,6 +170,10 @@
|
||||
<item quantity="one">Sie haben %1$d Abschlussnote bekommen</item>
|
||||
<item quantity="other">Sie haben %1$d Abschlussnoten bekommen</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_descriptive">
|
||||
<item quantity="one">You received %1$d descriptive grade</item>
|
||||
<item quantity="other">You received %1$d descriptive grades</item>
|
||||
</plurals>
|
||||
<!--Timetable-->
|
||||
<string name="timetable_lesson">Lektion</string>
|
||||
<string name="timetable_room">Klassenzimmer</string>
|
||||
@ -743,6 +754,9 @@
|
||||
<string name="auth_title">Authorization</string>
|
||||
<string name="auth_description">To operate the application, we need to confirm your identity. Please enter the student\'s PESEL <b>%1$s</b> in the field below</string>
|
||||
<string name="auth_button_skip">Skip for now</string>
|
||||
<!--Captcha-->
|
||||
<string name="captcha_dialog_title">Verification is in progress. Wait…</string>
|
||||
<string name="captcha_verified_message">Verified successfully</string>
|
||||
<!--Errors-->
|
||||
<string name="error_no_internet">Keine Internetverbindung</string>
|
||||
<string name="error_invalid_device_datetime">Es ist ein Fehler aufgetreten. Überprüfen Sie Ihre Geräteuhr</string>
|
||||
@ -752,6 +766,7 @@
|
||||
<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_cloudflare_captcha">Captcha verification required</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_not_available">Feature in diesem Modus nicht verfügbar</string>
|
||||
|
@ -1,759 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!--Activity/Fragment title-->
|
||||
<string name="login_title">Login</string>
|
||||
<string name="main_title">Wulkanowy</string>
|
||||
<string name="grade_title">Grades</string>
|
||||
<string name="attendance_title">Attendance</string>
|
||||
<string name="exam_title">Exams</string>
|
||||
<string name="timetable_title">Timetable</string>
|
||||
<string name="settings_title">Settings</string>
|
||||
<string name="more_title">More</string>
|
||||
<string name="about_title">About</string>
|
||||
<string name="logviewer_title">Log viewer</string>
|
||||
<string name="debug_title">Debug</string>
|
||||
<string name="notification_debug_title">Notification debug</string>
|
||||
<string name="contributors_title">Contributors</string>
|
||||
<string name="license_title">Licenses</string>
|
||||
<string name="message_title">Messages</string>
|
||||
<string name="send_message_title">New message</string>
|
||||
<string name="add_homework_title">New homework</string>
|
||||
<string name="note_title">Notes and achievements</string>
|
||||
<string name="homework_title">Homework</string>
|
||||
<string name="account_title">Accounts manager</string>
|
||||
<string name="account_quick_title">Select account</string>
|
||||
<string name="account_details_title">Account details</string>
|
||||
<string name="student_info_title">Student info</string>
|
||||
<string name="dashboard_title">Dashboard</string>
|
||||
<string name="notifications_center_title">Notifications center</string>
|
||||
<string name="menu_order_title">Menu configuartion</string>
|
||||
<!--Subtitles-->
|
||||
<string name="grade_subtitle">Semester %1$d, %2$d/%3$d</string>
|
||||
<!--Login-->
|
||||
<string name="login_header_default">Sign in with the student or parent account</string>
|
||||
<string name="login_header_symbol">Enter the symbol from the register page for account: <b>%1$s</b></string>
|
||||
<string name="login_nickname_hint">Username</string>
|
||||
<string name="login_email_hint">Email</string>
|
||||
<string name="login_login_pesel_email_hint">Login, PESEL or e-mail</string>
|
||||
<string name="login_password_hint">Password</string>
|
||||
<string name="login_host_hint">UONET+ register variant</string>
|
||||
<string name="login_domain_suffix_hint">Custom domain suffix</string>
|
||||
<string name="login_type_api">Mobile API</string>
|
||||
<string name="login_type_scrapper">Scraper</string>
|
||||
<string name="login_type_hybrid">Hybrid</string>
|
||||
<string name="login_token_hint">Token</string>
|
||||
<string name="login_pin_hint">PIN</string>
|
||||
<string name="login_symbol_hint">Symbol</string>
|
||||
<string name="login_symbol_placeholder">E.g. \"lodz\" or \"powiatjaroslawski\"</string>
|
||||
<string name="login_sign_in">Sign in</string>
|
||||
<string name="login_invalid_password">Password too short</string>
|
||||
<string name="login_incorrect_password_default">Login details are incorrect</string>
|
||||
<string name="login_incorrect_password">%1$s. Make sure the correct UONET+ register variation is selected below</string>
|
||||
<string name="login_invalid_pin">Invalid PIN</string>
|
||||
<string name="login_invalid_token">Invalid token</string>
|
||||
<string name="login_expired_token">Token expired</string>
|
||||
<string name="login_invalid_email">Invalid email</string>
|
||||
<string name="login_invalid_login">Use the assigned login instead of email</string>
|
||||
<string name="login_invalid_custom_email">Use the assigned login or email in @%1$s</string>
|
||||
<string name="login_invalid_symbol">Invalid symbol. If you cannot find it, please contact the school</string>
|
||||
<string name="login_invalid_symbol_definitely">Don\'t make this up! If you cannot find it, please contact the school</string>
|
||||
<string name="login_incorrect_symbol">Student not found. Validate the symbol and the chosen variation of the UONET+ register</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 <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Wygeneruj kod dostępu</b>.\n\nMake sure that you have set the appropriate register variant in the <b>UONET+ register variant</b> field on the first login screen</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_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_scraper">This mode displays the same data as it appears on the register website</string>
|
||||
<string name="login_advanced_warning_hybrid">The combination of the best features of the other two modes. It works faster than scraper and provides features not available in the Mobile API mode. It is in the experimental phase</string>
|
||||
<string name="login_privacy_policy">Privacy policy</string>
|
||||
<string name="login_contact_header">Trouble signing in? Contact us!</string>
|
||||
<string name="login_contact_email">Email</string>
|
||||
<string name="login_contact_discord">Discord</string>
|
||||
<string name="login_email_intent_title">Send email</string>
|
||||
<string name="login_recover_warning">Make sure you select the correct UONET+ register variation!</string>
|
||||
<string name="login_recover_button">Reset password</string>
|
||||
<string name="login_recover_title">Recover your account</string>
|
||||
<string name="login_recover">Recover</string>
|
||||
<string name="login_signed_in">Student is already signed in</string>
|
||||
<string name="login_host_standard">Standard</string>
|
||||
<string name="login_other_search_locations">Other search locations</string>
|
||||
<string name="login_no_active_student">No active students found</string>
|
||||
<string name="login_symbol_enter">Enter a different symbol</string>
|
||||
<string name="login_support_title">Get help</string>
|
||||
<string name="login_support_school_hint">Full school name with the town (required)</string>
|
||||
<string name="login_support_school_placeholder">Np. ZSTiO Jarosław lub SP nr 99 w Łodzi</string>
|
||||
<string name="login_support_school_invalid">Enter correct name of the school</string>
|
||||
<string name="login_support_additional_hint">Additional information in Polish (optional)</string>
|
||||
<string name="login_support_additional_placeholder">Np. \"Ostatnio zmieniłem szkołę i…\" albo \"Jestem rodzicem i nie widzę drugiego dziecka…\"</string>
|
||||
<string name="login_support_submit">Submit</string>
|
||||
<!--Notifications-->
|
||||
<string name="notifications_header_title">Enable notifications</string>
|
||||
<string name="notifications_header_description">Enable notifications so you don\'t miss message from teacher or new grade</string>
|
||||
<string name="notifications_skip">Skip</string>
|
||||
<string name="notifications_enable">Enable</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Account manager</string>
|
||||
<string name="main_log_in">Log in</string>
|
||||
<string name="main_session_expired">Session expired</string>
|
||||
<string name="main_session_relogin">Session expired, log in again</string>
|
||||
<string name="main_expired_credentials_description">Your account password has been changed. You need to log in to Wulkanowy again</string>
|
||||
<string name="main_expired_credentials_title">Password changed</string>
|
||||
<string name="main_support_title">Application support</string>
|
||||
<string name="main_support_description">Do you like this app? Support its development by enabling non-invasive ads that you can disable at any time</string>
|
||||
<string name="main_support_positive">Enable ads</string>
|
||||
<!--Grade-->
|
||||
<string name="grade_header">Grade</string>
|
||||
<string name="grade_semester">Semester %d</string>
|
||||
<string name="grade_switch_semester">Change semester</string>
|
||||
<string name="grade_no_items">No grades</string>
|
||||
<string name="grade_weight">Weight</string>
|
||||
<string name="grade_weight_value">Weight: %s</string>
|
||||
<string name="grade_comment">Comment</string>
|
||||
<string name="grade_number_new_items">Number of new ratings: %1$d</string>
|
||||
<string name="grade_average">Average: %1$.2f</string>
|
||||
<string name="grade_points_sum">Points: %s</string>
|
||||
<string name="grade_no_average">No average</string>
|
||||
<string name="grade_summary_points">Total points</string>
|
||||
<string name="grade_summary_final_grade">Final grade</string>
|
||||
<string name="grade_summary_predicted_grade">Predicted grade</string>
|
||||
<string name="grade_summary_calculated_average">Calculated average</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_title">How does Calculated Average work?</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_message">The Calculated Average is the arithmetic average calculated from the subjects averages. It allows you to know the approximate final average. It is calculated in a way selected by the user in the application settings. It is recommended that you choose the appropriate option. This is because the calculation of school averages differs. Additionally, if your school reports the average of the subjects on the Vulcan page, the application downloads them and does not calculate these averages. This can be changed by forcing the calculation of the average in the application settings.\n\n<b>Average of grades only from selected semester</b>:\n1. Calculating the weighted average for each subject in a given semester\n2.Adding calculated averages\n3. Calculation of the arithmetic average of the summed averages\n\n<b>Average of averages from both semesters</b>:\n1.Calculating the weighted average for each subject in semester 1 and 2\n2. Calculating the arithmetic average of the calculated averages for semesters 1 and 2 for each subject.\n3. Adding calculated averages\n4. Calculation of the arithmetic average of the summed averages\n\n<b>Average of grades from the whole year:</b>\n1. Calculating weighted average over the year for each subject. The final average in the 1st semester is irrelevant.\n2. Adding calculated averages\n3. Calculating the arithmetic average of summed averages</string>
|
||||
<string name="grade_summary_final_average_help_dialog_title">How does the Final Average work?</string>
|
||||
<string name="grade_summary_final_average_help_dialog_message">The Final Average is the arithmetic average calculated from all currently available final grades in the given semester.\n\nThe calculation scheme consists of the following steps:\n1. Summing up the final grades given by teachers\n2. Divide by the number of subjects that have already been graded</string>
|
||||
<string name="grade_summary_final_average">Final average</string>
|
||||
<string name="grade_summary_from_subjects">from %1$d of %2$d subjects</string>
|
||||
<string name="grade_menu_summary">Summary</string>
|
||||
<string name="grade_menu_statistics">Class</string>
|
||||
<string name="grade_menu_read">Mark as read</string>
|
||||
<string name="grade_statistics_partial">Partial</string>
|
||||
<string name="grade_statistics_semester">Semester</string>
|
||||
<string name="grade_statistics_points">Points</string>
|
||||
<string name="grade_statistics_legend">Legend</string>
|
||||
<string name="grade_statistics_class_average">Class average: %1$s</string>
|
||||
<string name="grade_statistics_student_average">Your average: %1$s</string>
|
||||
<string name="grade_statistics_student_grade">Your grade: %1$s</string>
|
||||
<string name="grade_statistics_average_class">Class</string>
|
||||
<string name="grade_statistics_average_student">Student</string>
|
||||
<plurals name="grade_number_item">
|
||||
<item quantity="one">%d grade</item>
|
||||
<item quantity="other">%d grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items">
|
||||
<item quantity="one">New grade</item>
|
||||
<item quantity="other">New grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_predicted">
|
||||
<item quantity="one">New predicted grade</item>
|
||||
<item quantity="other">New predicted grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_final">
|
||||
<item quantity="one">New final grade</item>
|
||||
<item quantity="other">New final grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items">
|
||||
<item quantity="one">You received %1$d grade</item>
|
||||
<item quantity="other">You received %1$d grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_predicted">
|
||||
<item quantity="one">You received %1$d predicted grade</item>
|
||||
<item quantity="other">You received %1$d predicted grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_final">
|
||||
<item quantity="one">You received %1$d final grade</item>
|
||||
<item quantity="other">You received %1$d final grades</item>
|
||||
</plurals>
|
||||
<!--Timetable-->
|
||||
<string name="timetable_lesson">Lesson</string>
|
||||
<string name="timetable_room">Room</string>
|
||||
<string name="timetable_group">Group</string>
|
||||
<string name="timetable_time">Hours</string>
|
||||
<string name="timetable_changes">Changes</string>
|
||||
<string name="timetable_no_items">No lessons this day</string>
|
||||
<string name="timetable_minutes">%s min</string>
|
||||
<string name="timetable_seconds">%s sec</string>
|
||||
<string name="timetable_time_left">%1$s left</string>
|
||||
<string name="timetable_time_until">in %1$s</string>
|
||||
<string name="timetable_finished">Finished</string>
|
||||
<string name="timetable_now">Now: %s</string>
|
||||
<string name="timetable_next">Next: %s</string>
|
||||
<string name="timetable_later">Later: %s</string>
|
||||
<string name="timetable_notify_lesson">%1$s lesson %2$d - %3$s</string>
|
||||
<string name="timetable_notify_change_room">Change of room from %1$s to %2$s</string>
|
||||
<string name="timetable_notify_change_teacher">Change of teacher from %1$s to %2$s</string>
|
||||
<string name="timetable_notify_change_subject">Change of subject from %1$s to %2$s</string>
|
||||
<plurals name="timetable_no_lesson">
|
||||
<item quantity="one">No lesson</item>
|
||||
<item quantity="other">No lessons</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_notify_new_items_title">
|
||||
<item quantity="one">Timetable change</item>
|
||||
<item quantity="other">Timetable changes</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_notify_new_items">
|
||||
<item quantity="one">%1$s - %2$d change in timetable</item>
|
||||
<item quantity="other">%1$s - %2$d changes in timetable</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_notify_new_items_group">
|
||||
<item quantity="one">%1$d change in timetable</item>
|
||||
<item quantity="other">%1$d changes in timetable</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_number_item">
|
||||
<item quantity="one">%d change</item>
|
||||
<item quantity="other">%d changes</item>
|
||||
</plurals>
|
||||
<!--Completed lessons-->
|
||||
<string name="completed_lessons_title">Completed lessons</string>
|
||||
<string name="completed_lessons_button">Show completed lessons</string>
|
||||
<string name="completed_lessons_no_items">No info about completed lessons</string>
|
||||
<string name="completed_lessons_topic">Topic</string>
|
||||
<string name="completed_lessons_absence">Absence</string>
|
||||
<string name="completed_lessons_resources">Resources</string>
|
||||
<!--Additional lessons-->
|
||||
<string name="additional_lessons_title">Additional lessons</string>
|
||||
<string name="additional_lessons_button">Show additional lessons</string>
|
||||
<string name="additional_lessons_no_items">No info about additional lessons</string>
|
||||
<string name="additional_lessons_add">New lesson</string>
|
||||
<string name="additional_lessons_add_title">New additional lesson</string>
|
||||
<string name="additional_lessons_add_success">Additional lesson added successfully</string>
|
||||
<string name="additional_lessons_delete_success">Additional lesson deleted successfully</string>
|
||||
<string name="additional_lessons_repeat">Repeat weekly</string>
|
||||
<string name="additional_lessons_delete_title">Delete additional lesson</string>
|
||||
<string name="additional_lessons_delete_one">Just this lesson</string>
|
||||
<string name="additional_lessons_delete_series">All in the series</string>
|
||||
<string name="additional_lessons_start">Start time</string>
|
||||
<string name="additional_lessons_end">End time</string>
|
||||
<string name="additional_lessons_end_time_error">End time must be greater than start time</string>
|
||||
<!--Attendance-->
|
||||
<string name="attendance_summary_button">Attendance summary</string>
|
||||
<string name="attendance_absence_school">Absent for school reasons</string>
|
||||
<string name="attendance_absence_excused">Excused absence</string>
|
||||
<string name="attendance_absence_unexcused">Unexcused absence</string>
|
||||
<string name="attendance_exemption">Exemption</string>
|
||||
<string name="attendance_excused_lateness">Excused lateness</string>
|
||||
<string name="attendance_unexcused_lateness">Unexcused lateness</string>
|
||||
<string name="attendance_present">Present</string>
|
||||
<string name="attendance_deleted">Deleted</string>
|
||||
<string name="attendance_unknown">Unknown</string>
|
||||
<string name="attendance_number">Number of lesson</string>
|
||||
<string name="attendance_no_items">No entries</string>
|
||||
<string name="attendance_excuse_dialog_reason">Absence reason (optional)</string>
|
||||
<string name="attendance_excuse_dialog_submit">Send</string>
|
||||
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
|
||||
<string name="attendance_excuse_no_selection">You must select at least one absence!</string>
|
||||
<string name="attendance_excuse_title">Excuse</string>
|
||||
<plurals name="attendance_notify_new_items_title">
|
||||
<item quantity="one">New attendance</item>
|
||||
<item quantity="other">New attendance</item>
|
||||
</plurals>
|
||||
<plurals name="attendance_notify_new_items">
|
||||
<item quantity="one">%1$d new attendance</item>
|
||||
<item quantity="other">%1$d attendance</item>
|
||||
</plurals>
|
||||
<plurals name="attendance_number_item">
|
||||
<item quantity="one">%d attendance</item>
|
||||
<item quantity="other">%d attendance</item>
|
||||
</plurals>
|
||||
<!--Attendance summary-->
|
||||
<string name="attendance_summary_total">Total</string>
|
||||
<!--Exam-->
|
||||
<string name="exam_no_items">No exams this week</string>
|
||||
<string name="exam_type">Type</string>
|
||||
<string name="exam_entry_date">Entry date</string>
|
||||
<plurals name="exam_notify_new_item_title">
|
||||
<item quantity="one">New exam</item>
|
||||
<item quantity="other">New exams</item>
|
||||
</plurals>
|
||||
<plurals name="exam_notify_new_item_content">
|
||||
<item quantity="one">%d new exam</item>
|
||||
<item quantity="other">%d new exams</item>
|
||||
</plurals>
|
||||
<plurals name="exam_number_item">
|
||||
<item quantity="one">%d exam</item>
|
||||
<item quantity="other">%d exams</item>
|
||||
</plurals>
|
||||
<!--Message-->
|
||||
<string name="message_inbox">Inbox</string>
|
||||
<string name="message_sent">Sent</string>
|
||||
<string name="message_trash">Trash</string>
|
||||
<string name="message_no_subject">(no subject)</string>
|
||||
<string name="message_no_items">No messages</string>
|
||||
<string name="message_from">From:</string>
|
||||
<string name="message_to">To:</string>
|
||||
<string name="message_date">Date: %1$s</string>
|
||||
<string name="message_reply">Reply</string>
|
||||
<string name="message_forward">Forward</string>
|
||||
<string name="message_select_all">Select all</string>
|
||||
<string name="message_unselect_all">Unselect all</string>
|
||||
<string name="message_move_to_trash">Move to trash</string>
|
||||
<string name="message_delete_forever">Delete permanently</string>
|
||||
<string name="message_delete_success">Message deleted successfully</string>
|
||||
<string name="message_mailbox_type_student">student</string>
|
||||
<string name="message_mailbox_type_parent">parent</string>
|
||||
<string name="message_mailbox_type_guardian">guardian</string>
|
||||
<string name="message_mailbox_type_employee">employee</string>
|
||||
<string name="message_share">Share</string>
|
||||
<string name="message_print">Print</string>
|
||||
<string name="message_subject">Subject</string>
|
||||
<string name="message_content">Content</string>
|
||||
<string name="message_send_successful">Message sent successfully</string>
|
||||
<string name="message_not_exists">Message does not exist</string>
|
||||
<string name="message_required_recipients">You need to choose at least 1 recipient</string>
|
||||
<string name="message_content_min_length">The message content must be at least 3 characters</string>
|
||||
<string name="message_chip_all_mailboxes">All mailboxes</string>
|
||||
<string name="message_chip_only_unread">Only unread</string>
|
||||
<string name="message_chip_only_with_attachments">Only with attachments</string>
|
||||
<string name="message_read">Read: %s</string>
|
||||
<string name="message_read_by">Read by: %1$d of %2$d people</string>
|
||||
<plurals name="message_number_item">
|
||||
<item quantity="one">%1$d message</item>
|
||||
<item quantity="other">%1$d messages</item>
|
||||
</plurals>
|
||||
<plurals name="message_new_items">
|
||||
<item quantity="one">New message</item>
|
||||
<item quantity="other">New messages</item>
|
||||
</plurals>
|
||||
<string name="message_restore_dialog">Do you want to restore draft message?</string>
|
||||
<string name="message_restore_dialog_with_recipients">Do you want to restore draft message with recipients: %s?</string>
|
||||
<plurals name="message_notify_new_items">
|
||||
<item quantity="one">You received %1$d message</item>
|
||||
<item quantity="other">You received %1$d messages</item>
|
||||
</plurals>
|
||||
<plurals name="message_selected_messages_count">
|
||||
<item quantity="one">%1$d selected</item>
|
||||
<item quantity="other">%1$d selected</item>
|
||||
</plurals>
|
||||
<string name="message_messages_deleted">Messages deleted</string>
|
||||
<string name="message_mailbox_chooser_title">Choose mailbox</string>
|
||||
<string name="message_incognito_mode_on">Incognito mode is on</string>
|
||||
<string name="message_incognito_description">Thanks to incognito mode sender is not notified when you read the message</string>
|
||||
<!--Note-->
|
||||
<string name="note_no_items">No info about notes</string>
|
||||
<string name="note_points">Points</string>
|
||||
<plurals name="note_number_item">
|
||||
<item quantity="one">%d note</item>
|
||||
<item quantity="other">%d notes</item>
|
||||
</plurals>
|
||||
<plurals name="note_new_items">
|
||||
<item quantity="one">New note</item>
|
||||
<item quantity="other">New notes</item>
|
||||
</plurals>
|
||||
<plurals name="note_notify_new_items">
|
||||
<item quantity="one">You received %1$d note</item>
|
||||
<item quantity="other">You received %1$d notes</item>
|
||||
</plurals>
|
||||
<!--Praise-->
|
||||
<plurals name="praise_number_item">
|
||||
<item quantity="one">%d praise</item>
|
||||
<item quantity="other">%d praises</item>
|
||||
</plurals>
|
||||
<plurals name="praise_new_items">
|
||||
<item quantity="one">New praise</item>
|
||||
<item quantity="other">New praises</item>
|
||||
</plurals>
|
||||
<plurals name="praise_notify_new_items">
|
||||
<item quantity="one">You received %1$d praise</item>
|
||||
<item quantity="other">You received %1$d praises</item>
|
||||
</plurals>
|
||||
<!--Neutral notes-->
|
||||
<plurals name="neutral_note_number_item">
|
||||
<item quantity="one">%d neutral note</item>
|
||||
<item quantity="other">%d neutral notes</item>
|
||||
</plurals>
|
||||
<plurals name="neutral_note_new_items">
|
||||
<item quantity="one">New neutral note</item>
|
||||
<item quantity="other">New neutral notes</item>
|
||||
</plurals>
|
||||
<plurals name="neutral_note_notify_new_items">
|
||||
<item quantity="one">You received %1$d neutral note</item>
|
||||
<item quantity="other">You received %1$d neutral notes</item>
|
||||
</plurals>
|
||||
<!--Homework-->
|
||||
<string name="homework_no_items">No info about homework</string>
|
||||
<string name="homework_mark_as_done">Mark as done</string>
|
||||
<string name="homework_mark_as_undone">Mark as undone</string>
|
||||
<string name="homework_add">Add homework</string>
|
||||
<string name="homework_add_success">Homework added successfully</string>
|
||||
<string name="homework_delete_success">Homework deleted successfully</string>
|
||||
<string name="homework_attachments">Attachments</string>
|
||||
<plurals name="homework_notify_new_item_title">
|
||||
<item quantity="one">New homework</item>
|
||||
<item quantity="other">New homework</item>
|
||||
</plurals>
|
||||
<plurals name="homework_notify_new_item_content">
|
||||
<item quantity="one">You received %d new homework</item>
|
||||
<item quantity="other">You received %d new homework</item>
|
||||
</plurals>
|
||||
<plurals name="homework_number_item">
|
||||
<item quantity="one">%d homework</item>
|
||||
<item quantity="other">%d homework</item>
|
||||
</plurals>
|
||||
<!--Lucky number-->
|
||||
<string name="lucky_number_title">Lucky number</string>
|
||||
<string name="lucky_number_header">Today\'s lucky number is</string>
|
||||
<string name="lucky_number_empty">No info about the lucky number</string>
|
||||
<string name="lucky_number_notify_new_item_title">Lucky number for today</string>
|
||||
<string name="lucky_number_notify_new_item">Today\'s lucky number is: %s</string>
|
||||
<string name="lucky_number_history_button">Show history</string>
|
||||
<!--Lucky number history-->
|
||||
<string name="lucky_number_history_title">Lucky number history</string>
|
||||
<string name="lucky_number_history_empty">No info about lucky numbers</string>
|
||||
<!--Mobile devices-->
|
||||
<string name="mobile_devices_title">Mobile devices</string>
|
||||
<string name="mobile_devices_no_items">No devices</string>
|
||||
<string name="mobile_devices_unregister">Deregister</string>
|
||||
<string name="mobile_device_removed">Device removed</string>
|
||||
<string name="mobile_device_qr">QR code</string>
|
||||
<string name="mobile_device_token">Token</string>
|
||||
<string name="mobile_device_symbol">Symbol</string>
|
||||
<string name="mobile_device_pin">PIN</string>
|
||||
<!--School and teachers-->
|
||||
<string name="schoolandteachers_title">School and teachers</string>
|
||||
<!--School-->
|
||||
<string name="school_title">School</string>
|
||||
<string name="school_no_info">No info about school</string>
|
||||
<string name="school_name">School name</string>
|
||||
<string name="school_address">School address</string>
|
||||
<string name="school_telephone">Telephone</string>
|
||||
<string name="school_headmaster">Name of headmaster</string>
|
||||
<string name="school_pedagogue">Name of pedagogue</string>
|
||||
<string name="school_address_button">Show on map</string>
|
||||
<string name="school_telephone_button">Call</string>
|
||||
<!--Teacher-->
|
||||
<string name="teachers_title">Teachers</string>
|
||||
<string name="teacher_no_items">No info about teachers</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>
|
||||
<plurals name="conference_number_item">
|
||||
<item quantity="one">%d conference</item>
|
||||
<item quantity="other">%d conferences</item>
|
||||
</plurals>
|
||||
<plurals name="conference_notify_new_item_title">
|
||||
<item quantity="one">New conference</item>
|
||||
<item quantity="other">New conferences</item>
|
||||
</plurals>
|
||||
<plurals name="conference_notify_new_items">
|
||||
<item quantity="one">You have %1$d new conference</item>
|
||||
<item quantity="other">You have %1$d new conferences</item>
|
||||
</plurals>
|
||||
<string name="conferences_present">Present at conference</string>
|
||||
<string name="conference_agenda">Agenda</string>
|
||||
<string name="conference_place">Place</string>
|
||||
<string name="conference_topic">Topic</string>
|
||||
<!--Director information-->
|
||||
<string name="school_announcement_title">School announcements</string>
|
||||
<string name="school_announcement_no_items">No school announcements</string>
|
||||
<plurals name="school_announcement_number_item">
|
||||
<item quantity="one">%d school announcement</item>
|
||||
<item quantity="other">%d school announcements</item>
|
||||
</plurals>
|
||||
<plurals name="school_announcement_notify_new_item_title">
|
||||
<item quantity="one">New school announcement</item>
|
||||
<item quantity="other">New school announcements</item>
|
||||
</plurals>
|
||||
<plurals name="school_announcement_notify_new_items">
|
||||
<item quantity="one">You have %1$d new school announcement</item>
|
||||
<item quantity="other">You have %1$d new school announcements</item>
|
||||
</plurals>
|
||||
<!--Account-->
|
||||
<string name="account_add_new">Add account</string>
|
||||
<string name="account_logout">Logout</string>
|
||||
<string name="account_confirm">Do you want to log out this student?</string>
|
||||
<string name="account_logout_student">Student logout</string>
|
||||
<string name="account_type_student">Student account</string>
|
||||
<string name="account_type_parent">Parent account</string>
|
||||
<string name="account_details_edit">Edit data</string>
|
||||
<string name="account_quick_manager">Accounts manager</string>
|
||||
<string name="account_select_student">Select student</string>
|
||||
<string name="account_family">Family</string>
|
||||
<string name="account_contact">Contact</string>
|
||||
<string name="account_address">Residence details</string>
|
||||
<string name="account_personal_data">Personal information</string>
|
||||
<!--About-->
|
||||
<string name="about_version">App version</string>
|
||||
<string name="about_contributor">Contributors</string>
|
||||
<string name="about_contributor_summary">List of Wulkanowy developers</string>
|
||||
<string name="about_feedback">Report a bug</string>
|
||||
<string name="about_feedback_summary">Send a bug report via e-mail</string>
|
||||
<string name="about_faq">FAQ</string>
|
||||
<string name="about_faq_summary">Read Frequently Asked Questions</string>
|
||||
<string name="about_discord">Discord server</string>
|
||||
<string name="about_discord_summary">Join the Wulkanowy community</string>
|
||||
<string name="about_facebook">Facebook fanpage</string>
|
||||
<string name="about_twitter">Twitter page</string>
|
||||
<string name="about_twitter_summary">Follow us on twitter</string>
|
||||
<string name="about_facebook_summary">Like our facebook fanpage</string>
|
||||
<string name="about_privacy">Privacy policy</string>
|
||||
<string name="about_privacy_summary">Rules for collecting personal data</string>
|
||||
<string name="about_system">System settings</string>
|
||||
<string name="about_system_summary">Open system settings</string>
|
||||
<string name="about_homepage">Homepage</string>
|
||||
<string name="about_homepage_summary">Visit the website and help develop the application</string>
|
||||
<string name="about_licenses">Licenses</string>
|
||||
<string name="about_licenses_summary">Licenses of libraries used in the application</string>
|
||||
<!--Licenses-->
|
||||
<string name="license_dialog_title">License</string>
|
||||
<!--Contributor-->
|
||||
<string name="contributor_avatar_description">Avatar</string>
|
||||
<string name="contributor_see_more">See more on GitHub</string>
|
||||
<!--Student info-->
|
||||
<string name="student_info_empty">No info about student or student family</string>
|
||||
<string name="student_info_first_name">Name</string>
|
||||
<string name="student_info_second_name">Second name</string>
|
||||
<string name="student_info_gender">Gender</string>
|
||||
<string name="student_info_polish_citizenship">Polish citizenship</string>
|
||||
<string name="student_info_family_name">Family name</string>
|
||||
<string name="student_info_parents_name">Mother\'s and father\'s names</string>
|
||||
<string name="student_info_phone">Phone</string>
|
||||
<string name="student_info_cellphone">Cellphone</string>
|
||||
<string name="student_info_email">E-mail</string>
|
||||
<string name="student_info_address">Address of residence</string>
|
||||
<string name="student_info_registered_address">Address of registration</string>
|
||||
<string name="student_info_correspondence_address">Correspondence address</string>
|
||||
<string name="student_info_full_name">Surname and first name</string>
|
||||
<string name="student_info_kinship">Degree of kinship</string>
|
||||
<string name="student_info_guardian_address">Address</string>
|
||||
<string name="student_info_phones">Phones</string>
|
||||
<string name="student_info_male">Male</string>
|
||||
<string name="student_info_female">Female</string>
|
||||
<string name="student_info_last_name">Last name</string>
|
||||
<string name="student_info_guardian">Guardian</string>
|
||||
<!--Account edit-->
|
||||
<string name="account_edit_nick_hint">Nick</string>
|
||||
<string name="account_edit_header">Add nick</string>
|
||||
<string name="account_edit_avatar_title">Choose avatar color</string>
|
||||
<!--Log viewer-->
|
||||
<string name="logviewer_share">Share logs</string>
|
||||
<string name="logviewer_refresh">Refresh</string>
|
||||
<!--Dashboard-->
|
||||
<string name="dashboard_timetable_title">Lessons</string>
|
||||
<string name="dashboard_timetable_title_tomorrow">(Tomorrow)</string>
|
||||
<string name="dashboard_timetable_title_today_and_tomorrow">(Today and tomorrow)</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_moment">In a moment:</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_soon">Soon:</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_first">First:</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_now">Now:</string>
|
||||
<string name="dashboard_timetable_second_lesson_value_end">End of lessons</string>
|
||||
<string name="dashboard_timetable_second_lessons_title">Next:</string>
|
||||
<string name="dashboard_timetable_third_title">Later:</string>
|
||||
<plurals name="dashboard_timetable_third_value">
|
||||
<item quantity="one">%1$d more lesson</item>
|
||||
<item quantity="other">%1$d more lessons</item>
|
||||
</plurals>
|
||||
<string name="dashboard_timetable_third_time">until %1$s</string>
|
||||
<string name="dashboard_timetable_no_lessons">No upcoming lessons</string>
|
||||
<string name="dashboard_timetable_error">An error occurred while loading the lessons</string>
|
||||
<string name="dashboard_homework_title">Homework</string>
|
||||
<string name="dashboard_homework_no_homework">No homework to do</string>
|
||||
<string name="dashboard_homework_error">An error occurred while loading the homework</string>
|
||||
<plurals name="dashboard_homework_more">
|
||||
<item quantity="one">%1$d more homework</item>
|
||||
<item quantity="other">%1$d more homework</item>
|
||||
</plurals>
|
||||
<string name="dashboard_homework_time">due %1$s</string>
|
||||
<string name="dashboard_grade_title">Last grades</string>
|
||||
<string name="dashboard_grade_no_grade">No new grades</string>
|
||||
<string name="dashboard_grade_error">An error occurred while loading the grades</string>
|
||||
<string name="dashboard_announcements_title">School announcements</string>
|
||||
<string name="dashboard_announcements_no_announcements">No current announcements</string>
|
||||
<string name="dashboard_announcements_error">An error occurred while loading the announcements</string>
|
||||
<plurals name="dashboard_announcements_more">
|
||||
<item quantity="one">%1$d more announcement</item>
|
||||
<item quantity="other">%1$d more announcements</item>
|
||||
</plurals>
|
||||
<string name="dashboard_exams_title">Exams</string>
|
||||
<string name="dashboard_exams_no_exams">No upcoming exams</string>
|
||||
<string name="dashboard_exams_error">An error occurred while loading the exams</string>
|
||||
<plurals name="dashboard_exams_more">
|
||||
<item quantity="one">%1$d more exam</item>
|
||||
<item quantity="other">%1$d more exams</item>
|
||||
</plurals>
|
||||
<string name="dashboard_conferences_title">Conferences</string>
|
||||
<string name="dashboard_conferences_no_conferences">No upcoming conferences</string>
|
||||
<string name="dashboard_conferences_error">An error occurred while loading the conferences</string>
|
||||
<plurals name="dashboard_conference_more">
|
||||
<item quantity="one">%1$d more conference</item>
|
||||
<item quantity="other">%1$d more conferences</item>
|
||||
</plurals>
|
||||
<string name="dashboard_horizontal_group_error">An error occurred while loading data</string>
|
||||
<string name="dashboard_horizontal_group_no_data">None</string>
|
||||
<!--Error dialog-->
|
||||
<string name="dialog_error_check_update">Check for updates</string>
|
||||
<string name="dialog_error_check_update_message">Before reporting a bug, check first if an update with the bug fix is available</string>
|
||||
<!--Generic-->
|
||||
<string name="all_content">Content</string>
|
||||
<string name="all_retry">Retry</string>
|
||||
<string name="all_description">Description</string>
|
||||
<string name="all_no_description">No description</string>
|
||||
<string name="all_teacher">Teacher</string>
|
||||
<string name="all_date">Date</string>
|
||||
<string name="all_entry_date">Entry date</string>
|
||||
<string name="all_color">Color</string>
|
||||
<string name="all_details">Details</string>
|
||||
<string name="all_category">Category</string>
|
||||
<string name="all_close">Close</string>
|
||||
<string name="all_no_data">No data</string>
|
||||
<string name="all_subject">Subject</string>
|
||||
<string name="all_prev">Prev</string>
|
||||
<string name="all_next">Next</string>
|
||||
<string name="all_search">Search</string>
|
||||
<string name="all_search_hint">Search…</string>
|
||||
<string name="all_yes">Yes</string>
|
||||
<string name="all_no">No</string>
|
||||
<string name="all_save">Save</string>
|
||||
<string name="all_title">Title</string>
|
||||
<string name="all_add">Add</string>
|
||||
<string name="all_copied">Copied</string>
|
||||
<string name="all_undo">Undo</string>
|
||||
<string name="all_change">Change</string>
|
||||
<string name="all_add_to_calendar">Add to calendar</string>
|
||||
<string name="all_cancel">Cancel</string>
|
||||
<!--Timetable Widget-->
|
||||
<string name="widget_timetable_no_items">No lessons</string>
|
||||
<string name="widget_timetable_last_synchronization">Synchronized on %1$s at %2$s</string>
|
||||
<string name="widget_timetable_theme_title">Choose theme</string>
|
||||
<string name="widget_timetable_theme_light">Light</string>
|
||||
<string name="widget_timetable_theme_dark">Dark</string>
|
||||
<string name="widget_timetable_theme_system">System Theme</string>
|
||||
<!--Preferences-->
|
||||
<string name="pref_view_header">App</string>
|
||||
<string name="pref_view_list">Default view</string>
|
||||
<string name="pref_view_grade_average_mode">Calculated average options</string>
|
||||
<string name="pref_view_grade_average_force_calc">Force average calculation by app</string>
|
||||
<string name="pref_view_present">Show presence</string>
|
||||
<string name="pref_view_app_theme">Theme</string>
|
||||
<string name="pref_view_expand_grade">Grades expanding</string>
|
||||
<string name="pref_view_timetable_show_groups">Show groups next to subjects</string>
|
||||
<string name="pref_view_timetable_show_gaps">Show empty tiles where there\'s no lesson</string>
|
||||
<string name="pref_view_grade_statistics_list">Show chart list in class grades</string>
|
||||
<string name="pref_view_subjects_without_grades">Show subjects without grades</string>
|
||||
<string name="pref_view_grade_color_scheme">Grades color scheme</string>
|
||||
<string name="pref_view_grade_sorting_mode">Subjects sorting</string>
|
||||
<string name="pref_view_app_language">Language</string>
|
||||
<string name="pref_view_menu_order_title">Menu configuration</string>
|
||||
<string name="pref_view_menu_order_summary">Set the order of functions in the menu</string>
|
||||
<string name="pref_notify_header">Notifications</string>
|
||||
<string name="pref_notify_header_other">Other</string>
|
||||
<string name="pref_notify_switch">Show notifications</string>
|
||||
<string name="pref_notify_upcoming_lessons_switch">Show upcoming lesson notifications</string>
|
||||
<string name="pref_notify_upcoming_lessons_persistent_switch">Make upcoming lesson notification persistent</string>
|
||||
<string name="pref_notify_upcoming_lessons_persistent_summary">Turn off when notification is not showing in your watch/band</string>
|
||||
<string name="pref_notify_open_system_settings">Open system notification settings</string>
|
||||
<string name="pref_notify_fix_sync_issues">Fix synchronization & notifications issues</string>
|
||||
<string name="pref_notify_fix_sync_issues_message">Your device may have data synchronization issues and with notifications.\n\nTo fix them, you need to add Wulkanowy to the autostart and turn off battery optimization/saving in the phone settings.</string>
|
||||
<string name="pref_notify_debug_switch">Show debug notifications</string>
|
||||
<string name="pref_notify_disabled_summary">Synchronization is disabled</string>
|
||||
<string name="pref_notify_notifications_piggyback_header">Official app notifications</string>
|
||||
<string name="pref_notify_notifications_piggyback">Capture official app notifications</string>
|
||||
<string name="pref_notify_notifications_piggyback_cancel_original">Remove official app notifications after capture</string>
|
||||
<string name="pref_notification_piggyback_popup_title">Capture notifications</string>
|
||||
<string name="pref_notification_piggyback_popup_description">With this feature you can gain a substitute of push notifications like in the official app. All you need to do is allow Wulkanowy to receive all notifications in your system settings.\n\nHow it works?\nWhen you get a notification in Dziennik VULCAN, Wulkanowy will be notified (that\'s what these extra permissions are for) and will trigger a sync so that can send its own notification.\n\nFOR ADVANCED USERS ONLY</string>
|
||||
<string name="pref_notification_exact_alarm_popup_title">Upcoming lesson notifications</string>
|
||||
<string name="pref_notification_exact_alarm_popup_descriptions">You must allow the Wulkanowy app to set alarms and reminders in your system settings to use this feature.</string>
|
||||
<string name="pref_notification_go_to_settings">Go to settings</string>
|
||||
<string name="pref_services_header">Synchronization</string>
|
||||
<string name="pref_services_switch">Automatic update</string>
|
||||
<string name="pref_services_suspended">Suspended on holidays</string>
|
||||
<string name="pref_services_interval">Updates interval</string>
|
||||
<string name="pref_services_wifi">Wi-Fi only</string>
|
||||
<string name="pref_services_force_sync">Sync now</string>
|
||||
<string name="pref_services_message_sync_success">Synced!</string>
|
||||
<string name="pref_services_message_sync_failed">Sync failed</string>
|
||||
<string name="pref_services_sync_in_progress">Sync in progress</string>
|
||||
<string name="pref_services_last_full_sync_date">Last full sync: %s</string>
|
||||
<string name="pref_other_grade_modifier_plus">Value of the plus</string>
|
||||
<string name="pref_other_grade_modifier_minus">Value of the minus</string>
|
||||
<string name="pref_other_fill_message_content">Reply with message history</string>
|
||||
<string name="pref_other_optional_arithmetic_average">Show arithmetic average when no weights provided</string>
|
||||
<string name="pref_other_incognito_mode">Incognito mode</string>
|
||||
<string name="pref_other_incognito_mode_summary">Do not inform about reading the message</string>
|
||||
<string name="pref_ads_support_category_name">Support</string>
|
||||
<string name="pref_ads_privacy_policy">Privacy Policy</string>
|
||||
<string name="pref_ads_agreements">Agreements</string>
|
||||
<string name="pref_ads_consent">Show consent to data processing</string>
|
||||
<string name="pref_ads_show_in_app">Show ads in app</string>
|
||||
<string name="pref_ads_support">Watch single ad to support project</string>
|
||||
<string name="pref_ads_privacy_title">Consent to data processing</string>
|
||||
<string name="pref_ads_privacy_description">To view an advertisement you must agree to the data processing terms of our Privacy Policy</string>
|
||||
<string name="pref_ads_privacy_agree">Agree</string>
|
||||
<string name="pref_ads_privacy_link">Privacy policy</string>
|
||||
<string name="pref_ads_loading">Ad is loading</string>
|
||||
<string name="pref_ads_once_per_visit">Thank you for your support, come back later for more ads</string>
|
||||
<string name="pref_settings_advanced_title">Advanced</string>
|
||||
<string name="pref_settings_appearance_title">Appearance & Behavior</string>
|
||||
<string name="pref_settings_notifications_title">Notifications</string>
|
||||
<string name="pref_settings_sync_title">Synchronization</string>
|
||||
<string name="pref_settings_ads_title">Advertisements</string>
|
||||
<string name="pref_grades_appearance_header">Grades</string>
|
||||
<string name="pref_dashboard_appearance_header">Dashboard</string>
|
||||
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</string>
|
||||
<string name="pref_attendance_appearance_view">Attendance</string>
|
||||
<string name="pref_timetable_appearance_view">Timetable</string>
|
||||
<string name="pref_grades_advanced_header">Grades</string>
|
||||
<string name="pref_counted_average_advanced_header">Calculated average</string>
|
||||
<string name="pref_messages_advanced_header">Messages</string>
|
||||
<string name="pref_appearance_category">Appearance & Behavior</string>
|
||||
<string name="pref_appearance_category_summary">Languages, themes, subjects sorting</string>
|
||||
<string name="pref_notifications_category_summary">App notifications, fix problems</string>
|
||||
<string name="pref_notifications_category">Notifications</string>
|
||||
<string name="pref_sync_category">Synchronization</string>
|
||||
<string name="pref_sync_category_summary">Automatic update, synchronization interval</string>
|
||||
<string name="pref_advanced_category_summary">Plus and minus values, average calculation</string>
|
||||
<string name="pref_advanced_category">Advanced</string>
|
||||
<string name="pref_about_category_summary">App version, contributors, social portals</string>
|
||||
<string name="pref_ads_category_summary">Displaying advertisements, project support</string>
|
||||
<!--Notification Channels-->
|
||||
<string name="channel_new_grades">New grades</string>
|
||||
<string name="channel_new_homework">New homework</string>
|
||||
<string name="channel_new_conference">New conferences</string>
|
||||
<string name="channel_new_exam">New exams</string>
|
||||
<string name="channel_lucky_number">Lucky number</string>
|
||||
<string name="channel_new_message">New messages</string>
|
||||
<string name="channel_new_notes">New notes</string>
|
||||
<string name="channel_new_school_announcement">New school announcements</string>
|
||||
<string name="channel_push">Push notifications</string>
|
||||
<string name="channel_upcoming_lessons">Upcoming lessons</string>
|
||||
<string name="channel_debug">Debug</string>
|
||||
<string name="channel_change_timetable">Timetable change</string>
|
||||
<string name="channel_new_attendance">New attendance</string>
|
||||
<!--Colors-->
|
||||
<string name="all_black">Black</string>
|
||||
<string name="all_red">Red</string>
|
||||
<string name="all_blue">Blue</string>
|
||||
<string name="all_green">Green</string>
|
||||
<string name="all_purple">Purple</string>
|
||||
<string name="all_empty_color">No color</string>
|
||||
<!--Update helper-->
|
||||
<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_button">Restart</string>
|
||||
<string name="update_failed">Update failed! Wulkanowy may not function properly. Consider updating</string>
|
||||
<!--Menu order-->
|
||||
<string name="menu_order_confirm_title">Application restart</string>
|
||||
<string name="menu_order_confirm_content">The application must restart for the changes to be saved</string>
|
||||
<string name="menu_order_confirm_restart">Restart</string>
|
||||
<!--Auth-->
|
||||
<string name="auth_api_error">Authorization has been rejected. The data provided does not match the records in the secretary\'s office.</string>
|
||||
<string name="auth_invalid_error">Invalid PESEL</string>
|
||||
<string name="auth_pesel">PESEL</string>
|
||||
<string name="auth_button">Authorize</string>
|
||||
<string name="auth_success">Authorization completed successfully</string>
|
||||
<string name="auth_title">Authorization</string>
|
||||
<string name="auth_description">To operate the application, we need to confirm your identity. Please enter the student\'s PESEL <b>%1$s</b> in the field below</string>
|
||||
<string name="auth_button_skip">Skip for now</string>
|
||||
<!--Errors-->
|
||||
<string name="error_no_internet">No internet connection</string>
|
||||
<string name="error_invalid_device_datetime">An error occurred. Check your device clock</string>
|
||||
<string name="error_timeout">Connection to register failed. Servers can be overloaded. Please try again later</string>
|
||||
<string name="error_login_failed">Loading data failed. Please try again later</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_unknown_uonet">Unknown UONET + register error. Try again later</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_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_field_required">This field is required</string>
|
||||
</resources>
|
@ -1,759 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!--Activity/Fragment title-->
|
||||
<string name="login_title">Login</string>
|
||||
<string name="main_title">Wulkanowy</string>
|
||||
<string name="grade_title">Grades</string>
|
||||
<string name="attendance_title">Attendance</string>
|
||||
<string name="exam_title">Exams</string>
|
||||
<string name="timetable_title">Timetable</string>
|
||||
<string name="settings_title">Settings</string>
|
||||
<string name="more_title">More</string>
|
||||
<string name="about_title">About</string>
|
||||
<string name="logviewer_title">Log viewer</string>
|
||||
<string name="debug_title">Debug</string>
|
||||
<string name="notification_debug_title">Notification debug</string>
|
||||
<string name="contributors_title">Contributors</string>
|
||||
<string name="license_title">Licenses</string>
|
||||
<string name="message_title">Messages</string>
|
||||
<string name="send_message_title">New message</string>
|
||||
<string name="add_homework_title">New homework</string>
|
||||
<string name="note_title">Notes and achievements</string>
|
||||
<string name="homework_title">Homework</string>
|
||||
<string name="account_title">Accounts manager</string>
|
||||
<string name="account_quick_title">Select account</string>
|
||||
<string name="account_details_title">Account details</string>
|
||||
<string name="student_info_title">Student info</string>
|
||||
<string name="dashboard_title">Dashboard</string>
|
||||
<string name="notifications_center_title">Notifications center</string>
|
||||
<string name="menu_order_title">Menu configuartion</string>
|
||||
<!--Subtitles-->
|
||||
<string name="grade_subtitle">Semester %1$d, %2$d/%3$d</string>
|
||||
<!--Login-->
|
||||
<string name="login_header_default">Sign in with the student or parent account</string>
|
||||
<string name="login_header_symbol">Enter the symbol from the register page for account: <b>%1$s</b></string>
|
||||
<string name="login_nickname_hint">Username</string>
|
||||
<string name="login_email_hint">Email</string>
|
||||
<string name="login_login_pesel_email_hint">Login, PESEL or e-mail</string>
|
||||
<string name="login_password_hint">Password</string>
|
||||
<string name="login_host_hint">UONET+ register variant</string>
|
||||
<string name="login_domain_suffix_hint">Custom domain suffix</string>
|
||||
<string name="login_type_api">Mobile API</string>
|
||||
<string name="login_type_scrapper">Scraper</string>
|
||||
<string name="login_type_hybrid">Hybrid</string>
|
||||
<string name="login_token_hint">Token</string>
|
||||
<string name="login_pin_hint">PIN</string>
|
||||
<string name="login_symbol_hint">Symbol</string>
|
||||
<string name="login_symbol_placeholder">E.g. \"lodz\" or \"powiatjaroslawski\"</string>
|
||||
<string name="login_sign_in">Sign in</string>
|
||||
<string name="login_invalid_password">Password too short</string>
|
||||
<string name="login_incorrect_password_default">Login details are incorrect</string>
|
||||
<string name="login_incorrect_password">%1$s. Make sure the correct UONET+ register variation is selected below</string>
|
||||
<string name="login_invalid_pin">Invalid PIN</string>
|
||||
<string name="login_invalid_token">Invalid token</string>
|
||||
<string name="login_expired_token">Token expired</string>
|
||||
<string name="login_invalid_email">Invalid email</string>
|
||||
<string name="login_invalid_login">Use the assigned login instead of email</string>
|
||||
<string name="login_invalid_custom_email">Use the assigned login or email in @%1$s</string>
|
||||
<string name="login_invalid_symbol">Invalid symbol. If you cannot find it, please contact the school</string>
|
||||
<string name="login_invalid_symbol_definitely">Don\'t make this up! If you cannot find it, please contact the school</string>
|
||||
<string name="login_incorrect_symbol">Student not found. Validate the symbol and the chosen variation of the UONET+ register</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 <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Wygeneruj kod dostępu</b>.\n\nMake sure that you have set the appropriate register variant in the <b>UONET+ register variant</b> field on the first login screen</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_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_scraper">This mode displays the same data as it appears on the register website</string>
|
||||
<string name="login_advanced_warning_hybrid">The combination of the best features of the other two modes. It works faster than scraper and provides features not available in the Mobile API mode. It is in the experimental phase</string>
|
||||
<string name="login_privacy_policy">Privacy policy</string>
|
||||
<string name="login_contact_header">Trouble signing in? Contact us!</string>
|
||||
<string name="login_contact_email">Email</string>
|
||||
<string name="login_contact_discord">Discord</string>
|
||||
<string name="login_email_intent_title">Send email</string>
|
||||
<string name="login_recover_warning">Make sure you select the correct UONET+ register variation!</string>
|
||||
<string name="login_recover_button">Reset password</string>
|
||||
<string name="login_recover_title">Recover your account</string>
|
||||
<string name="login_recover">Recover</string>
|
||||
<string name="login_signed_in">Student is already signed in</string>
|
||||
<string name="login_host_standard">Standard</string>
|
||||
<string name="login_other_search_locations">Other search locations</string>
|
||||
<string name="login_no_active_student">No active students found</string>
|
||||
<string name="login_symbol_enter">Enter a different symbol</string>
|
||||
<string name="login_support_title">Get help</string>
|
||||
<string name="login_support_school_hint">Full school name with the town (required)</string>
|
||||
<string name="login_support_school_placeholder">Np. ZSTiO Jarosław lub SP nr 99 w Łodzi</string>
|
||||
<string name="login_support_school_invalid">Enter correct name of the school</string>
|
||||
<string name="login_support_additional_hint">Additional information in Polish (optional)</string>
|
||||
<string name="login_support_additional_placeholder">Np. \"Ostatnio zmieniłem szkołę i…\" albo \"Jestem rodzicem i nie widzę drugiego dziecka…\"</string>
|
||||
<string name="login_support_submit">Submit</string>
|
||||
<!--Notifications-->
|
||||
<string name="notifications_header_title">Enable notifications</string>
|
||||
<string name="notifications_header_description">Enable notifications so you don\'t miss message from teacher or new grade</string>
|
||||
<string name="notifications_skip">Skip</string>
|
||||
<string name="notifications_enable">Enable</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Account manager</string>
|
||||
<string name="main_log_in">Log in</string>
|
||||
<string name="main_session_expired">Session expired</string>
|
||||
<string name="main_session_relogin">Session expired, log in again</string>
|
||||
<string name="main_expired_credentials_description">Your account password has been changed. You need to log in to Wulkanowy again</string>
|
||||
<string name="main_expired_credentials_title">Password changed</string>
|
||||
<string name="main_support_title">Application support</string>
|
||||
<string name="main_support_description">Do you like this app? Support its development by enabling non-invasive ads that you can disable at any time</string>
|
||||
<string name="main_support_positive">Enable ads</string>
|
||||
<!--Grade-->
|
||||
<string name="grade_header">Grade</string>
|
||||
<string name="grade_semester">Semester %d</string>
|
||||
<string name="grade_switch_semester">Change semester</string>
|
||||
<string name="grade_no_items">No grades</string>
|
||||
<string name="grade_weight">Weight</string>
|
||||
<string name="grade_weight_value">Weight: %s</string>
|
||||
<string name="grade_comment">Comment</string>
|
||||
<string name="grade_number_new_items">Number of new ratings: %1$d</string>
|
||||
<string name="grade_average">Average: %1$.2f</string>
|
||||
<string name="grade_points_sum">Points: %s</string>
|
||||
<string name="grade_no_average">No average</string>
|
||||
<string name="grade_summary_points">Total points</string>
|
||||
<string name="grade_summary_final_grade">Final grade</string>
|
||||
<string name="grade_summary_predicted_grade">Predicted grade</string>
|
||||
<string name="grade_summary_calculated_average">Calculated average</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_title">How does Calculated Average work?</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_message">The Calculated Average is the arithmetic average calculated from the subjects averages. It allows you to know the approximate final average. It is calculated in a way selected by the user in the application settings. It is recommended that you choose the appropriate option. This is because the calculation of school averages differs. Additionally, if your school reports the average of the subjects on the Vulcan page, the application downloads them and does not calculate these averages. This can be changed by forcing the calculation of the average in the application settings.\n\n<b>Average of grades only from selected semester</b>:\n1. Calculating the weighted average for each subject in a given semester\n2.Adding calculated averages\n3. Calculation of the arithmetic average of the summed averages\n\n<b>Average of averages from both semesters</b>:\n1.Calculating the weighted average for each subject in semester 1 and 2\n2. Calculating the arithmetic average of the calculated averages for semesters 1 and 2 for each subject.\n3. Adding calculated averages\n4. Calculation of the arithmetic average of the summed averages\n\n<b>Average of grades from the whole year:</b>\n1. Calculating weighted average over the year for each subject. The final average in the 1st semester is irrelevant.\n2. Adding calculated averages\n3. Calculating the arithmetic average of summed averages</string>
|
||||
<string name="grade_summary_final_average_help_dialog_title">How does the Final Average work?</string>
|
||||
<string name="grade_summary_final_average_help_dialog_message">The Final Average is the arithmetic average calculated from all currently available final grades in the given semester.\n\nThe calculation scheme consists of the following steps:\n1. Summing up the final grades given by teachers\n2. Divide by the number of subjects that have already been graded</string>
|
||||
<string name="grade_summary_final_average">Final average</string>
|
||||
<string name="grade_summary_from_subjects">from %1$d of %2$d subjects</string>
|
||||
<string name="grade_menu_summary">Summary</string>
|
||||
<string name="grade_menu_statistics">Class</string>
|
||||
<string name="grade_menu_read">Mark as read</string>
|
||||
<string name="grade_statistics_partial">Partial</string>
|
||||
<string name="grade_statistics_semester">Semester</string>
|
||||
<string name="grade_statistics_points">Points</string>
|
||||
<string name="grade_statistics_legend">Legend</string>
|
||||
<string name="grade_statistics_class_average">Class average: %1$s</string>
|
||||
<string name="grade_statistics_student_average">Your average: %1$s</string>
|
||||
<string name="grade_statistics_student_grade">Your grade: %1$s</string>
|
||||
<string name="grade_statistics_average_class">Class</string>
|
||||
<string name="grade_statistics_average_student">Student</string>
|
||||
<plurals name="grade_number_item">
|
||||
<item quantity="one">%d grade</item>
|
||||
<item quantity="other">%d grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items">
|
||||
<item quantity="one">New grade</item>
|
||||
<item quantity="other">New grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_predicted">
|
||||
<item quantity="one">New predicted grade</item>
|
||||
<item quantity="other">New predicted grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_final">
|
||||
<item quantity="one">New final grade</item>
|
||||
<item quantity="other">New final grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items">
|
||||
<item quantity="one">You received %1$d grade</item>
|
||||
<item quantity="other">You received %1$d grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_predicted">
|
||||
<item quantity="one">You received %1$d predicted grade</item>
|
||||
<item quantity="other">You received %1$d predicted grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_final">
|
||||
<item quantity="one">You received %1$d final grade</item>
|
||||
<item quantity="other">You received %1$d final grades</item>
|
||||
</plurals>
|
||||
<!--Timetable-->
|
||||
<string name="timetable_lesson">Lesson</string>
|
||||
<string name="timetable_room">Room</string>
|
||||
<string name="timetable_group">Group</string>
|
||||
<string name="timetable_time">Hours</string>
|
||||
<string name="timetable_changes">Changes</string>
|
||||
<string name="timetable_no_items">No lessons this day</string>
|
||||
<string name="timetable_minutes">%s min</string>
|
||||
<string name="timetable_seconds">%s sec</string>
|
||||
<string name="timetable_time_left">%1$s left</string>
|
||||
<string name="timetable_time_until">in %1$s</string>
|
||||
<string name="timetable_finished">Finished</string>
|
||||
<string name="timetable_now">Now: %s</string>
|
||||
<string name="timetable_next">Next: %s</string>
|
||||
<string name="timetable_later">Later: %s</string>
|
||||
<string name="timetable_notify_lesson">%1$s lesson %2$d - %3$s</string>
|
||||
<string name="timetable_notify_change_room">Change of room from %1$s to %2$s</string>
|
||||
<string name="timetable_notify_change_teacher">Change of teacher from %1$s to %2$s</string>
|
||||
<string name="timetable_notify_change_subject">Change of subject from %1$s to %2$s</string>
|
||||
<plurals name="timetable_no_lesson">
|
||||
<item quantity="one">No lesson</item>
|
||||
<item quantity="other">No lessons</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_notify_new_items_title">
|
||||
<item quantity="one">Timetable change</item>
|
||||
<item quantity="other">Timetable changes</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_notify_new_items">
|
||||
<item quantity="one">%1$s - %2$d change in timetable</item>
|
||||
<item quantity="other">%1$s - %2$d changes in timetable</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_notify_new_items_group">
|
||||
<item quantity="one">%1$d change in timetable</item>
|
||||
<item quantity="other">%1$d changes in timetable</item>
|
||||
</plurals>
|
||||
<plurals name="timetable_number_item">
|
||||
<item quantity="one">%d change</item>
|
||||
<item quantity="other">%d changes</item>
|
||||
</plurals>
|
||||
<!--Completed lessons-->
|
||||
<string name="completed_lessons_title">Completed lessons</string>
|
||||
<string name="completed_lessons_button">Show completed lessons</string>
|
||||
<string name="completed_lessons_no_items">No info about completed lessons</string>
|
||||
<string name="completed_lessons_topic">Topic</string>
|
||||
<string name="completed_lessons_absence">Absence</string>
|
||||
<string name="completed_lessons_resources">Resources</string>
|
||||
<!--Additional lessons-->
|
||||
<string name="additional_lessons_title">Additional lessons</string>
|
||||
<string name="additional_lessons_button">Show additional lessons</string>
|
||||
<string name="additional_lessons_no_items">No info about additional lessons</string>
|
||||
<string name="additional_lessons_add">New lesson</string>
|
||||
<string name="additional_lessons_add_title">New additional lesson</string>
|
||||
<string name="additional_lessons_add_success">Additional lesson added successfully</string>
|
||||
<string name="additional_lessons_delete_success">Additional lesson deleted successfully</string>
|
||||
<string name="additional_lessons_repeat">Repeat weekly</string>
|
||||
<string name="additional_lessons_delete_title">Delete additional lesson</string>
|
||||
<string name="additional_lessons_delete_one">Just this lesson</string>
|
||||
<string name="additional_lessons_delete_series">All in the series</string>
|
||||
<string name="additional_lessons_start">Start time</string>
|
||||
<string name="additional_lessons_end">End time</string>
|
||||
<string name="additional_lessons_end_time_error">End time must be greater than start time</string>
|
||||
<!--Attendance-->
|
||||
<string name="attendance_summary_button">Attendance summary</string>
|
||||
<string name="attendance_absence_school">Absent for school reasons</string>
|
||||
<string name="attendance_absence_excused">Excused absence</string>
|
||||
<string name="attendance_absence_unexcused">Unexcused absence</string>
|
||||
<string name="attendance_exemption">Exemption</string>
|
||||
<string name="attendance_excused_lateness">Excused lateness</string>
|
||||
<string name="attendance_unexcused_lateness">Unexcused lateness</string>
|
||||
<string name="attendance_present">Present</string>
|
||||
<string name="attendance_deleted">Deleted</string>
|
||||
<string name="attendance_unknown">Unknown</string>
|
||||
<string name="attendance_number">Number of lesson</string>
|
||||
<string name="attendance_no_items">No entries</string>
|
||||
<string name="attendance_excuse_dialog_reason">Absence reason (optional)</string>
|
||||
<string name="attendance_excuse_dialog_submit">Send</string>
|
||||
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
|
||||
<string name="attendance_excuse_no_selection">You must select at least one absence!</string>
|
||||
<string name="attendance_excuse_title">Excuse</string>
|
||||
<plurals name="attendance_notify_new_items_title">
|
||||
<item quantity="one">New attendance</item>
|
||||
<item quantity="other">New attendance</item>
|
||||
</plurals>
|
||||
<plurals name="attendance_notify_new_items">
|
||||
<item quantity="one">%1$d new attendance</item>
|
||||
<item quantity="other">%1$d attendance</item>
|
||||
</plurals>
|
||||
<plurals name="attendance_number_item">
|
||||
<item quantity="one">%d attendance</item>
|
||||
<item quantity="other">%d attendance</item>
|
||||
</plurals>
|
||||
<!--Attendance summary-->
|
||||
<string name="attendance_summary_total">Total</string>
|
||||
<!--Exam-->
|
||||
<string name="exam_no_items">No exams this week</string>
|
||||
<string name="exam_type">Type</string>
|
||||
<string name="exam_entry_date">Entry date</string>
|
||||
<plurals name="exam_notify_new_item_title">
|
||||
<item quantity="one">New exam</item>
|
||||
<item quantity="other">New exams</item>
|
||||
</plurals>
|
||||
<plurals name="exam_notify_new_item_content">
|
||||
<item quantity="one">%d new exam</item>
|
||||
<item quantity="other">%d new exams</item>
|
||||
</plurals>
|
||||
<plurals name="exam_number_item">
|
||||
<item quantity="one">%d exam</item>
|
||||
<item quantity="other">%d exams</item>
|
||||
</plurals>
|
||||
<!--Message-->
|
||||
<string name="message_inbox">Inbox</string>
|
||||
<string name="message_sent">Sent</string>
|
||||
<string name="message_trash">Trash</string>
|
||||
<string name="message_no_subject">(no subject)</string>
|
||||
<string name="message_no_items">No messages</string>
|
||||
<string name="message_from">From:</string>
|
||||
<string name="message_to">To:</string>
|
||||
<string name="message_date">Date: %1$s</string>
|
||||
<string name="message_reply">Reply</string>
|
||||
<string name="message_forward">Forward</string>
|
||||
<string name="message_select_all">Select all</string>
|
||||
<string name="message_unselect_all">Unselect all</string>
|
||||
<string name="message_move_to_trash">Move to trash</string>
|
||||
<string name="message_delete_forever">Delete permanently</string>
|
||||
<string name="message_delete_success">Message deleted successfully</string>
|
||||
<string name="message_mailbox_type_student">student</string>
|
||||
<string name="message_mailbox_type_parent">parent</string>
|
||||
<string name="message_mailbox_type_guardian">guardian</string>
|
||||
<string name="message_mailbox_type_employee">employee</string>
|
||||
<string name="message_share">Share</string>
|
||||
<string name="message_print">Print</string>
|
||||
<string name="message_subject">Subject</string>
|
||||
<string name="message_content">Content</string>
|
||||
<string name="message_send_successful">Message sent successfully</string>
|
||||
<string name="message_not_exists">Message does not exist</string>
|
||||
<string name="message_required_recipients">You need to choose at least 1 recipient</string>
|
||||
<string name="message_content_min_length">The message content must be at least 3 characters</string>
|
||||
<string name="message_chip_all_mailboxes">All mailboxes</string>
|
||||
<string name="message_chip_only_unread">Only unread</string>
|
||||
<string name="message_chip_only_with_attachments">Only with attachments</string>
|
||||
<string name="message_read">Read: %s</string>
|
||||
<string name="message_read_by">Read by: %1$d of %2$d people</string>
|
||||
<plurals name="message_number_item">
|
||||
<item quantity="one">%1$d message</item>
|
||||
<item quantity="other">%1$d messages</item>
|
||||
</plurals>
|
||||
<plurals name="message_new_items">
|
||||
<item quantity="one">New message</item>
|
||||
<item quantity="other">New messages</item>
|
||||
</plurals>
|
||||
<string name="message_restore_dialog">Do you want to restore draft message?</string>
|
||||
<string name="message_restore_dialog_with_recipients">Do you want to restore draft message with recipients: %s?</string>
|
||||
<plurals name="message_notify_new_items">
|
||||
<item quantity="one">You received %1$d message</item>
|
||||
<item quantity="other">You received %1$d messages</item>
|
||||
</plurals>
|
||||
<plurals name="message_selected_messages_count">
|
||||
<item quantity="one">%1$d selected</item>
|
||||
<item quantity="other">%1$d selected</item>
|
||||
</plurals>
|
||||
<string name="message_messages_deleted">Messages deleted</string>
|
||||
<string name="message_mailbox_chooser_title">Choose mailbox</string>
|
||||
<string name="message_incognito_mode_on">Incognito mode is on</string>
|
||||
<string name="message_incognito_description">Thanks to incognito mode sender is not notified when you read the message</string>
|
||||
<!--Note-->
|
||||
<string name="note_no_items">No info about notes</string>
|
||||
<string name="note_points">Points</string>
|
||||
<plurals name="note_number_item">
|
||||
<item quantity="one">%d note</item>
|
||||
<item quantity="other">%d notes</item>
|
||||
</plurals>
|
||||
<plurals name="note_new_items">
|
||||
<item quantity="one">New note</item>
|
||||
<item quantity="other">New notes</item>
|
||||
</plurals>
|
||||
<plurals name="note_notify_new_items">
|
||||
<item quantity="one">You received %1$d note</item>
|
||||
<item quantity="other">You received %1$d notes</item>
|
||||
</plurals>
|
||||
<!--Praise-->
|
||||
<plurals name="praise_number_item">
|
||||
<item quantity="one">%d praise</item>
|
||||
<item quantity="other">%d praises</item>
|
||||
</plurals>
|
||||
<plurals name="praise_new_items">
|
||||
<item quantity="one">New praise</item>
|
||||
<item quantity="other">New praises</item>
|
||||
</plurals>
|
||||
<plurals name="praise_notify_new_items">
|
||||
<item quantity="one">You received %1$d praise</item>
|
||||
<item quantity="other">You received %1$d praises</item>
|
||||
</plurals>
|
||||
<!--Neutral notes-->
|
||||
<plurals name="neutral_note_number_item">
|
||||
<item quantity="one">%d neutral note</item>
|
||||
<item quantity="other">%d neutral notes</item>
|
||||
</plurals>
|
||||
<plurals name="neutral_note_new_items">
|
||||
<item quantity="one">New neutral note</item>
|
||||
<item quantity="other">New neutral notes</item>
|
||||
</plurals>
|
||||
<plurals name="neutral_note_notify_new_items">
|
||||
<item quantity="one">You received %1$d neutral note</item>
|
||||
<item quantity="other">You received %1$d neutral notes</item>
|
||||
</plurals>
|
||||
<!--Homework-->
|
||||
<string name="homework_no_items">No info about homework</string>
|
||||
<string name="homework_mark_as_done">Mark as done</string>
|
||||
<string name="homework_mark_as_undone">Mark as undone</string>
|
||||
<string name="homework_add">Add homework</string>
|
||||
<string name="homework_add_success">Homework added successfully</string>
|
||||
<string name="homework_delete_success">Homework deleted successfully</string>
|
||||
<string name="homework_attachments">Attachments</string>
|
||||
<plurals name="homework_notify_new_item_title">
|
||||
<item quantity="one">New homework</item>
|
||||
<item quantity="other">New homework</item>
|
||||
</plurals>
|
||||
<plurals name="homework_notify_new_item_content">
|
||||
<item quantity="one">You received %d new homework</item>
|
||||
<item quantity="other">You received %d new homework</item>
|
||||
</plurals>
|
||||
<plurals name="homework_number_item">
|
||||
<item quantity="one">%d homework</item>
|
||||
<item quantity="other">%d homework</item>
|
||||
</plurals>
|
||||
<!--Lucky number-->
|
||||
<string name="lucky_number_title">Lucky number</string>
|
||||
<string name="lucky_number_header">Today\'s lucky number is</string>
|
||||
<string name="lucky_number_empty">No info about the lucky number</string>
|
||||
<string name="lucky_number_notify_new_item_title">Lucky number for today</string>
|
||||
<string name="lucky_number_notify_new_item">Today\'s lucky number is: %s</string>
|
||||
<string name="lucky_number_history_button">Show history</string>
|
||||
<!--Lucky number history-->
|
||||
<string name="lucky_number_history_title">Lucky number history</string>
|
||||
<string name="lucky_number_history_empty">No info about lucky numbers</string>
|
||||
<!--Mobile devices-->
|
||||
<string name="mobile_devices_title">Mobile devices</string>
|
||||
<string name="mobile_devices_no_items">No devices</string>
|
||||
<string name="mobile_devices_unregister">Deregister</string>
|
||||
<string name="mobile_device_removed">Device removed</string>
|
||||
<string name="mobile_device_qr">QR code</string>
|
||||
<string name="mobile_device_token">Token</string>
|
||||
<string name="mobile_device_symbol">Symbol</string>
|
||||
<string name="mobile_device_pin">PIN</string>
|
||||
<!--School and teachers-->
|
||||
<string name="schoolandteachers_title">School and teachers</string>
|
||||
<!--School-->
|
||||
<string name="school_title">School</string>
|
||||
<string name="school_no_info">No info about school</string>
|
||||
<string name="school_name">School name</string>
|
||||
<string name="school_address">School address</string>
|
||||
<string name="school_telephone">Telephone</string>
|
||||
<string name="school_headmaster">Name of headmaster</string>
|
||||
<string name="school_pedagogue">Name of pedagogue</string>
|
||||
<string name="school_address_button">Show on map</string>
|
||||
<string name="school_telephone_button">Call</string>
|
||||
<!--Teacher-->
|
||||
<string name="teachers_title">Teachers</string>
|
||||
<string name="teacher_no_items">No info about teachers</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>
|
||||
<plurals name="conference_number_item">
|
||||
<item quantity="one">%d conference</item>
|
||||
<item quantity="other">%d conferences</item>
|
||||
</plurals>
|
||||
<plurals name="conference_notify_new_item_title">
|
||||
<item quantity="one">New conference</item>
|
||||
<item quantity="other">New conferences</item>
|
||||
</plurals>
|
||||
<plurals name="conference_notify_new_items">
|
||||
<item quantity="one">You have %1$d new conference</item>
|
||||
<item quantity="other">You have %1$d new conferences</item>
|
||||
</plurals>
|
||||
<string name="conferences_present">Present at conference</string>
|
||||
<string name="conference_agenda">Agenda</string>
|
||||
<string name="conference_place">Place</string>
|
||||
<string name="conference_topic">Topic</string>
|
||||
<!--Director information-->
|
||||
<string name="school_announcement_title">School announcements</string>
|
||||
<string name="school_announcement_no_items">No school announcements</string>
|
||||
<plurals name="school_announcement_number_item">
|
||||
<item quantity="one">%d school announcement</item>
|
||||
<item quantity="other">%d school announcements</item>
|
||||
</plurals>
|
||||
<plurals name="school_announcement_notify_new_item_title">
|
||||
<item quantity="one">New school announcement</item>
|
||||
<item quantity="other">New school announcements</item>
|
||||
</plurals>
|
||||
<plurals name="school_announcement_notify_new_items">
|
||||
<item quantity="one">You have %1$d new school announcement</item>
|
||||
<item quantity="other">You have %1$d new school announcements</item>
|
||||
</plurals>
|
||||
<!--Account-->
|
||||
<string name="account_add_new">Add account</string>
|
||||
<string name="account_logout">Logout</string>
|
||||
<string name="account_confirm">Do you want to log out this student?</string>
|
||||
<string name="account_logout_student">Student logout</string>
|
||||
<string name="account_type_student">Student account</string>
|
||||
<string name="account_type_parent">Parent account</string>
|
||||
<string name="account_details_edit">Edit data</string>
|
||||
<string name="account_quick_manager">Accounts manager</string>
|
||||
<string name="account_select_student">Select student</string>
|
||||
<string name="account_family">Family</string>
|
||||
<string name="account_contact">Contact</string>
|
||||
<string name="account_address">Residence details</string>
|
||||
<string name="account_personal_data">Personal information</string>
|
||||
<!--About-->
|
||||
<string name="about_version">App version</string>
|
||||
<string name="about_contributor">Contributors</string>
|
||||
<string name="about_contributor_summary">List of Wulkanowy developers</string>
|
||||
<string name="about_feedback">Report a bug</string>
|
||||
<string name="about_feedback_summary">Send a bug report via e-mail</string>
|
||||
<string name="about_faq">FAQ</string>
|
||||
<string name="about_faq_summary">Read Frequently Asked Questions</string>
|
||||
<string name="about_discord">Discord server</string>
|
||||
<string name="about_discord_summary">Join the Wulkanowy community</string>
|
||||
<string name="about_facebook">Facebook fanpage</string>
|
||||
<string name="about_twitter">Twitter page</string>
|
||||
<string name="about_twitter_summary">Follow us on twitter</string>
|
||||
<string name="about_facebook_summary">Like our facebook fanpage</string>
|
||||
<string name="about_privacy">Privacy policy</string>
|
||||
<string name="about_privacy_summary">Rules for collecting personal data</string>
|
||||
<string name="about_system">System settings</string>
|
||||
<string name="about_system_summary">Open system settings</string>
|
||||
<string name="about_homepage">Homepage</string>
|
||||
<string name="about_homepage_summary">Visit the website and help develop the application</string>
|
||||
<string name="about_licenses">Licenses</string>
|
||||
<string name="about_licenses_summary">Licenses of libraries used in the application</string>
|
||||
<!--Licenses-->
|
||||
<string name="license_dialog_title">License</string>
|
||||
<!--Contributor-->
|
||||
<string name="contributor_avatar_description">Avatar</string>
|
||||
<string name="contributor_see_more">See more on GitHub</string>
|
||||
<!--Student info-->
|
||||
<string name="student_info_empty">No info about student or student family</string>
|
||||
<string name="student_info_first_name">Name</string>
|
||||
<string name="student_info_second_name">Second name</string>
|
||||
<string name="student_info_gender">Gender</string>
|
||||
<string name="student_info_polish_citizenship">Polish citizenship</string>
|
||||
<string name="student_info_family_name">Family name</string>
|
||||
<string name="student_info_parents_name">Mother\'s and father\'s names</string>
|
||||
<string name="student_info_phone">Phone</string>
|
||||
<string name="student_info_cellphone">Cellphone</string>
|
||||
<string name="student_info_email">E-mail</string>
|
||||
<string name="student_info_address">Address of residence</string>
|
||||
<string name="student_info_registered_address">Address of registration</string>
|
||||
<string name="student_info_correspondence_address">Correspondence address</string>
|
||||
<string name="student_info_full_name">Surname and first name</string>
|
||||
<string name="student_info_kinship">Degree of kinship</string>
|
||||
<string name="student_info_guardian_address">Address</string>
|
||||
<string name="student_info_phones">Phones</string>
|
||||
<string name="student_info_male">Male</string>
|
||||
<string name="student_info_female">Female</string>
|
||||
<string name="student_info_last_name">Last name</string>
|
||||
<string name="student_info_guardian">Guardian</string>
|
||||
<!--Account edit-->
|
||||
<string name="account_edit_nick_hint">Nick</string>
|
||||
<string name="account_edit_header">Add nick</string>
|
||||
<string name="account_edit_avatar_title">Choose avatar color</string>
|
||||
<!--Log viewer-->
|
||||
<string name="logviewer_share">Share logs</string>
|
||||
<string name="logviewer_refresh">Refresh</string>
|
||||
<!--Dashboard-->
|
||||
<string name="dashboard_timetable_title">Lessons</string>
|
||||
<string name="dashboard_timetable_title_tomorrow">(Tomorrow)</string>
|
||||
<string name="dashboard_timetable_title_today_and_tomorrow">(Today and tomorrow)</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_moment">In a moment:</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_soon">Soon:</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_first">First:</string>
|
||||
<string name="dashboard_timetable_first_lesson_title_now">Now:</string>
|
||||
<string name="dashboard_timetable_second_lesson_value_end">End of lessons</string>
|
||||
<string name="dashboard_timetable_second_lessons_title">Next:</string>
|
||||
<string name="dashboard_timetable_third_title">Later:</string>
|
||||
<plurals name="dashboard_timetable_third_value">
|
||||
<item quantity="one">%1$d more lesson</item>
|
||||
<item quantity="other">%1$d more lessons</item>
|
||||
</plurals>
|
||||
<string name="dashboard_timetable_third_time">until %1$s</string>
|
||||
<string name="dashboard_timetable_no_lessons">No upcoming lessons</string>
|
||||
<string name="dashboard_timetable_error">An error occurred while loading the lessons</string>
|
||||
<string name="dashboard_homework_title">Homework</string>
|
||||
<string name="dashboard_homework_no_homework">No homework to do</string>
|
||||
<string name="dashboard_homework_error">An error occurred while loading the homework</string>
|
||||
<plurals name="dashboard_homework_more">
|
||||
<item quantity="one">%1$d more homework</item>
|
||||
<item quantity="other">%1$d more homework</item>
|
||||
</plurals>
|
||||
<string name="dashboard_homework_time">due %1$s</string>
|
||||
<string name="dashboard_grade_title">Last grades</string>
|
||||
<string name="dashboard_grade_no_grade">No new grades</string>
|
||||
<string name="dashboard_grade_error">An error occurred while loading the grades</string>
|
||||
<string name="dashboard_announcements_title">School announcements</string>
|
||||
<string name="dashboard_announcements_no_announcements">No current announcements</string>
|
||||
<string name="dashboard_announcements_error">An error occurred while loading the announcements</string>
|
||||
<plurals name="dashboard_announcements_more">
|
||||
<item quantity="one">%1$d more announcement</item>
|
||||
<item quantity="other">%1$d more announcements</item>
|
||||
</plurals>
|
||||
<string name="dashboard_exams_title">Exams</string>
|
||||
<string name="dashboard_exams_no_exams">No upcoming exams</string>
|
||||
<string name="dashboard_exams_error">An error occurred while loading the exams</string>
|
||||
<plurals name="dashboard_exams_more">
|
||||
<item quantity="one">%1$d more exam</item>
|
||||
<item quantity="other">%1$d more exams</item>
|
||||
</plurals>
|
||||
<string name="dashboard_conferences_title">Conferences</string>
|
||||
<string name="dashboard_conferences_no_conferences">No upcoming conferences</string>
|
||||
<string name="dashboard_conferences_error">An error occurred while loading the conferences</string>
|
||||
<plurals name="dashboard_conference_more">
|
||||
<item quantity="one">%1$d more conference</item>
|
||||
<item quantity="other">%1$d more conferences</item>
|
||||
</plurals>
|
||||
<string name="dashboard_horizontal_group_error">An error occurred while loading data</string>
|
||||
<string name="dashboard_horizontal_group_no_data">None</string>
|
||||
<!--Error dialog-->
|
||||
<string name="dialog_error_check_update">Check for updates</string>
|
||||
<string name="dialog_error_check_update_message">Before reporting a bug, check first if an update with the bug fix is available</string>
|
||||
<!--Generic-->
|
||||
<string name="all_content">Content</string>
|
||||
<string name="all_retry">Retry</string>
|
||||
<string name="all_description">Description</string>
|
||||
<string name="all_no_description">No description</string>
|
||||
<string name="all_teacher">Teacher</string>
|
||||
<string name="all_date">Date</string>
|
||||
<string name="all_entry_date">Entry date</string>
|
||||
<string name="all_color">Color</string>
|
||||
<string name="all_details">Details</string>
|
||||
<string name="all_category">Category</string>
|
||||
<string name="all_close">Close</string>
|
||||
<string name="all_no_data">No data</string>
|
||||
<string name="all_subject">Subject</string>
|
||||
<string name="all_prev">Prev</string>
|
||||
<string name="all_next">Next</string>
|
||||
<string name="all_search">Search</string>
|
||||
<string name="all_search_hint">Search…</string>
|
||||
<string name="all_yes">Yes</string>
|
||||
<string name="all_no">No</string>
|
||||
<string name="all_save">Save</string>
|
||||
<string name="all_title">Title</string>
|
||||
<string name="all_add">Add</string>
|
||||
<string name="all_copied">Copied</string>
|
||||
<string name="all_undo">Undo</string>
|
||||
<string name="all_change">Change</string>
|
||||
<string name="all_add_to_calendar">Add to calendar</string>
|
||||
<string name="all_cancel">Cancel</string>
|
||||
<!--Timetable Widget-->
|
||||
<string name="widget_timetable_no_items">No lessons</string>
|
||||
<string name="widget_timetable_last_synchronization">Synchronized on %1$s at %2$s</string>
|
||||
<string name="widget_timetable_theme_title">Choose theme</string>
|
||||
<string name="widget_timetable_theme_light">Light</string>
|
||||
<string name="widget_timetable_theme_dark">Dark</string>
|
||||
<string name="widget_timetable_theme_system">System Theme</string>
|
||||
<!--Preferences-->
|
||||
<string name="pref_view_header">App</string>
|
||||
<string name="pref_view_list">Default view</string>
|
||||
<string name="pref_view_grade_average_mode">Calculated average options</string>
|
||||
<string name="pref_view_grade_average_force_calc">Force average calculation by app</string>
|
||||
<string name="pref_view_present">Show presence</string>
|
||||
<string name="pref_view_app_theme">Theme</string>
|
||||
<string name="pref_view_expand_grade">Grades expanding</string>
|
||||
<string name="pref_view_timetable_show_groups">Show groups next to subjects</string>
|
||||
<string name="pref_view_timetable_show_gaps">Show empty tiles where there\'s no lesson</string>
|
||||
<string name="pref_view_grade_statistics_list">Show chart list in class grades</string>
|
||||
<string name="pref_view_subjects_without_grades">Show subjects without grades</string>
|
||||
<string name="pref_view_grade_color_scheme">Grades color scheme</string>
|
||||
<string name="pref_view_grade_sorting_mode">Subjects sorting</string>
|
||||
<string name="pref_view_app_language">Language</string>
|
||||
<string name="pref_view_menu_order_title">Menu configuration</string>
|
||||
<string name="pref_view_menu_order_summary">Set the order of functions in the menu</string>
|
||||
<string name="pref_notify_header">Notifications</string>
|
||||
<string name="pref_notify_header_other">Other</string>
|
||||
<string name="pref_notify_switch">Show notifications</string>
|
||||
<string name="pref_notify_upcoming_lessons_switch">Show upcoming lesson notifications</string>
|
||||
<string name="pref_notify_upcoming_lessons_persistent_switch">Make upcoming lesson notification persistent</string>
|
||||
<string name="pref_notify_upcoming_lessons_persistent_summary">Turn off when notification is not showing in your watch/band</string>
|
||||
<string name="pref_notify_open_system_settings">Open system notification settings</string>
|
||||
<string name="pref_notify_fix_sync_issues">Fix synchronization & notifications issues</string>
|
||||
<string name="pref_notify_fix_sync_issues_message">Your device may have data synchronization issues and with notifications.\n\nTo fix them, you need to add Wulkanowy to the autostart and turn off battery optimization/saving in the phone settings.</string>
|
||||
<string name="pref_notify_debug_switch">Show debug notifications</string>
|
||||
<string name="pref_notify_disabled_summary">Synchronization is disabled</string>
|
||||
<string name="pref_notify_notifications_piggyback_header">Official app notifications</string>
|
||||
<string name="pref_notify_notifications_piggyback">Capture official app notifications</string>
|
||||
<string name="pref_notify_notifications_piggyback_cancel_original">Remove official app notifications after capture</string>
|
||||
<string name="pref_notification_piggyback_popup_title">Capture notifications</string>
|
||||
<string name="pref_notification_piggyback_popup_description">With this feature you can gain a substitute of push notifications like in the official app. All you need to do is allow Wulkanowy to receive all notifications in your system settings.\n\nHow it works?\nWhen you get a notification in Dziennik VULCAN, Wulkanowy will be notified (that\'s what these extra permissions are for) and will trigger a sync so that can send its own notification.\n\nFOR ADVANCED USERS ONLY</string>
|
||||
<string name="pref_notification_exact_alarm_popup_title">Upcoming lesson notifications</string>
|
||||
<string name="pref_notification_exact_alarm_popup_descriptions">You must allow the Wulkanowy app to set alarms and reminders in your system settings to use this feature.</string>
|
||||
<string name="pref_notification_go_to_settings">Go to settings</string>
|
||||
<string name="pref_services_header">Synchronization</string>
|
||||
<string name="pref_services_switch">Automatic update</string>
|
||||
<string name="pref_services_suspended">Suspended on holidays</string>
|
||||
<string name="pref_services_interval">Updates interval</string>
|
||||
<string name="pref_services_wifi">Wi-Fi only</string>
|
||||
<string name="pref_services_force_sync">Sync now</string>
|
||||
<string name="pref_services_message_sync_success">Synced!</string>
|
||||
<string name="pref_services_message_sync_failed">Sync failed</string>
|
||||
<string name="pref_services_sync_in_progress">Sync in progress</string>
|
||||
<string name="pref_services_last_full_sync_date">Last full sync: %s</string>
|
||||
<string name="pref_other_grade_modifier_plus">Value of the plus</string>
|
||||
<string name="pref_other_grade_modifier_minus">Value of the minus</string>
|
||||
<string name="pref_other_fill_message_content">Reply with message history</string>
|
||||
<string name="pref_other_optional_arithmetic_average">Show arithmetic average when no weights provided</string>
|
||||
<string name="pref_other_incognito_mode">Incognito mode</string>
|
||||
<string name="pref_other_incognito_mode_summary">Do not inform about reading the message</string>
|
||||
<string name="pref_ads_support_category_name">Support</string>
|
||||
<string name="pref_ads_privacy_policy">Privacy Policy</string>
|
||||
<string name="pref_ads_agreements">Agreements</string>
|
||||
<string name="pref_ads_consent">Show consent to data processing</string>
|
||||
<string name="pref_ads_show_in_app">Show ads in app</string>
|
||||
<string name="pref_ads_support">Watch single ad to support project</string>
|
||||
<string name="pref_ads_privacy_title">Consent to data processing</string>
|
||||
<string name="pref_ads_privacy_description">To view an advertisement you must agree to the data processing terms of our Privacy Policy</string>
|
||||
<string name="pref_ads_privacy_agree">Agree</string>
|
||||
<string name="pref_ads_privacy_link">Privacy policy</string>
|
||||
<string name="pref_ads_loading">Ad is loading</string>
|
||||
<string name="pref_ads_once_per_visit">Thank you for your support, come back later for more ads</string>
|
||||
<string name="pref_settings_advanced_title">Advanced</string>
|
||||
<string name="pref_settings_appearance_title">Appearance & Behavior</string>
|
||||
<string name="pref_settings_notifications_title">Notifications</string>
|
||||
<string name="pref_settings_sync_title">Synchronization</string>
|
||||
<string name="pref_settings_ads_title">Advertisements</string>
|
||||
<string name="pref_grades_appearance_header">Grades</string>
|
||||
<string name="pref_dashboard_appearance_header">Dashboard</string>
|
||||
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</string>
|
||||
<string name="pref_attendance_appearance_view">Attendance</string>
|
||||
<string name="pref_timetable_appearance_view">Timetable</string>
|
||||
<string name="pref_grades_advanced_header">Grades</string>
|
||||
<string name="pref_counted_average_advanced_header">Calculated average</string>
|
||||
<string name="pref_messages_advanced_header">Messages</string>
|
||||
<string name="pref_appearance_category">Appearance & Behavior</string>
|
||||
<string name="pref_appearance_category_summary">Languages, themes, subjects sorting</string>
|
||||
<string name="pref_notifications_category_summary">App notifications, fix problems</string>
|
||||
<string name="pref_notifications_category">Notifications</string>
|
||||
<string name="pref_sync_category">Synchronization</string>
|
||||
<string name="pref_sync_category_summary">Automatic update, synchronization interval</string>
|
||||
<string name="pref_advanced_category_summary">Plus and minus values, average calculation</string>
|
||||
<string name="pref_advanced_category">Advanced</string>
|
||||
<string name="pref_about_category_summary">App version, contributors, social portals</string>
|
||||
<string name="pref_ads_category_summary">Displaying advertisements, project support</string>
|
||||
<!--Notification Channels-->
|
||||
<string name="channel_new_grades">New grades</string>
|
||||
<string name="channel_new_homework">New homework</string>
|
||||
<string name="channel_new_conference">New conferences</string>
|
||||
<string name="channel_new_exam">New exams</string>
|
||||
<string name="channel_lucky_number">Lucky number</string>
|
||||
<string name="channel_new_message">New messages</string>
|
||||
<string name="channel_new_notes">New notes</string>
|
||||
<string name="channel_new_school_announcement">New school announcements</string>
|
||||
<string name="channel_push">Push notifications</string>
|
||||
<string name="channel_upcoming_lessons">Upcoming lessons</string>
|
||||
<string name="channel_debug">Debug</string>
|
||||
<string name="channel_change_timetable">Timetable change</string>
|
||||
<string name="channel_new_attendance">New attendance</string>
|
||||
<!--Colors-->
|
||||
<string name="all_black">Black</string>
|
||||
<string name="all_red">Red</string>
|
||||
<string name="all_blue">Blue</string>
|
||||
<string name="all_green">Green</string>
|
||||
<string name="all_purple">Purple</string>
|
||||
<string name="all_empty_color">No color</string>
|
||||
<!--Update helper-->
|
||||
<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_button">Restart</string>
|
||||
<string name="update_failed">Update failed! Wulkanowy may not function properly. Consider updating</string>
|
||||
<!--Menu order-->
|
||||
<string name="menu_order_confirm_title">Application restart</string>
|
||||
<string name="menu_order_confirm_content">The application must restart for the changes to be saved</string>
|
||||
<string name="menu_order_confirm_restart">Restart</string>
|
||||
<!--Auth-->
|
||||
<string name="auth_api_error">Authorization has been rejected. The data provided does not match the records in the secretary\'s office.</string>
|
||||
<string name="auth_invalid_error">Invalid PESEL</string>
|
||||
<string name="auth_pesel">PESEL</string>
|
||||
<string name="auth_button">Authorize</string>
|
||||
<string name="auth_success">Authorization completed successfully</string>
|
||||
<string name="auth_title">Authorization</string>
|
||||
<string name="auth_description">To operate the application, we need to confirm your identity. Please enter the student\'s PESEL <b>%1$s</b> in the field below</string>
|
||||
<string name="auth_button_skip">Skip for now</string>
|
||||
<!--Errors-->
|
||||
<string name="error_no_internet">No internet connection</string>
|
||||
<string name="error_invalid_device_datetime">An error occurred. Check your device clock</string>
|
||||
<string name="error_timeout">Connection to register failed. Servers can be overloaded. Please try again later</string>
|
||||
<string name="error_login_failed">Loading data failed. Please try again later</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_unknown_uonet">Unknown UONET + register error. Try again later</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_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_field_required">This field is required</string>
|
||||
</resources>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user