Merge branch 'release/1.9.0'
2
LICENSE
@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2022 Wulkanowy
|
||||
Copyright 2023 Wulkanowy
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -16,15 +16,15 @@ apply from: 'hooks.gradle'
|
||||
|
||||
android {
|
||||
namespace 'io.github.wulkanowy'
|
||||
compileSdkVersion 32
|
||||
compileSdkVersion 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "io.github.wulkanowy"
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 32
|
||||
versionCode 118
|
||||
versionName "1.8.3"
|
||||
targetSdkVersion 33
|
||||
versionCode 119
|
||||
versionName "1.9.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
resValue "string", "app_name", "Wulkanowy"
|
||||
@ -162,7 +162,7 @@ play {
|
||||
track = 'production'
|
||||
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
||||
userFraction = 0.10d
|
||||
updatePriority = 5
|
||||
updatePriority = 1
|
||||
enabled.set(false)
|
||||
}
|
||||
|
||||
@ -181,23 +181,23 @@ ext {
|
||||
android_hilt = "1.0.0"
|
||||
room = "2.4.3"
|
||||
chucker = "3.5.2"
|
||||
mockk = "1.13.2"
|
||||
mockk = "1.13.3"
|
||||
coroutines = "1.6.4"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "io.github.wulkanowy:sdk:1.8.3"
|
||||
implementation "io.github.wulkanowy:sdk:1.9.0"
|
||||
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
|
||||
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
||||
|
||||
implementation "androidx.core:core-ktx:1.8.0"
|
||||
implementation "androidx.core:core-ktx:1.9.0"
|
||||
implementation 'androidx.core:core-splashscreen:1.0.0'
|
||||
implementation "androidx.activity:activity-ktx:1.5.1"
|
||||
implementation "androidx.activity:activity-ktx:1.6.1"
|
||||
implementation "androidx.appcompat:appcompat:1.5.1"
|
||||
implementation "androidx.fragment:fragment-ktx:1.5.4"
|
||||
implementation "androidx.fragment:fragment-ktx:1.5.5"
|
||||
implementation "androidx.annotation:annotation:1.5.0"
|
||||
|
||||
implementation "androidx.preference:preference-ktx:1.2.0"
|
||||
@ -237,20 +237,21 @@ dependencies {
|
||||
implementation 'com.github.bastienpaulfr:Treessence:1.0.5'
|
||||
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
||||
implementation "io.coil-kt:coil:2.2.2"
|
||||
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
|
||||
implementation "io.github.wulkanowy:AppKillerManager:3.0.1"
|
||||
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||
implementation 'com.fredporciuncula:flow-preferences:1.8.0'
|
||||
implementation 'org.apache.commons:commons-text:1.10.0'
|
||||
|
||||
playImplementation platform('com.google.firebase:firebase-bom:31.0.3')
|
||||
playImplementation platform('com.google.firebase:firebase-bom:31.1.1')
|
||||
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
||||
playImplementation 'com.google.firebase:firebase-messaging:'
|
||||
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
||||
playImplementation 'com.google.android.play:core:1.10.3'
|
||||
playImplementation 'com.google.android.play:core-ktx:1.8.1'
|
||||
playImplementation 'com.google.android.gms:play-services-ads:21.3.0'
|
||||
playImplementation 'com.google.android.gms:play-services-ads:21.4.0'
|
||||
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.8.0.300'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.7.3.300'
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.9.0.301'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.7.3.302'
|
||||
|
||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||
|
||||
@ -263,7 +264,7 @@ dependencies {
|
||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
|
||||
testImplementation 'org.robolectric:robolectric:4.9'
|
||||
testImplementation 'org.robolectric:robolectric:4.9.1'
|
||||
testImplementation "androidx.test:runner:1.5.1"
|
||||
testImplementation "androidx.test.ext:junit:1.1.4"
|
||||
testImplementation "androidx.test:core:1.5.0"
|
||||
@ -271,9 +272,9 @@ dependencies {
|
||||
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
||||
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||
|
||||
androidTestImplementation "androidx.test:core:1.4.0"
|
||||
androidTestImplementation "androidx.test:runner:1.4.0"
|
||||
androidTestImplementation "androidx.test.ext:junit:1.1.3"
|
||||
androidTestImplementation "androidx.test:core:1.5.0"
|
||||
androidTestImplementation "androidx.test:runner:1.5.1"
|
||||
androidTestImplementation "androidx.test.ext:junit:1.1.4"
|
||||
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
}
|
||||
|
@ -2,4 +2,5 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/colorPrimary" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
|
||||
</adaptive-icon>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground_dev_mono" />
|
||||
</adaptive-icon>
|
||||
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/colorPrimary" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 13 KiB |
@ -8,7 +8,8 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
@ -36,13 +37,14 @@
|
||||
<application
|
||||
android:name=".WulkanowyApp"
|
||||
android:allowBackup="false"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="false"
|
||||
android:theme="@style/WulkanowyTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||
tools:ignore="DataExtractionRules,UnusedAttribute">
|
||||
<activity
|
||||
android:name=".ui.modules.splash.SplashActivity"
|
||||
android:exported="true"
|
||||
|
@ -0,0 +1,87 @@
|
||||
package io.github.wulkanowy.data.mappers
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.pojos.*
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.mapper.mapSemesters
|
||||
import java.time.Instant
|
||||
import io.github.wulkanowy.sdk.scrapper.register.RegisterStudent as SdkRegisterStudent
|
||||
import io.github.wulkanowy.sdk.scrapper.register.RegisterUser as SdkRegisterUser
|
||||
|
||||
fun SdkRegisterUser.mapToPojo(password: String) = RegisterUser(
|
||||
email = email,
|
||||
login = login,
|
||||
password = password,
|
||||
baseUrl = baseUrl,
|
||||
loginType = loginType,
|
||||
symbols = symbols.map { registerSymbol ->
|
||||
RegisterSymbol(
|
||||
symbol = registerSymbol.symbol,
|
||||
error = registerSymbol.error,
|
||||
userName = registerSymbol.userName,
|
||||
schools = registerSymbol.schools.map {
|
||||
RegisterUnit(
|
||||
userLoginId = it.userLoginId,
|
||||
schoolId = it.schoolId,
|
||||
schoolName = it.schoolName,
|
||||
schoolShortName = it.schoolShortName,
|
||||
parentIds = it.parentIds,
|
||||
studentIds = it.studentIds,
|
||||
employeeIds = it.employeeIds,
|
||||
error = it.error,
|
||||
students = it.subjects
|
||||
.filterIsInstance<SdkRegisterStudent>()
|
||||
.map { registerSubject ->
|
||||
RegisterStudent(
|
||||
studentId = registerSubject.studentId,
|
||||
studentName = registerSubject.studentName,
|
||||
studentSecondName = registerSubject.studentSecondName,
|
||||
studentSurname = registerSubject.studentSurname,
|
||||
className = registerSubject.className,
|
||||
classId = registerSubject.classId,
|
||||
isParent = registerSubject.isParent,
|
||||
semesters = registerSubject.semesters
|
||||
.mapSemesters()
|
||||
.mapToEntities(registerSubject.studentId),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
fun RegisterStudent.mapToStudentWithSemesters(
|
||||
user: RegisterUser,
|
||||
symbol: RegisterSymbol,
|
||||
unit: RegisterUnit,
|
||||
colors: List<Long>,
|
||||
): StudentWithSemesters = StudentWithSemesters(
|
||||
semesters = semesters,
|
||||
student = Student(
|
||||
email = user.login, // for compatibility
|
||||
userName = symbol.userName,
|
||||
userLoginId = unit.userLoginId,
|
||||
isParent = isParent,
|
||||
className = className,
|
||||
classId = classId,
|
||||
studentId = studentId,
|
||||
symbol = symbol.symbol,
|
||||
loginType = user.loginType.name,
|
||||
schoolName = unit.schoolName,
|
||||
schoolShortName = unit.schoolShortName,
|
||||
schoolSymbol = unit.schoolId,
|
||||
studentName = "$studentName $studentSurname",
|
||||
loginMode = Sdk.Mode.SCRAPPER.name,
|
||||
scrapperBaseUrl = user.baseUrl,
|
||||
mobileBaseUrl = "",
|
||||
certificateKey = "",
|
||||
privateKey = "",
|
||||
password = user.password,
|
||||
isCurrent = false,
|
||||
registrationDate = Instant.now(),
|
||||
).apply {
|
||||
avatarColor = colors.random()
|
||||
},
|
||||
)
|
@ -0,0 +1,43 @@
|
||||
package io.github.wulkanowy.data.pojos
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.sdk.scrapper.Scrapper
|
||||
|
||||
data class RegisterUser(
|
||||
val email: String,
|
||||
val password: String,
|
||||
val login: String, // may be the same as email
|
||||
val baseUrl: String,
|
||||
val loginType: Scrapper.LoginType,
|
||||
val symbols: List<RegisterSymbol>,
|
||||
) : java.io.Serializable
|
||||
|
||||
data class RegisterSymbol(
|
||||
val symbol: String,
|
||||
val error: Throwable?,
|
||||
val userName: String,
|
||||
val schools: List<RegisterUnit>,
|
||||
) : java.io.Serializable
|
||||
|
||||
data class RegisterUnit(
|
||||
val userLoginId: Int,
|
||||
val schoolId: String,
|
||||
val schoolName: String,
|
||||
val schoolShortName: String,
|
||||
val parentIds: List<Int>,
|
||||
val studentIds: List<Int>,
|
||||
val employeeIds: List<Int>,
|
||||
val error: Throwable?,
|
||||
val students: List<RegisterStudent>,
|
||||
) : java.io.Serializable
|
||||
|
||||
data class RegisterStudent(
|
||||
val studentId: Int,
|
||||
val studentName: String,
|
||||
val studentSecondName: String,
|
||||
val studentSurname: String,
|
||||
val className: String,
|
||||
val classId: Int,
|
||||
val isParent: Boolean,
|
||||
val semesters: List<Semester>,
|
||||
) : java.io.Serializable
|
@ -178,7 +178,7 @@ class MessageRepository @Inject constructor(
|
||||
).first()
|
||||
}
|
||||
|
||||
suspend fun deleteMessage(student: Student, mailbox: Mailbox, message: Message) {
|
||||
suspend fun deleteMessage(student: Student, mailbox: Mailbox?, message: Message) {
|
||||
deleteMessages(student, mailbox, listOf(message))
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,8 @@ import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.data.mappers.mapToPojo
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.DispatchersProvider
|
||||
@ -52,6 +54,14 @@ class StudentRepository @Inject constructor(
|
||||
sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol)
|
||||
.mapToEntities(password, appInfo.defaultColorsForAvatar)
|
||||
|
||||
suspend fun getUserSubjectsFromScrapper(
|
||||
email: String,
|
||||
password: String,
|
||||
scrapperBaseUrl: String,
|
||||
symbol: String
|
||||
): RegisterUser = sdk.getUserSubjectsFromScrapper(email, password, scrapperBaseUrl, symbol)
|
||||
.mapToPojo(password)
|
||||
|
||||
suspend fun getStudentsHybrid(
|
||||
email: String,
|
||||
password: String,
|
||||
|
@ -37,7 +37,7 @@ class ErrorDialog : DialogFragment() {
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val error = requireArguments().getSerializable(ARGUMENT_KEY) as Throwable
|
||||
val error = requireArguments().serializable<Throwable>(ARGUMENT_KEY)
|
||||
|
||||
val binding = DialogErrorBinding.inflate(layoutInflater)
|
||||
binding.bindErrorDetails(error)
|
||||
|
@ -1,6 +1,9 @@
|
||||
package io.github.wulkanowy.ui.base
|
||||
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PackageManager.GET_ACTIVITIES
|
||||
import android.os.Build
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
@ -41,9 +44,8 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer
|
||||
)
|
||||
}
|
||||
|
||||
private fun isThemeApplicable(activity: AppCompatActivity) =
|
||||
activity.packageManager
|
||||
.getPackageInfo(activity.packageName, GET_ACTIVITIES)
|
||||
private fun isThemeApplicable(activity: AppCompatActivity): Boolean =
|
||||
getPackageInfo(activity)
|
||||
.activities
|
||||
.singleOrNull { it.name == activity::class.java.canonicalName }
|
||||
?.theme
|
||||
@ -52,4 +54,14 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer
|
||||
|| it == R.style.WulkanowyTheme_Login || it == R.style.WulkanowyTheme_Login_Black
|
||||
|| it == R.style.WulkanowyTheme_MessageSend || it == R.style.WulkanowyTheme_MessageSend_Black
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun getPackageInfo(activity: AppCompatActivity): PackageInfo {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
activity.packageManager.getPackageInfo(
|
||||
activity.packageName,
|
||||
PackageManager.PackageInfoFlags.of(GET_ACTIVITIES.toLong())
|
||||
)
|
||||
} else activity.packageManager.getPackageInfo(activity.packageName, GET_ACTIVITIES)
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ class AccountFragment : BaseFragment<FragmentAccountBinding>(R.layout.fragment_a
|
||||
|
||||
override val titleStringId = R.string.account_title
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -6,6 +6,7 @@ import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.get
|
||||
import androidx.core.view.isVisible
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
@ -21,6 +22,7 @@ import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoFragment
|
||||
import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoView
|
||||
import io.github.wulkanowy.utils.createNameInitialsDrawable
|
||||
import io.github.wulkanowy.utils.nickOrName
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -37,12 +39,12 @@ class AccountDetailsFragment :
|
||||
|
||||
private const val ARGUMENT_KEY = "Data"
|
||||
|
||||
fun newInstance(student: Student) =
|
||||
AccountDetailsFragment().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, student) }
|
||||
}
|
||||
fun newInstance(student: Student) = AccountDetailsFragment().apply {
|
||||
arguments = bundleOf(ARGUMENT_KEY to student)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
@ -51,7 +53,7 @@ class AccountDetailsFragment :
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentAccountDetailsBinding.bind(view)
|
||||
presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student)
|
||||
presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY))
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
|
@ -4,11 +4,13 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.databinding.DialogAccountEditBinding
|
||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -24,12 +26,9 @@ class AccountEditDialog : BaseDialogFragment<DialogAccountEditBinding>(), Accoun
|
||||
|
||||
private const val ARGUMENT_KEY = "student_with_semesters"
|
||||
|
||||
fun newInstance(student: Student) =
|
||||
AccountEditDialog().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable(ARGUMENT_KEY, student)
|
||||
}
|
||||
}
|
||||
fun newInstance(student: Student) = AccountEditDialog().apply {
|
||||
arguments = bundleOf(ARGUMENT_KEY to student)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@ -45,7 +44,7 @@ class AccountEditDialog : BaseDialogFragment<DialogAccountEditBinding>(), Accoun
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student)
|
||||
presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY))
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
|
@ -4,6 +4,7 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
@ -13,6 +14,7 @@ import io.github.wulkanowy.ui.modules.account.AccountAdapter
|
||||
import io.github.wulkanowy.ui.modules.account.AccountFragment
|
||||
import io.github.wulkanowy.ui.modules.account.AccountItem
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -30,9 +32,7 @@ class AccountQuickDialog : BaseDialogFragment<DialogAccountQuickBinding>(), Acco
|
||||
|
||||
fun newInstance(studentsWithSemesters: List<StudentWithSemesters>) =
|
||||
AccountQuickDialog().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable(STUDENTS_ARGUMENT_KEY, studentsWithSemesters.toTypedArray())
|
||||
}
|
||||
arguments = bundleOf(STUDENTS_ARGUMENT_KEY to studentsWithSemesters.toTypedArray())
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,8 +49,8 @@ class AccountQuickDialog : BaseDialogFragment<DialogAccountQuickBinding>(), Acco
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val studentsWithSemesters =
|
||||
(requireArguments()[STUDENTS_ARGUMENT_KEY] as Array<StudentWithSemesters>).toList()
|
||||
val studentsWithSemesters = requireArguments()
|
||||
.serializable<Array<StudentWithSemesters>>(STUDENTS_ARGUMENT_KEY).toList()
|
||||
|
||||
presenter.onAttachView(this, studentsWithSemesters)
|
||||
}
|
||||
|
@ -4,11 +4,13 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.databinding.DialogAttendanceBinding
|
||||
import io.github.wulkanowy.utils.descriptionRes
|
||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
|
||||
class AttendanceDialog : DialogFragment() {
|
||||
@ -22,16 +24,14 @@ class AttendanceDialog : DialogFragment() {
|
||||
private const val ARGUMENT_KEY = "Item"
|
||||
|
||||
fun newInstance(exam: Attendance) = AttendanceDialog().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
||||
arguments = bundleOf(ARGUMENT_KEY to exam)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
arguments?.run {
|
||||
attendance = getSerializable(ARGUMENT_KEY) as Attendance
|
||||
}
|
||||
attendance = requireArguments().serializable(ARGUMENT_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -84,6 +84,7 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -4,11 +4,13 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import io.github.wulkanowy.databinding.DialogConferenceBinding
|
||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
|
||||
class ConferenceDialog : DialogFragment() {
|
||||
@ -22,16 +24,14 @@ class ConferenceDialog : DialogFragment() {
|
||||
private const val ARGUMENT_KEY = "item"
|
||||
|
||||
fun newInstance(conference: Conference) = ConferenceDialog().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, conference) }
|
||||
arguments = bundleOf(ARGUMENT_KEY to conference)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
arguments?.let {
|
||||
conference = it.getSerializable(ARGUMENT_KEY) as Conference
|
||||
}
|
||||
conference = requireArguments().serializable(ARGUMENT_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
@ -57,4 +57,4 @@ class ConferenceDialog : DialogFragment() {
|
||||
conferenceDialogAgendaTitle.isVisible = conference.agenda.isNotBlank()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragme
|
||||
fun newInstance() = DashboardFragment()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -1,9 +1,7 @@
|
||||
package io.github.wulkanowy.ui.modules.debug.logviewer
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.Intent.EXTRA_EMAIL
|
||||
import android.content.Intent.EXTRA_STREAM
|
||||
import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
import android.content.Intent.*
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
@ -36,6 +34,7 @@ class LogViewerFragment : BaseFragment<FragmentLogviewerBinding>(R.layout.fragme
|
||||
fun newInstance() = LogViewerFragment()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -4,12 +4,14 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.databinding.DialogExamBinding
|
||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||
import io.github.wulkanowy.utils.openCalendarEventAdd
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import java.time.LocalTime
|
||||
|
||||
@ -24,16 +26,14 @@ class ExamDialog : DialogFragment() {
|
||||
private const val ARGUMENT_KEY = "Item"
|
||||
|
||||
fun newInstance(exam: Exam) = ExamDialog().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
||||
arguments = bundleOf(ARGUMENT_KEY to exam)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
arguments?.run {
|
||||
exam = getSerializable(ARGUMENT_KEY) as Exam
|
||||
}
|
||||
exam = requireArguments().serializable(ARGUMENT_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -51,6 +51,7 @@ class GradeFragment : BaseFragment<FragmentGradeBinding>(R.layout.fragment_grade
|
||||
|
||||
override val currentPageIndex get() = binding.gradeViewPager.currentItem
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -5,6 +5,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
@ -27,22 +28,19 @@ class GradeDetailsDialog : DialogFragment() {
|
||||
|
||||
private const val COLOR_THEME_KEY = "Theme"
|
||||
|
||||
fun newInstance(grade: Grade, colorTheme: GradeColorTheme) =
|
||||
GradeDetailsDialog().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable(ARGUMENT_KEY, grade)
|
||||
putSerializable(COLOR_THEME_KEY, colorTheme)
|
||||
}
|
||||
}
|
||||
fun newInstance(grade: Grade, colorTheme: GradeColorTheme) = GradeDetailsDialog().apply {
|
||||
arguments = bundleOf(
|
||||
ARGUMENT_KEY to grade,
|
||||
COLOR_THEME_KEY to colorTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
arguments?.run {
|
||||
grade = getSerializable(ARGUMENT_KEY) as Grade
|
||||
gradeColorTheme = getSerializable(COLOR_THEME_KEY) as GradeColorTheme
|
||||
}
|
||||
grade = requireArguments().serializable(ARGUMENT_KEY)
|
||||
gradeColorTheme = requireArguments().serializable(COLOR_THEME_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -5,9 +5,7 @@ import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.INVISIBLE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.View.*
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
@ -42,6 +40,7 @@ class GradeDetailsFragment :
|
||||
override val isViewEmpty
|
||||
get() = gradeDetailsAdapter.itemCount == 0
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -15,6 +15,7 @@ import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeView
|
||||
import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import io.github.wulkanowy.utils.setOnItemSelectedListener
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -48,8 +49,8 @@ class GradeStatisticsFragment :
|
||||
messageContainer = binding.gradeStatisticsRecycler
|
||||
presenter.onAttachView(
|
||||
view = this,
|
||||
type = savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? GradeStatisticsItem.DataType,
|
||||
subjectName = savedInstanceState?.getSerializable(SAVED_SUBJECT_NAME) as? String,
|
||||
type = savedInstanceState?.serializable(SAVED_CHART_TYPE),
|
||||
subjectName = savedInstanceState?.serializable(SAVED_SUBJECT_NAME),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
@ -14,6 +15,7 @@ import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.databinding.DialogHomeworkBinding
|
||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -35,16 +37,14 @@ class HomeworkDetailsDialog : BaseDialogFragment<DialogHomeworkBinding>(), Homew
|
||||
private const val ARGUMENT_KEY = "Item"
|
||||
|
||||
fun newInstance(homework: Homework) = HomeworkDetailsDialog().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, homework) }
|
||||
arguments = bundleOf(ARGUMENT_KEY to homework)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
arguments?.run {
|
||||
homework = getSerializable(ARGUMENT_KEY) as Homework
|
||||
}
|
||||
homework = requireArguments().serializable(ARGUMENT_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -2,13 +2,17 @@ package io.github.wulkanowy.ui.modules.login
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build.VERSION_CODES.TIRAMISU
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE
|
||||
import androidx.fragment.app.commit
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.databinding.ActivityLoginBinding
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment
|
||||
@ -16,6 +20,9 @@ import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment
|
||||
import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment
|
||||
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
|
||||
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.notifications.NotificationsFragment
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.UpdateHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -28,6 +35,9 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
||||
@Inject
|
||||
lateinit var updateHelper: UpdateHelper
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
companion object {
|
||||
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
|
||||
}
|
||||
@ -55,7 +65,7 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == android.R.id.home) onBackPressed()
|
||||
if (item.itemId == android.R.id.home) onBackPressedDispatcher.onBackPressed()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -67,8 +77,24 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
||||
openFragment(LoginSymbolFragment.newInstance(loginData))
|
||||
}
|
||||
|
||||
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
|
||||
openFragment(LoginStudentSelectFragment.newInstance(studentsWithSemesters))
|
||||
fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
|
||||
openFragment(LoginStudentSelectFragment.newInstance(loginData, registerUser))
|
||||
}
|
||||
|
||||
fun navigateToNotifications() {
|
||||
val isNotificationsPermissionRequired = appInfo.systemVersion >= TIRAMISU
|
||||
val isPermissionGranted = ContextCompat.checkSelfPermission(
|
||||
this, "android.permission.POST_NOTIFICATIONS"
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
|
||||
if (isNotificationsPermissionRequired && !isPermissionGranted) {
|
||||
openFragment(NotificationsFragment.newInstance(), clearBackStack = true)
|
||||
} else navigateToFinish()
|
||||
}
|
||||
|
||||
fun navigateToFinish() {
|
||||
startActivity(MainActivity.getStartIntent(this))
|
||||
finish()
|
||||
}
|
||||
|
||||
fun onAdvancedLoginClick() {
|
||||
@ -80,6 +106,8 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
||||
}
|
||||
|
||||
private fun openFragment(fragment: Fragment, clearBackStack: Boolean = false) {
|
||||
supportFragmentManager.popBackStack(fragment::class.java.name, POP_BACK_STACK_INCLUSIVE)
|
||||
|
||||
supportFragmentManager.commit {
|
||||
replace(R.id.loginContainer, fragment)
|
||||
setReorderingAllowed(true)
|
||||
|
@ -6,4 +6,5 @@ data class LoginData(
|
||||
val login: String,
|
||||
val password: String,
|
||||
val baseUrl: String,
|
||||
val symbol: String?,
|
||||
) : Serializable
|
||||
|
@ -8,7 +8,7 @@ import android.widget.ArrayAdapter
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.databinding.FragmentLoginAdvancedBinding
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
@ -327,8 +327,8 @@ class LoginAdvancedFragment :
|
||||
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
|
||||
}
|
||||
|
||||
override fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
|
||||
(activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
|
||||
override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
|
||||
(activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -4,9 +4,15 @@ import io.github.wulkanowy.data.Resource
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.logResourceStatus
|
||||
import io.github.wulkanowy.data.onResourceNotLoading
|
||||
import io.github.wulkanowy.data.pojos.RegisterStudent
|
||||
import io.github.wulkanowy.data.pojos.RegisterSymbol
|
||||
import io.github.wulkanowy.data.pojos.RegisterUnit
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.resourceFlow
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.scrapper.Scrapper
|
||||
import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
@ -142,19 +148,23 @@ class LoginAdvancedPresenter @Inject constructor(
|
||||
is Resource.Success -> {
|
||||
analytics.logEvent(
|
||||
"registration_form",
|
||||
"success" to true,
|
||||
"students" to it.data.size,
|
||||
"error" to "No error"
|
||||
)
|
||||
val loginData = LoginData(
|
||||
login = view?.formUsernameValue.orEmpty().trim(),
|
||||
password = view?.formPassValue.orEmpty().trim(),
|
||||
baseUrl = view?.formHostValue.orEmpty().trim()
|
||||
)
|
||||
when (it.data.size) {
|
||||
0 -> view?.navigateToSymbol(loginData)
|
||||
else -> view?.navigateToStudentSelect(it.data)
|
||||
}
|
||||
"success" to true,
|
||||
"students" to it.data.size,
|
||||
"error" to "No error"
|
||||
)
|
||||
val loginData = LoginData(
|
||||
login = view?.formUsernameValue.orEmpty().trim(),
|
||||
password = view?.formPassValue.orEmpty().trim(),
|
||||
baseUrl = view?.formHostValue.orEmpty().trim(),
|
||||
symbol = view?.formSymbolValue.orEmpty().trim().getNormalizedSymbol(),
|
||||
)
|
||||
when (it.data.size) {
|
||||
0 -> view?.navigateToSymbol(loginData)
|
||||
else -> view?.navigateToStudentSelect(
|
||||
loginData = loginData,
|
||||
registerUser = it.data.toRegisterUser(loginData),
|
||||
)
|
||||
}
|
||||
}
|
||||
is Resource.Error -> {
|
||||
analytics.logEvent(
|
||||
@ -173,6 +183,58 @@ class LoginAdvancedPresenter @Inject constructor(
|
||||
}.launch("login")
|
||||
}
|
||||
|
||||
private fun List<StudentWithSemesters>.toRegisterUser(loginData: LoginData) = RegisterUser(
|
||||
email = loginData.login,
|
||||
password = loginData.password,
|
||||
login = loginData.login,
|
||||
baseUrl = loginData.baseUrl,
|
||||
loginType = firstOrNull()?.student?.loginType?.let(
|
||||
Scrapper.LoginType::valueOf
|
||||
) ?: Scrapper.LoginType.AUTO,
|
||||
symbols = this
|
||||
.groupBy { students -> students.student.symbol }
|
||||
.map { (symbol, students) ->
|
||||
RegisterSymbol(
|
||||
symbol = symbol,
|
||||
error = null,
|
||||
userName = "",
|
||||
schools = students
|
||||
.groupBy { student ->
|
||||
Triple(
|
||||
first = student.student.schoolSymbol,
|
||||
second = student.student.userLoginId,
|
||||
third = student.student.schoolShortName
|
||||
)
|
||||
}
|
||||
.map { (groupKey, students) ->
|
||||
val (schoolId, loginId, schoolName) = groupKey
|
||||
RegisterUnit(
|
||||
students = students.map {
|
||||
RegisterStudent(
|
||||
studentId = it.student.studentId,
|
||||
studentName = it.student.studentName,
|
||||
studentSecondName = it.student.studentName,
|
||||
studentSurname = it.student.studentName,
|
||||
className = it.student.className,
|
||||
classId = it.student.classId,
|
||||
isParent = it.student.isParent,
|
||||
semesters = it.semesters,
|
||||
)
|
||||
},
|
||||
userLoginId = loginId,
|
||||
schoolId = schoolId,
|
||||
schoolName = schoolName,
|
||||
schoolShortName = schoolName,
|
||||
parentIds = listOf(),
|
||||
studentIds = listOf(),
|
||||
employeeIds = listOf(),
|
||||
error = null
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
private suspend fun getStudentsAppropriatesToLoginType(): List<StudentWithSemesters> {
|
||||
val email = view?.formUsernameValue.orEmpty()
|
||||
val password = view?.formPassValue.orEmpty()
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.github.wulkanowy.ui.modules.login.advanced
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
|
||||
@ -72,7 +73,7 @@ interface LoginAdvancedView : BaseView {
|
||||
|
||||
fun navigateToSymbol(loginData: LoginData)
|
||||
|
||||
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>)
|
||||
fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser)
|
||||
|
||||
fun setErrorPinRequired()
|
||||
|
||||
|
@ -9,7 +9,7 @@ import androidx.core.view.isVisible
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
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
|
||||
@ -226,8 +226,8 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
|
||||
}
|
||||
|
||||
override fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
|
||||
(activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
|
||||
override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
|
||||
(activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser)
|
||||
}
|
||||
|
||||
override fun openAdvancedLogin() {
|
||||
|
@ -93,7 +93,7 @@ class LoginFormPresenter @Inject constructor(
|
||||
if (!validateCredentials(email, password, host)) return
|
||||
|
||||
resourceFlow {
|
||||
studentRepository.getStudentsScrapper(
|
||||
studentRepository.getUserSubjectsFromScrapper(
|
||||
email = email,
|
||||
password = password,
|
||||
scrapperBaseUrl = host,
|
||||
@ -109,14 +109,14 @@ class LoginFormPresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
.onResourceSuccess {
|
||||
when (it.size) {
|
||||
0 -> view?.navigateToSymbol(LoginData(email, password, host))
|
||||
else -> view?.navigateToStudentSelect(it)
|
||||
val loginData = LoginData(email, password, host, symbol)
|
||||
when (it.symbols.size) {
|
||||
0 -> view?.navigateToSymbol(loginData)
|
||||
else -> view?.navigateToStudentSelect(loginData, it)
|
||||
}
|
||||
analytics.logEvent(
|
||||
"registration_form",
|
||||
"success" to true,
|
||||
"students" to it.size,
|
||||
"scrapperBaseUrl" to host,
|
||||
"error" to "No error"
|
||||
)
|
||||
@ -134,7 +134,6 @@ class LoginFormPresenter @Inject constructor(
|
||||
analytics.logEvent(
|
||||
"registration_form",
|
||||
"success" to false,
|
||||
"students" to -1,
|
||||
"scrapperBaseUrl" to host,
|
||||
"error" to it.message.ifNullOrBlank { "No message" }
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
package io.github.wulkanowy.ui.modules.login.form
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
|
||||
@ -60,7 +60,7 @@ interface LoginFormView : BaseView {
|
||||
|
||||
fun navigateToSymbol(loginData: LoginData)
|
||||
|
||||
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>)
|
||||
fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser)
|
||||
|
||||
fun openPrivacyPolicyPage()
|
||||
|
||||
|
@ -98,7 +98,7 @@ class LoginRecoverFragment :
|
||||
loginRecoverButton.setOnClickListener { presenter.onRecoverClick() }
|
||||
loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() }
|
||||
loginRecoverErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||
loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressed() }
|
||||
loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressedDispatcher.onBackPressed() }
|
||||
}
|
||||
|
||||
with(bindingLocal.loginRecoverHost) {
|
||||
|
@ -2,65 +2,182 @@ package io.github.wulkanowy.ui.modules.login.studentselect
|
||||
|
||||
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.DiffUtil.ItemCallback
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.databinding.ItemLoginStudentSelectBinding
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.databinding.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
class LoginStudentSelectAdapter @Inject constructor() :
|
||||
RecyclerView.Adapter<LoginStudentSelectAdapter.ItemViewHolder>() {
|
||||
ListAdapter<LoginStudentSelectItem, RecyclerView.ViewHolder>(Differ) {
|
||||
|
||||
private val checkedList = mutableMapOf<Int, Boolean>()
|
||||
override fun getItemViewType(position: Int): Int = getItem(position).type.ordinal
|
||||
|
||||
var items = emptyList<Pair<StudentWithSemesters, Boolean>>()
|
||||
set(value) {
|
||||
field = value
|
||||
checkedList.clear()
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return when (LoginStudentSelectItemType.values()[viewType]) {
|
||||
LoginStudentSelectItemType.EMPTY_SYMBOLS_HEADER -> EmptySymbolsHeaderViewHolder(
|
||||
ItemLoginStudentSelectEmptySymbolHeaderBinding.inflate(inflater, parent, false),
|
||||
)
|
||||
LoginStudentSelectItemType.SYMBOL_HEADER -> SymbolsHeaderViewHolder(
|
||||
ItemLoginStudentSelectHeaderSymbolBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
LoginStudentSelectItemType.SCHOOL_HEADER -> SchoolHeaderViewHolder(
|
||||
ItemLoginStudentSelectHeaderSchoolBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
LoginStudentSelectItemType.STUDENT -> StudentViewHolder(
|
||||
ItemLoginStudentSelectStudentBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
LoginStudentSelectItemType.HELP -> HelpViewHolder(
|
||||
ItemLoginStudentSelectHelpBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var onClickListener: (StudentWithSemesters, alreadySaved: Boolean) -> Unit = { _, _ -> }
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is EmptySymbolsHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.EmptySymbolsHeader)
|
||||
is SymbolsHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.SymbolHeader)
|
||||
is SchoolHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.SchoolHeader)
|
||||
is StudentViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.Student)
|
||||
is HelpViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.Help)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
private class EmptySymbolsHeaderViewHolder(
|
||||
private val binding: ItemLoginStudentSelectEmptySymbolHeaderBinding,
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
|
||||
ItemLoginStudentSelectBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
)
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
|
||||
val (studentAndSemesters, alreadySaved) = items[position]
|
||||
val student = studentAndSemesters.student
|
||||
val semesters = studentAndSemesters.semesters
|
||||
val diary = semesters.maxByOrNull { it.semesterId }
|
||||
|
||||
with(holder.binding) {
|
||||
loginItemName.text = "${student.studentName} ${diary?.diaryName.orEmpty()}"
|
||||
loginItemSchool.text = student.schoolName
|
||||
loginItemName.isEnabled = !alreadySaved
|
||||
loginItemSchool.isEnabled = !alreadySaved
|
||||
loginItemSignedIn.visibility = if (alreadySaved) View.VISIBLE else View.GONE
|
||||
|
||||
with(loginItemCheck) {
|
||||
isEnabled = !alreadySaved
|
||||
keyListener = null
|
||||
isChecked = checkedList[position] ?: false
|
||||
fun bind(item: LoginStudentSelectItem.EmptySymbolsHeader) {
|
||||
with(binding) {
|
||||
loginStudentSelectEmptySymbolChevron.rotation = if (item.isExpanded) 270f else 90f
|
||||
root.setOnClickListener { item.onClick() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root.setOnClickListener {
|
||||
onClickListener(studentAndSemesters, alreadySaved)
|
||||
private class SymbolsHeaderViewHolder(
|
||||
private val binding: ItemLoginStudentSelectHeaderSymbolBinding,
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: LoginStudentSelectItem.SymbolHeader) {
|
||||
with(binding) {
|
||||
loginStudentSelectHeaderSymbolValue.text = buildString {
|
||||
append(root.context.getString(R.string.mobile_device_symbol))
|
||||
append(": ")
|
||||
append(item.humanReadableName ?: item.symbol.symbol)
|
||||
if (!item.humanReadableName.isNullOrBlank()) {
|
||||
append(" (${item.symbol.symbol})")
|
||||
}
|
||||
}
|
||||
loginStudentSelectHeaderSymbolUsername.text = item.symbol.userName
|
||||
loginStudentSelectHeaderSymbolUsername.isVisible = item.symbol.userName.isNotBlank()
|
||||
loginStudentSelectHeaderSymbolError.text = item.symbol.error?.message
|
||||
loginStudentSelectHeaderSymbolError.isVisible = item.symbol.error != null
|
||||
loginStudentSelectHeaderSymbolError.maxLines = when {
|
||||
item.isErrorExpanded -> Int.MAX_VALUE
|
||||
else -> 2
|
||||
}
|
||||
|
||||
if (item.symbol.error != null) {
|
||||
root.setOnClickListener { item.onClick(item.symbol) }
|
||||
} else root.setOnClickListener(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SchoolHeaderViewHolder(
|
||||
private val binding: ItemLoginStudentSelectHeaderSchoolBinding,
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: LoginStudentSelectItem.SchoolHeader) {
|
||||
with(binding) {
|
||||
loginStudentSelectHeaderSchoolName.text = buildString {
|
||||
append(item.unit.schoolName.trim())
|
||||
append(" (")
|
||||
append(item.unit.schoolShortName)
|
||||
append(")")
|
||||
}
|
||||
loginStudentSelectHeaderSchoolDetails.isVisible = item.unit.students.isEmpty()
|
||||
loginStudentSelectHeaderSchoolError.text = item.unit.error?.message
|
||||
loginStudentSelectHeaderSchoolError.isVisible = item.unit.error != null
|
||||
loginStudentSelectHeaderSchoolError.maxLines = when {
|
||||
item.isErrorExpanded -> Int.MAX_VALUE
|
||||
else -> 2
|
||||
}
|
||||
|
||||
if (item.unit.error != null) {
|
||||
root.setOnClickListener { item.onClick(item.unit) }
|
||||
} else root.setOnClickListener(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class StudentViewHolder(
|
||||
private val binding: ItemLoginStudentSelectStudentBinding,
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: LoginStudentSelectItem.Student) {
|
||||
val student = item.student
|
||||
val semesters = student.semesters
|
||||
val diary = semesters.maxByOrNull { it.semesterId }
|
||||
|
||||
with(binding) {
|
||||
loginItemName.text = "${student.studentName} ${student.studentSurname}"
|
||||
loginItemName.isEnabled = item.isEnabled
|
||||
loginItemSignedIn.text = if (!item.isEnabled) {
|
||||
root.context.getString(R.string.login_signed_in)
|
||||
} else diary?.diaryName
|
||||
|
||||
with(loginItemCheck) {
|
||||
if (isEnabled) {
|
||||
isChecked = !isChecked
|
||||
checkedList[position] = isChecked
|
||||
}
|
||||
keyListener = null
|
||||
isEnabled = item.isEnabled
|
||||
isChecked = item.isSelected || !item.isEnabled
|
||||
}
|
||||
|
||||
root.isEnabled = item.isEnabled
|
||||
root.setOnClickListener {
|
||||
item.onClick(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ItemViewHolder(val binding: ItemLoginStudentSelectBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
private class HelpViewHolder(
|
||||
private val binding: ItemLoginStudentSelectHelpBinding,
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: LoginStudentSelectItem.Help) {
|
||||
with(binding) {
|
||||
loginStudentSelectHelpSymbol.isVisible = item.isSymbolButtonVisible
|
||||
loginStudentSelectHelpSymbol.setOnClickListener { item.onEnterSymbolClick() }
|
||||
loginStudentSelectHelpMail.setOnClickListener { item.onContactUsClick() }
|
||||
loginStudentSelectHelpDiscord.setOnClickListener { item.onDiscordClick() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object Differ : ItemCallback<LoginStudentSelectItem>() {
|
||||
|
||||
override fun areItemsTheSame(
|
||||
oldItem: LoginStudentSelectItem, newItem: LoginStudentSelectItem
|
||||
): Boolean = when {
|
||||
oldItem is LoginStudentSelectItem.EmptySymbolsHeader && newItem is LoginStudentSelectItem.EmptySymbolsHeader -> true
|
||||
oldItem is LoginStudentSelectItem.SymbolHeader && newItem is LoginStudentSelectItem.SymbolHeader -> {
|
||||
oldItem.symbol == newItem.symbol
|
||||
}
|
||||
oldItem is LoginStudentSelectItem.Student && newItem is LoginStudentSelectItem.Student -> {
|
||||
oldItem.student == newItem.student
|
||||
}
|
||||
else -> oldItem == newItem
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItem: LoginStudentSelectItem, newItem: LoginStudentSelectItem
|
||||
): Boolean = oldItem == newItem
|
||||
}
|
||||
}
|
||||
|
@ -2,21 +2,20 @@ package io.github.wulkanowy.ui.modules.login.studentselect
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.core.view.isVisible
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
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.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
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
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -36,12 +35,23 @@ class LoginStudentSelectFragment :
|
||||
@Inject
|
||||
lateinit var preferencesRepository: PreferencesRepository
|
||||
|
||||
companion object {
|
||||
const val ARG_STUDENTS = "STUDENTS"
|
||||
private lateinit var symbolsNames: Array<String>
|
||||
private lateinit var symbolsValues: Array<String>
|
||||
|
||||
fun newInstance(studentsWithSemesters: List<StudentWithSemesters>) =
|
||||
override val symbols: Map<String, String> by lazy {
|
||||
symbolsValues.zip(symbolsNames).toMap()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ARG_LOGIN = "LOGIN"
|
||||
private const val ARG_STUDENTS = "STUDENTS"
|
||||
|
||||
fun newInstance(loginData: LoginData, registerUser: RegisterUser) =
|
||||
LoginStudentSelectFragment().apply {
|
||||
arguments = bundleOf(ARG_STUDENTS to studentsWithSemesters)
|
||||
arguments = bundleOf(
|
||||
ARG_LOGIN to loginData,
|
||||
ARG_STUDENTS to registerUser,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,62 +59,50 @@ class LoginStudentSelectFragment :
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentLoginStudentSelectBinding.bind(view)
|
||||
|
||||
symbolsNames = resources.getStringArray(R.array.symbols)
|
||||
symbolsValues = resources.getStringArray(R.array.symbols_values)
|
||||
|
||||
presenter.onAttachView(
|
||||
view = this,
|
||||
students = requireArguments().getSerializable(ARG_STUDENTS) as List<StudentWithSemesters>,
|
||||
loginData = requireArguments().serializable(ARG_LOGIN),
|
||||
registerUser = requireArguments().serializable(ARG_STUDENTS),
|
||||
)
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
(requireActivity() as LoginActivity).showActionBar(true)
|
||||
|
||||
loginAdapter.onClickListener = presenter::onItemSelected
|
||||
|
||||
with(binding) {
|
||||
loginStudentSelectSignIn.setOnClickListener { presenter.onSignIn() }
|
||||
loginStudentSelectContactDiscord.setOnClickListener { presenter.onDiscordClick() }
|
||||
loginStudentSelectContactEmail.setOnClickListener { presenter.onEmailClick() }
|
||||
|
||||
with(loginStudentSelectRecycler) {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = loginAdapter
|
||||
}
|
||||
loginStudentSelectRecycler.adapter = loginAdapter
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateData(data: List<Pair<StudentWithSemesters, Boolean>>) {
|
||||
with(loginAdapter) {
|
||||
items = data
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
override fun updateData(data: List<LoginStudentSelectItem>) {
|
||||
loginAdapter.submitList(data)
|
||||
}
|
||||
|
||||
override fun openMainView() {
|
||||
startActivity(MainActivity.getStartIntent(requireContext()))
|
||||
requireActivity().finish()
|
||||
override fun navigateToSymbol(loginData: LoginData) {
|
||||
(requireActivity() as LoginActivity).navigateToSymbolFragment(loginData)
|
||||
}
|
||||
|
||||
override fun navigateToNext() {
|
||||
(requireActivity() as LoginActivity).navigateToNotifications()
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
binding.loginStudentSelectProgress.visibility = if (show) VISIBLE else GONE
|
||||
binding.loginStudentSelectProgress.isVisible = show
|
||||
}
|
||||
|
||||
override fun showContent(show: Boolean) {
|
||||
binding.loginStudentSelectContent.visibility = if (show) VISIBLE else GONE
|
||||
binding.loginStudentSelectContent.isVisible = show
|
||||
}
|
||||
|
||||
override fun enableSignIn(enable: Boolean) {
|
||||
binding.loginStudentSelectSignIn.isEnabled = enable
|
||||
}
|
||||
|
||||
override fun showContact(show: Boolean) {
|
||||
binding.loginStudentSelectContact.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
presenter.onDetachView()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun openDiscordInvite() {
|
||||
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
|
||||
}
|
||||
@ -125,4 +123,9 @@ class LoginStudentSelectFragment :
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
presenter.onDetachView()
|
||||
super.onDestroyView()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
package io.github.wulkanowy.ui.modules.login.studentselect
|
||||
|
||||
import io.github.wulkanowy.data.pojos.RegisterStudent
|
||||
import io.github.wulkanowy.data.pojos.RegisterSymbol
|
||||
import io.github.wulkanowy.data.pojos.RegisterUnit
|
||||
|
||||
sealed class LoginStudentSelectItem(val type: LoginStudentSelectItemType) {
|
||||
|
||||
data class EmptySymbolsHeader(
|
||||
val isExpanded: Boolean,
|
||||
val onClick: () -> Unit,
|
||||
) : LoginStudentSelectItem(LoginStudentSelectItemType.EMPTY_SYMBOLS_HEADER)
|
||||
|
||||
data class SymbolHeader(
|
||||
val symbol: RegisterSymbol,
|
||||
val humanReadableName: String?,
|
||||
val isErrorExpanded: Boolean,
|
||||
val onClick: (RegisterSymbol) -> Unit,
|
||||
) : LoginStudentSelectItem(LoginStudentSelectItemType.SYMBOL_HEADER)
|
||||
|
||||
data class SchoolHeader(
|
||||
val unit: RegisterUnit,
|
||||
val isErrorExpanded: Boolean,
|
||||
val onClick: (RegisterUnit) -> Unit,
|
||||
) : LoginStudentSelectItem(LoginStudentSelectItemType.SCHOOL_HEADER)
|
||||
|
||||
data class Student(
|
||||
val symbol: RegisterSymbol,
|
||||
val unit: RegisterUnit,
|
||||
val student: RegisterStudent,
|
||||
val isEnabled: Boolean,
|
||||
val isSelected: Boolean,
|
||||
val onClick: (Student) -> Unit,
|
||||
) : LoginStudentSelectItem(LoginStudentSelectItemType.STUDENT)
|
||||
|
||||
data class Help(
|
||||
val onEnterSymbolClick: () -> Unit,
|
||||
val onContactUsClick: () -> Unit,
|
||||
val onDiscordClick: () -> Unit,
|
||||
val isSymbolButtonVisible: Boolean,
|
||||
) : LoginStudentSelectItem(LoginStudentSelectItemType.HELP)
|
||||
}
|
||||
|
||||
enum class LoginStudentSelectItemType {
|
||||
EMPTY_SYMBOLS_HEADER,
|
||||
SYMBOL_HEADER,
|
||||
SCHOOL_HEADER,
|
||||
STUDENT,
|
||||
HELP,
|
||||
}
|
@ -1,15 +1,23 @@
|
||||
package io.github.wulkanowy.ui.modules.login.studentselect
|
||||
|
||||
import io.github.wulkanowy.data.Resource
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.dataOrNull
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.logResourceStatus
|
||||
import io.github.wulkanowy.data.mappers.mapToStudentWithSemesters
|
||||
import io.github.wulkanowy.data.pojos.RegisterStudent
|
||||
import io.github.wulkanowy.data.pojos.RegisterSymbol
|
||||
import io.github.wulkanowy.data.pojos.RegisterUnit
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.resourceFlow
|
||||
import io.github.wulkanowy.sdk.scrapper.login.AccountPermissionException
|
||||
import io.github.wulkanowy.services.sync.SyncManager
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
@ -19,18 +27,30 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
studentRepository: StudentRepository,
|
||||
private val loginErrorHandler: LoginErrorHandler,
|
||||
private val syncManager: SyncManager,
|
||||
private val analytics: AnalyticsHelper
|
||||
private val analytics: AnalyticsHelper,
|
||||
private val appInfo: AppInfo,
|
||||
) : BasePresenter<LoginStudentSelectView>(loginErrorHandler, studentRepository) {
|
||||
|
||||
private var lastError: Throwable? = null
|
||||
|
||||
private val selectedStudents = mutableListOf<StudentWithSemesters>()
|
||||
private lateinit var registerUser: RegisterUser
|
||||
private lateinit var loginData: LoginData
|
||||
|
||||
fun onAttachView(view: LoginStudentSelectView, students: List<StudentWithSemesters>) {
|
||||
private lateinit var students: List<StudentWithSemesters>
|
||||
private var isEmptySymbolsExpanded = false
|
||||
private var expandedSymbolError: RegisterSymbol? = null
|
||||
private var expandedSchoolError: RegisterUnit? = null
|
||||
|
||||
private val selectedStudents = mutableListOf<LoginStudentSelectItem.Student>()
|
||||
|
||||
fun onAttachView(
|
||||
view: LoginStudentSelectView,
|
||||
loginData: LoginData,
|
||||
registerUser: RegisterUser,
|
||||
) {
|
||||
super.onAttachView(view)
|
||||
with(view) {
|
||||
initView()
|
||||
showContact(false)
|
||||
enableSignIn(false)
|
||||
loginErrorHandler.onStudentDuplicate = {
|
||||
showMessage(it)
|
||||
@ -38,50 +58,171 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
if (students.size == 1) registerStudents(students)
|
||||
loadData(students)
|
||||
this.loginData = loginData
|
||||
this.registerUser = registerUser
|
||||
loadData()
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
resetSelectedState()
|
||||
|
||||
resourceFlow { studentRepository.getSavedStudents(false) }.onEach {
|
||||
students = it.dataOrNull.orEmpty()
|
||||
when (it) {
|
||||
is Resource.Loading -> Timber.d("Login student select students load started")
|
||||
is Resource.Success -> refreshItems()
|
||||
is Resource.Error -> {
|
||||
errorHandler.dispatch(it.error)
|
||||
lastError = it.error
|
||||
refreshItems()
|
||||
}
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun createItems(): List<LoginStudentSelectItem> = buildList {
|
||||
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 }))
|
||||
}
|
||||
|
||||
addAll(createNotEmptySymbolItems(notEmptySymbols, students))
|
||||
addAll(createEmptySymbolItems(emptySymbols, notEmptySymbols.isNotEmpty()))
|
||||
|
||||
val helpItem = LoginStudentSelectItem.Help(
|
||||
onEnterSymbolClick = ::onEnterSymbol,
|
||||
onContactUsClick = ::onEmailClick,
|
||||
onDiscordClick = ::onDiscordClick,
|
||||
isSymbolButtonVisible = "login" !in loginData.baseUrl,
|
||||
)
|
||||
add(helpItem)
|
||||
}
|
||||
|
||||
private fun createNotEmptySymbolItems(
|
||||
notEmptySymbols: List<RegisterSymbol>,
|
||||
students: List<StudentWithSemesters>,
|
||||
) = buildList {
|
||||
notEmptySymbols.forEach { registerSymbol ->
|
||||
val symbolHeader = LoginStudentSelectItem.SymbolHeader(
|
||||
symbol = registerSymbol,
|
||||
humanReadableName = view?.symbols?.get(registerSymbol.symbol),
|
||||
isErrorExpanded = expandedSymbolError == registerSymbol,
|
||||
onClick = ::onSymbolItemClick,
|
||||
)
|
||||
add(symbolHeader)
|
||||
|
||||
registerSymbol.schools.forEach { registerUnit ->
|
||||
val schoolHeader = LoginStudentSelectItem.SchoolHeader(
|
||||
unit = registerUnit,
|
||||
isErrorExpanded = expandedSchoolError == registerUnit,
|
||||
onClick = ::onUnitItemClick,
|
||||
)
|
||||
add(schoolHeader)
|
||||
|
||||
registerUnit.students.forEach {
|
||||
add(createStudentItem(it, registerSymbol, registerUnit, students))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createStudentItem(
|
||||
student: RegisterStudent,
|
||||
symbol: RegisterSymbol,
|
||||
school: RegisterUnit,
|
||||
students: List<StudentWithSemesters>,
|
||||
) = LoginStudentSelectItem.Student(
|
||||
symbol = symbol,
|
||||
unit = school,
|
||||
student = student,
|
||||
onClick = ::onItemSelected,
|
||||
isEnabled = students.none {
|
||||
it.student.email == registerUser.login
|
||||
&& it.student.symbol == symbol.symbol
|
||||
&& it.student.studentId == student.studentId
|
||||
&& it.student.schoolSymbol == school.schoolId
|
||||
&& it.student.classId == student.classId
|
||||
},
|
||||
isSelected = selectedStudents
|
||||
.filter { it.symbol.symbol == symbol.symbol }
|
||||
.filter { it.unit.schoolId == school.schoolId }
|
||||
.filter { it.student.studentId == student.studentId }
|
||||
.filter { it.student.classId == student.classId }
|
||||
.size == 1,
|
||||
)
|
||||
|
||||
private fun createEmptySymbolItems(
|
||||
emptySymbols: List<RegisterSymbol>,
|
||||
isNotEmptySymbolsExist: Boolean,
|
||||
) = buildList {
|
||||
val filteredEmptySymbols = emptySymbols.filter {
|
||||
it.error !is AccountPermissionException
|
||||
}.ifEmpty { emptySymbols.takeIf { !isNotEmptySymbolsExist }.orEmpty() }
|
||||
|
||||
if (filteredEmptySymbols.isNotEmpty() && isNotEmptySymbolsExist) {
|
||||
val emptyHeader = LoginStudentSelectItem.EmptySymbolsHeader(
|
||||
isExpanded = isEmptySymbolsExpanded,
|
||||
onClick = ::onEmptySymbolsToggle,
|
||||
)
|
||||
add(emptyHeader)
|
||||
if (isEmptySymbolsExpanded) {
|
||||
filteredEmptySymbols.forEach {
|
||||
add(createEmptySymbolItem(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredEmptySymbols.isNotEmpty() && !isNotEmptySymbolsExist) {
|
||||
filteredEmptySymbols.forEach {
|
||||
add(createEmptySymbolItem(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createEmptySymbolItem(registerSymbol: RegisterSymbol) =
|
||||
LoginStudentSelectItem.SymbolHeader(
|
||||
symbol = registerSymbol,
|
||||
humanReadableName = view?.symbols?.get(registerSymbol.symbol),
|
||||
isErrorExpanded = expandedSymbolError == registerSymbol,
|
||||
onClick = ::onSymbolItemClick,
|
||||
)
|
||||
|
||||
fun onSignIn() {
|
||||
registerStudents(selectedStudents)
|
||||
}
|
||||
|
||||
fun onItemSelected(studentWithSemester: StudentWithSemesters, alreadySaved: Boolean) {
|
||||
if (alreadySaved) return
|
||||
private fun onEmptySymbolsToggle() {
|
||||
isEmptySymbolsExpanded = !isEmptySymbolsExpanded
|
||||
|
||||
refreshItems()
|
||||
}
|
||||
|
||||
private fun onItemSelected(item: LoginStudentSelectItem.Student) {
|
||||
if (!item.isEnabled) return
|
||||
|
||||
selectedStudents
|
||||
.removeAll { it == studentWithSemester }
|
||||
.let { if (!it) selectedStudents.add(studentWithSemester) }
|
||||
.removeAll {
|
||||
it.student.studentId == item.student.studentId &&
|
||||
it.student.classId == item.student.classId &&
|
||||
it.unit.schoolId == item.unit.schoolId &&
|
||||
it.symbol.symbol == item.symbol.symbol
|
||||
}
|
||||
.let { if (!it) selectedStudents.add(item) }
|
||||
|
||||
view?.enableSignIn(selectedStudents.isNotEmpty())
|
||||
refreshItems()
|
||||
}
|
||||
|
||||
private fun compareStudents(a: Student, b: Student): Boolean {
|
||||
return a.email == b.email
|
||||
&& a.symbol == b.symbol
|
||||
&& a.studentId == b.studentId
|
||||
&& a.schoolSymbol == b.schoolSymbol
|
||||
&& a.classId == b.classId
|
||||
private fun onSymbolItemClick(symbol: RegisterSymbol) {
|
||||
expandedSymbolError = if (symbol != expandedSymbolError) symbol else null
|
||||
refreshItems()
|
||||
}
|
||||
|
||||
private fun loadData(studentsWithSemesters: List<StudentWithSemesters>) {
|
||||
resetSelectedState()
|
||||
|
||||
resourceFlow { studentRepository.getSavedStudents(false) }.onEach {
|
||||
when (it) {
|
||||
is Resource.Loading -> Timber.d("Login student select students load started")
|
||||
is Resource.Success -> view?.updateData(studentsWithSemesters.map { studentWithSemesters ->
|
||||
studentWithSemesters to it.data.any { item ->
|
||||
compareStudents(studentWithSemesters.student, item.student)
|
||||
}
|
||||
})
|
||||
is Resource.Error -> {
|
||||
errorHandler.dispatch(it.error)
|
||||
lastError = it.error
|
||||
view?.updateData(studentsWithSemesters.map { student -> student to false })
|
||||
}
|
||||
}
|
||||
}.launch()
|
||||
private fun onUnitItemClick(unit: RegisterUnit) {
|
||||
expandedSchoolError = if (unit != expandedSchoolError) unit else null
|
||||
refreshItems()
|
||||
}
|
||||
|
||||
private fun resetSelectedState() {
|
||||
@ -89,7 +230,20 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
view?.enableSignIn(false)
|
||||
}
|
||||
|
||||
private fun registerStudents(studentsWithSemesters: List<StudentWithSemesters>) {
|
||||
private fun refreshItems() {
|
||||
view?.updateData(createItems())
|
||||
}
|
||||
|
||||
private fun registerStudents(students: List<LoginStudentSelectItem>) {
|
||||
val studentsWithSemesters = students
|
||||
.filterIsInstance<LoginStudentSelectItem.Student>().map { item ->
|
||||
item.student.mapToStudentWithSemesters(
|
||||
user = registerUser,
|
||||
symbol = item.symbol,
|
||||
unit = item.unit,
|
||||
colors = appInfo.defaultColorsForAvatar,
|
||||
)
|
||||
}
|
||||
resourceFlow { studentRepository.saveStudents(studentsWithSemesters) }
|
||||
.logResourceStatus("registration")
|
||||
.onEach {
|
||||
@ -100,14 +254,13 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
}
|
||||
is Resource.Success -> {
|
||||
syncManager.startOneTimeSyncWorker(quiet = true)
|
||||
view?.openMainView()
|
||||
view?.navigateToNext()
|
||||
logRegisterEvent(studentsWithSemesters)
|
||||
}
|
||||
is Resource.Error -> {
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
showContact(true)
|
||||
}
|
||||
lastError = it.error
|
||||
loginErrorHandler.dispatch(it.error)
|
||||
@ -117,12 +270,22 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
}.launch("register")
|
||||
}
|
||||
|
||||
fun onDiscordClick() {
|
||||
private fun onEnterSymbol() {
|
||||
view?.navigateToSymbol(loginData)
|
||||
}
|
||||
|
||||
private fun onDiscordClick() {
|
||||
view?.openDiscordInvite()
|
||||
}
|
||||
|
||||
fun onEmailClick() {
|
||||
view?.openEmail(lastError?.message.ifNullOrBlank { "empty" })
|
||||
private fun onEmailClick() {
|
||||
view?.openEmail(lastError?.message.ifNullOrBlank {
|
||||
registerUser.symbols.flatMap { symbol ->
|
||||
symbol.schools.map { it.error?.message } + symbol.error?.message
|
||||
}.filterNotNull().distinct().joinToString("; ") {
|
||||
it.take(46) + "..."
|
||||
}.ifEmpty { "blank" }
|
||||
})
|
||||
}
|
||||
|
||||
private fun logRegisterEvent(
|
||||
|
@ -1,15 +1,19 @@
|
||||
package io.github.wulkanowy.ui.modules.login.studentselect
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
|
||||
interface LoginStudentSelectView : BaseView {
|
||||
|
||||
val symbols: Map<String, String>
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<Pair<StudentWithSemesters, Boolean>>)
|
||||
fun updateData(data: List<LoginStudentSelectItem>)
|
||||
|
||||
fun openMainView()
|
||||
fun navigateToSymbol(loginData: LoginData)
|
||||
|
||||
fun navigateToNext()
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
@ -17,8 +21,6 @@ interface LoginStudentSelectView : BaseView {
|
||||
|
||||
fun enableSignIn(enable: Boolean)
|
||||
|
||||
fun showContact(show: Boolean)
|
||||
|
||||
fun openDiscordInvite()
|
||||
|
||||
fun openEmail(lastError: String)
|
||||
|
@ -12,17 +12,13 @@ import androidx.core.text.parseAsHtml
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.hideSoftInput
|
||||
import io.github.wulkanowy.utils.openEmailClient
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import io.github.wulkanowy.utils.showSoftInput
|
||||
import io.github.wulkanowy.utils.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -46,6 +42,8 @@ class LoginSymbolFragment :
|
||||
}
|
||||
}
|
||||
|
||||
override val symbolValue: String? get() = binding.loginSymbolName.text?.toString()
|
||||
|
||||
override val symbolNameError: CharSequence?
|
||||
get() = binding.loginSymbolNameLayout.error
|
||||
|
||||
@ -54,7 +52,7 @@ class LoginSymbolFragment :
|
||||
binding = FragmentLoginSymbolBinding.bind(view)
|
||||
presenter.onAttachView(
|
||||
view = this,
|
||||
loginData = requireArguments().getSerializable(SAVED_LOGIN_DATA) as LoginData,
|
||||
loginData = requireArguments().serializable(SAVED_LOGIN_DATA),
|
||||
)
|
||||
}
|
||||
|
||||
@ -62,7 +60,7 @@ class LoginSymbolFragment :
|
||||
(requireActivity() as LoginActivity).showActionBar(true)
|
||||
|
||||
with(binding) {
|
||||
loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) }
|
||||
loginSymbolSignIn.setOnClickListener { presenter.attemptLogin() }
|
||||
loginSymbolFaq.setOnClickListener { presenter.onFaqClick() }
|
||||
loginSymbolContactEmail.setOnClickListener { presenter.onEmailClick() }
|
||||
|
||||
@ -96,9 +94,13 @@ class LoginSymbolFragment :
|
||||
}
|
||||
|
||||
override fun setErrorSymbolRequire() {
|
||||
binding.loginSymbolNameLayout.apply {
|
||||
setErrorSymbol(getString(R.string.error_field_required))
|
||||
}
|
||||
|
||||
override fun setErrorSymbol(message: String) {
|
||||
with(binding.loginSymbolNameLayout) {
|
||||
requestFocus()
|
||||
error = getString(R.string.error_field_required)
|
||||
error = message
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,8 +131,8 @@ class LoginSymbolFragment :
|
||||
binding.loginSymbolContainer.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
|
||||
(activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
|
||||
override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
|
||||
(activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
|
@ -1,9 +1,12 @@
|
||||
package io.github.wulkanowy.ui.modules.login.symbol
|
||||
|
||||
import io.github.wulkanowy.data.Resource
|
||||
import io.github.wulkanowy.data.dataOrNull
|
||||
import io.github.wulkanowy.data.onResourceNotLoading
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.resourceFlow
|
||||
import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
@ -23,9 +26,14 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
|
||||
lateinit var loginData: LoginData
|
||||
|
||||
private var registerUser: RegisterUser? = null
|
||||
|
||||
fun onAttachView(view: LoginSymbolView, loginData: LoginData) {
|
||||
super.onAttachView(view)
|
||||
this.loginData = loginData
|
||||
loginErrorHandler.onBadCredentials = {
|
||||
view.setErrorSymbol(it.orEmpty())
|
||||
}
|
||||
with(view) {
|
||||
initView()
|
||||
showContact(false)
|
||||
@ -39,20 +47,24 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
view?.apply { if (symbolNameError != null) clearSymbolError() }
|
||||
}
|
||||
|
||||
fun attemptLogin(symbol: String) {
|
||||
if (symbol.isBlank()) {
|
||||
fun attemptLogin() {
|
||||
if (view?.symbolValue.isNullOrBlank()) {
|
||||
view?.setErrorSymbolRequire()
|
||||
return
|
||||
}
|
||||
|
||||
loginData = loginData.copy(
|
||||
symbol = view?.symbolValue?.getNormalizedSymbol(),
|
||||
)
|
||||
resourceFlow {
|
||||
studentRepository.getStudentsScrapper(
|
||||
studentRepository.getUserSubjectsFromScrapper(
|
||||
email = loginData.login,
|
||||
password = loginData.password,
|
||||
scrapperBaseUrl = loginData.baseUrl,
|
||||
symbol = symbol,
|
||||
symbol = view?.symbolValue.orEmpty(),
|
||||
)
|
||||
}.onEach {
|
||||
registerUser = it.dataOrNull
|
||||
when (it) {
|
||||
is Resource.Loading -> view?.run {
|
||||
Timber.i("Login with symbol started")
|
||||
@ -61,7 +73,7 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
showContent(false)
|
||||
}
|
||||
is Resource.Success -> {
|
||||
when (it.data.size) {
|
||||
when (it.data.symbols.size) {
|
||||
0 -> {
|
||||
Timber.i("Login with symbol result: Empty student list")
|
||||
view?.run {
|
||||
@ -71,15 +83,14 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
}
|
||||
else -> {
|
||||
Timber.i("Login with symbol result: Success")
|
||||
view?.navigateToStudentSelect(requireNotNull(it.data))
|
||||
view?.navigateToStudentSelect(loginData, requireNotNull(it.data))
|
||||
}
|
||||
}
|
||||
analytics.logEvent(
|
||||
"registration_symbol",
|
||||
"success" to true,
|
||||
"students" to it.data.size,
|
||||
"scrapperBaseUrl" to loginData.baseUrl,
|
||||
"symbol" to symbol,
|
||||
"symbol" to view?.symbolValue,
|
||||
"error" to "No error"
|
||||
)
|
||||
}
|
||||
@ -90,7 +101,7 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
"success" to false,
|
||||
"students" to -1,
|
||||
"scrapperBaseUrl" to loginData.baseUrl,
|
||||
"symbol" to symbol,
|
||||
"symbol" to view?.symbolValue,
|
||||
"error" to it.error.message.ifNullOrBlank { "No message" }
|
||||
)
|
||||
loginErrorHandler.dispatch(it.error)
|
||||
@ -111,6 +122,12 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onEmailClick() {
|
||||
view?.openEmail(loginData.baseUrl, lastError?.message.ifNullOrBlank { "empty" })
|
||||
view?.openEmail(loginData.baseUrl, lastError?.message.ifNullOrBlank {
|
||||
registerUser?.symbols?.flatMap { symbol ->
|
||||
symbol.schools.map { it.error?.message } + symbol.error?.message
|
||||
}?.filterNotNull()?.distinct()?.joinToString(";") {
|
||||
it.take(46) + "..."
|
||||
} ?: "blank"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package io.github.wulkanowy.ui.modules.login.symbol
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
|
||||
interface LoginSymbolView : BaseView {
|
||||
|
||||
val symbolValue: String?
|
||||
|
||||
val symbolNameError: CharSequence?
|
||||
|
||||
fun initView()
|
||||
@ -15,6 +18,8 @@ interface LoginSymbolView : BaseView {
|
||||
|
||||
fun setErrorSymbolRequire()
|
||||
|
||||
fun setErrorSymbol(message: String)
|
||||
|
||||
fun clearSymbolError()
|
||||
|
||||
fun clearAndFocusSymbol()
|
||||
@ -27,7 +32,7 @@ interface LoginSymbolView : BaseView {
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
|
||||
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>)
|
||||
fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser)
|
||||
|
||||
fun showContact(show: Boolean)
|
||||
|
||||
|
@ -6,6 +6,8 @@ import android.os.Build.VERSION_CODES.P
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.addCallback
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.DialogFragment
|
||||
@ -50,6 +52,8 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
private var onBackCallback: OnBackPressedCallback? = null
|
||||
|
||||
private var accountMenu: MenuItem? = null
|
||||
|
||||
private val overlayProvider by lazy { ElevationOverlayProvider(this) }
|
||||
@ -88,6 +92,9 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
this.savedInstanceState = savedInstanceState
|
||||
messageContainer = binding.mainMessageContainer
|
||||
updateHelper.messageContainer = binding.mainFragmentContainer
|
||||
onBackCallback = onBackPressedDispatcher.addCallback(this, enabled = false) {
|
||||
presenter.onBackPressed()
|
||||
}
|
||||
|
||||
val destination = intent.getStringExtra(EXTRA_START_DESTINATION)
|
||||
?.takeIf { savedInstanceState == null }
|
||||
@ -266,6 +273,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
|
||||
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
|
||||
navController.pushFragment(fragment)
|
||||
onBackCallback?.isEnabled = !isRootView
|
||||
}
|
||||
|
||||
override fun popView(depth: Int) {
|
||||
@ -273,10 +281,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
|
||||
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
|
||||
navController.safelyPopFragments(depth)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
presenter.onBackPressed { super.onBackPressed() }
|
||||
onBackCallback?.isEnabled = !isRootView
|
||||
}
|
||||
|
||||
override fun showStudentAvatar(student: Student) {
|
||||
|
@ -139,12 +139,9 @@ class MainPresenter @Inject constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
fun onBackPressed(default: () -> Unit) {
|
||||
fun onBackPressed() {
|
||||
Timber.i("Back pressed in main view")
|
||||
view?.run {
|
||||
if (isRootView) default()
|
||||
else popView()
|
||||
}
|
||||
view?.popView()
|
||||
}
|
||||
|
||||
fun onTabSelected(index: Int, wasSelected: Boolean): Boolean {
|
||||
|
@ -10,6 +10,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.data.db.entities.Mailbox
|
||||
import io.github.wulkanowy.databinding.DialogMailboxChooserBinding
|
||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||
import io.github.wulkanowy.utils.parcelableArray
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -52,8 +53,7 @@ class MailboxChooserDialog : BaseDialogFragment<DialogMailboxChooserBinding>(),
|
||||
presenter.onAttachView(
|
||||
view = this,
|
||||
requireMailbox = requireArguments().getBoolean(REQUIRED_KEY, false),
|
||||
mailboxes = requireArguments().getParcelableArray(MAILBOX_KEY).orEmpty()
|
||||
.toList() as List<Mailbox>,
|
||||
mailboxes = requireArguments().parcelableArray<Mailbox>(MAILBOX_KEY).orEmpty().toList(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
@ -23,6 +24,7 @@ import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import io.github.wulkanowy.utils.shareText
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -66,13 +68,12 @@ class MessagePreviewFragment :
|
||||
companion object {
|
||||
const val MESSAGE_ID_KEY = "message_id"
|
||||
|
||||
fun newInstance(message: Message): MessagePreviewFragment {
|
||||
return MessagePreviewFragment().apply {
|
||||
arguments = Bundle().apply { putSerializable(MESSAGE_ID_KEY, message) }
|
||||
}
|
||||
fun newInstance(message: Message) = MessagePreviewFragment().apply {
|
||||
arguments = bundleOf(MESSAGE_ID_KEY to message)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
@ -83,8 +84,8 @@ class MessagePreviewFragment :
|
||||
binding = FragmentMessagePreviewBinding.bind(view)
|
||||
messageContainer = binding.messagePreviewContainer
|
||||
presenter.onAttachView(
|
||||
this,
|
||||
(savedInstanceState ?: arguments)?.getSerializable(MESSAGE_ID_KEY) as? Message
|
||||
view = this,
|
||||
message = (savedInstanceState ?: arguments)?.serializable(MESSAGE_ID_KEY),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
runCatching {
|
||||
val student = studentRepository.getCurrentStudent(decryptPass = true)
|
||||
val mailbox = messageRepository.getMailboxByStudent(student)
|
||||
messageRepository.deleteMessage(student, mailbox!!, message!!)
|
||||
messageRepository.deleteMessage(student, mailbox, message!!)
|
||||
}
|
||||
.onFailure {
|
||||
retryCallback = { onMessageDelete() }
|
||||
|
@ -28,6 +28,7 @@ import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialo
|
||||
import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog.Companion.LISTENER_KEY
|
||||
import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.hideSoftInput
|
||||
import io.github.wulkanowy.utils.nullableSerializable
|
||||
import io.github.wulkanowy.utils.showSoftInput
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -108,12 +109,12 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter, ActivitySendMessa
|
||||
|
||||
presenter.onAttachView(
|
||||
view = this,
|
||||
reason = intent.getSerializableExtra(EXTRA_REASON) as? String,
|
||||
message = intent.getSerializableExtra(EXTRA_MESSAGE) as? Message,
|
||||
reply = intent.getSerializableExtra(EXTRA_REPLY) as? Boolean
|
||||
reason = intent.nullableSerializable(EXTRA_REASON),
|
||||
message = intent.nullableSerializable(EXTRA_MESSAGE),
|
||||
reply = intent.nullableSerializable(EXTRA_REPLY)
|
||||
)
|
||||
supportFragmentManager.setFragmentResultListener(LISTENER_KEY, this) { _, bundle ->
|
||||
presenter.onMailboxSelected(bundle.getSerializable(MAILBOX_KEY) as? Mailbox)
|
||||
presenter.onMailboxSelected(bundle.nullableSerializable(MAILBOX_KEY))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import android.view.View.*
|
||||
import android.widget.CompoundButton
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.setFragmentResultListener
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@ -27,6 +28,7 @@ import io.github.wulkanowy.ui.widgets.DividerItemDecoration
|
||||
import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.hideSoftInput
|
||||
import io.github.wulkanowy.utils.nullableSerializable
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -43,12 +45,8 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
|
||||
|
||||
const val MESSAGE_TAB_FOLDER_ID = "message_tab_folder_id"
|
||||
|
||||
fun newInstance(folder: MessageFolder): MessageTabFragment {
|
||||
return MessageTabFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString(MESSAGE_TAB_FOLDER_ID, folder.name)
|
||||
}
|
||||
}
|
||||
fun newInstance(folder: MessageFolder) = MessageTabFragment().apply {
|
||||
arguments = bundleOf(MESSAGE_TAB_FOLDER_ID to folder.name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,6 +84,7 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
@ -130,11 +129,12 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
|
||||
|
||||
setFragmentResultListener(requireArguments().getString(MESSAGE_TAB_FOLDER_ID)!!) { _, bundle ->
|
||||
presenter.onMailboxSelected(
|
||||
mailbox = bundle.getSerializable(MailboxChooserDialog.MAILBOX_KEY) as? Mailbox,
|
||||
mailbox = bundle.nullableSerializable(MailboxChooserDialog.MAILBOX_KEY),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
inflater.inflate(R.menu.action_menu_message_tab, menu)
|
||||
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Note
|
||||
@ -13,6 +14,7 @@ import io.github.wulkanowy.databinding.DialogNoteBinding
|
||||
import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
|
||||
class NoteDialog : DialogFragment() {
|
||||
@ -25,17 +27,15 @@ class NoteDialog : DialogFragment() {
|
||||
|
||||
private const val ARGUMENT_KEY = "Item"
|
||||
|
||||
fun newInstance(exam: Note) = NoteDialog().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
||||
fun newInstance(note: Note) = NoteDialog().apply {
|
||||
arguments = bundleOf(ARGUMENT_KEY to note)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
arguments?.run {
|
||||
note = getSerializable(ARGUMENT_KEY) as Note
|
||||
}
|
||||
note = requireArguments().serializable(ARGUMENT_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -0,0 +1,64 @@
|
||||
package io.github.wulkanowy.ui.modules.notifications
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.databinding.FragmentNotificationsBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.utils.openNotificationSettings
|
||||
|
||||
@AndroidEntryPoint
|
||||
class NotificationsFragment :
|
||||
BaseFragment<FragmentNotificationsBinding>(R.layout.fragment_notifications) {
|
||||
|
||||
private val permission = "android.permission.POST_NOTIFICATIONS"
|
||||
|
||||
private val requestPermissionLauncher = registerForActivityResult(RequestPermission()) {
|
||||
if (it) {
|
||||
navigateToFinish()
|
||||
} else showSettingsDialog()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance() = NotificationsFragment()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentNotificationsBinding.bind(view)
|
||||
initView()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
with(binding) {
|
||||
notificationsSkip.setOnClickListener { navigateToFinish() }
|
||||
notificationsEnable.setOnClickListener { requestPermission() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSettingsDialog() {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.notifications_header_title)
|
||||
.setMessage(R.string.notifications_header_description)
|
||||
.setNegativeButton(R.string.notifications_skip) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
navigateToFinish()
|
||||
}
|
||||
.setPositiveButton(R.string.pref_notification_go_to_settings) { _, _ ->
|
||||
requireActivity().openNotificationSettings()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun requestPermission() {
|
||||
requestPermissionLauncher.launch(permission)
|
||||
}
|
||||
|
||||
private fun navigateToFinish() {
|
||||
(requireActivity() as LoginActivity).navigateToFinish()
|
||||
}
|
||||
}
|
@ -2,10 +2,10 @@ package io.github.wulkanowy.ui.modules.schoolannouncement
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.text.parseAsHtml
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
||||
import io.github.wulkanowy.databinding.ItemSchoolAnnouncementBinding
|
||||
import io.github.wulkanowy.utils.parseUonetHtml
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -28,7 +28,7 @@ class SchoolAnnouncementAdapter @Inject constructor() :
|
||||
with(holder.binding) {
|
||||
schoolAnnouncementItemDate.text = item.date.toFormattedString()
|
||||
schoolAnnouncementItemType.text = item.subject
|
||||
schoolAnnouncementItemContent.text = item.content.parseAsHtml()
|
||||
schoolAnnouncementItemContent.text = item.content.parseUonetHtml()
|
||||
|
||||
root.setOnClickListener { onItemClickListener(item) }
|
||||
}
|
||||
|
@ -4,11 +4,13 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.text.parseAsHtml
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
||||
import io.github.wulkanowy.databinding.DialogSchoolAnnouncementBinding
|
||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||
import io.github.wulkanowy.utils.parseUonetHtml
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
|
||||
class SchoolAnnouncementDialog : DialogFragment() {
|
||||
@ -21,17 +23,15 @@ class SchoolAnnouncementDialog : DialogFragment() {
|
||||
|
||||
private const val ARGUMENT_KEY = "item"
|
||||
|
||||
fun newInstance(exam: SchoolAnnouncement) = SchoolAnnouncementDialog().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
||||
fun newInstance(announcement: SchoolAnnouncement) = SchoolAnnouncementDialog().apply {
|
||||
arguments = bundleOf(ARGUMENT_KEY to announcement)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
arguments?.run {
|
||||
announcement = getSerializable(ARGUMENT_KEY) as SchoolAnnouncement
|
||||
}
|
||||
announcement = requireArguments().serializable(ARGUMENT_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
@ -46,7 +46,7 @@ class SchoolAnnouncementDialog : DialogFragment() {
|
||||
with(binding) {
|
||||
announcementDialogSubjectValue.text = announcement.subject
|
||||
announcementDialogDateValue.text = announcement.date.toFormattedString()
|
||||
announcementDialogDescriptionValue.text = announcement.content.parseAsHtml()
|
||||
announcementDialogDescriptionValue.text = announcement.content.parseUonetHtml()
|
||||
|
||||
announcementDialogClose.setOnClickListener { dismiss() }
|
||||
}
|
||||
|
@ -1,18 +1,16 @@
|
||||
package io.github.wulkanowy.ui.modules.settings.notifications
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
@ -26,7 +24,7 @@ import io.github.wulkanowy.ui.base.ErrorDialog
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import timber.log.Timber
|
||||
import io.github.wulkanowy.utils.openNotificationSettings
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -42,7 +40,14 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
||||
|
||||
override val titleStringId get() = R.string.pref_settings_notifications_title
|
||||
|
||||
private val notificationsPermission = "android.permission.POST_NOTIFICATIONS"
|
||||
|
||||
override val isNotificationPermissionGranted: Boolean
|
||||
get() = ContextCompat.checkSelfPermission(
|
||||
requireContext(), notificationsPermission
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
|
||||
override val isNotificationPiggybackPermissionGranted: Boolean
|
||||
get() {
|
||||
val packageNameList =
|
||||
NotificationManagerCompat.getEnabledListenerPackages(requireContext())
|
||||
@ -51,6 +56,13 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
||||
return appPackageName in packageNameList
|
||||
}
|
||||
|
||||
private val requestPermissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||
if (it) {
|
||||
presenter.onNotificationsPermissionResult()
|
||||
} else openNotificationsPermissionDialog()
|
||||
}
|
||||
|
||||
private val notificationSettingsPiggybackContract =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
presenter.onNotificationPiggybackPermissionResult()
|
||||
@ -156,25 +168,29 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
||||
.show()
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
override fun openSystemSettings() {
|
||||
val intent = if (appInfo.systemVersion >= Build.VERSION_CODES.O) {
|
||||
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
|
||||
putExtra("android.provider.extra.APP_PACKAGE", requireActivity().packageName)
|
||||
}
|
||||
} else {
|
||||
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.fromParts("package", requireActivity().packageName, null)
|
||||
}
|
||||
}
|
||||
try {
|
||||
requireActivity().startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
requireActivity().openNotificationSettings()
|
||||
}
|
||||
|
||||
override fun openNotificationPermissionDialog() {
|
||||
override fun requestNotificationPermissions() {
|
||||
requestPermissionLauncher.launch(notificationsPermission)
|
||||
}
|
||||
|
||||
override fun openNotificationsPermissionDialog() {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.notifications_header_title)
|
||||
.setMessage(R.string.notifications_header_description)
|
||||
.setPositiveButton(R.string.pref_notification_go_to_settings) { _, _ ->
|
||||
requireActivity().openNotificationSettings()
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
setNotificationPreferencesChecked(false)
|
||||
}
|
||||
.setOnDismissListener { setNotificationPreferencesChecked(false) }
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun openNotificationPiggyBackPermissionDialog() {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(getString(R.string.pref_notification_piggyback_popup_title))
|
||||
.setMessage(getString(R.string.pref_notification_piggyback_popup_description))
|
||||
@ -202,6 +218,11 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun setNotificationPreferencesChecked(isChecked: Boolean) {
|
||||
findPreference<SwitchPreferenceCompat>(getString(R.string.pref_key_notifications_enable))?.isChecked =
|
||||
isChecked
|
||||
}
|
||||
|
||||
override fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) {
|
||||
findPreference<SwitchPreferenceCompat>(getString(R.string.pref_key_notifications_piggyback))?.isChecked =
|
||||
isChecked
|
||||
|
@ -26,12 +26,13 @@ class NotificationsPresenter @Inject constructor(
|
||||
|
||||
with(view) {
|
||||
enableNotification(
|
||||
preferencesRepository.notificationsEnableKey,
|
||||
preferencesRepository.isServiceEnabled
|
||||
notificationKey = preferencesRepository.notificationsEnableKey,
|
||||
enable = preferencesRepository.isServiceEnabled
|
||||
)
|
||||
initView(appInfo.isDebug)
|
||||
}
|
||||
|
||||
checkNotificationsPermissionState()
|
||||
checkNotificationPiggybackState()
|
||||
|
||||
Timber.i("Settings notifications view was initialized")
|
||||
@ -49,12 +50,17 @@ class NotificationsPresenter @Inject constructor(
|
||||
view?.openNotificationExactAlarmSettings()
|
||||
}
|
||||
}
|
||||
notificationsEnableKey -> {
|
||||
if (isNotificationsEnable && view?.isNotificationPermissionGranted == false) {
|
||||
view?.requestNotificationPermissions()
|
||||
}
|
||||
}
|
||||
isDebugNotificationEnableKey -> {
|
||||
chuckerCollector.showNotification = isDebugNotificationEnable
|
||||
}
|
||||
isNotificationPiggybackEnabledKey -> {
|
||||
if (isNotificationPiggybackEnabled && view?.isNotificationPermissionGranted == false) {
|
||||
view?.openNotificationPermissionDialog()
|
||||
if (isNotificationPiggybackEnabled && view?.isNotificationPiggybackPermissionGranted == false) {
|
||||
view?.openNotificationPiggyBackPermissionDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,9 +76,15 @@ class NotificationsPresenter @Inject constructor(
|
||||
view?.openSystemSettings()
|
||||
}
|
||||
|
||||
fun onNotificationsPermissionResult() {
|
||||
view?.run {
|
||||
setNotificationPreferencesChecked(isNotificationPermissionGranted)
|
||||
}
|
||||
}
|
||||
|
||||
fun onNotificationPiggybackPermissionResult() {
|
||||
view?.run {
|
||||
setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
|
||||
setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted)
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,10 +92,18 @@ class NotificationsPresenter @Inject constructor(
|
||||
view?.setUpcomingLessonsNotificationPreferenceChecked(timetableNotificationHelper.canScheduleExactAlarms())
|
||||
}
|
||||
|
||||
private fun checkNotificationsPermissionState() {
|
||||
if (preferencesRepository.isNotificationsEnable) {
|
||||
view?.run {
|
||||
setNotificationPreferencesChecked(isNotificationPermissionGranted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkNotificationPiggybackState() {
|
||||
if (preferencesRepository.isNotificationPiggybackEnabled) {
|
||||
view?.run {
|
||||
setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
|
||||
setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ interface NotificationsView : BaseView {
|
||||
|
||||
val isNotificationPermissionGranted: Boolean
|
||||
|
||||
val isNotificationPiggybackPermissionGranted: Boolean
|
||||
|
||||
fun initView(showDebugNotificationSwitch: Boolean)
|
||||
|
||||
fun showFixSyncDialog()
|
||||
@ -14,10 +16,16 @@ interface NotificationsView : BaseView {
|
||||
|
||||
fun enableNotification(notificationKey: String, enable: Boolean)
|
||||
|
||||
fun openNotificationPermissionDialog()
|
||||
fun requestNotificationPermissions()
|
||||
|
||||
fun openNotificationsPermissionDialog()
|
||||
|
||||
fun openNotificationPiggyBackPermissionDialog()
|
||||
|
||||
fun openNotificationExactAlarmSettings()
|
||||
|
||||
fun setNotificationPreferencesChecked(isChecked: Boolean)
|
||||
|
||||
fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean)
|
||||
|
||||
fun setUpcomingLessonsNotificationPreferenceChecked(isChecked: Boolean)
|
||||
|
@ -8,6 +8,7 @@ import android.view.MenuInflater
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.get
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@ -24,6 +25,8 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.capitalise
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.nullableSerializable
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -38,7 +41,9 @@ class StudentInfoFragment :
|
||||
lateinit var studentInfoAdapter: StudentInfoAdapter
|
||||
|
||||
override val titleStringId: Int
|
||||
get() = when (requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as? StudentInfoView.Type) {
|
||||
get() = when (
|
||||
requireArguments().nullableSerializable<StudentInfoView.Type>(INFO_TYPE_ARGUMENT_KEY)
|
||||
) {
|
||||
StudentInfoView.Type.PERSONAL -> R.string.account_personal_data
|
||||
StudentInfoView.Type.CONTACT -> R.string.account_contact
|
||||
StudentInfoView.Type.ADDRESS -> R.string.account_address
|
||||
@ -58,13 +63,14 @@ class StudentInfoFragment :
|
||||
|
||||
fun newInstance(type: StudentInfoView.Type, studentWithSemesters: StudentWithSemesters) =
|
||||
StudentInfoFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable(INFO_TYPE_ARGUMENT_KEY, type)
|
||||
putSerializable(STUDENT_ARGUMENT_KEY, studentWithSemesters)
|
||||
}
|
||||
arguments = bundleOf(
|
||||
INFO_TYPE_ARGUMENT_KEY to type,
|
||||
STUDENT_ARGUMENT_KEY to studentWithSemesters
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
@ -74,9 +80,9 @@ class StudentInfoFragment :
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentStudentInfoBinding.bind(view)
|
||||
presenter.onAttachView(
|
||||
this,
|
||||
requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as StudentInfoView.Type,
|
||||
requireArguments().getSerializable(STUDENT_ARGUMENT_KEY) as StudentWithSemesters
|
||||
view = this,
|
||||
type = requireArguments().serializable(INFO_TYPE_ARGUMENT_KEY),
|
||||
studentWithSemesters = requireArguments().serializable(STUDENT_ARGUMENT_KEY),
|
||||
)
|
||||
}
|
||||
|
||||
@ -153,7 +159,6 @@ class StudentInfoFragment :
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
override fun showFamilyTypeData(studentInfo: StudentInfo) {
|
||||
val items = buildList {
|
||||
add(studentInfo.firstGuardian?.let {
|
||||
|
@ -8,14 +8,12 @@ import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.databinding.DialogTimetableBinding
|
||||
import io.github.wulkanowy.utils.capitalise
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import io.github.wulkanowy.utils.*
|
||||
import java.time.Instant
|
||||
|
||||
class TimetableDialog : DialogFragment() {
|
||||
@ -28,17 +26,15 @@ class TimetableDialog : DialogFragment() {
|
||||
|
||||
private const val ARGUMENT_KEY = "Item"
|
||||
|
||||
fun newInstance(exam: Timetable) = TimetableDialog().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
||||
fun newInstance(lesson: Timetable) = TimetableDialog().apply {
|
||||
arguments = bundleOf(ARGUMENT_KEY to lesson)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
arguments?.run {
|
||||
lesson = getSerializable(ARGUMENT_KEY) as Timetable
|
||||
}
|
||||
lesson = requireArguments().serializable(ARGUMENT_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -7,6 +7,7 @@ import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.text.parseAsHtml
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
@ -39,9 +40,7 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
|
||||
private const val ARGUMENT_DATE_KEY = "ARGUMENT_DATE"
|
||||
|
||||
fun newInstance(date: LocalDate? = null) = TimetableFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
date?.let { putLong(ARGUMENT_DATE_KEY, it.toEpochDay()) }
|
||||
}
|
||||
arguments = date?.let { bundleOf(ARGUMENT_DATE_KEY to it.toEpochDay()) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,6 +50,7 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
|
||||
|
||||
override val currentStackSize get() = (activity as? MainActivity)?.currentStackSize
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -4,10 +4,12 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||
import io.github.wulkanowy.databinding.DialogLessonCompletedBinding
|
||||
import io.github.wulkanowy.utils.lifecycleAwareVariable
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
|
||||
class CompletedLessonDialog : DialogFragment() {
|
||||
|
||||
@ -19,17 +21,15 @@ class CompletedLessonDialog : DialogFragment() {
|
||||
|
||||
private const val ARGUMENT_KEY = "Item"
|
||||
|
||||
fun newInstance(exam: CompletedLesson) = CompletedLessonDialog().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
||||
fun newInstance(lesson: CompletedLesson) = CompletedLessonDialog().apply {
|
||||
arguments = bundleOf(ARGUMENT_KEY to lesson)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
arguments?.run {
|
||||
completedLesson = getSerializable(ARGUMENT_KEY) as CompletedLesson
|
||||
}
|
||||
completedLesson = requireArguments().serializable(ARGUMENT_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -0,0 +1,32 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import java.io.Serializable
|
||||
|
||||
inline fun <reified T : Serializable> Bundle.serializable(key: String): T = when {
|
||||
Build.VERSION.SDK_INT >= 33 -> getSerializable(key, T::class.java)!!
|
||||
else -> @Suppress("DEPRECATION") getSerializable(key) as T
|
||||
}
|
||||
|
||||
inline fun <reified T : Serializable> Bundle.nullableSerializable(key: String): T? = when {
|
||||
Build.VERSION.SDK_INT >= 33 -> getSerializable(key, T::class.java)
|
||||
else -> @Suppress("DEPRECATION") getSerializable(key) as T?
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION", "UNCHECKED_CAST")
|
||||
inline fun <reified T : Serializable> Bundle.parcelableArray(key: String): Array<T>? = when {
|
||||
Build.VERSION.SDK_INT >= 33 -> getParcelableArray(key, T::class.java)
|
||||
else -> getParcelableArray(key) as Array<T>?
|
||||
}
|
||||
|
||||
inline fun <reified T : Serializable> Intent.serializable(key: String): T = when {
|
||||
Build.VERSION.SDK_INT >= 33 -> getSerializableExtra(key, T::class.java)!!
|
||||
else -> @Suppress("DEPRECATION") getSerializableExtra(key) as T
|
||||
}
|
||||
|
||||
inline fun <reified T : Serializable> Intent.nullableSerializable(key: String): T? = when {
|
||||
Build.VERSION.SDK_INT >= 33 -> getSerializableExtra(key, T::class.java)
|
||||
else -> @Suppress("DEPRECATION") getSerializableExtra(key) as T?
|
||||
}
|
@ -1,11 +1,15 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.CalendarContract
|
||||
import android.provider.Settings
|
||||
import io.github.wulkanowy.BuildConfig
|
||||
import timber.log.Timber
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
|
||||
@ -86,6 +90,23 @@ fun Context.openDialer(phone: String) {
|
||||
}
|
||||
}
|
||||
|
||||
fun Activity.openNotificationSettings() {
|
||||
val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
|
||||
putExtra("android.provider.extra.APP_PACKAGE", packageName)
|
||||
}
|
||||
} else {
|
||||
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.fromParts("package", packageName, null)
|
||||
}
|
||||
}
|
||||
try {
|
||||
startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.shareText(text: String, subject: String?) {
|
||||
val sendIntent: Intent = Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
|
@ -1,7 +1,15 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import androidx.core.text.parseAsHtml
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
|
||||
inline fun String?.ifNullOrBlank(defaultValue: () -> String) =
|
||||
if (isNullOrBlank()) defaultValue() else this
|
||||
|
||||
fun String.capitalise() =
|
||||
replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
|
||||
replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
|
||||
|
||||
fun String.parseUonetHtml() = this
|
||||
.let(StringEscapeUtils::unescapeHtml4)
|
||||
.replace("\n", "<br/>")
|
||||
.parseAsHtml()
|
||||
|
@ -1,8 +1,10 @@
|
||||
Wersja 1.8.3
|
||||
Wersja 1.9.0
|
||||
|
||||
- naprawiliśmy logowanie dla użytkowników systemu Resman Rzeszów
|
||||
- dodaliśmy wsparcie dla nowej platformy z Tomaszowa Mazowieckiego
|
||||
- poprawiliśmy dopasowywanie skrzynek pocztowych do uczniów
|
||||
- naprawiliśmy literówkę w tytule wiadomości z szablonem usprawiedliwienia
|
||||
- dodaliśmy obsługę Androida 13 (w tym ikona aplikacji obsługująca Material You)
|
||||
- przerobiliśmy ekran wyboru ucznia przy pierwszym logowaniu
|
||||
- naprawiliśmy usuwanie wiadomości w niektórych przypadkach
|
||||
- naprawiliśmy błąd występujący przy resecie hasła
|
||||
- naprawiliśmy literówkę w tytule domyślnej treści wiadomości usprawiedliwiania
|
||||
- naprawiliśmy nazwę aplikacji przy ustawionym w telefonie jezyku francuskim
|
||||
|
||||
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
||||
|
@ -0,0 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="1926"
|
||||
android:viewportHeight="1926">
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M920,1357.7v-184.5h42.7q19.3,0.3 34.3,6.6 15.2,6.2 25.6,17.5 10.6,11.2 16,26.9 5.6,15.6 5.7, 34.6v13.5q-0.1,19 -5.7,34.7 -5.4,15.6 -16,26.9 -10.4,11.2 -25.6,17.5 -15,6.2 -34.3,6.3zM943.8,1192.5v146.1h18.9q15, -0.1 25.8,-5.2 11,-5.2 18,-14 7.3,-9 10.7,-21 3.5,-12 3.6,-26v-13.9q0,-14 -3.6,-26t-10.7,-20.7q-7,-9 -18,-14 -10.9,-5 -25.8,-5.3zM1179.5,1272.5h-77v65.4h89.8v19.9L1079,1357.8v-184.6h112.2v20h-88.7v59.4h77zM1288.9, 1320l43.6,-146.8h25l-58.2,184.6h-20.4l-58.3,-184.6h25z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#000" />
|
||||
<clip-path android:pathData="M 0 0 L 1926 0 L 1926 1111 L 850 1111 L 850 1926 L 0 1926 z" />
|
||||
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M1082,1260v4l-6,73c0,5 -5,9 -10,9H879c-4,0 -8,-2 -10,-5l-31,-58 -29,-71v-8l48,-94c2,-3 2,-5 1, -8l-24,-65c-1,-2 0,-5 1,-7l39,-84c4,-8 17,-8 20,1l12,38 38,101c1,2 3,5 6,6l80,27c3,1 6,3 7,6l45,135zM852,717c0,-23 15,-43 35,-52l-2,-8c0,-11 13,-20 29,-20h1a38,38 0,0 1,36 -18l3,-2c11,-16 37,-27 68,-27 12,0 23,2 32,4 3,-3 8,-6 14,-6s12,3 14,8c8,-9 22,-16 38,-16 25,0 45,16 45,36l-1,7 3,4c16,6 27,17 27,30 0,14 -15,27 -34,32 -2,0 -3,1 -3,3 0,11 -11,21 -26,22v1c0,22 -41,40 -92,40 -11,0 -21,-1 -31,-3v1c0,9 -12,16 -26,16h-2l2,7c0,14 -18,25 -40,25h-7l-4, 2c-2,7 -8,12 -15,12 -9,0 -16,-7 -16,-16 0,-5 1,-8 4,-11l1,-4c-2,-3 -2,-5 -2,-8 0,-2 -2,-3 -3,-3 -27,-6 -48,-29 -48,-56z" />
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M1336,1346h-125c-3,0 -6,-1 -8,-4l-84,-118 -1,-2 -42,-122 -5,-5 -102,-52 -5,-6 -15,-75 -2,-3 -34,-51c-2,-3 -2,-6 -1,-9l21,-45c2,-4 5,-6 9,-6l39,-2c3,0 5,-1 6,-3l29,-22c5,-4 14,-2 17,4l98,201 1,2 13,81 2,5 197,216c6,6 1,16 -8,16zM801,1302c1,3 1,6 -1,8l-19,31c-2,3 -5,5 -9,5H591c-8,0 -13,-8 -9,-15l116,-171 2,-3 53, -228c1,-3 3,-5 5,-6l72,-40c3,-1 5,-4 5,-7l10,-42c2,-9 15,-11 20,-3l3,6c2,2 2,5 1,8l-66,190v5l16,91v5l-40,88v6l22,72z" />
|
||||
|
||||
</vector>
|
12
app/src/main/res/drawable/ic_launcher_foreground_mono.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="1926"
|
||||
android:viewportHeight="1926">
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M1082,1260v4l-6,73c0,5 -5,9 -10,9H879c-4,0 -8,-2 -10,-5l-31,-58 -29,-71v-8l48,-94c2,-3 2,-5 1, -8l-24,-65c-1,-2 0,-5 1,-7l39,-84c4,-8 17,-8 20,1l12,38 38,101c1,2 3,5 6,6l80,27c3,1 6,3 7,6l45,135zM852,717c0,-23 15,-43 35,-52l-2,-8c0,-11 13,-20 29,-20h1a38,38 0,0 1,36 -18l3,-2c11,-16 37,-27 68,-27 12,0 23,2 32,4 3,-3 8,-6 14,-6s12,3 14,8c8,-9 22,-16 38,-16 25,0 45,16 45,36l-1,7 3,4c16,6 27,17 27,30 0,14 -15,27 -34,32 -2,0 -3,1 -3,3 0,11 -11,21 -26,22v1c0,22 -41,40 -92,40 -11,0 -21,-1 -31,-3v1c0,9 -12,16 -26,16h-2l2,7c0,14 -18,25 -40,25h-7l-4, 2c-2,7 -8,12 -15,12 -9,0 -16,-7 -16,-16 0,-5 1,-8 4,-11l1,-4c-2,-3 -2,-5 -2,-8 0,-2 -2,-3 -3,-3 -27,-6 -48,-29 -48,-56z" />
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M1336,1346h-125c-3,0 -6,-1 -8,-4l-84,-118 -1,-2 -42,-122 -5,-5 -102,-52 -5,-6 -15,-75 -2,-3 -34,-51c-2,-3 -2,-6 -1,-9l21,-45c2,-4 5,-6 9,-6l39,-2c3,0 5,-1 6,-3l29,-22c5,-4 14,-2 17,4l98,201 1,2 13,81 2,5 197,216c6,6 1,16 -8,16zM801,1302c1,3 1,6 -1,8l-19,31c-2,3 -5,5 -9,5H591c-8,0 -13,-8 -9,-15l116,-171 2,-3 53, -228c1,-3 3,-5 5,-6l72,-40c3,-1 5,-4 5,-7l10,-42c2,-9 15,-11 20,-3l3,6c2,2 2,5 1,8l-66,190v5l16,91v5l-40,88v6l22,72z" />
|
||||
</vector>
|
@ -40,7 +40,7 @@
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:text="@string/all_title"
|
||||
android:text="@string/conference_place"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
@ -71,7 +71,7 @@
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:text="@string/all_subject"
|
||||
android:text="@string/conference_topic"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -3,92 +3,14 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/loginStudentSelectProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone" />
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.modules.login.studentselect.LoginStudentSelectFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/loginStudentSelectContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/loginStudentSelectContact"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible">
|
||||
|
||||
<View
|
||||
android:id="@+id/loginStudentSelectContactTopDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginStudentSelectContactHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginLeft="32dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginRight="32dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/login_contact_header"
|
||||
android:textSize="14sp"
|
||||
app:fontFamily="sans-serif-medium" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/loginStudentSelectContactButtons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginStudentSelectContactEmail"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/login_contact_email"
|
||||
app:icon="@drawable/ic_more_messages" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginStudentSelectContactDiscord"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/login_contact_discord"
|
||||
app:icon="@drawable/ic_about_discord" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/loginStudentSelectContactBottomDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginStudentSelectHeader"
|
||||
android:layout_width="match_parent"
|
||||
@ -106,22 +28,24 @@
|
||||
app:layout_constraintBottom_toTopOf="@id/loginStudentSelectRecycler"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/loginStudentSelectContact"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/loginStudentSelectRecycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="144dp"
|
||||
android:fadingEdge="vertical"
|
||||
android:fadingEdgeLength="100dp"
|
||||
android:requiresFadingEdge="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/loginStudentSelectSignIn"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_max="432dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/loginStudentSelectHeader"
|
||||
tools:itemCount="6"
|
||||
tools:listitem="@layout/item_login_student_select" />
|
||||
tools:itemCount="33"
|
||||
tools:listitem="@layout/item_login_student_select_student" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginStudentSelectSignIn"
|
||||
@ -136,4 +60,12 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/loginStudentSelectRecycler" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/loginStudentSelectProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
69
app/src/main/res/layout/fragment_notifications.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<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"
|
||||
tools:context=".ui.modules.notifications.NotificationsFragment">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/notifications_header_icon"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:src="@drawable/ic_settings_notifications"
|
||||
app:layout_constraintBottom_toTopOf="@id/notifications_header_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.4"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notifications_header_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginVertical="16dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/notifications_header_title"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/notifications_header_description"
|
||||
app:layout_constraintTop_toBottomOf="@id/notifications_header_icon"
|
||||
app:lineHeight="30sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notifications_header_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/notifications_header_description"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/notifications_skip"
|
||||
app:layout_constraintTop_toBottomOf="@id/notifications_header_title"
|
||||
app:lineHeight="24sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/notifications_skip"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/notifications_skip"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/notifications_enable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/notifications_enable"
|
||||
app:icon="@drawable/ic_settings_notifications"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="?selectableItemBackground"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_student_select_empty_symbol_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="16dp"
|
||||
android:text="@string/login_other_search_locations"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/login_student_select_empty_symbol_chevron"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:rotation="90"
|
||||
android:src="@drawable/ic_chevron_right"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?android:textColorPrimary"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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="wrap_content"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_student_select_header_school_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Publiczna szkoła Wulkanowego" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_student_select_header_school_details"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="@string/login_no_active_student"
|
||||
android:textColor="?colorTimetableChange"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_student_select_header_school_name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_student_select_header_school_error"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?colorError"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_student_select_header_school_details"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_student_select_header_symbol_value"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="powiatjaroslawski" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_student_select_header_symbol_username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_student_select_header_symbol_value"
|
||||
tools:text="Jan Kowalski" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_student_select_header_symbol_error"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?colorError"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_student_select_header_symbol_username"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
61
app/src/main/res/layout/item_login_student_select_help.xml
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/login_student_select_help_symbol"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/login_symbol_enter"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_student_select_help_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/login_contact_header"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/login_student_select_help_mail"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_student_select_help_symbol" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/login_student_select_help_mail"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:contentDescription="@string/login_contact_email"
|
||||
app:icon="@drawable/ic_more_messages"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="0dp"
|
||||
app:layout_constraintEnd_toEndOf="@id/login_student_select_help_title"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/login_student_select_help_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_student_select_help_symbol" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/login_student_select_help_discord"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/login_contact_discord"
|
||||
app:icon="@drawable/ic_about_discord"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="0dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/login_student_select_help_mail"
|
||||
app:layout_constraintTop_toTopOf="@id/login_student_select_help_mail" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -4,7 +4,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:minHeight="72dp"
|
||||
android:minHeight="56dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
tools:context=".ui.modules.login.studentselect.LoginStudentSelectAdapter">
|
||||
@ -14,9 +14,10 @@
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="28dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:clickable="false"
|
||||
tools:text=" " />
|
||||
|
||||
<TextView
|
||||
@ -32,34 +33,18 @@
|
||||
tools:text="@tools:sample/full_names" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginItemSchool"
|
||||
android:id="@+id/loginItemSignedIn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/loginItemName"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_toEndOf="@id/loginItemCheck"
|
||||
android:ellipsize="end"
|
||||
android:gravity="bottom"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="14sp"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginItemSignedIn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="20dp"
|
||||
android:layout_below="@id/loginItemSchool"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_toEndOf="@id/loginItemCheck"
|
||||
android:ellipsize="end"
|
||||
android:enabled="false"
|
||||
android:gravity="bottom"
|
||||
android:maxLines="1"
|
||||
android:minHeight="20dp"
|
||||
android:text="@string/login_signed_in"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
android:textSize="14sp" />
|
||||
</RelativeLayout>
|
@ -2,4 +2,5 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/colorPrimary" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground_mono" />
|
||||
</adaptive-icon>
|
||||
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/colorPrimary" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 12 KiB |
@ -55,7 +55,7 @@
|
||||
<string name="login_invalid_symbol">Neplatný symbol</string>
|
||||
<string name="login_incorrect_symbol">Žák nebyl nalezen. Zkontrolujte správnost symbolu a vybrané varianty deníku UONET+</string>
|
||||
<string name="login_duplicate_student">Vybraný žák je už přihlášen</string>
|
||||
<string name="login_symbol_helper">Symbol najdete na stránce deníku v  <b>Uczeń</b>→ <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b>.\n\nUjistěte se, že jste na předchozí obrazovce nastavili správnou variantu deníku do pole <b>Variace deníku UONET+</b></string>
|
||||
<string name="login_symbol_helper">Symbol najdete na stránce deníku v  <b>Uczeń</b>→ <b>Dostęp Mobilny</b> → <b>Wygeneruj kod dostępu</b>.\n\nUjistěte se, že jste nastavili správnou variantu deníku v poli <b>Variace deníku UONET+</b> na první přihlašovací obrazovce</string>
|
||||
<string name="login_select_student">Vyberte žáky, kteří se mají do aplikace přihlásit</string>
|
||||
<string name="login_advanced">Jiné možnosti</string>
|
||||
<string name="login_advanced_warning_mobile_api">V tomto režimu nefungují následující: šťastné číslo, statistiky třídy, shrnutí frekvencí, ospravedlnění nepřítomnosti, dokončené lekce, informace o škole a prohlížení seznamu registrovaných zařízení</string>
|
||||
@ -72,6 +72,14 @@
|
||||
<string name="login_recover">Obnovit</string>
|
||||
<string name="login_signed_in">Žák je už přihlášen</string>
|
||||
<string name="login_host_standard">Standardní</string>
|
||||
<string name="login_other_search_locations">Jiná místa vyhledávání</string>
|
||||
<string name="login_no_active_student">Nebyli nalezeni žádní aktivní žáci</string>
|
||||
<string name="login_symbol_enter">Zadejte jiný symbol</string>
|
||||
<!--Notifications-->
|
||||
<string name="notifications_header_title">Povolit oznámení</string>
|
||||
<string name="notifications_header_description">Povolit upozornění, abyste nezmeškali zprávu od učitele nebo o nové známce</string>
|
||||
<string name="notifications_skip">Přeskočit</string>
|
||||
<string name="notifications_enable">Zapnout</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Manažer účtů</string>
|
||||
<string name="main_log_in">Přihlásit se</string>
|
||||
@ -485,6 +493,8 @@
|
||||
</plurals>
|
||||
<string name="conferences_present">Přítomnost na setkání</string>
|
||||
<string name="conference_agenda">Agenda</string>
|
||||
<string name="conference_place">Místo</string>
|
||||
<string name="conference_topic">Téma</string>
|
||||
<!--Director information-->
|
||||
<string name="school_announcement_title">Školní oznámení</string>
|
||||
<string name="school_announcement_no_items">Žádná školní oznámení</string>
|
||||
|
65
app/src/main/res/values-da-rDK/preferences_values.xml
Normal file
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string-array name="app_theme_entries" tools:ignore="InconsistentArrays">
|
||||
<item>Light</item>
|
||||
<item>Dark</item>
|
||||
<item>Black (AMOLED)</item>
|
||||
</string-array>
|
||||
<string-array name="app_language_entries">
|
||||
<item>System language</item>
|
||||
<item>Polski</item>
|
||||
<item>English</item>
|
||||
<item>Pусский</item>
|
||||
<item>Українська</item>
|
||||
<item>Deutsch</item>
|
||||
<item>Čeština</item>
|
||||
<item>Slovenčina</item>
|
||||
</string-array>
|
||||
<string-array name="services_interval_entries">
|
||||
<item>15 minutes</item>
|
||||
<item>30 minutes</item>
|
||||
<item>1 hour</item>
|
||||
<item>2 hours</item>
|
||||
<item>6 hours</item>
|
||||
<item>12 hours</item>
|
||||
<item>24 hours</item>
|
||||
</string-array>
|
||||
<string-array name="grade_modifier_entries">
|
||||
<item>0,00</item>
|
||||
<item>0,25</item>
|
||||
<item>0,33</item>
|
||||
<item>0,5</item>
|
||||
<item>0,75</item>
|
||||
</string-array>
|
||||
<string-array name="grade_sorting_mode_entries">
|
||||
<item>Alphabetically</item>
|
||||
<item>By date</item>
|
||||
<item>By average</item>
|
||||
</string-array>
|
||||
<string-array name="grade_color_scheme_entries">
|
||||
<item>Dzienniczek+</item>
|
||||
<item>Wulkanowy</item>
|
||||
<item>Grade colors in register</item>
|
||||
</string-array>
|
||||
<string-array name="default_expand_grade_entries">
|
||||
<item>Up to 1 at once</item>
|
||||
<item>Always expanded</item>
|
||||
<item>Unlimited expansions</item>
|
||||
</string-array>
|
||||
<string-array name="grade_average_mode_entries">
|
||||
<item>Average of grades only from selected semester</item>
|
||||
<item>Average of averages from both semesters</item>
|
||||
<item>Average of grades from the whole year</item>
|
||||
</string-array>
|
||||
<string-array name="dashboard_tile_entries">
|
||||
<item>Lucky number</item>
|
||||
<item>Unread messages</item>
|
||||
<item>Attendance</item>
|
||||
<item>Lessons</item>
|
||||
<item>Grades</item>
|
||||
<item>Homework</item>
|
||||
<item>School announcements</item>
|
||||
<item>Exams</item>
|
||||
<item>Conferences</item>
|
||||
</string-array>
|
||||
</resources>
|
728
app/src/main/res/values-da-rDK/strings.xml
Normal file
@ -0,0 +1,728 @@
|
||||
<?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>
|
||||
<!--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_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_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</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">I forgot my 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>
|
||||
<!--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_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_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>
|
||||
<!--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>
|
||||
<!--Timetable Widget-->
|
||||
<string name="widget_timetable_no_items">No lessons</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_timers">Mark current lesson</string>
|
||||
<string name="pref_view_timetable_show_groups">Show groups next to subjects</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_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_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">Consent to processing of data related to ads</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_ads_consent_title">Can we use your data to display ads?</string>
|
||||
<string name="pref_ads_consent_description">You can change your choice anytime in the app settings. We may use your data to display ads tailored to you or, using less of your data, display non-personalized ads. Please see our Privacy Policy for details</string>
|
||||
<string name="pref_ads_summary_personalized">Personalized ads</string>
|
||||
<string name="pref_ads_summary_non_personalized">Non-personalized ads</string>
|
||||
<string name="pref_ads_over_18_years_old">I am over 18 years old</string>
|
||||
<string name="pref_ads_option_personalized">Yes, personalized ads</string>
|
||||
<string name="pref_ads_option_non_personalized">Yes, non-personalized 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>
|
||||
<!--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>
|
@ -55,7 +55,7 @@
|
||||
<string name="login_invalid_symbol">Ungültige symbol</string>
|
||||
<string name="login_incorrect_symbol">Schüler nicht gefunden. Überprüfen Sie das Symbol und die gewählte Variation des UONET+ Registers</string>
|
||||
<string name="login_duplicate_student">Ausgewählter Student ist bereits angemeldet.</string>
|
||||
<string name="login_symbol_helper">Das Symbol kann auf der Registerseite in <b>Uczeń</b>→ <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b>gefunden werden.\n\nStellen Sie sicher, dass Sie die entsprechende Registervariante im Feld <b>UONET+ Registervariante</b> auf dem vorherigen Bildschirm festgelegt haben</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">Wählen Sie die Studenten aus, die sich bei der Anwendung anmelden sollen</string>
|
||||
<string name="login_advanced">Andere Optionen</string>
|
||||
<string name="login_advanced_warning_mobile_api">In diesem Modus funktioniert eine Glücknummer, eine Klassenstatistik, eine Zusammenfassung der Anwesenheit, eine Entschuldigung für die Abwesenheit, abgeschlossene Lektionen, Schulinformationen und eine Vorschau der Liste der registrierten Geräte nicht</string>
|
||||
@ -72,6 +72,14 @@
|
||||
<string name="login_recover">Wiederherstellen</string>
|
||||
<string name="login_signed_in">Student ist bereits angemeldet</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>
|
||||
<!--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">Kundenbetreuer</string>
|
||||
<string name="main_log_in">Anmelden</string>
|
||||
@ -275,7 +283,7 @@
|
||||
<string name="message_not_exists">Nachricht nicht vorhanden</string>
|
||||
<string name="message_required_recipients">Sie müssen mindestens 1 Empfänger auswählen.</string>
|
||||
<string name="message_content_min_length">Der Inhalt der Nachricht muss mindestens 3 Zeichen lang sein.</string>
|
||||
<string name="message_chip_all_mailboxes">All mailboxes</string>
|
||||
<string name="message_chip_all_mailboxes">Alle postfächer</string>
|
||||
<string name="message_chip_only_unread">Nur ungelesen</string>
|
||||
<string name="message_chip_only_with_attachments">Nur mit Anhängen</string>
|
||||
<string name="message_read">Lesen: %s</string>
|
||||
@ -299,7 +307,7 @@
|
||||
<item quantity="other">%1$d ausgewählt</item>
|
||||
</plurals>
|
||||
<string name="message_messages_deleted">Nachrichten gelöscht</string>
|
||||
<string name="message_mailbox_chooser_title">Choose mailbox</string>
|
||||
<string name="message_mailbox_chooser_title">Postfach auswählen</string>
|
||||
<!--Note-->
|
||||
<string name="note_no_items">Keine Informationen über Eintragen</string>
|
||||
<string name="note_points">Punkte</string>
|
||||
@ -413,6 +421,8 @@
|
||||
</plurals>
|
||||
<string name="conferences_present">Teilnahme an einem Meeting</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">Schulankündigungen</string>
|
||||
<string name="school_announcement_no_items">Keine schulankündigungen</string>
|
||||
|
@ -55,7 +55,7 @@
|
||||
<string name="login_invalid_symbol">Invalid symbol</string>
|
||||
<string name="login_incorrect_symbol">Student not found. Validate the symbol and the chosen variation of the UONET+ register</string>
|
||||
<string name="login_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>Zarejestruj urządzenie mobilne</b>.\n\nMake sure that you have set the appropriate register variant in the <b>UONET+ register variant</b> field on the previous screen</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>
|
||||
@ -72,6 +72,14 @@
|
||||
<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>
|
||||
<!--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>
|
||||
@ -413,6 +421,8 @@
|
||||
</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>
|
||||
|
@ -55,7 +55,7 @@
|
||||
<string name="login_invalid_symbol">Nieprawidłowy symbol</string>
|
||||
<string name="login_incorrect_symbol">Nie znaleziono ucznia. Sprawdź poprawność symbolu i wybranej odmiany dziennika UONET+</string>
|
||||
<string name="login_duplicate_student">Wybrany uczeń jest już zalogowany</string>
|
||||
<string name="login_symbol_helper">Symbol znajdziesz na stronie dziennika w <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b>.\n\nUpewnij się, że w polu <b>Dziennik UONET+</b> na poprzednim ekranie została ustawiona odpowiednia odmiana dziennika</string>
|
||||
<string name="login_symbol_helper">Symbol można znaleźć na stronie dziennika w <b>Uczeń</b>→ <b>Dostęp Mobilny</b> → <b>Wygeneruj kod dostępu</b>.\n\nUpewnij się, że ustawiłeś odpowiednią odmianę dziennika w polu <b>Odmiana dziennika UONET+</b> na pierwszym ekranie logowania</string>
|
||||
<string name="login_select_student">Wybierz uczniów do zalogowania w aplikacji</string>
|
||||
<string name="login_advanced">Inne opcje</string>
|
||||
<string name="login_advanced_warning_mobile_api">W tym trybie nie działa szczęśliwy numerek, uczeń na tle klasy, podsumowanie frekwencji, usprawiedliwianie nieobecności, lekcje zrealizowane, informacje o szkole i podgląd listy zarejestrowanych urządzeń</string>
|
||||
@ -72,6 +72,14 @@
|
||||
<string name="login_recover">Przywróć</string>
|
||||
<string name="login_signed_in">Uczeń jest już zalogowany</string>
|
||||
<string name="login_host_standard">Standardowa</string>
|
||||
<string name="login_other_search_locations">Inne lokalizacje wyszukiwania</string>
|
||||
<string name="login_no_active_student">Nie znaleziono aktywnych uczniów</string>
|
||||
<string name="login_symbol_enter">Wprowadź inny symbol</string>
|
||||
<!--Notifications-->
|
||||
<string name="notifications_header_title">Włącz powiadomienia</string>
|
||||
<string name="notifications_header_description">Włącz powiadomienia, aby nie przegapić wiadomości od nauczyciela lub nowej oceny</string>
|
||||
<string name="notifications_skip">Pomiń</string>
|
||||
<string name="notifications_enable">Włącz</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Menadżer kont</string>
|
||||
<string name="main_log_in">Zaloguj się</string>
|
||||
@ -485,6 +493,8 @@
|
||||
</plurals>
|
||||
<string name="conferences_present">Obecność na zebraniu</string>
|
||||
<string name="conference_agenda">Agenda</string>
|
||||
<string name="conference_place">Miejsce</string>
|
||||
<string name="conference_topic">Temat</string>
|
||||
<!--Director information-->
|
||||
<string name="school_announcement_title">Ogłoszenia szkolne</string>
|
||||
<string name="school_announcement_no_items">Brak ogłoszeń szkolnych</string>
|
||||
|
@ -55,7 +55,7 @@
|
||||
<string name="login_invalid_symbol">Неверный symbol</string>
|
||||
<string name="login_incorrect_symbol">Ученик не найден. Проверьте symbol и выбранный тип дненика UONET+</string>
|
||||
<string name="login_duplicate_student">Данный ученик уже авторизован</string>
|
||||
<string name="login_symbol_helper">Symbol можно найти на странице регистрации в  <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b>.\n\nУбедитесь, что вы выбрали соответствующий тип дневника в поле <b>Тип дневника UONET+</b> на предыдущем экране</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">Выберите учеников для авторизации в приложении</string>
|
||||
<string name="login_advanced">Другие варианты</string>
|
||||
<string name="login_advanced_warning_mobile_api">В этом режиме не работают: счастливый номер, статистика класса по оценкам, статистика посещаемости и уроков, информация о школе и список зарегистрированных устройств</string>
|
||||
@ -72,6 +72,14 @@
|
||||
<string name="login_recover">Восстановить</string>
|
||||
<string name="login_signed_in">Ученик уже авторизован</string>
|
||||
<string name="login_host_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>
|
||||
<!--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">Менеджер аккаунтов</string>
|
||||
<string name="main_log_in">Войти</string>
|
||||
@ -485,6 +493,8 @@
|
||||
</plurals>
|
||||
<string name="conferences_present">Присутствует на встрече</string>
|
||||
<string name="conference_agenda">Повестка дня</string>
|
||||
<string name="conference_place">Place</string>
|
||||
<string name="conference_topic">Topic</string>
|
||||
<!--Director information-->
|
||||
<string name="school_announcement_title">Объявления школы</string>
|
||||
<string name="school_announcement_no_items">Нет школьных объявлений</string>
|
||||
|
@ -35,7 +35,7 @@
|
||||
<string name="login_email_hint">Email</string>
|
||||
<string name="login_login_pesel_email_hint">Prihlásenie, číslo PESEL alebo e-mail</string>
|
||||
<string name="login_password_hint">Heslo</string>
|
||||
<string name="login_host_hint">Variácie denníka UONET+</string>
|
||||
<string name="login_host_hint">Variácia denníka UONET+</string>
|
||||
<string name="login_type_api">Mobile API</string>
|
||||
<string name="login_type_scrapper">Scraper</string>
|
||||
<string name="login_type_hybrid">Hybridné</string>
|
||||
@ -55,7 +55,7 @@
|
||||
<string name="login_invalid_symbol">Neplatný symbol</string>
|
||||
<string name="login_incorrect_symbol">Žiak nebol nájdený. Skontrolujte správnosť symbolu a vybrané varianty denníka UONET+</string>
|
||||
<string name="login_duplicate_student">Vybraný žiak už je prihlásený</string>
|
||||
<string name="login_symbol_helper">Symbol nájdete na stránke denníka v  <b>Uczeń</b>→ <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b>.\n\nUistite sa, že ste na predchádzajúcu obrazovke nastaviť správny variant denníka do poľa <b>Variácie denníka UONET+</b></string>
|
||||
<string name="login_symbol_helper">Symbol nájdete na stránke denníka v  <b>Uczeń</b>→ <b>Dostęp Mobilny</b> → <b>Wygeneruj kod dostępu</b>.\n\nUistite sa, že ste nastavili správny variant denníka v poli <b>Variácia denníka UONET+</b> na prvej prihlasovacej obrazovke</string>
|
||||
<string name="login_select_student">Vyberte žiakov, ktorí sa majú do aplikácie prihlásiť</string>
|
||||
<string name="login_advanced">Iné možnosti</string>
|
||||
<string name="login_advanced_warning_mobile_api">V tomto režime nefungujú nasledovné: šťastné číslo, štatistiky triedy, zhrnutie frekvencií, ospravedlnenie neprítomnosti, dokončené lekcie, informácie o škole a prezeranie zoznamu registrovaných zariadení</string>
|
||||
@ -72,6 +72,14 @@
|
||||
<string name="login_recover">Obnoviť</string>
|
||||
<string name="login_signed_in">Žiak je už prihlásený</string>
|
||||
<string name="login_host_standard">Štandardná</string>
|
||||
<string name="login_other_search_locations">Iné miesta vyhľadávania</string>
|
||||
<string name="login_no_active_student">Neboli nájdení žiadni aktívni žiaci</string>
|
||||
<string name="login_symbol_enter">Zadajte iný symbol</string>
|
||||
<!--Notifications-->
|
||||
<string name="notifications_header_title">Povoliť oznámenia</string>
|
||||
<string name="notifications_header_description">Povoliť oznámenia, aby ste nezmeškali správu od učiteľa alebo o novej známke</string>
|
||||
<string name="notifications_skip">Preskočiť</string>
|
||||
<string name="notifications_enable">Zapnúť</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Manažér účtov</string>
|
||||
<string name="main_log_in">Prihlásiť sa</string>
|
||||
@ -485,6 +493,8 @@
|
||||
</plurals>
|
||||
<string name="conferences_present">Prítomnosť na stretnutí</string>
|
||||
<string name="conference_agenda">Agenda</string>
|
||||
<string name="conference_place">Miesto</string>
|
||||
<string name="conference_topic">Téma</string>
|
||||
<!--Director information-->
|
||||
<string name="school_announcement_title">Školské oznámenia</string>
|
||||
<string name="school_announcement_no_items">Žiadne školské oznámenia</string>
|
||||
|
@ -55,7 +55,7 @@
|
||||
<string name="login_invalid_symbol">Неправильний symbol</string>
|
||||
<string name="login_incorrect_symbol">Студента не знайдено. Перевірте symbol та обранний тип щоденника UONET+</string>
|
||||
<string name="login_duplicate_student">Цього учня вже авторизовано</string>
|
||||
<string name="login_symbol_helper">Symbol можна знайти на сторінці реєстрації в  <b>Uczeń</b>→ <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b>.\n\nПереконайтесь, що ви встановили відповідний тип щоденника в полі <b>Тип щоденника UONET+</b> на попередньому екрані</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">Виберіть учнів для авторизації в додатку</string>
|
||||
<string name="login_advanced">Інші варіанти</string>
|
||||
<string name="login_advanced_warning_mobile_api">У цьому режимі не працюють: щасливий номер, статистика класу по оцінкам, статистика відвідуваності та уроків, інформація про школу та список зареєстрованих пристроїв</string>
|
||||
@ -72,6 +72,14 @@
|
||||
<string name="login_recover">Відновити</string>
|
||||
<string name="login_signed_in">Учня вже авторизовано</string>
|
||||
<string name="login_host_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>
|
||||
<!--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">Змінити облікові записи</string>
|
||||
<string name="main_log_in">Увійти</string>
|
||||
@ -485,6 +493,8 @@
|
||||
</plurals>
|
||||
<string name="conferences_present">Присутність на зустрічі</string>
|
||||
<string name="conference_agenda">Порядок денний</string>
|
||||
<string name="conference_place">Place</string>
|
||||
<string name="conference_topic">Topic</string>
|
||||
<!--Director information-->
|
||||
<string name="school_announcement_title">Оголошення школи</string>
|
||||
<string name="school_announcement_no_items">Немає шкільних оголошень</string>
|
||||
|
@ -42,7 +42,7 @@
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
<item>https://vulcan.net.pl/?login</item>
|
||||
<item>http://fakelog.cf/?email</item>
|
||||
<item>https://fakelog.cf/?email</item>
|
||||
</string-array>
|
||||
<string-array name="hosts_symbols">
|
||||
<item>Default</item>
|
||||
|
@ -55,7 +55,7 @@
|
||||
<string name="login_invalid_symbol">Invalid symbol</string>
|
||||
<string name="login_incorrect_symbol">Student not found. Validate the symbol and the chosen variation of the UONET+ register</string>
|
||||
<string name="login_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>Zarejestruj urządzenie mobilne</b>.\n\nMake sure that you have set the appropriate register variant in the <b>UONET+ register variant</b> field on the previous screen</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>
|
||||
@ -74,6 +74,14 @@
|
||||
<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>
|
||||
<!--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>
|
||||
@ -417,6 +425,8 @@
|
||||
</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>
|
||||
|
17
app/src/main/res/xml/data_extraction_rules.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<exclude domain="file" />
|
||||
<exclude domain="database" />
|
||||
<exclude domain="sharedpref" />
|
||||
<exclude domain="external" />
|
||||
<exclude domain="root" />
|
||||
</cloud-backup>
|
||||
<device-transfer>
|
||||
<exclude domain="file" />
|
||||
<exclude domain="database" />
|
||||
<exclude domain="sharedpref" />
|
||||
<exclude domain="external" />
|
||||
<exclude domain="root" />
|
||||
</device-transfer>
|
||||
</data-extraction-rules>
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true"/>
|
||||
<debug-overrides>
|
||||
<trust-anchors>
|
||||
<certificates src="user" />
|
||||
|