forked from github/wulkanowy-mirror
Merge branch 'release/0.9.2'
This commit is contained in:
commit
5c185c5eca
@ -11,9 +11,10 @@ cache:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
|
||||
#branches:
|
||||
# only:
|
||||
# - develop
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- 0.9.2
|
||||
|
||||
android:
|
||||
licenses:
|
||||
|
@ -17,8 +17,8 @@ android {
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 28
|
||||
versionCode 39
|
||||
versionName "0.9.1"
|
||||
versionCode 40
|
||||
versionName "0.9.2"
|
||||
multiDexEnabled true
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
@ -98,18 +98,23 @@ play {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'io.github.wulkanowy:api:0.9.1'
|
||||
implementation "io.github.wulkanowy:api:0.9.2"
|
||||
|
||||
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 "com.google.android.material:material:1.1.0-alpha05"
|
||||
implementation 'com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f'
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
|
||||
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 "androidx.work:work-runtime:2.0.1"
|
||||
implementation "androidx.work:work-rxjava2:2.0.1"
|
||||
@ -121,51 +126,51 @@ dependencies {
|
||||
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 "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'
|
||||
}
|
||||
}
|
||||
|
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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
|
||||
|
@ -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,25 @@ 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 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()
|
||||
|
@ -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
|
||||
}
|
@ -1,14 +1,9 @@
|
||||
Wersja 0.9.0
|
||||
|
||||
Dodaliśmy:
|
||||
- zarządzanie dostępem mobilnym do dziennika
|
||||
- wyświetlanie sumy punktów
|
||||
- wyświetlanie informacji o wygasłej sesji, gdy zostanie zmienione hasło
|
||||
Wersja 0.9.2
|
||||
|
||||
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
|
||||
- ustawienia synchronizacji w tle
|
||||
- ręczne odświeżanie ocen jeśli średnia była pobierana z dziennika
|
||||
- wygląd ładowania w widoku Dostęp Mobilny
|
||||
- sporadyczne awarie aplikacji na starszych urządzeniach
|
||||
|
||||
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"
|
||||
|
@ -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">
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user