diff --git a/.circleci/config.yml b/.circleci/config.yml
index 2cb2e147..ce2922ba 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -162,7 +162,7 @@ jobs:
openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks
- run:
name: Publish release
- command: ./gradlew publishPlayRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
+ command: ./gradlew publishPlayRelease --no-daemon --stacktrace --console=plain -PenableCrashlytics -PdisablePreDex
workflows:
version: 2
diff --git a/.github/workflows/deploy-store.yml b/.github/workflows/deploy-store.yml
index 0195f3e5..e8237a38 100644
--- a/.github/workflows/deploy-store.yml
+++ b/.github/workflows/deploy-store.yml
@@ -40,7 +40,7 @@ jobs:
SINGLE_SUPPORT_AD_ID: ${{ secrets.SINGLE_SUPPORT_AD_ID }}
DASHBOARD_TILE_AD_ID: ${{ secrets.DASHBOARD_TILE_AD_ID }}
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
- run: ./gradlew publishPlayReleaseApps --stacktrace;
+ run: ./gradlew publishPlayReleaseApps -PenableFirebase --stacktrace;
deploy-app-gallery:
name: AppGallery
diff --git a/.github/workflows/deploy-test.yml b/.github/workflows/deploy-test.yml
index 42c1f8e7..c4f55e6a 100644
--- a/.github/workflows/deploy-test.yml
+++ b/.github/workflows/deploy-test.yml
@@ -36,7 +36,8 @@ jobs:
- 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/google-services.json
+ 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: |
@@ -130,7 +131,7 @@ jobs:
BITRISE_KEYSTORE_PASSWORD: ${{ secrets.BITRISE_KEYSTORE_PASSWORD }}
BITRISE_KEY_ALIAS: ${{ secrets.BITRISE_KEY_ALIAS }}
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
- run: ./gradlew assemblePlayDebug --stacktrace
+ run: ./gradlew assemblePlayDebug -PenableFirebase --stacktrace
- name: Upload apk to github artifacts
uses: actions/upload-artifact@v3
with:
diff --git a/.gitignore b/.gitignore
index ad83ced8..980085e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,10 +67,6 @@ captures/
.idea/discord.xml
.idea/migrations.xml
.idea/androidTestResultsUserPreferences.xml
-.idea/copilot
-.idea/deploymentTargetDropDown.xml
-.idea/deploymentTargetSelector.xml
-.idea/kotlinc.xml
# Keystore files
*.jks
@@ -117,13 +113,12 @@ Thumbs.db
*.ear
### AndroidStudio Patch ###
+
!/gradle/wrapper/gradle-wrapper.jar
.idea/jarRepositories.xml
-### Services config files
-agconnect-services.json
-agconnect-credentials.json
-google-services.json
-!app/google-services.json
-
+app/src/release/agconnect-services.json
+app/src/release/agconnect-credentials.json
+.idea/deploymentTargetDropDown.xml
+.idea/kotlinc.xml
diff --git a/.travis.yml b/.travis.yml
index e0b0be97..04db3a61 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -61,7 +61,7 @@ script:
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/agconnect-services.json.gpg;
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg;
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg;
- ./gradlew publishPlayRelease --stacktrace;
+ ./gradlew publishPlayRelease -PenableFirebase --stacktrace;
fi
after_success:
diff --git a/app/build.gradle b/app/build.gradle
index d1c67ab0..6f63715b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -27,12 +27,15 @@ android {
testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 21
targetSdkVersion 34
- versionCode 150
- versionName "2.5.1"
+ versionCode 149
+ versionName "2.5.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resValue "string", "app_name", "Wulkanowy"
- manifestPlaceholders = [admob_project_id: ""]
+ manifestPlaceholders = [
+ firebase_enabled: project.hasProperty("enableFirebase"),
+ admob_project_id: ""
+ ]
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "null"
buildConfigField "String", "DASHBOARD_TILE_AD_ID", "null"
@@ -73,6 +76,7 @@ android {
resValue "string", "app_name", "Wulkanowy DEV"
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
+ ext.enableCrashlytics = project.hasProperty("enableFirebase")
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
buildConfigField "String", "SCHOOLS_BASE_URL", '"https://schools.wulkanowy.net.pl"'
}
@@ -160,7 +164,7 @@ play {
defaultToAppBundles = false
track = 'production'
releaseStatus = ReleaseStatus.IN_PROGRESS
- userFraction = 0.50d
+ userFraction = 0.20d
updatePriority = 1
enabled.set(false)
}
@@ -191,7 +195,7 @@ ext {
}
dependencies {
- implementation 'io.github.wulkanowy:sdk:2.5.1'
+ implementation 'io.github.wulkanowy:sdk:2.5.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
@@ -248,13 +252,13 @@ dependencies {
implementation 'com.fredporciuncula:flow-preferences:1.9.1'
implementation 'org.apache.commons:commons-text:1.11.0'
- playImplementation platform('com.google.firebase:firebase-bom:32.7.4')
+ playImplementation platform('com.google.firebase:firebase-bom:32.7.3')
playImplementation 'com.google.firebase:firebase-analytics'
playImplementation 'com.google.firebase:firebase-messaging'
playImplementation 'com.google.firebase:firebase-crashlytics:'
playImplementation 'com.google.firebase:firebase-config'
- playImplementation 'com.google.android.gms:play-services-ads:23.0.0'
+ playImplementation 'com.google.android.gms:play-services-ads:22.6.0'
playImplementation "com.google.android.play:integrity:1.3.0"
playImplementation 'com.google.android.play:app-update-ktx:2.1.0'
playImplementation 'com.google.android.play:review-ktx:2.0.1'
diff --git a/app/play-publish-lint.sh b/app/play-publish-lint.sh
index 5f0391de..d3354b1a 100755
--- a/app/play-publish-lint.sh
+++ b/app/play-publish-lint.sh
@@ -1,8 +1,7 @@
#!/bin/bash -
content=$(cat < "app/src/main/play/release-notes/pl-PL/default.txt") || exit
-content2=echo "$content" | dos2unix
-if [[ "${#content2}" -gt 500 ]]; then
+if [[ "${#content}" -gt 500 ]]; then
echo >&2 "Release notes content has reached the limit of 500 characters"
exit 1
fi
diff --git a/app/src/debug/agconnect-services.json b/app/src/debug/agconnect-services.json
new file mode 100644
index 00000000..52426f54
--- /dev/null
+++ b/app/src/debug/agconnect-services.json
@@ -0,0 +1,92 @@
+{
+ "agcgw": {
+ "backurl": "connect-dre.hispace.hicloud.com",
+ "url": "connect-dre.dbankcloud.cn",
+ "websocketbackurl": "connect-ws-dre.hispace.dbankcloud.com",
+ "websocketurl": "connect-ws-dre.hispace.dbankcloud.cn"
+ },
+ "agcgw_all": {
+ "CN": "connect-drcn.dbankcloud.cn",
+ "CN_back": "connect-drcn.hispace.hicloud.com",
+ "DE": "connect-dre.dbankcloud.cn",
+ "DE_back": "connect-dre.hispace.hicloud.com",
+ "RU": "connect-drru.hispace.dbankcloud.ru",
+ "RU_back": "connect-drru.hispace.dbankcloud.cn",
+ "SG": "connect-dra.dbankcloud.cn",
+ "SG_back": "connect-dra.hispace.hicloud.com"
+ },
+ "websocketgw_all": {
+ "CN": "connect-ws-drcn.hispace.dbankcloud.cn",
+ "CN_back": "connect-ws-drcn.hispace.dbankcloud.com",
+ "DE": "connect-ws-dre.hispace.dbankcloud.cn",
+ "DE_back": "connect-ws-dre.hispace.dbankcloud.com",
+ "RU": "connect-ws-drru.hispace.dbankcloud.ru",
+ "RU_back": "connect-ws-drru.hispace.dbankcloud.cn",
+ "SG": "connect-ws-dra.hispace.dbankcloud.cn",
+ "SG_back": "connect-ws-dra.hispace.dbankcloud.com"
+ },
+ "client": {
+ "cp_id": "890048000024105546",
+ "product_id": "736430079244736562",
+ "client_id": "514530959291319360",
+ "client_secret": "C42522DBF17D3D4BBE9D9C1783A54484B7E6844B388B7A67502D36A633A4186B",
+ "project_id": "736430079244736562",
+ "app_id": "106552551",
+ "api_key": "CgB6e3x9BUNiq+r8ebCHNojjjYsMT4pJSjjNDOkm9owtBb6rVI6LjnASoZBRxbjjhObcrV5gANo99fI/eKZDTbWS",
+ "package_name": "io.github.wulkanowy.dev"
+ },
+ "oauth_client": {
+ "client_id": "106552551",
+ "client_type": 1
+ },
+ "app_info": {
+ "app_id": "106552551",
+ "package_name": "io.github.wulkanowy.dev"
+ },
+ "service": {
+ "analytics": {
+ "collector_url": "datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
+ "collector_url_ru": "datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com",
+ "collector_url_sg": "datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn",
+ "collector_url_de": "datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
+ "collector_url_cn": "datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
+ "resource_id": "p1",
+ "channel_id": ""
+ },
+ "search":{
+ "url":"https://search-dre.cloud.huawei.com"
+ },
+ "cloudstorage": {
+ "storage_url_sg_back": "https://agc-storage-dra.cloud.huawei.asia",
+ "storage_url_ru_back": "https://agc-storage-drru.cloud.huawei.ru",
+ "storage_url_ru": "https://agc-storage-drru.cloud.huawei.ru",
+ "storage_url_de_back": "https://agc-storage-dre.cloud.huawei.eu",
+ "storage_url_de": "https://ops-dre.agcstorage.link",
+ "storage_url": "https://agc-storage-drcn.platform.dbankcloud.cn",
+ "storage_url_sg": "https://ops-dra.agcstorage.link",
+ "storage_url_cn_back": "https://agc-storage-drcn.cloud.huawei.com.cn",
+ "storage_url_cn": "https://agc-storage-drcn.platform.dbankcloud.cn"
+ },
+ "ml": {
+ "mlservice_url": "ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
+ }
+ },
+ "region": "DE",
+ "configuration_version": "3.0",
+ "appInfos": [
+ {
+ "package_name": "io.github.wulkanowy.dev",
+ "client": {
+ "app_id": "106552551"
+ },
+ "app_info": {
+ "package_name": "io.github.wulkanowy.dev",
+ "app_id": "106552551"
+ },
+ "oauth_client": {
+ "client_type": 1,
+ "client_id": "106552551"
+ }
+ }
+ ]
+}
diff --git a/app/google-services.json b/app/src/debug/google-services.json
similarity index 100%
rename from app/google-services.json
rename to app/src/debug/google-services.json
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4e617c93..f43dfdd2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -155,9 +155,33 @@
android:resource="@xml/provider_paths" />
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/io/github/wulkanowy/data/DataModule.kt b/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
index a492c08d..50d6c8f9 100644
--- a/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
@@ -18,13 +18,17 @@ import io.github.wulkanowy.data.api.SchoolsService
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.repositories.PreferencesRepository
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AppInfo
+import io.github.wulkanowy.utils.RemoteConfigHelper
+import io.github.wulkanowy.utils.WebkitCookieManagerProxy
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.create
+import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
@@ -32,6 +36,23 @@ import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
internal class DataModule {
+ @Singleton
+ @Provides
+ fun provideSdk(
+ chuckerInterceptor: ChuckerInterceptor,
+ remoteConfig: RemoteConfigHelper,
+ webkitCookieManagerProxy: WebkitCookieManagerProxy,
+ ) = Sdk().apply {
+ androidVersion = android.os.Build.VERSION.RELEASE
+ buildTag = android.os.Build.MODEL
+ userAgentTemplate = remoteConfig.userAgentTemplate
+ setSimpleHttpLogger { Timber.d(it) }
+ setAdditionalCookieManager(webkitCookieManagerProxy)
+
+ // for debug only
+ addInterceptor(chuckerInterceptor, network = true)
+ }
+
@Singleton
@Provides
fun provideChuckerCollector(
diff --git a/app/src/main/java/io/github/wulkanowy/data/Resource.kt b/app/src/main/java/io/github/wulkanowy/data/Resource.kt
index 712a946f..108b0d58 100644
--- a/app/src/main/java/io/github/wulkanowy/data/Resource.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/Resource.kt
@@ -1,17 +1,11 @@
package io.github.wulkanowy.data
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
@@ -20,39 +14,16 @@ import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import timber.log.Timber
-import kotlin.time.Duration
-import kotlin.time.Duration.Companion.seconds
-sealed interface Resource {
- /**
- * The initial value of a resource flow. Indicates no data that is currently available to be shown,
- * however with the expectation that the state will transition to another one soon.
- */
- open class Loading : Resource
+sealed class Resource {
+
+ open class Loading : Resource()
- /**
- * A semi-loading state with some data available to be displayed (usually cached data loaded from
- * the database). Still not the target state and it's expected to transition into another one soon.
- */
data class Intermediate(val data: T) : Loading()
- /**
- * The happy-path target state. Data can either be:
- * - loaded from the database - while it may seem like this case is already handled by the
- * Intermediate state, the difference here is semantic. Cached data is returned as Intermediate
- * when there's a API request in progress (or soon expected to be), however when there is no
- * intention of immediately querying the API, the cached data is returned as a Success.
- * - fetched from the API.
- */
- data class Success(val data: T) : Resource
+ data class Success(val data: T) : Resource()
- /**
- * Something bad happened and we were unable to get the requested data. This can be caused by
- * a database error, a network error, or really just any other error. Upon receiving this state
- * the UI can either: display a full screen error, or, when it has received any data previously,
- * display a snack bar informing of the problem.
- */
- data class Error(val error: Throwable) : Resource
+ data class Error(val error: Throwable) : Resource()
}
val Resource.dataOrNull: T?
@@ -93,22 +64,6 @@ fun Resource.mapData(block: (T) -> U) = when (this) {
is Resource.Error -> Resource.Error(this.error)
}
-/**
- * Injects another flow into this flow's resource data.
- */
-inline fun Flow>.combineWithResourceData(
- flow: Flow,
- crossinline block: suspend (T1, T2) -> R
-): Flow> =
- combine(flow) { resource, inject ->
- when (resource) {
- is Resource.Success -> Resource.Success(block(resource.data, inject))
- is Resource.Intermediate -> Resource.Intermediate(block(resource.data, inject))
- is Resource.Loading -> Resource.Loading()
- is Resource.Error -> Resource.Error(resource.error)
- }
- }
-
fun Flow>.logResourceStatus(name: String, showData: Boolean = false) = onEach {
val description = when (it) {
is Resource.Intermediate -> "intermediate data received" + if (showData) " (data: `${it.data}`)" else ""
@@ -119,29 +74,8 @@ fun Flow>.logResourceStatus(name: String, showData: Boolean = fa
Timber.i("$name: $description")
}
-inline fun Flow>.mapResourceData(crossinline block: suspend (T) -> U) = map {
- when (it) {
- is Resource.Success -> Resource.Success(block(it.data))
- is Resource.Intermediate -> Resource.Intermediate(block(it.data))
- is Resource.Loading -> Resource.Loading()
- is Resource.Error -> Resource.Error(it.error)
- }
-}
-
-@OptIn(ExperimentalCoroutinesApi::class)
-fun Flow>.flatMapResourceData(
- inheritIntermediate: Boolean = true, block: suspend (T) -> Flow>
-) = flatMapLatest {
- when (it) {
- is Resource.Success -> block(it.data)
- is Resource.Intermediate -> block(it.data).map { newRes ->
- if (inheritIntermediate && newRes is Resource.Success) Resource.Intermediate(newRes.data)
- else newRes
- }
-
- is Resource.Loading -> flowOf(Resource.Loading())
- is Resource.Error -> flowOf(Resource.Error(it.error))
- }
+fun Flow>.mapResourceData(block: (T) -> U) = map {
+ it.mapData(block)
}
fun Flow>.onResourceData(block: suspend (T) -> Unit) = onEach {
@@ -171,13 +105,13 @@ fun Flow>.onResourceSuccess(block: suspend (T) -> Unit) = onEach
}
}
-fun Flow>.onResourceError(block: suspend (Throwable) -> Unit) = onEach {
+fun Flow>.onResourceError(block: (Throwable) -> Unit) = onEach {
if (it is Resource.Error) {
block(it.error)
}
}
-fun Flow>.onResourceNotLoading(block: suspend () -> Unit) = onEach {
+fun Flow>.onResourceNotLoading(block: () -> Unit) = onEach {
if (it !is Resource.Loading) {
block()
}
@@ -187,99 +121,70 @@ suspend fun Flow>.toFirstResult() = filter { it !is Resource.Loa
suspend fun Flow>.waitForResult() = takeWhile { it is Resource.Loading }.collect()
-// Can cause excessive amounts of `Resource.Intermediate` to be emitted. Unless that is desired,
-// use `debounceIntermediates` to alleviate this behavior.
-inline fun combineResourceFlows(flows: Iterable>>): Flow>> =
- combine(flows) { items ->
- var isIntermediate = false
- val data = mutableListOf()
- for (item in items) {
- when (item) {
- is Resource.Success -> data.add(item.data)
- is Resource.Intermediate -> {
- isIntermediate = true
- data.add(item.data)
- }
-
- is Resource.Loading -> return@combine Resource.Loading()
- is Resource.Error -> continue
- }
- }
- if (data.isEmpty()) {
- // All items have to be errors for this to happen, so just return the first one.
- // mapData is functionally useless and exists only to satisfy the type checker
- items.first().mapData { listOf(it) }
- } else if (isIntermediate) {
- Resource.Intermediate(data)
- } else {
- Resource.Success(data)
- }
- }
-
-@OptIn(FlowPreview::class)
-fun Flow>.debounceIntermediates(timeout: Duration = 5.seconds) = flow {
- var wasIntermediate = false
-
- emitAll(this@debounceIntermediates.debounce {
- if (it is Resource.Intermediate) {
- if (!wasIntermediate) {
- wasIntermediate = true
- Duration.ZERO
- } else {
- timeout
- }
- } else {
- wasIntermediate = false
- Duration.ZERO
- }
- })
-}
-
-
-inline fun networkBoundResource(
+inline fun networkBoundResource(
mutex: Mutex = Mutex(),
- crossinline isResultEmpty: (OutputType) -> Boolean,
- crossinline query: () -> Flow,
- crossinline fetch: suspend () -> ApiType,
- crossinline saveFetchResult: suspend (old: OutputType, new: ApiType) -> Unit,
- crossinline shouldFetch: (OutputType) -> Boolean = { true },
- crossinline filterResult: (OutputType) -> OutputType = { it }
-) = networkBoundResource(
- mutex = mutex,
- isResultEmpty = isResultEmpty,
- query = query,
- fetch = fetch,
- saveFetchResult = saveFetchResult,
- shouldFetch = shouldFetch,
- mapResult = filterResult
-)
-
-@JvmName("networkBoundResourceWithMap")
-inline fun networkBoundResource(
- mutex: Mutex = Mutex(),
- crossinline isResultEmpty: (OutputType) -> Boolean,
- crossinline query: () -> Flow,
- crossinline fetch: suspend () -> ApiType,
- crossinline saveFetchResult: suspend (old: DatabaseType, new: ApiType) -> Unit,
- crossinline shouldFetch: (DatabaseType) -> Boolean = { true },
- crossinline mapResult: (DatabaseType) -> OutputType,
+ showSavedOnLoading: Boolean = true,
+ crossinline isResultEmpty: (ResultType) -> Boolean,
+ crossinline query: () -> Flow,
+ crossinline fetch: suspend (ResultType) -> RequestType,
+ crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit,
+ crossinline onFetchFailed: (Throwable) -> Unit = { },
+ crossinline shouldFetch: (ResultType) -> Boolean = { true },
+ crossinline filterResult: (ResultType) -> ResultType = { it }
) = flow {
emit(Resource.Loading())
val data = query().first()
- if (shouldFetch(data)) {
- emit(Resource.Intermediate(data))
+ emitAll(if (shouldFetch(data)) {
+ val filteredResult = filterResult(data)
+
+ if (showSavedOnLoading && !isResultEmpty(filteredResult)) {
+ emit(Resource.Intermediate(filteredResult))
+ }
try {
- val newData = fetch()
+ val newData = fetch(data)
mutex.withLock { saveFetchResult(query().first(), newData) }
+ query().map { Resource.Success(filterResult(it)) }
} catch (throwable: Throwable) {
- emit(Resource.Error(throwable))
- return@flow
+ onFetchFailed(throwable)
+ flowOf(Resource.Error(throwable))
}
- }
-
- emitAll(query().map { Resource.Success(it) })
+ } else {
+ query().map { Resource.Success(filterResult(it)) }
+ })
+}
+
+@JvmName("networkBoundResourceWithMap")
+inline fun networkBoundResource(
+ mutex: Mutex = Mutex(),
+ showSavedOnLoading: Boolean = true,
+ crossinline isResultEmpty: (T) -> Boolean,
+ crossinline query: () -> Flow,
+ crossinline fetch: suspend (ResultType) -> RequestType,
+ crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit,
+ crossinline onFetchFailed: (Throwable) -> Unit = { },
+ crossinline shouldFetch: (ResultType) -> Boolean = { true },
+ crossinline mapResult: (ResultType) -> T,
+) = flow {
+ emit(Resource.Loading())
+
+ val data = query().first()
+ emitAll(if (shouldFetch(data)) {
+ val mappedResult = mapResult(data)
+
+ if (showSavedOnLoading && !isResultEmpty(mappedResult)) {
+ emit(Resource.Intermediate(mappedResult))
+ }
+ try {
+ val newData = fetch(data)
+ mutex.withLock { saveFetchResult(query().first(), newData) }
+ query().map { Resource.Success(mapResult(it)) }
+ } catch (throwable: Throwable) {
+ onFetchFailed(throwable)
+ flowOf(Resource.Error(throwable))
+ }
+ } else {
+ query().map { Resource.Success(mapResult(it)) }
+ })
}
- .mapResourceData { mapResult(it) }
- .filterNot { it is Resource.Intermediate && isResultEmpty(it.data) }
diff --git a/app/src/main/java/io/github/wulkanowy/data/WulkanowySdkFactory.kt b/app/src/main/java/io/github/wulkanowy/data/WulkanowySdkFactory.kt
deleted file mode 100644
index 6d4f9eda..00000000
--- a/app/src/main/java/io/github/wulkanowy/data/WulkanowySdkFactory.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package io.github.wulkanowy.data
-
-import com.chuckerteam.chucker.api.ChuckerInterceptor
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.RemoteConfigHelper
-import io.github.wulkanowy.utils.WebkitCookieManagerProxy
-import timber.log.Timber
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class WulkanowySdkFactory @Inject constructor(
- private val chuckerInterceptor: ChuckerInterceptor,
- private val remoteConfig: RemoteConfigHelper,
- private val webkitCookieManagerProxy: WebkitCookieManagerProxy
-) {
-
- private val sdk = Sdk().apply {
- androidVersion = android.os.Build.VERSION.RELEASE
- buildTag = android.os.Build.MODEL
- userAgentTemplate = remoteConfig.userAgentTemplate
- setSimpleHttpLogger { Timber.d(it) }
- setAdditionalCookieManager(webkitCookieManagerProxy)
-
- // for debug only
- addInterceptor(chuckerInterceptor, network = true)
- }
-
- fun create() = sdk
-
- fun create(student: Student, semester: Semester? = null): Sdk {
- return create().apply {
- email = student.email
- password = student.password
- symbol = student.symbol
- schoolSymbol = student.schoolSymbol
- studentId = student.studentId
- classId = student.classId
- emptyCookieJarInterceptor = true
-
- if (Sdk.Mode.valueOf(student.loginMode) == Sdk.Mode.HEBE) {
- mobileBaseUrl = student.mobileBaseUrl
- } else {
- scrapperBaseUrl = student.scrapperBaseUrl
- domainSuffix = student.scrapperDomainSuffix
- loginType = Sdk.ScrapperLoginType.valueOf(student.loginType)
- }
-
- mode = Sdk.Mode.valueOf(student.loginMode)
- mobileBaseUrl = student.mobileBaseUrl
- keyId = student.certificateKey
- privatePem = student.privateKey
-
- if (semester != null) {
- diaryId = semester.diaryId
- kindergartenDiaryId = semester.kindergartenDiaryId
- schoolYear = semester.schoolYear
- unitId = semester.unitId
- }
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/AttendanceCalculatorSortingMode.kt b/app/src/main/java/io/github/wulkanowy/data/enums/AttendanceCalculatorSortingMode.kt
deleted file mode 100644
index 77dd5fc4..00000000
--- a/app/src/main/java/io/github/wulkanowy/data/enums/AttendanceCalculatorSortingMode.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package io.github.wulkanowy.data.enums
-
-enum class AttendanceCalculatorSortingMode(private val value: String) {
- ALPHABETIC("alphabetic"),
- ATTENDANCE("attendance_percentage"),
- LESSON_BALANCE("lesson_balance");
-
- companion object {
- fun getByValue(value: String) =
- AttendanceCalculatorSortingMode.values()
- .find { it.value == value } ?: ALPHABETIC
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/AttendanceData.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/AttendanceData.kt
deleted file mode 100644
index 5810363c..00000000
--- a/app/src/main/java/io/github/wulkanowy/data/pojos/AttendanceData.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package io.github.wulkanowy.data.pojos
-
-data class AttendanceData(
- val subjectName: String,
- val lessonBalance: Int,
- val presences: Int,
- val absences: Int,
-) {
- val total: Int
- get() = presences + absences
-
- val presencePercentage: Double
- get() = if (total == 0) 0.0 else (presences.toDouble() / total) * 100
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AdminMessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AdminMessageRepository.kt
index aa0022b0..b831ee75 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/AdminMessageRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AdminMessageRepository.kt
@@ -6,7 +6,6 @@ import io.github.wulkanowy.data.db.dao.AdminMessageDao
import io.github.wulkanowy.data.db.entities.AdminMessage
import io.github.wulkanowy.data.networkBoundResource
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.sync.Mutex
import javax.inject.Inject
import javax.inject.Singleton
@@ -29,6 +28,6 @@ class AdminMessageRepository @Inject constructor(
saveFetchResult = { oldItems, newItems ->
adminMessageDao.removeOldAndSaveNew(oldItems, newItems)
},
+ showSavedOnLoading = false,
)
- .filterNot { it is Resource.Intermediate }
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt
index 9b94cc10..46ea29f8 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.AttendanceDao
import io.github.wulkanowy.data.db.dao.TimetableDao
import io.github.wulkanowy.data.db.entities.Attendance
@@ -8,11 +7,14 @@ import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Absent
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.sunday
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex
@@ -26,7 +28,7 @@ import javax.inject.Singleton
class AttendanceRepository @Inject constructor(
private val attendanceDb: AttendanceDao,
private val timetableDb: TimetableDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -57,7 +59,8 @@ class AttendanceRepository @Inject constructor(
val lessons = timetableDb.load(
semester.diaryId, semester.studentId, start.monday, end.sunday
)
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getAttendance(start.monday, end.sunday)
.mapToEntities(semester, lessons)
},
@@ -87,10 +90,8 @@ class AttendanceRepository @Inject constructor(
}
suspend fun excuseForAbsence(
- student: Student,
- semester: Semester,
- absenceList: List,
- reason: String? = null
+ student: Student, semester: Semester,
+ absenceList: List, reason: String? = null
) {
val items = absenceList.map { attendance ->
Absent(
@@ -98,7 +99,8 @@ class AttendanceRepository @Inject constructor(
timeId = attendance.timeId
)
}
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.excuseForAbsence(items, reason)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt
index 78c98169..c6cfc2f6 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt
@@ -1,15 +1,17 @@
package io.github.wulkanowy.data.repositories
import androidx.room.withTransaction
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.sync.Mutex
import javax.inject.Inject
@@ -18,9 +20,9 @@ import javax.inject.Singleton
@Singleton
class AttendanceSummaryRepository @Inject constructor(
private val attendanceDb: AttendanceSummaryDao,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
private val appDatabase: AppDatabase,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
) {
private val saveFetchResultMutex = Mutex()
@@ -41,7 +43,8 @@ class AttendanceSummaryRepository @Inject constructor(
},
query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getAttendanceSummary(subjectId)
.mapToEntities(semester, subjectId)
},
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt
index 45a36f55..f7f86b23 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt
@@ -1,15 +1,17 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.sunday
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.sync.Mutex
import java.time.LocalDate
@@ -19,7 +21,7 @@ import javax.inject.Singleton
@Singleton
class CompletedLessonsRepository @Inject constructor(
private val completedLessonsDb: CompletedLessonsDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -51,7 +53,8 @@ class CompletedLessonsRepository @Inject constructor(
)
},
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getCompletedLessons(start.monday, end.sunday)
.mapToEntities(semester)
},
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt
index 58ce0091..fbe57860 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt
@@ -1,14 +1,16 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.ConferenceDao
import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex
@@ -19,7 +21,7 @@ import javax.inject.Singleton
@Singleton
class ConferenceRepository @Inject constructor(
private val conferenceDb: ConferenceDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -44,7 +46,8 @@ class ConferenceRepository @Inject constructor(
conferenceDb.loadAll(semester.diaryId, student.studentId, startDate)
},
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getConferences()
.mapToEntities(semester)
.filter { it.date >= startDate }
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt
index 89dbcd5c..9b8dd02e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt
@@ -1,16 +1,18 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.ExamDao
import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.endExamsDay
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.startExamsDay
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex
@@ -21,7 +23,7 @@ import javax.inject.Singleton
@Singleton
class ExamRepository @Inject constructor(
private val examDb: ExamDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -54,7 +56,8 @@ class ExamRepository @Inject constructor(
)
},
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getExams(start.startExamsDay, start.endExamsDay)
.mapToEntities(semester)
},
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt
index e899f900..ac1ef541 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.GradeDao
import io.github.wulkanowy.data.db.dao.GradeDescriptiveDao
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
@@ -11,8 +10,11 @@ import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.toLocalDate
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
@@ -28,7 +30,7 @@ class GradeRepository @Inject constructor(
private val gradeDb: GradeDao,
private val gradeSummaryDb: GradeSummaryDao,
private val gradeDescriptiveDb: GradeDescriptiveDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -61,7 +63,8 @@ class GradeRepository @Inject constructor(
}
},
fetch = {
- val (details, summary, descriptive) = wulkanowySdkFactory.create(student, semester)
+ val (details, summary, descriptive) = sdk.init(student)
+ .switchSemester(semester)
.getGrades(semester.semesterId)
Triple(
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt
index f120d34f..809f92d3 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao
@@ -13,8 +12,11 @@ import io.github.wulkanowy.data.mappers.mapPointsToStatisticsItems
import io.github.wulkanowy.data.mappers.mapSemesterToStatisticItems
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.sync.Mutex
import java.util.Locale
@@ -26,7 +28,7 @@ class GradeStatisticsRepository @Inject constructor(
private val gradePartialStatisticsDb: GradePartialStatisticsDao,
private val gradePointsStatisticsDb: GradePointsStatisticsDao,
private val gradeSemesterStatisticsDb: GradeSemesterStatisticsDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -54,7 +56,8 @@ class GradeStatisticsRepository @Inject constructor(
},
query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getGradesPartialStatistics(semester.semesterId)
.mapToEntities(semester)
},
@@ -101,7 +104,8 @@ class GradeStatisticsRepository @Inject constructor(
},
query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getGradesSemesterStatistics(semester.semesterId)
.mapToEntities(semester)
},
@@ -159,7 +163,8 @@ class GradeStatisticsRepository @Inject constructor(
},
query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getGradesPointsStatistics(semester.semesterId)
.mapToEntities(semester)
},
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt
index 7893ef63..1a9c7ffa 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt
@@ -1,16 +1,18 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.HomeworkDao
import io.github.wulkanowy.data.db.entities.Homework
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.sunday
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.sync.Mutex
import java.time.LocalDate
@@ -20,7 +22,7 @@ import javax.inject.Singleton
@Singleton
class HomeworkRepository @Inject constructor(
private val homeworkDb: HomeworkDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -53,7 +55,8 @@ class HomeworkRepository @Inject constructor(
)
},
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getHomework(start.monday, end.sunday)
.mapToEntities(semester)
},
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt
index 3636cb51..45b7f6e2 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt
@@ -1,11 +1,12 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntity
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.init
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.sync.Mutex
@@ -17,7 +18,7 @@ import javax.inject.Singleton
@Singleton
class LuckyNumberRepository @Inject constructor(
private val luckyNumberDb: LuckyNumberDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
) {
private val saveFetchResultMutex = Mutex()
@@ -32,9 +33,7 @@ class LuckyNumberRepository @Inject constructor(
shouldFetch = { it == null || forceRefresh },
query = { luckyNumberDb.load(student.studentId, now()) },
fetch = {
- wulkanowySdkFactory.create(student)
- .getLuckyNumber(student.schoolShortName)
- ?.mapToEntity(student)
+ sdk.init(student).getLuckyNumber(student.schoolShortName)?.mapToEntity(student)
},
saveFetchResult = { oldLuckyNumber, newLuckyNumber ->
newLuckyNumber ?: return@networkBoundResource
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
index f91dc63e..a4517760 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
@@ -4,7 +4,6 @@ import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.R
import io.github.wulkanowy.data.Resource
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.db.dao.MailboxDao
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
@@ -30,9 +29,11 @@ import io.github.wulkanowy.data.pojos.MessageDraft
import io.github.wulkanowy.data.toFirstResult
import io.github.wulkanowy.data.waitForResult
import io.github.wulkanowy.domain.messages.GetMailboxByStudentUseCase
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Folder
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex
@@ -47,7 +48,7 @@ class MessageRepository @Inject constructor(
private val messagesDb: MessagesDao,
private val mutedMessageSendersDao: MutedMessageSendersDao,
private val messageAttachmentDao: MessageAttachmentDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
@ApplicationContext private val context: Context,
private val refreshHelper: AutoRefreshHelper,
private val sharedPrefProvider: SharedPrefProvider,
@@ -81,16 +82,10 @@ class MessageRepository @Inject constructor(
} else messagesDb.loadMessagesWithMutedAuthor(mailbox.globalKey, folder.id)
},
fetch = {
- wulkanowySdkFactory.create(student)
- .getMessages(
- folder = Folder.valueOf(folder.name),
- mailboxKey = mailbox?.globalKey,
- )
- .mapToEntities(
- student = student,
- mailbox = mailbox,
- allMailboxes = mailboxDao.loadAll(student.email)
- )
+ sdk.init(student).getMessages(
+ folder = Folder.valueOf(folder.name),
+ mailboxKey = mailbox?.globalKey,
+ ).mapToEntities(student, mailbox, mailboxDao.loadAll(student.email))
},
saveFetchResult = { oldWithAuthors, new ->
val old = oldWithAuthors.map { it.message }
@@ -120,11 +115,10 @@ class MessageRepository @Inject constructor(
},
query = { messagesDb.loadMessageWithAttachment(message.messageGlobalKey) },
fetch = {
- wulkanowySdkFactory.create(student)
- .getMessageDetails(
- messageKey = message.messageGlobalKey,
- markAsRead = message.unread && markAsRead,
- )
+ sdk.init(student).getMessageDetails(
+ messageKey = it!!.message.messageGlobalKey,
+ markAsRead = message.unread && markAsRead,
+ )
},
saveFetchResult = { old, new ->
checkNotNull(old) { "Fetched message no longer exist!" }
@@ -165,19 +159,19 @@ class MessageRepository @Inject constructor(
recipients: List,
mailbox: Mailbox,
) {
- wulkanowySdkFactory.create(student)
- .sendMessage(
- subject = subject,
- content = content,
- recipients = recipients.mapFromEntities(),
- mailboxId = mailbox.globalKey,
- )
+ sdk.init(student).sendMessage(
+ subject = subject,
+ content = content,
+ recipients = recipients.mapFromEntities(),
+ mailboxId = mailbox.globalKey,
+ )
refreshFolders(student, mailbox, listOf(SENT))
}
suspend fun restoreMessages(student: Student, mailbox: Mailbox?, messages: List) {
- wulkanowySdkFactory.create(student)
- .restoreMessages(messages = messages.map { it.messageGlobalKey })
+ sdk.init(student).restoreMessages(
+ messages = messages.map { it.messageGlobalKey },
+ )
refreshFolders(student, mailbox)
}
@@ -188,11 +182,10 @@ class MessageRepository @Inject constructor(
suspend fun deleteMessages(student: Student, messages: List) {
val firstMessage = messages.first()
- wulkanowySdkFactory.create(student)
- .deleteMessages(
- messages = messages.map { it.messageGlobalKey },
- removeForever = firstMessage.folderId == TRASHED.id,
- )
+ sdk.init(student).deleteMessages(
+ messages = messages.map { it.messageGlobalKey },
+ removeForever = firstMessage.folderId == TRASHED.id,
+ )
if (firstMessage.folderId != TRASHED.id) {
val deletedMessages = messages.map {
@@ -237,9 +230,7 @@ class MessageRepository @Inject constructor(
},
query = { mailboxDao.loadAll(student.email, student.symbol, student.schoolSymbol) },
fetch = {
- wulkanowySdkFactory.create(student)
- .getMailboxes()
- .mapToEntities(student)
+ sdk.init(student).getMailboxes().mapToEntities(student)
},
saveFetchResult = { old, new ->
mailboxDao.deleteAll(old uniqueSubtract new)
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt
index 19466554..48b4fc28 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
import io.github.wulkanowy.data.db.entities.MobileDevice
import io.github.wulkanowy.data.db.entities.Semester
@@ -9,8 +8,11 @@ import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.mappers.mapToMobileDeviceToken
import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.data.pojos.MobileDeviceToken
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.sync.Mutex
import javax.inject.Inject
@@ -19,7 +21,7 @@ import javax.inject.Singleton
@Singleton
class MobileDeviceRepository @Inject constructor(
private val mobileDb: MobileDeviceDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -40,7 +42,8 @@ class MobileDeviceRepository @Inject constructor(
},
query = { mobileDb.loadAll(student.userLoginId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getRegisteredDevices()
.mapToEntities(student)
},
@@ -54,14 +57,16 @@ class MobileDeviceRepository @Inject constructor(
)
suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.unregisterDevice(device.deviceId)
mobileDb.deleteAll(listOf(device))
}
suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken {
- return wulkanowySdkFactory.create(student, semester)
+ return sdk.init(student)
+ .switchSemester(semester)
.getToken()
.mapToMobileDeviceToken()
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt
index 9551e01e..feb92c15 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt
@@ -1,14 +1,16 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.NoteDao
import io.github.wulkanowy.data.db.entities.Note
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.toLocalDate
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
@@ -19,7 +21,7 @@ import javax.inject.Singleton
@Singleton
class NoteRepository @Inject constructor(
private val noteDb: NoteDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -43,7 +45,8 @@ class NoteRepository @Inject constructor(
},
query = { noteDb.loadAll(student.studentId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getNotes()
.mapToEntities(semester)
},
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt
index 2bb1538c..64e60a60 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt
@@ -10,7 +10,6 @@ import com.fredporciuncula.flow.preferences.Serializer
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.R
import io.github.wulkanowy.data.enums.AppTheme
-import io.github.wulkanowy.data.enums.AttendanceCalculatorSortingMode
import io.github.wulkanowy.data.enums.GradeColorTheme
import io.github.wulkanowy.data.enums.GradeExpandMode
import io.github.wulkanowy.data.enums.GradeSortingMode
@@ -42,27 +41,6 @@ class PreferencesRepository @Inject constructor(
R.bool.pref_default_attendance_present
)
- val targetAttendanceFlow: Flow
- get() = flowSharedPref.getInt(
- context.getString(R.string.pref_key_attendance_target),
- context.resources.getInteger(R.integer.pref_default_attendance_target)
- ).asFlow()
-
- val attendanceCalculatorSortingModeFlow: Flow
- get() = flowSharedPref.getString(
- context.getString(R.string.pref_key_attendance_calculator_sorting_mode),
- context.resources.getString(R.string.pref_default_attendance_calculator_sorting_mode)
- ).asFlow().map(AttendanceCalculatorSortingMode::getByValue)
-
- /**
- * Subjects are empty when they don't have any attendances (total = 0, attendances = 0, absences = 0).
- */
- val attendanceCalculatorShowEmptySubjects: Flow
- get() = flowSharedPref.getBoolean(
- context.getString(R.string.pref_key_attendance_calculator_show_empty_subjects),
- context.resources.getBoolean(R.bool.pref_default_attendance_calculator_show_empty_subjects)
- ).asFlow()
-
private val gradeAverageModePref: Preference
get() = getObjectFlow(
R.string.pref_key_grade_average_mode,
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt
index 8233d932..4a1474ce 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.RecipientDao
import io.github.wulkanowy.data.db.entities.Mailbox
import io.github.wulkanowy.data.db.entities.MailboxType
@@ -8,8 +7,10 @@ import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.uniqueSubtract
import javax.inject.Inject
import javax.inject.Singleton
@@ -17,15 +18,14 @@ import javax.inject.Singleton
@Singleton
class RecipientRepository @Inject constructor(
private val recipientDb: RecipientDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
private val cacheKey = "recipient"
suspend fun refreshRecipients(student: Student, mailbox: Mailbox, type: MailboxType) {
- val new = wulkanowySdkFactory.create(student)
- .getRecipients(mailbox.globalKey)
+ val new = sdk.init(student).getRecipients(mailbox.globalKey)
.mapToEntities(mailbox.globalKey)
val old = recipientDb.loadAll(type, mailbox.globalKey)
@@ -60,7 +60,7 @@ class RecipientRepository @Inject constructor(
): List {
mailbox ?: return emptyList()
- return wulkanowySdkFactory.create(student)
+ return sdk.init(student)
.getMessageReplayDetails(message.messageGlobalKey)
.sender
.let(::listOf)
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt
index b554bda0..5940f477 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt
@@ -1,23 +1,17 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
+import io.github.wulkanowy.sdk.Sdk
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
-class RecoverRepository @Inject constructor(
- private val wulkanowySdkFactory: WulkanowySdkFactory
-) {
+class RecoverRepository @Inject constructor(private val sdk: Sdk) {
- suspend fun getReCaptchaSiteKey(host: String, symbol: String): Pair =
- wulkanowySdkFactory.create()
- .getPasswordResetCaptchaCode(host, symbol)
+ suspend fun getReCaptchaSiteKey(host: String, symbol: String): Pair {
+ return sdk.getPasswordResetCaptchaCode(host, symbol)
+ }
suspend fun sendRecoverRequest(
- url: String,
- symbol: String,
- email: String,
- reCaptchaResponse: String
- ): String = wulkanowySdkFactory.create()
- .sendPasswordResetRequest(url, symbol, email, reCaptchaResponse)
+ url: String, symbol: String, email: String, reCaptchaResponse: String
+ ): String = sdk.sendPasswordResetRequest(url, symbol, email, reCaptchaResponse)
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolAnnouncementRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolAnnouncementRepository.kt
index 6a04ce75..f09a46aa 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolAnnouncementRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolAnnouncementRepository.kt
@@ -1,13 +1,14 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.SchoolAnnouncementDao
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex
@@ -17,7 +18,7 @@ import javax.inject.Singleton
@Singleton
class SchoolAnnouncementRepository @Inject constructor(
private val schoolAnnouncementDb: SchoolAnnouncementDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -40,7 +41,7 @@ class SchoolAnnouncementRepository @Inject constructor(
schoolAnnouncementDb.loadAll(student.userLoginId)
},
fetch = {
- val sdk = wulkanowySdkFactory.create(student)
+ val sdk = sdk.init(student)
val lastAnnouncements = sdk.getLastAnnouncements().mapToEntities(student)
val directorInformation = sdk.getDirectorInformation().mapToEntities(student)
lastAnnouncements + directorInformation
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt
index c48abb6f..b42b4d57 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt
@@ -1,13 +1,15 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.SchoolDao
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntity
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import kotlinx.coroutines.sync.Mutex
import javax.inject.Inject
import javax.inject.Singleton
@@ -15,7 +17,7 @@ import javax.inject.Singleton
@Singleton
class SchoolRepository @Inject constructor(
private val schoolDb: SchoolDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -38,7 +40,8 @@ class SchoolRepository @Inject constructor(
},
query = { schoolDb.load(semester.studentId, semester.classId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getSchool()
.mapToEntity(semester)
},
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolsRepository.kt
index 4a16d6f1..216a8c11 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolsRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolsRepository.kt
@@ -1,15 +1,17 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.api.SchoolsService
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.pojos.IntegrityRequest
import io.github.wulkanowy.data.pojos.LoginEvent
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.utils.IntegrityHelper
import io.github.wulkanowy.utils.getCurrentOrLast
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import kotlinx.coroutines.withTimeout
import timber.log.Timber
import java.util.UUID
@@ -21,7 +23,7 @@ import kotlin.time.Duration.Companion.seconds
class SchoolsRepository @Inject constructor(
private val integrityHelper: IntegrityHelper,
private val schoolsService: SchoolsService,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
) {
suspend fun logSchoolLogin(loginData: LoginData, students: List) {
@@ -38,9 +40,10 @@ class SchoolsRepository @Inject constructor(
private suspend fun logLogin(loginData: LoginData, student: Student, semester: Semester) {
val requestId = UUID.randomUUID().toString()
val token = integrityHelper.getIntegrityToken(requestId) ?: return
- val updatedStudent = student.copy(password = loginData.password)
- val schoolInfo = wulkanowySdkFactory.create(updatedStudent, semester)
+ val schoolInfo = sdk
+ .init(student.copy(password = loginData.password))
+ .switchSemester(semester)
.getSchool()
schoolsService.logLoginEvent(
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt
index da21f59a..9ae22bab 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.SemesterDao
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
@@ -8,6 +7,7 @@ import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.DispatchersProvider
import io.github.wulkanowy.utils.getCurrentOrLast
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.isCurrent
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.withContext
@@ -18,7 +18,7 @@ import javax.inject.Singleton
@Singleton
class SemesterRepository @Inject constructor(
private val semesterDb: SemesterDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val dispatchers: DispatchersProvider,
) {
@@ -60,10 +60,7 @@ class SemesterRepository @Inject constructor(
}
private suspend fun refreshSemesters(student: Student) {
- val new = wulkanowySdkFactory.create(student)
- .getSemesters()
- .mapToEntities(student.studentId)
-
+ val new = sdk.init(student).getSemesters().mapToEntities(student.studentId)
if (new.isEmpty()) return Timber.i("Empty semester list!")
val old = semesterDb.loadAll(student.studentId, student.classId)
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt
index db4c0aeb..d42be180 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt
@@ -1,11 +1,13 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.StudentInfoDao
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntity
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import kotlinx.coroutines.sync.Mutex
import javax.inject.Inject
import javax.inject.Singleton
@@ -13,7 +15,7 @@ import javax.inject.Singleton
@Singleton
class StudentInfoRepository @Inject constructor(
private val studentInfoDao: StudentInfoDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
) {
private val saveFetchResultMutex = Mutex()
@@ -28,9 +30,9 @@ class StudentInfoRepository @Inject constructor(
shouldFetch = { it == null || forceRefresh },
query = { studentInfoDao.loadStudentInfo(student.studentId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
- .getStudentInfo()
- .mapToEntity(semester)
+ sdk.init(student)
+ .switchSemester(semester)
+ .getStudentInfo().mapToEntity(semester)
},
saveFetchResult = { old, new ->
if (old != null && new != old) {
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt
index 9a5ecd53..e063840c 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt
@@ -1,7 +1,6 @@
package io.github.wulkanowy.data.repositories
import androidx.room.withTransaction
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.dao.SemesterDao
import io.github.wulkanowy.data.db.dao.StudentDao
@@ -15,7 +14,9 @@ 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.DispatchersProvider
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.security.Scrambler
+import io.github.wulkanowy.utils.switchSemester
import kotlinx.coroutines.withContext
import javax.inject.Inject
import javax.inject.Singleton
@@ -25,7 +26,7 @@ class StudentRepository @Inject constructor(
private val dispatchers: DispatchersProvider,
private val studentDb: StudentDao,
private val semesterDb: SemesterDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val appDatabase: AppDatabase,
private val scrambler: Scrambler,
) {
@@ -36,7 +37,7 @@ class StudentRepository @Inject constructor(
pin: String,
symbol: String,
token: String
- ): RegisterUser = wulkanowySdkFactory.create()
+ ): RegisterUser = sdk
.getStudentsFromHebe(token, pin, symbol, "")
.mapToPojo(null)
@@ -46,7 +47,7 @@ class StudentRepository @Inject constructor(
scrapperBaseUrl: String,
domainSuffix: String,
symbol: String
- ): RegisterUser = wulkanowySdkFactory.create()
+ ): RegisterUser = sdk
.getUserSubjectsFromScrapper(email, password, scrapperBaseUrl, domainSuffix, symbol)
.mapToPojo(password)
@@ -55,7 +56,7 @@ class StudentRepository @Inject constructor(
password: String,
scrapperBaseUrl: String,
symbol: String
- ): RegisterUser = wulkanowySdkFactory.create()
+ ): RegisterUser = sdk
.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol)
.mapToPojo(password)
@@ -148,11 +149,13 @@ class StudentRepository @Inject constructor(
.distinctBy { it.student.studentName }.size == 1
suspend fun authorizePermission(student: Student, semester: Semester, pesel: String) =
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.authorizePermission(pesel)
suspend fun refreshStudentName(student: Student, semester: Semester) {
- val newCurrentApiStudent = wulkanowySdkFactory.create(student, semester)
+ val newCurrentApiStudent = sdk.init(student)
+ .switchSemester(semester)
.getCurrentStudent() ?: return
val studentName = StudentName(
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt
index 573c7c14..cf7f86c2 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt
@@ -1,13 +1,15 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.SubjectDao
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.sync.Mutex
import javax.inject.Inject
@@ -16,7 +18,7 @@ import javax.inject.Singleton
@Singleton
class SubjectRepository @Inject constructor(
private val subjectDao: SubjectDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -37,7 +39,8 @@ class SubjectRepository @Inject constructor(
},
query = { subjectDao.loadAll(semester.diaryId, semester.studentId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getSubjects()
.mapToEntities(semester)
},
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt
index a5a6e3f9..5a488b27 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt
@@ -1,13 +1,15 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.TeacherDao
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.sync.Mutex
import javax.inject.Inject
@@ -16,7 +18,7 @@ import javax.inject.Singleton
@Singleton
class TeacherRepository @Inject constructor(
private val teacherDb: TeacherDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -37,7 +39,8 @@ class TeacherRepository @Inject constructor(
},
query = { teacherDb.loadAll(semester.studentId, semester.classId) },
fetch = {
- wulkanowySdkFactory.create(student, semester)
+ sdk.init(student)
+ .switchSemester(semester)
.getTeachers()
.mapToEntities(semester)
},
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt
index 33578999..0d208c1f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.data.repositories
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao
import io.github.wulkanowy.data.db.dao.TimetableDao
import io.github.wulkanowy.data.db.dao.TimetableHeaderDao
@@ -12,11 +11,14 @@ import io.github.wulkanowy.data.db.entities.TimetableHeader
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.data.pojos.TimetableFull
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.sunday
+import io.github.wulkanowy.utils.switchSemester
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -31,7 +33,7 @@ class TimetableRepository @Inject constructor(
private val timetableDb: TimetableDao,
private val timetableAdditionalDb: TimetableAdditionalDao,
private val timetableHeaderDb: TimetableHeaderDao,
- private val wulkanowySdkFactory: WulkanowySdkFactory,
+ private val sdk: Sdk,
private val schedulerHelper: TimetableNotificationSchedulerHelper,
private val refreshHelper: AutoRefreshHelper,
) {
@@ -72,7 +74,8 @@ class TimetableRepository @Inject constructor(
},
query = { getFullTimetableFromDatabase(student, semester, start, end) },
fetch = {
- val timetableFull = wulkanowySdkFactory.create(student, semester)
+ val timetableFull = sdk.init(student)
+ .switchSemester(semester)
.getTimetable(start.monday, end.sunday)
timetableFull.mapToEntities(semester)
diff --git a/app/src/main/java/io/github/wulkanowy/domain/attendance/GetAttendanceCalculatorDataUseCase.kt b/app/src/main/java/io/github/wulkanowy/domain/attendance/GetAttendanceCalculatorDataUseCase.kt
deleted file mode 100644
index 294abd1b..00000000
--- a/app/src/main/java/io/github/wulkanowy/domain/attendance/GetAttendanceCalculatorDataUseCase.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-package io.github.wulkanowy.domain.attendance
-
-import io.github.wulkanowy.data.*
-import io.github.wulkanowy.data.db.entities.AttendanceSummary
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.db.entities.Subject
-import io.github.wulkanowy.data.enums.AttendanceCalculatorSortingMode
-import io.github.wulkanowy.data.enums.AttendanceCalculatorSortingMode.*
-import io.github.wulkanowy.data.pojos.AttendanceData
-import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository
-import io.github.wulkanowy.data.repositories.PreferencesRepository
-import io.github.wulkanowy.data.repositories.SubjectRepository
-import io.github.wulkanowy.utils.allAbsences
-import io.github.wulkanowy.utils.allPresences
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-import kotlin.math.ceil
-import kotlin.math.floor
-
-class GetAttendanceCalculatorDataUseCase @Inject constructor(
- private val subjectRepository: SubjectRepository,
- private val attendanceSummaryRepository: AttendanceSummaryRepository,
- private val preferencesRepository: PreferencesRepository,
-) {
-
- operator fun invoke(
- student: Student,
- semester: Semester,
- forceRefresh: Boolean,
- ): Flow>> =
- subjectRepository.getSubjects(student, semester, forceRefresh)
- .mapResourceData { subjects -> subjects.sortedBy(Subject::name) }
- .combineWithResourceData(preferencesRepository.targetAttendanceFlow, ::Pair)
- .flatMapResourceData { (subjects, targetFreq) ->
- combineResourceFlows(subjects.map { subject ->
- attendanceSummaryRepository.getAttendanceSummary(
- student = student,
- semester = semester,
- subjectId = subject.realId,
- forceRefresh = forceRefresh
- ).mapResourceData { summaries ->
- summaries.toAttendanceData(subject.name, targetFreq)
- }
- })
- // Every individual combined flow causes separate network requests to update data.
- // When there is N child flows, they can cause up to N-1 items to be emitted. Since all
- // requests are usually completed in less than 5s, there is no need to emit multiple
- // intermediates that will be visible for barely any time.
- .debounceIntermediates()
- }
- .combineWithResourceData(preferencesRepository.attendanceCalculatorShowEmptySubjects) { attendanceDataList, showEmptySubjects ->
- attendanceDataList.filter { it.total != 0 || showEmptySubjects }
- }
- .combineWithResourceData(preferencesRepository.attendanceCalculatorSortingModeFlow, List::sortedBy)
-}
-
-private fun List.toAttendanceData(subjectName: String, targetFreq: Int): AttendanceData {
- val presences = sumOf { it.allPresences }
- val absences = sumOf { it.allAbsences }
- return AttendanceData(
- subjectName = subjectName,
- lessonBalance = calcLessonBalance(
- targetFreq.toDouble() / 100, presences, absences
- ),
- presences = presences,
- absences = absences,
- )
-}
-
-private fun calcLessonBalance(targetFreq: Double, presences: Int, absences: Int): Int {
- val total = presences + absences
- // The `+ 1` is to avoid false positives in close cases. Eg.:
- // target frequency 99%, 1 presence. Without the `+ 1` this would be reported shown as
- // a positive balance of +1, however that is not actually true as skipping one class
- // would make it so that the balance would actually be negative (-98). The `+ 1`
- // fixes this and makes sure that in situations like these, it's not reporting incorrect
- // balances
- return when {
- presences / (total + 1f) >= targetFreq -> calcMissingAbsences(
- targetFreq, absences, presences
- )
- presences / (total + 0f) < targetFreq -> -calcMissingPresences(
- targetFreq, absences, presences
- )
- else -> 0
- }
-}
-
-private fun calcMissingPresences(targetFreq: Double, absences: Int, presences: Int) =
- calcMinRequiredPresencesFor(targetFreq, absences) - presences
-
-private fun calcMinRequiredPresencesFor(targetFreq: Double, absences: Int) =
- ceil((targetFreq / (1 - targetFreq)) * absences).toInt()
-
-private fun calcMissingAbsences(targetFreq: Double, absences: Int, presences: Int) =
- calcMinRequiredAbsencesFor(targetFreq, presences) - absences
-
-private fun calcMinRequiredAbsencesFor(targetFreq: Double, presences: Int) =
- floor((presences * (1 - targetFreq)) / targetFreq).toInt()
-
-private fun List.sortedBy(mode: AttendanceCalculatorSortingMode) = when (mode) {
- ALPHABETIC -> sortedBy(AttendanceData::subjectName)
- ATTENDANCE -> sortedByDescending(AttendanceData::presencePercentage)
- LESSON_BALANCE -> sortedBy(AttendanceData::lessonBalance)
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt
index 922c3536..10735dab 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt
@@ -1,7 +1,6 @@
package io.github.wulkanowy.ui.base
import android.app.ActivityManager
-import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.Toast
@@ -46,19 +45,11 @@ abstract class BaseActivity, VB : ViewBinding> :
themeManager.applyActivityTheme(this)
super.onCreate(savedInstanceState)
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleLogger, true)
- applyCustomTaskDescription()
- }
- @Suppress("DEPRECATION")
- private fun applyCustomTaskDescription() {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) return
- try {
- val newColor = getThemeAttrColor(R.attr.colorSurface)
- val taskDescription = ActivityManager.TaskDescription(null, null, newColor)
- setTaskDescription(taskDescription)
- } catch (e: Exception) {
- Timber.e(e)
- }
+ @Suppress("DEPRECATION")
+ setTaskDescription(
+ ActivityManager.TaskDescription(null, null, getThemeAttrColor(R.attr.colorSurface))
+ )
}
override fun showError(text: String, error: Throwable) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt
index f5689ec8..4e9baac3 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.ui.modules.attendance
-import android.content.res.ColorStateList
import android.graphics.Typeface
import android.view.LayoutInflater
import android.view.View
@@ -34,17 +33,17 @@ class AttendanceAdapter @Inject constructor() :
)
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
- val context = holder.binding.root.context
val item = items[position]
with(holder.binding) {
attendanceItemNumber.text = item.number.toString()
- attendanceItemSubject.text = item.subject
- .ifBlank { context.getString(R.string.all_no_data) }
+ attendanceItemSubject.text = item.subject.ifBlank {
+ root.context.getString(R.string.all_no_data)
+ }
attendanceItemDescription.setText(item.descriptionRes)
attendanceItemDescription.setTextColor(
- context.getThemeAttrColor(
+ root.context.getThemeAttrColor(
when {
item.absence && !item.excused -> R.attr.colorAttendanceAbsence
item.lateness && !item.excused -> R.attr.colorAttendanceLateness
@@ -62,15 +61,13 @@ class AttendanceAdapter @Inject constructor() :
attendanceItemAlert.isVisible =
item.let { (it.absence && !it.excused) || (it.lateness && !it.excused) }
- attendanceItemAlert.imageTintList = ColorStateList.valueOf(
- context.getThemeAttrColor(
- when {
- item.absence && !item.excused -> R.attr.colorAttendanceAbsence
- item.lateness && !item.excused -> R.attr.colorAttendanceLateness
- else -> android.R.attr.colorPrimary
- }
- )
- )
+ attendanceItemAlert.setColorFilter(root.context.getThemeAttrColor(
+ when{
+ item.absence && !item.excused -> R.attr.colorAttendanceAbsence
+ item.lateness && !item.excused -> R.attr.colorAttendanceLateness
+ else -> android.R.attr.colorPrimary
+ }
+ ))
attendanceItemNumber.visibility = View.GONE
attendanceItemExcuseInfo.visibility = View.GONE
attendanceItemExcuseCheckbox.visibility = View.GONE
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
index 07649e43..6e842b4d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
@@ -14,7 +14,6 @@ import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.databinding.DialogExcuseBinding
import io.github.wulkanowy.databinding.FragmentAttendanceBinding
import io.github.wulkanowy.ui.base.BaseFragment
-import io.github.wulkanowy.ui.modules.attendance.calculator.AttendanceCalculatorFragment
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
@@ -135,7 +134,6 @@ class AttendanceFragment : BaseFragment(R.layout.frag
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == R.id.attendanceMenuSummary) presenter.onSummarySwitchSelected()
- else if (item.itemId == R.id.attendanceMenuCalculator) presenter.onCalculatorSwitchSelected()
else false
}
@@ -255,10 +253,6 @@ class AttendanceFragment : BaseFragment(R.layout.frag
(activity as? MainActivity)?.pushView(AttendanceSummaryFragment.newInstance())
}
- override fun openCalculatorView() {
- (activity as? MainActivity)?.pushView(AttendanceCalculatorFragment.newInstance())
- }
-
override fun startActionMode() {
actionMode = (activity as MainActivity?)?.startSupportActionMode(actionModeCallback)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt
index 586a41ad..82fe69cb 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt
@@ -1,36 +1,16 @@
package io.github.wulkanowy.ui.modules.attendance
import android.annotation.SuppressLint
-import io.github.wulkanowy.data.Resource
+import io.github.wulkanowy.data.*
import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.flatResourceFlow
-import io.github.wulkanowy.data.logResourceStatus
-import io.github.wulkanowy.data.mapResourceData
-import io.github.wulkanowy.data.onResourceData
-import io.github.wulkanowy.data.onResourceError
-import io.github.wulkanowy.data.onResourceIntermediate
-import io.github.wulkanowy.data.onResourceLoading
-import io.github.wulkanowy.data.onResourceNotLoading
-import io.github.wulkanowy.data.onResourceSuccess
import io.github.wulkanowy.data.repositories.AttendanceRepository
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository
-import io.github.wulkanowy.data.resourceFlow
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.utils.AnalyticsHelper
-import io.github.wulkanowy.utils.capitalise
-import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
-import io.github.wulkanowy.utils.isExcusableOrNotExcused
-import io.github.wulkanowy.utils.isHolidays
-import io.github.wulkanowy.utils.monday
-import io.github.wulkanowy.utils.nextSchoolDay
-import io.github.wulkanowy.utils.previousOrSameSchoolDay
-import io.github.wulkanowy.utils.previousSchoolDay
-import io.github.wulkanowy.utils.sunday
-import io.github.wulkanowy.utils.toFormattedString
+import io.github.wulkanowy.utils.*
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
@@ -215,11 +195,6 @@ class AttendancePresenter @Inject constructor(
return true
}
- fun onCalculatorSwitchSelected(): Boolean {
- view?.openCalculatorView()
- return true
- }
-
private fun loadData(forceRefresh: Boolean = false) {
Timber.i("Loading attendance data started")
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt
index f51ce7c7..2629c217 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt
@@ -56,8 +56,6 @@ interface AttendanceView : BaseView {
fun openSummaryView()
- fun openCalculatorView()
-
fun startSendMessageIntent(date: LocalDate, numbers: String, reason: String)
fun startActionMode()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorAdapter.kt
deleted file mode 100644
index 4b908bba..00000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorAdapter.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package io.github.wulkanowy.ui.modules.attendance.calculator
-
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import androidx.core.view.isVisible
-import androidx.recyclerview.widget.RecyclerView
-import io.github.wulkanowy.R
-import io.github.wulkanowy.data.pojos.AttendanceData
-import io.github.wulkanowy.databinding.ItemAttendanceCalculatorHeaderBinding
-import javax.inject.Inject
-import kotlin.math.abs
-import kotlin.math.roundToInt
-
-class AttendanceCalculatorAdapter @Inject constructor() :
- RecyclerView.Adapter() {
-
- var items = emptyList()
-
- override fun getItemCount() = items.size
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
- ItemAttendanceCalculatorHeaderBinding.inflate(
- LayoutInflater.from(parent.context), parent, false
- )
- )
-
- override fun onBindViewHolder(parent: ViewHolder, position: Int) {
- val context = parent.binding.root.context
- val item = items[position]
-
- with(parent.binding) {
- attendanceCalculatorPercentage.text = "${item.presencePercentage.roundToInt()}"
-
- attendanceCalculatorSummaryBalance.text = when {
- item.lessonBalance > 0 -> {
- context.getString(
- R.string.attendance_calculator_summary_balance_positive,
- item.lessonBalance
- )
- }
-
- item.lessonBalance < 0 -> {
- context.getString(
- R.string.attendance_calculator_summary_balance_negative,
- abs(item.lessonBalance)
- )
- }
-
- else -> context.getString(R.string.attendance_calculator_summary_balance_neutral)
- }
- attendanceCalculatorWarning.isVisible = item.lessonBalance < 0
- attendanceCalculatorTitle.text = item.subjectName
- attendanceCalculatorSummaryValues.text = if (item.total == 0) {
- context.getString(R.string.attendance_calculator_summary_values_empty)
- } else {
- context.getString(
- R.string.attendance_calculator_summary_values,
- item.presences,
- item.total
- )
- }
- }
- }
-
- class ViewHolder(val binding: ItemAttendanceCalculatorHeaderBinding) :
- RecyclerView.ViewHolder(binding.root)
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorFragment.kt
deleted file mode 100644
index 2d566701..00000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorFragment.kt
+++ /dev/null
@@ -1,105 +0,0 @@
-package io.github.wulkanowy.ui.modules.attendance.calculator
-
-import android.os.Bundle
-import android.view.View
-import androidx.core.view.isVisible
-import androidx.recyclerview.widget.LinearLayoutManager
-import dagger.hilt.android.AndroidEntryPoint
-import io.github.wulkanowy.R
-import io.github.wulkanowy.data.pojos.AttendanceData
-import io.github.wulkanowy.databinding.FragmentAttendanceCalculatorBinding
-import io.github.wulkanowy.ui.base.BaseFragment
-import io.github.wulkanowy.ui.modules.main.MainView
-import io.github.wulkanowy.ui.widgets.DividerItemDecoration
-import io.github.wulkanowy.utils.getThemeAttrColor
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class AttendanceCalculatorFragment :
- BaseFragment(R.layout.fragment_attendance_calculator),
- AttendanceCalculatorView, MainView.TitledView {
-
- @Inject
- lateinit var presenter: AttendanceCalculatorPresenter
-
- @Inject
- lateinit var attendanceCalculatorAdapter: AttendanceCalculatorAdapter
-
- override val titleStringId get() = R.string.attendance_title
-
- companion object {
- fun newInstance() = AttendanceCalculatorFragment()
- }
-
- override val isViewEmpty get() = attendanceCalculatorAdapter.items.isEmpty()
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- binding = FragmentAttendanceCalculatorBinding.bind(view)
- messageContainer = binding.attendanceCalculatorRecycler
- presenter.onAttachView(this)
- }
-
- override fun initView() {
- with(binding.attendanceCalculatorRecycler) {
- layoutManager = LinearLayoutManager(context)
- adapter = attendanceCalculatorAdapter
- addItemDecoration(DividerItemDecoration(context))
- }
-
- with(binding) {
- attendanceCalculatorSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
- attendanceCalculatorSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary))
- attendanceCalculatorSwipe.setProgressBackgroundColorSchemeColor(requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh))
- attendanceCalculatorErrorRetry.setOnClickListener { presenter.onRetry() }
- attendanceCalculatorErrorDetails.setOnClickListener { presenter.onDetailsClick() }
- }
- }
-
- override fun updateData(data: List) {
- with(attendanceCalculatorAdapter) {
- items = data
- notifyDataSetChanged()
- }
- }
-
- override fun clearView() {
- with(attendanceCalculatorAdapter) {
- items = emptyList()
- notifyDataSetChanged()
- }
- }
-
- override fun showEmpty(show: Boolean) {
- binding.attendanceCalculatorEmpty.isVisible = show
- }
-
- override fun showErrorView(show: Boolean) {
- binding.attendanceCalculatorError.isVisible = show
- }
-
- override fun setErrorDetails(message: String) {
- binding.attendanceCalculatorErrorMessage.text = message
- }
-
- override fun showProgress(show: Boolean) {
- binding.attendanceCalculatorProgress.isVisible = show
- }
-
- override fun enableSwipe(enable: Boolean) {
- binding.attendanceCalculatorSwipe.isEnabled = enable
- }
-
- override fun showContent(show: Boolean) {
- binding.attendanceCalculatorRecycler.isVisible = show
- }
-
- override fun showRefresh(show: Boolean) {
- binding.attendanceCalculatorSwipe.isRefreshing = show
- }
-
- override fun onDestroyView() {
- presenter.onDetachView()
- super.onDestroyView()
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorPresenter.kt
deleted file mode 100644
index d292e565..00000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorPresenter.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-package io.github.wulkanowy.ui.modules.attendance.calculator
-
-import io.github.wulkanowy.data.*
-import io.github.wulkanowy.data.repositories.SemesterRepository
-import io.github.wulkanowy.data.repositories.StudentRepository
-import io.github.wulkanowy.domain.attendance.GetAttendanceCalculatorDataUseCase
-import io.github.wulkanowy.ui.base.BasePresenter
-import io.github.wulkanowy.ui.base.ErrorHandler
-import timber.log.Timber
-import javax.inject.Inject
-
-class AttendanceCalculatorPresenter @Inject constructor(
- errorHandler: ErrorHandler,
- studentRepository: StudentRepository,
- private val semesterRepository: SemesterRepository,
- private val getAttendanceCalculatorData: GetAttendanceCalculatorDataUseCase,
-) : BasePresenter(errorHandler, studentRepository) {
-
- private lateinit var lastError: Throwable
-
- override fun onAttachView(view: AttendanceCalculatorView) {
- super.onAttachView(view)
- view.initView()
- Timber.i("Attendance calculator view was initialized")
- errorHandler.showErrorMessage = ::showErrorViewOnError
- loadData()
- }
-
- fun onSwipeRefresh() {
- Timber.i("Force refreshing the attendance calculator")
- loadData(forceRefresh = true)
- }
-
- fun onRetry() {
- view?.run {
- showErrorView(false)
- showProgress(true)
- }
- loadData()
- }
-
- fun onDetailsClick() {
- view?.showErrorDetailsDialog(lastError)
- }
-
- private fun loadData(forceRefresh: Boolean = false) {
- flatResourceFlow {
- val student = studentRepository.getCurrentStudent()
- val semester = semesterRepository.getCurrentSemester(student)
- getAttendanceCalculatorData(student, semester, forceRefresh)
- }
- .logResourceStatus("load attendance calculator")
- .onResourceData {
- view?.run {
- showProgress(false)
- showErrorView(false)
- showContent(it.isNotEmpty())
- showEmpty(it.isEmpty())
- updateData(it)
- }
- }
- .onResourceIntermediate { view?.showRefresh(true) }
- .onResourceNotLoading {
- view?.run {
- enableSwipe(true)
- showRefresh(false)
- showProgress(false)
- }
- }
- .onResourceError(errorHandler::dispatch)
- .launch()
- }
-
- private fun showErrorViewOnError(message: String, error: Throwable) {
- view?.run {
- if (isViewEmpty) {
- lastError = error
- setErrorDetails(message)
- showErrorView(true)
- showEmpty(false)
- } else showError(message, error)
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorView.kt
deleted file mode 100644
index 94e66121..00000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorView.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.github.wulkanowy.ui.modules.attendance.calculator
-
-import io.github.wulkanowy.data.pojos.AttendanceData
-import io.github.wulkanowy.ui.base.BaseView
-
-interface AttendanceCalculatorView : BaseView {
-
- val isViewEmpty: Boolean
-
- fun initView()
-
- fun showRefresh(show: Boolean)
-
- fun showContent(show: Boolean)
-
- fun showProgress(show: Boolean)
-
- fun enableSwipe(enable: Boolean)
-
- fun showEmpty(show: Boolean)
-
- fun showErrorView(show: Boolean)
-
- fun setErrorDetails(message: String)
-
- fun updateData(data: List)
-
- fun clearView()
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt
index 0f7c4234..fa29df47 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt
@@ -78,9 +78,4 @@ class AuthDialog : BaseDialogFragment(), AuthView {
override fun showDescriptionWithName(name: String) {
binding.authDescription.text = getString(R.string.auth_description, name).parseAsHtml()
}
-
- override fun onDestroyView() {
- presenter.onDetachView()
- super.onDestroyView()
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/captcha/CaptchaDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/captcha/CaptchaDialog.kt
index ce2173d2..98b4fda7 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/captcha/CaptchaDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/captcha/CaptchaDialog.kt
@@ -10,8 +10,8 @@ import android.webkit.WebViewClient
import androidx.core.os.bundleOf
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.databinding.DialogCaptchaBinding
+import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.base.BaseDialogFragment
import io.github.wulkanowy.utils.WebkitCookieManagerProxy
import timber.log.Timber
@@ -21,7 +21,7 @@ import javax.inject.Inject
class CaptchaDialog : BaseDialogFragment() {
@Inject
- lateinit var wulkanowySdkFactory: WulkanowySdkFactory
+ lateinit var sdk: Sdk
@Inject
lateinit var webkitCookieManagerProxy: WebkitCookieManagerProxy
@@ -59,7 +59,7 @@ class CaptchaDialog : BaseDialogFragment() {
webView = this
with(settings) {
javaScriptEnabled = true
- userAgentString = wulkanowySdkFactory.create().userAgent
+ userAgentString = sdk.userAgent
}
webViewClient = object : WebViewClient() {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt
index 11d3c6c1..8bd84f2b 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt
@@ -47,6 +47,7 @@ class MailboxChooserDialog : BaseDialogFragment(),
}
+ @Suppress("UNCHECKED_CAST")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter.onAttachView(
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
index 8e7c7276..75778bac 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
@@ -82,10 +82,10 @@ class MessagePreviewFragment :
get() = getString(R.string.message_not_exists)
companion object {
- private const val MESSAGE_ARG_KEY = "message"
+ const val MESSAGE_ID_KEY = "message_id"
fun newInstance(message: Message) = MessagePreviewFragment().apply {
- arguments = bundleOf(MESSAGE_ARG_KEY to message)
+ arguments = bundleOf(MESSAGE_ID_KEY to message)
}
}
@@ -101,7 +101,7 @@ class MessagePreviewFragment :
messageContainer = binding.messagePreviewContainer
presenter.onAttachView(
view = this,
- message = requireArguments().serializable(MESSAGE_ARG_KEY),
+ message = (savedInstanceState ?: arguments)?.serializable(MESSAGE_ID_KEY),
)
}
@@ -233,6 +233,11 @@ class MessagePreviewFragment :
(activity as MainActivity).popView()
}
+ override fun onSaveInstanceState(outState: Bundle) {
+ outState.putSerializable(MESSAGE_ID_KEY, presenter.messageWithAttachments)
+ super.onSaveInstanceState(outState)
+ }
+
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
index 3b3b2b42..9bb0d32a 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
@@ -3,15 +3,10 @@ package io.github.wulkanowy.ui.modules.message.preview
import android.annotation.SuppressLint
import androidx.core.text.parseAsHtml
import io.github.wulkanowy.R
+import io.github.wulkanowy.data.*
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
import io.github.wulkanowy.data.enums.MessageFolder
-import io.github.wulkanowy.data.flatResourceFlow
-import io.github.wulkanowy.data.logResourceStatus
-import io.github.wulkanowy.data.onResourceData
-import io.github.wulkanowy.data.onResourceError
-import io.github.wulkanowy.data.onResourceNotLoading
-import io.github.wulkanowy.data.onResourceSuccess
import io.github.wulkanowy.data.repositories.MessageRepository
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.StudentRepository
@@ -33,17 +28,17 @@ class MessagePreviewPresenter @Inject constructor(
private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
- private var messageWithAttachments: MessageWithAttachment? = null
+ var messageWithAttachments: MessageWithAttachment? = null
private lateinit var lastError: Throwable
private var retryCallback: () -> Unit = {}
- fun onAttachView(view: MessagePreviewView, message: Message) {
+ fun onAttachView(view: MessagePreviewView, message: Message?) {
super.onAttachView(view)
view.initView()
errorHandler.showErrorMessage = ::showErrorViewOnError
- loadData(message)
+ loadData(requireNotNull(message))
}
private fun onMessageLoadRetry(message: Message) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt
index ba234aae..3d0c8052 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt
@@ -4,7 +4,6 @@ import android.content.SharedPreferences
import android.os.Bundle
import android.view.View
import androidx.preference.PreferenceFragmentCompat
-import androidx.preference.SeekBarPreference
import com.yariksoffice.lingver.Lingver
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
@@ -37,15 +36,6 @@ class AppearanceFragment : PreferenceFragmentCompat(),
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.scheme_preferences_appearance, rootKey)
- val attendanceTargetPref =
- findPreference(requireContext().getString(R.string.pref_key_attendance_target))!!
- attendanceTargetPref.setOnPreferenceChangeListener { _, newValueObj ->
- val newValue = (((newValueObj as Int).toDouble() + 2.5) / 5).toInt() * 5
- attendanceTargetPref.value =
- newValue.coerceIn(attendanceTargetPref.min, attendanceTargetPref.max)
-
- false
- }
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
diff --git a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt
index 3cac0b48..397c9595 100644
--- a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt
+++ b/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt
@@ -10,19 +10,19 @@ import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceCategory
* (https://www.vulcan.edu.pl/vulcang_files/user/AABW/AABW-PDF/uonetplus/uonetplus_Frekwencja-liczby-obecnych-nieobecnych.pdf)
*/
-inline val AttendanceSummary.allPresences: Int
- get() = presence + absenceForSchoolReasons + lateness + latenessExcused
+private inline val AttendanceSummary.allPresences: Double
+ get() = presence.toDouble() + absenceForSchoolReasons + lateness + latenessExcused
-inline val AttendanceSummary.allAbsences: Int
- get() = absence + absenceExcused
+private inline val AttendanceSummary.allAbsences: Double
+ get() = absence.toDouble() + absenceExcused
inline val Attendance.isExcusableOrNotExcused: Boolean
get() = (excusable || ((absence || lateness) && !excused)) && excuseStatus == null
-fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences.toDouble(), allAbsences.toDouble())
+fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences)
fun List.calculatePercentage(): Double {
- return calculatePercentage(sumOf { it.allPresences.toDouble() }, sumOf { it.allAbsences.toDouble() })
+ return calculatePercentage(sumOf { it.allPresences }, sumOf { it.allAbsences })
}
private fun calculatePercentage(presence: Double, absence: Double): Double {
diff --git a/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt
index b1742b4f..d3c9f800 100644
--- a/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt
+++ b/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt
@@ -4,31 +4,30 @@ import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
-import androidx.core.os.BundleCompat
import java.io.Serializable
-// Even though API was introduced in 33, we use 34 as 33 is bugged in some scenarios.
-
inline fun Bundle.serializable(key: String): T = when {
- Build.VERSION.SDK_INT >= 34 -> getSerializable(key, T::class.java)!!
+ Build.VERSION.SDK_INT >= 33 -> getSerializable(key, T::class.java)!!
else -> @Suppress("DEPRECATION") getSerializable(key) as T
}
inline fun Bundle.nullableSerializable(key: String): T? = when {
- Build.VERSION.SDK_INT >= 34 -> getSerializable(key, T::class.java)
+ Build.VERSION.SDK_INT >= 33 -> getSerializable(key, T::class.java)
else -> @Suppress("DEPRECATION") getSerializable(key) as T?
}
@Suppress("UNCHECKED_CAST")
-inline fun Bundle.parcelableArray(key: String): Array? =
- BundleCompat.getParcelableArray(this, key, T::class.java) as Array?
+inline fun Bundle.parcelableArray(key: String): Array? = when {
+ Build.VERSION.SDK_INT >= 33 -> getParcelableArray(key, T::class.java)
+ else -> @Suppress("DEPRECATION") getParcelableArray(key) as Array?
+}
inline fun Intent.serializable(key: String): T = when {
- Build.VERSION.SDK_INT >= 34 -> getSerializableExtra(key, T::class.java)!!
+ Build.VERSION.SDK_INT >= 33 -> getSerializableExtra(key, T::class.java)!!
else -> @Suppress("DEPRECATION") getSerializableExtra(key) as T
}
inline fun Intent.nullableSerializable(key: String): T? = when {
- Build.VERSION.SDK_INT >= 34 -> getSerializableExtra(key, T::class.java)
+ Build.VERSION.SDK_INT >= 33 -> getSerializableExtra(key, T::class.java)
else -> @Suppress("DEPRECATION") getSerializableExtra(key) as T?
}
diff --git a/app/src/main/java/io/github/wulkanowy/utils/SdkExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/SdkExtension.kt
new file mode 100644
index 00000000..9b6ca706
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/utils/SdkExtension.kt
@@ -0,0 +1,42 @@
+package io.github.wulkanowy.utils
+
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.sdk.Sdk
+import timber.log.Timber
+
+fun Sdk.init(student: Student): Sdk {
+ email = student.email
+ password = student.password
+ symbol = student.symbol
+ schoolSymbol = student.schoolSymbol
+ studentId = student.studentId
+ classId = student.classId
+ emptyCookieJarInterceptor = true
+
+ if (Sdk.Mode.valueOf(student.loginMode) == Sdk.Mode.HEBE) {
+ mobileBaseUrl = student.mobileBaseUrl
+ } else {
+ scrapperBaseUrl = student.scrapperBaseUrl
+ domainSuffix = student.scrapperDomainSuffix
+ loginType = Sdk.ScrapperLoginType.valueOf(student.loginType)
+ }
+
+ mode = Sdk.Mode.valueOf(student.loginMode)
+ mobileBaseUrl = student.mobileBaseUrl
+ keyId = student.certificateKey
+ privatePem = student.privateKey
+
+ Timber.d("Sdk in ${student.loginMode} mode reinitialized")
+
+ return this
+}
+
+fun Sdk.switchSemester(semester: Semester): Sdk {
+ return switchDiary(
+ diaryId = semester.diaryId,
+ kindergartenDiaryId = semester.kindergartenDiaryId,
+ schoolYear = semester.schoolYear,
+ unitId = semester.unitId,
+ )
+}
diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt
index 2a57977f..98c48e15 100644
--- a/app/src/main/play/release-notes/pl-PL/default.txt
+++ b/app/src/main/play/release-notes/pl-PL/default.txt
@@ -1,4 +1,4 @@
-Wersja 2.5.1
+Wersja 2.5.0
— dodaliśmy wyświetlanie ogłoszeń
— dodaliśmy opcję przywracania wiadomości z kosza
diff --git a/app/src/main/res/drawable/ic_menu_attendance_calculator.xml b/app/src/main/res/drawable/ic_menu_attendance_calculator.xml
deleted file mode 100644
index 8a7d209a..00000000
--- a/app/src/main/res/drawable/ic_menu_attendance_calculator.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/layout/fragment_attendance_calculator.xml b/app/src/main/res/layout/fragment_attendance_calculator.xml
deleted file mode 100644
index 346c6aec..00000000
--- a/app/src/main/res/layout/fragment_attendance_calculator.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/fragment_message.xml b/app/src/main/res/layout/fragment_message.xml
index a437e5f9..b3dac0dd 100644
--- a/app/src/main/res/layout/fragment_message.xml
+++ b/app/src/main/res/layout/fragment_message.xml
@@ -29,6 +29,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/pref_target_attendance.xml b/app/src/main/res/layout/pref_target_attendance.xml
deleted file mode 100644
index 558b0d36..00000000
--- a/app/src/main/res/layout/pref_target_attendance.xml
+++ /dev/null
@@ -1,140 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/menu/action_menu_attendance.xml b/app/src/main/res/menu/action_menu_attendance.xml
index 5c59d239..bb20c8ec 100644
--- a/app/src/main/res/menu/action_menu_attendance.xml
+++ b/app/src/main/res/menu/action_menu_attendance.xml
@@ -1,13 +1,6 @@