Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class CloudSyncCoordinator @Inject constructor(
return when (scope) {
CloudSyncScope.LOCAL_HISTORY -> 2_000L
CloudSyncScope.IPTV -> 750L
CloudSyncScope.PLUGINS -> 1_000L
else -> 500L
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ enum class CloudSyncScope {
IPTV,
WATCHLIST,
LOCAL_HISTORY,
ACCOUNT
ACCOUNT,
PLUGINS
}

data class CloudSyncInvalidation(
Expand Down
40 changes: 16 additions & 24 deletions app/src/sideload/kotlin/com/arflix/tv/core/plugin/PluginManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import com.arflix.tv.core.plugin.cloudstream.ExternalExtensionLoader
import com.arflix.tv.core.plugin.cloudstream.ExternalExtensionRunner
import com.arflix.tv.core.plugin.cloudstream.ExternalRepoParser
import com.arflix.tv.data.local.PluginDataStore
import com.arflix.tv.data.repository.CloudSyncInvalidationBus
import com.arflix.tv.data.repository.CloudSyncScope
import com.arflix.tv.domain.model.ExternalPluginEntry
import com.arflix.tv.domain.model.LocalScraperResult
import com.arflix.tv.domain.model.PluginManifest
Expand Down Expand Up @@ -65,7 +67,8 @@ class PluginManager @Inject constructor(
private val runtime: PluginRuntime,
private val externalRepoParser: ExternalRepoParser,
private val externalExtensionLoader: ExternalExtensionLoader,
private val externalExtensionRunner: ExternalExtensionRunner
private val externalExtensionRunner: ExternalExtensionRunner,
private val invalidationBus: CloudSyncInvalidationBus
) {
private val moshi = Moshi.Builder()
.addLast(KotlinJsonAdapterFactory())
Expand Down Expand Up @@ -247,28 +250,21 @@ class PluginManager @Inject constructor(
fun flushPendingSync() {
if (pendingPushAfterSync) {
pendingPushAfterSync = false
Log.d(TAG, "flushPendingSync: firing deferred push")
triggerRemoteSync()
Log.d(TAG, "flushPendingSync: firing deferred push after remote sync")
triggerRemoteSync("flush after remote sync")
}
}

private var syncJob: kotlinx.coroutines.Job? = null

private fun triggerRemoteSync() {
private fun triggerRemoteSync(reason: String = "plugin change") {
if (isSyncingFromRemote) {
Log.d(TAG, "triggerRemoteSync: skipped (syncing from remote), will push after sync")
Log.d(TAG, "triggerRemoteSync: deferred (syncing from remote)")
pendingPushAfterSync = true
return
}
if (true /* !authManager.isAuthenticated */) {
Log.d(TAG, "triggerRemoteSync: skipped (not authenticated, simulated)")
return
}
Log.d(TAG, "triggerRemoteSync: scheduling push in 500ms")
syncJob?.cancel()
syncJob = syncScope.launch {
kotlinx.coroutines.delay(500)
}
Log.d(TAG, "triggerRemoteSync: marking dirty — $reason")
invalidationBus.markDirty(CloudSyncScope.PLUGINS, null, reason)
}

// Combined flow of enabled scrapers
Expand Down Expand Up @@ -399,7 +395,7 @@ class PluginManager @Inject constructor(
downloadJsScrapers(repo.id, canonicalManifestUrl, manifest.getActiveScrapers())

Log.d(TAG, "NuvioTV repository added: ${repo.name} with ${manifest.getActiveScrapers().size} scrapers")
triggerRemoteSync()
triggerRemoteSync("repo added: ${repo.name}")
return Result.success(repo)
}

Expand Down Expand Up @@ -430,7 +426,7 @@ class PluginManager @Inject constructor(
downloadDexExtensions(repo.id, parseResult.plugins)

Log.d(TAG, "External repository added: ${repo.name} with ${parseResult.plugins.size} extensions")
triggerRemoteSync()
triggerRemoteSync("repo added: ${repo.name}")
return Result.success(repo)
}

Expand All @@ -457,14 +453,7 @@ class PluginManager @Inject constructor(
// Remove repository
dataStore.removeRepository(repoId)

// Push synchronously when user-initiated (not during reconciliation)
// to prevent the next sync pull from re-adding the removed repo
if (!isSyncingFromRemote && false /* authManager.isAuthenticated */) {
Log.d(TAG, "removeRepository: pushing removal to remote synchronously")
// pluginSyncService.pushToRemote()
} else if (isSyncingFromRemote) {
pendingPushAfterSync = true
}
triggerRemoteSync("repo removed: $repoId")
}


Expand Down Expand Up @@ -603,6 +592,7 @@ class PluginManager @Inject constructor(
if (scraper.id == scraperId) scraper.copy(enabled = enabled) else scraper
}
dataStore.saveScrapers(updatedScrapers)
triggerRemoteSync("scraper toggled: $scraperId=$enabled")
}

/**
Expand All @@ -614,13 +604,15 @@ class PluginManager @Inject constructor(
if (scraper.repositoryId == repoId) scraper.copy(enabled = enabled) else scraper
}
dataStore.saveScrapers(updatedScrapers)
triggerRemoteSync("all scrapers toggled for repo: $repoId=$enabled")
}

/**
* Toggle plugins globally enabled
*/
suspend fun setPluginsEnabled(enabled: Boolean) {
dataStore.setPluginsEnabled(enabled)
triggerRemoteSync("plugins enabled=$enabled")
}

suspend fun setGroupStreamsByRepository(enabled: Boolean) {
Expand Down
Loading