[App] Refactor app core modules, use Timber for logging (#205)

* [App] Fix config migration issues

* Move .sync to .core

* Move .firebase, .network, .managers, .receivers, .sync to .core

* Replace HyperLog with Timber

* Cleanup logs every 7 days

* Rename NotificationChannelManager, reformat App

* Create FirebaseManager, ShortcutManager
This commit is contained in:
Kuba Szczodrzyński 2024-07-01 22:35:11 +02:00 committed by GitHub
parent 77e1acbb1e
commit e1dbc2f050
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
151 changed files with 3324 additions and 858 deletions

View File

@ -240,11 +240,11 @@ dependencies {
implementation "com.github.ChuckerTeam.Chucker:library:3.5.2" // https://github.com/ChuckerTeam/chucker
implementation "com.github.antonKozyriatskyi:CircularProgressIndicator:1.2.2" // https://github.com/antonKozyriatskyi/CircularProgressIndicator
implementation "com.github.bassaer:chatmessageview:2.0.1" // https://github.com/bassaer/ChatMessageView
implementation "com.github.hypertrack:hyperlog-android:0.0.10" // https://github.com/hypertrack/hyperlog-android
implementation "com.github.smuyyh:JsonViewer:V1.0.6" // https://github.com/smuyyh/JsonViewer
implementation "com.github.underwindfall.PowerPermission:powerpermission-coroutines:1.4.0" // https://github.com/underwindfall/PowerPermission
implementation "com.github.underwindfall.PowerPermission:powerpermission:1.4.0" // https://github.com/underwindfall/PowerPermission
implementation "com.github.wulkanowy.uonet-request-signer:hebe-jvm:a99ca50a31" // https://github.com/wulkanowy/uonet-request-signer
implementation 'com.jakewharton.timber:timber:5.0.1'
implementation "com.jaredrummler:colorpicker:1.1.0"
implementation "io.coil-kt:coil:1.1.1"
implementation "me.dm7.barcodescanner:zxing:1.9.8"

View File

@ -37,7 +37,7 @@
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.luckynumber.WidgetLuckyNumberProvider
-keep class pl.szczodrzynski.edziennik.data.config.AppData { *; }
-keep class pl.szczodrzynski.edziennik.data.config.AppData$** { *; }
-keep class pl.szczodrzynski.edziennik.utils.managers.TextStylingManager$HtmlMode { *; }
-keep class pl.szczodrzynski.edziennik.core.manager.TextStylingManager$HtmlMode { *; }
-keepnames class androidx.appcompat.view.menu.MenuBuilder { setHeaderTitleInt(java.lang.CharSequence); }
-keepnames class androidx.appcompat.view.menu.MenuPopupHelper { showPopup(int, int, boolean, boolean); }

File diff suppressed because it is too large Load Diff

View File

@ -173,7 +173,7 @@
| | \ \ __/ (_| __/ |\ V / __/ | \__ \
|_| \_\___|\___\___|_| \_/ \___|_| |___/
-->
<receiver android:name=".receivers.UserPresentReceiver"
<receiver android:name=".core.receiver.UserPresentReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
@ -186,7 +186,7 @@
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.SzkolnyReceiver"
<receiver android:name=".core.receiver.SzkolnyReceiver"
android:exported="true">
<intent-filter>
<action android:name="pl.szczodrzynski.edziennik.SZKOLNY_MAIN" />
@ -201,7 +201,7 @@
|_____/ \___|_| \_/ |_|\___\___||___/
-->
<service android:name=".data.api.ApiService" android:foregroundServiceType="dataSync"/>
<service android:name=".data.firebase.MyFirebaseService"
<service android:name=".core.firebase.MyFirebaseService"
android:exported="false" android:foregroundServiceType="dataSync">
<intent-filter android:priority="10000000">
<action android:name="com.google.firebase.MESSAGING_EVENT" />

View File

@ -4,12 +4,6 @@
package pl.szczodrzynski.edziennik
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.graphics.drawable.Icon
import android.os.Build
import android.provider.Settings
import android.util.Log
import android.widget.Toast
@ -20,12 +14,7 @@ import cat.ereza.customactivityoncrash.config.CaocConfig
import com.chuckerteam.chucker.api.ChuckerCollector
import com.chuckerteam.chucker.api.ChuckerInterceptor
import com.chuckerteam.chucker.api.RetentionManager
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.messaging.FirebaseMessaging
import com.google.gson.Gson
import com.hypertrack.hyperlog.HyperLog
import com.mikepenz.iconics.Iconics
import im.wangchao.mhttp.MHttp
import kotlinx.coroutines.CoroutineScope
@ -36,41 +25,39 @@ import kotlinx.coroutines.withContext
import me.leolin.shortcutbadger.ShortcutBadger
import okhttp3.OkHttpClient
import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.data.config.AppData
import pl.szczodrzynski.edziennik.data.config.Config
import pl.szczodrzynski.edziennik.core.manager.AttendanceManager
import pl.szczodrzynski.edziennik.core.manager.AvailabilityManager
import pl.szczodrzynski.edziennik.core.manager.BuildManager
import pl.szczodrzynski.edziennik.core.manager.EventManager
import pl.szczodrzynski.edziennik.core.manager.FirebaseManager
import pl.szczodrzynski.edziennik.core.manager.GradesManager
import pl.szczodrzynski.edziennik.core.manager.LoggingManager
import pl.szczodrzynski.edziennik.core.manager.MessageManager
import pl.szczodrzynski.edziennik.core.manager.NoteManager
import pl.szczodrzynski.edziennik.core.manager.NotificationManager
import pl.szczodrzynski.edziennik.core.manager.PermissionManager
import pl.szczodrzynski.edziennik.core.manager.ShortcutManager
import pl.szczodrzynski.edziennik.core.manager.TextStylingManager
import pl.szczodrzynski.edziennik.core.manager.TimetableManager
import pl.szczodrzynski.edziennik.core.manager.UiManager
import pl.szczodrzynski.edziennik.core.manager.UpdateManager
import pl.szczodrzynski.edziennik.core.manager.UserActionManager
import pl.szczodrzynski.edziennik.core.network.DumbCookieJar
import pl.szczodrzynski.edziennik.core.work.SyncWorker
import pl.szczodrzynski.edziennik.core.work.UpdateWorker
import pl.szczodrzynski.edziennik.data.api.events.ProfileListEmptyEvent
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
import pl.szczodrzynski.edziennik.data.config.AppData
import pl.szczodrzynski.edziennik.data.config.Config
import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.enums.LoginType
import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.MS
import pl.szczodrzynski.edziennik.ext.putExtras
import pl.szczodrzynski.edziennik.network.SSLProviderInstaller
import pl.szczodrzynski.edziennik.network.cookie.DumbCookieJar
import pl.szczodrzynski.edziennik.sync.SyncWorker
import pl.szczodrzynski.edziennik.sync.UpdateWorker
import pl.szczodrzynski.edziennik.ui.base.CrashActivity
import pl.szczodrzynski.edziennik.data.enums.NavTarget
import pl.szczodrzynski.edziennik.utils.DebugLogFormat
import pl.szczodrzynski.edziennik.utils.PermissionChecker
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.managers.AttendanceManager
import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager
import pl.szczodrzynski.edziennik.utils.managers.BuildManager
import pl.szczodrzynski.edziennik.utils.managers.EventManager
import pl.szczodrzynski.edziennik.utils.managers.GradesManager
import pl.szczodrzynski.edziennik.utils.managers.MessageManager
import pl.szczodrzynski.edziennik.utils.managers.NoteManager
import pl.szczodrzynski.edziennik.utils.managers.NotificationChannelsManager
import pl.szczodrzynski.edziennik.utils.managers.PermissionManager
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager
import pl.szczodrzynski.edziennik.utils.managers.UiManager
import pl.szczodrzynski.edziennik.utils.managers.TimetableManager
import pl.szczodrzynski.edziennik.utils.managers.UpdateManager
import pl.szczodrzynski.edziennik.utils.managers.UserActionManager
import timber.log.Timber
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
import kotlin.system.exitProcess
@ -81,7 +68,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
lateinit var db: AppDb
private set
lateinit var config: Config
// private set // for LabFragment
// private set // for LabFragment
lateinit var profile: Profile
private set
lateinit var data: AppData
@ -98,11 +86,14 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
val availabilityManager by lazy { AvailabilityManager(this) }
val buildManager by lazy { BuildManager(this) }
val eventManager by lazy { EventManager(this) }
val firebaseManager by lazy { FirebaseManager(this) }
val gradesManager by lazy { GradesManager(this) }
val loggingManager by lazy { LoggingManager(this) }
val messageManager by lazy { MessageManager(this) }
val noteManager by lazy { NoteManager(this) }
val notificationChannelsManager by lazy { NotificationChannelsManager(this) }
val notificationManager by lazy { NotificationManager(this) }
val permissionManager by lazy { PermissionManager(this) }
val shortcutManager by lazy { ShortcutManager(this) }
val textStylingManager by lazy { TextStylingManager(this) }
val timetableManager by lazy { TimetableManager(this) }
val uiManager by lazy { UiManager(this) }
@ -125,8 +116,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
get() = job + Dispatchers.Main
override val workManagerConfiguration: Configuration = Configuration.Builder()
.setMinimumLoggingLevel(Log.VERBOSE)
.build()
.setMinimumLoggingLevel(Log.VERBOSE)
.build()
val permissionChecker by lazy { PermissionChecker(this) }
val gson by lazy { Gson() }
@ -155,7 +146,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
if (devMode) {
if (enableChucker) {
val chuckerCollector = ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR)
val chuckerCollector =
ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR)
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
builder.addInterceptor(chuckerInterceptor)
}
@ -170,6 +162,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
MHttp.instance().customOkHttpClient(http)
}
val cookieJar by lazy { DumbCookieJar(this) }
/* _____ _ _
@ -180,7 +173,12 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|_____/|_|\__, |_| |_|\__,_|\__|\__,_|_| \___|
__/ |
|__*/
val deviceId: String by lazy { Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID) ?: "" }
val deviceId: String by lazy {
Settings.Secure.getString(
contentResolver,
Settings.Secure.ANDROID_ID
) ?: ""
}
private var unreadBadgesAvailable = true
/* _____ _
@ -191,225 +189,77 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
\___/|_| |_|\_____|_| \___|\__,_|\__\__*/
override fun onCreate() {
super.onCreate()
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
CaocConfig.Builder.create()
.backgroundMode(CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM)
.enabled(true)
.showErrorDetails(true)
.showRestartButton(true)
.logErrorOnRestart(true)
.trackActivities(true)
.minTimeBetweenCrashesMs(60*1000)
.errorDrawable(R.drawable.ic_rip)
.restartActivity(MainActivity::class.java)
.errorActivity(CrashActivity::class.java)
.apply()
Iconics.init(applicationContext)
Iconics.respectFontBoundsDefault = true
// initialize companion object values
// initialize Timber to enable basic logging
Timber.plant(loggingManager.logcatTree)
Timber.i("Initializing Szkolny.eu app v${BuildConfig.VERSION_NAME}")
// initialize core objects
AppData.read(this)
App.db = AppDb(this)
// read and migrate global config
App.config = Config(this)
App.config.migrate()
// add database logging to Timber
Timber.plant(loggingManager.databaseTree)
Timber.i("Initialized Szkolny.eu app v${BuildConfig.VERSION_NAME}")
devMode = config.devMode ?: BuildConfig.DEBUG
if (config.devModePassword != null)
checkDevModePassword()
enableChucker = config.enableChucker ?: devMode
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
CaocConfig.Builder.create()
.backgroundMode(CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM)
.enabled(true)
.showErrorDetails(true)
.showRestartButton(true)
.logErrorOnRestart(true)
.trackActivities(true)
.minTimeBetweenCrashesMs(60 * 1000)
.errorDrawable(R.drawable.ic_rip)
.restartActivity(MainActivity::class.java)
.errorActivity(CrashActivity::class.java)
.apply()
Iconics.init(applicationContext)
Iconics.respectFontBoundsDefault = true
Signing.getCert(this)
Utils.initializeStorageDir(this)
buildHttp()
uiManager.applyNightMode()
uiManager.applyLanguage(this)
if (devMode) {
HyperLog.initialize(this)
HyperLog.setLogLevel(Log.VERBOSE)
HyperLog.setLogFormat(DebugLogFormat(this))
}
if (!profileLoadById(config.lastProfileId)) {
val success = db.profileDao().firstId?.let { profileLoadById(it) }
if (success != true)
profileLoad(Profile(0, 0, LoginType.TEMPLATE, ""))
}
buildHttp()
launch(Dispatchers.Default) {
buildManager.fetchInstalledTime()
firebaseManager.initializeApps()
loggingManager.cleanupIfNeeded()
loggingManager.cleanupHyperLogDatabase()
notificationManager.registerAllChannels()
shortcutManager.createShortcuts()
Signing.getCert(this)
Utils.initializeStorageDir(this)
SSLProviderInstaller.install(applicationContext, this@App::buildHttp)
launch {
withContext(Dispatchers.Default) {
SSLProviderInstaller.install(applicationContext, this@App::buildHttp)
if (config.sync.enabled)
SyncWorker.scheduleNext(this@App, false)
else
SyncWorker.cancelNext(this@App)
if (config.sync.enabled)
SyncWorker.scheduleNext(this@App, false)
else
SyncWorker.cancelNext(this@App)
if (config.sync.notifyAboutUpdates)
UpdateWorker.scheduleNext(this@App, false)
else
UpdateWorker.cancelNext(this@App)
}
if (config.sync.notifyAboutUpdates)
UpdateWorker.scheduleNext(this@App, false)
else
UpdateWorker.cancelNext(this@App)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
val shortcutManager = getSystemService(ShortcutManager::class.java)
val shortcutTimetable = ShortcutInfo.Builder(this@App, "item_timetable")
.setShortLabel(getString(R.string.shortcut_timetable)).setLongLabel(getString(R.string.shortcut_timetable))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_timetable))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtras("fragmentId" to NavTarget.TIMETABLE))
.build()
val shortcutAgenda = ShortcutInfo.Builder(this@App, "item_agenda")
.setShortLabel(getString(R.string.shortcut_agenda)).setLongLabel(getString(R.string.shortcut_agenda))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_agenda))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtras("fragmentId" to NavTarget.AGENDA))
.build()
val shortcutGrades = ShortcutInfo.Builder(this@App, "item_grades")
.setShortLabel(getString(R.string.shortcut_grades)).setLongLabel(getString(R.string.shortcut_grades))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_grades))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtras("fragmentId" to NavTarget.GRADES))
.build()
val shortcutHomework = ShortcutInfo.Builder(this@App, "item_homeworks")
.setShortLabel(getString(R.string.shortcut_homework)).setLongLabel(getString(R.string.shortcut_homework))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_homework))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtras("fragmentId" to NavTarget.HOMEWORK))
.build()
val shortcutMessages = ShortcutInfo.Builder(this@App, "item_messages")
.setShortLabel(getString(R.string.shortcut_messages)).setLongLabel(getString(R.string.shortcut_messages))
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_messages))
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
.putExtras("fragmentId" to NavTarget.MESSAGES))
.build()
shortcutManager.dynamicShortcuts = listOf(
shortcutTimetable,
shortcutAgenda,
shortcutGrades,
shortcutHomework,
shortcutMessages
)
} // shortcuts - end
notificationChannelsManager.registerAllChannels()
if (config.appInstalledTime == 0L)
try {
config.appInstalledTime = packageManager.getPackageInfo(packageName, 0).firstInstallTime
config.appRateSnackbarTime = config.appInstalledTime + 7 * DAY * MS
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
}
val pushMobidziennikApp = FirebaseApp.initializeApp(
this@App,
FirebaseOptions.Builder()
.setProjectId("mobidziennik")
.setStorageBucket("mobidziennik.appspot.com")
.setDatabaseUrl("https://mobidziennik.firebaseio.com")
.setGcmSenderId("747285019373")
.setApiKey("AIzaSyCi5LmsZ5BBCQnGtrdvWnp1bWLCNP8OWQE")
.setApplicationId("1:747285019373:android:f6341bf7b158621d")
.build(),
"Mobidziennik2"
)
val pushLibrusApp = FirebaseApp.initializeApp(
this@App,
FirebaseOptions.Builder()
.setProjectId("synergiadru")
.setStorageBucket("synergiadru.appspot.com")
.setDatabaseUrl("https://synergiadru.firebaseio.com")
.setGcmSenderId("513056078587")
.setApiKey("AIzaSyDfTuEoYPKdv4aceEws1CO3n0-HvTndz-o")
.setApplicationId("1:513056078587:android:1e29083b760af544")
.build(),
"Librus"
)
val pushVulcanApp = FirebaseApp.initializeApp(
this@App,
FirebaseOptions.Builder()
.setProjectId("dzienniczekplus")
.setStorageBucket("dzienniczekplus.appspot.com")
.setDatabaseUrl("https://dzienniczekplus.firebaseio.com")
.setGcmSenderId("987828170337")
.setApiKey("AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA")
.setApplicationId("1:987828170337:android:ac97431a0a4578c3")
.build(),
"Vulcan"
)
val pushVulcanHebeApp = FirebaseApp.initializeApp(
this@App,
FirebaseOptions.Builder()
.setProjectId("dzienniczekplus")
.setStorageBucket("dzienniczekplus.appspot.com")
.setDatabaseUrl("https://dzienniczekplus.firebaseio.com")
.setGcmSenderId("987828170337")
.setApiKey("AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA")
.setApplicationId("1:987828170337:android:7e16404b9e5deaaa")
.build(),
"VulcanHebe"
)
try {
FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener { instanceIdResult ->
val token = instanceIdResult.token
d("Firebase", "Got App token: $token")
config.sync.tokenApp = token
}
FirebaseInstanceId.getInstance(pushMobidziennikApp).instanceId.addOnSuccessListener { instanceIdResult ->
val token = instanceIdResult.token
d("Firebase", "Got Mobidziennik2 token: $token")
if (token != config.sync.tokenMobidziennik) {
config.sync.tokenMobidziennik = token
config.sync.tokenMobidziennikList = listOf()
}
}
FirebaseInstanceId.getInstance(pushLibrusApp).instanceId.addOnSuccessListener { instanceIdResult ->
val token = instanceIdResult.token
d("Firebase", "Got Librus token: $token")
if (token != config.sync.tokenLibrus) {
config.sync.tokenLibrus = token
config.sync.tokenLibrusList = listOf()
}
}
FirebaseInstanceId.getInstance(pushVulcanApp).instanceId.addOnSuccessListener { instanceIdResult ->
val token = instanceIdResult.token
d("Firebase", "Got Vulcan token: $token")
if (token != config.sync.tokenVulcan) {
config.sync.tokenVulcan = token
config.sync.tokenVulcanList = listOf()
}
}
FirebaseInstanceId.getInstance(pushVulcanHebeApp).instanceId.addOnSuccessListener { instanceIdResult ->
val token = instanceIdResult.token
d("Firebase", "Got VulcanHebe token: $token")
if (token != config.sync.tokenVulcanHebe) {
config.sync.tokenVulcanHebe = token
config.sync.tokenVulcanHebeList = listOf()
}
}
FirebaseMessaging.getInstance().subscribeToTopic(packageName)
} catch (e: IllegalStateException) {
e.printStackTrace()
}
}
db.metadataDao().countUnseen().observeForever { count: Int ->
if (unreadBadgesAvailable)
unreadBadgesAvailable = ShortcutBadger.applyCount(this@App, count)
}
db.metadataDao().countUnseen().observeForever { count: Int ->
if (unreadBadgesAvailable)
unreadBadgesAvailable = ShortcutBadger.applyCount(this@App, count)
}
}
@ -418,7 +268,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
App.config.lastProfileId = profile.id
try {
App.data = AppData.get(profile.loginStoreType)
d("App", "Loaded AppData: ${App.data}")
Timber.d("Loaded AppData: ${App.data}")
// apply newly-added config overrides, if not changed by the user yet
for ((key, value) in App.data.configOverrides) {
val config = App.profile.config
@ -426,7 +276,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
config[key] = value
}
} catch (e: Exception) {
Log.e("App", "Cannot load AppData", e)
Timber.e(e, "Cannot load AppData")
Toast.makeText(this, R.string.app_cannot_load_data, Toast.LENGTH_LONG).show()
exitProcess(0)
}
@ -439,6 +289,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
}
return false
}
fun profileLoad(profileId: Int, onSuccess: (profile: Profile) -> Unit) {
launch {
val success = withContext(Dispatchers.Default) {
@ -450,6 +301,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
profileLoadLast(onSuccess)
}
}
fun profileLoadLast(onSuccess: (profile: Profile) -> Unit) {
launch {
val success = withContext(Dispatchers.Default) {
@ -457,12 +309,12 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
}
if (!success) {
EventBus.getDefault().post(ProfileListEmptyEvent())
}
else {
} else {
onSuccess(profile)
}
}
}
fun profileSave() = profileSave(profile)
fun profileSave(profile: Profile) {
if (profile.id == profileId)
@ -474,9 +326,12 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
fun checkDevModePassword() {
devMode = devMode || try {
Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", config.devModePassword) == "ok here you go it's enabled now"
Utils.AESCrypt.decrypt(
"nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=",
config.devModePassword
) == "ok here you go it's enabled now"
} catch (e: Exception) {
e.printStackTrace()
Timber.e(e)
false
}
}

View File

@ -45,10 +45,10 @@ import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.enums.FeatureType
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.sync.AppManagerDetectedEvent
import pl.szczodrzynski.edziennik.sync.SyncWorker
import pl.szczodrzynski.edziennik.sync.UpdateStateEvent
import pl.szczodrzynski.edziennik.sync.UpdateWorker
import pl.szczodrzynski.edziennik.core.work.AppManagerDetectedEvent
import pl.szczodrzynski.edziennik.core.work.SyncWorker
import pl.szczodrzynski.edziennik.core.work.UpdateStateEvent
import pl.szczodrzynski.edziennik.core.work.UpdateWorker
import pl.szczodrzynski.edziennik.ui.base.MainSnackbar
import pl.szczodrzynski.edziennik.data.enums.NavTarget
import pl.szczodrzynski.edziennik.data.enums.NavTargetLocation
@ -66,9 +66,8 @@ import pl.szczodrzynski.edziennik.ui.login.LoginActivity
import pl.szczodrzynski.edziennik.ui.messages.list.MessagesFragment
import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment
import pl.szczodrzynski.edziennik.utils.*
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type
import pl.szczodrzynski.edziennik.utils.managers.UserActionManager
import pl.szczodrzynski.edziennik.core.manager.AvailabilityManager.Error.Type
import pl.szczodrzynski.edziennik.core.manager.UserActionManager
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.navlib.*
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
@ -76,6 +75,7 @@ import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
import pl.szczodrzynski.navlib.drawer.NavDrawer
import pl.szczodrzynski.navlib.drawer.items.DrawerPrimaryItem
import timber.log.Timber
import java.io.IOException
import kotlin.coroutines.CoroutineContext
import kotlin.math.roundToInt
@ -123,18 +123,19 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
d(TAG, "Activity created")
Timber.i("Activity created")
app.uiManager.applyTheme(this)
app.uiManager.applyLanguage(this)
app.buildManager.validateBuild(this)
if (App.profileId == 0) {
Timber.i("Profile is not loaded")
onProfileListEmptyEvent(ProfileListEmptyEvent())
return
}
d(TAG, "Profile is valid, inflating views")
Timber.i("Profile is valid, inflating views")
setContentView(b.root)
@ -542,7 +543,6 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onProfileListEmptyEvent(event: ProfileListEmptyEvent) {
d(TAG, "Profile list is empty. Launch LoginActivity.")
app.config.loginFinished = false
startActivity(Intent(this, LoginActivity::class.java))
finish()
@ -617,7 +617,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
try {
startActivity(Intent(Settings.ACTION_SETTINGS))
} catch (e: Exception) {
e.printStackTrace()
Timber.e(e)
Toast.makeText(this, R.string.app_manager_open_failed, Toast.LENGTH_SHORT)
.show()
}
@ -665,11 +665,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
fun handleIntent(extras: Bundle?) {
d(TAG, "handleIntent() {")
extras?.keySet()?.forEach { key ->
d(TAG, " \"$key\": " + extras.get(key))
}
d(TAG, "}")
Timber.d("handleIntent() ${extras?.keySet()}")
val intentProfileId = extras.getIntOrNull("profileId").takePositive()
var intentNavTarget = extras.getEnum<NavTarget>("fragmentId")
@ -783,17 +779,17 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
override fun onStart() {
d(TAG, "Activity started")
Timber.i("Activity started")
super.onStart()
}
override fun onStop() {
d(TAG, "Activity stopped")
Timber.i("Activity stopped")
super.onStop()
}
override fun onResume() {
d(TAG, "Activity resumed")
Timber.i("Activity resumed")
val filter = IntentFilter()
filter.addAction(Intent.ACTION_MAIN)
ContextCompat.registerReceiver(
@ -807,14 +803,14 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
override fun onPause() {
d(TAG, "Activity paused")
Timber.i("Activity paused")
unregisterReceiver(intentReceiver)
EventBus.getDefault().unregister(this)
super.onPause()
}
override fun onDestroy() {
d(TAG, "Activity destroyed")
Timber.i("Activity destroyed")
super.onDestroy()
}
@ -868,7 +864,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
args: Bundle? = null,
skipBeforeNavigate: Boolean = false,
): Boolean {
d(TAG, "navigate(profileId = ${profile?.id ?: profileId}, target = ${navTarget?.name}, args = $args)")
Timber.d("navigate(profileId = ${profile?.id ?: profileId}, target = ${navTarget?.name}, args = $args)")
if (!(skipBeforeNavigate || navTarget == this.navTarget) && !canNavigate()) {
bottomSheet.close()
drawer.close()
@ -901,7 +897,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
args: Bundle?,
profileChanged: Boolean,
) {
d(TAG, "navigateImpl(profileId = ${profile.id}, target = ${navTarget.name}, args = $args)")
Timber.d("navigateImpl(profileId = ${profile.id}, target = ${navTarget.name}, args = $args)")
if (navTarget.featureType != null && !profile.hasUIFeature(navTarget.featureType)) {
navigateImpl(profile, NavTarget.HOME, args, profileChanged)
@ -954,7 +950,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
navView.bottomBar.fabExtended = false
navView.bottomBar.setFabOnClickListener(null)
d("NavDebug", "Navigating from ${this.navTarget.name} to ${navTarget.name}")
Timber.d("Navigating from ${this.navTarget.name} to ${navTarget.name}")
val fragment = navTarget.fragmentClass?.getDeclaredConstructor()?.newInstance() ?: return
fragment.arguments = arguments
@ -1014,9 +1010,9 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
}
d("NavDebug", "Current fragment ${navTarget.name}, back stack:")
Timber.d("Current fragment ${navTarget.name}, back stack:")
navBackStack.forEachIndexed { index, item ->
d("NavDebug", " - $index: ${item.first.name}")
Timber.d(" - $index: ${item.first.name}")
}
transaction.replace(R.id.fragment, fragment)
@ -1099,8 +1095,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
else
BitmapDrawable.createFromPath(it)
}
} catch (e: IOException) {
e.printStackTrace()
} catch (e: Exception) {
Timber.e(e)
}
}
@ -1141,7 +1137,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
fun setDrawerItems() {
d("NavDebug", "setDrawerItems() app.profile = ${app.profile}")
Timber.d("setDrawerItems() app.profile = ${app.profile}")
val drawerItems = arrayListOf<IDrawerItem<*>>()
val drawerItemsMore = arrayListOf<IDrawerItem<*>>()
val drawerItemsBottom = arrayListOf<IDrawerItem<*>>()

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
package pl.szczodrzynski.edziennik.core.firebase
class FirebaseSendException(reason: String?) : Exception(reason) {
companion object {

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
package pl.szczodrzynski.edziennik.core.firebase
import android.annotation.SuppressLint
import android.app.PendingIntent
@ -14,6 +14,7 @@ import com.google.firebase.iid.zzaz
import com.google.firebase.messaging.zzc
import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.ext.*
import timber.log.Timber
import java.util.*
import com.google.firebase.messaging.zzo.zza as logNotificationOpen
import com.google.firebase.messaging.zzo.zza as logNotificationReceived
@ -44,7 +45,7 @@ open class FirebaseService : zzc() {
try {
it.send()
} catch (e: CanceledException) {
Log.e(TAG, "Notification pending intent canceled")
Timber.e("Notification pending intent canceled")
}
}
@ -59,7 +60,7 @@ open class FirebaseService : zzc() {
final override fun zzc(intent: Intent?) {
val action = intent?.action
val json = intent?.toJsonObject()
Log.d(TAG, "zzc Intent(action=$action, extras=$json)")
Timber.d("zzc Intent(action=$action, extras=$json)")
if (action == null || json == null)
return
@ -73,12 +74,13 @@ open class FirebaseService : zzc() {
onNewToken(json.getString("token"))
}
"com.google.android.c2dm.intent.RECEIVE",
"com.google.firebase.messaging.RECEIVE_DIRECT_BOOT" -> {
"com.google.firebase.messaging.RECEIVE_DIRECT_BOOT",
-> {
val messageId = json.getString("google.message_id")
if (messageId != null) {
// send back an acknowledgement to Google Play Services
val ackBundle = Bundle(
"google.message_id" to messageId
"google.message_id" to messageId
)
zzad.zza(this).zza(2, ackBundle)
}
@ -86,7 +88,7 @@ open class FirebaseService : zzc() {
// and add it to queue
if (messageId.isNotNullNorEmpty()) {
if (messageQueue.contains(messageId)) {
Log.d(TAG, "Received duplicate message: $messageId")
Timber.d("Received duplicate message: $messageId")
return
}
if (messageQueue.size >= 10)
@ -97,7 +99,7 @@ open class FirebaseService : zzc() {
processMessage(messageId, json, intent)
}
else -> {
Log.d(TAG, "Unknown intent action: $action")
Timber.d("Unknown intent action: $action")
}
}
}
@ -128,7 +130,7 @@ open class FirebaseService : zzc() {
)
}
else -> {
Log.w(TAG, "Received message with unknown type: $it")
Timber.w("Received message with unknown type: $it")
return
}
}

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
package pl.szczodrzynski.edziennik.core.firebase
import android.content.Context
import android.util.Log
@ -11,6 +11,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.App
import timber.log.Timber
import kotlin.coroutines.CoroutineContext
class MyFirebaseService : FirebaseService(), CoroutineScope {
@ -25,17 +26,13 @@ class MyFirebaseService : FirebaseService(), CoroutineScope {
get() = job + Dispatchers.Main
override fun onNewToken(token: String?) {
Log.d(TAG, "Got new token: $token")
Timber.d("Got new token: $token")
app.config.sync.tokenApp = token
}
override fun onMessageReceived(message: Message) {
launch(Dispatchers.Default) {
Log.d(TAG, "Message received from ${message.from}: $message")
app.getSharedPreferences("firebase_service_log", Context.MODE_PRIVATE).edit().apply {
putString(System.currentTimeMillis().toString(), message.toString())
apply()
}
Timber.d("Message received from ${message.from}: $message")
val profiles = app.db.profileDao().profilesForFirebaseNow
when (message.from) {
"640759989760" -> SzkolnyAppFirebase(app, profiles, message)

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
package pl.szczodrzynski.edziennik.core.firebase
import com.google.gson.JsonParser
import com.google.gson.reflect.TypeToken

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
package pl.szczodrzynski.edziennik.core.firebase
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
package pl.szczodrzynski.edziennik.core.firebase
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
package pl.szczodrzynski.edziennik.core.firebase
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-4-28.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import com.mikepenz.iconics.typeface.IIcon
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2021-9-18.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.BuildConfig

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2021-3-27.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.content.pm.PackageManager
import android.text.TextUtils
@ -20,7 +20,9 @@ import pl.szczodrzynski.edziennik.BuildConfig
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.Intent
import pl.szczodrzynski.edziennik.ext.MS
import pl.szczodrzynski.edziennik.ext.asBoldSpannable
import pl.szczodrzynski.edziennik.ext.asColoredSpannable
import pl.szczodrzynski.edziennik.ext.concat
@ -34,7 +36,7 @@ import pl.szczodrzynski.edziennik.ext.resolveColor
import pl.szczodrzynski.edziennik.ext.toJsonObject
import pl.szczodrzynski.edziennik.ui.base.BuildInvalidActivity
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
@ -101,6 +103,18 @@ class BuildManager(val app: App) : CoroutineScope {
else -> Update.Type.RELEASE
}
fun fetchInstalledTime() {
if (app.config.appInstalledTime != 0L)
return
try {
app.config.appInstalledTime =
app.packageManager.getPackageInfo(app.packageName, 0).firstInstallTime
app.config.appRateSnackbarTime = app.config.appInstalledTime + 7 * DAY * MS
} catch (e: PackageManager.NameNotFoundException) {
Timber.e(e)
}
}
fun showVersionDialog(activity: AppCompatActivity) {
val yes = activity.getString(R.string.yes)
val no = activity.getString(R.string.no)
@ -235,7 +249,7 @@ class BuildManager(val app: App) : CoroutineScope {
fun validateBuild(activity: AppCompatActivity) {
launch {
gitRemote = getRemoteRepo()
d("BuildManager", "isSigned = $isSigned, buildType = $buildType, buildFlavor = $buildFlavor, remote = $gitRemote")
Timber.d("isSigned = $isSigned, buildType = $buildType, buildFlavor = $buildFlavor, remote = $gitRemote")
// officially signed package
if (isSigned)

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-4-3.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.widget.TextView
import androidx.core.view.isVisible

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) Kuba Szczodrzyński 2024-7-1.
*/
package pl.szczodrzynski.edziennik.core.manager
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.messaging.FirebaseMessaging
import pl.szczodrzynski.edziennik.App
import timber.log.Timber
class FirebaseManager(val app: App) {
data class Instance(
val name: String,
val projectId: String,
val projectNumber: String,
val apiKey: String,
val applicationId: String,
val onToken: (token: String) -> Unit,
)
private val instances = listOf(
Instance(
name = "Mobidziennik",
projectId = "mobidziennik",
projectNumber = "747285019373",
apiKey = "AIzaSyCi5LmsZ5BBCQnGtrdvWnp1bWLCNP8OWQE",
applicationId = "f6341bf7b158621d",
onToken = {
app.config.sync.tokenMobidziennik = it
app.config.sync.tokenMobidziennikList = listOf()
},
),
Instance(
name = "Librus",
projectId = "synergiadru",
projectNumber = "513056078587",
apiKey = "AIzaSyDfTuEoYPKdv4aceEws1CO3n0-HvTndz-o",
applicationId = "1e29083b760af544",
onToken = {
app.config.sync.tokenLibrus = it
app.config.sync.tokenLibrusList = listOf()
},
),
Instance(
name = "Vulcan",
projectId = "dzienniczekplus",
projectNumber = "987828170337",
apiKey = "AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA",
applicationId = "ac97431a0a4578c3",
onToken = {
app.config.sync.tokenVulcan = it
app.config.sync.tokenVulcanList = listOf()
},
),
Instance(
name = "VulcanHebe",
projectId = "dzienniczekplus",
projectNumber = "987828170337",
apiKey = "AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA",
applicationId = "7e16404b9e5deaaa",
onToken = {
app.config.sync.tokenVulcanHebe = it
app.config.sync.tokenVulcanHebeList = listOf()
},
),
)
fun initializeApps() {
FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener { result ->
val token = result.token
Timber.i("Got App token: $token")
app.config.sync.tokenApp = token
}
FirebaseMessaging.getInstance().subscribeToTopic(app.packageName)
instances.forEach {
val options = FirebaseOptions.Builder()
.setProjectId(it.projectId)
.setStorageBucket("${it.projectId}.appspot.com")
.setDatabaseUrl("https://${it.projectId}.firebaseio.com")
.setGcmSenderId(it.projectNumber)
.setApiKey(it.apiKey)
.setApplicationId("1:${it.projectNumber}:android:${it.applicationId}")
.build()
val instance = FirebaseApp.initializeApp(app, options, it.name)
FirebaseInstanceId.getInstance(instance).instanceId.addOnSuccessListener { result ->
val token = result.token
Timber.i("Got ${it.name} token: $token")
if (token != app.config["token${it.name}"])
it.onToken(token)
}
}
}
}

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-3-1.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.content.Context
import com.google.android.material.color.MaterialColors

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) Kuba Szczodrzyński 2024-7-1.
*/
package pl.szczodrzynski.edziennik.core.manager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.entity.LogEntry
import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.MS
import pl.szczodrzynski.edziennik.ext.ignore
import timber.log.Timber
class LoggingManager(val app: App) : CoroutineScope {
companion object {
private const val CLEANUP_INTERVAL = 2 * DAY * MS
private const val CLEANUP_MAX_AGE = 7 * DAY * MS
}
override val coroutineContext = Job() + Dispatchers.IO
val logcatTree = object : Timber.DebugTree() {
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
super.log(
priority = priority,
tag = tag?.substringBefore("$")?.let { "Szkolny/$it" },
message = message,
t = t,
)
}
}
val databaseTree = object : Timber.DebugTree() {
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) = launch {
val entry = LogEntry(
timestamp = System.currentTimeMillis(),
priority = priority,
tag = tag?.substringBefore("$"),
message = message,
)
app.db.logDao().add(entry)
}.ignore()
}
suspend fun cleanupIfNeeded(force: Boolean = false) {
if (!force && System.currentTimeMillis() - app.config.lastLogCleanupTime < CLEANUP_INTERVAL)
return
withContext(Dispatchers.IO) {
val timestamp = System.currentTimeMillis() - CLEANUP_MAX_AGE
Timber.i("Cleaning logs older than $timestamp")
app.db.logDao().clearBefore(timestamp)
}
app.config.lastLogCleanupTime = System.currentTimeMillis()
}
fun cleanupHyperLogDatabase() {
try {
app.deleteDatabase("com.hypertrack.common.device_logs.db")
} catch (e: Exception) {
Timber.e(e)
}
}
}

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2021-10-7.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.content.Context
import android.os.Bundle
@ -30,8 +30,8 @@ import pl.szczodrzynski.edziennik.ext.setText
import pl.szczodrzynski.edziennik.ui.messages.MessagesUtils
import pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.ORIGINAL
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.StylingConfig
import pl.szczodrzynski.edziennik.core.manager.TextStylingManager.HtmlMode.ORIGINAL
import pl.szczodrzynski.edziennik.core.manager.TextStylingManager.StylingConfig
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import pl.szczodrzynski.edziennik.utils.span.BoldSpan

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2021-10-17.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.annotation.SuppressLint
import android.text.SpannableStringBuilder

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-2-15.
*/
package pl.szczodrzynski.edziennik.core.manager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat.*
import androidx.core.app.NotificationManagerCompat.*
import pl.szczodrzynski.edziennik.R
class NotificationManager(val c: Context) {
data class Channel(
val id: Int,
val key: String,
val name: String,
val description: String,
val importance: Int,
val priority: Int,
val quiet: Boolean = false,
val lightColor: Int? = null
)
fun registerAllChannels() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
return
val manager = c.getSystemService(NotificationManager::class.java)
val registered = manager.notificationChannels.map { it.id }.toSet()
val all = all.map { it.key }.toSet()
val toRegister = all - registered
val toDelete = registered - all
for (key in toRegister) {
val channel = this.all.firstOrNull { it.key == key } ?: continue
manager.createNotificationChannel(NotificationChannel(key, channel.name, channel.importance).apply {
description = channel.description
if (channel.quiet) {
enableVibration(false)
setSound(null, null)
}
channel.lightColor?.let {
enableLights(true)
lightColor = it
}
})
}
for (key in toDelete) {
if (key.contains("chucker"))
continue
manager.deleteNotificationChannel(key)
}
}
val sync = Channel(
1,
"pl.szczodrzynski.edziennik.SYNC",
c.getString(R.string.notification_channel_get_data_name),
c.getString(R.string.notification_channel_get_data_desc),
IMPORTANCE_MIN,
PRIORITY_MIN,
quiet = true
)
val data = Channel(
50,
"pl.szczodrzynski.edziennik.DATA",
c.getString(R.string.notification_channel_notifications_name),
c.getString(R.string.notification_channel_notifications_desc),
IMPORTANCE_HIGH,
PRIORITY_MAX,
lightColor = 0xff2196f3.toInt()
)
val dataQuiet = Channel(
60,
"pl.szczodrzynski.edziennik.DATA_QUIET",
c.getString(R.string.notification_channel_notifications_quiet_name),
c.getString(R.string.notification_channel_notifications_quiet_desc),
IMPORTANCE_LOW,
PRIORITY_LOW,
quiet = true
)
val updates = Channel(
100,
"pl.szczodrzynski.edziennik.UPDATES",
c.getString(R.string.notification_channel_updates_name),
c.getString(R.string.notification_channel_updates_desc),
IMPORTANCE_DEFAULT,
PRIORITY_DEFAULT
)
val userAttention = Channel(
200,
"pl.szczodrzynski.edziennik.USER_ATTENTION",
c.getString(R.string.notification_channel_user_attention_name),
c.getString(R.string.notification_channel_user_attention_desc),
IMPORTANCE_DEFAULT,
PRIORITY_DEFAULT
)
val all by lazy { listOf(
sync,
data,
dataQuiet,
updates,
userAttention
) }
}

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-4-7.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.Manifest
import android.content.Intent

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) Kuba Szczodrzyński 2024-7-1.
*/
package pl.szczodrzynski.edziennik.core.manager
import android.content.Intent
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.graphics.drawable.Icon
import android.os.Build
import androidx.core.content.getSystemService
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.enums.NavTarget
import pl.szczodrzynski.edziennik.ext.putExtras
class ShortcutManager(val app: App) {
data class Shortcut(
val id: String,
val label: Int,
val icon: Int,
val target: NavTarget,
)
private val shortcuts = listOf(
Shortcut(
id = "item_timetable",
label = R.string.shortcut_timetable,
icon = R.mipmap.ic_shortcut_timetable,
target = NavTarget.TIMETABLE,
),
Shortcut(
id = "item_agenda",
label = R.string.shortcut_agenda,
icon = R.mipmap.ic_shortcut_agenda,
target = NavTarget.AGENDA,
),
Shortcut(
id = "item_grades",
label = R.string.shortcut_grades,
icon = R.mipmap.ic_shortcut_grades,
target = NavTarget.GRADES,
),
Shortcut(
id = "item_homeworks",
label = R.string.shortcut_homework,
icon = R.mipmap.ic_shortcut_homework,
target = NavTarget.HOMEWORK,
),
Shortcut(
id = "item_messages",
label = R.string.shortcut_messages,
icon = R.mipmap.ic_shortcut_messages,
target = NavTarget.MESSAGES,
),
)
fun createShortcuts() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
app.getSystemService<ShortcutManager>()?.dynamicShortcuts = shortcuts.map {
ShortcutInfo.Builder(app, it.id)
.setShortLabel(app.getString(it.label))
.setLongLabel(app.getString(it.label))
.setIcon(Icon.createWithResource(app, it.icon))
.setIntent(
Intent(Intent.ACTION_MAIN, null, app, MainActivity::class.java)
.putExtras("fragmentId" to it.target)
)
.build()
}
}
}
}

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2021-10-7.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.text.SpannableStringBuilder
import android.text.Spanned
@ -31,7 +31,7 @@ import pl.szczodrzynski.edziennik.ext.replaceSpan
import pl.szczodrzynski.edziennik.ui.dialogs.StyledTextDialog
import pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.*
import pl.szczodrzynski.edziennik.core.manager.TextStylingManager.HtmlMode.*
import pl.szczodrzynski.edziennik.utils.span.BoldSpan
import pl.szczodrzynski.edziennik.utils.span.ItalicSpan

View File

@ -2,11 +2,9 @@
* Copyright (c) Kuba Szczodrzyński 2020-3-10.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.content.Context
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.widget.TextView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -15,11 +13,8 @@ import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.data.db.full.LessonFull
import pl.szczodrzynski.edziennik.ext.resolveAttr
import pl.szczodrzynski.edziennik.ext.setText
import pl.szczodrzynski.edziennik.ext.setTintColor
import pl.szczodrzynski.edziennik.ext.startCoroutineTimer
import pl.szczodrzynski.navlib.getColorFromAttr
import kotlin.coroutines.CoroutineContext
class TimetableManager(val app: App) : CoroutineScope {

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2024-6-26.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.content.Context
import android.os.Build
@ -17,7 +17,7 @@ import pl.szczodrzynski.edziennik.data.enums.Theme
import pl.szczodrzynski.edziennik.data.enums.Theme.Mode
import pl.szczodrzynski.edziennik.data.enums.Theme.Type
import pl.szczodrzynski.edziennik.ext.isNightMode
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.util.Locale
class UiManager(val app: App) {
@ -63,7 +63,7 @@ class UiManager(val app: App) {
) {
color = Theme.BLUE
}
d(TAG, "Applying theme $color($type, $mode)")
Timber.d("Applying theme $color($type, $mode)")
color.styleRes[type to mode] ?: color.styleRes[Type.M3 to Mode.DAYNIGHT]!!
}
activity.setTheme(themeRes)

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2022-10-22.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-2-15.
*/
package pl.szczodrzynski.edziennik.utils.managers
package pl.szczodrzynski.edziennik.core.manager
import android.app.NotificationManager
import android.app.PendingIntent
@ -24,7 +24,7 @@ import pl.szczodrzynski.edziennik.ui.login.oauth.OAuthLoginActivity
import pl.szczodrzynski.edziennik.ui.login.oauth.OAuthLoginResult
import pl.szczodrzynski.edziennik.ui.login.recaptcha.RecaptchaActivity
import pl.szczodrzynski.edziennik.ui.login.recaptcha.RecaptchaResult
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class UserActionManager(val app: App) {
companion object {
@ -55,7 +55,7 @@ class UserActionManager(val app: App) {
)
val notification =
NotificationCompat.Builder(app, app.notificationChannelsManager.userAttention.key)
NotificationCompat.Builder(app, app.notificationManager.userAttention.key)
.setContentTitle(app.getString(R.string.notification_user_action_required_title))
.setContentText(text)
.setSmallIcon(R.drawable.ic_error_outline)
@ -82,7 +82,7 @@ class UserActionManager(val app: App) {
event: UserActionRequiredEvent,
callback: UserActionCallback,
) {
d(TAG, "Running user action (${event.type}) with params: ${event.params}")
Timber.d("Running user action (${event.type}) with params: ${event.params}")
val isSuccessful = when (event.type) {
UserActionRequiredEvent.Type.RECAPTCHA -> executeRecaptcha(activity, event, callback)
UserActionRequiredEvent.Type.OAUTH -> executeOauth(activity, event, callback)

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-3-24.
*/
package pl.szczodrzynski.edziennik.network.cookie
package pl.szczodrzynski.edziennik.core.network
import okhttp3.Cookie
import okhttp3.HttpUrl

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-3-24.
*/
package pl.szczodrzynski.edziennik.network.cookie
package pl.szczodrzynski.edziennik.core.network
import android.content.Context
import androidx.core.content.edit

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2019-10-1.
*/
package pl.szczodrzynski.edziennik.receivers
package pl.szczodrzynski.edziennik.core.receiver
import android.content.BroadcastReceiver
import android.content.Context

View File

@ -1,4 +1,4 @@
package pl.szczodrzynski.edziennik.receivers;
package pl.szczodrzynski.edziennik.core.receiver;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;

View File

@ -1,3 +1,3 @@
package pl.szczodrzynski.edziennik.sync
package pl.szczodrzynski.edziennik.core.work
class AppManagerDetectedEvent(val failedWorkTimestamps: List<Long>)
class AppManagerDetectedEvent(val failedWorkTimestamps: List<Long>)

View File

@ -1,4 +1,4 @@
package pl.szczodrzynski.edziennik.sync
package pl.szczodrzynski.edziennik.core.work
import android.annotation.SuppressLint
import android.content.Context
@ -6,7 +6,7 @@ import androidx.work.*
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
import pl.szczodrzynski.edziennik.ext.formatDate
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.util.concurrent.TimeUnit
class SyncWorker(val context: Context, val params: WorkerParameters) : Worker(context, params) {
@ -38,7 +38,7 @@ class SyncWorker(val context: Context, val params: WorkerParameters) : Worker(co
val syncInterval = app.config.sync.interval.toLong()
val syncAt = System.currentTimeMillis() + syncInterval*1000
d(TAG, "Scheduling work at ${syncAt.formatDate()}")
Timber.d("Scheduling work at ${syncAt.formatDate()}")
val constraints = Constraints.Builder()
.setRequiredNetworkType(
@ -61,14 +61,14 @@ class SyncWorker(val context: Context, val params: WorkerParameters) : Worker(co
* Cancel any scheduled sync job.
*/
fun cancelNext(app: App) {
d(TAG, "Cancelling work by tag $TAG")
Timber.d("Cancelling work by tag $TAG")
WorkManager.getInstance(app).cancelAllWorkByTag(TAG)
//WorkManager.getInstance(app).pruneWork() // do not prune the work in order to look for failed tasks
}
}
override fun doWork(): Result {
d(TAG, "Running worker ID ${params.id}")
Timber.d("Running worker ID ${params.id}")
EdziennikTask.sync().enqueue(context)
rescheduleNext(context as App)
return Result.success()

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2022-10-22.
*/
package pl.szczodrzynski.edziennik.sync
package pl.szczodrzynski.edziennik.core.work
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-18.
*/
package pl.szczodrzynski.edziennik.sync
package pl.szczodrzynski.edziennik.core.work
import android.annotation.SuppressLint
import android.content.Context
@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.formatDate
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
@ -43,7 +44,7 @@ class UpdateWorker(val context: Context, val params: WorkerParameters) : Worker(
val syncInterval = 4 * DAY;
val syncAt = System.currentTimeMillis() + syncInterval*1000
Utils.d(TAG, "Scheduling work at ${syncAt.formatDate()}")
Timber.d("Scheduling work at ${syncAt.formatDate()}")
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
@ -62,7 +63,7 @@ class UpdateWorker(val context: Context, val params: WorkerParameters) : Worker(
* Cancel any scheduled sync job.
*/
fun cancelNext(app: App) {
Utils.d(TAG, "Cancelling work by tag $TAG")
Timber.d("Cancelling work by tag $TAG")
WorkManager.getInstance(app).cancelAllWorkByTag(TAG)
}
}
@ -72,7 +73,7 @@ class UpdateWorker(val context: Context, val params: WorkerParameters) : Worker(
get() = job + Dispatchers.Main
override fun doWork(): Result {
Utils.d(TAG, "Running worker ID ${params.id}")
Timber.d("Running worker ID ${params.id}")
val app = context as App
if (!app.config.sync.notifyAboutUpdates) {
return Result.success()

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-18.
*/
package pl.szczodrzynski.edziennik.sync
package pl.szczodrzynski.edziennik.core.work
import android.annotation.SuppressLint
import android.os.AsyncTask
@ -14,6 +14,7 @@ import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.ext.MINUTE
import pl.szczodrzynski.edziennik.ext.formatDate
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
object WorkerUtils {
/**
@ -26,27 +27,27 @@ object WorkerUtils {
val workManager = WorkManager.getInstance(app) as WorkManagerImpl
val scheduledWork = workManager.workDatabase.workSpecDao().getScheduledWork().toMutableList()
scheduledWork.forEach {
Utils.d("WorkerUtils", "Work: ${it.id} at ${it.calculateNextRunTime().formatDate()}. State = ${it.state} (finished = ${it.state.isFinished})")
Timber.d("Work: ${it.id} at ${it.calculateNextRunTime().formatDate()}. State = ${it.state} (finished = ${it.state.isFinished})")
}
// remove finished work and other than SyncWorker
scheduledWork.removeAll { it.workerClassName != SyncWorker::class.java.canonicalName || it.isPeriodic || it.state.isFinished }
Utils.d("WorkerUtils", "Found ${scheduledWork.size} unfinished work")
Timber.d("Found ${scheduledWork.size} unfinished work")
// remove all enqueued work that had to (but didn't) run at some point in the past (at least 1min ago)
val failedWork = scheduledWork.filter { it.state == WorkInfo.State.ENQUEUED && it.calculateNextRunTime() < System.currentTimeMillis() - 1 * MINUTE * 1000 }
Utils.d("WorkerUtils", "${failedWork.size} work requests failed to start (out of ${scheduledWork.size} requests)")
Timber.d("${failedWork.size} work requests failed to start (out of ${scheduledWork.size} requests)")
if (rescheduleIfFailedFound) {
if (failedWork.isNotEmpty()) {
Utils.d("WorkerUtils", "App Manager detected!")
Timber.d("App Manager detected!")
EventBus.getDefault().postSticky(AppManagerDetectedEvent(failedWork.map { it.calculateNextRunTime() }))
}
if (scheduledWork.size - failedWork.size < 1) {
Utils.d("WorkerUtils", "No pending work found, scheduling next:")
Timber.d("No pending work found, scheduling next:")
onReschedule()
}
} else {
Utils.d("WorkerUtils", "NOT rescheduling: waiting to open the activity")
Timber.d("NOT rescheduling: waiting to open the activity")
if (scheduledWork.size < 1) {
Utils.d("WorkerUtils", "No work found *at all*, scheduling next:")
Timber.d("No work found *at all*, scheduling next:")
onReschedule()
}
}

View File

@ -23,7 +23,7 @@ import pl.szczodrzynski.edziennik.data.api.task.IApiTask
import pl.szczodrzynski.edziennik.data.api.task.SzkolnyTask
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.ext.toApiError
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import kotlin.math.min
import kotlin.math.roundToInt
@ -76,7 +76,7 @@ class ApiService : Service() {
private val taskCallback = object : EdziennikCallback {
override fun onCompleted() {
lastEventTime = System.currentTimeMillis()
d(TAG, "Task $taskRunningId (profile $taskProfileId) finished in ${System.currentTimeMillis()-taskStartTime}")
Timber.d("Task $taskRunningId (profile $taskProfileId) finished in ${System.currentTimeMillis()-taskStartTime}")
EventBus.getDefault().postSticky(ApiTaskFinishedEvent(taskProfileId))
clearTask()
@ -93,12 +93,12 @@ class ApiService : Service() {
override fun onError(apiError: ApiError) {
lastEventTime = System.currentTimeMillis()
d(TAG, "Task $taskRunningId threw an error - $apiError")
Timber.d("Task $taskRunningId threw an error - $apiError")
apiError.profileId = taskProfileId
EventBus.getDefault().postSticky(ApiTaskErrorEvent(apiError))
errorList.add(apiError)
apiError.throwable?.printStackTrace()
Timber.e(apiError.throwable)
if (apiError.isCritical) {
taskRunning?.cancel()
@ -119,7 +119,7 @@ class ApiService : Service() {
taskProgress = 0f
taskProgress += step
taskProgress = min(100f, taskProgress)
d(TAG, "Task $taskRunningId progress: ${taskProgress.roundToInt()}%")
Timber.d("Task $taskRunningId progress: ${taskProgress.roundToInt()}%")
EventBus.getDefault().post(ApiTaskProgressEvent(taskProfileId, taskProgress, taskProgressText))
notification.setProgress(taskProgress).post()
}
@ -127,7 +127,7 @@ class ApiService : Service() {
override fun onStartProgress(stringRes: Int) {
lastEventTime = System.currentTimeMillis()
taskProgressText = getString(stringRes)
d(TAG, "Task $taskRunningId progress: $taskProgressText")
Timber.d("Task $taskRunningId progress: $taskProgressText")
EventBus.getDefault().post(ApiTaskProgressEvent(taskProfileId, taskProgress, taskProgressText))
notification.setProgressText(taskProgressText).post()
}
@ -166,7 +166,7 @@ class ApiService : Service() {
taskProgress = -1f
taskProgressText = task.taskName
d(TAG, "Executing task $taskRunningId - ${task::class.java.name}")
Timber.d("Executing task $taskRunningId - ${task::class.java.name}")
// update the notification
notification.setCurrentTask(taskRunningId, taskProgressText).post()
@ -200,7 +200,7 @@ class ApiService : Service() {
if (System.currentTimeMillis() - lastEventTime > 30*1000
|| taskCancelTries >= 3) {
val time = System.currentTimeMillis() - lastEventTime
d(TAG, "!!! Task $taskRunningId froze for $time ms. $taskRunning")
Timber.d("!!! Task $taskRunningId froze for $time ms. $taskRunning")
clearTask()
return true
}
@ -245,7 +245,7 @@ class ApiService : Service() {
@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
fun onApiTask(task: IApiTask) {
EventBus.getDefault().removeStickyEvent(task)
d(TAG, task.toString())
Timber.d(task.toString())
if (task is EdziennikTask) {
// fix for duplicated tasks, thank you EventBus
@ -270,10 +270,10 @@ class ApiService : Service() {
else {
taskQueue += task
}
d(TAG, "EventBus received an IApiTask: $task")
d(TAG, "Current queue:")
Timber.d("EventBus received an IApiTask: $task")
Timber.d("Current queue:")
taskQueue.forEach {
d(TAG, " - $it")
Timber.d(" - $it")
}
runTask()
}
@ -281,7 +281,7 @@ class ApiService : Service() {
@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
fun onTaskCancelRequest(request: TaskCancelRequest) {
EventBus.getDefault().removeStickyEvent(request)
d(TAG, request.toString())
Timber.d(request.toString())
taskCancelTries++
taskCancelled = true
@ -291,7 +291,7 @@ class ApiService : Service() {
@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
fun onServiceCloseRequest(request: ServiceCloseRequest) {
EventBus.getDefault().removeStickyEvent(request)
d(TAG, request.toString())
Timber.d(request.toString())
serviceClosed = true
taskCancelled = true
@ -306,19 +306,19 @@ class ApiService : Service() {
____) | __/ | \ V /| | (_| __/ | (_) \ V / __/ | | | | | (_| | __/\__ \
|_____/ \___|_| \_/ |_|\___\___| \___/ \_/ \___|_| |_| |_|\__,_|\___||__*/
override fun onCreate() {
d(TAG, "Service created")
Timber.d("Service created")
EventBus.getDefault().register(this)
notification.setIdle().setCloseAction()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
d(TAG, "Foreground service onStartCommand")
startForeground(app.notificationChannelsManager.sync.id, notification.notification)
Timber.d("Foreground service onStartCommand")
startForeground(app.notificationManager.sync.id, notification.notification)
return START_NOT_STICKY
}
override fun onDestroy() {
d(TAG, "Service destroyed")
Timber.d("Service destroyed")
serviceClosed = true
EventBus.getDefault().unregister(this)
}

View File

@ -14,7 +14,7 @@ import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.ext.Bundle
import pl.szczodrzynski.edziennik.ext.pendingIntentFlag
import pl.szczodrzynski.edziennik.receivers.SzkolnyReceiver
import pl.szczodrzynski.edziennik.core.receiver.SzkolnyReceiver
import kotlin.math.roundToInt
@ -138,7 +138,7 @@ class EdziennikNotification(val app: App) {
fun post() {
if (serviceClosed)
return
notificationManager.notify(app.notificationChannelsManager.sync.id, notification)
notificationManager.notify(app.notificationManager.sync.id, notification)
}
}

View File

@ -30,8 +30,8 @@ import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.ext.isBeforeYear
import pl.szczodrzynski.edziennik.ext.shouldArchive
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type
import pl.szczodrzynski.edziennik.core.manager.AvailabilityManager.Error.Type
import timber.log.Timber
open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTask(profileId) {
companion object {
@ -80,16 +80,16 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
internal fun run(app: App, taskCallback: EdziennikCallback) {
profile?.let { profile ->
if (profile.archived) {
d(TAG, "The profile $profileId is archived")
Timber.d("The profile $profileId is archived")
taskCallback.onError(ApiError(TAG, ERROR_PROFILE_ARCHIVED))
return
}
else if (profile.shouldArchive()) {
d(TAG, "The profile $profileId's year ended on ${profile.dateYearEnd}, archiving")
Timber.d("The profile $profileId's year ended on ${profile.dateYearEnd}, archiving")
ProfileArchiver(app, profile)
}
if (profile.isBeforeYear()) {
d(TAG, "The profile $profileId's school year has not started yet; aborting sync")
Timber.d("The profile $profileId's school year has not started yet; aborting sync")
cancel()
taskCallback.onCompleted()
return
@ -143,7 +143,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
}
override fun cancel() {
d(TAG, "Task ${toString()} cancelling...")
Timber.d("Task ${toString()} cancelling...")
edziennikInterface?.cancel()
}

View File

@ -9,8 +9,8 @@ import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.enums.LoginType
import pl.szczodrzynski.edziennik.ext.Intent
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
import timber.log.Timber
class ProfileArchiver(val app: App, val profile: Profile) {
companion object {
@ -20,14 +20,14 @@ class ProfileArchiver(val app: App, val profile: Profile) {
init {
if (profile.archiveId == null)
profile.archiveId = profile.id
d(TAG, "Processing ${profile.name}#${profile.id}, archiveId = ${profile.archiveId}")
Timber.d("Processing ${profile.name}#${profile.id}, archiveId = ${profile.archiveId}")
profile.archived = true
app.db.profileDao().add(profile)
//app.db.metadataDao().setAllSeen(profile.id, true)
app.db.notificationDao().clear(profile.id)
app.db.endpointTimerDao().clear(profile.id)
d(TAG, "Archived profile ${profile.id} saved")
Timber.d("Archived profile ${profile.id} saved")
profile.archived = false
// guess the nearest school year
@ -48,7 +48,7 @@ class ProfileArchiver(val app: App, val profile: Profile) {
profile.subname = "Nowy rok szkolny - ${profile.studentSchoolYearStart}"
profile.studentClassName = null
d(TAG, "New profile ID for ${profile.name}: ${profile.id}")
Timber.d("New profile ID for ${profile.name}: ${profile.id}")
when (profile.loginStoreType) {
LoginType.LIBRUS -> {
@ -79,7 +79,7 @@ class ProfileArchiver(val app: App, val profile: Profile) {
LoginType.TEMPLATE -> {}
}
d(TAG, "Processed student data: ${profile.studentData}")
Timber.d("Processed student data: ${profile.studentData}")
app.db.profileDao().add(profile)

View File

@ -29,7 +29,7 @@ import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
companion object {
@ -67,10 +67,10 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
}
private fun login(loginMethod: LoginMethod? = null, afterLogin: (() -> Unit)? = null) {
d(TAG, "Trying to login with ${data.targetLoginMethods}")
Timber.d("Trying to login with ${data.targetLoginMethods}")
if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") }
Timber.d(" - Internal errors:")
internalErrorList.forEach { Timber.d(" - code $it") }
}
loginMethod?.let { data.prepareFor(it) }
afterLogin?.let { this.afterLogin = it }
@ -80,10 +80,10 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
}
private fun data() {
d(TAG, "Endpoint IDs: ${data.targetEndpoints}")
Timber.d("Endpoint IDs: ${data.targetEndpoints}")
if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") }
Timber.d(" - Internal errors:")
internalErrorList.forEach { Timber.d(" - code $it") }
}
afterLogin?.invoke() ?: LibrusData(data) {
completed()
@ -158,7 +158,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
override fun firstLogin() { LibrusFirstLogin(data) { completed() } }
override fun cancel() {
d(TAG, "Cancelled")
Timber.d("Cancelled")
data.cancel()
}

View File

@ -12,7 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.net.HttpURLConnection.*
open class LibrusApi(open val data: DataLibrus, open val lastSync: Long?) {
@ -28,7 +28,7 @@ open class LibrusApi(open val data: DataLibrus, open val lastSync: Long?) {
fun apiGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, ignoreErrors: List<Int> = emptyList(), onSuccess: (json: JsonObject) -> Unit) {
d(tag, "Request: Librus/Api - ${if (data.fakeLogin) FAKE_LIBRUS_API else LIBRUS_API_URL}/$endpoint")
Timber.tag(tag).d("Request: Librus/Api - ${if (data.fakeLogin) FAKE_LIBRUS_API else LIBRUS_API_URL}/$endpoint")
val callback = object : JsonCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response?) {

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.Librus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaInfo
import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
companion object {
@ -41,7 +42,7 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
}
private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
Timber.d("Using endpoint $endpointId. Last sync time = $lastSync")
when (endpointId) {
/**
* API

View File

@ -20,7 +20,7 @@ import org.jsoup.parser.Parser
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.io.File
import java.io.StringWriter
import javax.xml.parsers.DocumentBuilderFactory
@ -43,7 +43,7 @@ open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
fun messagesGet(tag: String, module: String, method: Int = POST,
parameters: Map<String, Any>? = null, onSuccess: (doc: Document) -> Unit) {
d(tag, "Request: Librus/Messages - $LIBRUS_MESSAGES_URL/$module")
Timber.tag(tag).d("Request: Librus/Messages - $LIBRUS_MESSAGES_URL/$module")
val callback = object : TextCallbackHandler() {
override fun onSuccess(text: String?, response: Response?) {
@ -127,7 +127,7 @@ open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
fun messagesGetJson(tag: String, module: String, method: Int = POST,
parameters: Map<String, Any>? = null, onSuccess: (json: JsonObject?) -> Unit) {
d(tag, "Request: Librus/Messages - $LIBRUS_MESSAGES_URL/$module")
Timber.tag(tag).d("Request: Librus/Messages - $LIBRUS_MESSAGES_URL/$module")
val callback = object : TextCallbackHandler() {
override fun onSuccess(text: String?, response: Response?) {
@ -211,7 +211,7 @@ open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
fun sandboxGet(tag: String, action: String, parameters: Map<String, Any>? = null,
onSuccess: (json: JsonObject) -> Unit) {
d(tag, "Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action")
Timber.tag(tag).d("Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action")
val callback = object : JsonCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response?) {
@ -256,7 +256,7 @@ open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
method: Int = GET,
onProgress: (written: Long, total: Long) -> Unit) {
d(tag, "Request: Librus/Messages - $url")
Timber.tag(tag).d("Request: Librus/Messages - $url")
val callback = object : FileCallbackHandler(targetFile) {
override fun onSuccess(file: File?, response: Response?) {

View File

@ -8,7 +8,7 @@ import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.net.HttpURLConnection
open class LibrusPortal(open val data: DataLibrus) {
@ -24,7 +24,7 @@ open class LibrusPortal(open val data: DataLibrus) {
fun portalGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, onSuccess: (json: JsonObject, response: Response?) -> Unit) {
d(tag, "Request: Librus/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_PORTAL else LIBRUS_PORTAL_URL}$endpoint")
Timber.tag(tag).d("Request: Librus/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_PORTAL else LIBRUS_PORTAL_URL}$endpoint")
val callback = object : JsonCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response?) {
@ -59,8 +59,8 @@ open class LibrusPortal(open val data: DataLibrus) {
if (response?.code() == HttpURLConnection.HTTP_OK) {
try {
onSuccess(json, response)
} catch (e: NullPointerException) {
e.printStackTrace()
} catch (e: Exception) {
Timber.e(e)
data.error(ApiError(tag, EXCEPTION_LIBRUS_PORTAL_SYNERGIA_TOKEN)
.withResponse(response)
.withThrowable(e)

View File

@ -10,7 +10,7 @@ import im.wangchao.mhttp.callback.TextCallbackHandler
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
open class LibrusSynergia(open val data: DataLibrus, open val lastSync: Long?) {
companion object {
@ -25,7 +25,7 @@ open class LibrusSynergia(open val data: DataLibrus, open val lastSync: Long?) {
fun synergiaGet(tag: String, endpoint: String, method: Int = GET,
parameters: Map<String, Any> = emptyMap(), onSuccess: (text: String) -> Unit) {
d(tag, "Request: Librus/Synergia - $LIBRUS_SYNERGIA_URL/$endpoint")
Timber.tag(tag).d("Request: Librus/Synergia - $LIBRUS_SYNERGIA_URL/$endpoint")
val callback = object : TextCallbackHandler() {
override fun onSuccess(text: String?, response: Response?) {
@ -91,7 +91,7 @@ open class LibrusSynergia(open val data: DataLibrus, open val lastSync: Long?) {
}
fun redirectUrlGet(tag: String, url: String, onSuccess: (url: String) -> Unit) {
d(tag, "Request: Librus/Synergia - $url")
Timber.tag(tag).d("Request: Librus/Synergia - $url")
val callback = object : TextCallbackHandler() {
override fun onSuccess(text: String?, response: Response) {

View File

@ -16,10 +16,10 @@ import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.enums.MetadataType
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import pl.szczodrzynski.edziennik.utils.models.Week
import timber.log.Timber
class LibrusApiTimetables(override val data: DataLibrus,
override val lastSync: Long?,
@ -71,7 +71,7 @@ class LibrusApiTimetables(override val data: DataLibrus,
}
}
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
Timber.d("Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
if (data.timetableNotPublic) data.timetableNotPublic = false

View File

@ -8,6 +8,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class LibrusLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
companion object {
@ -43,7 +44,7 @@ class LibrusLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
onSuccess(null)
return
}
Utils.d(TAG, "Using login method $loginMethod")
Timber.d("Using login method $loginMethod")
when (loginMethod) {
LoginMethod.LIBRUS_PORTAL -> {
data.startProgress(R.string.edziennik_progress_login_librus_portal)

View File

@ -17,7 +17,7 @@ import pl.szczodrzynski.edziennik.data.enums.LoginMode
import pl.szczodrzynski.edziennik.ext.getInt
import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.ext.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.net.HttpURLConnection.*
@Suppress("ConvertSecondaryConstructorToPrimary")
@ -171,7 +171,7 @@ class LibrusLoginApi {
}
private fun synergiaGetToken() {
d(TAG, "Request: Librus/Login/Api - $LIBRUS_API_TOKEN_URL")
Timber.d("Request: Librus/Login/Api - $LIBRUS_API_TOKEN_URL")
Request.builder()
.url(LIBRUS_API_TOKEN_URL)
@ -192,7 +192,7 @@ class LibrusLoginApi {
.enqueue()
}
private fun synergiaRefreshToken() {
d(TAG, "Request: Librus/Login/Api - $LIBRUS_API_TOKEN_URL")
Timber.d("Request: Librus/Login/Api - $LIBRUS_API_TOKEN_URL")
Request.builder()
.url(LIBRUS_API_TOKEN_URL)
@ -211,7 +211,7 @@ class LibrusLoginApi {
.enqueue()
}
private fun jstGetToken() {
d(TAG, "Request: Librus/Login/Api - $LIBRUS_API_TOKEN_JST_URL")
Timber.d("Request: Librus/Login/Api - $LIBRUS_API_TOKEN_JST_URL")
Request.builder()
.url(LIBRUS_API_TOKEN_JST_URL)
@ -233,7 +233,7 @@ class LibrusLoginApi {
.enqueue()
}
private fun jstRefreshToken() {
d(TAG, "Request: Librus/Login/Api - $LIBRUS_API_TOKEN_JST_URL")
Timber.d("Request: Librus/Login/Api - $LIBRUS_API_TOKEN_JST_URL")
Request.builder()
.url(LIBRUS_API_TOKEN_JST_URL)

View File

@ -14,7 +14,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.LibrusRecaptchaHelpe
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.ext.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.io.StringWriter
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.OutputKeys
@ -108,7 +108,7 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
* XML (Flash messages website) login method. Uses a Synergia login and password.
*/
private fun loginWithCredentials() {
d(TAG, "Request: Librus/Login/Messages - $LIBRUS_MESSAGES_URL/Login")
Timber.d("Request: Librus/Login/Messages - $LIBRUS_MESSAGES_URL/Login")
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
val doc = docBuilder.newDocument()
@ -152,7 +152,7 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
* A login method using the Synergia website (/wiadomosci2 Auto Login).
*/
private fun loginWithSynergia(url: String = "https://synergia.librus.pl/wiadomosci2") {
d(TAG, "Request: Librus/Login/Messages - $url")
Timber.d("Request: Librus/Login/Messages - $url")
Request.builder()
.url(url)

View File

@ -14,7 +14,7 @@ import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.enums.LoginMode
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.net.HttpURLConnection.*
import java.util.*
import java.util.regex.Pattern
@ -63,7 +63,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
}}
private fun authorize(url: String, referer: String? = null) {
d(TAG, "Request: Librus/Login/Portal - $url")
Timber.d("Request: Librus/Login/Portal - $url")
Request.builder()
.url(url)
@ -176,7 +176,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
return
}
d(TAG, "Request: Librus/Login/Portal - $url")
Timber.d("Request: Librus/Login/Portal - $url")
val recaptchaCode = data.arguments?.getString("recaptchaCode") ?: data.loginStore.getLoginData("recaptchaCode", null)
val recaptchaTime = data.arguments?.getLong("recaptchaTime") ?: data.loginStore.getLoginData("recaptchaTime", 0L)
@ -239,7 +239,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
}
private fun accessToken(code: String?, refreshToken: String?) {
d(TAG, "Request: Librus/Login/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_TOKEN else LIBRUS_TOKEN_URL}")
Timber.d("Request: Librus/Login/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_TOKEN else LIBRUS_TOKEN_URL}")
val onSuccess = { json: JsonObject, response: Response? ->
data.portalAccessToken = json.getString("access_token")

View File

@ -15,7 +15,7 @@ import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.ext.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.net.HttpURLConnection
class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Unit) : LibrusApi(data, null) {
@ -58,7 +58,7 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
* A login method using the Synergia API (AutoLoginToken endpoint).
*/
private fun loginWithApi() {
d(TAG, "Request: Librus/Login/Synergia - $LIBRUS_API_URL/AutoLoginToken")
Timber.d("Request: Librus/Login/Synergia - $LIBRUS_API_URL/AutoLoginToken")
val onSuccess = { json: JsonObject ->
loginWithToken(json.getString("Token"))
@ -73,7 +73,7 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
return
}
d(TAG, "Request: Librus/Login/Synergia - " + LIBRUS_SYNERGIA_TOKEN_LOGIN_URL.replace("TOKEN", token) + "/uczen/widok/centrum_powiadomien")
Timber.d("Request: Librus/Login/Synergia - " + LIBRUS_SYNERGIA_TOKEN_LOGIN_URL.replace("TOKEN", token) + "/uczen/widok/centrum_powiadomien")
val callback = object : TextCallbackHandler() {
override fun onSuccess(json: String?, response: Response?) {

View File

@ -9,7 +9,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusPortal
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.enums.LoginMode
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class SynergiaTokenExtractor(override val data: DataLibrus, val onSuccess: () -> Unit) : LibrusPortal(data) {
companion object {
@ -45,7 +45,7 @@ class SynergiaTokenExtractor(override val data: DataLibrus, val onSuccess: () ->
val accountLogin = data.apiLogin ?: return false
data.portalAccessToken ?: return false
d(TAG, "Request: Librus/SynergiaTokenExtractor - ${if (data.fakeLogin) FAKE_LIBRUS_ACCOUNT else LIBRUS_ACCOUNT_URL}$accountLogin")
Timber.d("Request: Librus/SynergiaTokenExtractor - ${if (data.fakeLogin) FAKE_LIBRUS_ACCOUNT else LIBRUS_ACCOUNT_URL}$accountLogin")
val onSuccess = { json: JsonObject, response: Response? ->
// synergiaAccount is executed when a synergia token needs a refresh

View File

@ -23,7 +23,7 @@ import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
companion object {
@ -63,10 +63,10 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
}
private fun login(loginMethod: LoginMethod? = null, afterLogin: (() -> Unit)? = null) {
d(TAG, "Trying to login with ${data.targetLoginMethods}")
Timber.d("Trying to login with ${data.targetLoginMethods}")
if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") }
Timber.d(" - Internal errors:")
internalErrorList.forEach { Timber.d(" - code $it") }
}
loginMethod?.let { data.prepareFor(it) }
afterLogin?.let { this.afterLogin = it }
@ -76,10 +76,10 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
}
private fun data() {
d(TAG, "Endpoint IDs: ${data.targetEndpoints}")
Timber.d("Endpoint IDs: ${data.targetEndpoints}")
if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") }
Timber.d(" - Internal errors:")
internalErrorList.forEach { Timber.d(" - code $it") }
}
afterLogin?.invoke() ?: MobidziennikData(data) {
completed()
@ -138,7 +138,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
override fun firstLogin() { MobidziennikFirstLogin(data) { completed() } }
override fun cancel() {
d(TAG, "Cancelled")
Timber.d("Cancelled")
data.cancel()
}

View File

@ -10,6 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api.Mobid
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api2.MobidziennikApi2Main
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.*
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
companion object {
@ -38,7 +39,7 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
}
private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
Timber.d("Using endpoint $endpointId. Last sync time = $lastSync")
when (endpointId) {
ENDPOINT_MOBIDZIENNIK_API_MAIN -> {
data.startProgress(R.string.edziennik_progress_endpoint_data)

View File

@ -11,7 +11,7 @@ import im.wangchao.mhttp.callback.TextCallbackHandler
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.io.File
open class MobidziennikWeb(open val data: DataMobidziennik, open val lastSync: Long?) {
@ -52,7 +52,7 @@ open class MobidziennikWeb(open val data: DataMobidziennik, open val lastSync: L
) {
val url = fullUrl ?: "https://${data.loginServerName}.mobidziennik.pl$endpoint"
d(tag, "Request: Mobidziennik/Web - $url")
Timber.tag(tag).d("Request: Mobidziennik/Web - $url")
if (data.webSessionKey == null) {
data.error(TAG, ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY)
@ -128,7 +128,7 @@ open class MobidziennikWeb(open val data: DataMobidziennik, open val lastSync: L
onProgress: (written: Long, total: Long) -> Unit) {
val url = "https://${data.loginServerName}.mobidziennik.pl$action"
d(tag, "Request: Mobidziennik/Web - $url")
Timber.tag(tag).d("Request: Mobidziennik/Web - $url")
if (data.webSessionKey == null) {
data.error(TAG, ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY)

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.enums.MetadataType
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import timber.log.Timber
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
@ -45,8 +46,8 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List<String>) {
val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US)
val addedDate = try {
format.parse(cols[7]).time
} catch (e: ParseException) {
e.printStackTrace()
} catch (e: Exception) {
Timber.e(e)
System.currentTimeMillis()
}

View File

@ -17,6 +17,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.ext.getJsonObject
import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class MobidziennikApi2Main(val data: DataMobidziennik,
val lastSync: Long?,
@ -33,7 +34,7 @@ class MobidziennikApi2Main(val data: DataMobidziennik,
get() = data.profile
init {
Utils.d(TAG, "Request: Mobidziennik/Api2/Main - https://${data.loginServerName}.mobidziennik.pl/api2/logowanie")
Timber.d("Request: Mobidziennik/Api2/Main - https://${data.loginServerName}.mobidziennik.pl/api2/logowanie")
val callback = object : JsonCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response?) {

View File

@ -25,10 +25,10 @@ import pl.szczodrzynski.edziennik.ext.dateToSemester
import pl.szczodrzynski.edziennik.ext.fixName
import pl.szczodrzynski.edziennik.ext.get
import pl.szczodrzynski.edziennik.ext.singleOrNull
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import pl.szczodrzynski.edziennik.utils.models.Week
import timber.log.Timber
class MobidziennikWebAttendance(override val data: DataMobidziennik,
override val lastSync: Long?,
@ -156,7 +156,7 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
}
}
d(TAG, "Done in ${System.currentTimeMillis()-start} ms (request ${start-requestTime} ms)")
Timber.d("Done in ${System.currentTimeMillis()-start} ms (request ${start-requestTime} ms)")
onSuccess()
}

View File

@ -8,6 +8,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class MobidziennikLogin(val data: DataMobidziennik, val onSuccess: () -> Unit) {
companion object {
@ -43,7 +44,7 @@ class MobidziennikLogin(val data: DataMobidziennik, val onSuccess: () -> Unit) {
onSuccess(null)
return
}
Utils.d(TAG, "Using login method $loginMethod")
Timber.d("Using login method $loginMethod")
when (loginMethod) {
LoginMethod.MOBIDZIENNIK_WEB -> {
data.startProgress(R.string.edziennik_progress_login_mobidziennik_web)

View File

@ -19,6 +19,7 @@ import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.ext.isNotNullNorBlank
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class MobidziennikLoginApi2(val data: DataMobidziennik, val onSuccess: () -> Unit) {
companion object {
@ -54,7 +55,7 @@ class MobidziennikLoginApi2(val data: DataMobidziennik, val onSuccess: () -> Uni
}}
private fun loginWithCredentials() {
Utils.d(TAG, "Request: Mobidziennik/Login/Api2 - https://mobidziennik.pl/logowanie")
Timber.d("Request: Mobidziennik/Login/Api2 - https://mobidziennik.pl/logowanie")
val callback = object : JsonCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response?) {

View File

@ -13,7 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.Mobidziennik
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.ext.getUnixDate
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class MobidziennikLoginWeb(val data: DataMobidziennik, val onSuccess: () -> Unit) {
companion object {
@ -36,7 +36,7 @@ class MobidziennikLoginWeb(val data: DataMobidziennik, val onSuccess: () -> Unit
}}
private fun loginWithCredentials() {
d(TAG, "Request: Mobidziennik/Login/Web - https://${data.loginServerName}.mobidziennik.pl/api/")
Timber.d("Request: Mobidziennik/Login/Web - https://${data.loginServerName}.mobidziennik.pl/api/")
val callback = object : TextCallbackHandler() {
override fun onSuccess(text: String?, response: Response?) {

View File

@ -25,6 +25,7 @@ import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
import java.io.File
class Podlasie(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
@ -58,8 +59,8 @@ class Podlasie(val app: App, val profile: Profile?, val loginStore: LoginStore,
override fun sync(featureTypes: Set<FeatureType>?, onlyEndpoints: Set<Int>?, arguments: JsonObject?) {
data.arguments = arguments
data.prepare(PodlasieFeatures, featureTypes, onlyEndpoints)
Utils.d(TAG, "LoginMethod IDs: ${data.targetLoginMethods}")
Utils.d(TAG, "Endpoint IDs: ${data.targetEndpoints}")
Timber.d("LoginMethod IDs: ${data.targetLoginMethods}")
Timber.d("Endpoint IDs: ${data.targetEndpoints}")
PodlasieLogin(data) {
PodlasieData(data) {
completed()
@ -133,7 +134,7 @@ class Podlasie(val app: App, val profile: Profile?, val loginStore: LoginStore,
}
override fun cancel() {
Utils.d(TAG, "Cancelled")
Timber.d("Cancelled")
data.cancel()
}

View File

@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.ext.getInt
import pl.szczodrzynski.edziennik.ext.getJsonObject
import pl.szczodrzynski.edziennik.ext.toHexString
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
import java.security.MessageDigest
import java.text.SimpleDateFormat
import java.util.*
@ -34,7 +35,7 @@ open class PodlasieApi(open val data: DataPodlasie, open val lastSync: Long?) {
fun apiGet(tag: String, endpoint: String, onSuccess: (json: JsonObject) -> Unit) {
val url = PODLASIE_API_URL + endpoint
Utils.d(tag, "Request: Podlasie/Api - $url")
Timber.tag(tag).d("Request: Podlasie/Api - $url")
if (data.apiToken == null) {
data.error(tag, ERROR_PODLASIE_API_NO_TOKEN)

View File

@ -9,6 +9,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.ENDPOINT_PODLASIE_API_MAIN
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.api.PodlasieApiMain
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class PodlasieData(val data: DataPodlasie, val onSuccess: () -> Unit) {
companion object {
@ -37,7 +38,7 @@ class PodlasieData(val data: DataPodlasie, val onSuccess: () -> Unit) {
}
private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
Timber.d("Using endpoint $endpointId. Last sync time = $lastSync")
when (endpointId) {
ENDPOINT_PODLASIE_API_MAIN -> {
data.startProgress(R.string.edziennik_progress_endpoint_data)

View File

@ -8,6 +8,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class PodlasieLogin(val data: DataPodlasie, val onSuccess: () -> Unit) {
companion object {
@ -43,7 +44,7 @@ class PodlasieLogin(val data: DataPodlasie, val onSuccess: () -> Unit) {
onSuccess(null)
return
}
Utils.d(TAG, "Using login method $loginMethod")
Timber.d("Using login method $loginMethod")
when (loginMethod) {
LoginMethod.PODLASIE_API -> {
data.startProgress(R.string.edziennik_progress_login_podlasie_api)

View File

@ -22,7 +22,7 @@ import pl.szczodrzynski.edziennik.data.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class Template(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
companion object {
@ -55,8 +55,8 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
override fun sync(featureTypes: Set<FeatureType>?, onlyEndpoints: Set<Int>?, arguments: JsonObject?) {
data.arguments = arguments
data.prepare(TemplateFeatures, featureTypes, onlyEndpoints)
d(TAG, "LoginMethod IDs: ${data.targetLoginMethods}")
d(TAG, "Endpoint IDs: ${data.targetEndpoints}")
Timber.d("LoginMethod IDs: ${data.targetLoginMethods}")
Timber.d("Endpoint IDs: ${data.targetEndpoints}")
TemplateLogin(data) {
TemplateData(data) {
completed()
@ -99,7 +99,7 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
}
override fun cancel() {
d(TAG, "Cancelled")
Timber.d("Cancelled")
data.cancel()
}

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.template.data.api.TemplateA
import pl.szczodrzynski.edziennik.data.api.edziennik.template.data.web.TemplateWebSample
import pl.szczodrzynski.edziennik.data.api.edziennik.template.data.web.TemplateWebSample2
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class TemplateData(val data: DataTemplate, val onSuccess: () -> Unit) {
companion object {
@ -41,7 +42,7 @@ class TemplateData(val data: DataTemplate, val onSuccess: () -> Unit) {
}
private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
Timber.d("Using endpoint $endpointId. Last sync time = $lastSync")
when (endpointId) {
ENDPOINT_TEMPLATE_WEB_SAMPLE -> {
data.startProgress(R.string.edziennik_progress_endpoint_student_info)

View File

@ -8,6 +8,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.template.DataTemplate
import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class TemplateLogin(val data: DataTemplate, val onSuccess: () -> Unit) {
companion object {
@ -43,7 +44,7 @@ class TemplateLogin(val data: DataTemplate, val onSuccess: () -> Unit) {
onSuccess(null)
return
}
Utils.d(TAG, "Using login method $loginMethod")
Timber.d("Using login method $loginMethod")
when (loginMethod) {
LoginMethod.TEMPLATE_WEB -> {
data.startProgress(R.string.edziennik_progress_login_template_web)

View File

@ -21,7 +21,7 @@ import pl.szczodrzynski.edziennik.data.enums.FeatureType
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class Usos(
val app: App,
@ -55,8 +55,8 @@ class Usos(
) {
data.arguments = arguments
data.prepare(UsosFeatures, featureTypes, onlyEndpoints)
d(TAG, "LoginMethod IDs: ${data.targetLoginMethods}")
d(TAG, "Endpoint IDs: ${data.targetEndpoints}")
Timber.d("LoginMethod IDs: ${data.targetLoginMethods}")
Timber.d("Endpoint IDs: ${data.targetEndpoints}")
UsosLogin(data) {
UsosData(data) {
completed()
@ -79,7 +79,7 @@ class Usos(
}
override fun cancel() {
d(TAG, "Cancelled")
Timber.d("Cancelled")
data.cancel()
}

View File

@ -19,7 +19,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.usos.DataUsos
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.login.UsosLoginApi
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.net.HttpURLConnection.*
import java.util.UUID
@ -89,7 +89,7 @@ open class UsosApi(open val data: DataUsos, open val lastSync: Long?) {
onSuccess: (data: T, response: Response?) -> Unit,
) {
val url = "${data.instanceUrl}services/$service"
d(tag, "Request: Usos/Api - $url")
Timber.tag(tag).d("Request: Usos/Api - $url")
val formData = mutableMapOf<String, String>()
if (params != null)

View File

@ -5,13 +5,12 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.usos.data
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.template.data.web.TemplateWebSample
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.*
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.data.api.UsosApiCourses
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.data.api.UsosApiTerms
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.data.api.UsosApiTimetable
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.data.api.UsosApiUser
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class UsosData(val data: DataUsos, val onSuccess: () -> Unit) {
companion object {
@ -40,7 +39,7 @@ class UsosData(val data: DataUsos, val onSuccess: () -> Unit) {
}
private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
Timber.d("Using endpoint $endpointId. Last sync time = $lastSync")
when (endpointId) {
ENDPOINT_USOS_API_USER -> {
data.startProgress(R.string.edziennik_progress_endpoint_student_info)

View File

@ -7,7 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.usos.login
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.DataUsos
import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class UsosLogin(val data: DataUsos, val onSuccess: () -> Unit) {
companion object {
@ -43,7 +43,7 @@ class UsosLogin(val data: DataUsos, val onSuccess: () -> Unit) {
onSuccess(null)
return
}
d(TAG, "Using login method $loginMethod")
Timber.d("Using login method $loginMethod")
when (loginMethod) {
LoginMethod.USOS_API -> {
data.startProgress(R.string.edziennik_progress_login_usos_api)

View File

@ -11,7 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.usos.data.UsosApi
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class UsosLoginApi(val data: DataUsos, val onSuccess: () -> Unit) {
companion object {
@ -71,7 +71,7 @@ class UsosLoginApi(val data: DataUsos, val onSuccess: () -> Unit) {
}
private fun login() {
d(TAG, "Login to ${data.schoolId} with ${data.oauthLoginResponse}")
Timber.d("Login to ${data.schoolId} with ${data.oauthLoginResponse}")
val authorizeResponse = data.oauthLoginResponse?.fromQueryString()
?: return // checked in init {}

View File

@ -34,7 +34,7 @@ import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import java.io.File
class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
@ -78,10 +78,10 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
return
}
d(TAG, "Trying to login with ${data.targetLoginMethods}")
Timber.d("Trying to login with ${data.targetLoginMethods}")
if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") }
Timber.d(" - Internal errors:")
internalErrorList.forEach { Timber.d(" - code $it") }
}
loginMethod?.let { data.prepareFor(it) }
afterLogin?.let { this.afterLogin = it }
@ -91,10 +91,10 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
}
private fun data() {
d(TAG, "Endpoint IDs: ${data.targetEndpoints}")
Timber.d("Endpoint IDs: ${data.targetEndpoints}")
if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") }
Timber.d(" - Internal errors:")
internalErrorList.forEach { Timber.d(" - code $it") }
}
afterLogin?.invoke() ?: VulcanData(data) {
completed()
@ -179,7 +179,7 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
override fun firstLogin() { VulcanFirstLogin(data) { completed() } }
override fun cancel() {
d(TAG, "Cancelled")
Timber.d("Cancelled")
data.cancel()
}

View File

@ -10,6 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.*
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.web.VulcanWebLuckyNumber
import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
companion object {
@ -82,7 +83,7 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
}
private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
Timber.d("Using endpoint $endpointId. Last sync time = $lastSync")
when (endpointId) {
ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS -> {
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)

View File

@ -22,9 +22,9 @@ import pl.szczodrzynski.edziennik.data.db.entity.LessonRange
import pl.szczodrzynski.edziennik.data.db.entity.Subject
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import timber.log.Timber
import java.net.HttpURLConnection
import java.net.HttpURLConnection.HTTP_NOT_FOUND
import java.net.URLEncoder
@ -189,7 +189,7 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
) {
val url = "${if (baseUrl) data.apiUrl else data.fullApiUrl}$endpoint"
d(tag, "Request: Vulcan/Hebe - $url")
Timber.tag(tag).d("Request: Vulcan/Hebe - $url")
val privateKey = data.hebePrivateKey
val publicHash = data.hebePublicHash

View File

@ -18,6 +18,7 @@ import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.models.Date
import timber.log.Timber
import java.io.File
import java.net.HttpURLConnection
@ -269,7 +270,7 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) {
else -> "uonetplus"
} + ".${data.webHost}/${data.symbol}/$endpoint"
Utils.d(tag, "Request: Vulcan/WebMain - $url")
Timber.tag(tag).d("Request: Vulcan/WebMain - $url")
val payload = JsonObject()
parameters.map { (name, value) ->

View File

@ -25,9 +25,9 @@ import pl.szczodrzynski.edziennik.ext.getBoolean
import pl.szczodrzynski.edziennik.ext.getInt
import pl.szczodrzynski.edziennik.ext.getJsonObject
import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Week
import timber.log.Timber
class VulcanHebeTimetable(
override val data: DataVulcan,
@ -107,8 +107,7 @@ class VulcanHebeTimetable(
date.stepForward(0, 0, 1)
}
d(
TAG,
Timber.d(
"Clearing lessons between ${dateFrom.stringY_m_d} and ${dateTo.stringY_m_d}"
)

View File

@ -8,6 +8,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class VulcanLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
companion object {
@ -43,7 +44,7 @@ class VulcanLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
onSuccess(null)
return
}
Utils.d(TAG, "Using login method $loginMethod")
Timber.d("Using login method $loginMethod")
when (loginMethod) {
LoginMethod.VULCAN_WEB_MAIN -> {
data.startProgress(R.string.edziennik_progress_login_vulcan_web_main)

View File

@ -22,6 +22,7 @@ import pl.szczodrzynski.edziennik.data.enums.LoginMethod
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.models.Date
import timber.log.Timber
abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) {
companion object {
@ -159,11 +160,6 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
}
}
private fun d(message: String) {
if (DEBUG)
Utils.d(TAG, message)
}
fun clear() {
loginMethods.clear()
@ -201,7 +197,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
return // return on first login
val totalStart = System.currentTimeMillis()
var startTime = System.currentTimeMillis()
d("Saving data to DB")
Timber.d("Saving data to DB")
profile.userCode = generateUserCode()
@ -233,7 +229,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
}
}
d("Profiles saved in ${System.currentTimeMillis()-startTime} ms")
Timber.d("Profiles saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
// always present and not empty, during every sync
@ -250,7 +246,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
db.gradeCategoryDao().clear(profileId)
db.gradeCategoryDao().addAll(gradeCategories.values())
d("Maps saved in ${System.currentTimeMillis()-startTime} ms")
Timber.d("Maps saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
// may be empty - extracted from DB on demand, by an endpoint
@ -267,12 +263,12 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
if (librusLessons.size > 0)
db.librusLessonDao().addAll(librusLessons.values())
d("On-demand maps saved in ${System.currentTimeMillis()-startTime} ms")
Timber.d("On-demand maps saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
// clear DB with DataRemoveModels added by endpoints
for (model in toRemove) {
d("Clearing DB with $model")
Timber.d("Clearing DB with $model")
when (model) {
is DataRemoveModel.Timetable -> model.commit(profileId, db.timetableDao())
is DataRemoveModel.Grades -> model.commit(profileId, db.gradeDao())
@ -281,7 +277,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
}
}
d("DB cleared in ${System.currentTimeMillis()-startTime} ms")
Timber.d("DB cleared in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
if (metadataList.isNotEmpty())
@ -289,7 +285,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
if (setSeenMetadataList.isNotEmpty())
db.metadataDao().setSeen(setSeenMetadataList)
d("Metadata saved in ${System.currentTimeMillis()-startTime} ms")
Timber.d("Metadata saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
db.timetableDao().putAll(lessonList, removeNotKept = true)
@ -310,9 +306,9 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
if (messageRecipientIgnoreList.isNotEmpty())
db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList)
d("Other data saved in ${System.currentTimeMillis()-startTime} ms")
Timber.d("Other data saved in ${System.currentTimeMillis()-startTime} ms")
d("Total save time: ${System.currentTimeMillis()-totalStart} ms")
Timber.d("Total save time: ${System.currentTimeMillis()-totalStart} ms")
}
fun setSyncNext(endpointId: Int, syncIn: Long? = null, forceFeatureType: FeatureType? = null, syncAt: Long? = null) {
@ -339,7 +335,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
abstract fun generateUserCode(): String
fun cancel() {
d("Cancelled")
Timber.d("Cancelled")
cancelled = true
saveData()
}

View File

@ -10,6 +10,7 @@ import android.content.pm.PackageManager
import android.util.Base64
import pl.szczodrzynski.edziennik.BuildConfig
import pl.szczodrzynski.edziennik.ext.sha256
import timber.log.Timber
import java.security.MessageDigest
object Signing {
@ -32,7 +33,7 @@ object Signing {
appCertificate = Base64.encodeToString(md.digest(), Base64.NO_WRAP)
}
} catch (e: Exception) {
e.printStackTrace()
Timber.e(e)
}
}}

View File

@ -11,6 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.EdziennikNotification
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.utils.Utils
import timber.log.Timber
class ErrorReportTask : IApiTask(-1) {
override fun prepare(app: App) {
@ -23,7 +24,7 @@ class ErrorReportTask : IApiTask(-1) {
fun run(app: App, taskCallback: EdziennikCallback, notification: EdziennikNotification, errorList: MutableList<ApiError>) {
errorList.forEach { error ->
Utils.d(ApiService.TAG, "Error ${error.tag} profile ${error.profileId}: code ${error.errorCode}")
Timber.d("Error ${error.tag} profile ${error.profileId}: code ${error.errorCode}")
}
errorList.clear()

View File

@ -51,7 +51,7 @@ class PostNotifications(val app: App, nList: List<AppNotification>) {
else
it.setDefaults(NotificationCompat.DEFAULT_ALL)
}
.setGroup(if (quiet) app.notificationChannelsManager.dataQuiet.key else app.notificationChannelsManager.data.key)
.setGroup(if (quiet) app.notificationManager.dataQuiet.key else app.notificationManager.data.key)
}
private fun buildSummaryText(summaryCounts: Map<NotificationType, Int>): CharSequence {
@ -79,7 +79,7 @@ class PostNotifications(val app: App, nList: List<AppNotification>) {
MainActivity::class.java,
"fragmentId" to NavTarget.NOTIFICATIONS
)
val summaryIntent = PendingIntent.getActivity(app, app.notificationChannelsManager.data.id, intent, PendingIntent.FLAG_ONE_SHOT or pendingIntentFlag())
val summaryIntent = PendingIntent.getActivity(app, app.notificationManager.data.id, intent, PendingIntent.FLAG_ONE_SHOT or pendingIntentFlag())
// On Nougat or newer - show maximum 8 notifications
// On Marshmallow or older - show maximum 4 notifications
@ -95,7 +95,7 @@ class PostNotifications(val app: App, nList: List<AppNotification>) {
}
// Create a summary to show *instead* of notifications
val combined = NotificationCompat.Builder(app, app.notificationChannelsManager.data.key)
val combined = NotificationCompat.Builder(app, app.notificationManager.data.key)
.setContentTitle(app.getString(R.string.app_name))
.setContentText(buildSummaryText(summaryCounts))
.setTicker(newNotificationsText)
@ -128,7 +128,7 @@ class PostNotifications(val app: App, nList: List<AppNotification>) {
// Less than 8 notifications
val notifications = nList.map {
summaryCounts[it.type] = summaryCounts.getOrDefault(it.type, 0) + 1
NotificationCompat.Builder(app, app.notificationChannelsManager.data.key)
NotificationCompat.Builder(app, app.notificationManager.data.key)
.setContentTitle(it.profileName ?: app.getString(R.string.app_name))
.setContentText(it.text)
.setSubText(if (it.type == NotificationType.SERVER_MESSAGE) null else it.title)
@ -155,7 +155,7 @@ class PostNotifications(val app: App, nList: List<AppNotification>) {
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val summary = NotificationCompat.Builder(app, app.notificationChannelsManager.data.key)
val summary = NotificationCompat.Builder(app, app.notificationManager.data.key)
.setContentTitle(newNotificationsText)
.setContentText(buildSummaryText(summaryCounts))
.setTicker(newNotificationsText)
@ -170,7 +170,7 @@ class PostNotifications(val app: App, nList: List<AppNotification>) {
.setAutoCancel(true)
.build()
notificationManager.notify(app.notificationChannelsManager.data.id, summary)
notificationManager.notify(app.notificationManager.data.id, summary)
}
}
}}

View File

@ -11,7 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
import pl.szczodrzynski.edziennik.data.db.entity.Notification
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.ext.HOUR
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
class SzkolnyTask(val app: App, val syncingProfiles: List<Profile>) : IApiTask(-1) {
companion object {
@ -49,7 +49,7 @@ class SzkolnyTask(val app: App, val syncingProfiles: List<Profile>) : IApiTask(-
notifications.sharedEventNotifications()
}
}
d(TAG, "Created ${notificationList.count()} notifications.")
Timber.d("Created ${notificationList.count()} notifications.")
// filter notifications
notificationList
@ -70,7 +70,7 @@ class SzkolnyTask(val app: App, val syncingProfiles: List<Profile>) : IApiTask(-
// post all notifications
PostNotifications(app, notificationList)
d(TAG, "SzkolnyTask: finished in ${System.currentTimeMillis()-startTime} ms.")
Timber.d("SzkolnyTask: finished in ${System.currentTimeMillis()-startTime} ms.")
taskCallback.onCompleted()
}
}

View File

@ -13,7 +13,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.enums.LoginType
import pl.szczodrzynski.edziennik.ext.getJsonObject
import pl.szczodrzynski.edziennik.ext.mergeWith
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode
import pl.szczodrzynski.edziennik.core.manager.TextStylingManager.HtmlMode
data class AppData(
val configOverrides: Map<String, String>,

View File

@ -4,14 +4,14 @@
package pl.szczodrzynski.edziennik.data.config
import android.util.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.entity.ConfigEntry
import pl.szczodrzynski.edziennik.ext.takePositive
import pl.szczodrzynski.edziennik.utils.Utils.d
import timber.log.Timber
import kotlin.coroutines.CoroutineContext
abstract class BaseConfig<T>(
@ -32,6 +32,7 @@ abstract class BaseConfig<T>(
val values = hashMapOf<String, String?>()
private var currentDataVersion: Int by config<Int>("dataVersion") {
Timber.d("Initializing ${this::class.java.simpleName} version $dataVersion")
currentDataVersion = dataVersion
dataVersion
}
@ -45,15 +46,19 @@ abstract class BaseConfig<T>(
entries = app.db.configDao().getAllNow()
values.clear()
for ((profileId, key, value) in entries!!) {
if (profileId.takePositive() != this.profileId)
if (profileId != (this.profileId ?: -1))
continue
values[key] = value
Timber.v("Loaded ${this::class.java.simpleName} profile $profileId key $key value $value")
}
}
fun migrate() {
if (this.dataVersion == this.currentDataVersion)
if (this.dataVersion == this.currentDataVersion) {
Timber.d("Config ${this::class.java.simpleName} is up to date (${this.currentDataVersion})")
return
}
Timber.i("Migrating ${this::class.java.simpleName} ${this.currentDataVersion} -> ${this.dataVersion}")
var dataVersion = this.currentDataVersion
while (dataVersion < this.dataVersion) {
@Suppress("UNCHECKED_CAST")
@ -70,7 +75,7 @@ abstract class BaseConfig<T>(
operator fun set(key: String, value: String?) {
values[key] = value
launch(Dispatchers.IO) {
d(TAG, "Setting config value ($profileId): $key = $value")
Timber.i("Setting config value ($profileId): $key = $value")
app.db.configDao().add(ConfigEntry(profileId ?: -1, key, value))
}
}

View File

@ -10,20 +10,20 @@ import pl.szczodrzynski.edziennik.BuildConfig
import pl.szczodrzynski.edziennik.data.config.migration.ConfigMigration11
import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
import pl.szczodrzynski.edziennik.data.config.migration.ConfigMigration13
import pl.szczodrzynski.edziennik.data.config.migration.ConfigMigration14
import pl.szczodrzynski.edziennik.data.enums.NavTarget
import pl.szczodrzynski.edziennik.data.enums.Theme
import pl.szczodrzynski.edziennik.ext.HOUR
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.ORDER_BY_DATE_DESC
import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.ORDER_BY_DATE_DESC
import pl.szczodrzynski.edziennik.utils.models.Time
class Config(app: App) : BaseConfig<Config>(app, profileId = null) {
override val dataVersion = 13
override val dataVersion = 14
override val migrations
get() = mapOf(
11 to ConfigMigration11(),
13 to ConfigMigration13(),
14 to ConfigMigration14(),
)
private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf()
@ -58,6 +58,7 @@ class Config(app: App) : BaseConfig<Config>(app, profileId = null) {
var apiKeyCustom by config<String?>(null)
var appInstalledTime by config<Long>(0L)
var appRateSnackbarTime by config<Long>(0L)
var lastLogCleanupTime by config<Long>(0L)
var appVersion by config<Int>(BuildConfig.VERSION_CODE)
var validation by config<String?>(null, "buildValidation")

View File

@ -4,15 +4,14 @@
package pl.szczodrzynski.edziennik.data.config
import android.util.Log
import com.google.gson.Gson
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.reflect.TypeToken
import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import timber.log.Timber
import java.lang.reflect.ParameterizedType
import java.lang.reflect.WildcardType
import kotlin.reflect.KProperty
@ -108,8 +107,7 @@ class ConfigDelegate<T>(
value = config[key]?.let(::deserialize)
} catch (e: Exception) {
value = getDefault()
d(TAG, "Couldn't deserialize '$key'")
e.printStackTrace()
Timber.e(e, "Couldn't deserialize '$key'")
}
if (value == null && !nullable)
value = getDefault()

View File

@ -14,8 +14,8 @@ import pl.szczodrzynski.edziennik.data.db.entity.ConfigEntry
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
import pl.szczodrzynski.edziennik.data.enums.NotificationType
import pl.szczodrzynski.edziennik.ui.home.HomeCardModel
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_ALL_GRADES
import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.COLOR_MODE_WEIGHTED
import pl.szczodrzynski.edziennik.core.manager.GradesManager.Companion.YEAR_ALL_GRADES
class ProfileConfig(
app: App,

View File

@ -19,7 +19,7 @@ import pl.szczodrzynski.edziennik.data.enums.Theme.TEAL
import pl.szczodrzynski.edziennik.data.enums.Theme.Type.M3
import pl.szczodrzynski.edziennik.ext.toJsonArray
class ConfigMigration13 : BaseMigration<Config>() {
class ConfigMigration14 : BaseMigration<Config>() {
override fun migrate(config: Config) = config.apply {
get("theme")?.toIntOrNull()?.let {
@ -65,7 +65,7 @@ class ConfigMigration13 : BaseMigration<Config>() {
try {
ui.miniMenuButtons = it.map { id -> NavTarget.getById(id.asInt) }.toSet()
} catch (e: Exception) {
ui.miniMenuButtons = NavTarget.getDefaultConfig()
ui.miniMenuButtons = ui.miniMenuButtons
}
}
}

View File

@ -29,7 +29,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.*
FeedbackMessage::class,
Message::class,
MessageRecipient::class,
DebugLog::class,
LogEntry::class,
EndpointTimer::class,
LessonRange::class,
Notification::class,
@ -42,7 +42,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.*
TimetableManual::class,
Note::class,
Metadata::class
], version = 100)
], version = 101)
@TypeConverters(
ConverterTime::class,
ConverterDate::class,
@ -71,7 +71,7 @@ abstract class AppDb : RoomDatabase() {
abstract fun feedbackMessageDao(): FeedbackMessageDao
abstract fun messageDao(): MessageDao
abstract fun messageRecipientDao(): MessageRecipientDao
abstract fun debugLogDao(): DebugLogDao
abstract fun logDao(): LogDao
abstract fun endpointTimerDao(): EndpointTimerDao
abstract fun lessonRangeDao(): LessonRangeDao
abstract fun notificationDao(): NotificationDao
@ -187,6 +187,7 @@ abstract class AppDb : RoomDatabase() {
Migration98(),
Migration99(),
Migration100(),
Migration101(),
).allowMainThreadQueries().build()
}
}

View File

@ -1,16 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
*/
package pl.szczodrzynski.edziennik.data.db.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import pl.szczodrzynski.edziennik.data.db.entity.DebugLog;
@Dao
public interface DebugLogDao {
@Insert
void add(DebugLog debugLog);
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) Kuba Szczodrzyński 2024-7-1.
*/
package pl.szczodrzynski.edziennik.data.db.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import pl.szczodrzynski.edziennik.data.db.entity.LogEntry
@Dao
interface LogDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun add(entry: LogEntry)
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addAll(list: List<LogEntry>)
@Query("DELETE FROM logs")
suspend fun clear()
@Query("DELETE FROM logs WHERE timestamp < :timestamp")
suspend fun clearBefore(timestamp: Long)
}

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
*/
package pl.szczodrzynski.edziennik.data.db.entity;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import static pl.szczodrzynski.edziennik.utils.Utils.d;
@Entity(tableName = "debugLogs")
public class DebugLog {
@PrimaryKey(autoGenerate = true)
public int id;
public String text;
public DebugLog(String text) {
d("DebugLog", text);
this.text = text;
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) Kuba Szczodrzyński 2024-7-1.
*/
package pl.szczodrzynski.edziennik.data.db.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "logs")
data class LogEntry(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
@ColumnInfo(index = true)
val timestamp: Long,
val priority: Int,
val tag: String?,
val message: String,
)

View File

@ -18,6 +18,7 @@ import pl.szczodrzynski.edziennik.data.enums.NotificationType
import pl.szczodrzynski.edziennik.ext.pendingIntentFlag
import pl.szczodrzynski.edziennik.ext.putExtras
import pl.szczodrzynski.edziennik.data.enums.NavTarget
import timber.log.Timber
@Entity(tableName = "notifications")
data class Notification(
@ -74,8 +75,8 @@ data class Notification(
intent.putExtra(key, primitive.asString)
}
}
} catch (e: NullPointerException) {
e.printStackTrace()
} catch (e: Exception) {
Timber.e(e)
}
}

Some files were not shown because too many files have changed in this diff Show More