-
-
-
- %SUBJECT% | Wulkanowy
-
-
-
-%SUBJECT%
-
-
- %INFO%
-
-
-
-
-
Treść wiadomości
- %CONTENT%
-
-
-
diff --git a/app/src/main/assets/wulkanowy-logo-black.svg b/app/src/main/assets/wulkanowy-logo-black.svg
deleted file mode 100644
index 9bfbe2c02..000000000
--- a/app/src/main/assets/wulkanowy-logo-black.svg
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
\ No newline at end of file
diff --git a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
index 0e6055aac..96ec7cb84 100644
--- a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
+++ b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
@@ -1,33 +1,37 @@
package io.github.wulkanowy
-import android.app.Application
import android.content.Context
import android.util.Log.DEBUG
import android.util.Log.INFO
import android.util.Log.VERBOSE
-import android.webkit.WebView
-import androidx.hilt.work.HiltWorkerFactory
import androidx.multidex.MultiDex
import androidx.work.Configuration
+import com.jakewharton.threetenabp.AndroidThreeTen
import com.yariksoffice.lingver.Lingver
-import dagger.hilt.android.HiltAndroidApp
+import dagger.android.AndroidInjector
+import dagger.android.support.DaggerApplication
+import eu.davidea.flexibleadapter.FlexibleAdapter
+import eu.davidea.flexibleadapter.utils.Log
import fr.bipi.tressence.file.FileLoggerTree
-import io.github.wulkanowy.data.repositories.PreferencesRepository
+import io.github.wulkanowy.di.DaggerAppComponent
+import io.github.wulkanowy.services.sync.SyncWorkerFactory
import io.github.wulkanowy.ui.base.ThemeManager
import io.github.wulkanowy.utils.ActivityLifecycleLogger
-import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.AppInfo
-import io.github.wulkanowy.utils.CrashLogExceptionTree
-import io.github.wulkanowy.utils.CrashLogTree
+import io.github.wulkanowy.utils.CrashlyticsExceptionTree
+import io.github.wulkanowy.utils.CrashlyticsTree
import io.github.wulkanowy.utils.DebugLogTree
+import io.github.wulkanowy.utils.initCrashlytics
+import io.reactivex.exceptions.UndeliverableException
+import io.reactivex.plugins.RxJavaPlugins
import timber.log.Timber
+import java.io.IOException
import javax.inject.Inject
-@HiltAndroidApp
-class WulkanowyApp : Application(), Configuration.Provider {
+class WulkanowyApp : DaggerApplication(), Configuration.Provider {
@Inject
- lateinit var workerFactory: HiltWorkerFactory
+ lateinit var workerFactory: SyncWorkerFactory
@Inject
lateinit var themeManager: ThemeManager
@@ -35,12 +39,6 @@ class WulkanowyApp : Application(), Configuration.Provider {
@Inject
lateinit var appInfo: AppInfo
- @Inject
- lateinit var preferencesRepository: PreferencesRepository
-
- @Inject
- lateinit var analyticsHelper: AnalyticsHelper
-
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
MultiDex.install(this)
@@ -48,45 +46,43 @@ class WulkanowyApp : Application(), Configuration.Provider {
override fun onCreate() {
super.onCreate()
-
- initializeAppLanguage()
+ AndroidThreeTen.init(this)
+ RxJavaPlugins.setErrorHandler(::onError)
+ Lingver.init(this)
themeManager.applyDefaultTheme()
+
initLogging()
- fixWebViewLocale()
+ initCrashlytics(this, appInfo)
}
private fun initLogging() {
if (appInfo.isDebug) {
+ FlexibleAdapter.enableLogs(Log.Level.DEBUG)
Timber.plant(DebugLogTree())
- Timber.plant(
- FileLoggerTree.Builder()
- .withFileName("wulkanowy.%g.log")
- .withDirName(applicationContext.filesDir.absolutePath)
- .withFileLimit(10)
- .withMinPriority(DEBUG)
- .build()
+ Timber.plant(FileLoggerTree.Builder()
+ .withFileName("wulkanowy.%g.log")
+ .withDirName(applicationContext.filesDir.absolutePath)
+ .withFileLimit(10)
+ .withMinPriority(DEBUG)
+ .build()
)
} else {
- Timber.plant(CrashLogExceptionTree())
- Timber.plant(CrashLogTree())
+ Timber.plant(CrashlyticsExceptionTree())
+ Timber.plant(CrashlyticsTree())
}
registerActivityLifecycleCallbacks(ActivityLifecycleLogger())
}
- private fun initializeAppLanguage() {
- Lingver.init(this)
-
- if (preferencesRepository.appLanguage == "system") {
- Lingver.getInstance().setFollowSystemLocale(this)
- analyticsHelper.logEvent("language", "startup" to appInfo.systemLanguage)
- } else {
- analyticsHelper.logEvent("language", "startup" to preferencesRepository.appLanguage)
- }
+ private fun onError(error: Throwable) {
+ //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
}
- private fun fixWebViewLocale() {
- //https://stackoverflow.com/questions/40398528/android-webview-language-changes-abruptly-on-android-7-0-and-above
- WebView(this).destroy()
+ override fun applicationInjector(): AndroidInjector {
+ return DaggerAppComponent.factory().create(this)
}
override fun getWorkManagerConfiguration() = Configuration.Builder()
diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt
index 8b850659d..43c27c529 100644
--- a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt
@@ -5,49 +5,47 @@ import android.content.SharedPreferences
import android.content.res.AssetManager
import android.content.res.Resources
import androidx.preference.PreferenceManager
+import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
+import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.strategy.WalledGardenInternetObservingStrategy
import com.chuckerteam.chucker.api.ChuckerCollector
import com.chuckerteam.chucker.api.ChuckerInterceptor
import com.chuckerteam.chucker.api.RetentionManager
import dagger.Module
import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.qualifiers.ApplicationContext
-import dagger.hilt.components.SingletonComponent
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.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.sdk.Sdk
import timber.log.Timber
import javax.inject.Singleton
@Module
-@InstallIn(SingletonComponent::class)
internal class RepositoryModule {
@Singleton
@Provides
- fun provideSdk(chuckerCollector: ChuckerCollector, @ApplicationContext context: Context): Sdk {
+ fun provideInternetObservingSettings(): InternetObservingSettings {
+ return InternetObservingSettings.builder()
+ .strategy(WalledGardenInternetObservingStrategy())
+ .build()
+ }
+
+ @Singleton
+ @Provides
+ fun provideSdk(chuckerCollector: ChuckerCollector, context: Context): Sdk {
return Sdk().apply {
androidVersion = android.os.Build.VERSION.RELEASE
buildTag = android.os.Build.MODEL
setSimpleHttpLogger { Timber.d(it) }
// for debug only
- addInterceptor(
- ChuckerInterceptor.Builder(context)
- .collector(chuckerCollector)
- .alwaysReadResponseBody(true)
- .build(), network = true
- )
+ addInterceptor(ChuckerInterceptor(context, chuckerCollector), true)
}
}
@Singleton
@Provides
- fun provideChuckerCollector(
- @ApplicationContext context: Context,
- prefRepository: PreferencesRepository
- ): ChuckerCollector {
+ fun provideChuckerCollector(context: Context, prefRepository: PreferencesRepository): ChuckerCollector {
return ChuckerCollector(
context = context,
showNotification = prefRepository.isDebugNotificationEnable,
@@ -57,23 +55,19 @@ internal class RepositoryModule {
@Singleton
@Provides
- fun provideDatabase(
- @ApplicationContext context: Context,
- sharedPrefProvider: SharedPrefProvider,
- ) = AppDatabase.newInstance(context, sharedPrefProvider)
+ fun provideDatabase(context: Context, sharedPrefProvider: SharedPrefProvider) = AppDatabase.newInstance(context, sharedPrefProvider)
@Singleton
@Provides
- fun provideResources(@ApplicationContext context: Context): Resources = context.resources
+ fun provideResources(context: Context): Resources = context.resources
@Singleton
@Provides
- fun provideAssets(@ApplicationContext context: Context): AssetManager = context.assets
+ fun provideAssets(context: Context): AssetManager = context.assets
@Singleton
@Provides
- fun provideSharedPref(@ApplicationContext context: Context): SharedPreferences =
- PreferenceManager.getDefaultSharedPreferences(context)
+ fun provideSharedPref(context: Context): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
@Singleton
@Provides
@@ -93,16 +87,11 @@ internal class RepositoryModule {
@Singleton
@Provides
- fun provideGradePartialStatisticsDao(database: AppDatabase) = database.gradePartialStatisticsDao
+ fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics
@Singleton
@Provides
- fun provideGradeSemesterStatisticsDao(database: AppDatabase) =
- database.gradeSemesterStatisticsDao
-
- @Singleton
- @Provides
- fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatisticsDao
+ fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatistics
@Singleton
@Provides
@@ -167,16 +156,4 @@ internal class RepositoryModule {
@Singleton
@Provides
fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao
-
- @Singleton
- @Provides
- fun provideConferenceDao(database: AppDatabase) = database.conferenceDao
-
- @Singleton
- @Provides
- fun provideTimetableAdditionalDao(database: AppDatabase) = database.timetableAdditionalDao
-
- @Singleton
- @Provides
- fun provideStudentInfoDao(database: AppDatabase) = database.studentInfoDao
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/Resource.kt b/app/src/main/java/io/github/wulkanowy/data/Resource.kt
deleted file mode 100644
index 406440c83..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/Resource.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package io.github.wulkanowy.data
-
-data class Resource(val status: Status, val data: T?, val error: Throwable?) {
- companion object {
- fun success(data: T?): Resource {
- return Resource(Status.SUCCESS, data, null)
- }
-
- fun error(error: Throwable?, data: T? = null): Resource {
- return Resource(Status.ERROR, data, error)
- }
-
- fun loading(data: T? = null): Resource {
- return Resource(Status.LOADING, data, null)
- }
- }
-}
-
-enum class Status {
- LOADING,
- SUCCESS,
- ERROR
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt
index 806f0c9d1..762c52f8f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt
@@ -10,12 +10,10 @@ import androidx.room.migration.Migration
import io.github.wulkanowy.data.db.dao.AttendanceDao
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
-import io.github.wulkanowy.data.db.dao.ConferenceDao
import io.github.wulkanowy.data.db.dao.ExamDao
import io.github.wulkanowy.data.db.dao.GradeDao
-import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
-import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao
+import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
import io.github.wulkanowy.data.db.dao.HomeworkDao
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
@@ -28,20 +26,16 @@ import io.github.wulkanowy.data.db.dao.ReportingUnitDao
import io.github.wulkanowy.data.db.dao.SchoolDao
import io.github.wulkanowy.data.db.dao.SemesterDao
import io.github.wulkanowy.data.db.dao.StudentDao
-import io.github.wulkanowy.data.db.dao.StudentInfoDao
import io.github.wulkanowy.data.db.dao.SubjectDao
import io.github.wulkanowy.data.db.dao.TeacherDao
-import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao
import io.github.wulkanowy.data.db.dao.TimetableDao
import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.db.entities.CompletedLesson
-import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.data.db.entities.Grade
-import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
-import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
+import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Homework
import io.github.wulkanowy.data.db.entities.LuckyNumber
@@ -54,11 +48,9 @@ import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.data.db.entities.School
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.db.entities.StudentInfo
import io.github.wulkanowy.data.db.entities.Subject
import io.github.wulkanowy.data.db.entities.Teacher
import io.github.wulkanowy.data.db.entities.Timetable
-import io.github.wulkanowy.data.db.entities.TimetableAdditional
import io.github.wulkanowy.data.db.migrations.Migration10
import io.github.wulkanowy.data.db.migrations.Migration11
import io.github.wulkanowy.data.db.migrations.Migration12
@@ -76,14 +68,7 @@ import io.github.wulkanowy.data.db.migrations.Migration22
import io.github.wulkanowy.data.db.migrations.Migration23
import io.github.wulkanowy.data.db.migrations.Migration24
import io.github.wulkanowy.data.db.migrations.Migration25
-import io.github.wulkanowy.data.db.migrations.Migration26
-import io.github.wulkanowy.data.db.migrations.Migration27
-import io.github.wulkanowy.data.db.migrations.Migration28
-import io.github.wulkanowy.data.db.migrations.Migration29
import io.github.wulkanowy.data.db.migrations.Migration3
-import io.github.wulkanowy.data.db.migrations.Migration30
-import io.github.wulkanowy.data.db.migrations.Migration31
-import io.github.wulkanowy.data.db.migrations.Migration32
import io.github.wulkanowy.data.db.migrations.Migration4
import io.github.wulkanowy.data.db.migrations.Migration5
import io.github.wulkanowy.data.db.migrations.Migration6
@@ -103,9 +88,8 @@ import javax.inject.Singleton
AttendanceSummary::class,
Grade::class,
GradeSummary::class,
- GradePartialStatistics::class,
+ GradeStatistics::class,
GradePointsStatistics::class,
- GradeSemesterStatistics::class,
Message::class,
MessageAttachment::class,
Note::class,
@@ -117,10 +101,7 @@ import javax.inject.Singleton
Recipient::class,
MobileDevice::class,
Teacher::class,
- School::class,
- Conference::class,
- TimetableAdditional::class,
- StudentInfo::class,
+ School::class
],
version = AppDatabase.VERSION_SCHEMA,
exportSchema = true
@@ -129,7 +110,7 @@ import javax.inject.Singleton
abstract class AppDatabase : RoomDatabase() {
companion object {
- const val VERSION_SCHEMA = 32
+ const val VERSION_SCHEMA = 25
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array {
return arrayOf(
@@ -156,14 +137,7 @@ abstract class AppDatabase : RoomDatabase() {
Migration22(),
Migration23(),
Migration24(),
- Migration25(),
- Migration26(),
- Migration27(),
- Migration28(),
- Migration29(),
- Migration30(),
- Migration31(),
- Migration32()
+ Migration25()
)
}
@@ -193,11 +167,9 @@ abstract class AppDatabase : RoomDatabase() {
abstract val gradeSummaryDao: GradeSummaryDao
- abstract val gradePartialStatisticsDao: GradePartialStatisticsDao
+ abstract val gradeStatistics: GradeStatisticsDao
- abstract val gradePointsStatisticsDao: GradePointsStatisticsDao
-
- abstract val gradeSemesterStatisticsDao: GradeSemesterStatisticsDao
+ abstract val gradePointsStatistics: GradePointsStatisticsDao
abstract val messagesDao: MessagesDao
@@ -222,10 +194,4 @@ abstract class AppDatabase : RoomDatabase() {
abstract val teacherDao: TeacherDao
abstract val schoolDao: SchoolDao
-
- abstract val conferenceDao: ConferenceDao
-
- abstract val timetableAdditionalDao: TimetableAdditionalDao
-
- abstract val studentInfoDao: StudentInfoDao
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt
index def0b3715..294f73d3d 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt
@@ -1,31 +1,21 @@
package io.github.wulkanowy.data.db
import androidx.room.TypeConverter
-import com.squareup.moshi.Moshi
-import com.squareup.moshi.Types
-import io.github.wulkanowy.data.db.adapters.PairAdapterFactory
-import java.time.Instant
-import java.time.LocalDate
-import java.time.LocalDateTime
-import java.time.Month
-import java.time.ZoneOffset
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import org.threeten.bp.DateTimeUtils
+import org.threeten.bp.Instant
+import org.threeten.bp.LocalDate
+import org.threeten.bp.LocalDateTime
+import org.threeten.bp.Month
+import org.threeten.bp.ZoneOffset
import java.util.Date
class Converters {
- private val moshi by lazy { Moshi.Builder().add(PairAdapterFactory).build() }
-
- private val integerListAdapter by lazy {
- moshi.adapter>(Types.newParameterizedType(List::class.java, Integer::class.java))
- }
-
- private val stringListPairAdapter by lazy {
- moshi.adapter>>(Types.newParameterizedType(List::class.java, Pair::class.java, String::class.java, String::class.java))
- }
-
@TypeConverter
fun timestampToDate(value: Long?): LocalDate? = value?.run {
- Date(value).toInstant().atZone(ZoneOffset.UTC).toLocalDate()
+ DateTimeUtils.toInstant(Date(value)).atZone(ZoneOffset.UTC).toLocalDate()
}
@TypeConverter
@@ -50,22 +40,22 @@ class Converters {
fun intToMonth(value: Int?) = value?.let { Month.of(it) }
@TypeConverter
- fun intListToJson(list: List): String {
- return integerListAdapter.toJson(list)
+ fun intListToGson(list: List): String {
+ return Gson().toJson(list)
}
@TypeConverter
- fun jsonToIntList(value: String): List {
- return integerListAdapter.fromJson(value).orEmpty()
+ fun gsonToIntList(value: String): List {
+ return Gson().fromJson(value, object : TypeToken>() {}.type)
}
@TypeConverter
- fun stringPairListToJson(list: List>): String {
- return stringListPairAdapter.toJson(list)
+ fun stringPairListToGson(list: List>): String {
+ return Gson().toJson(list)
}
@TypeConverter
- fun jsonToStringPairList(value: String): List> {
- return stringListPairAdapter.fromJson(value).orEmpty()
+ fun gsonToStringPairList(value: String): List> {
+ return Gson().fromJson(value, object : TypeToken>>() {}.type)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
index 9301d5fa9..4a4aaf74f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
@@ -6,9 +6,7 @@ import javax.inject.Inject
import javax.inject.Singleton
@Singleton
-class SharedPrefProvider @Inject constructor(
- private val sharedPref: SharedPreferences
-) {
+class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) {
companion object {
const val APP_VERSION_CODE_KEY = "app_version_code"
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt b/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt
deleted file mode 100644
index 4a9b168dd..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-package io.github.wulkanowy.data.db.adapters
-
-import com.squareup.moshi.JsonAdapter
-import com.squareup.moshi.JsonReader
-import com.squareup.moshi.JsonWriter
-import com.squareup.moshi.Moshi
-import com.squareup.moshi.Types
-import java.lang.reflect.ParameterizedType
-import java.lang.reflect.Type
-
-object PairAdapterFactory : JsonAdapter.Factory {
-
- override fun create(type: Type, annotations: MutableSet, moshi: Moshi): JsonAdapter<*>? {
- if (type !is ParameterizedType || List::class.java != type.rawType) return null
- if (type.actualTypeArguments[0] != Pair::class.java) return null
-
- val listType = Types.newParameterizedType(List::class.java, Map::class.java, String::class.java)
- val listAdapter = moshi.adapter>>(listType)
-
- val mapType = Types.newParameterizedType(MutableMap::class.java, String::class.java, String::class.java)
- val mapAdapter = moshi.adapter