Files
gotify-android-client/app/src/main/kotlin/com/github/gotify/init/InitializationActivity.kt
2023-01-27 16:04:20 +01:00

191 lines
6.7 KiB
Kotlin

package com.github.gotify.init
import android.Manifest
import android.app.NotificationManager
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceManager
import com.github.gotify.NotificationSupport
import com.github.gotify.R
import com.github.gotify.Settings
import com.github.gotify.api.ApiException
import com.github.gotify.api.Callback
import com.github.gotify.api.Callback.SuccessCallback
import com.github.gotify.api.ClientFactory
import com.github.gotify.client.model.User
import com.github.gotify.client.model.VersionInfo
import com.github.gotify.log.Log
import com.github.gotify.log.UncaughtExceptionHandler
import com.github.gotify.login.LoginActivity
import com.github.gotify.messages.MessagesActivity
import com.github.gotify.service.WebSocketService
import com.github.gotify.settings.ThemeHelper
import com.livinglifetechway.quickpermissionskotlin.runWithPermissions
import com.livinglifetechway.quickpermissionskotlin.util.QuickPermissionsOptions
import com.livinglifetechway.quickpermissionskotlin.util.QuickPermissionsRequest
internal class InitializationActivity : AppCompatActivity() {
private lateinit var settings: Settings
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.init(this)
val theme = PreferenceManager.getDefaultSharedPreferences(this)
.getString(getString(R.string.setting_key_theme), getString(R.string.theme_default))!!
ThemeHelper.setTheme(this, theme)
setContentView(R.layout.splash)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationSupport.createChannels(
this.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
)
}
UncaughtExceptionHandler.registerCurrentThread()
settings = Settings(this)
Log.i("Entering ${javaClass.simpleName}")
if (settings.tokenExists()) {
runWithNeededPermissions {
tryAuthenticate()
}
} else {
showLogin()
}
}
private fun showLogin() {
startActivity(Intent(this, LoginActivity::class.java))
finish()
}
private fun tryAuthenticate() {
ClientFactory.userApiWithToken(settings)
.currentUser()
.enqueue(
Callback.callInUI(
this,
onSuccess = Callback.SuccessBody { user -> authenticated(user) },
onError = { exception -> failed(exception) }
)
)
}
private fun failed(exception: ApiException) {
when (exception.code) {
0 -> {
dialog(getString(R.string.not_available, settings.url))
return
}
401 -> {
dialog(getString(R.string.auth_failed))
return
}
}
var response = exception.body
response = response.take(200)
dialog(getString(R.string.other_error, settings.url, exception.code, response))
}
private fun dialog(message: String) {
AlertDialog.Builder(this)
.setTitle(R.string.oops)
.setMessage(message)
.setPositiveButton(R.string.retry) { _, _ -> tryAuthenticate() }
.setNegativeButton(R.string.logout) { _, _ -> showLogin() }
.show()
}
private fun authenticated(user: User) {
Log.i("Authenticated as ${user.name}")
settings.setUser(user.name, user.isAdmin)
requestVersion {
startActivity(Intent(this, MessagesActivity::class.java))
finish()
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(Intent(this, WebSocketService::class.java))
} else {
startService(Intent(this, WebSocketService::class.java))
}
}
private fun requestVersion(runnable: Runnable) {
requestVersion(
callback = Callback.SuccessBody { version: VersionInfo ->
Log.i("Server version: ${version.version}@${version.buildDate}")
settings.serverVersion = version.version
runnable.run()
},
errorCallback = { runnable.run() }
)
}
private fun requestVersion(
callback: SuccessCallback<VersionInfo>,
errorCallback: Callback.ErrorCallback
) {
ClientFactory.versionApi(settings.url, settings.sslSettings())
.version
.enqueue(Callback.callInUI(this, callback, errorCallback))
}
private fun runWithNeededPermissions(action: () -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val quickPermissionsOption = QuickPermissionsOptions(
handleRationale = true,
handlePermanentlyDenied = true,
rationaleMethod = { req -> processPermissionRationale(req) },
permissionsDeniedMethod = { req -> processPermissionRationale(req) },
permanentDeniedMethod = { req -> processPermissionsPermanentDenied(req) }
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// Android 13 and above
runWithPermissions(
Manifest.permission.SCHEDULE_EXACT_ALARM,
Manifest.permission.POST_NOTIFICATIONS,
options = quickPermissionsOption,
callback = action
)
} else {
// Android 12 and Android 12L
runWithPermissions(
Manifest.permission.SCHEDULE_EXACT_ALARM,
options = quickPermissionsOption,
callback = action
)
}
} else {
// Android 11 and below
action()
}
}
private fun processPermissionRationale(req: QuickPermissionsRequest) {
AlertDialog.Builder(this)
.setMessage(getString(R.string.permissions_denied_temp))
.setPositiveButton(getString(R.string.permissions_dialog_grant)) { _, _ ->
req.proceed()
}
.setCancelable(false)
.show()
}
private fun processPermissionsPermanentDenied(req: QuickPermissionsRequest) {
AlertDialog.Builder(this)
.setMessage(getString(R.string.permissions_denied_permanent))
.setPositiveButton(getString(R.string.permissions_dialog_grant)) { _, _ ->
req.openAppSettings()
}
.setCancelable(false)
.show()
}
}