Merge branch 'dev' into dev
This commit is contained in:
@@ -229,7 +229,6 @@ class BridgeService : Service() {
|
||||
pendingSocialSnapshotCallback?.let { callback ->
|
||||
pendingSocialSnapshotCallback = null
|
||||
callback(parsedFriends, parsedGroups)
|
||||
return
|
||||
}
|
||||
remoteSideContext.database.replaceMessagingData(parsedFriends, parsedGroups)
|
||||
remoteSideContext.database.receiveMessagingDataCallback(parsedFriends, parsedGroups)
|
||||
|
||||
@@ -121,6 +121,7 @@ class DownloadProcessor (
|
||||
inputFile.outputStream().use {
|
||||
bitmap.compress(compressFormat, 100, it)
|
||||
}
|
||||
bitmap.recycle()
|
||||
fileType = FileType.fromFile(inputFile)
|
||||
}
|
||||
}
|
||||
@@ -673,6 +674,10 @@ class DownloadProcessor (
|
||||
mergedBitmap.compress(compressFormat, 100, it)
|
||||
}
|
||||
|
||||
originalBitmap.recycle()
|
||||
overlayBitmap.recycle()
|
||||
mergedBitmap.recycle()
|
||||
|
||||
saveMediaToGallery(pendingTask, mergedImage, downloadMetadata)
|
||||
mergedImage.delete()
|
||||
renamedOverlayMedia.delete()
|
||||
|
||||
@@ -92,6 +92,10 @@ class FFMpegProcessor(
|
||||
|
||||
private val sharedExecutor = Executors.newSingleThreadExecutor()
|
||||
|
||||
protected fun finalize() {
|
||||
runCatching { sharedExecutor.shutdown() }
|
||||
}
|
||||
|
||||
private suspend fun newFFMpegTask(globalArguments: ArgumentList, inputArguments: ArgumentList, outputArguments: ArgumentList) = suspendCancellableCoroutine<FFmpegSession> {
|
||||
val stringBuilder = StringBuilder()
|
||||
arrayOf(globalArguments, inputArguments, outputArguments).forEach { argumentList ->
|
||||
|
||||
@@ -138,6 +138,11 @@ fun AppDatabase.replaceMessagingData(
|
||||
} finally {
|
||||
database.endTransaction()
|
||||
}
|
||||
|
||||
// Notify with the full updated list from the DB
|
||||
val allFriends = getFriends(descOrder = true)
|
||||
val allGroups = getGroups()
|
||||
receiveMessagingDataCallback(allFriends, allGroups)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -256,11 +256,7 @@ class AddFriendDialog(
|
||||
)
|
||||
}
|
||||
|
||||
if (context.bridgeService != null) {
|
||||
context.bridgeService?.requestEphemeralSocialSnapshot(updateSnapshot)
|
||||
} else {
|
||||
context.database.receiveMessagingDataCallback = updateSnapshot
|
||||
}
|
||||
context.database.receiveMessagingDataCallback = updateSnapshot
|
||||
context.requestSocialSnapshotRefresh()
|
||||
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.eternal.purrfectsnap.core.features.impl
|
||||
|
||||
import me.eternal.purrfectsnap.core.features.Feature
|
||||
import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging
|
||||
|
||||
import me.eternal.purrfectsnap.core.util.hook.HookStage
|
||||
import me.eternal.purrfectsnap.core.util.hook.Hooker
|
||||
@@ -165,6 +166,11 @@ class ConfigurationOverride : Feature("Configuration Override") {
|
||||
|
||||
overrideProperty("DF_VOPERA_FOR_STORIES", { context.config.userInterface.verticalStoryViewer.get() },
|
||||
{ true }, isAppExperiment = true)
|
||||
overrideProperty("SPOTLIGHT_5TH_TAB_ENABLED", {
|
||||
context.config.userInterface.disableSpotlight.get() &&
|
||||
context.feature(Messaging::class).openedConversationUUID == null
|
||||
},
|
||||
{ false })
|
||||
|
||||
overrideProperty("BYPASS_AD_FEATURE_GATE", { context.config.global.blockAds.get() },
|
||||
{ true })
|
||||
|
||||
@@ -76,6 +76,7 @@ import me.eternal.purrfectsnap.core.wrapper.impl.media.opera.ParamMap
|
||||
import me.eternal.purrfectsnap.core.wrapper.impl.media.toKeyPair
|
||||
import me.eternal.purrfectsnap.mapper.impl.OperaPageViewControllerMapper
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import kotlin.math.absoluteValue
|
||||
@@ -91,6 +92,8 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
private set
|
||||
@Volatile
|
||||
private var pendingBatchDownloadIndices: MutableList<Int>? = null
|
||||
private val batchLock = Any()
|
||||
|
||||
@Volatile
|
||||
private var batchForceAllowDuplicate: Boolean = false
|
||||
private val translations by lazy {
|
||||
@@ -107,12 +110,9 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
private fun logVerbose(msg: String) = this@MediaDownloader.context.log.verbose("[MediaDownloader] $msg")
|
||||
private fun logError(msg: String, e: Throwable? = null) = if (e != null) this@MediaDownloader.context.log.error("[MediaDownloader] $msg", e) else this@MediaDownloader.context.log.error("[MediaDownloader] $msg")
|
||||
|
||||
@Volatile
|
||||
private var batchTotalCount: Int = 0
|
||||
@Volatile
|
||||
private var batchSuccessCount: Int = 0
|
||||
@Volatile
|
||||
private var batchFailureCount: Int = 0
|
||||
private val batchTotalCount = AtomicInteger(0)
|
||||
private val batchSuccessCount = AtomicInteger(0)
|
||||
private val batchFailureCount = AtomicInteger(0)
|
||||
@Volatile
|
||||
private var initialBatchStoryIdentity: String? = null
|
||||
|
||||
@@ -179,11 +179,11 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
}.onFailure { logError("Post-Processing Logic Failed for $outputFile", it) }
|
||||
|
||||
if (isBatch) {
|
||||
batchSuccessCount++
|
||||
batchSuccessCount.incrementAndGet()
|
||||
if (downloadLogging.contains("success")) {
|
||||
modCtx.inAppOverlay.showStatusToast(
|
||||
icon = Icons.Outlined.DownloadDone,
|
||||
text = translations.format("batch_progress_toast", "current" to (batchSuccessCount + batchFailureCount).toString(), "total" to batchTotalCount.toString()),
|
||||
text = translations.format("batch_progress_toast", "current" to (batchSuccessCount.get() + batchFailureCount.get()).toString(), "total" to batchTotalCount.get().toString()),
|
||||
durationMs = 1300
|
||||
)
|
||||
}
|
||||
@@ -207,7 +207,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
override fun onFailure(message: String, throwable: String?) {
|
||||
if (!downloadLogging.contains("failure")) return
|
||||
val errorText = translations[if (message == "Failed to download") "failed_generic_toast" else message] ?: message
|
||||
if (isBatch) { batchFailureCount++; return }
|
||||
if (isBatch) { batchFailureCount.incrementAndGet(); return }
|
||||
if (modCtx.isMainActivityPaused) modCtx.shortToast(errorText)
|
||||
modCtx.inAppOverlay.showStatusToast(Icons.Outlined.ErrorOutline, errorText, 1300)
|
||||
}
|
||||
@@ -283,9 +283,9 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
val mediaInfoMap = lastSeenMediaInfoMap ?: return
|
||||
val modCtx = this@MediaDownloader.context
|
||||
|
||||
batchTotalCount = indices.size
|
||||
batchSuccessCount = 0; batchFailureCount = 0
|
||||
pendingBatchDownloadIndices = indices
|
||||
batchTotalCount.set(indices.size)
|
||||
batchSuccessCount.set(0); batchFailureCount.set(0)
|
||||
synchronized(batchLock) { pendingBatchDownloadIndices = indices }
|
||||
batchForceAllowDuplicate = allowDuplicate
|
||||
initialBatchStoryIdentity = paramMap.getStoryIdentity()
|
||||
|
||||
@@ -297,7 +297,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
modCtx.coroutineScope.launch { processNextBatchDownload(paramMap, mediaInfoMap) }
|
||||
} else {
|
||||
val jumped = modCtx.feature(OperaStoryOverlay::class).requestJumpToSnap(targetIndex, totalCount)
|
||||
if (!jumped) { pendingBatchDownloadIndices = null; modCtx.shortToast(translations["batch_download_jump_failed_toast"] ?: "Jump Failed") }
|
||||
if (!jumped) { synchronized(batchLock) { pendingBatchDownloadIndices = null }; modCtx.shortToast(translations["batch_download_jump_failed_toast"] ?: "Jump Failed") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,13 +305,13 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
runCatching {
|
||||
handleOperaMedia(paramMap, mediaInfoMap, forceDownload = true, forceAllowDuplicate = batchForceAllowDuplicate, isBatch = true)
|
||||
}.onFailure {
|
||||
batchFailureCount++
|
||||
if (batchSuccessCount + batchFailureCount == batchTotalCount) flushPendingMergeAndComplete()
|
||||
batchFailureCount.incrementAndGet()
|
||||
if (batchSuccessCount.get() + batchFailureCount.get() == batchTotalCount.get()) flushPendingMergeAndComplete()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processNextBatchDownload(paramMap: ParamMap, mediaInfoMap: Map<SplitMediaAssetType, MediaInfo>) {
|
||||
val queue = pendingBatchDownloadIndices ?: return
|
||||
val queue = synchronized(batchLock) { pendingBatchDownloadIndices } ?: return
|
||||
if (queue.isEmpty()) return
|
||||
val modCtx = this@MediaDownloader.context
|
||||
|
||||
@@ -323,7 +323,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
val currentIndex = paramMap.getStorySnapIndex() ?: -1
|
||||
if (currentIndex != queue.first()) return
|
||||
|
||||
queue.removeAt(0)
|
||||
synchronized(batchLock) { queue.removeAt(0) }
|
||||
downloadSingleSnap(paramMap, mediaInfoMap)
|
||||
|
||||
if (queue.isNotEmpty()) {
|
||||
@@ -333,7 +333,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
|
||||
val jumped = runCatching { modCtx.feature(OperaStoryOverlay::class).requestJumpToSnap(queue.first(), totalCount) }.getOrNull() == true
|
||||
if (!jumped && retryCount < 1) tryJump(retryCount + 1)
|
||||
else if (!jumped) { pendingBatchDownloadIndices = null; modCtx.shortToast(translations["batch_download_jump_failed_toast"] ?: "Jump Failed") }
|
||||
else if (!jumped) { synchronized(batchLock) { pendingBatchDownloadIndices = null }; modCtx.shortToast(translations["batch_download_jump_failed_toast"] ?: "Jump Failed") }
|
||||
}, if (retryCount == 0) 120L else 220L)
|
||||
}
|
||||
tryJump()
|
||||
@@ -343,8 +343,8 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
|
||||
|
||||
private fun flushPendingMergeAndComplete() {
|
||||
val modCtx = this@MediaDownloader.context
|
||||
pendingBatchDownloadIndices = null
|
||||
modCtx.shortToast(if (batchFailureCount == 0) translations["batch_download_complete_toast"] ?: "Batch Complete" else "Batch complete: $batchSuccessCount succeeded, $batchFailureCount failed")
|
||||
synchronized(batchLock) { pendingBatchDownloadIndices = null }
|
||||
modCtx.shortToast(if (batchFailureCount.get() == 0) translations["batch_download_complete_toast"] ?: "Batch Complete" else "Batch complete: ${batchSuccessCount.get()} succeeded, ${batchFailureCount.get()} failed")
|
||||
}
|
||||
|
||||
fun showLastOperaDebugMediaInfo() {
|
||||
|
||||
@@ -373,7 +373,7 @@ class AutoOpenSnaps: MessagingRuleFeature("Auto Open Snaps", MessagingRuleType.A
|
||||
|
||||
if (!isCompact) {
|
||||
val recentSnaps = synchronized(queuedSnaps) { queuedSnaps.takeLast(5) }
|
||||
val bigTextStyle = Notification.BigTextStyle().setSummaryText("")
|
||||
val bigTextStyle = Notification.BigTextStyle().setSummaryText(null)
|
||||
val detailText = buildString {
|
||||
append("QUEUE STATISTICS\n")
|
||||
append("├─ Opened: $processed snaps\n")
|
||||
|
||||
Reference in New Issue
Block a user