commit b2bc23d0e0d519905dfed97fc486eab984a91fd6
parent de0342fdac51e4ffcae1e2df28a12030594bec0b
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sun, 21 Jul 2024 00:15:17 +0200

feat(ui/sif): download indicator

Signed-off-by: rhunk <101876869+rhunk@users.noreply.github.com>

Diffstat:
Mapp/src/main/kotlin/me/rhunk/snapenhance/RemoteSharedLibraryManager.kt | 47+++++++++++++++++++++++++++++++++++++++++++----
Mapp/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt | 6+++++-
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/setup/SetupActivity.kt | 4++--
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SecurityScreen.kt | 58++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mcommon/build.gradle.kts | 1+
5 files changed, 103 insertions(+), 13 deletions(-)

diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSharedLibraryManager.kt b/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSharedLibraryManager.kt @@ -1,7 +1,14 @@ package me.rhunk.snapenhance import android.annotation.SuppressLint +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Intent import android.os.Build +import androidx.core.net.toUri +import me.rhunk.snapenhance.common.BuildConfig import me.rhunk.snapenhance.common.bridge.InternalFileHandleType import okhttp3.OkHttpClient import okhttp3.Request @@ -16,7 +23,7 @@ class RemoteSharedLibraryManager( return runCatching { okHttpClient.newCall( Request.Builder() - .url("https://raw.githubusercontent.com/SnapEnhance/resources/main/sif/version") + .url("${BuildConfig.SIF_ENDPOINT}/version") .build() ).execute().use { response -> if (!response.isSuccessful) { @@ -30,7 +37,7 @@ class RemoteSharedLibraryManager( private fun downloadLatest(outputFile: File): Boolean { val abi = Build.SUPPORTED_ABIS.firstOrNull() ?: return false val request = Request.Builder() - .url("https://raw.githubusercontent.com/SnapEnhance/resources/main/sif/$abi.so") + .url("${BuildConfig.SIF_ENDPOINT}/$abi.so") .build() runCatching { okHttpClient.newCall(request).execute().use { response -> @@ -60,8 +67,7 @@ class RemoteSharedLibraryManager( return } val latestVersion = getVersion()?.trim() ?: run { - remoteSideContext.log.warn("Failed to get latest sif version") - return + throw Exception("Failed to get latest sif version") } if (currentVersion == latestVersion) { @@ -73,12 +79,45 @@ class RemoteSharedLibraryManager( if (downloadLatest(libraryFile)) { remoteSideContext.sharedPreferences.edit().putString("sif", latestVersion).commit() remoteSideContext.shortToast("SIF updated to $latestVersion!") + + if (currentVersion.isNotEmpty()) { + val notificationManager = remoteSideContext.androidContext.getSystemService(NotificationManager::class.java) + val channelId = "sif_update" + + notificationManager.createNotificationChannel( + NotificationChannel( + channelId, + "SIF Updates", + NotificationManager.IMPORTANCE_DEFAULT + ) + ) + + notificationManager.notify( + System.nanoTime().toInt(), + Notification.Builder(remoteSideContext.androidContext, channelId) + .setContentTitle("SnapEnhance") + .setContentText("Security Features have been updated to version $latestVersion") + .setSmallIcon(android.R.drawable.stat_sys_download_done) + .setContentIntent(PendingIntent.getActivity( + remoteSideContext.androidContext, + 0, + Intent().apply { + action = Intent.ACTION_VIEW + data = "https://github.com/SnapEnhance/resources".toUri() + flags = Intent.FLAG_ACTIVITY_NEW_TASK + }, + PendingIntent.FLAG_UPDATE_CURRENT + )).build() + ) + } + // force restart snapchat runCatching { remoteSideContext.config.configStateListener?.takeIf { it.asBinder().pingBinder() }?.onRestartRequired() } } else { remoteSideContext.log.warn("Failed to download latest sif") + throw Exception("Failed to download latest sif") } } } \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt b/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt @@ -133,7 +133,11 @@ class RemoteSideContext( } } coroutineScope.launch { - remoteSharedLibraryManager.init() + runCatching { + remoteSharedLibraryManager.init() + }.onFailure { + log.error("Failed to init RemoteSharedLibraryManager", it) + } } } }.onFailure { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/SetupActivity.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/SetupActivity.kt @@ -66,9 +66,9 @@ class SetupActivity : ComponentActivity() { if (isFirstRun || hasRequirement(Requirements.MAPPINGS)) { add(MappingsScreen().apply { route = "mappings" }) } - /*if (isFirstRun || hasRequirement(Requirements.SIF)) { + if (hasRequirement(Requirements.SIF)) { add(SecurityScreen().apply { route = "security" }) - }*/ + } } // If there are no required screens, we can just finish the activity diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SecurityScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SecurityScreen.kt @@ -1,6 +1,9 @@ package me.rhunk.snapenhance.ui.setup.screens.impl +import android.annotation.SuppressLint import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.WarningAmber import androidx.compose.material3.* @@ -10,16 +13,22 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import me.rhunk.snapenhance.ui.setup.screens.SetupScreen class SecurityScreen : SetupScreen() { + @SuppressLint("ApplySharedPref") @Composable override fun Content() { Icon( imageVector = Icons.Default.WarningAmber, contentDescription = null, - modifier = Modifier.padding(16.dp).size(30.dp), + modifier = Modifier + .padding(16.dp) + .size(30.dp), ) DialogText( @@ -57,6 +66,47 @@ class SecurityScreen : SetupScreen() { ) } + var downloadJob by remember { mutableStateOf(null as Job?) } + var jobError by remember { mutableStateOf(null as Throwable?) } + + if (downloadJob != null) { + AlertDialog(onDismissRequest = { + downloadJob?.cancel() + downloadJob = null + }, confirmButton = {}, text = { + Column( + modifier = Modifier.verticalScroll(rememberScrollState()).fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp), + ) { + if (jobError != null) { + Text("Failed to download the required files.\n\n${jobError?.message}") + } else { + Text("Downloading the required files...") + CircularProgressIndicator(modifier = Modifier.padding(16.dp)) + } + } + }) + } + + fun newDownloadJob() { + downloadJob?.cancel() + downloadJob = context.coroutineScope.launch { + context.sharedPreferences.edit().putString("sif", "").commit() + runCatching { + context.remoteSharedLibraryManager.init() + }.onFailure { + jobError = it + context.log.error("Failed to download the required files", it) + }.onSuccess { + downloadJob = null + withContext(Dispatchers.Main) { + goNext() + } + } + } + } + Column ( modifier = Modifier.padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, @@ -64,11 +114,7 @@ class SecurityScreen : SetupScreen() { ) { Button( onClick = { - context.coroutineScope.launch { - context.sharedPreferences.edit().putString("sif", "").commit() - context.remoteSharedLibraryManager.init() - } - goNext() + newDownloadJob() } ) { Text("Accept and continue", fontSize = 18.sp, fontWeight = FontWeight.Bold) diff --git a/common/build.gradle.kts b/common/build.gradle.kts @@ -30,6 +30,7 @@ android { standardOutput = gitHash } buildConfigField("String", "GIT_HASH", "\"${gitHash.toString(Charsets.UTF_8).trim()}\"") + buildConfigField("String", "SIF_ENDPOINT", "\"${properties["debug_sif_endpoint"]?.toString() ?: "https://raw.githubusercontent.com/SnapEnhance/resources/main/sif"}\"") } compileOptions {