Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
08ecbb5341 | |||
e38e458386 | |||
14674b7778 | |||
c6f0588165 | |||
7591af0de1 | |||
cbfed09b52 | |||
4a026e4a70 | |||
5c185c5eca | |||
0bccbc6011 | |||
ed6a0f8cd0 | |||
58d5e4da0e | |||
ba6fb1a4b9 | |||
b6b862d4c3 | |||
9b044a19fe | |||
7485cb2a39 | |||
75122d0dcd | |||
39af56484b | |||
05f7e1d115 | |||
9cd5377438 | |||
7a61b233f0 | |||
83dbd9874e | |||
1d9a49d552 | |||
6175081b88 | |||
116e551186 | |||
713500d892 |
@ -11,9 +11,10 @@ cache:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
|
||||
#branches:
|
||||
# only:
|
||||
# - develop
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- 0.9.2
|
||||
|
||||
android:
|
||||
licenses:
|
||||
|
@ -6,6 +6,7 @@ apply plugin: 'io.fabric'
|
||||
apply plugin: 'com.github.triplet.play'
|
||||
apply from: 'jacoco.gradle'
|
||||
apply from: 'sonarqube.gradle'
|
||||
apply from: 'hooks.gradle'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
@ -16,8 +17,8 @@ android {
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 28
|
||||
versionCode 38
|
||||
versionName "0.9.0"
|
||||
versionCode 41
|
||||
versionName "0.9.3"
|
||||
multiDexEnabled true
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
@ -97,74 +98,79 @@ play {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'io.github.wulkanowy:api:0.9.0'
|
||||
implementation "io.github.wulkanowy:api:0.9.3"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
implementation "androidx.core:core:1.0.2"
|
||||
implementation "androidx.appcompat:appcompat:1.0.2"
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation "androidx.fragment:fragment:1.0.0"
|
||||
implementation "androidx.annotation:annotation:1.1.0"
|
||||
implementation "androidx.multidex:multidex:2.0.1"
|
||||
|
||||
implementation "androidx.cardview:cardview:1.0.0"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation "androidx.recyclerview:recyclerview:1.0.0"
|
||||
implementation "androidx.viewpager:viewpager:1.0.0"
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.0.0"
|
||||
implementation "com.google.android.material:material:1.1.0-alpha07"
|
||||
implementation 'com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f'
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
|
||||
implementation "com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f"
|
||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||
|
||||
implementation "androidx.work:work-runtime:2.0.1"
|
||||
implementation "androidx.work:work-rxjava2:2.0.1"
|
||||
|
||||
implementation "androidx.room:room-runtime:2.1.0-rc01"
|
||||
implementation "androidx.room:room-rxjava2:2.1.0-rc01"
|
||||
kapt "androidx.room:room-compiler:2.1.0-rc01"
|
||||
implementation "androidx.room:room-runtime:2.1.0"
|
||||
implementation "androidx.room:room-rxjava2:2.1.0"
|
||||
kapt "androidx.room:room-compiler:2.1.0"
|
||||
|
||||
implementation "com.google.dagger:dagger-android-support:2.23.1"
|
||||
kapt "com.google.dagger:dagger-compiler:2.23.1"
|
||||
kapt "com.google.dagger:dagger-android-processor:2.23.1"
|
||||
implementation 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
|
||||
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
|
||||
implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0"
|
||||
kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.4.0"
|
||||
|
||||
implementation "eu.davidea:flexible-adapter:5.1.0"
|
||||
implementation "eu.davidea:flexible-adapter-ui:1.0.0"
|
||||
implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
|
||||
implementation 'com.ncapdevi:frag-nav:3.2.0'
|
||||
implementation "com.ncapdevi:frag-nav:3.2.0"
|
||||
|
||||
implementation 'com.github.pwittchen:reactivenetwork-rx2:3.0.3'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.3"
|
||||
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.2.9"
|
||||
|
||||
implementation 'com.google.code.gson:gson:2.8.5'
|
||||
implementation "com.jakewharton.threetenabp:threetenabp:1.2.0"
|
||||
implementation "com.google.code.gson:gson:2.8.5"
|
||||
implementation "com.jakewharton.threetenabp:threetenabp:1.2.1"
|
||||
implementation "com.jakewharton.timber:timber:4.7.1"
|
||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:3.12.3"
|
||||
|
||||
implementation "com.mikepenz:aboutlibraries:6.2.3"
|
||||
implementation 'com.takisoft.preferencex:preferencex:1.0.0'
|
||||
implementation "com.takisoft.preferencex:preferencex:1.0.0"
|
||||
|
||||
playImplementation 'com.google.firebase:firebase-core:16.0.9'
|
||||
playImplementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
|
||||
playImplementation "com.google.firebase:firebase-core:16.0.9"
|
||||
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
|
||||
|
||||
releaseImplementation 'fr.o80.chucker:library-no-op:2.0.4'
|
||||
releaseImplementation "fr.o80.chucker:library-no-op:2.0.4"
|
||||
|
||||
debugImplementation 'fr.o80.chucker:library:2.0.4'
|
||||
debugImplementation "fr.o80.chucker:library:2.0.4"
|
||||
debugImplementation "com.amitshekhar.android:debug-db:1.0.6"
|
||||
|
||||
testImplementation "junit:junit:4.12"
|
||||
testImplementation "io.mockk:mockk:1.9.2"
|
||||
testImplementation 'org.threeten:threetenbp:1.4.0'
|
||||
testImplementation "org.threeten:threetenbp:1.4.0"
|
||||
testImplementation "org.mockito:mockito-core:2.28.2"
|
||||
testImplementation("org.mockito:mockito-inline:2.28.2") {
|
||||
exclude group: 'org.mockito', module: 'mockito-core'
|
||||
exclude group: "org.mockito", module: "mockito-core"
|
||||
}
|
||||
|
||||
androidTestImplementation 'androidx.test:core:1.2.0'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation "androidx.test:core:1.2.0"
|
||||
androidTestImplementation "androidx.test:runner:1.2.0"
|
||||
androidTestImplementation "androidx.test.ext:junit:1.1.1"
|
||||
androidTestImplementation "io.mockk:mockk-android:1.9.2"
|
||||
androidTestImplementation "androidx.room:room-testing:2.1.0-rc01"
|
||||
androidTestImplementation "androidx.room:room-testing:2.1.0"
|
||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
androidTestImplementation "org.mockito:mockito-core:2.28.2"
|
||||
androidTestImplementation('org.mockito:mockito-android:2.28.2') {
|
||||
androidTestImplementation("org.mockito:mockito-android:2.28.2") {
|
||||
exclude group: 'org.mockito', module: 'mockito-core'
|
||||
}
|
||||
}
|
||||
|
10
app/hooks.gradle
Normal file
10
app/hooks.gradle
Normal file
@ -0,0 +1,10 @@
|
||||
apply plugin: "com.star-zero.gradle.githook"
|
||||
|
||||
githook {
|
||||
failOnMissingHooksDir = false
|
||||
hooks {
|
||||
"pre-push" {
|
||||
shell = "./app/play-publish-lint.sh"
|
||||
}
|
||||
}
|
||||
}
|
7
app/play-publish-lint.sh
Executable file
7
app/play-publish-lint.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash -
|
||||
|
||||
content=$(cat < "app/src/main/play/release-notes/pl-PL/default.txt") || exit
|
||||
if [[ "${#content}" -gt 500 ]]; then
|
||||
echo >&2 "Release notes content has reached the limit of 500 characters"
|
||||
exit 1
|
||||
fi
|
3
app/proguard-rules.pro
vendored
3
app/proguard-rules.pro
vendored
@ -37,3 +37,6 @@
|
||||
|
||||
#Config for API
|
||||
-keep class io.github.wulkanowy.api.** {*;}
|
||||
|
||||
#Config for Material Components
|
||||
-keep class com.google.android.material.tabs.** {*;}
|
||||
|
@ -5,13 +5,13 @@ package io.github.wulkanowy.utils
|
||||
import android.content.Context
|
||||
import timber.log.Timber
|
||||
|
||||
fun initCrashlytics(context: Context, appInfo: AppInfo) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
class CrashlyticsTree : Timber.Tree() {
|
||||
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
fun initCrashlytics(context: Context) {
|
||||
// do nothing
|
||||
}
|
||||
|
@ -80,7 +80,6 @@
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/provider_widget_timetable" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider"
|
||||
android:label="@string/lucky_number_title">
|
||||
|
@ -1,6 +1,8 @@
|
||||
package io.github.wulkanowy
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log.INFO
|
||||
import android.util.Log.VERBOSE
|
||||
import androidx.multidex.MultiDex
|
||||
import androidx.work.Configuration
|
||||
import androidx.work.WorkManager
|
||||
@ -9,10 +11,10 @@ import dagger.android.AndroidInjector
|
||||
import dagger.android.support.DaggerApplication
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.utils.Log
|
||||
import io.github.wulkanowy.BuildConfig.DEBUG
|
||||
import io.github.wulkanowy.di.DaggerAppComponent
|
||||
import io.github.wulkanowy.services.sync.SyncWorkerFactory
|
||||
import io.github.wulkanowy.utils.ActivityLifecycleLogger
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.CrashlyticsTree
|
||||
import io.github.wulkanowy.utils.DebugLogTree
|
||||
import io.github.wulkanowy.utils.initCrashlytics
|
||||
@ -27,6 +29,9 @@ class WulkanowyApp : DaggerApplication() {
|
||||
@Inject
|
||||
lateinit var workerFactory: SyncWorkerFactory
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
super.attachBaseContext(base)
|
||||
MultiDex.install(this)
|
||||
@ -35,15 +40,23 @@ class WulkanowyApp : DaggerApplication() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
AndroidThreeTen.init(this)
|
||||
WorkManager.initialize(this, Configuration.Builder().setWorkerFactory(workerFactory).build())
|
||||
RxJavaPlugins.setErrorHandler(::onError)
|
||||
|
||||
initCrashlytics(applicationContext)
|
||||
initWorkManager()
|
||||
initLogging()
|
||||
initCrashlytics(this, appInfo)
|
||||
}
|
||||
|
||||
private fun initWorkManager() {
|
||||
WorkManager.initialize(this,
|
||||
Configuration.Builder()
|
||||
.setWorkerFactory(workerFactory)
|
||||
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
||||
.build())
|
||||
}
|
||||
|
||||
private fun initLogging() {
|
||||
if (DEBUG) {
|
||||
if (appInfo.isDebug) {
|
||||
Timber.plant(DebugLogTree())
|
||||
FlexibleAdapter.enableLogs(Log.Level.DEBUG)
|
||||
} else {
|
||||
@ -53,8 +66,10 @@ class WulkanowyApp : DaggerApplication() {
|
||||
}
|
||||
|
||||
private fun onError(error: Throwable) {
|
||||
if (error is UndeliverableException && error.cause is IOException || error.cause is InterruptedException) {
|
||||
Timber.e(error.cause, "An undeliverable error occurred")
|
||||
//RxJava's too deep stack traces may cause SOE on older android devices
|
||||
val cause = error.cause
|
||||
if (error is UndeliverableException && cause is IOException || cause is InterruptedException || cause is StackOverflowError) {
|
||||
Timber.e(cause, "An undeliverable error occurred")
|
||||
} else throw error
|
||||
}
|
||||
|
||||
|
@ -35,10 +35,18 @@ class MobileDeviceRepository @Inject constructor(
|
||||
}
|
||||
|
||||
fun unregisterDevice(semester: Semester, device: MobileDevice): Single<Boolean> {
|
||||
return remote.unregisterDevice(semester, device)
|
||||
return ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.unregisterDevice(semester, device)
|
||||
else Single.error(UnknownHostException())
|
||||
}
|
||||
}
|
||||
|
||||
fun getToken(semester: Semester): Single<MobileDeviceToken> {
|
||||
return remote.getToken(semester)
|
||||
return ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.getToken(semester)
|
||||
else Single.error(UnknownHostException())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ class PreferencesRepository @Inject constructor(
|
||||
val gradeAverageMode: String
|
||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_average_mode), "only_one_semester") ?: "only_one_semester"
|
||||
|
||||
val gradeAverageForceCalc: Boolean
|
||||
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_grade_average_force_calc), false)
|
||||
|
||||
val isGradeExpandable: Boolean
|
||||
get() = !sharedPref.getBoolean(context.getString(R.string.pref_key_expand_grade), false)
|
||||
|
||||
|
@ -6,10 +6,9 @@ import dagger.Module
|
||||
import dagger.Provides
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.BuildConfig.DEBUG
|
||||
import io.github.wulkanowy.WulkanowyApp
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@ -31,7 +30,6 @@ internal class AppModule {
|
||||
fun provideAppWidgetManager(context: Context): AppWidgetManager = AppWidgetManager.getInstance(context)
|
||||
|
||||
@Singleton
|
||||
@Named("isDebug")
|
||||
@Provides
|
||||
fun provideIsDebug() = DEBUG
|
||||
fun provideAppInfo() = AppInfo()
|
||||
}
|
||||
|
@ -10,30 +10,46 @@ import androidx.work.NetworkType.CONNECTED
|
||||
import androidx.work.NetworkType.UNMETERED
|
||||
import androidx.work.PeriodicWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import io.github.wulkanowy.data.db.SharedPrefHelper
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.services.sync.channels.DebugChannel
|
||||
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.isHolidays
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit.MINUTES
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class SyncManager @Inject constructor(
|
||||
private val workManager: WorkManager,
|
||||
private val preferencesRepository: PreferencesRepository,
|
||||
sharedPrefHelper: SharedPrefHelper,
|
||||
newEntriesChannel: NewEntriesChannel,
|
||||
debugChannel: DebugChannel,
|
||||
@Named("isDebug") isDebug: Boolean
|
||||
appInfo: AppInfo
|
||||
) {
|
||||
|
||||
companion object {
|
||||
|
||||
private const val APP_VERSION_CODE_KEY = "app_version_code"
|
||||
}
|
||||
|
||||
init {
|
||||
if (SDK_INT >= O) newEntriesChannel.create()
|
||||
if (SDK_INT >= O && isDebug) debugChannel.create()
|
||||
if (now().isHolidays) stopSyncWorker()
|
||||
|
||||
if (SDK_INT > O) {
|
||||
newEntriesChannel.create()
|
||||
if (appInfo.isDebug) debugChannel.create()
|
||||
}
|
||||
|
||||
if (sharedPrefHelper.getLong(APP_VERSION_CODE_KEY, -1L) != appInfo.versionCode.toLong()) {
|
||||
startSyncWorker(true)
|
||||
sharedPrefHelper.putLong(APP_VERSION_CODE_KEY, appInfo.versionCode.toLong(), true)
|
||||
}
|
||||
|
||||
Timber.i("SyncManager was initialized")
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,10 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.mikepenz.aboutlibraries.LibsBuilder
|
||||
import com.mikepenz.aboutlibraries.LibsFragmentCompat
|
||||
import io.github.wulkanowy.BuildConfig
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import io.github.wulkanowy.utils.withOnExtraListener
|
||||
import javax.inject.Inject
|
||||
@ -24,6 +24,9 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
|
||||
@Inject
|
||||
lateinit var fragmentCompat: LibsFragmentCompat
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
companion object {
|
||||
fun newInstance() = AboutFragment()
|
||||
}
|
||||
@ -71,9 +74,9 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
|
||||
putExtra(Intent.EXTRA_EMAIL, Array(1) { "wulkanowyinc@gmail.com" })
|
||||
putExtra(Intent.EXTRA_SUBJECT, "Zgłoszenie błędu")
|
||||
putExtra(Intent.EXTRA_TEXT, "Tu umieść treść zgłoszenia\n\n" + "-".repeat(40) + "\n" + """
|
||||
Build: ${BuildConfig.VERSION_CODE}
|
||||
SDK: ${android.os.Build.VERSION.SDK_INT}
|
||||
Device: ${android.os.Build.MANUFACTURER} ${android.os.Build.MODEL}
|
||||
Build: ${appInfo.versionCode}
|
||||
SDK: ${appInfo.systemVersion}
|
||||
Device: ${appInfo.systemManufacturer} ${appInfo.systemModel}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,6 @@ class GradeAverageProvider @Inject constructor(
|
||||
if (it.any { summary -> summary.average != .0 }) {
|
||||
Maybe.just(it.map { summary -> summary.subject to summary.average }.toMap())
|
||||
} else Maybe.empty()
|
||||
}
|
||||
}.filter { !preferencesRepository.gradeAverageForceCalc }
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
.flatMap { (student, semesters) ->
|
||||
averageProvider.getGradeAverage(student, semesters, semesterId, forceRefresh)
|
||||
.flatMap { averages ->
|
||||
gradeRepository.getGrades(student, semesters.first { semester -> semester.semesterId == semesterId })
|
||||
gradeRepository.getGrades(student, semesters.first { it.semesterId == semesterId }, forceRefresh)
|
||||
.map { it.sortedByDescending { grade -> grade.date } }
|
||||
.map { it.groupBy { grade -> grade.subject }.toSortedMap() }
|
||||
.map { createGradeItems(it, averages) }
|
||||
|
@ -10,11 +10,11 @@ import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo.IME_ACTION_DONE
|
||||
import android.view.inputmethod.EditorInfo.IME_NULL
|
||||
import android.widget.ArrayAdapter
|
||||
import io.github.wulkanowy.BuildConfig.VERSION_NAME
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.hideSoftInput
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import io.github.wulkanowy.utils.setOnItemSelectedListener
|
||||
@ -28,6 +28,9 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
|
||||
@Inject
|
||||
lateinit var presenter: LoginFormPresenter
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
companion object {
|
||||
fun newInstance() = LoginFormFragment()
|
||||
}
|
||||
@ -128,7 +131,7 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
|
||||
override fun showVersion() {
|
||||
loginFormVersion.apply {
|
||||
visibility = VISIBLE
|
||||
text = "${getString(R.string.app_name)} $VERSION_NAME"
|
||||
text = "${getString(R.string.app_name)} ${appInfo.versionName}"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,25 +3,26 @@ package io.github.wulkanowy.ui.modules.login.form
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class LoginFormPresenter @Inject constructor(
|
||||
schedulers: SchedulersProvider,
|
||||
studentRepository: StudentRepository,
|
||||
private val loginErrorHandler: LoginErrorHandler,
|
||||
private val analytics: FirebaseAnalyticsHelper,
|
||||
@param:Named("isDebug") private val isDebug: Boolean
|
||||
private val appInfo: AppInfo
|
||||
) : BasePresenter<LoginFormView>(loginErrorHandler, studentRepository, schedulers) {
|
||||
|
||||
override fun onAttachView(view: LoginFormView) {
|
||||
super.onAttachView(view)
|
||||
view.run {
|
||||
initView()
|
||||
if (isDebug) showVersion() else showPrivacyPolicy()
|
||||
if (appInfo.isDebug) showVersion() else showPrivacyPolicy()
|
||||
|
||||
loginErrorHandler.onBadCredentials = {
|
||||
setErrorPassIncorrect()
|
||||
@ -81,7 +82,7 @@ class LoginFormPresenter @Inject constructor(
|
||||
view?.notifyParentAccountLogged(it)
|
||||
}, {
|
||||
Timber.i("Login result: An exception occurred")
|
||||
analytics.logEvent("registration_form", "success" to false, "students" to -1, "endpoint" to endpoint, "error" to it.localizedMessage.ifEmpty { "No message" })
|
||||
analytics.logEvent("registration_form", "success" to false, "students" to -1, "endpoint" to endpoint, "error" to it.message.ifNullOrBlank { "No message" })
|
||||
loginErrorHandler.dispatch(it)
|
||||
}))
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import timber.log.Timber
|
||||
import java.io.Serializable
|
||||
import javax.inject.Inject
|
||||
@ -81,7 +82,7 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
Timber.i("Registration result: Success")
|
||||
view?.openMainView()
|
||||
}, { error ->
|
||||
students.forEach { analytics.logEvent("registration_student_select", "success" to false, "endpoint" to it.endpoint, "symbol" to it.symbol, "error" to error.localizedMessage.ifEmpty { "No message" }) }
|
||||
students.forEach { analytics.logEvent("registration_student_select", "success" to false, "endpoint" to it.endpoint, "symbol" to it.symbol, "error" to error.message.ifNullOrBlank { "No message" }) }
|
||||
Timber.i("Registration result: An exception occurred ")
|
||||
loginErrorHandler.dispatch(error)
|
||||
view?.apply {
|
||||
|
@ -5,6 +5,7 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import io.reactivex.Single
|
||||
import timber.log.Timber
|
||||
import java.io.Serializable
|
||||
@ -70,7 +71,7 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
}
|
||||
}, {
|
||||
Timber.i("Login with symbol result: An exception occurred")
|
||||
analytics.logEvent("registration_symbol", "success" to false, "students" to -1, "endpoint" to loginData?.third, "symbol" to symbol, "error" to it.localizedMessage.ifEmpty { "No message" })
|
||||
analytics.logEvent("registration_symbol", "success" to false, "students" to -1, "endpoint" to loginData?.third, "symbol" to symbol, "error" to it.message.ifNullOrBlank { "No message" })
|
||||
loginErrorHandler.dispatch(it)
|
||||
}))
|
||||
}
|
||||
|
@ -6,5 +6,5 @@ import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
|
||||
class MobileDeviceAdapter<T : IFlexible<*>> : FlexibleAdapter<T>(null, null, true) {
|
||||
|
||||
var onDeviceUnregisterListener: (MobileDevice, position: Int) -> Unit = { _, _ -> }
|
||||
var onDeviceUnregisterListener: (device: MobileDevice, position: Int) -> Unit = { _, _ -> }
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.helpers.EmptyViewHelper
|
||||
import eu.davidea.flexibleadapter.helpers.UndoHelper
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
@ -48,7 +48,7 @@ class MobileDeviceFragment : BaseFragment(), MobileDeviceView, MainView.TitledVi
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
mobileDevicesRecycler.run {
|
||||
with(mobileDevicesRecycler) {
|
||||
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||
adapter = devicesAdapter
|
||||
addItemDecoration(FlexibleItemDecoration(context)
|
||||
@ -56,37 +56,43 @@ class MobileDeviceFragment : BaseFragment(), MobileDeviceView, MainView.TitledVi
|
||||
.withDrawDividerOnLastItem(false)
|
||||
)
|
||||
}
|
||||
EmptyViewHelper.create(devicesAdapter, mobileDevicesEmpty)
|
||||
with(devicesAdapter) {
|
||||
isPermanentDelete = false
|
||||
onDeviceUnregisterListener = presenter::onUnregisterDevice
|
||||
}
|
||||
mobileDevicesSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
||||
mobileDeviceAddButton.setOnClickListener { presenter.onRegisterDevice() }
|
||||
devicesAdapter.run {
|
||||
isPermanentDelete = false
|
||||
onDeviceUnregisterListener = { device, position ->
|
||||
val onActionListener = object : UndoHelper.OnActionListener {
|
||||
override fun onActionConfirmed(action: Int, event: Int) {
|
||||
presenter.onUnregister(device)
|
||||
}
|
||||
|
||||
override fun onActionCanceled(action: Int, positions: MutableList<Int>?) {
|
||||
devicesAdapter.restoreDeletedItems()
|
||||
}
|
||||
}
|
||||
UndoHelper(devicesAdapter, onActionListener)
|
||||
.withConsecutive(false)
|
||||
.withAction(UndoHelper.Action.REMOVE)
|
||||
.start(listOf(position), mobileDevicesRecycler, R.string.mobile_device_removed, R.string.all_undo, 3000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateData(data: List<MobileDeviceItem>) {
|
||||
devicesAdapter.updateDataSet(data)
|
||||
}
|
||||
|
||||
override fun restoreDeleteItem() {
|
||||
devicesAdapter.restoreDeletedItems()
|
||||
}
|
||||
|
||||
override fun clearData() {
|
||||
devicesAdapter.clear()
|
||||
}
|
||||
|
||||
override fun showUndo(position: Int, device: MobileDevice) {
|
||||
val onActionListener = object : UndoHelper.OnActionListener {
|
||||
override fun onActionConfirmed(action: Int, event: Int) {
|
||||
presenter.onUnregisterConfirmed(device)
|
||||
}
|
||||
|
||||
override fun onActionCanceled(action: Int, positions: MutableList<Int>?) {
|
||||
presenter.onUnregisterCancelled()
|
||||
}
|
||||
}
|
||||
|
||||
UndoHelper(devicesAdapter, onActionListener)
|
||||
.withConsecutive(false)
|
||||
.withAction(UndoHelper.Action.REMOVE)
|
||||
.start(listOf(position), mobileDevicesRecycler, R.string.mobile_device_removed, R.string.all_undo, 3000)
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
mobileDevicesSwipe.isRefreshing = false
|
||||
}
|
||||
@ -95,6 +101,10 @@ class MobileDeviceFragment : BaseFragment(), MobileDeviceView, MainView.TitledVi
|
||||
mobileDevicesProgress.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showEmpty(show: Boolean) {
|
||||
mobileDevicesEmpty.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun enableSwipe(enable: Boolean) {
|
||||
mobileDevicesSwipe.isEnabled = enable
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ class MobileDevicePresenter @Inject constructor(
|
||||
view?.run {
|
||||
updateData(it)
|
||||
showContent(it.isNotEmpty())
|
||||
showEmpty(it.isEmpty())
|
||||
}
|
||||
analytics.logEvent("load_devices", "items" to it.size, "force_refresh" to forceRefresh)
|
||||
}) {
|
||||
@ -62,13 +63,27 @@ class MobileDevicePresenter @Inject constructor(
|
||||
view?.showTokenDialog()
|
||||
}
|
||||
|
||||
fun onUnregister(device: MobileDevice) {
|
||||
fun onUnregisterDevice(device: MobileDevice, position: Int) {
|
||||
view?.run {
|
||||
showUndo(position, device)
|
||||
showEmpty(isViewEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
fun onUnregisterCancelled() {
|
||||
view?.run {
|
||||
restoreDeleteItem()
|
||||
showEmpty(isViewEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
fun onUnregisterConfirmed(device: MobileDevice) {
|
||||
Timber.i("Unregister device started")
|
||||
disposable.add(studentRepository.getCurrentStudent()
|
||||
.flatMap { semesterRepository.getCurrentSemester(it) }
|
||||
.flatMap { semester ->
|
||||
mobileDeviceRepository.unregisterDevice(semester, device)
|
||||
.flatMap { mobileDeviceRepository.getDevices(semester, it) }
|
||||
.flatMap { mobileDeviceRepository.getDevices(semester, it) }
|
||||
}
|
||||
.map { items -> items.map { MobileDeviceItem(it) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
@ -84,6 +99,7 @@ class MobileDevicePresenter @Inject constructor(
|
||||
view?.run {
|
||||
updateData(it)
|
||||
showContent(it.isNotEmpty())
|
||||
showEmpty(it.isEmpty())
|
||||
}
|
||||
}) {
|
||||
Timber.i("Unregister device result: An exception occurred")
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.ui.modules.mobiledevice
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface MobileDeviceView : BaseView {
|
||||
@ -10,6 +11,8 @@ interface MobileDeviceView : BaseView {
|
||||
|
||||
fun updateData(data: List<MobileDeviceItem>)
|
||||
|
||||
fun restoreDeleteItem()
|
||||
|
||||
fun hideRefresh()
|
||||
|
||||
fun clearData()
|
||||
@ -20,5 +23,9 @@ interface MobileDeviceView : BaseView {
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
|
||||
fun showEmpty(show: Boolean)
|
||||
|
||||
fun showUndo(position: Int, device: MobileDevice)
|
||||
|
||||
fun showTokenDialog()
|
||||
}
|
||||
|
@ -5,10 +5,10 @@ import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import com.takisoft.preferencex.PreferenceFragmentCompat
|
||||
import dagger.android.support.AndroidSupportInjection
|
||||
import io.github.wulkanowy.BuildConfig.DEBUG
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import javax.inject.Inject
|
||||
|
||||
class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener,
|
||||
@ -17,6 +17,9 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
|
||||
@Inject
|
||||
lateinit var presenter: SettingsPresenter
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
companion object {
|
||||
fun newInstance() = SettingsFragment()
|
||||
}
|
||||
@ -36,7 +39,7 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
|
||||
|
||||
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.scheme_preferences)
|
||||
findPreference(getString(R.string.pref_key_notification_debug)).isVisible = DEBUG
|
||||
findPreference(getString(R.string.pref_key_notification_debug)).isVisible = appInfo.isDebug
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
||||
|
@ -33,7 +33,7 @@ class SettingsPresenter @Inject constructor(
|
||||
Timber.i("Change settings $key")
|
||||
preferencesRepository.apply {
|
||||
when (key) {
|
||||
serviceEnableKey -> syncManager.run { if (isServiceEnabled) startSyncWorker() else stopSyncWorker() }
|
||||
serviceEnableKey -> with(syncManager) { if (isServiceEnabled) startSyncWorker() else stopSyncWorker() }
|
||||
servicesIntervalKey, servicesOnlyWifiKey -> syncManager.startSyncWorker(true)
|
||||
isDebugNotificationEnableKey -> chuckCollector.showNotification(isDebugNotificationEnable)
|
||||
appThemeKey -> view?.recreateView()
|
||||
|
28
app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt
Normal file
28
app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt
Normal file
@ -0,0 +1,28 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.os.Build.MANUFACTURER
|
||||
import android.os.Build.MODEL
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import io.github.wulkanowy.BuildConfig.CRASHLYTICS_ENABLED
|
||||
import io.github.wulkanowy.BuildConfig.DEBUG
|
||||
import io.github.wulkanowy.BuildConfig.VERSION_CODE
|
||||
import io.github.wulkanowy.BuildConfig.VERSION_NAME
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
open class AppInfo {
|
||||
|
||||
open val isCrashlyticsEnabled get() = CRASHLYTICS_ENABLED
|
||||
|
||||
open val isDebug get() = DEBUG
|
||||
|
||||
open val versionCode get() = VERSION_CODE
|
||||
|
||||
open val versionName get() = VERSION_NAME
|
||||
|
||||
open val systemVersion get() = SDK_INT
|
||||
|
||||
open val systemManufacturer: String get() = MANUFACTURER
|
||||
|
||||
open val systemModel: String get() = MODEL
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
inline fun String?.ifNullOrBlank(defaultValue: () -> String) = if (this.isNullOrBlank()) defaultValue() else this
|
@ -1,14 +1,8 @@
|
||||
Wersja 0.9.0
|
||||
|
||||
Dodaliśmy:
|
||||
- zarządzanie dostępem mobilnym do dziennika
|
||||
- wyświetlanie sumy punktów (jeśli dziennik obsługuje)
|
||||
- wyświetlanie informacji o wygasłej sesji, gdy zostanie zmienione hasło
|
||||
Wersja 0.9.3
|
||||
|
||||
Naprawiliśmy:
|
||||
- wykrywanie uczniów przy logowaniu, jeśli symbol zawiera cyfry
|
||||
- błędne wyświetlanie średniej
|
||||
- synchronizację w tle na danych komórkowych przy domyślnych ustawieniach
|
||||
- rzadkie błędy podczas ładowania szczęśliwego numerka
|
||||
- problemy z logowaniem jeśli symbol zawierał cyfry
|
||||
- bardzo rzadkie problemy z ładowaniem ocen
|
||||
- jeszcze rzadsze problemy ze stabilnością podczas logowania
|
||||
|
||||
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
||||
|
@ -20,7 +20,7 @@
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="10dp"
|
||||
android:alpha="0.0">
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -253,6 +253,7 @@
|
||||
<string name="pref_view_header">Wygląd</string>
|
||||
<string name="pref_view_list">Domyślny widok</string>
|
||||
<string name="pref_view_grade_average_mode">Obliczanie średniej końcoworocznej</string>
|
||||
<string name="pref_view_grade_average_force_calc">Wymuś obliczanie średniej przez aplikację</string>
|
||||
<string name="pref_view_present">Pokazuj obecność we frekwencji</string>
|
||||
<string name="pref_view_app_theme">Motyw aplikacji</string>
|
||||
<string name="pref_view_expand_grade">Rozwiń oceny</string>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<item>2 godziny</item>
|
||||
<item>6 godzin</item>
|
||||
<item>12 godzin</item>
|
||||
<item>24 godzin</item>
|
||||
<item>24 godziny</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="app_theme_entries">
|
||||
|
@ -6,6 +6,7 @@
|
||||
<string name="pref_key_grade_color_scheme">grade_color_scheme</string>
|
||||
<string name="pref_key_expand_grade">expand_grade</string>
|
||||
<string name="pref_key_grade_average_mode">grade_average_mode</string>
|
||||
<string name="pref_key_grade_average_force_calc">grade_average_always_calc</string>
|
||||
<string name="pref_key_services_enable">services_enable</string>
|
||||
<string name="pref_key_services_interval">services_interval</string>
|
||||
<string name="pref_key_services_wifi_only">services_disable_wifi_only</string>
|
||||
|
@ -237,6 +237,7 @@
|
||||
<string name="pref_view_header">Appearance</string>
|
||||
<string name="pref_view_list">Default view</string>
|
||||
<string name="pref_view_grade_average_mode">Calculation of the end-of-year average</string>
|
||||
<string name="pref_view_grade_average_force_calc">Force average calculation by app</string>
|
||||
<string name="pref_view_present">Show presence in attendance</string>
|
||||
<string name="pref_view_app_theme">Application theme</string>
|
||||
<string name="pref_view_expand_grade">Expand grades</string>
|
||||
|
@ -105,6 +105,11 @@
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_view_grade_average_mode"
|
||||
app:iconSpaceReserved="false" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="@string/pref_key_grade_average_force_calc"
|
||||
android:title="@string/pref_view_grade_average_force_calc"
|
||||
app:iconSpaceReserved="false" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="@string/pref_key_fill_message_content"
|
||||
|
@ -4,9 +4,21 @@ import android.content.Context
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import com.crashlytics.android.core.CrashlyticsCore
|
||||
import io.fabric.sdk.android.Fabric
|
||||
import io.github.wulkanowy.BuildConfig
|
||||
import timber.log.Timber
|
||||
|
||||
fun initCrashlytics(context: Context, appInfo: AppInfo) {
|
||||
Fabric.with(Fabric.Builder(context)
|
||||
.kits(
|
||||
Crashlytics.Builder()
|
||||
.core(CrashlyticsCore.Builder()
|
||||
.disabled(!appInfo.isCrashlyticsEnabled)
|
||||
.build())
|
||||
.build()
|
||||
)
|
||||
.debuggable(appInfo.isDebug)
|
||||
.build())
|
||||
}
|
||||
|
||||
class CrashlyticsTree : Timber.Tree() {
|
||||
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
@ -17,9 +29,3 @@ class CrashlyticsTree : Timber.Tree() {
|
||||
else Crashlytics.logException(t)
|
||||
}
|
||||
}
|
||||
|
||||
fun initCrashlytics(context: Context) {
|
||||
Fabric.with(Fabric.Builder(context).kits(
|
||||
Crashlytics.Builder().core(CrashlyticsCore.Builder().disabled(!BuildConfig.CRASHLYTICS_ENABLED).build()).build()
|
||||
).debuggable(BuildConfig.DEBUG).build())
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ class GradeAverageProviderTest {
|
||||
|
||||
doReturn(.33).`when`(preferencesRepository).gradeMinusModifier
|
||||
doReturn(.33).`when`(preferencesRepository).gradePlusModifier
|
||||
doReturn(false).`when`(preferencesRepository).gradeAverageForceCalc
|
||||
|
||||
doReturn(Single.just(firstGrades)).`when`(gradeRepository).getGrades(student, semesters[1], true)
|
||||
doReturn(Single.just(secondGrade)).`when`(gradeRepository).getGrades(student, semesters[2], true)
|
||||
@ -128,6 +129,24 @@ class GradeAverageProviderTest {
|
||||
assertEquals(3.26, averages["Fizyka"])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onlyOneSemester_averageFromSummary_forceCalc() {
|
||||
doReturn(true).`when`(preferencesRepository).gradeAverageForceCalc
|
||||
doReturn("all_year").`when`(preferencesRepository).gradeAverageMode
|
||||
doReturn(Single.just(firstGrades)).`when`(gradeRepository).getGrades(student, semesters[1], false)
|
||||
doReturn(Single.just(listOf(
|
||||
getSummary(22, "Matematyka", 3.1),
|
||||
getSummary(22, "Fizyka", 3.26)
|
||||
))).`when`(gradeSummaryRepository).getGradesSummary(semesters[2], true)
|
||||
|
||||
val averages = gradeAverageProvider.getGradeAverage(student, semesters, semesters[2].semesterId, true)
|
||||
.blockingGet()
|
||||
|
||||
assertEquals(2, averages.size)
|
||||
assertEquals(3.0, averages["Matematyka"])
|
||||
assertEquals(3.25, averages["Fizyka"])
|
||||
}
|
||||
|
||||
private fun getGrade(semesterId: Int, subject: String, value: Int): Grade {
|
||||
return Grade(
|
||||
studentId = 101,
|
||||
|
@ -4,6 +4,7 @@ import io.github.wulkanowy.TestSchedulersProvider
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.reactivex.Single
|
||||
import org.junit.Before
|
||||
@ -33,13 +34,16 @@ class LoginFormPresenterTest {
|
||||
@Mock
|
||||
lateinit var analytics: FirebaseAnalyticsHelper
|
||||
|
||||
@Mock
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
private lateinit var presenter: LoginFormPresenter
|
||||
|
||||
@Before
|
||||
fun initPresenter() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
clearInvocations(repository, loginFormView)
|
||||
presenter = LoginFormPresenter(TestSchedulersProvider(), repository, errorHandler, analytics, false)
|
||||
presenter = LoginFormPresenter(TestSchedulersProvider(), repository, errorHandler, analytics, appInfo)
|
||||
presenter.onAttachView(loginFormView)
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ buildscript {
|
||||
classpath "io.fabric.tools:gradle:1.29.0"
|
||||
classpath "com.github.triplet.gradle:play-publisher:2.2.1"
|
||||
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1"
|
||||
classpath "gradle.plugin.com.star-zero.gradle:githook:1.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user