Merge branch 'release/1.1.1'

This commit is contained in:
Mikołaj Pich 2021-03-16 00:43:33 +01:00
commit 60a9bcae46
22 changed files with 230 additions and 90 deletions

View File

@ -68,3 +68,135 @@ jobs:
PLAY_SERVICE_ACCOUNT_EMAIL: ${{ secrets.PLAY_SERVICE_ACCOUNT_EMAIL }} PLAY_SERVICE_ACCOUNT_EMAIL: ${{ secrets.PLAY_SERVICE_ACCOUNT_EMAIL }}
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }} PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
run: ./gradlew publishPlayRelease -PenableFirebase --stacktrace; run: ./gradlew publishPlayRelease -PenableFirebase --stacktrace;
deploy-appcenter:
name: Deploy to App Center
runs-on: ubuntu-latest
timeout-minutes: 10
environment: app-center
if: github.ref != 'refs/heads/develop'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 11
- uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Set run number with offset
env:
BUILD_NUMBER_OFFSET: ${{ secrets.BUILD_NUMBER_OFFSET }}
run: echo "RUN_NUMBER=$((GITHUB_RUN_NUMBER+BUILD_NUMBER_OFFSET))" >> $GITHUB_ENV
- name: Prepare build configuration
run: |
sed -i -e "s#applicationIdSuffix \".dev\"#applicationIdSuffix \".${GITHUB_HEAD_REF//[-.\/]/_}\"#" app/build.gradle
sed -i -e "s#.dev\"#.${GITHUB_HEAD_REF//[-.\/]/_}\"#" app/src/debug/google-services.json
sed -i -e "s#.dev\"#.${GITHUB_HEAD_REF//[-.\/]/_}\"#" app/src/debug/agconnect-services.json
sed -i -e '/versionNameSuffix/d' app/build.gradle
- name: Add signing config
run: |
cat >> app/build.gradle <<EOF
android.signingConfigs.debug {
storeFile file("bitrise.jks")
storePassword System.getenv("BITRISE_KEYSTORE_PASSWORD")
keyAlias System.getenv("BITRISE_KEY_ALIAS")
keyPassword System.getenv("BITRISE_KEY_PASSWORD")
}
EOF
- name: Decrypt keys
env:
BITRISE_ENCRYPT_KEY: ${{ secrets.BITRISE_ENCRYPT_KEY }}
run: |
gpg --yes --batch --passphrase=$BITRISE_ENCRYPT_KEY ./app/bitrise.jks.gpg
- name: Bump version
uses: chkfung/android-version-actions@v1.1
with:
gradlePath: app/build.gradle
versionCode: ${{ env.RUN_NUMBER }}
versionName: ${{ env.RUN_NUMBER }}-${{ github.head_ref }}
- name: Build apk
env:
BITRISE_KEYSTORE_PASSWORD: ${{ secrets.BITRISE_KEYSTORE_PASSWORD }}
BITRISE_KEY_ALIAS: ${{ secrets.BITRISE_KEY_ALIAS }}
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
run: ./gradlew assembleFdroidDebug --stacktrace
- name: Upload apk to github artifacts
uses: actions/upload-artifact@v2
with:
name: wulkanowyDEV-${{ env.RUN_NUMBER }}.apk
path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk
- name: Deploy to app center
uses: wzieba/AppCenter-Github-Action@v1
with:
appName: wulkanowy/wulkanowy
token: ${{ secrets.APP_CENTER_TOKEN }}
group: Testers
file: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk
notifyTesters: true
debug: true
deploy-app-distribution:
name: Deploy to AppDistribution
runs-on: ubuntu-latest
timeout-minutes: 10
environment: app-distribution
if: github.ref == 'refs/heads/develop'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 11
- uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Set run number with offset
env:
BUILD_NUMBER_OFFSET: ${{ secrets.BUILD_NUMBER_OFFSET }}
run: echo "RUN_NUMBER=$((GITHUB_RUN_NUMBER+BUILD_NUMBER_OFFSET))" >> $GITHUB_ENV
- name: Add signing config
run: |
cat >> app/build.gradle <<EOF
android.signingConfigs.debug {
storeFile file("bitrise.jks")
storePassword System.getenv("BITRISE_KEYSTORE_PASSWORD")
keyAlias System.getenv("BITRISE_KEY_ALIAS")
keyPassword System.getenv("BITRISE_KEY_PASSWORD")
}
EOF
- name: Decrypt keys
env:
BITRISE_ENCRYPT_KEY: ${{ secrets.BITRISE_ENCRYPT_KEY }}
BITRISE_SERVICES_ENCRYPT_KEY: ${{ secrets.BITRISE_SERVICES_ENCRYPT_KEY }}
run: |
gpg --yes --batch --passphrase=$BITRISE_SERVICES_ENCRYPT_KEY ./app/src/debug/google-services.json.gpg
gpg --yes --batch --passphrase=$BITRISE_ENCRYPT_KEY ./app/bitrise.jks.gpg
- name: Bump version
uses: chkfung/android-version-actions@v1.1
with:
gradlePath: app/build.gradle
versionCode: ${{ env.RUN_NUMBER }}
versionName: ${{ env.RUN_NUMBER }}
- name: Build apk
env:
BITRISE_KEYSTORE_PASSWORD: ${{ secrets.BITRISE_KEYSTORE_PASSWORD }}
BITRISE_KEY_ALIAS: ${{ secrets.BITRISE_KEY_ALIAS }}
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
run: ./gradlew assemblePlayDebug -PenableFirebase --stacktrace
- name: Upload apk to github artifacts
uses: actions/upload-artifact@v2
with:
name: wulkanowyDEV-${{ env.RUN_NUMBER }}-dev.apk
path: app/build/outputs/apk/play/debug/app-play-debug.apk
- name: Deploy to app distribution
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{ secrets.FIREBASE_APP_ID }}
token: ${{ secrets.FIREBASE_TOKEN }}
groups: discord
file: app/build/outputs/apk/play/debug/app-play-debug.apk

BIN
app/bitrise.jks Normal file

Binary file not shown.

BIN
app/bitrise.jks.gpg Normal file

Binary file not shown.

View File

@ -5,6 +5,8 @@ apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'com.google.firebase.crashlytics' apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.github.triplet.play' apply plugin: 'com.github.triplet.play'
apply plugin: 'com.mikepenz.aboutlibraries.plugin' apply plugin: 'com.mikepenz.aboutlibraries.plugin'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.huawei.agconnect'
apply from: 'jacoco.gradle' apply from: 'jacoco.gradle'
apply from: 'sonarqube.gradle' apply from: 'sonarqube.gradle'
apply from: 'hooks.gradle' apply from: 'hooks.gradle'
@ -18,8 +20,8 @@ android {
testApplicationId "io.github.tests.wulkanowy" testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 30 targetSdkVersion 30
versionCode 86 versionCode 87
versionName "1.1.0" versionName "1.1.1"
multiDexEnabled true multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@ -58,7 +60,7 @@ android {
release { release {
minifyEnabled true minifyEnabled true
shrinkResources true shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release signingConfig signingConfigs.release
} }
debug { debug {
@ -115,6 +117,7 @@ android {
} }
kotlinOptions { kotlinOptions {
useIR = true
jvmTarget = "1.8" jvmTarget = "1.8"
freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"] freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
} }
@ -134,31 +137,31 @@ play {
serviceAccountCredentials = file('key.p12') serviceAccountCredentials = file('key.p12')
defaultToAppBundles = false defaultToAppBundles = false
track = 'production' track = 'production'
updatePriority = 3 updatePriority = 5
} }
ext { ext {
work_manager = "2.5.0" work_manager = "2.5.0"
work_hilt = "1.0.0-alpha03" work_hilt = "1.0.0-beta01"
room = "2.3.0-beta02" room = "2.3.0-beta03"
chucker = "3.4.0" chucker = "3.4.0"
mockk = "1.10.6" mockk = "1.10.6"
moshi = "1.11.0" moshi = "1.11.0"
} }
dependencies { dependencies {
implementation "io.github.wulkanowy:sdk:1.1.0" implementation "io.github.wulkanowy:sdk:1.1.1"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
implementation "androidx.core:core-ktx:1.3.2" implementation "androidx.core:core-ktx:1.3.2"
implementation "androidx.activity:activity-ktx:1.2.0" implementation "androidx.activity:activity-ktx:1.2.1"
implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.appcompat:appcompat-resources:1.2.0" implementation "androidx.appcompat:appcompat-resources:1.2.0"
implementation "androidx.fragment:fragment-ktx:1.3.0" implementation "androidx.fragment:fragment-ktx:1.3.1"
implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.annotation:annotation:1.1.0"
implementation "androidx.multidex:multidex:2.0.1" implementation "androidx.multidex:multidex:2.0.1"
@ -169,7 +172,7 @@ dependencies {
implementation "androidx.constraintlayout:constraintlayout:2.0.4" implementation "androidx.constraintlayout:constraintlayout:2.0.4"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0" implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
implementation "com.google.android.material:material:1.3.0" implementation "com.google.android.material:material:1.3.0"
implementation "com.github.wulkanowy:material-chips-input:2.1.1" implementation "com.github.wulkanowy:material-chips-input:2.2.0"
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
implementation 'com.mikhaellopez:circularimageview:4.2.0' implementation 'com.mikhaellopez:circularimageview:4.2.0'
@ -203,7 +206,7 @@ dependencies {
implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
implementation 'me.xdrop:fuzzywuzzy:1.3.1' implementation 'me.xdrop:fuzzywuzzy:1.3.1'
playImplementation platform('com.google.firebase:firebase-bom:26.6.0') playImplementation platform('com.google.firebase:firebase-bom:26.7.0')
playImplementation 'com.google.firebase:firebase-analytics-ktx' playImplementation 'com.google.firebase:firebase-analytics-ktx'
playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx' playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx'
playImplementation "com.google.firebase:firebase-inappmessaging-ktx" playImplementation "com.google.firebase:firebase-inappmessaging-ktx"
@ -239,6 +242,3 @@ dependencies {
androidTestImplementation "io.mockk:mockk-android:$mockk" androidTestImplementation "io.mockk:mockk-android:$mockk"
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
} }
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.huawei.agconnect'

View File

@ -1,33 +1,21 @@
# Optimizations # General
-optimizationpasses 5
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-dontobfuscate -dontobfuscate
-allowaccessmodification
-repackageclasses ''
-verbose
#Keep all wulkanowy files #Config for wulkanowy
-keep class io.github.wulkanowy.** {*;} -keep class io.github.wulkanowy.** {*;}
#Config for anallitycs #Config for firebase crashlitycs
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable -keepattributes SourceFile,LineNumberTable
-keep class com.crashlytics.** {*;}
-keep public class * extends java.lang.Exception -keep public class * extends java.lang.Exception
-dontwarn com.crashlytics.**
#Config for OkHttp #Config for Okio and OkHttp
-dontwarn javax.annotation.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase -keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
-dontwarn org.codehaus.mojo.animal_sniffer.* -dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okhttp3.internal.platform.ConscryptPlatform -dontwarn okhttp3.internal.platform.ConscryptPlatform
-dontwarn javax.annotation.**
#Config for MPAndroidChart #Config for MPAndroidChart
@ -36,10 +24,3 @@
#Config for Material Components #Config for Material Components
-keep class com.google.android.material.tabs.** { *; } -keep class com.google.android.material.tabs.** { *; }
#Config for About Libraries
-keep class .R
-keep class **.R$* {
<fields>;
}

View File

@ -192,7 +192,7 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
} }
override fun showContent(show: Boolean) { override fun showContent(show: Boolean) {
binding. attendanceRecycler.visibility = if (show) VISIBLE else GONE binding.attendanceRecycler.visibility = if (show) VISIBLE else GONE
} }
override fun showRefresh(show: Boolean) { override fun showRefresh(show: Boolean) {

View File

@ -190,35 +190,48 @@ class AttendancePresenter @Inject constructor(
flowWithResourceIn { flowWithResourceIn {
val student = studentRepository.getCurrentStudent() val student = studentRepository.getCurrentStudent()
val semester = semesterRepository.getCurrentSemester(student) val semester = semesterRepository.getCurrentSemester(student)
attendanceRepository.getAttendance(student, semester, currentDate, currentDate, forceRefresh) attendanceRepository.getAttendance(
student,
semester,
currentDate,
currentDate,
forceRefresh
)
}.onEach { }.onEach {
when (it.status) { when (it.status) {
Status.LOADING -> { Status.LOADING -> {
view?.showExcuseButton(false) view?.showExcuseButton(false)
if (!it.data.isNullOrEmpty()) { if (!it.data.isNullOrEmpty()) {
val filteredAttendance = if (prefRepository.isShowPresent) {
it.data
} else {
it.data.filter { item -> !item.presence }
}
view?.run { view?.run {
enableSwipe(true) enableSwipe(true)
showRefresh(true) showRefresh(true)
showProgress(false) showProgress(false)
showContent(true) showEmpty(filteredAttendance.isEmpty())
updateData(it.data.let { items -> showContent(filteredAttendance.isNotEmpty())
if (prefRepository.isShowPresent) items updateData(filteredAttendance.sortedBy { item -> item.number })
else items.filter { item -> !item.presence }
}.sortedBy { item -> item.number })
} }
} }
} }
Status.SUCCESS -> { Status.SUCCESS -> {
Timber.i("Loading attendance result: Success") Timber.i("Loading attendance result: Success")
val filteredAttendance = if (prefRepository.isShowPresent) {
it.data.orEmpty()
} else {
it.data?.filter { item -> !item.presence }.orEmpty()
}
view?.apply { view?.apply {
updateData(it.data!!.let { items -> updateData(filteredAttendance.sortedBy { item -> item.number })
if (prefRepository.isShowPresent) items showEmpty(filteredAttendance.isEmpty())
else items.filter { item -> !item.presence }
}.sortedBy { item -> item.number })
showEmpty(it.data.isEmpty())
showErrorView(false) showErrorView(false)
showContent(it.data.isNotEmpty()) showContent(filteredAttendance.isNotEmpty())
showExcuseButton(it.data.any { item -> item.excusable }) showExcuseButton(filteredAttendance.any { item -> item.excusable })
} }
analytics.logEvent( analytics.logEvent(
"load_data", "load_data",

View File

@ -10,6 +10,7 @@ import android.view.View.VISIBLE
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.databinding.FragmentGradeBinding import io.github.wulkanowy.databinding.FragmentGradeBinding
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
@ -121,11 +122,9 @@ class GradeFragment : BaseFragment<FragmentGradeBinding>(R.layout.fragment_grade
semesterSwitchMenu?.isVisible = show semesterSwitchMenu?.isVisible = show
} }
override fun showSemesterDialog(selectedIndex: Int) { override fun showSemesterDialog(selectedIndex: Int, semesters: List<Semester>) {
val choices = arrayOf( val choices = semesters.map { getString(R.string.grade_semester, it.semesterName) }
getString(R.string.grade_semester, 1), .toTypedArray()
getString(R.string.grade_semester, 2)
)
AlertDialog.Builder(requireContext()) AlertDialog.Builder(requireContext())
.setSingleChoiceItems(choices, selectedIndex) { dialog, which -> .setSingleChoiceItems(choices, selectedIndex) { dialog, which ->

View File

@ -49,7 +49,9 @@ class GradePresenter @Inject constructor(
} }
fun onSemesterSwitch(): Boolean { fun onSemesterSwitch(): Boolean {
if (semesters.isNotEmpty()) view?.showSemesterDialog(selectedIndex - 1) if (semesters.isNotEmpty()) {
view?.showSemesterDialog(selectedIndex - 1, semesters.slice(0..1))
}
return true return true
} }
@ -137,11 +139,17 @@ class GradePresenter @Inject constructor(
private fun loadChild(index: Int, forceRefresh: Boolean = false) { private fun loadChild(index: Int, forceRefresh: Boolean = false) {
Timber.d("Load grade tab child. Selected semester: $selectedIndex, semesters: ${semesters.joinToString { it.semesterName.toString() }}") Timber.d("Load grade tab child. Selected semester: $selectedIndex, semesters: ${semesters.joinToString { it.semesterName.toString() }}")
semesters.first { it.semesterName == selectedIndex }.semesterId.also {
if (forceRefresh || loadedSemesterId[index] != it) { val newSelectedSemesterId = try {
Timber.i("Load grade child view index: $index") semesters.first { it.semesterName == selectedIndex }.semesterId
view?.notifyChildLoadData(index, it, forceRefresh) } catch (e: NoSuchElementException) {
} Timber.e(e, "Selected semester no exists")
return
}
if (forceRefresh || loadedSemesterId[index] != newSelectedSemesterId) {
Timber.i("Load grade child view index: $index")
view?.notifyChildLoadData(index, newSelectedSemesterId, forceRefresh)
} }
} }

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.ui.modules.grade package io.github.wulkanowy.ui.modules.grade
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.ui.base.BaseView import io.github.wulkanowy.ui.base.BaseView
interface GradeView : BaseView { interface GradeView : BaseView {
@ -18,7 +19,7 @@ interface GradeView : BaseView {
fun showSemesterSwitch(show: Boolean) fun showSemesterSwitch(show: Boolean)
fun showSemesterDialog(selectedIndex: Int) fun showSemesterDialog(selectedIndex: Int, semesters: List<Semester>)
fun setCurrentSemesterName(semester: Int, schoolYear: Int) fun setCurrentSemesterName(semester: Int, schoolYear: Int)

View File

@ -291,7 +291,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
): Boolean { ): Boolean {
val fragment = val fragment =
supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment) supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment)
navController.pushFragment(fragment) pushView(fragment)
return true return true
} }
@ -305,6 +305,8 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
} }
override fun switchMenuView(position: Int) { override fun switchMenuView(position: Int) {
if (supportFragmentManager.isStateSaved) return
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.switchTab(position) navController.switchTab(position)
} }
@ -322,6 +324,8 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
} }
override fun showAccountPicker(studentWithSemesters: List<StudentWithSemesters>) { override fun showAccountPicker(studentWithSemesters: List<StudentWithSemesters>) {
if (supportFragmentManager.isStateSaved) return
navController.showDialogFragment(AccountQuickDialog.newInstance(studentWithSemesters)) navController.showDialogFragment(AccountQuickDialog.newInstance(studentWithSemesters))
} }
@ -339,15 +343,21 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
} }
fun showDialogFragment(dialog: DialogFragment) { fun showDialogFragment(dialog: DialogFragment) {
if (supportFragmentManager.isStateSaved) return
navController.showDialogFragment(dialog) navController.showDialogFragment(dialog)
} }
fun pushView(fragment: Fragment) { fun pushView(fragment: Fragment) {
if (supportFragmentManager.isStateSaved) return
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.pushFragment(fragment) navController.pushFragment(fragment)
} }
override fun popView(depth: Int) { override fun popView(depth: Int) {
if (supportFragmentManager.isStateSaved) return
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.safelyPopFragments(depth) navController.safelyPopFragments(depth)
} }

View File

@ -113,7 +113,7 @@ class MainPresenter @Inject constructor(
private fun showCurrentStudentAvatar() { private fun showCurrentStudentAvatar() {
val currentStudent = val currentStudent =
studentsWitSemesters!!.single { it.student.isCurrent }.student studentsWitSemesters?.singleOrNull { it.student.isCurrent }?.student ?: return
view?.showStudentAvatar(currentStudent) view?.showStudentAvatar(currentStudent)
} }

View File

@ -53,13 +53,14 @@ class SchoolFragment : BaseFragment<FragmentSchoolBinding>(R.layout.fragment_sch
override fun updateData(data: School) { override fun updateData(data: School) {
with(binding) { with(binding) {
schoolName.text = data.name val noDataString = getString(R.string.all_no_data)
schoolAddress.text = data.address.ifBlank { "-" } schoolName.text = data.name.ifBlank { noDataString }
schoolAddress.text = data.address.ifBlank { noDataString }
schoolAddressButton.visibility = if (data.address.isNotBlank()) VISIBLE else GONE schoolAddressButton.visibility = if (data.address.isNotBlank()) VISIBLE else GONE
schoolTelephone.text = data.contact.ifBlank { "-" } schoolTelephone.text = data.contact.ifBlank { noDataString }
schoolTelephoneButton.visibility = if (data.contact.isNotBlank()) VISIBLE else GONE schoolTelephoneButton.visibility = if (data.contact.isNotBlank()) VISIBLE else GONE
schoolHeadmaster.text = data.headmaster schoolHeadmaster.text = data.headmaster.ifBlank { noDataString }
schoolPedagogue.text = data.pedagogue schoolPedagogue.text = data.pedagogue.ifBlank { noDataString }
} }
} }

View File

@ -1,11 +1,6 @@
Wersja 1.1.0 Wersja 1.1.1
- dodaliśmy wyświetlanie inicjałów imienia ucznia jako awatar widoczny w aplikacji - naprawiliśmy wyświetlanie planu lekcji
- dodaliśmy historię szczęśliwego numerka - naprawiliśmy kilka rzadkich problemów ze stabilnością
- dodaliśmy język słowacki
- zmieniliśmy kolor górnego i dolnego paska systemowego lepiej dostosowując je do aplikacji
- zmieniliśmy wygląd ustawień dzieląc je na sekcje
- naprawiliśmy problem dublujących się czasem ocen
- naprawiliśmy kilka innych błędów i poprawiliśmy stabilność aplikacji
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases

View File

@ -192,7 +192,7 @@
</plurals> </plurals>
<string name="attendance_excuse_dialog_reason">Důvod nepřítomnosti (volitelný)</string> <string name="attendance_excuse_dialog_reason">Důvod nepřítomnosti (volitelný)</string>
<string name="attendance_excuse_dialog_submit">Poslat</string> <string name="attendance_excuse_dialog_submit">Poslat</string>
<string name="attendance_excuse_success">Nepřítomnost úspěšně omluvena!</string> <string name="attendance_excuse_success">Žádost o omluvu nepřítomnosti byla úspěšně odeslána!</string>
<string name="attendance_excuse_no_selection">Musíte vybrat alespoň jednu nepřítomnost!</string> <string name="attendance_excuse_no_selection">Musíte vybrat alespoň jednu nepřítomnost!</string>
<string name="attendance_excuse_title">Ospravedlnit</string> <string name="attendance_excuse_title">Ospravedlnit</string>
<!--Attendance summary--> <!--Attendance summary-->

View File

@ -176,7 +176,7 @@
</plurals> </plurals>
<string name="attendance_excuse_dialog_reason">Abwesenheitsgrund (optional)</string> <string name="attendance_excuse_dialog_reason">Abwesenheitsgrund (optional)</string>
<string name="attendance_excuse_dialog_submit">Senden</string> <string name="attendance_excuse_dialog_submit">Senden</string>
<string name="attendance_excuse_success">Abwesenheit erfolgreich entschuldigt!</string> <string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
<string name="attendance_excuse_no_selection">Sie müssen mindestens eine Abwesenheit auswählen!</string> <string name="attendance_excuse_no_selection">Sie müssen mindestens eine Abwesenheit auswählen!</string>
<string name="attendance_excuse_title">Verzeihung</string> <string name="attendance_excuse_title">Verzeihung</string>
<!--Attendance summary--> <!--Attendance summary-->

View File

@ -192,7 +192,7 @@
</plurals> </plurals>
<string name="attendance_excuse_dialog_reason">Absence reason (optional)</string> <string name="attendance_excuse_dialog_reason">Absence reason (optional)</string>
<string name="attendance_excuse_dialog_submit">Send</string> <string name="attendance_excuse_dialog_submit">Send</string>
<string name="attendance_excuse_success">Absence excused successfully!</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_no_selection">You must select at least one absence!</string>
<string name="attendance_excuse_title">Excuse</string> <string name="attendance_excuse_title">Excuse</string>
<!--Attendance summary--> <!--Attendance summary-->

View File

@ -192,7 +192,7 @@
</plurals> </plurals>
<string name="attendance_excuse_dialog_reason">Powód nieobecności (opcjonalny)</string> <string name="attendance_excuse_dialog_reason">Powód nieobecności (opcjonalny)</string>
<string name="attendance_excuse_dialog_submit">Wyślij</string> <string name="attendance_excuse_dialog_submit">Wyślij</string>
<string name="attendance_excuse_success">Usprawiedliwiono pomyślnie!</string> <string name="attendance_excuse_success">Prośba o usprawiedliwienie została pomyślnie wysłana!</string>
<string name="attendance_excuse_no_selection">Musisz wybrać co najmniej jedną nieobecność!</string> <string name="attendance_excuse_no_selection">Musisz wybrać co najmniej jedną nieobecność!</string>
<string name="attendance_excuse_title">Usprawiedliw</string> <string name="attendance_excuse_title">Usprawiedliw</string>
<!--Attendance summary--> <!--Attendance summary-->
@ -317,7 +317,7 @@
<string name="lucky_number_history_button">Pokaż historię</string> <string name="lucky_number_history_button">Pokaż historię</string>
<!--Lucky number history--> <!--Lucky number history-->
<string name="lucky_number_history_title">Historia numerków</string> <string name="lucky_number_history_title">Historia numerków</string>
<string name="lucky_number_history_empty">Brak informacji o szczęśliwych numerach</string> <string name="lucky_number_history_empty">Brak informacji o szczęśliwych numerkach</string>
<!--Mobile devices--> <!--Mobile devices-->
<string name="mobile_devices_title">Dostęp mobilny</string> <string name="mobile_devices_title">Dostęp mobilny</string>
<string name="mobile_devices_no_items">Brak urządzeń</string> <string name="mobile_devices_no_items">Brak urządzeń</string>

View File

@ -192,7 +192,7 @@
</plurals> </plurals>
<string name="attendance_excuse_dialog_reason">Причина отсутствия (необязательно)</string> <string name="attendance_excuse_dialog_reason">Причина отсутствия (необязательно)</string>
<string name="attendance_excuse_dialog_submit">Послать</string> <string name="attendance_excuse_dialog_submit">Послать</string>
<string name="attendance_excuse_success">Статус отсутствия изменён</string> <string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
<string name="attendance_excuse_no_selection">Выберите хотя-бы одно отсутствие</string> <string name="attendance_excuse_no_selection">Выберите хотя-бы одно отсутствие</string>
<string name="attendance_excuse_title">Изменить статус</string> <string name="attendance_excuse_title">Изменить статус</string>
<!--Attendance summary--> <!--Attendance summary-->

View File

@ -192,7 +192,7 @@
</plurals> </plurals>
<string name="attendance_excuse_dialog_reason">Dôvod neprítomnosti (voliteľný)</string> <string name="attendance_excuse_dialog_reason">Dôvod neprítomnosti (voliteľný)</string>
<string name="attendance_excuse_dialog_submit">Poslať</string> <string name="attendance_excuse_dialog_submit">Poslať</string>
<string name="attendance_excuse_success">Neprítomnosť úspešne ospravedlnená!</string> <string name="attendance_excuse_success">Žiadosť o ospravedlnenie neprítomnosti bola úspešne odoslaná!</string>
<string name="attendance_excuse_no_selection">Musíte vybrať aspoň jednu neprítomnosť!</string> <string name="attendance_excuse_no_selection">Musíte vybrať aspoň jednu neprítomnosť!</string>
<string name="attendance_excuse_title">Ospravedlniť</string> <string name="attendance_excuse_title">Ospravedlniť</string>
<!--Attendance summary--> <!--Attendance summary-->

View File

@ -192,7 +192,7 @@
</plurals> </plurals>
<string name="attendance_excuse_dialog_reason">Причина відсутності (необов’язково)</string> <string name="attendance_excuse_dialog_reason">Причина відсутності (необов’язково)</string>
<string name="attendance_excuse_dialog_submit">Надіслати</string> <string name="attendance_excuse_dialog_submit">Надіслати</string>
<string name="attendance_excuse_success">Змінено статус відсутності</string> <string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
<string name="attendance_excuse_no_selection">Оберіть хоча б одну відсутність</string> <string name="attendance_excuse_no_selection">Оберіть хоча б одну відсутність</string>
<string name="attendance_excuse_title">Змінити статус</string> <string name="attendance_excuse_title">Змінити статус</string>
<!--Attendance summary--> <!--Attendance summary-->

View File

@ -194,7 +194,7 @@
</plurals> </plurals>
<string name="attendance_excuse_dialog_reason">Absence reason (optional)</string> <string name="attendance_excuse_dialog_reason">Absence reason (optional)</string>
<string name="attendance_excuse_dialog_submit">Send</string> <string name="attendance_excuse_dialog_submit">Send</string>
<string name="attendance_excuse_success">Absence excused successfully!</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_no_selection">You must select at least one absence!</string>
<string name="attendance_excuse_title">Excuse</string> <string name="attendance_excuse_title">Excuse</string>