mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-20 03:24:50 +00:00
Support for cache in reconstructions, non-required cache added to exports, playlists shares now add a cache aswell for quicker importing
This commit is contained in:
parent
56e6314c11
commit
6ffc067b24
12 changed files with 147 additions and 36 deletions
|
@ -34,6 +34,7 @@ import com.futo.platformplayer.dialogs.MigrateDialog
|
|||
import com.futo.platformplayer.dialogs.ProgressDialog
|
||||
import com.futo.platformplayer.engine.exceptions.PluginException
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.models.ImportCache
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StateBackup
|
||||
import com.futo.platformplayer.stores.v2.ManagedStore
|
||||
|
@ -343,8 +344,8 @@ class UIDialogs {
|
|||
}
|
||||
}
|
||||
|
||||
fun showImportDialog(context: Context, store: ManagedStore<*>, name: String, reconstructions: List<String>, onConcluded: () -> Unit) {
|
||||
val dialog = ImportDialog(context, store, name, reconstructions, onConcluded);
|
||||
fun showImportDialog(context: Context, store: ManagedStore<*>, name: String, reconstructions: List<String>, cache: ImportCache?, onConcluded: () -> Unit) {
|
||||
val dialog = ImportDialog(context, store, name, reconstructions, cache, onConcluded);
|
||||
registerDialogOpened(dialog);
|
||||
dialog.setOnDismissListener { registerDialogClosed(dialog) };
|
||||
dialog.show();
|
||||
|
|
|
@ -41,6 +41,7 @@ import com.futo.platformplayer.fragment.mainactivity.topbar.NavigationTopBarFrag
|
|||
import com.futo.platformplayer.fragment.mainactivity.topbar.SearchTopBarFragment
|
||||
import com.futo.platformplayer.listeners.OrientationManager
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.models.ImportCache
|
||||
import com.futo.platformplayer.models.UrlVideoWithTime
|
||||
import com.futo.platformplayer.states.*
|
||||
import com.futo.platformplayer.stores.FragmentedStorage
|
||||
|
@ -693,10 +694,22 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
|
|||
if(!recon.trim().startsWith("["))
|
||||
return handleUnknownJson(recon);
|
||||
|
||||
val reconLines = Json.decodeFromString<List<String>>(recon);
|
||||
var reconLines = Json.decodeFromString<List<String>>(recon);
|
||||
val cacheStr = reconLines.find { it.startsWith("__CACHE:") }?.substring("__CACHE:".length);
|
||||
reconLines = reconLines.filter { !it.startsWith("__CACHE:") }; //TODO: constant prefix
|
||||
var cache: ImportCache? = null;
|
||||
try {
|
||||
if(cacheStr != null)
|
||||
cache = Json.decodeFromString(cacheStr);
|
||||
}
|
||||
catch(ex: Throwable) {
|
||||
Logger.e(TAG, "Failed to deserialize cache");
|
||||
}
|
||||
|
||||
|
||||
recon = reconLines.joinToString("\n");
|
||||
Logger.i(TAG, "Opened shared playlist reconstruction\n${recon}");
|
||||
handleReconstruction(recon);
|
||||
handleReconstruction(recon, cache);
|
||||
return true;
|
||||
}
|
||||
else if(file.lowercase().endsWith(".zip") || mime == "application/zip") {
|
||||
|
@ -711,12 +724,25 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
|
|||
fun handleFile(file: String): Boolean {
|
||||
Logger.i(TAG, "handleFile(url=$file)");
|
||||
if(file.lowercase().endsWith(".json")) {
|
||||
val recon = String(readSharedFile(file));
|
||||
var recon = String(readSharedFile(file));
|
||||
if(!recon.startsWith("["))
|
||||
return handleUnknownJson(recon);
|
||||
|
||||
var reconLines = Json.decodeFromString<List<String>>(recon);
|
||||
val cacheStr = reconLines.find { it.startsWith("__CACHE:") }?.substring("__CACHE:".length);
|
||||
reconLines = reconLines.filter { !it.startsWith("__CACHE:") }; //TODO: constant prefix
|
||||
var cache: ImportCache? = null;
|
||||
try {
|
||||
if(cacheStr != null)
|
||||
cache = Json.decodeFromString(cacheStr);
|
||||
}
|
||||
catch(ex: Throwable) {
|
||||
Logger.e(TAG, "Failed to deserialize cache");
|
||||
}
|
||||
recon = reconLines.joinToString("\n");
|
||||
|
||||
Logger.i(TAG, "Opened shared playlist reconstruction\n${recon}");
|
||||
handleReconstruction(recon);
|
||||
handleReconstruction(recon, cache);
|
||||
return true;
|
||||
}
|
||||
else if(file.lowercase().endsWith(".zip")) {
|
||||
|
@ -728,7 +754,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
fun handleReconstruction(recon: String) {
|
||||
fun handleReconstruction(recon: String, cache: ImportCache? = null) {
|
||||
val type = ManagedStore.getReconstructionIdentifier(recon);
|
||||
val store: ManagedStore<*> = when(type) {
|
||||
"Playlist" -> StatePlaylists.instance.playlistStore
|
||||
|
@ -745,7 +771,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
|
|||
|
||||
|
||||
if(!type.isNullOrEmpty()) {
|
||||
UIDialogs.showImportDialog(this, store, name, listOf(recon)) {
|
||||
UIDialogs.showImportDialog(this, store, name, listOf(recon), cache) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,10 @@ class SerializedChannel(
|
|||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
fun isSameUrl(url: String): Boolean {
|
||||
return this.url == url || urlAlternatives.contains(url);
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromChannel(channel: IPlatformChannel): SerializedChannel {
|
||||
return SerializedChannel(
|
||||
|
|
|
@ -22,7 +22,9 @@ import com.futo.platformplayer.UIDialogs
|
|||
import com.futo.platformplayer.api.media.exceptions.NoPlatformClientException
|
||||
import com.futo.platformplayer.assume
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.models.ImportCache
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StateBackup
|
||||
import com.futo.platformplayer.stores.v2.ManagedStore
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -66,13 +68,15 @@ class ImportDialog : AlertDialog {
|
|||
private val _name: String;
|
||||
private val _toImport: List<String>;
|
||||
|
||||
private val _cache: ImportCache?;
|
||||
|
||||
constructor(context: Context, importStore: ManagedStore<*>, name: String, toReconstruct: List<String>, onConcluded: ()->Unit): super(context) {
|
||||
constructor(context: Context, importStore: ManagedStore<*>, name: String, toReconstruct: List<String>, cache: ImportCache?, onConcluded: ()->Unit): super(context) {
|
||||
_context = context;
|
||||
_store = importStore;
|
||||
_onConcluded = onConcluded;
|
||||
_name = name;
|
||||
_toImport = ArrayList(toReconstruct);
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -146,7 +150,7 @@ class ImportDialog : AlertDialog {
|
|||
val scope = StateApp.instance.scopeOrNull;
|
||||
scope?.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val migrationResult = _store.importReconstructions(_toImport) { finished, total ->
|
||||
val migrationResult = _store.importReconstructions(_toImport, _cache) { finished, total ->
|
||||
scope.launch(Dispatchers.Main) {
|
||||
_textProgress.text = "${finished}/${total}";
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ class HistoryVideo {
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun fromReconString(str: String, resolve: ((url: String)->SerializedPlatformVideo)? = null): HistoryVideo {
|
||||
fun fromReconString(str: String, resolve: ((url: String)->SerializedPlatformVideo?)? = null): HistoryVideo {
|
||||
var index = str.indexOf("|||");
|
||||
if(index < 0) throw IllegalArgumentException("Invalid history string: " + str);
|
||||
val url = str.substring(0, index);
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package com.futo.platformplayer.models
|
||||
|
||||
import com.futo.platformplayer.api.media.models.channels.SerializedChannel
|
||||
import com.futo.platformplayer.api.media.models.video.SerializedPlatformVideo
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
class ImportCache(
|
||||
var videos: List<SerializedPlatformVideo>? = null,
|
||||
var channels: List<SerializedChannel>? = null
|
||||
);
|
|
@ -10,6 +10,7 @@ import com.futo.platformplayer.UIDialogs
|
|||
import com.futo.platformplayer.activities.IWithResultLauncher
|
||||
import com.futo.platformplayer.activities.MainActivity
|
||||
import com.futo.platformplayer.activities.SettingsActivity
|
||||
import com.futo.platformplayer.api.media.models.channels.SerializedChannel
|
||||
import com.futo.platformplayer.api.media.models.video.SerializedPlatformVideo
|
||||
import com.futo.platformplayer.copyTo
|
||||
import com.futo.platformplayer.encryption.GPasswordEncryptionProvider
|
||||
|
@ -17,6 +18,7 @@ import com.futo.platformplayer.encryption.GPasswordEncryptionProviderV0
|
|||
import com.futo.platformplayer.fragment.mainactivity.main.ImportSubscriptionsFragment
|
||||
import com.futo.platformplayer.getNowDiffHours
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.models.ImportCache
|
||||
import com.futo.platformplayer.readBytes
|
||||
import com.futo.platformplayer.stores.FragmentedStorage
|
||||
import com.futo.platformplayer.stores.v2.ManagedStore
|
||||
|
@ -58,6 +60,19 @@ class StateBackup {
|
|||
StatePlaylists.instance.toMigrateCheck()
|
||||
).flatten();
|
||||
|
||||
fun getCache(): ImportCache {
|
||||
val allPlaylists = StatePlaylists.instance.getPlaylists();
|
||||
val videos = allPlaylists.flatMap { it.videos }.distinctBy { it.url };
|
||||
|
||||
val allSubscriptions = StateSubscriptions.instance.getSubscriptions();
|
||||
val channels = allSubscriptions.map { it.channel };
|
||||
|
||||
return ImportCache(
|
||||
videos = videos,
|
||||
channels = channels
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private fun getAutomaticBackupPassword(customPassword: String? = null): String {
|
||||
val password = customPassword ?: Settings.instance.backup.autoBackupPassword ?: "";
|
||||
|
@ -233,11 +248,10 @@ class StateBackup {
|
|||
.associateBy { it.config.id }
|
||||
.mapValues { it.value.config.sourceUrl!! };
|
||||
|
||||
val cache = getCache();
|
||||
|
||||
val export = ExportStructure(exportInfo, settings, storesToSave, pluginUrls, pluginSettings, cache);
|
||||
|
||||
val export = ExportStructure(exportInfo, settings, storesToSave, pluginUrls, pluginSettings);
|
||||
//export.videoCache = StatePlaylists.instance.getHistory()
|
||||
// .distinctBy { it.video.url }
|
||||
// .map { it.video };
|
||||
return export;
|
||||
}
|
||||
|
||||
|
@ -324,7 +338,7 @@ class StateBackup {
|
|||
continue;
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
UIDialogs.showImportDialog(context, relevantStore, store.key, store.value) {
|
||||
UIDialogs.showImportDialog(context, relevantStore, store.key, store.value, export.cache) {
|
||||
synchronized(toAwait) {
|
||||
toAwait.remove(store.key);
|
||||
if(toAwait.isEmpty())
|
||||
|
@ -453,8 +467,8 @@ class StateBackup {
|
|||
val stores: Map<String, List<String>>,
|
||||
val plugins: Map<String, String>,
|
||||
val pluginSettings: Map<String, Map<String, String?>>,
|
||||
var cache: ImportCache? = null
|
||||
) {
|
||||
var videoCache: List<SerializedPlatformVideo>? = null;
|
||||
|
||||
fun asZip(): ByteArray {
|
||||
return ByteArrayOutputStream().use { byteStream ->
|
||||
|
@ -478,6 +492,17 @@ class StateBackup {
|
|||
|
||||
zipStream.putNextEntry(ZipEntry("plugin_settings"));
|
||||
zipStream.write(Json.encodeToString(pluginSettings).toByteArray());
|
||||
|
||||
if(cache != null) {
|
||||
if(cache?.videos != null) {
|
||||
zipStream.putNextEntry(ZipEntry("cache_videos"));
|
||||
zipStream.write(Json.encodeToString(cache!!.videos).toByteArray());
|
||||
}
|
||||
if(cache?.channels != null) {
|
||||
zipStream.putNextEntry(ZipEntry("cache_channels"));
|
||||
zipStream.write(Json.encodeToString(cache!!.channels).toByteArray());
|
||||
}
|
||||
}
|
||||
};
|
||||
return byteStream.toByteArray();
|
||||
}
|
||||
|
@ -492,6 +517,8 @@ class StateBackup {
|
|||
val stores: MutableMap<String, List<String>> = mutableMapOf();
|
||||
var plugins: Map<String, String> = mapOf();
|
||||
var pluginSettings: Map<String, Map<String, String?>> = mapOf();
|
||||
var videoCache: List<SerializedPlatformVideo>? = null
|
||||
var channelCache: List<SerializedChannel>? = null
|
||||
|
||||
while (zipStream.nextEntry.also { entry = it } != null) {
|
||||
if(entry!!.isDirectory)
|
||||
|
@ -503,6 +530,22 @@ class StateBackup {
|
|||
"settings" -> settings = String(zipStream.readBytes());
|
||||
"plugins" -> plugins = Json.decodeFromString(String(zipStream.readBytes()));
|
||||
"plugin_settings" -> pluginSettings = Json.decodeFromString(String(zipStream.readBytes()));
|
||||
"cache_videos" -> {
|
||||
try {
|
||||
videoCache = Json.decodeFromString(String(zipStream.readBytes()));
|
||||
}
|
||||
catch(ex: Exception) {
|
||||
Logger.e(TAG, "Couldn't deserialize video cache", ex);
|
||||
}
|
||||
};
|
||||
"cache_channels" -> {
|
||||
try {
|
||||
channelCache = Json.decodeFromString(String(zipStream.readBytes()));
|
||||
}
|
||||
catch(ex: Exception) {
|
||||
Logger.e(TAG, "Couldn't deserialize channel cache", ex);
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
stores[entry!!.name.substring("stores/".length)] = Json.decodeFromString(String(zipStream.readBytes()));
|
||||
|
@ -511,7 +554,10 @@ class StateBackup {
|
|||
throw IllegalStateException("Failed to parse zip [${entry?.name}] due to ${ex.message}");
|
||||
}
|
||||
}
|
||||
return ExportStructure(exportInfo, settings, stores, plugins, pluginSettings);
|
||||
return ExportStructure(exportInfo, settings, stores, plugins, pluginSettings, ImportCache(
|
||||
videos = videoCache,
|
||||
channels = channelCache
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.futo.platformplayer.api.media.structures.IPager
|
|||
import com.futo.platformplayer.constructs.Event2
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.models.HistoryVideo
|
||||
import com.futo.platformplayer.models.ImportCache
|
||||
import com.futo.platformplayer.stores.FragmentedStorage
|
||||
import com.futo.platformplayer.stores.db.ManagedDBStore
|
||||
import com.futo.platformplayer.stores.db.types.DBHistory
|
||||
|
@ -20,8 +21,8 @@ class StateHistory {
|
|||
private val _historyStore = FragmentedStorage.storeJson<HistoryVideo>("history")
|
||||
.withRestore(object: ReconstructStore<HistoryVideo>() {
|
||||
override fun toReconstruction(obj: HistoryVideo): String = obj.toReconString();
|
||||
override suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder): HistoryVideo
|
||||
= HistoryVideo.fromReconString(backup, null);
|
||||
override suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder, cache: ImportCache?): HistoryVideo
|
||||
= HistoryVideo.fromReconString(backup) { url -> cache?.videos?.find { it.url == url } };
|
||||
})
|
||||
.load();
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.futo.platformplayer.constructs.Event0
|
|||
import com.futo.platformplayer.engine.exceptions.ScriptUnavailableException
|
||||
import com.futo.platformplayer.exceptions.ReconstructionException
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.models.ImportCache
|
||||
import com.futo.platformplayer.models.Playlist
|
||||
import com.futo.platformplayer.stores.FragmentedStorage
|
||||
import com.futo.platformplayer.stores.StringArrayStorage
|
||||
|
@ -32,8 +33,10 @@ class StatePlaylists {
|
|||
.withUnique { it.url }
|
||||
.withRestore(object: ReconstructStore<SerializedPlatformVideo>() {
|
||||
override fun toReconstruction(obj: SerializedPlatformVideo): String = obj.url;
|
||||
override suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder): SerializedPlatformVideo
|
||||
= SerializedPlatformVideo.fromVideo(StatePlatform.instance.getContentDetails(backup).await() as IPlatformVideoDetails);
|
||||
override suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder, importCache: ImportCache?): SerializedPlatformVideo
|
||||
= SerializedPlatformVideo.fromVideo(
|
||||
importCache?.videos?.find { it.url == backup }?.let { Logger.i(TAG, "Reconstruction [${backup}] from cache"); return@let it; } ?:
|
||||
StatePlatform.instance.getContentDetails(backup).await() as IPlatformVideoDetails);
|
||||
})
|
||||
.load();
|
||||
private val _watchlistOrderStore = FragmentedStorage.get<StringArrayStorage>("watchListOrder"); //Temporary workaround to add order..
|
||||
|
@ -154,7 +157,11 @@ class StatePlaylists {
|
|||
val reconstruction = playlistStore.getReconstructionString(playlist, true);
|
||||
|
||||
val newFile = File(playlistShareDir, playlist.name + ".json");
|
||||
newFile.writeText(Json.encodeToString(reconstruction.split("\n")), Charsets.UTF_8);
|
||||
newFile.writeText(Json.encodeToString(reconstruction.split("\n") + listOf(
|
||||
"__CACHE:" + Json.encodeToString(ImportCache(
|
||||
videos = playlist.videos.toList()
|
||||
))
|
||||
)), Charsets.UTF_8);
|
||||
|
||||
return FileProvider.getUriForFile(context, context.resources.getString(R.string.authority), newFile);
|
||||
}
|
||||
|
@ -185,7 +192,7 @@ class StatePlaylists {
|
|||
items.addAll(obj.videos.map { it.url });
|
||||
return items.map { it.replace("\n","") }.joinToString("\n");
|
||||
}
|
||||
override suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder): Playlist {
|
||||
override suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder, importCache: ImportCache?): Playlist {
|
||||
val items = backup.split("\n");
|
||||
if(items.size <= 0) {
|
||||
throw IllegalStateException("Cannot reconstructor playlist ${id}");
|
||||
|
@ -194,10 +201,17 @@ class StatePlaylists {
|
|||
val name = items[0];
|
||||
val videos = items.drop(1).filter { it.isNotEmpty() }.map {
|
||||
try {
|
||||
val video = StatePlatform.instance.getContentDetails(it).await();
|
||||
val videoUrl = it;
|
||||
val video = importCache?.videos?.find { it.url == videoUrl } ?:
|
||||
StatePlatform.instance.getContentDetails(it).await();
|
||||
if (video is IPlatformVideoDetails) {
|
||||
return@map SerializedPlatformVideo.fromVideo(video);
|
||||
} else {
|
||||
}
|
||||
else if(video is SerializedPlatformVideo) {
|
||||
Logger.i(TAG, "Reconstruction [${it}] from cache");
|
||||
return@map video;
|
||||
}
|
||||
else {
|
||||
return@map null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.futo.platformplayer.constructs.Event2
|
|||
import com.futo.platformplayer.constructs.Event3
|
||||
import com.futo.platformplayer.functional.CentralizedFeed
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.models.ImportCache
|
||||
import com.futo.platformplayer.models.Subscription
|
||||
import com.futo.platformplayer.models.SubscriptionGroup
|
||||
import com.futo.platformplayer.polycentric.PolycentricCache
|
||||
|
@ -38,8 +39,8 @@ class StateSubscriptions {
|
|||
.withRestore(object: ReconstructStore<Subscription>(){
|
||||
override fun toReconstruction(obj: Subscription): String =
|
||||
obj.channel.url;
|
||||
override suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder): Subscription =
|
||||
Subscription(SerializedChannel.fromChannel(StatePlatform.instance.getChannelLive(backup, false)));
|
||||
override suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder, importCache: ImportCache?): Subscription =
|
||||
Subscription(importCache?.channels?.find { it.isSameUrl(backup) } ?: SerializedChannel.fromChannel(StatePlatform.instance.getChannelLive(backup, false)));
|
||||
}).load();
|
||||
private val _subscriptionOthers = FragmentedStorage.storeJson<Subscription>("subscriptions_others")
|
||||
.withUnique { it.channel.url }
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.futo.platformplayer.stores.v2
|
|||
|
||||
import com.futo.platformplayer.assume
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.models.ImportCache
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -105,7 +106,7 @@ class ManagedStore<T>{
|
|||
_toReconstruct.clear();
|
||||
}
|
||||
}
|
||||
suspend fun importReconstructions(items: List<String>, onProgress: ((Int, Int)->Unit)? = null): ReconstructionResult {
|
||||
suspend fun importReconstructions(items: List<String>, cache: ImportCache? = null, onProgress: ((Int, Int)->Unit)? = null): ReconstructionResult {
|
||||
var successes = 0;
|
||||
val exs = ArrayList<Throwable>();
|
||||
|
||||
|
@ -120,7 +121,7 @@ class ManagedStore<T>{
|
|||
for (i in 0 .. 1) {
|
||||
try {
|
||||
Logger.i(TAG, "Importing ${logName(recon)}");
|
||||
val reconId = createFromReconstruction(recon, builder);
|
||||
val reconId = createFromReconstruction(recon, builder, cache);
|
||||
successes++;
|
||||
Logger.i(TAG, "Imported ${logName(reconId)}");
|
||||
break;
|
||||
|
@ -272,12 +273,12 @@ class ManagedStore<T>{
|
|||
save(obj, withReconstruction, onlyExisting);
|
||||
}
|
||||
|
||||
suspend fun createFromReconstruction(reconstruction: String, builder: ReconstructStore.Builder): String {
|
||||
suspend fun createFromReconstruction(reconstruction: String, builder: ReconstructStore.Builder, cache: ImportCache? = null): String {
|
||||
if(_reconstructStore == null)
|
||||
throw IllegalStateException("Can't reconstruct as no reconstruction is implemented for this type");
|
||||
|
||||
val id = UUID.randomUUID().toString();
|
||||
val reconstruct = _reconstructStore!!.toObjectWithHeader(id, reconstruction, builder);
|
||||
val reconstruct = _reconstructStore!!.toObjectWithHeader(id, reconstruction, builder, cache);
|
||||
save(reconstruct);
|
||||
return id;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.futo.platformplayer.stores.v2
|
||||
|
||||
import com.futo.platformplayer.models.ImportCache
|
||||
|
||||
abstract class ReconstructStore<T> {
|
||||
open val backupOnSave: Boolean = false;
|
||||
open val backupOnCreate: Boolean = true;
|
||||
|
@ -11,18 +13,18 @@ abstract class ReconstructStore<T> {
|
|||
}
|
||||
|
||||
abstract fun toReconstruction(obj: T): String;
|
||||
abstract suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder): T;
|
||||
abstract suspend fun toObject(id: String, backup: String, reconstructionBuilder: Builder, importCache: ImportCache? = null): T;
|
||||
|
||||
fun toReconstructionWithHeader(obj: T, fallbackName: String): String {
|
||||
val identifier = identifierName ?: fallbackName;
|
||||
return "@/${identifier}\n${toReconstruction(obj)}";
|
||||
}
|
||||
|
||||
suspend fun toObjectWithHeader(id: String, backup: String, builder: Builder): T {
|
||||
suspend fun toObjectWithHeader(id: String, backup: String, builder: Builder, importCache: ImportCache? = null): T {
|
||||
if(backup.startsWith("@/") && backup.contains("\n"))
|
||||
return toObject(id, backup.substring(backup.indexOf("\n") + 1), builder);
|
||||
return toObject(id, backup.substring(backup.indexOf("\n") + 1), builder, importCache);
|
||||
else
|
||||
return toObject(id, backup, builder);
|
||||
return toObject(id, backup, builder, importCache);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue