From 61da95f41b3716364a587a156ac8981b0c9ecf4b Mon Sep 17 00:00:00 2001 From: rhunk <101876869+rhunk@users.noreply.github.com> Date: Thu, 31 Aug 2023 00:59:30 +0200 Subject: [PATCH] feat: log system - debug actions - move packages to core --- .../kotlin/me/rhunk/snapenhance/LogManager.kt | 189 +++++++++++ .../me/rhunk/snapenhance/RemoteSideContext.kt | 71 ++-- .../rhunk/snapenhance/bridge/BridgeService.kt | 35 +- .../snapenhance/download/DownloadProcessor.kt | 29 +- .../snapenhance/messaging/ModDatabase.kt | 7 +- .../rhunk/snapenhance/ui/manager/Section.kt | 4 +- .../ui/manager/data/InstallationSummary.kt | 27 +- .../ui/manager/sections/HomeSection.kt | 147 --------- .../sections/downloads/DownloadsSection.kt | 4 +- .../sections/features/FeaturesSection.kt | 2 +- .../ui/manager/sections/home/HomeSection.kt | 312 ++++++++++++++++++ .../manager/sections/home/HomeSubSection.kt | 214 ++++++++++++ .../sections/social/AddFriendDialog.kt | 15 +- .../manager/sections/social/SocialSection.kt | 4 +- .../ui/setup/screens/impl/MappingsScreen.kt | 4 +- .../setup/screens/impl/PickLanguageScreen.kt | 2 +- .../ui/setup/screens/impl/SaveFolderScreen.kt | 2 - .../ui/util/ActivityLauncherHelper.kt | 2 +- .../rhunk/snapenhance/ui/util/AlertDialogs.kt | 2 +- .../snapenhance/bridge/BridgeInterface.aidl | 33 +- core/src/main/assets/lang/en_US.json | 6 +- .../kotlin/me/rhunk/snapenhance/Constants.kt | 2 - .../kotlin/me/rhunk/snapenhance/Logger.kt | 98 ++++-- .../kotlin/me/rhunk/snapenhance/ModContext.kt | 16 +- .../me/rhunk/snapenhance/SnapEnhance.kt | 9 +- .../snapenhance/action/AbstractAction.kt | 9 +- .../me/rhunk/snapenhance/action/EnumAction.kt | 17 + .../action/impl/CheckForUpdates.kt | 19 -- .../snapenhance/action/impl/CleanCache.kt | 4 +- .../action/impl/ClearMessageLogger.kt | 10 - .../action/impl/ExportChatMessages.kt | 9 +- .../rhunk/snapenhance/action/impl/OpenMap.kt | 2 +- .../action/impl/RefreshMappings.kt | 11 - .../{ => core}/bridge/BridgeClient.kt | 18 +- .../{ => core}/bridge/FileLoaderWrapper.kt | 4 +- .../{ => core}/bridge/types/BridgeFileType.kt | 2 +- .../{ => core}/bridge/types/FileActionType.kt | 2 +- .../bridge/wrapper/LocaleWrapper.kt | 6 +- .../bridge/wrapper/MappingsWrapper.kt | 11 +- .../bridge/wrapper/MessageLoggerWrapper.kt | 2 +- .../snapenhance/core/config/ConfigObjects.kt | 2 +- .../snapenhance/core/config/ModConfig.kt | 10 +- .../core/config/impl/Experimental.kt | 3 +- .../{ => core}/database/DatabaseAccess.kt | 10 +- .../{ => core}/database/DatabaseObject.kt | 2 +- .../database/objects/ConversationMessage.kt | 4 +- .../database/objects/FriendFeedEntry.kt | 4 +- .../{ => core}/database/objects/FriendInfo.kt | 4 +- .../{ => core}/database/objects/StoryEntry.kt | 4 +- .../database/objects/UserConversationLink.kt | 4 +- .../download/DownloadManagerClient.kt | 26 +- .../download/DownloadTaskManager.kt | 10 +- .../download/data/DownloadMediaType.kt | 2 +- .../download/data/DownloadMetadata.kt | 2 +- .../download/data/DownloadObject.kt | 4 +- .../download/data/DownloadRequest.kt | 2 +- .../{ => core}/download/data/DownloadStage.kt | 2 +- .../download/data/MediaEncryptionKeyPair.kt | 2 +- .../{ => core}/download/data/MediaFilter.kt | 2 +- .../download/data/SplitMediaAssetType.kt | 2 +- .../snapenhance/core/eventbus/EventBus.kt | 7 +- .../snapenhance/features/BridgeFileFeature.kt | 2 +- .../snapenhance/features/impl/AutoUpdater.kt | 3 +- .../impl/downloader/MediaDownloader.kt | 32 +- .../downloader/ProfilePictureDownloader.kt | 3 +- .../impl/experiments/DeviceSpooferHook.kt | 7 +- .../impl/privacy/PreventMessageSending.kt | 3 +- .../impl/spying/AnonymousStoryViewing.kt | 1 - .../features/impl/spying/MessageLogger.kt | 3 +- .../features/impl/tweaks/AutoSave.kt | 2 +- .../tweaks/DisableVideoLengthRestriction.kt | 3 +- .../impl/tweaks/GooglePlayServicesDialogs.kt | 3 +- .../features/impl/tweaks/Notifications.kt | 6 +- .../features/impl/ui/PinConversations.kt | 2 +- .../snapenhance/manager/impl/ActionManager.kt | 45 ++- .../ui/menu/impl/FriendFeedInfoMenu.kt | 10 +- .../ui/menu/impl/OperaContextActionMenu.kt | 3 +- .../snapenhance/ui/menu/impl/SettingsMenu.kt | 6 +- .../snapenhance/util/SQLiteDatabaseHelper.kt | 2 +- .../snapenhance/util/download/HttpServer.kt | 14 +- .../util/download/RemoteMediaResolver.kt | 2 +- .../util/export/MessageExporter.kt | 9 +- .../util/snap/MediaDownloaderHelper.kt | 2 +- 83 files changed, 1118 insertions(+), 515 deletions(-) create mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/LogManager.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/HomeSection.kt create mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSection.kt create mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSubSection.kt create mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/action/EnumAction.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CheckForUpdates.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/action/impl/ClearMessageLogger.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/action/impl/RefreshMappings.kt rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/bridge/BridgeClient.kt (89%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/bridge/FileLoaderWrapper.kt (91%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/bridge/types/BridgeFileType.kt (94%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/bridge/types/FileActionType.kt (62%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/bridge/wrapper/LocaleWrapper.kt (95%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/bridge/wrapper/MappingsWrapper.kt (93%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/bridge/wrapper/MessageLoggerWrapper.kt (98%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/database/DatabaseAccess.kt (94%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/database/DatabaseObject.kt (68%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/database/objects/ConversationMessage.kt (94%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/database/objects/FriendFeedEntry.kt (94%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/database/objects/FriendInfo.kt (96%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/database/objects/StoryEntry.kt (86%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/database/objects/UserConversationLink.kt (85%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/DownloadManagerClient.kt (74%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/DownloadTaskManager.kt (95%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/data/DownloadMediaType.kt (91%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/data/DownloadMetadata.kt (79%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/data/DownloadObject.kt (87%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/data/DownloadRequest.kt (92%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/data/DownloadStage.kt (83%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/data/MediaEncryptionKeyPair.kt (93%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/data/MediaFilter.kt (89%) rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/download/data/SplitMediaAssetType.kt (54%) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/LogManager.kt b/app/src/main/kotlin/me/rhunk/snapenhance/LogManager.kt new file mode 100644 index 00000000..caabcd53 --- /dev/null +++ b/app/src/main/kotlin/me/rhunk/snapenhance/LogManager.kt @@ -0,0 +1,189 @@ +package me.rhunk.snapenhance + +import android.content.SharedPreferences +import android.util.Log +import java.io.File +import java.io.OutputStream +import java.io.RandomAccessFile +import java.time.format.DateTimeFormatter +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream +import kotlin.time.Duration.Companion.hours + +class LogLine( + val logLevel: LogLevel, + val dateTime: String, + val tag: String, + val message: String +) { + companion object { + fun fromString(line: String) = runCatching { + val parts = line.trimEnd().split("/") + if (parts.size != 4) return@runCatching null + LogLine( + LogLevel.fromLetter(parts[0]) ?: return@runCatching null, + parts[1], + parts[2], + parts[3] + ) + }.getOrNull() + } + + override fun toString(): String { + return "${logLevel.letter}/$dateTime/$tag/$message" + } +} + + +class LogReader( + logFile: File +) { + private val randomAccessFile = RandomAccessFile(logFile, "r") + private var startLineIndexes = mutableListOf() + var lineCount = queryLineCount() + + fun incrementLineCount() { + randomAccessFile.seek(randomAccessFile.length()) + startLineIndexes.add(randomAccessFile.filePointer) + lineCount++ + } + + private fun queryLineCount(): Int { + randomAccessFile.seek(0) + var lines = 0 + var lastIndex: Long + while (true) { + lastIndex = randomAccessFile.filePointer + randomAccessFile.readLine() ?: break + startLineIndexes.add(lastIndex) + lines++ + } + return lines + } + + private fun getLine(index: Int): String? { + if (index <= 0 || index > lineCount) return null + randomAccessFile.seek(startLineIndexes[index]) + return randomAccessFile.readLine() + } + + fun getLogLine(index: Int): LogLine? { + return getLine(index)?.let { LogLine.fromString(it) } + } +} + + +class LogManager( + remoteSideContext: RemoteSideContext +) { + companion object { + private const val TAG = "SnapEnhanceManager" + private val LOG_LIFETIME = 24.hours + } + + var lineAddListener = { _: LogLine -> } + + private val logFolder = File(remoteSideContext.androidContext.cacheDir, "logs") + private val preferences: SharedPreferences + + private var logFile: File + + init { + if (!logFolder.exists()) { + logFolder.mkdirs() + } + preferences = remoteSideContext.androidContext.getSharedPreferences("logger", 0) + logFile = preferences.getString("log_file", null)?.let { File(it) }?.takeIf { it.exists() } ?: run { + newLogFile() + logFile + } + + if (System.currentTimeMillis() - preferences.getLong("last_created", 0) > LOG_LIFETIME.inWholeMilliseconds) { + newLogFile() + } + } + + private fun getCurrentDateTime(pathSafe: Boolean = false): String { + return DateTimeFormatter.ofPattern(if (pathSafe) "yyyy-MM-dd_HH-mm-ss" else "yyyy-MM-dd HH:mm:ss").format( + java.time.LocalDateTime.now() + ) + } + + private fun newLogFile() { + val currentTime = System.currentTimeMillis() + logFile = File(logFolder, "snapenhance_${getCurrentDateTime(pathSafe = true)}.log").also { + it.createNewFile() + } + preferences.edit().putString("log_file", logFile.absolutePath).putLong("last_created", currentTime).apply() + } + + fun clearLogs() { + logFile.delete() + newLogFile() + } + + fun getLogFile() = logFile + + fun exportLogsToZip(outputStream: OutputStream) { + val zipOutputStream = ZipOutputStream(outputStream) + //add logFolder to zip + logFolder.walk().forEach { + if (it.isFile) { + zipOutputStream.putNextEntry(ZipEntry(it.name)) + it.inputStream().copyTo(zipOutputStream) + zipOutputStream.closeEntry() + } + } + + //add device info to zip + zipOutputStream.putNextEntry(ZipEntry("device_info.txt")) + + + zipOutputStream.close() + } + + fun newReader(onAddLine: (LogLine) -> Unit) = LogReader(logFile).also { + lineAddListener = { line -> it.incrementLineCount(); onAddLine(line) } + } + + fun debug(message: Any?, tag: String = TAG) { + internalLog(tag, LogLevel.DEBUG, message) + } + + fun error(message: Any?, tag: String = TAG) { + internalLog(tag, LogLevel.ERROR, message) + } + + fun error(message: Any?, throwable: Throwable, tag: String = TAG) { + internalLog(tag, LogLevel.ERROR, message) + internalLog(tag, LogLevel.ERROR, throwable) + } + + fun info(message: Any?, tag: String = TAG) { + internalLog(tag, LogLevel.INFO, message) + } + + fun verbose(message: Any?, tag: String = TAG) { + internalLog(tag, LogLevel.VERBOSE, message) + } + + fun warn(message: Any?, tag: String = TAG) { + internalLog(tag, LogLevel.WARN, message) + } + + fun assert(message: Any?, tag: String = TAG) { + internalLog(tag, LogLevel.ASSERT, message) + } + + fun internalLog(tag: String, logLevel: LogLevel, message: Any?) { + runCatching { + val line = LogLine(logLevel, getCurrentDateTime(), tag, message.toString()) + logFile.appendText("$line\n", Charsets.UTF_8) + lineAddListener(line) + Log.println(logLevel.priority, tag, message.toString()) + }.onFailure { + Log.println(Log.ERROR, tag, "Failed to log message: $message") + Log.println(Log.ERROR, tag, it.toString()) + } + } +} \ 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 index a523196b..75c50c4c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt @@ -3,9 +3,12 @@ package me.rhunk.snapenhance import android.app.Activity import android.content.Context import android.content.Intent +import android.content.pm.PackageManager import android.net.Uri +import android.os.Build import android.widget.Toast import androidx.activity.ComponentActivity +import androidx.core.app.CoreComponentFactory import androidx.documentfile.provider.DocumentFile import coil.ImageLoader import coil.decode.VideoFrameDecoder @@ -13,18 +16,25 @@ import coil.disk.DiskCache import coil.memory.MemoryCache import kotlinx.coroutines.Dispatchers import me.rhunk.snapenhance.bridge.BridgeService -import me.rhunk.snapenhance.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.bridge.wrapper.MappingsWrapper +import me.rhunk.snapenhance.core.BuildConfig +import me.rhunk.snapenhance.core.bridge.wrapper.LocaleWrapper +import me.rhunk.snapenhance.core.bridge.wrapper.MappingsWrapper import me.rhunk.snapenhance.core.config.ModConfig -import me.rhunk.snapenhance.download.DownloadTaskManager +import me.rhunk.snapenhance.core.download.DownloadTaskManager import me.rhunk.snapenhance.messaging.ModDatabase import me.rhunk.snapenhance.messaging.StreaksReminder +import me.rhunk.snapenhance.ui.manager.MainActivity import me.rhunk.snapenhance.ui.manager.data.InstallationSummary -import me.rhunk.snapenhance.ui.manager.data.ModMappingsInfo +import me.rhunk.snapenhance.ui.manager.data.ModInfo +import me.rhunk.snapenhance.ui.manager.data.PlatformInfo import me.rhunk.snapenhance.ui.manager.data.SnapchatAppInfo import me.rhunk.snapenhance.ui.setup.Requirements import me.rhunk.snapenhance.ui.setup.SetupActivity +import java.io.ByteArrayInputStream import java.lang.ref.WeakReference +import java.security.cert.CertificateFactory +import java.security.cert.X509Certificate + class RemoteSideContext( val androidContext: Context @@ -42,6 +52,7 @@ class RemoteSideContext( val downloadTaskManager = DownloadTaskManager() val modDatabase = ModDatabase(this) val streaksReminder = StreaksReminder(this) + val log = LogManager(this) //used to load bitmoji selfies and download previews val imageLoader by lazy { @@ -76,37 +87,57 @@ class RemoteSideContext( modDatabase.init() streaksReminder.init() }.onFailure { - Logger.error("Failed to load RemoteSideContext", it) + log.error("Failed to load RemoteSideContext", it) } } - fun getInstallationSummary() = InstallationSummary( - snapchatInfo = mappings.getSnapchatPackageInfo()?.let { - SnapchatAppInfo( - version = it.versionName, - versionCode = it.longVersionCode + val installationSummary by lazy { + InstallationSummary( + snapchatInfo = mappings.getSnapchatPackageInfo()?.let { + SnapchatAppInfo( + packageName = it.packageName, + version = it.versionName, + versionCode = it.longVersionCode, + isLSPatched = it.applicationInfo.appComponentFactory != CoreComponentFactory::class.java.name, + isSplitApk = it.splitNames.isNotEmpty() + ) + }, + modInfo = ModInfo( + loaderPackageName = MainActivity::class.java.`package`?.name ?: "unknown", + buildPackageName = BuildConfig.APPLICATION_ID, + buildVersion = BuildConfig.VERSION_NAME, + buildVersionCode = BuildConfig.VERSION_CODE.toLong(), + buildIssuer = androidContext.packageManager.getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_SIGNING_CERTIFICATES) + ?.signingInfo?.apkContentsSigners?.firstOrNull()?.let { + val certFactory = CertificateFactory.getInstance("X509") + val cert = certFactory.generateCertificate(ByteArrayInputStream(it.toByteArray())) as X509Certificate + cert.issuerDN.toString() + } ?: throw Exception("Failed to get certificate info"), + isDebugBuild = BuildConfig.DEBUG, + mappingVersion = mappings.getGeneratedBuildNumber(), + mappingsOutdated = mappings.isMappingsOutdated() + ), + platformInfo = PlatformInfo( + device = Build.DEVICE, + buildFingerprint = Build.FINGERPRINT, + androidVersion = Build.VERSION.RELEASE, + systemAbi = Build.SUPPORTED_ABIS.firstOrNull() ?: "unknown" ) - }, - mappingsInfo = if (mappings.isMappingsLoaded()) { - ModMappingsInfo( - generatedSnapchatVersion = mappings.getGeneratedBuildNumber(), - isOutdated = mappings.isMappingsOutdated() - ) - } else null - ) + ) + } fun longToast(message: Any) { androidContext.mainExecutor.execute { Toast.makeText(androidContext, message.toString(), Toast.LENGTH_LONG).show() } - Logger.debug(message.toString()) + log.debug(message.toString()) } fun shortToast(message: Any) { androidContext.mainExecutor.execute { Toast.makeText(androidContext, message.toString(), Toast.LENGTH_SHORT).show() } - Logger.debug(message.toString()) + log.debug(message.toString()) } fun checkForRequirements(overrideRequirements: Int? = null): Boolean { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt index 56cec538..84dd0137 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt @@ -3,16 +3,16 @@ package me.rhunk.snapenhance.bridge import android.app.Service import android.content.Intent import android.os.IBinder -import me.rhunk.snapenhance.Logger +import me.rhunk.snapenhance.LogLevel import me.rhunk.snapenhance.RemoteSideContext import me.rhunk.snapenhance.SharedContextHolder -import me.rhunk.snapenhance.bridge.types.BridgeFileType -import me.rhunk.snapenhance.bridge.types.FileActionType -import me.rhunk.snapenhance.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.bridge.wrapper.MessageLoggerWrapper +import me.rhunk.snapenhance.core.bridge.types.BridgeFileType +import me.rhunk.snapenhance.core.bridge.types.FileActionType +import me.rhunk.snapenhance.core.bridge.wrapper.LocaleWrapper +import me.rhunk.snapenhance.core.bridge.wrapper.MessageLoggerWrapper +import me.rhunk.snapenhance.core.database.objects.FriendInfo import me.rhunk.snapenhance.core.messaging.MessagingFriendInfo import me.rhunk.snapenhance.core.messaging.MessagingGroupInfo -import me.rhunk.snapenhance.database.objects.FriendInfo import me.rhunk.snapenhance.download.DownloadProcessor import me.rhunk.snapenhance.util.SerializableDataObject import kotlin.system.measureTimeMillis @@ -36,7 +36,7 @@ class BridgeService : Service() { fun triggerFriendSync(friendId: String) { val syncedFriend = syncCallback.syncFriend(friendId) if (syncedFriend == null) { - Logger.error("Failed to sync friend $friendId") + remoteSideContext.log.error("Failed to sync friend $friendId") return } SerializableDataObject.fromJson(syncedFriend).let { @@ -47,7 +47,7 @@ class BridgeService : Service() { fun triggerGroupSync(groupId: String) { val syncedGroup = syncCallback.syncGroup(groupId) if (syncedGroup == null) { - Logger.error("Failed to sync group $groupId") + remoteSideContext.log.error("Failed to sync group $groupId") return } SerializableDataObject.fromJson(syncedGroup).let { @@ -56,10 +56,12 @@ class BridgeService : Service() { } inner class BridgeBinder : BridgeInterface.Stub() { + override fun broadcastLog(tag: String, level: String, message: String) { + remoteSideContext.log.internalLog(tag, LogLevel.fromShortName(level) ?: LogLevel.INFO, message) + } + override fun fileOperation(action: Int, fileType: Int, content: ByteArray?): ByteArray { - val resolvedFile by lazy { - BridgeFileType.fromValue(fileType)?.resolve(this@BridgeService) - } + val resolvedFile = BridgeFileType.fromValue(fileType)?.resolve(this@BridgeService) return when (FileActionType.values()[action]) { FileActionType.CREATE_AND_READ -> { @@ -108,8 +110,6 @@ class BridgeService : Service() { override fun deleteMessageLoggerMessage(conversationId: String, id: Long) = messageLoggerWrapper.deleteMessage(conversationId, id) - override fun clearMessageLogger() = messageLoggerWrapper.clearMessages() - override fun getApplicationApkPath(): String = applicationInfo.publicSourceDir override fun fetchLocales(userLocale: String) = @@ -133,25 +133,24 @@ class BridgeService : Service() { } override fun sync(callback: SyncCallback) { - Logger.debug("Syncing remote") syncCallback = callback measureTimeMillis { remoteSideContext.modDatabase.getFriends().map { it.userId } .forEach { friendId -> runCatching { triggerFriendSync(friendId) }.onFailure { - Logger.error("Failed to sync friend $friendId", it) + remoteSideContext.log.error("Failed to sync friend $friendId", it) } } remoteSideContext.modDatabase.getGroups().map { it.conversationId }.forEach { groupId -> runCatching { triggerGroupSync(groupId) }.onFailure { - Logger.error("Failed to sync group $groupId", it) + remoteSideContext.log.error("Failed to sync group $groupId", it) } } }.also { - Logger.debug("Syncing remote took $it ms") + remoteSideContext.log.verbose("Syncing remote took $it ms") } } @@ -159,7 +158,7 @@ class BridgeService : Service() { groups: List, friends: List ) { - Logger.debug("Received ${groups.size} groups and ${friends.size} friends") + remoteSideContext.log.verbose("Received ${groups.size} groups and ${friends.size} friends") remoteSideContext.modDatabase.receiveMessagingDataCallback( friends.map { SerializableDataObject.fromJson(it) }, groups.map { SerializableDataObject.fromJson(it) } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt b/app/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt index cd937e47..7aeec42e 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt @@ -19,14 +19,15 @@ import me.rhunk.snapenhance.Constants import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.RemoteSideContext import me.rhunk.snapenhance.bridge.DownloadCallback +import me.rhunk.snapenhance.core.download.DownloadManagerClient import me.rhunk.snapenhance.data.FileType -import me.rhunk.snapenhance.download.data.DownloadMediaType -import me.rhunk.snapenhance.download.data.DownloadMetadata -import me.rhunk.snapenhance.download.data.DownloadObject -import me.rhunk.snapenhance.download.data.DownloadRequest -import me.rhunk.snapenhance.download.data.DownloadStage -import me.rhunk.snapenhance.download.data.InputMedia -import me.rhunk.snapenhance.download.data.MediaEncryptionKeyPair +import me.rhunk.snapenhance.core.download.data.DownloadMediaType +import me.rhunk.snapenhance.core.download.data.DownloadMetadata +import me.rhunk.snapenhance.core.download.data.DownloadObject +import me.rhunk.snapenhance.core.download.data.DownloadRequest +import me.rhunk.snapenhance.core.download.data.DownloadStage +import me.rhunk.snapenhance.core.download.data.InputMedia +import me.rhunk.snapenhance.core.download.data.MediaEncryptionKeyPair import me.rhunk.snapenhance.util.download.RemoteMediaResolver import me.rhunk.snapenhance.util.snap.MediaDownloaderHelper import java.io.File @@ -178,14 +179,14 @@ class DownloadProcessor ( mediaScanIntent.setData(outputFile.uri) remoteSideContext.androidContext.sendBroadcast(mediaScanIntent) }.onFailure { - Logger.error("Failed to scan media file", it) + remoteSideContext.log.error("Failed to scan media file", it) callbackOnFailure(translation.format("failed_gallery_toast", "error" to it.toString()), it.message) } - Logger.debug("download complete") + remoteSideContext.log.verbose("download complete") callbackOnSuccess(fileName) }.onFailure { exception -> - Logger.error(exception) + remoteSideContext.log.error("Failed to save media to gallery", exception) callbackOnFailure(translation.format("failed_gallery_toast", "error" to exception.toString()), exception.message) downloadObject.downloadStage = DownloadStage.FAILED } @@ -284,7 +285,7 @@ class DownloadProcessor ( saveMediaToGallery(outputFile, downloadObjectObject) }.onFailure { exception -> if (coroutineContext.job.isCancelled) return@onFailure - Logger.error(exception) + remoteSideContext.log.error("Failed to download dash media", exception) callbackOnFailure(translation.format("failed_processing_toast", "error" to exception.toString()), exception.message) downloadObjectObject.downloadStage = DownloadStage.FAILED } @@ -333,7 +334,7 @@ class DownloadProcessor ( val downloadedMedias = downloadInputMedias(downloadRequest).map { it.key to DownloadedFile(it.value, FileType.fromFile(it.value)) }.toMap().toMutableMap() - Logger.debug("downloaded ${downloadedMedias.size} medias") + remoteSideContext.log.verbose("downloaded ${downloadedMedias.size} medias") var shouldMergeOverlay = downloadRequest.shouldMergeOverlay @@ -376,7 +377,7 @@ class DownloadProcessor ( saveMediaToGallery(mergedOverlay, downloadObjectObject) }.onFailure { exception -> if (coroutineContext.job.isCancelled) return@onFailure - Logger.error(exception) + remoteSideContext.log.error("Failed to merge overlay", exception) callbackOnFailure(translation.format("failed_processing_toast", "error" to exception.toString()), exception.message) downloadObjectObject.downloadStage = DownloadStage.MERGE_FAILED } @@ -390,7 +391,7 @@ class DownloadProcessor ( downloadRemoteMedia(downloadObjectObject, downloadedMedias, downloadRequest) }.onFailure { exception -> downloadObjectObject.downloadStage = DownloadStage.FAILED - Logger.error(exception) + remoteSideContext.log.error("Failed to download media", exception) callbackOnFailure(translation["failed_generic_toast"], exception.message) } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/messaging/ModDatabase.kt b/app/src/main/kotlin/me/rhunk/snapenhance/messaging/ModDatabase.kt index e87c6535..978b5aa4 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/messaging/ModDatabase.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/messaging/ModDatabase.kt @@ -1,13 +1,12 @@ package me.rhunk.snapenhance.messaging import android.database.sqlite.SQLiteDatabase -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.RemoteSideContext +import me.rhunk.snapenhance.core.database.objects.FriendInfo import me.rhunk.snapenhance.core.messaging.FriendStreaks import me.rhunk.snapenhance.core.messaging.MessagingFriendInfo import me.rhunk.snapenhance.core.messaging.MessagingGroupInfo import me.rhunk.snapenhance.core.messaging.MessagingRuleType -import me.rhunk.snapenhance.database.objects.FriendInfo import me.rhunk.snapenhance.util.SQLiteDatabaseHelper import me.rhunk.snapenhance.util.ktx.getInteger import me.rhunk.snapenhance.util.ktx.getLongOrNull @@ -28,7 +27,7 @@ class ModDatabase( runCatching { block() }.onFailure { - Logger.error("Failed to execute async block", it) + context.log.error("Failed to execute async block", it) } } } @@ -103,7 +102,7 @@ class ModDatabase( selfieId = cursor.getStringOrNull("selfieId") )) }.onFailure { - Logger.error("Failed to parse friend", it) + context.log.error("Failed to parse friend", it) } } friends diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Section.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Section.kt index b6a4fba1..717ca5d6 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Section.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Section.kt @@ -13,7 +13,7 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.ui.manager.sections.HomeSection +import me.rhunk.snapenhance.ui.manager.sections.home.HomeSection import me.rhunk.snapenhance.ui.manager.sections.NotImplemented import me.rhunk.snapenhance.ui.manager.sections.downloads.DownloadsSection import me.rhunk.snapenhance.ui.manager.sections.features.FeaturesSection @@ -64,6 +64,8 @@ open class Section { lateinit var context: RemoteSideContext lateinit var navController: NavController + val currentRoute get() = navController.currentBackStackEntry?.destination?.route + open fun init() {} open fun onResumed() {} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/InstallationSummary.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/InstallationSummary.kt index a5dcfd22..24e73e0c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/InstallationSummary.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/InstallationSummary.kt @@ -2,16 +2,33 @@ package me.rhunk.snapenhance.ui.manager.data data class SnapchatAppInfo( + val packageName: String, val version: String, - val versionCode: Long + val versionCode: Long, + val isLSPatched: Boolean, + val isSplitApk: Boolean, ) -data class ModMappingsInfo( - val generatedSnapchatVersion: Long, - val isOutdated: Boolean +data class ModInfo( + val loaderPackageName: String, + val buildPackageName: String, + val buildVersion: String, + val buildVersionCode: Long, + val buildIssuer: String, + val isDebugBuild: Boolean, + val mappingVersion: Long?, + val mappingsOutdated: Boolean?, +) + +data class PlatformInfo( + val device: String, + val buildFingerprint: String, + val androidVersion: String, + val systemAbi: String, ) data class InstallationSummary( + val platformInfo: PlatformInfo, val snapchatInfo: SnapchatAppInfo?, - val mappingsInfo: ModMappingsInfo? + val modInfo: ModInfo?, ) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/HomeSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/HomeSection.kt deleted file mode 100644 index 3fd84cff..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/HomeSection.kt +++ /dev/null @@ -1,147 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.sections - -import androidx.compose.foundation.ScrollState -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Language -import androidx.compose.material.icons.filled.Map -import androidx.compose.material.icons.filled.OpenInNew -import androidx.compose.material.icons.filled.Refresh -import androidx.compose.material3.Button -import androidx.compose.material3.Icon -import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import me.rhunk.snapenhance.ui.manager.Section -import me.rhunk.snapenhance.ui.manager.data.InstallationSummary -import me.rhunk.snapenhance.ui.setup.Requirements -import java.util.Locale - -class HomeSection : Section() { - companion object { - val cardMargin = 10.dp - } - private val installationSummary = mutableStateOf(null as InstallationSummary?) - private val userLocale = mutableStateOf(null as String?) - - @Composable - private fun SummaryCards(installationSummary: InstallationSummary) { - //installation summary - OutlinedCard( - modifier = Modifier - .padding(all = cardMargin) - .fillMaxWidth() - ) { - Column(modifier = Modifier.padding(all = 16.dp)) { - if (installationSummary.snapchatInfo != null) { - Text("Snapchat version: ${installationSummary.snapchatInfo.version}") - Text("Snapchat version code: ${installationSummary.snapchatInfo.versionCode}") - } else { - Text("Snapchat not installed/detected") - } - } - } - - OutlinedCard( - modifier = Modifier - .padding(all = cardMargin) - .fillMaxWidth() - ) { - Row( - modifier = Modifier.padding(all = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween - ) { - Icon( - Icons.Filled.Map, - contentDescription = "Mappings", - modifier = Modifier - .padding(end = 10.dp) - .align(Alignment.CenterVertically) - ) - - Text(text = if (installationSummary.mappingsInfo == null || installationSummary.mappingsInfo.isOutdated) { - "Mappings ${if (installationSummary.mappingsInfo == null) "not generated" else "outdated"}" - } else { - "Mappings version ${installationSummary.mappingsInfo.generatedSnapchatVersion}" - }, modifier = Modifier - .weight(1f) - .align(Alignment.CenterVertically) - ) - - //inline button - Button(onClick = { - context.checkForRequirements(Requirements.MAPPINGS) - }, modifier = Modifier.height(40.dp)) { - Icon(Icons.Filled.Refresh, contentDescription = "Refresh") - } - } - } - OutlinedCard( - modifier = Modifier - .padding(all = cardMargin) - .fillMaxWidth() - ) { - Row( - modifier = Modifier.padding(all = 16.dp), - ) { - Icon( - Icons.Filled.Language, - contentDescription = "Language", - modifier = Modifier - .padding(end = 10.dp) - .align(Alignment.CenterVertically) - ) - Text(text = userLocale.value ?: "Unknown", modifier = Modifier - .weight(1f) - .align(Alignment.CenterVertically) - ) - - //inline button - Button(onClick = { - context.checkForRequirements(Requirements.LANGUAGE) - }, modifier = Modifier.height(40.dp)) { - Icon(Icons.Filled.OpenInNew, contentDescription = null) - } - } - } - } - - override fun onResumed() { - if (!context.mappings.isMappingsLoaded()) { - context.mappings.init(context.androidContext) - } - installationSummary.value = context.getInstallationSummary() - userLocale.value = context.translation.loadedLocale.getDisplayName(Locale.getDefault()) - } - - override fun sectionTopBarName() = "SnapEnhance" - - @Composable - @Preview - override fun Content() { - Column( - modifier = Modifier - .fillMaxSize() - .verticalScroll(ScrollState(0)) - ) { - Text( - text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec euismod, nisl eget ultricies ultrices, nunc nisl aliquam nunc, quis aliquam nisl nunc eu nisl. Donec euismod, nisl eget ultricies ultrices, nunc nisl aliquam nunc, quis aliquam nisl nunc eu nisl.", - modifier = Modifier.padding(16.dp) - ) - - SummaryCards(installationSummary = installationSummary.value ?: return) - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/downloads/DownloadsSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/downloads/DownloadsSection.kt index 26f6982e..2cd20aad 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/downloads/DownloadsSection.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/downloads/DownloadsSection.kt @@ -51,8 +51,8 @@ import androidx.compose.ui.unit.sp import coil.compose.rememberAsyncImagePainter import kotlinx.coroutines.launch import me.rhunk.snapenhance.data.FileType -import me.rhunk.snapenhance.download.data.DownloadObject -import me.rhunk.snapenhance.download.data.MediaFilter +import me.rhunk.snapenhance.core.download.data.DownloadObject +import me.rhunk.snapenhance.core.download.data.MediaFilter import me.rhunk.snapenhance.ui.manager.Section import me.rhunk.snapenhance.ui.util.BitmojiImage import me.rhunk.snapenhance.ui.util.ImageRequestHelper diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/features/FeaturesSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/features/FeaturesSection.kt index b6ed768a..7ede6f90 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/features/FeaturesSection.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/features/FeaturesSection.kt @@ -439,7 +439,7 @@ class FeaturesSection : Section() { IconButton(onClick = { showSearchBar = showSearchBar.not() - if (!showSearchBar && navController.currentBackStackEntry?.destination?.route == SEARCH_FEATURE_ROUTE) { + if (!showSearchBar && currentRoute == SEARCH_FEATURE_ROUTE) { navController.navigate(MAIN_ROUTE) } }) { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSection.kt new file mode 100644 index 00000000..6da9610a --- /dev/null +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSection.kt @@ -0,0 +1,312 @@ +package me.rhunk.snapenhance.ui.manager.sections.home + +import android.net.Uri +import androidx.compose.foundation.Image +import androidx.compose.foundation.ScrollState +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.BugReport +import androidx.compose.material.icons.filled.Language +import androidx.compose.material.icons.filled.Map +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material.icons.filled.OpenInNew +import androidx.compose.material.icons.filled.ReceiptLong +import androidx.compose.material.icons.filled.Refresh +import androidx.compose.material3.Button +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.scale +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable +import androidx.navigation.navigation +import me.rhunk.snapenhance.R +import me.rhunk.snapenhance.ui.manager.Section +import me.rhunk.snapenhance.ui.manager.data.InstallationSummary +import me.rhunk.snapenhance.ui.setup.Requirements +import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper +import me.rhunk.snapenhance.ui.util.saveFile +import java.util.Locale + +class HomeSection : Section() { + companion object { + val cardMargin = 10.dp + const val HOME_ROOT = "home_root" + const val DEBUG_SECTION_ROUTE = "home_debug" + const val LOGS_SECTION_ROUTE = "home_logs" + } + + private val installationSummary = mutableStateOf(null as InstallationSummary?) + private val userLocale = mutableStateOf(null as String?) + private val homeSubSection by lazy { HomeSubSection(context) } + private lateinit var activityLauncherHelper: ActivityLauncherHelper + + override fun init() { + activityLauncherHelper = ActivityLauncherHelper(context.activity!!) + } + + @Composable + private fun SummaryCardRow(icon: ImageVector? = null, title: String, action: @Composable () -> Unit) { + Row( + modifier = Modifier.padding(all = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + icon?.let { + Icon( + imageVector = it, + contentDescription = null, + modifier = Modifier + .padding(end = 10.dp) + .align(Alignment.CenterVertically) + ) + } + Text(text = title, modifier = Modifier + .weight(1f) + .align(Alignment.CenterVertically) + ) + Column { + action() + } + } + } + + @Composable + private fun SummaryCards(installationSummary: InstallationSummary) { + OutlinedCard( + modifier = Modifier + .padding(all = cardMargin) + .fillMaxWidth() + ) { + SummaryCardRow( + icon = Icons.Filled.Map, + title = if (installationSummary.modInfo == null || installationSummary.modInfo.mappingsOutdated == true) { + "Mappings ${if (installationSummary.modInfo == null) "not generated" else "outdated"}" + } else { + "Mappings version ${installationSummary.modInfo.mappingVersion}" + } + ) { + Button(onClick = { + context.checkForRequirements(Requirements.MAPPINGS) + }, modifier = Modifier.height(40.dp)) { + Icon(Icons.Filled.Refresh, contentDescription = null) + } + } + + SummaryCardRow(icon = Icons.Filled.Language, title = userLocale.value ?: "Unknown") { + Button(onClick = { + context.checkForRequirements(Requirements.LANGUAGE) + }, modifier = Modifier.height(40.dp)) { + Icon(Icons.Filled.OpenInNew, contentDescription = null) + } + } + } + + val summaryInfo = remember { + mapOf( + "Build Issuer" to (installationSummary.modInfo?.buildIssuer ?: "Unknown"), + "Device" to installationSummary.platformInfo.device, + "Android version" to installationSummary.platformInfo.androidVersion, + "System ABI" to installationSummary.platformInfo.systemAbi, + "Build fingerprint" to installationSummary.platformInfo.buildFingerprint + ) + } + + Card( + modifier = Modifier + .padding(all = cardMargin) + .fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + contentColor = MaterialTheme.colorScheme.onSurfaceVariant + ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(all = 10.dp), + ) { + summaryInfo.forEach { (title, value) -> + Column( + modifier = Modifier + .fillMaxWidth() + .padding(all = 5.dp), + ) { + Text( + text = title, + fontSize = 12.sp, + fontWeight = FontWeight.Light, + ) + Text( + fontSize = 14.sp, + text = value, + lineHeight = 20.sp + ) + } + } + } + + } + } + + override fun onResumed() { + if (!context.mappings.isMappingsLoaded()) { + context.mappings.init(context.androidContext) + } + installationSummary.value = context.installationSummary + userLocale.value = context.translation.loadedLocale.getDisplayName(Locale.getDefault()) + } + + override fun sectionTopBarName(): String { + if (currentRoute == HOME_ROOT) { + return "" + } + return context.translation["manager.routes.$currentRoute"] + } + + @Composable + override fun FloatingActionButton() { + if (currentRoute == LOGS_SECTION_ROUTE) { + homeSubSection.LogsActionButtons() + } + } + + @Composable + override fun TopBarActions(rowScope: RowScope) { + rowScope.apply { + when (currentRoute) { + HOME_ROOT -> { + IconButton(onClick = { + navController.navigate(LOGS_SECTION_ROUTE) + }) { + Icon(Icons.Filled.ReceiptLong, contentDescription = null) + } + IconButton(onClick = { + navController.navigate(DEBUG_SECTION_ROUTE) + }) { + Icon(Icons.Filled.BugReport, contentDescription = null) + } + } + LOGS_SECTION_ROUTE -> { + var showDropDown by remember { mutableStateOf(false) } + + IconButton(onClick = { + showDropDown = true + }) { + Icon(Icons.Filled.MoreVert, contentDescription = null) + } + + DropdownMenu( + expanded = showDropDown, + onDismissRequest = { showDropDown = false }, + modifier = Modifier.align(Alignment.CenterVertically) + ) { + DropdownMenuItem(onClick = { + context.log.clearLogs() + navController.navigate(LOGS_SECTION_ROUTE) + showDropDown = false + }, text = { + Text(text = "Clear logs") + }) + + DropdownMenuItem(onClick = { + val logFile = context.log.getLogFile() + activityLauncherHelper.saveFile(logFile.name, "text/plain") { uri -> + context.androidContext.contentResolver.openOutputStream(Uri.parse(uri))?.use { + logFile.inputStream().copyTo(it) + context.longToast("Saved logs to $uri") + } + } + showDropDown = false + }, text = { + Text(text = "Export logs") + }) + } + } + } + } + } + + override fun build(navGraphBuilder: NavGraphBuilder) { + navGraphBuilder.navigation( + route = enumSection.route, + startDestination = HOME_ROOT + ) { + composable(HOME_ROOT) { + Content() + } + composable(LOGS_SECTION_ROUTE) { + homeSubSection.LogsSection() + } + composable(DEBUG_SECTION_ROUTE) { + homeSubSection.DebugSection() + } + } + } + + + @Composable + @Preview + override fun Content() { + Column( + modifier = Modifier + .verticalScroll(ScrollState(0)) + ) { + Column( + modifier = Modifier + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = painterResource(id = R.drawable.launcher_icon_monochrome), + contentDescription = null, + colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary), + contentScale = ContentScale.FillHeight, + modifier = Modifier + .height(120.dp) + .scale(1.75f) + ) + Text( + text = ("\u0065" + "\u0063" + "\u006e" + "\u0061" + "\u0068" + "\u006e" + "\u0045" + "\u0070" + "\u0061" + "\u006e" + "\u0053").reversed(), + fontSize = 30.sp, + modifier = Modifier.padding(16.dp), + ) + } + + + Text( + text = "An xposed module that enhances the Snapchat experience", + modifier = Modifier.padding(16.dp) + ) + + SummaryCards(installationSummary = installationSummary.value ?: return) + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSubSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSubSection.kt new file mode 100644 index 00000000..0e371e9f --- /dev/null +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSubSection.kt @@ -0,0 +1,214 @@ +package me.rhunk.snapenhance.ui.manager.sections.home + +import androidx.compose.foundation.ScrollState +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.KeyboardDoubleArrowDown +import androidx.compose.material.icons.filled.KeyboardDoubleArrowUp +import androidx.compose.material.icons.filled.OpenInNew +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.FilledIconButton +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +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 androidx.compose.ui.window.Dialog +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import me.rhunk.snapenhance.Constants +import me.rhunk.snapenhance.LogReader +import me.rhunk.snapenhance.RemoteSideContext +import me.rhunk.snapenhance.action.EnumAction +import me.rhunk.snapenhance.core.bridge.types.BridgeFileType +import me.rhunk.snapenhance.manager.impl.ActionManager +import me.rhunk.snapenhance.ui.util.AlertDialogs + +class HomeSubSection( + private val context: RemoteSideContext +) { + private val dialogs by lazy { AlertDialogs(context.translation) } + + private lateinit var logListState: LazyListState + + @Composable + private fun RowAction(title: String, requireConfirmation: Boolean = false, action: () -> Unit) { + var confirmationDialog by remember { + mutableStateOf(false) + } + + fun takeAction() { + if (requireConfirmation) { + confirmationDialog = true + } else { + action() + } + } + + if (requireConfirmation && confirmationDialog) { + Dialog(onDismissRequest = { confirmationDialog = false }) { + dialogs.ConfirmDialog(title = "Are you sure?", onConfirm = { + action() + confirmationDialog = false + }, onDismiss = { + confirmationDialog = false + }) + } + } + + Row( + modifier = Modifier + .fillMaxWidth() + .height(65.dp) + .clickable { + takeAction() + }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text(text = title, modifier = Modifier.padding(start = 26.dp)) + IconButton(onClick = { takeAction() }) { + Icon( + imageVector = Icons.Filled.OpenInNew, + contentDescription = null, + modifier = Modifier.size(24.dp) + ) + } + } + } + + @Composable + fun LogsSection() { + val coroutineScope = rememberCoroutineScope() + var lineCount by remember { mutableIntStateOf(0) } + var logReader by remember { mutableStateOf(null) } + logListState = remember { LazyListState(0) } + + Column( + modifier = Modifier + .fillMaxSize() + ) { + LazyColumn( + modifier = Modifier.background(MaterialTheme.colorScheme.surfaceVariant), + state = logListState + ) { + items(lineCount) { index -> + val line = logReader?.getLogLine(index) ?: return@items + Box(modifier = Modifier + .fillMaxWidth() + .background( + if (index % 2 == 0) MaterialTheme.colorScheme.surface else MaterialTheme.colorScheme.surfaceVariant + )) { + Text(text = line.message, modifier = Modifier.padding(9.dp), fontSize = 10.sp) + } + } + } + + if (logReader == null) { + CircularProgressIndicator(modifier = Modifier.align(Alignment.CenterHorizontally)) + } + + LaunchedEffect(Unit) { + coroutineScope.launch(Dispatchers.IO) { + runCatching { + logReader = context.log.newReader { + lineCount++ + } + lineCount = logReader!!.lineCount + }.onFailure { + context.longToast("Failed to read logs!") + } + } + } + } + } + + @Composable + fun LogsActionButtons() { + val coroutineScope = rememberCoroutineScope() + Column( + verticalArrangement = Arrangement.spacedBy(5.dp), + ) { + FilledIconButton(onClick = { + coroutineScope.launch { + logListState.scrollToItem(0) + } + }) { + Icon(Icons.Filled.KeyboardDoubleArrowUp, contentDescription = null) + } + + FilledIconButton(onClick = { + coroutineScope.launch { + logListState.scrollToItem(logListState.layoutInfo.totalItemsCount - 1) + } + }) { + Icon(Icons.Filled.KeyboardDoubleArrowDown, contentDescription = null) + } + } + } + + private fun launchActionIntent(action: EnumAction) { + val intent = context.androidContext.packageManager.getLaunchIntentForPackage(Constants.SNAPCHAT_PACKAGE_NAME) + intent?.putExtra(ActionManager.ACTION_PARAMETER, action.key) + context.androidContext.startActivity(intent) + } + + @Composable + private fun RowTitle(title: String) { + Text(text = title, modifier = Modifier.padding(16.dp), fontSize = 20.sp, fontWeight = FontWeight.Bold) + } + + @Composable + fun DebugSection() { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(ScrollState(0)) + ) { + RowTitle(title = "Actions") + EnumAction.values().forEach { enumAction -> + RowAction(title = context.translation["actions.${enumAction.key}"]) { + launchActionIntent(enumAction) + } + } + + RowTitle(title = "Clear Files") + BridgeFileType.values().forEach { fileType -> + RowAction(title = fileType.displayName, requireConfirmation = true) { + runCatching { + fileType.resolve(context.androidContext).delete() + context.longToast("Deleted ${fileType.displayName}!") + }.onFailure { + context.longToast("Failed to delete ${fileType.displayName}!") + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/AddFriendDialog.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/AddFriendDialog.kt index 4db58491..37367aaa 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/AddFriendDialog.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/AddFriendDialog.kt @@ -43,9 +43,8 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.bridge.BridgeClient +import me.rhunk.snapenhance.core.bridge.BridgeClient import me.rhunk.snapenhance.core.messaging.MessagingFriendInfo import me.rhunk.snapenhance.core.messaging.MessagingGroupInfo import me.rhunk.snapenhance.util.snap.SnapWidgetBroadcastReceiverHelper @@ -55,8 +54,8 @@ class AddFriendDialog( private val section: SocialSection, ) { @Composable - private fun ListCardEntry(name: String, currentState: () -> Boolean, onState: (Boolean) -> Unit = {}) { - var currentState by remember { mutableStateOf(currentState()) } + private fun ListCardEntry(name: String, getCurrentState: () -> Boolean, onState: (Boolean) -> Unit = {}) { + var currentState by remember { mutableStateOf(getCurrentState()) } Row( modifier = Modifier @@ -74,7 +73,7 @@ class AddFriendDialog( modifier = Modifier .weight(1f) .onGloballyPositioned { - currentState = currentState() + currentState = getCurrentState() } ) @@ -149,7 +148,7 @@ class AddFriendDialog( runCatching { context.androidContext.sendBroadcast(it) }.onFailure { - Logger.error("Failed to send broadcast", it) + context.log.error("Failed to send broadcast", it) hasFetchError = true } } @@ -234,7 +233,7 @@ class AddFriendDialog( val group = filteredGroups[it] ListCardEntry( name = group.name, - currentState = { context.modDatabase.getGroupInfo(group.conversationId) != null } + getCurrentState = { context.modDatabase.getGroupInfo(group.conversationId) != null } ) { state -> if (state) { context.bridgeService.triggerGroupSync(group.conversationId) @@ -261,7 +260,7 @@ class AddFriendDialog( ListCardEntry( name = friend.displayName?.takeIf { name -> name.isNotBlank() } ?: friend.mutableUsername, - currentState = { context.modDatabase.getFriendInfo(friend.userId) != null } + getCurrentState = { context.modDatabase.getFriendInfo(friend.userId) != null } ) { state -> if (state) { context.bridgeService.triggerFriendSync(friend.userId) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/SocialSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/SocialSection.kt index 0ed9ec77..77ab4d87 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/SocialSection.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/SocialSection.kt @@ -79,7 +79,7 @@ class SocialSection : Section() { groupList = context.modDatabase.getGroups() } - override fun canGoBack() = navController.currentBackStackEntry?.destination?.route != MAIN_ROUTE + override fun canGoBack() = currentRoute != MAIN_ROUTE override fun build(navGraphBuilder: NavGraphBuilder) { navGraphBuilder.navigation(route = enumSection.route, startDestination = MAIN_ROUTE) { @@ -117,7 +117,7 @@ class SocialSection : Section() { } } - if (navController.currentBackStackEntry?.destination?.route != MAIN_ROUTE) { + if (currentRoute != MAIN_ROUTE) { IconButton( onClick = { deleteConfirmDialog = true }, ) { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/MappingsScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/MappingsScreen.kt index ad37dfe2..7d215f19 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/MappingsScreen.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/MappingsScreen.kt @@ -44,7 +44,7 @@ class MappingsScreen : SetupScreen() { fun tryToGenerateMappings() { //check for snapchat installation - val installationSummary = context.getInstallationSummary() + val installationSummary = context.installationSummary if (installationSummary.snapchatInfo == null) { throw Exception(context.translation["setup.mappings.generate_failure_no_snapchat"]) } @@ -69,7 +69,7 @@ class MappingsScreen : SetupScreen() { }.onFailure { isGenerating = false infoText = context.translation["setup.mappings.generate_failure"] + "\n\n" + it.message - Logger.error("Failed to generate mappings", it) + context.log.error("Failed to generate mappings", it) } } }) { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PickLanguageScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PickLanguageScreen.kt index 3f0f3bb6..8756d2a8 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PickLanguageScreen.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PickLanguageScreen.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog -import me.rhunk.snapenhance.bridge.wrapper.LocaleWrapper +import me.rhunk.snapenhance.core.bridge.wrapper.LocaleWrapper import me.rhunk.snapenhance.ui.setup.screens.SetupScreen import me.rhunk.snapenhance.ui.util.ObservableMutableState import java.util.Locale diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SaveFolderScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SaveFolderScreen.kt index 3017c003..47e4bb54 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SaveFolderScreen.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SaveFolderScreen.kt @@ -7,7 +7,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.ui.setup.screens.SetupScreen import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper import me.rhunk.snapenhance.ui.util.ObservableMutableState @@ -23,7 +22,6 @@ class SaveFolderScreen : SetupScreen() { saveFolder = ObservableMutableState( defaultValue = "", onChange = { _, newValue -> - Logger.debug(newValue) if (newValue.isNotBlank()) { context.config.root.downloader.saveFolder.set(newValue) context.config.writeConfig() diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ActivityLauncherHelper.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ActivityLauncherHelper.kt index d1fe3075..009e3340 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ActivityLauncherHelper.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ActivityLauncherHelper.kt @@ -16,7 +16,7 @@ class ActivityLauncherHelper( runCatching { callback?.let { it(result.data!!) } }.onFailure { - Logger.error("Failed to process activity result", it) + Logger.directError("Failed to process activity result", it) } } callback = null diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt index fd11427c..e30a3908 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt @@ -33,7 +33,7 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import me.rhunk.snapenhance.bridge.wrapper.LocaleWrapper +import me.rhunk.snapenhance.core.bridge.wrapper.LocaleWrapper import me.rhunk.snapenhance.core.config.DataProcessors import me.rhunk.snapenhance.core.config.PropertyPair diff --git a/core/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl b/core/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl index 29499ddd..c20ac698 100644 --- a/core/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl +++ b/core/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl @@ -5,53 +5,47 @@ import me.rhunk.snapenhance.bridge.DownloadCallback; import me.rhunk.snapenhance.bridge.SyncCallback; interface BridgeInterface { + /** + * broadcast a log message + */ + void broadcastLog(String tag, String level, String message); + /** * Execute a file operation + * @param fileType the corresponding file type (see BridgeFileType) */ byte[] fileOperation(int action, int fileType, in @nullable byte[] content); /** * Get the content of a logged message from the database - * - * @param conversationId the ID of the conversation - * @return the content of the message + * @return message ids that are logged */ long[] getLoggedMessageIds(String conversationId, int limit); /** * Get the content of a logged message from the database - * - * @param id the ID of the message logger message - * @return the content of the message */ @nullable byte[] getMessageLoggerMessage(String conversationId, long id); /** * Add a message to the message logger database - * - * @param id the ID of the message logger message - * @param message the content of the message */ void addMessageLoggerMessage(String conversationId, long id, in byte[] message); /** * Delete a message from the message logger database - * - * @param id the ID of the message logger message */ void deleteMessageLoggerMessage(String conversationId, long id); /** - * Clear the message logger database - */ - void clearMessageLogger(); - + * Get the application APK path (assets for the conversation exporter) + */ String getApplicationApkPath(); /** * Fetch the locales * - * @return the locale result + * @return the map of locales (key: locale short name, value: locale data as json) */ Map fetchLocales(String userLocale); @@ -62,11 +56,14 @@ interface BridgeInterface { /** * Get rules for a given user or conversation + * @return list of rules (MessagingRuleType) */ List getRules(String uuid); /** * Update rule for a giver user or conversation + * + * @param type rule type (MessagingRuleType) */ void setRule(String uuid, String type, boolean state); @@ -77,8 +74,8 @@ interface BridgeInterface { /** * Pass all groups and friends to be able to add them to the database - * @param groups serialized groups - * @param friends serialized friends + * @param groups list of groups (MessagingGroupInfo as json string) + * @param friends list of friends (MessagingFriendInfo as json string) */ oneway void passGroupsAndFriends(in List groups, in List friends); } \ No newline at end of file diff --git a/core/src/main/assets/lang/en_US.json b/core/src/main/assets/lang/en_US.json index f0f74d0d..a1062f51 100644 --- a/core/src/main/assets/lang/en_US.json +++ b/core/src/main/assets/lang/en_US.json @@ -20,6 +20,8 @@ "downloads": "Downloads", "features": "Features", "home": "Home", + "home_debug": "Debug", + "home_logs": "Logs", "social": "Social", "plugins": "Plugins" }, @@ -64,8 +66,8 @@ } }, - "action": { - "clean_cache": "Clean Cache", + "actions": { + "clean_snapchat_cache": "Clean Snapchat Cache", "clear_message_logger": "Clear Message Logger", "refresh_mappings": "Refresh Mappings", "open_map": "Choose location on map", diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/Constants.kt b/core/src/main/kotlin/me/rhunk/snapenhance/Constants.kt index 577e0d8c..4c9d9e14 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/Constants.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/Constants.kt @@ -1,14 +1,12 @@ package me.rhunk.snapenhance object Constants { - const val TAG = "SnapEnhance" const val SNAPCHAT_PACKAGE_NAME = "com.snapchat.android" const val VIEW_INJECTED_CODE = 0x7FFFFF02 val ARROYO_MEDIA_CONTAINER_PROTO_PATH = intArrayOf(4, 4) val ARROYO_STRING_CHAT_MESSAGE_PROTO = ARROYO_MEDIA_CONTAINER_PROTO_PATH + intArrayOf(2, 1) - val ARROYO_URL_KEY_PROTO_PATH = intArrayOf(4, 5, 1, 3) const val ENCRYPTION_PROTO_INDEX = 19 const val ENCRYPTION_PROTO_INDEX_V2 = 4 diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/Logger.kt b/core/src/main/kotlin/me/rhunk/snapenhance/Logger.kt index f4756fff..f78dd213 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/Logger.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/Logger.kt @@ -2,47 +2,81 @@ package me.rhunk.snapenhance import android.util.Log import de.robv.android.xposed.XposedBridge -import me.rhunk.snapenhance.core.BuildConfig +import me.rhunk.snapenhance.core.bridge.BridgeClient -object Logger { - private const val TAG = "SnapEnhance" +enum class LogLevel( + val letter: String, + val shortName: String, + val priority: Int = Log.INFO +) { + VERBOSE("V", "verbose", Log.VERBOSE), + DEBUG("D", "debug", Log.DEBUG), + INFO("I", "info", Log.INFO), + WARN("W", "warn", Log.WARN), + ERROR("E", "error", Log.ERROR), + ASSERT("A", "assert", Log.ASSERT); - fun log(message: Any?) { - Log.i(TAG, message.toString()) + companion object { + fun fromLetter(letter: String): LogLevel? { + return values().find { it.letter == letter } + } + + fun fromShortName(shortName: String): LogLevel? { + return values().find { it.shortName == shortName } + } + } +} + + +class Logger( + private val bridgeClient: BridgeClient +) { + companion object { + private const val TAG = "SnapEnhanceCore" + + fun directDebug(message: Any?, tag: String = TAG) { + Log.println(Log.DEBUG, tag, message.toString()) + } + + fun directError(message: Any?, throwable: Throwable, tag: String = TAG) { + Log.println(Log.ERROR, tag, message.toString()) + Log.println(Log.ERROR, tag, throwable.toString()) + } + + fun xposedLog(message: Any?, tag: String = TAG) { + Log.println(Log.INFO, tag, message.toString()) + XposedBridge.log("$tag: $message") + } + + fun xposedLog(message: Any?, throwable: Throwable, tag: String = TAG) { + Log.println(Log.INFO, tag, message.toString()) + XposedBridge.log("$tag: $message") + XposedBridge.log(throwable) + } } - fun debug(message: Any?) { - if (!BuildConfig.DEBUG) return - Log.d(TAG, message.toString()) + private fun internalLog(tag: String, logLevel: LogLevel, message: Any?) { + runCatching { + bridgeClient.broadcastLog(tag, logLevel.shortName, message.toString()) + }.onFailure { + Log.println(logLevel.priority, tag, message.toString()) + } } - fun debug(tag: String, message: Any?) { - if (!BuildConfig.DEBUG) return - Log.d(tag, message.toString()) + fun debug(message: Any?, tag: String = TAG) = internalLog(tag, LogLevel.DEBUG, message) + + fun error(message: Any?, tag: String = TAG) = internalLog(tag, LogLevel.ERROR, message) + + fun error(message: Any?, throwable: Throwable, tag: String = TAG) { + internalLog(tag, LogLevel.ERROR, message) + internalLog(tag, LogLevel.ERROR, throwable) } - fun error(throwable: Throwable) { - Log.e(TAG, "", throwable) - } + fun info(message: Any?, tag: String = TAG) = internalLog(tag, LogLevel.INFO, message) - fun error(message: Any?) { - Log.e(TAG, message.toString()) - } + fun verbose(message: Any?, tag: String = TAG) = internalLog(tag, LogLevel.VERBOSE, message) - fun error(message: Any?, throwable: Throwable) { - Log.e(TAG, message.toString(), throwable) - } + fun warn(message: Any?, tag: String = TAG) = internalLog(tag, LogLevel.WARN, message) - fun xposedLog(message: Any?) { - XposedBridge.log(message.toString()) - } - - fun xposedLog(message: Any?, throwable: Throwable?) { - XposedBridge.log(message.toString()) - XposedBridge.log(throwable) - } - - fun xposedLog(throwable: Throwable) { - XposedBridge.log(throwable) - } + fun assert(message: Any?, tag: String = TAG) = internalLog(tag, LogLevel.ASSERT, message) } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt index 468cd770..6ede07e6 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt @@ -11,13 +11,13 @@ import android.widget.Toast import com.google.gson.Gson import com.google.gson.GsonBuilder import kotlinx.coroutines.asCoroutineDispatcher -import me.rhunk.snapenhance.bridge.BridgeClient -import me.rhunk.snapenhance.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.bridge.wrapper.MappingsWrapper +import me.rhunk.snapenhance.core.bridge.BridgeClient +import me.rhunk.snapenhance.core.bridge.wrapper.LocaleWrapper +import me.rhunk.snapenhance.core.bridge.wrapper.MappingsWrapper import me.rhunk.snapenhance.core.config.ModConfig +import me.rhunk.snapenhance.core.database.DatabaseAccess import me.rhunk.snapenhance.core.eventbus.EventBus import me.rhunk.snapenhance.data.MessageSender -import me.rhunk.snapenhance.database.DatabaseAccess import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.manager.impl.ActionManager import me.rhunk.snapenhance.manager.impl.FeatureManager @@ -44,6 +44,7 @@ class ModContext { private val modConfig = ModConfig() val config by modConfig + val log by lazy { Logger(this.bridgeClient) } val event = EventBus(this) val eventDispatcher = EventDispatcher(this) val native = NativeLib() @@ -81,13 +82,13 @@ class ModContext { } } - fun shortToast(message: Any) { + fun shortToast(message: Any?) { runOnUiThread { Toast.makeText(androidContext, message.toString(), Toast.LENGTH_SHORT).show() } } - fun longToast(message: Any) { + fun longToast(message: Any?) { runOnUiThread { Toast.makeText(androidContext, message.toString(), Toast.LENGTH_LONG).show() } @@ -108,7 +109,7 @@ class ModContext { } fun crash(message: String, throwable: Throwable? = null) { - Logger.xposedLog(message, throwable) + Logger.xposedLog(message, throwable ?: Exception()) longToast(message) delayForceCloseApp(100) } @@ -123,6 +124,7 @@ class ModContext { } fun reloadConfig() { + log.verbose("reloading config") modConfig.loadFromBridge(bridgeClient) native.loadNativeConfig( NativeConfig( diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt index 3cd1221e..f960cc5b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt @@ -6,9 +6,9 @@ import android.content.Context import android.content.pm.PackageManager import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.bridge.BridgeClient import me.rhunk.snapenhance.bridge.SyncCallback import me.rhunk.snapenhance.core.BuildConfig +import me.rhunk.snapenhance.core.bridge.BridgeClient import me.rhunk.snapenhance.core.eventbus.events.impl.SnapWidgetBroadcastReceiveEvent import me.rhunk.snapenhance.core.eventbus.events.impl.UnaryCallEvent import me.rhunk.snapenhance.core.messaging.MessagingFriendInfo @@ -88,7 +88,7 @@ class SnapEnhance { return@hook } - Logger.debug("Reloading config") + appContext.actionManager.onNewIntent(activity.intent) appContext.reloadConfig() syncRemote() } @@ -114,7 +114,7 @@ class SnapEnhance { syncRemote() } }.also { time -> - Logger.debug("init took $time") + appContext.log.verbose("init took $time") } } @@ -126,7 +126,7 @@ class SnapEnhance { actionManager.init() } }.also { time -> - Logger.debug("onActivityCreate took $time") + appContext.log.verbose("onActivityCreate took $time") } } @@ -149,7 +149,6 @@ class SnapEnhance { val database = appContext.database appContext.executeAsync { - Logger.debug("request remote sync") appContext.bridgeClient.sync(object : SyncCallback.Stub() { override fun syncFriend(uuid: String): String? { return database.getFriendInfo(uuid)?.toJson() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/AbstractAction.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/AbstractAction.kt index 6026691c..c81908ba 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/AbstractAction.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/action/AbstractAction.kt @@ -3,16 +3,9 @@ package me.rhunk.snapenhance.action import me.rhunk.snapenhance.ModContext import java.io.File -abstract class AbstractAction( - val nameKey: String -) { +abstract class AbstractAction{ lateinit var context: ModContext - /** - * called on the main thread when the mod initialize - */ - open fun init() {} - /** * called when the action is triggered */ diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/EnumAction.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/EnumAction.kt new file mode 100644 index 00000000..376786da --- /dev/null +++ b/core/src/main/kotlin/me/rhunk/snapenhance/action/EnumAction.kt @@ -0,0 +1,17 @@ +package me.rhunk.snapenhance.action + +import me.rhunk.snapenhance.action.impl.CleanCache +import me.rhunk.snapenhance.action.impl.ExportChatMessages +import me.rhunk.snapenhance.action.impl.OpenMap +import kotlin.reflect.KClass + +enum class EnumAction( + val key: String, + val clazz: KClass, + val exitOnFinish: Boolean = false, + val isCritical: Boolean = false, +) { + CLEAN_CACHE("clean_snapchat_cache", CleanCache::class, exitOnFinish = true), + EXPORT_CHAT_MESSAGES("export_chat_messages", ExportChatMessages::class), + OPEN_MAP("open_map", OpenMap::class); +} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CheckForUpdates.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CheckForUpdates.kt deleted file mode 100644 index 3a8e2094..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CheckForUpdates.kt +++ /dev/null @@ -1,19 +0,0 @@ -package me.rhunk.snapenhance.action.impl - -import me.rhunk.snapenhance.action.AbstractAction -import me.rhunk.snapenhance.features.impl.AutoUpdater - -class CheckForUpdates : AbstractAction("action.check_for_updates") { - override fun run() { - context.executeAsync { - runCatching { - val latestVersion = context.feature(AutoUpdater::class).checkForUpdates() - if (latestVersion == null) { - context.longToast(context.translation["auto_updater.no_update_available"]) - } - }.onFailure { - context.longToast(it.message ?: "Failed to check for updates") - } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CleanCache.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CleanCache.kt index dfcab689..f8b0b449 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CleanCache.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CleanCache.kt @@ -3,7 +3,7 @@ package me.rhunk.snapenhance.action.impl import me.rhunk.snapenhance.action.AbstractAction import java.io.File -class CleanCache : AbstractAction("action.clean_cache") { +class CleanCache : AbstractAction() { companion object { private val FILES = arrayOf( "files/mbgl-offline.db", @@ -22,7 +22,7 @@ class CleanCache : AbstractAction("action.clean_cache") { } override fun run() { - FILES.forEach {fileName -> + FILES.forEach { fileName -> val fileCache = File(context.androidContext.dataDir, fileName) if (fileName.endsWith("*")) { val parent = fileCache.parentFile ?: throw IllegalStateException("Parent file is null") diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/ClearMessageLogger.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/ClearMessageLogger.kt deleted file mode 100644 index b31853cf..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/ClearMessageLogger.kt +++ /dev/null @@ -1,10 +0,0 @@ -package me.rhunk.snapenhance.action.impl - -import me.rhunk.snapenhance.action.AbstractAction - -class ClearMessageLogger : AbstractAction("action.clear_message_logger") { - override fun run() { - context.bridgeClient.clearMessageLogger() - context.shortToast("Message logger cleared") - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/ExportChatMessages.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/ExportChatMessages.kt index 990f63f0..a80c6623 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/ExportChatMessages.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/ExportChatMessages.kt @@ -14,10 +14,10 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.action.AbstractAction +import me.rhunk.snapenhance.core.database.objects.FriendFeedEntry import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.wrapper.impl.Message import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.database.objects.FriendFeedEntry import me.rhunk.snapenhance.features.impl.Messaging import me.rhunk.snapenhance.ui.ViewAppearanceHelper import me.rhunk.snapenhance.util.CallbackBuilder @@ -26,7 +26,7 @@ import me.rhunk.snapenhance.util.export.MessageExporter import java.io.File @OptIn(DelicateCoroutinesApi::class) -class ExportChatMessages : AbstractAction("action.export_chat_messages") { +class ExportChatMessages : AbstractAction() { private val callbackClass by lazy { context.mappings.getMappedClass("callbacks", "Callback") } private val fetchConversationWithMessagesCallbackClass by lazy { context.mappings.getMappedClass("callbacks", "FetchConversationWithMessagesCallback") } @@ -55,7 +55,7 @@ class ExportChatMessages : AbstractAction("action.export_chat_messages") { context.runOnUiThread { if (dialogLogs.size > 15) dialogLogs.removeAt(0) dialogLogs.add(message) - Logger.debug("dialog: $message") + context.log.debug("dialog: $message") currentActionDialog!!.setMessage(dialogLogs.joinToString("\n")) } } @@ -198,7 +198,6 @@ class ExportChatMessages : AbstractAction("action.export_chat_messages") { } while (true) { - Logger.debug("[$conversationName] fetching $lastMessageId") val messages = fetchMessagesPaginated(conversationId, lastMessageId) if (messages.isEmpty()) break foundMessages.addAll(messages) @@ -224,7 +223,7 @@ class ExportChatMessages : AbstractAction("action.export_chat_messages") { it.readMessages(foundMessages) }.onFailure { logDialog(context.translation.format("chat_export.export_failed","conversation" to it.message.toString())) - Logger.error(it) + context.log.error("Failed to read messages", it) return } }.exportTo(exportType!!) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt index 4fc77d4d..bb94c6e3 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt @@ -5,7 +5,7 @@ import android.os.Bundle import me.rhunk.snapenhance.action.AbstractAction import me.rhunk.snapenhance.core.BuildConfig -class OpenMap: AbstractAction("action.open_map") { +class OpenMap: AbstractAction() { override fun run() { context.runOnUiThread { val mapActivityIntent = Intent() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/RefreshMappings.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/RefreshMappings.kt deleted file mode 100644 index b2be23f5..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/RefreshMappings.kt +++ /dev/null @@ -1,11 +0,0 @@ -package me.rhunk.snapenhance.action.impl - -import me.rhunk.snapenhance.action.AbstractAction -import me.rhunk.snapenhance.bridge.types.BridgeFileType - -class RefreshMappings : AbstractAction("action.refresh_mappings") { - override fun run() { - context.bridgeClient.deleteFile(BridgeFileType.MAPPINGS) - context.softRestartApp() - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeClient.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt similarity index 89% rename from core/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeClient.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt index ded51434..a1cf662b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeClient.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge +package me.rhunk.snapenhance.core.bridge import android.content.ComponentName @@ -10,11 +10,13 @@ import android.os.Handler import android.os.HandlerThread import android.os.IBinder import de.robv.android.xposed.XposedHelpers -import me.rhunk.snapenhance.Logger.xposedLog import me.rhunk.snapenhance.ModContext -import me.rhunk.snapenhance.bridge.types.BridgeFileType -import me.rhunk.snapenhance.bridge.types.FileActionType +import me.rhunk.snapenhance.bridge.BridgeInterface +import me.rhunk.snapenhance.bridge.DownloadCallback +import me.rhunk.snapenhance.bridge.SyncCallback import me.rhunk.snapenhance.core.BuildConfig +import me.rhunk.snapenhance.core.bridge.types.BridgeFileType +import me.rhunk.snapenhance.core.bridge.types.FileActionType import me.rhunk.snapenhance.core.messaging.MessagingRuleType import me.rhunk.snapenhance.data.LocalePair import java.util.concurrent.CompletableFuture @@ -29,7 +31,7 @@ class BridgeClient( private lateinit var service: BridgeInterface companion object { - const val BRIDGE_SYNC_ACTION = "me.rhunk.snapenhance.bridge.SYNC" + const val BRIDGE_SYNC_ACTION = "me.rhunk.snapenhance.core.bridge.SYNC" } fun start(callback: (Boolean) -> Unit) { @@ -76,7 +78,7 @@ class BridgeClient( } override fun onNullBinding(name: ComponentName) { - xposedLog("failed to connect to bridge service") + context.log.error("BridgeClient", "failed to connect to bridge service") exitProcess(1) } @@ -84,6 +86,8 @@ class BridgeClient( exitProcess(0) } + fun broadcastLog(tag: String, level: String, message: String) = service.broadcastLog(tag, level, message) + fun createAndReadFile( fileType: BridgeFileType, defaultContent: ByteArray @@ -108,8 +112,6 @@ class BridgeClient( fun deleteMessageLoggerMessage(conversationId: String, id: Long) = service.deleteMessageLoggerMessage(conversationId, id) - fun clearMessageLogger() = service.clearMessageLogger() - fun fetchLocales(userLocale: String) = service.fetchLocales(userLocale).map { LocalePair(it.key, it.value) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/FileLoaderWrapper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/FileLoaderWrapper.kt similarity index 91% rename from core/src/main/kotlin/me/rhunk/snapenhance/bridge/FileLoaderWrapper.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/FileLoaderWrapper.kt index a98e597a..acf0c7a7 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/FileLoaderWrapper.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/FileLoaderWrapper.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.bridge +package me.rhunk.snapenhance.core.bridge import android.content.Context -import me.rhunk.snapenhance.bridge.types.BridgeFileType +import me.rhunk.snapenhance.core.bridge.types.BridgeFileType open class FileLoaderWrapper( private val fileType: BridgeFileType, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/types/BridgeFileType.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/types/BridgeFileType.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/bridge/types/BridgeFileType.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/types/BridgeFileType.kt index eca4b354..fc120de5 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/types/BridgeFileType.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/types/BridgeFileType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.types +package me.rhunk.snapenhance.core.bridge.types import android.content.Context import java.io.File diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/types/FileActionType.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/types/FileActionType.kt similarity index 62% rename from core/src/main/kotlin/me/rhunk/snapenhance/bridge/types/FileActionType.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/types/FileActionType.kt index 6754198d..49f00fe3 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/types/FileActionType.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/types/FileActionType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.types +package me.rhunk.snapenhance.core.bridge.types enum class FileActionType { CREATE_AND_READ, READ, WRITE, DELETE, EXISTS diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/LocaleWrapper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/LocaleWrapper.kt similarity index 95% rename from core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/LocaleWrapper.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/LocaleWrapper.kt index 186d87c5..110d0f94 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/LocaleWrapper.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/LocaleWrapper.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.bridge.wrapper +package me.rhunk.snapenhance.core.bridge.wrapper import android.content.Context import com.google.gson.JsonObject import com.google.gson.JsonParser import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.bridge.BridgeClient +import me.rhunk.snapenhance.core.bridge.BridgeClient import me.rhunk.snapenhance.data.LocalePair import java.util.Locale @@ -80,7 +80,7 @@ class LocaleWrapper { loadFromContext(context) } - operator fun get(key: String) = translationMap[key] ?: key.also { Logger.debug("Missing translation for $key") } + operator fun get(key: String) = translationMap[key] ?: key.also { Logger.directDebug("Missing translation for $key") } fun format(key: String, vararg args: Pair): String { return args.fold(get(key)) { acc, pair -> diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/MappingsWrapper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/MappingsWrapper.kt similarity index 93% rename from core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/MappingsWrapper.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/MappingsWrapper.kt index 938dbb79..1e7fc508 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/MappingsWrapper.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/MappingsWrapper.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.wrapper +package me.rhunk.snapenhance.core.bridge.wrapper import android.content.Context import com.google.gson.GsonBuilder @@ -6,8 +6,8 @@ import com.google.gson.JsonElement import com.google.gson.JsonParser import me.rhunk.snapenhance.Constants import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.bridge.FileLoaderWrapper -import me.rhunk.snapenhance.bridge.types.BridgeFileType +import me.rhunk.snapenhance.core.bridge.FileLoaderWrapper +import me.rhunk.snapenhance.core.bridge.types.BridgeFileType import me.rhunk.snapmapper.Mapper import me.rhunk.snapmapper.impl.BCryptClassMapper import me.rhunk.snapmapper.impl.CallbackMapper @@ -58,11 +58,8 @@ class MappingsWrapper : FileLoaderWrapper(BridgeFileType.MAPPINGS, "{}".toByteAr runCatching { loadCached() }.onFailure { - Logger.error("Failed to load cached mappings", it) delete() } - } else { - Logger.debug("Mappings file does not exist") } } @@ -122,7 +119,7 @@ class MappingsWrapper : FileLoaderWrapper(BridgeFileType.MAPPINGS, "{}".toByteAr } write(result.toString().toByteArray()) }.also { - Logger.debug("Generated mappings in $it ms") + Logger.directDebug("Generated mappings in $it ms") } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/MessageLoggerWrapper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/MessageLoggerWrapper.kt similarity index 98% rename from core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/MessageLoggerWrapper.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/MessageLoggerWrapper.kt index f25f4dc3..75d6395c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/MessageLoggerWrapper.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/MessageLoggerWrapper.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.wrapper +package me.rhunk.snapenhance.core.bridge.wrapper import android.content.ContentValues import android.database.sqlite.SQLiteDatabase diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigObjects.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigObjects.kt index a7a876ed..ef0c7219 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigObjects.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigObjects.kt @@ -1,6 +1,6 @@ package me.rhunk.snapenhance.core.config -import me.rhunk.snapenhance.bridge.wrapper.LocaleWrapper +import me.rhunk.snapenhance.core.bridge.wrapper.LocaleWrapper import kotlin.reflect.KProperty diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ModConfig.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ModConfig.kt index c4d3c32a..dfb23acc 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ModConfig.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ModConfig.kt @@ -4,11 +4,10 @@ import android.content.Context import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.JsonObject -import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.bridge.BridgeClient -import me.rhunk.snapenhance.bridge.FileLoaderWrapper -import me.rhunk.snapenhance.bridge.types.BridgeFileType -import me.rhunk.snapenhance.bridge.wrapper.LocaleWrapper +import me.rhunk.snapenhance.core.bridge.BridgeClient +import me.rhunk.snapenhance.core.bridge.FileLoaderWrapper +import me.rhunk.snapenhance.core.bridge.types.BridgeFileType +import me.rhunk.snapenhance.core.bridge.wrapper.LocaleWrapper import me.rhunk.snapenhance.core.config.impl.RootConfig import kotlin.properties.Delegates @@ -33,7 +32,6 @@ class ModConfig { runCatching { loadConfig() }.onFailure { - Logger.error("Failed to load config", it) writeConfig() } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Experimental.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Experimental.kt index 3debf9fd..1e48f4d4 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Experimental.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Experimental.kt @@ -1,6 +1,7 @@ package me.rhunk.snapenhance.core.config.impl import me.rhunk.snapenhance.core.config.ConfigContainer +import me.rhunk.snapenhance.core.config.FeatureNotice class Experimental : ConfigContainer() { val nativeHooks = container("native_hooks", NativeHooks()) { icon = "Memory" } @@ -9,6 +10,6 @@ class Experimental : ConfigContainer() { val appLockOnResume = boolean("app_lock_on_resume") val infiniteStoryBoost = boolean("infinite_story_boost") val meoPasscodeBypass = boolean("meo_passcode_bypass") - val unlimitedMultiSnap = boolean("unlimited_multi_snap") + val unlimitedMultiSnap = boolean("unlimited_multi_snap") { addNotices(FeatureNotice.MAY_BAN)} val noFriendScoreDelay = boolean("no_friend_score_delay") } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/database/DatabaseAccess.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/database/DatabaseAccess.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt index f81a7272..78c6d6b7 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/database/DatabaseAccess.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt @@ -1,10 +1,14 @@ -package me.rhunk.snapenhance.database +package me.rhunk.snapenhance.core.database import android.annotation.SuppressLint import android.database.sqlite.SQLiteDatabase import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.ModContext -import me.rhunk.snapenhance.database.objects.* +import me.rhunk.snapenhance.core.database.objects.ConversationMessage +import me.rhunk.snapenhance.core.database.objects.FriendFeedEntry +import me.rhunk.snapenhance.core.database.objects.FriendInfo +import me.rhunk.snapenhance.core.database.objects.StoryEntry +import me.rhunk.snapenhance.core.database.objects.UserConversationLink import me.rhunk.snapenhance.manager.Manager import java.io.File @@ -68,7 +72,7 @@ class DatabaseAccess(private val context: ModContext) : Manager { try { obj.write(cursor) } catch (e: Throwable) { - Logger.xposedLog(e) + context.log.error("Failed to read database object", e) } cursor.close() return obj diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/database/DatabaseObject.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseObject.kt similarity index 68% rename from core/src/main/kotlin/me/rhunk/snapenhance/database/DatabaseObject.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseObject.kt index d54f2553..def56fd5 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/database/DatabaseObject.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseObject.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.database +package me.rhunk.snapenhance.core.database import android.database.Cursor diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/ConversationMessage.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/ConversationMessage.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/database/objects/ConversationMessage.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/ConversationMessage.kt index d434449f..6e6c41ff 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/ConversationMessage.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/ConversationMessage.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.database.objects +package me.rhunk.snapenhance.core.database.objects import android.annotation.SuppressLint import android.database.Cursor import me.rhunk.snapenhance.Constants +import me.rhunk.snapenhance.core.database.DatabaseObject import me.rhunk.snapenhance.data.ContentType -import me.rhunk.snapenhance.database.DatabaseObject import me.rhunk.snapenhance.util.ktx.getBlobOrNull import me.rhunk.snapenhance.util.ktx.getInteger import me.rhunk.snapenhance.util.ktx.getLong diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/FriendFeedEntry.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/FriendFeedEntry.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/database/objects/FriendFeedEntry.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/FriendFeedEntry.kt index 4629d6f6..48d43835 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/FriendFeedEntry.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/FriendFeedEntry.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.database.objects +package me.rhunk.snapenhance.core.database.objects import android.annotation.SuppressLint import android.database.Cursor -import me.rhunk.snapenhance.database.DatabaseObject +import me.rhunk.snapenhance.core.database.DatabaseObject import me.rhunk.snapenhance.util.ktx.getIntOrNull import me.rhunk.snapenhance.util.ktx.getInteger import me.rhunk.snapenhance.util.ktx.getLong diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/FriendInfo.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/FriendInfo.kt similarity index 96% rename from core/src/main/kotlin/me/rhunk/snapenhance/database/objects/FriendInfo.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/FriendInfo.kt index 6dd435e5..18bd832c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/FriendInfo.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/FriendInfo.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.database.objects +package me.rhunk.snapenhance.core.database.objects import android.annotation.SuppressLint import android.database.Cursor -import me.rhunk.snapenhance.database.DatabaseObject +import me.rhunk.snapenhance.core.database.DatabaseObject import me.rhunk.snapenhance.util.SerializableDataObject import me.rhunk.snapenhance.util.ktx.getInteger import me.rhunk.snapenhance.util.ktx.getLong diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/StoryEntry.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/StoryEntry.kt similarity index 86% rename from core/src/main/kotlin/me/rhunk/snapenhance/database/objects/StoryEntry.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/StoryEntry.kt index 95bdd467..016a2ec3 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/StoryEntry.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/StoryEntry.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.database.objects +package me.rhunk.snapenhance.core.database.objects import android.annotation.SuppressLint import android.database.Cursor -import me.rhunk.snapenhance.database.DatabaseObject +import me.rhunk.snapenhance.core.database.DatabaseObject import me.rhunk.snapenhance.util.ktx.getInteger import me.rhunk.snapenhance.util.ktx.getStringOrNull diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/UserConversationLink.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/UserConversationLink.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/database/objects/UserConversationLink.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/UserConversationLink.kt index 28bf980e..9590c6b1 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/database/objects/UserConversationLink.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/objects/UserConversationLink.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.database.objects +package me.rhunk.snapenhance.core.database.objects import android.annotation.SuppressLint import android.database.Cursor -import me.rhunk.snapenhance.database.DatabaseObject +import me.rhunk.snapenhance.core.database.DatabaseObject import me.rhunk.snapenhance.util.ktx.getInteger import me.rhunk.snapenhance.util.ktx.getStringOrNull diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadManagerClient.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/DownloadManagerClient.kt similarity index 74% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadManagerClient.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/DownloadManagerClient.kt index b5dc376d..648e2770 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadManagerClient.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/DownloadManagerClient.kt @@ -1,15 +1,15 @@ -package me.rhunk.snapenhance.download +package me.rhunk.snapenhance.core.download import android.content.Intent import android.os.Bundle import me.rhunk.snapenhance.ModContext import me.rhunk.snapenhance.bridge.DownloadCallback -import me.rhunk.snapenhance.download.data.DashOptions -import me.rhunk.snapenhance.download.data.DownloadMediaType -import me.rhunk.snapenhance.download.data.DownloadMetadata -import me.rhunk.snapenhance.download.data.DownloadRequest -import me.rhunk.snapenhance.download.data.InputMedia -import me.rhunk.snapenhance.download.data.MediaEncryptionKeyPair +import me.rhunk.snapenhance.core.download.data.DashOptions +import me.rhunk.snapenhance.core.download.data.DownloadMediaType +import me.rhunk.snapenhance.core.download.data.DownloadMetadata +import me.rhunk.snapenhance.core.download.data.DownloadRequest +import me.rhunk.snapenhance.core.download.data.InputMedia +import me.rhunk.snapenhance.core.download.data.MediaEncryptionKeyPair class DownloadManagerClient ( private val context: ModContext, @@ -33,10 +33,12 @@ class DownloadManagerClient ( fun downloadDashMedia(playlistUrl: String, offsetTime: Long, duration: Long?) { enqueueDownloadRequest( DownloadRequest( - inputMedias = arrayOf(InputMedia( + inputMedias = arrayOf( + InputMedia( content = playlistUrl, type = DownloadMediaType.REMOTE_MEDIA - )), + ) + ), dashOptions = DashOptions(offsetTime, duration), flags = DownloadRequest.Flags.IS_DASH_PLAYLIST ) @@ -46,11 +48,13 @@ class DownloadManagerClient ( fun downloadSingleMedia(mediaData: String, mediaType: DownloadMediaType, encryption: MediaEncryptionKeyPair? = null) { enqueueDownloadRequest( DownloadRequest( - inputMedias = arrayOf(InputMedia( + inputMedias = arrayOf( + InputMedia( content = mediaData, type = mediaType, encryption = encryption - )) + ) + ) ) ) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadTaskManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/DownloadTaskManager.kt similarity index 95% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadTaskManager.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/DownloadTaskManager.kt index 4b5fdaf8..5360191a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadTaskManager.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/DownloadTaskManager.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.download +package me.rhunk.snapenhance.core.download import android.annotation.SuppressLint import android.content.Context import android.database.sqlite.SQLiteDatabase -import me.rhunk.snapenhance.download.data.DownloadMetadata -import me.rhunk.snapenhance.download.data.DownloadObject -import me.rhunk.snapenhance.download.data.DownloadStage -import me.rhunk.snapenhance.download.data.MediaFilter +import me.rhunk.snapenhance.core.download.data.DownloadMetadata +import me.rhunk.snapenhance.core.download.data.DownloadObject +import me.rhunk.snapenhance.core.download.data.DownloadStage +import me.rhunk.snapenhance.core.download.data.MediaFilter import me.rhunk.snapenhance.util.SQLiteDatabaseHelper import me.rhunk.snapenhance.util.ktx.getIntOrNull import me.rhunk.snapenhance.util.ktx.getStringOrNull diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadMediaType.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadMediaType.kt similarity index 91% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadMediaType.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadMediaType.kt index 03c6c18d..5cb8f9e8 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadMediaType.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadMediaType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.download.data +package me.rhunk.snapenhance.core.download.data import android.net.Uri diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadMetadata.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadMetadata.kt similarity index 79% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadMetadata.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadMetadata.kt index e66df166..8a342bdc 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadMetadata.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadMetadata.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.download.data +package me.rhunk.snapenhance.core.download.data data class DownloadMetadata( val mediaIdentifier: String?, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadObject.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadObject.kt similarity index 87% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadObject.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadObject.kt index e3eec134..4c40b3ac 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadObject.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadObject.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.download.data +package me.rhunk.snapenhance.core.download.data import kotlinx.coroutines.Job -import me.rhunk.snapenhance.download.DownloadTaskManager +import me.rhunk.snapenhance.core.download.DownloadTaskManager data class DownloadObject( var downloadId: Int = 0, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadRequest.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadRequest.kt similarity index 92% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadRequest.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadRequest.kt index 4bc08bea..3a2c0638 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadRequest.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadRequest.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.download.data +package me.rhunk.snapenhance.core.download.data data class DashOptions(val offsetTime: Long, val duration: Long?) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadStage.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadStage.kt similarity index 83% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadStage.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadStage.kt index c23c8d60..fa0e2073 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/DownloadStage.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/DownloadStage.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.download.data +package me.rhunk.snapenhance.core.download.data enum class DownloadStage( val isFinalStage: Boolean = false, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/MediaEncryptionKeyPair.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/MediaEncryptionKeyPair.kt similarity index 93% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/data/MediaEncryptionKeyPair.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/MediaEncryptionKeyPair.kt index 7797363d..30a13c4f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/MediaEncryptionKeyPair.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/MediaEncryptionKeyPair.kt @@ -1,6 +1,6 @@ @file:OptIn(ExperimentalEncodingApi::class) -package me.rhunk.snapenhance.download.data +package me.rhunk.snapenhance.core.download.data import me.rhunk.snapenhance.data.wrapper.impl.media.EncryptionWrapper import kotlin.io.encoding.Base64 diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/MediaFilter.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/MediaFilter.kt similarity index 89% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/data/MediaFilter.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/MediaFilter.kt index 1233b1ad..edf59178 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/MediaFilter.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/MediaFilter.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.download.data +package me.rhunk.snapenhance.core.download.data enum class MediaFilter( val key: String, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/SplitMediaAssetType.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/SplitMediaAssetType.kt similarity index 54% rename from core/src/main/kotlin/me/rhunk/snapenhance/download/data/SplitMediaAssetType.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/SplitMediaAssetType.kt index a1ffc26e..c5fae162 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/data/SplitMediaAssetType.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/download/data/SplitMediaAssetType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.download.data +package me.rhunk.snapenhance.core.download.data enum class SplitMediaAssetType { ORIGINAL, OVERLAY diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/EventBus.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/EventBus.kt index 111a8bb5..53feb585 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/EventBus.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/EventBus.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.core.eventbus -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.ModContext import kotlin.reflect.KClass @@ -14,7 +13,7 @@ interface IListener { } class EventBus( - private val context: ModContext + val context: ModContext ) { private val subscribers = mutableMapOf, MutableList>>() @@ -34,7 +33,7 @@ class EventBus( runCatching { listener(event) }.onFailure { - Logger.error("Error while handling event ${event::class.simpleName}", it) + context.log.error("Error while handling event ${event::class.simpleName}", it) } } } @@ -61,7 +60,7 @@ class EventBus( runCatching { (listener as IListener).handle(event) }.onFailure { t -> - Logger.error("Error while handling event ${event::class.simpleName} by ${listener::class.simpleName}", t) + context.log.error("Error while handling event ${event::class.simpleName} by ${listener::class.simpleName}", t) } } return event diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/BridgeFileFeature.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/BridgeFileFeature.kt index f03bdc0d..91f49116 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/BridgeFileFeature.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/BridgeFileFeature.kt @@ -1,6 +1,6 @@ package me.rhunk.snapenhance.features -import me.rhunk.snapenhance.bridge.types.BridgeFileType +import me.rhunk.snapenhance.core.bridge.types.BridgeFileType import java.io.BufferedReader import java.io.ByteArrayInputStream import java.io.InputStreamReader diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/AutoUpdater.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/AutoUpdater.kt index ae9b3f16..8b89a097 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/AutoUpdater.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/AutoUpdater.kt @@ -10,7 +10,6 @@ import android.net.Uri import android.os.Build import android.os.Environment import com.google.gson.JsonParser -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams @@ -36,7 +35,7 @@ class AutoUpdater : Feature("AutoUpdater", loadParams = FeatureLoadParams.ACTIVI runCatching { checkForUpdates() }.onFailure { - Logger.error("Failed to check for updates: ${it.message}", it) + context.log.error("Failed to check for updates: ${it.message}", it) }.onSuccess { context.bridgeClient.setAutoUpdaterTime(currentTimeMillis) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt index b96bee8a..61c00d5b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt @@ -6,9 +6,15 @@ import android.graphics.BitmapFactory import android.net.Uri import android.widget.ImageView import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.Logger.xposedLog import me.rhunk.snapenhance.bridge.DownloadCallback +import me.rhunk.snapenhance.core.database.objects.FriendInfo +import me.rhunk.snapenhance.core.download.DownloadManagerClient +import me.rhunk.snapenhance.core.download.data.DownloadMediaType +import me.rhunk.snapenhance.core.download.data.DownloadMetadata +import me.rhunk.snapenhance.core.download.data.InputMedia +import me.rhunk.snapenhance.core.download.data.MediaFilter +import me.rhunk.snapenhance.core.download.data.SplitMediaAssetType +import me.rhunk.snapenhance.core.download.data.toKeyPair import me.rhunk.snapenhance.core.messaging.MessagingRuleType import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.FileType @@ -17,14 +23,6 @@ import me.rhunk.snapenhance.data.wrapper.impl.media.dash.LongformVideoPlaylistIt import me.rhunk.snapenhance.data.wrapper.impl.media.dash.SnapPlaylistItem import me.rhunk.snapenhance.data.wrapper.impl.media.opera.Layer import me.rhunk.snapenhance.data.wrapper.impl.media.opera.ParamMap -import me.rhunk.snapenhance.database.objects.FriendInfo -import me.rhunk.snapenhance.download.DownloadManagerClient -import me.rhunk.snapenhance.download.data.DownloadMediaType -import me.rhunk.snapenhance.download.data.DownloadMetadata -import me.rhunk.snapenhance.download.data.InputMedia -import me.rhunk.snapenhance.download.data.MediaFilter -import me.rhunk.snapenhance.download.data.SplitMediaAssetType -import me.rhunk.snapenhance.download.data.toKeyPair import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.features.MessagingRuleFeature import me.rhunk.snapenhance.features.impl.Messaging @@ -84,19 +82,19 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp callback = object: DownloadCallback.Stub() { override fun onSuccess(outputFile: String) { if (!downloadLogging.contains("success")) return - Logger.debug("onSuccess: outputFile=$outputFile") + context.log.verbose("onSuccess: outputFile=$outputFile") context.shortToast(context.translation.format("download_processor.saved_toast", "path" to outputFile.split("/").takeLast(2).joinToString("/"))) } override fun onProgress(message: String) { if (!downloadLogging.contains("progress")) return - Logger.debug("onProgress: message=$message") + context.log.verbose("onProgress: message=$message") context.shortToast(message) } override fun onFailure(message: String, throwable: String?) { if (!downloadLogging.contains("failure")) return - Logger.debug("onFailure: message=$message, throwable=$throwable") + context.log.verbose("onFailure: message=$message, throwable=$throwable") throwable?.let { context.longToast((message + it.takeIf { it.isNotEmpty() }.orEmpty())) return @@ -402,8 +400,8 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp try { handleOperaMedia(mediaParamMap, mediaInfoMap, false) } catch (e: Throwable) { - xposedLog(e) - context.longToast(e.message!!) + context.log.error("Failed to handle opera media", e) + context.longToast(e.message) } } } @@ -524,11 +522,11 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp } }.onFailure { context.shortToast(translations["failed_to_create_preview_toast"]) - xposedLog(it) + context.log.error("Failed to create preview", it) } }.onFailure { context.longToast(translations["failed_generic_toast"]) - xposedLog(it) + context.log.error("Failed to download message", it) } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt index 3d770836..555f45b7 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt @@ -3,7 +3,6 @@ package me.rhunk.snapenhance.features.impl.downloader import android.annotation.SuppressLint import android.widget.Button import android.widget.RelativeLayout -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.core.eventbus.events.impl.AddViewEvent import me.rhunk.snapenhance.core.eventbus.events.impl.NetworkApiRequestEvent import me.rhunk.snapenhance.features.Feature @@ -45,7 +44,7 @@ class ProfilePictureDownloader : Feature("ProfilePictureDownloader", loadParams friendUsername!! ) }.onFailure { - Logger.error("Failed to download profile picture", it) + this@ProfilePictureDownloader.context.log.error("Failed to download profile picture", it) } } }.show() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/DeviceSpooferHook.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/DeviceSpooferHook.kt index 86b48c74..a9f26e72 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/DeviceSpooferHook.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/DeviceSpooferHook.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.experiments -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage @@ -17,11 +16,11 @@ class DeviceSpooferHook: Feature("device_spoofer", loadParams = FeatureLoadParam val fingerprintClass = android.os.Build::class.java Hooker.hook(fingerprintClass, "FINGERPRINT", HookStage.BEFORE) { hookAdapter -> hookAdapter.setResult(fingerprint) - Logger.debug("Fingerprint spoofed to $fingerprint") + context.log.verbose("Fingerprint spoofed to $fingerprint") } Hooker.hook(fingerprintClass, "deriveFingerprint", HookStage.BEFORE) { hookAdapter -> hookAdapter.setResult(fingerprint) - Logger.debug("Fingerprint spoofed to $fingerprint") + context.log.verbose("Fingerprint spoofed to $fingerprint") } } @@ -30,7 +29,7 @@ class DeviceSpooferHook: Feature("device_spoofer", loadParams = FeatureLoadParam Hooker.hook(settingsSecureClass, "getString", HookStage.BEFORE) { hookAdapter -> if(hookAdapter.args()[1] == "android_id") { hookAdapter.setResult(androidId) - Logger.debug("Android ID spoofed to $androidId") + context.log.verbose("Android ID spoofed to $androidId") } } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt index 78dc70f6..a8bddbfe 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.privacy -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.core.eventbus.events.impl.SendMessageWithContentEvent import me.rhunk.snapenhance.data.NotificationType import me.rhunk.snapenhance.features.Feature @@ -28,7 +27,7 @@ class PreventMessageSending : Feature("Prevent message sending", loadParams = Fe val associatedType = NotificationType.fromContentType(contentType) ?: return@subscribe if (preventMessageSending.contains(associatedType.key)) { - Logger.debug("Preventing message sending for $associatedType") + context.log.verbose("Preventing message sending for $associatedType") event.canceled = true } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt index 7cf52d10..086776b1 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.features.impl.spying import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.core.eventbus.events.impl.NetworkApiRequestEvent import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt index f9523882..54d82e31 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt @@ -3,7 +3,6 @@ package me.rhunk.snapenhance.features.impl.spying import android.os.DeadObjectException import com.google.gson.JsonObject import com.google.gson.JsonParser -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.MessageState import me.rhunk.snapenhance.data.wrapper.impl.Message @@ -72,7 +71,7 @@ class MessageLogger : Feature("MessageLogger", context.database.getFeedEntries(PREFETCH_FEED_COUNT).forEach { friendFeedInfo -> fetchedMessages.addAll(context.bridgeClient.getLoggedMessageIds(friendFeedInfo.key!!, PREFETCH_MESSAGE_COUNT).toList()) } - }.also { Logger.debug("Loaded ${fetchedMessages.size} cached messages in $it") } + }.also { context.log.verbose("Loaded ${fetchedMessages.size} cached messages in $it") } } private fun processSnapMessage(messageInstance: Any) { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/AutoSave.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/AutoSave.kt index 03505da2..66b3ed4c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/AutoSave.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/AutoSave.kt @@ -41,7 +41,7 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE, val callback = CallbackBuilder(callbackClass) .override("onError") { - Logger.xposedLog("Error saving message $messageId") + context.log.warn("Error saving message $messageId") }.build() runCatching { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt index 817ac10f..1d081af9 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt @@ -3,7 +3,6 @@ package me.rhunk.snapenhance.features.impl.tweaks import android.os.Build import android.os.FileObserver import com.google.gson.JsonParser -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.core.eventbus.events.impl.SendMessageWithContentEvent import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams @@ -32,7 +31,7 @@ class DisableVideoLengthRestriction : Feature("DisableVideoLengthRestriction", l val fileContent = JsonParser.parseReader(file.reader()).asJsonObject if (fileContent["timerOrDuration"].asLong < 0) file.delete() }.onFailure { - Logger.error("Failed to read story metadata file", it) + context.log.error("Failed to read story metadata file", it) } } }) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GooglePlayServicesDialogs.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GooglePlayServicesDialogs.kt index 4a5ec561..519cadef 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GooglePlayServicesDialogs.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GooglePlayServicesDialogs.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.features.impl.tweaks import android.app.AlertDialog -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage @@ -15,7 +14,7 @@ class GooglePlayServicesDialogs : Feature("Disable GMS Dialogs", loadParams = Fe findClass("com.google.android.gms.common.GoogleApiAvailability").methods .first { Modifier.isStatic(it.modifiers) && it.returnType == AlertDialog::class.java }.let { method -> method.hook(HookStage.BEFORE) { param -> - Logger.debug("GoogleApiAvailability.showErrorDialogFragment() called, returning null") + context.log.verbose("GoogleApiAvailability.showErrorDialogFragment() called, returning null") param.setResult(null) } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt index 3ebaaa2b..be27dd6d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt @@ -13,12 +13,12 @@ import android.os.UserHandle import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import me.rhunk.snapenhance.Logger +import me.rhunk.snapenhance.core.download.data.SplitMediaAssetType import me.rhunk.snapenhance.core.eventbus.events.impl.SnapWidgetBroadcastReceiveEvent import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.MediaReferenceType import me.rhunk.snapenhance.data.wrapper.impl.Message import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.download.data.SplitMediaAssetType import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.features.impl.Messaging @@ -297,7 +297,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN fetchMessagesResult(conversationId, messageList) } .override("onError") { - Logger.xposedLog("Failed to fetch message ${it.arg(0) as Any}") + context.log.error("Failed to fetch message ${it.arg(0) as Any}") }.build() fetchConversationWithMessagesMethod.invoke(conversationManager, SnapUUID.fromString(conversationId).instanceNonNull(), callback) @@ -323,7 +323,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN val intent = param.argNullable(0) ?: return@hook val messageType = intent.getStringExtra("type") ?: return@hook - Logger.xposedLog("received message type: $messageType") + context.log.debug("received message type: $messageType") if (states.contains(messageType.replaceFirst("mischief_", ""))) { param.setResult(null) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/PinConversations.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/PinConversations.kt index 04b0ec19..a7098ef4 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/PinConversations.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/PinConversations.kt @@ -1,6 +1,6 @@ package me.rhunk.snapenhance.features.impl.ui -import me.rhunk.snapenhance.bridge.types.BridgeFileType +import me.rhunk.snapenhance.core.bridge.types.BridgeFileType import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID import me.rhunk.snapenhance.features.BridgeFileFeature import me.rhunk.snapenhance.features.FeatureLoadParams diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ActionManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ActionManager.kt index a00c7419..33dd7c6f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ActionManager.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ActionManager.kt @@ -1,38 +1,37 @@ package me.rhunk.snapenhance.manager.impl +import android.content.Intent import me.rhunk.snapenhance.ModContext import me.rhunk.snapenhance.action.AbstractAction -import me.rhunk.snapenhance.action.impl.CheckForUpdates -import me.rhunk.snapenhance.action.impl.CleanCache -import me.rhunk.snapenhance.action.impl.ClearMessageLogger -import me.rhunk.snapenhance.action.impl.ExportChatMessages -import me.rhunk.snapenhance.action.impl.OpenMap -import me.rhunk.snapenhance.action.impl.RefreshMappings -import me.rhunk.snapenhance.core.BuildConfig +import me.rhunk.snapenhance.action.EnumAction import me.rhunk.snapenhance.manager.Manager -import kotlin.reflect.KClass class ActionManager( - private val context: ModContext, + private val modContext: ModContext, ) : Manager { - private val actions = mutableMapOf() - fun getActions() = actions.values.toList() - private fun load(clazz: KClass) { - val action = clazz.java.newInstance() - action.context = context - actions[action.nameKey] = action + companion object { + const val ACTION_PARAMETER = "se_action" } + private val actions = mutableMapOf() + override fun init() { - load(CleanCache::class) - load(ExportChatMessages::class) - load(OpenMap::class) - load(CheckForUpdates::class) - if(BuildConfig.DEBUG) { - load(ClearMessageLogger::class) - load(RefreshMappings::class) + EnumAction.values().forEach { enumAction -> + actions[enumAction.key] = enumAction.clazz.java.getConstructor().newInstance().apply { + this.context = modContext + } } + } + fun onNewIntent(intent: Intent?) { + val action = intent?.getStringExtra(ACTION_PARAMETER) ?: return + execute(EnumAction.values().find { it.key == action } ?: return) + intent.removeExtra(ACTION_PARAMETER) + } - actions.values.forEach(AbstractAction::init) + private fun execute(action: EnumAction) { + actions[action.key]?.run() + if (action.exitOnFinish) { + modContext.forceCloseApp() + } } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt index 66537761..918d89d4 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt @@ -11,11 +11,10 @@ import android.view.View import android.widget.Button import android.widget.CompoundButton import android.widget.Switch -import me.rhunk.snapenhance.Logger +import me.rhunk.snapenhance.core.database.objects.ConversationMessage +import me.rhunk.snapenhance.core.database.objects.FriendInfo +import me.rhunk.snapenhance.core.database.objects.UserConversationLink import me.rhunk.snapenhance.data.ContentType -import me.rhunk.snapenhance.database.objects.ConversationMessage -import me.rhunk.snapenhance.database.objects.FriendInfo -import me.rhunk.snapenhance.database.objects.UserConversationLink import me.rhunk.snapenhance.features.MessagingRuleFeature import me.rhunk.snapenhance.features.impl.Messaging import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader @@ -57,7 +56,7 @@ class FriendFeedInfoMenu : AbstractMenu() { ) } } catch (e: Throwable) { - Logger.xposedLog(e) + context.log.error("Error loading bitmoji selfie", e) } val finalIcon = icon context.runOnUiThread { @@ -243,7 +242,6 @@ class FriendFeedInfoMenu : AbstractMenu() { rules.forEach { ruleFeature -> if (!friendFeedMenuOptions.contains(ruleFeature.ruleType.key)) return@forEach - Logger.debug("${ruleFeature.ruleType.key} ${ruleFeature.getRuleState()}") val ruleState = ruleFeature.getRuleState() ?: return@forEach createToggleFeature(viewConsumer, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/OperaContextActionMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/OperaContextActionMenu.kt index 06438382..e0cc2482 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/OperaContextActionMenu.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/OperaContextActionMenu.kt @@ -8,7 +8,6 @@ import android.widget.Button import android.widget.LinearLayout import android.widget.ScrollView import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader import me.rhunk.snapenhance.ui.ViewAppearanceHelper.applyTheme import me.rhunk.snapenhance.ui.menu.AbstractMenu @@ -76,7 +75,7 @@ class OperaContextActionMenu : AbstractMenu() { linearLayout.addView(button) (childView as ViewGroup).addView(linearLayout, 0) } catch (e: Throwable) { - Logger.xposedLog(e) + context.log.error("Error while injecting OperaContextActionMenu", e) } } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsMenu.kt index 68eadf9c..34c5e321 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsMenu.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsMenu.kt @@ -2,15 +2,13 @@ package me.rhunk.snapenhance.ui.menu.impl import android.annotation.SuppressLint import android.view.View -import android.widget.Button -import me.rhunk.snapenhance.ui.ViewAppearanceHelper import me.rhunk.snapenhance.ui.menu.AbstractMenu class SettingsMenu : AbstractMenu() { //TODO: quick settings @SuppressLint("SetTextI18n") fun inject(viewModel: View, addView: (View) -> Unit) { - val actions = context.actionManager.getActions().map { + /*val actions = context.actionManager.getActions().map { Pair(it) { val button = Button(viewModel.context) button.text = context.translation[it.nameKey] @@ -25,6 +23,6 @@ class SettingsMenu : AbstractMenu() { actions.forEach { addView(it.second()) - } + }*/ } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/util/SQLiteDatabaseHelper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/util/SQLiteDatabaseHelper.kt index 50b4434a..c9768089 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/util/SQLiteDatabaseHelper.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/util/SQLiteDatabaseHelper.kt @@ -23,7 +23,7 @@ object SQLiteDatabaseHelper { if (newColumns.isEmpty()) return@forEach - Logger.log("Schema for table $tableName has changed") + Logger.directDebug("Schema for table $tableName has changed") sqLiteDatabase.execSQL("DROP TABLE $tableName") sqLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS $tableName (${columns.joinToString(", ")})") } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/util/download/HttpServer.kt b/core/src/main/kotlin/me/rhunk/snapenhance/util/download/HttpServer.kt index 02e663ed..e50496a2 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/util/download/HttpServer.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/util/download/HttpServer.kt @@ -37,7 +37,7 @@ class HttpServer( } coroutineScope.launch(Dispatchers.IO) { - Logger.debug("starting http server on port $port") + Logger.directDebug("starting http server on port $port") serverSocket = ServerSocket(port) callback(this@HttpServer) while (!serverSocket!!.isClosed) { @@ -48,21 +48,21 @@ class HttpServer( handleRequest(socket) timeoutJob = launch { delay(timeout.toLong()) - Logger.debug("http server closed due to timeout") + Logger.directDebug("http server closed due to timeout") runCatching { socketJob?.cancel() socket.close() serverSocket?.close() }.onFailure { - Logger.error(it) + Logger.directError("failed to close socket", it) } } } } catch (e: SocketException) { - Logger.debug("http server timed out") + Logger.directDebug("http server timed out") break; } catch (e: Throwable) { - Logger.error("failed to handle request", e) + Logger.directError("failed to handle request", e) } } }.also { socketJob = it } @@ -90,13 +90,13 @@ class HttpServer( outputStream.close() socket.close() }.onFailure { - Logger.error("failed to close socket", it) + Logger.directError("failed to close socket", it) } } val parse = StringTokenizer(line) val method = parse.nextToken().uppercase(Locale.getDefault()) var fileRequested = parse.nextToken().lowercase(Locale.getDefault()) - Logger.debug("[http-server:${port}] $method $fileRequested") + Logger.directDebug("[http-server:${port}] $method $fileRequested") if (method != "GET") { with(writer) { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/util/download/RemoteMediaResolver.kt b/core/src/main/kotlin/me/rhunk/snapenhance/util/download/RemoteMediaResolver.kt index 718cef50..839093d0 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/util/download/RemoteMediaResolver.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/util/download/RemoteMediaResolver.kt @@ -44,7 +44,7 @@ object RemoteMediaResolver { okHttpClient.newCall(request).execute().use { response -> if (!response.isSuccessful) { - Logger.log("Unexpected code $response") + Logger.directDebug("Unexpected code $response") return null } return ByteArrayInputStream(response.body.bytes()) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/util/export/MessageExporter.kt b/core/src/main/kotlin/me/rhunk/snapenhance/util/export/MessageExporter.kt index ad6f5c0a..ad364702 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/util/export/MessageExporter.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/util/export/MessageExporter.kt @@ -9,16 +9,15 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.ModContext import me.rhunk.snapenhance.core.BuildConfig +import me.rhunk.snapenhance.core.database.objects.FriendFeedEntry +import me.rhunk.snapenhance.core.database.objects.FriendInfo import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.FileType import me.rhunk.snapenhance.data.MediaReferenceType import me.rhunk.snapenhance.data.wrapper.impl.Message import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.database.objects.FriendFeedEntry -import me.rhunk.snapenhance.database.objects.FriendInfo import me.rhunk.snapenhance.util.protobuf.ProtoReader import me.rhunk.snapenhance.util.snap.EncryptionHelper import me.rhunk.snapenhance.util.snap.MediaDownloaderHelper @@ -138,7 +137,7 @@ class MessageExporter( } }.onFailure { printLog("failed to download media for ${message.messageDescriptor.conversationId}_${message.orderKey}") - Logger.error("failed to download media for ${message.messageDescriptor.conversationId}_${message.orderKey}", it) + context.log.error("failed to download media for ${message.messageDescriptor.conversationId}_${message.orderKey}", it) } } } @@ -219,7 +218,7 @@ class MessageExporter( } }.onFailure { printLog("failed to read template from apk") - Logger.error("failed to read template from apk", it) + context.log.error("failed to read template from apk", it) } output.write("".toByteArray()) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/util/snap/MediaDownloaderHelper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/util/snap/MediaDownloaderHelper.kt index e8ea611a..df4a7973 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/util/snap/MediaDownloaderHelper.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/util/snap/MediaDownloaderHelper.kt @@ -4,9 +4,9 @@ import com.arthenica.ffmpegkit.FFmpegKit import com.arthenica.ffmpegkit.FFmpegSession import kotlinx.coroutines.suspendCancellableCoroutine import me.rhunk.snapenhance.Constants +import me.rhunk.snapenhance.core.download.data.SplitMediaAssetType import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.FileType -import me.rhunk.snapenhance.download.data.SplitMediaAssetType import me.rhunk.snapenhance.util.download.RemoteMediaResolver import me.rhunk.snapenhance.util.protobuf.ProtoReader import java.io.ByteArrayInputStream