From d44df427277bd0f16a22433e2ed642099339342b Mon Sep 17 00:00:00 2001
From: Kelvin <kelvin@futo.org>
Date: Wed, 15 May 2024 21:26:44 +0200
Subject: [PATCH] Plugin auto-update support and prompting

---
 .../java/com/futo/platformplayer/UIDialogs.kt |  68 +++-
 .../activities/AddSourceActivity.kt           |   2 +-
 .../api/media/platforms/js/JSClient.kt        |   2 +
 .../media/platforms/js/SourcePluginConfig.kt  |  35 ++
 .../platforms/js/SourcePluginDescriptor.kt    |   4 +-
 .../dialogs/PluginUpdateDialog.kt             | 253 ++++++++++++++
 .../engine/packages/PackageHttp.kt            |   4 +-
 .../mainactivity/main/ChannelFragment.kt      |   2 +-
 .../main/ContentSearchResultsFragment.kt      |   2 +-
 .../main/CreatorSearchResultsFragment.kt      |   2 +-
 .../fragment/mainactivity/main/FeedView.kt    |   2 +-
 .../mainactivity/main/HistoryFragment.kt      |   2 +-
 .../mainactivity/main/HomeFragment.kt         |   4 +-
 .../mainactivity/main/PlaylistFragment.kt     |   2 +-
 .../main/PlaylistSearchResultsFragment.kt     |   2 +-
 .../mainactivity/main/PostDetailFragment.kt   |   2 +-
 .../main/SubscriptionsFeedFragment.kt         |   2 +-
 .../mainactivity/main/SuggestionsFragment.kt  |   2 +-
 .../mainactivity/main/VideoDetailView.kt      |   6 +-
 .../futo/platformplayer/states/StateApp.kt    |   8 +-
 .../platformplayer/states/StatePlatform.kt    |  60 ----
 .../platformplayer/states/StatePlugins.kt     | 108 ++++++
 .../views/adapters/DisabledSourceView.kt      |   3 +-
 .../views/adapters/EnabledSourceViewHolder.kt |   3 +-
 .../main/res/layout/dialog_plugin_update.xml  | 315 ++++++++++++++++++
 app/src/main/res/values/strings.xml           |   2 +
 .../assets/sources/test/TestConfig.json       |  24 --
 .../assets/sources/test/TestScript.js         |  45 ---
 .../unstable/assets/sources/test/odysee.png   | Bin 47198 -> 0 bytes
 app/src/unstable/assets/sources/youtube       |   2 +-
 30 files changed, 801 insertions(+), 167 deletions(-)
 create mode 100644 app/src/main/java/com/futo/platformplayer/dialogs/PluginUpdateDialog.kt
 create mode 100644 app/src/main/res/layout/dialog_plugin_update.xml
 delete mode 100644 app/src/unstable/assets/sources/test/TestConfig.json
 delete mode 100644 app/src/unstable/assets/sources/test/TestScript.js
 delete mode 100644 app/src/unstable/assets/sources/test/odysee.png

diff --git a/app/src/main/java/com/futo/platformplayer/UIDialogs.kt b/app/src/main/java/com/futo/platformplayer/UIDialogs.kt
index ec666462..c9169091 100644
--- a/app/src/main/java/com/futo/platformplayer/UIDialogs.kt
+++ b/app/src/main/java/com/futo/platformplayer/UIDialogs.kt
@@ -18,6 +18,7 @@ import android.widget.Toast
 import androidx.core.content.ContextCompat
 import com.futo.platformplayer.activities.MainActivity
 import com.futo.platformplayer.api.media.models.comments.IPlatformComment
+import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
 import com.futo.platformplayer.casting.StateCasting
 import com.futo.platformplayer.dialogs.AutoUpdateDialog
 import com.futo.platformplayer.dialogs.AutomaticBackupDialog
@@ -31,12 +32,17 @@ import com.futo.platformplayer.dialogs.ConnectedCastingDialog
 import com.futo.platformplayer.dialogs.ImportDialog
 import com.futo.platformplayer.dialogs.ImportOptionsDialog
 import com.futo.platformplayer.dialogs.MigrateDialog
+import com.futo.platformplayer.dialogs.PluginUpdateDialog
 import com.futo.platformplayer.dialogs.ProgressDialog
 import com.futo.platformplayer.engine.exceptions.PluginException
+import com.futo.platformplayer.fragment.mainactivity.main.MainFragment
+import com.futo.platformplayer.fragment.mainactivity.main.SourceDetailFragment
+import com.futo.platformplayer.fragment.mainactivity.main.VideoDetailFragment
 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.states.StatePlugins
 import com.futo.platformplayer.stores.v2.ManagedStore
 import com.futo.platformplayer.views.ToastView
 import kotlinx.coroutines.CoroutineScope
@@ -184,6 +190,14 @@ class UIDialogs {
             dialog.show();
         }
 
+        fun showPluginUpdateDialog(context: Context, oldConfig: SourcePluginConfig, newConfig: SourcePluginConfig) {
+            val dialog = PluginUpdateDialog(context, oldConfig, newConfig);
+            registerDialogOpened(dialog);
+            dialog.setOnDismissListener { registerDialogClosed(dialog) };
+            dialog.show();
+        }
+
+
         fun showDialog(context: Context, icon: Int, text: String, textDetails: String? = null, code: String? = null, defaultCloseAction: Int, vararg actions: Action) {
             val builder = AlertDialog.Builder(context);
             val view = LayoutInflater.from(context).inflate(R.layout.dialog_multi_button, null);
@@ -269,22 +283,48 @@ class UIDialogs {
                 }, UIDialogs.ActionStyle.PRIMARY)
             );
         }
-        fun showGeneralRetryErrorDialog(context: Context, msg: String, ex: Throwable? = null, retryAction: (() -> Unit)? = null, closeAction: (() -> Unit)? = null) {
+        fun showGeneralRetryErrorDialog(context: Context, msg: String, ex: Throwable? = null, retryAction: (() -> Unit)? = null, closeAction: (() -> Unit)? = null, mainFragment: MainFragment? = null) {
+            val pluginConfig = if(ex is PluginException) ex.config else null;
             val pluginInfo = if(ex is PluginException)
                 "\nPlugin [${ex.config.name}]" else "";
-            showDialog(context,
-                R.drawable.ic_error_pred,
-                "${msg}${pluginInfo}",
-                (if(ex != null ) "${ex.message}" else ""),
-                if(ex is PluginException) ex.code else null,
-                0,
-                UIDialogs.Action(context.getString(R.string.retry), {
-                    retryAction?.invoke();
-                }, UIDialogs.ActionStyle.PRIMARY),
-                UIDialogs.Action(context.getString(R.string.close), {
-                    closeAction?.invoke()
-                }, UIDialogs.ActionStyle.NONE)
-            );
+
+            var exMsg = if(ex != null ) "${ex.message}" else "";
+            if(pluginConfig != null && pluginConfig is SourcePluginConfig && StatePlugins.instance.hasUpdateAvailable(pluginConfig))
+                exMsg += "\n\nAn update is available"
+
+            if(mainFragment != null && pluginConfig != null && pluginConfig is SourcePluginConfig && StatePlugins.instance.hasUpdateAvailable(pluginConfig))
+                showDialog(context,
+                    R.drawable.ic_error_pred,
+                    "${msg}${pluginInfo}",
+                    exMsg,
+                    if(ex is PluginException) ex.code else null,
+                    1,
+                    UIDialogs.Action(context.getString(R.string.update), {
+                        mainFragment.navigate<SourceDetailFragment>(pluginConfig);
+                        if(mainFragment is VideoDetailFragment)
+                            mainFragment.minimizeVideoDetail();
+                    }, UIDialogs.ActionStyle.ACCENT),
+                    UIDialogs.Action(context.getString(R.string.close), {
+                        closeAction?.invoke()
+                    }, UIDialogs.ActionStyle.NONE),
+                    UIDialogs.Action(context.getString(R.string.retry), {
+                        retryAction?.invoke();
+                    }, UIDialogs.ActionStyle.PRIMARY)
+                );
+            else
+                showDialog(context,
+                    R.drawable.ic_error_pred,
+                    "${msg}${pluginInfo}",
+                    exMsg,
+                    if(ex is PluginException) ex.code else null,
+                    0,
+                    UIDialogs.Action(context.getString(R.string.close), {
+                        closeAction?.invoke()
+                    }, UIDialogs.ActionStyle.NONE),
+                    UIDialogs.Action(context.getString(R.string.retry), {
+                        retryAction?.invoke();
+                    }, UIDialogs.ActionStyle.PRIMARY)
+                );
         }
 
         fun showSingleButtonDialog(context: Context, icon: Int, text: String, buttonText: String, action: (() -> Unit)) {
diff --git a/app/src/main/java/com/futo/platformplayer/activities/AddSourceActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/AddSourceActivity.kt
index 85873d28..81be84ea 100644
--- a/app/src/main/java/com/futo/platformplayer/activities/AddSourceActivity.kt
+++ b/app/src/main/java/com/futo/platformplayer/activities/AddSourceActivity.kt
@@ -224,7 +224,7 @@ class AddSourceActivity : AppCompatActivity() {
         val isNew = !StatePlatform.instance.getAvailableClients().any { it.id == config.id };
         StatePlugins.instance.installPlugin(this, lifecycleScope, config, script) {
             if(it) {
-                StatePlatform.instance.clearUpdateAvailable(config)
+                StatePlugins.instance.clearUpdateAvailable(config)
                 if(isNew)
                     lifecycleScope.launch {
                         StatePlatform.instance.enableClient(listOf(config.id));
diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt
index 64ceb31a..0a3498bb 100644
--- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt
+++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt
@@ -46,6 +46,7 @@ import com.futo.platformplayer.constructs.Event2
 import com.futo.platformplayer.engine.V8Plugin
 import com.futo.platformplayer.engine.exceptions.PluginEngineException
 import com.futo.platformplayer.engine.exceptions.ScriptCaptchaRequiredException
+import com.futo.platformplayer.engine.exceptions.ScriptException
 import com.futo.platformplayer.engine.exceptions.ScriptImplementationException
 import com.futo.platformplayer.engine.exceptions.ScriptValidationException
 import com.futo.platformplayer.logging.Logger
@@ -56,6 +57,7 @@ import com.futo.platformplayer.states.StatePlatform
 import com.futo.platformplayer.states.StatePlugins
 import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
+import java.lang.Exception
 import java.time.OffsetDateTime
 import kotlin.reflect.full.findAnnotations
 import kotlin.reflect.jvm.kotlinFunction
diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginConfig.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginConfig.kt
index 30196913..e279fc0f 100644
--- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginConfig.kt
+++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginConfig.kt
@@ -80,6 +80,41 @@ class SourcePluginConfig(
         return _allowUrlsLowerVal!!;
     };
 
+    fun isLowRiskUpdate(oldScript: String, newConfig: SourcePluginConfig, newScript: String): Boolean{
+
+        //All urls should already be allowed
+        for(url in newConfig.allowUrls) {
+            if(!allowUrls.contains(url))
+                return false;
+        }
+        //All packages should already be allowed
+        for(pack in newConfig.packages) {
+            if(!packages.contains(pack))
+                return false;
+        }
+        //Developer Submit Url should be same or empty
+        if(!newConfig.developerSubmitUrl.isNullOrEmpty() && developerSubmitUrl != newConfig.developerSubmitUrl)
+            return false;
+
+        //Should have a public key
+        if(scriptPublicKey.isNullOrEmpty() || scriptSignature.isNullOrEmpty())
+            return false;
+
+        //Should be same public key
+        if(scriptPublicKey != newConfig.scriptPublicKey)
+            return false;
+
+        //Old signature should be valid
+        if(!validate(oldScript))
+            return false;
+
+        //New signature should be valid
+        if(!newConfig.validate(newScript))
+            return false;
+
+        return true;
+    }
+
     fun getWarnings(scriptToCheck: String? = null) : List<Pair<String,String>> {
         val list = mutableListOf<Pair<String,String>>();
 
diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginDescriptor.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginDescriptor.kt
index bea18399..add53131 100644
--- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginDescriptor.kt
+++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginDescriptor.kt
@@ -91,8 +91,10 @@ class SourcePluginDescriptor {
     @Serializable
     class AppPluginSettings {
 
-        @FormField(R.string.check_for_updates_setting, FieldForm.TOGGLE, R.string.check_for_updates_setting_description, 0)
+        @FormField(R.string.check_for_updates_setting, FieldForm.TOGGLE, R.string.check_for_updates_setting_description, -1)
         var checkForUpdates: Boolean = true;
+        @FormField(R.string.automatic_update_setting, FieldForm.TOGGLE, R.string.automatic_update_setting_description, 0)
+        var automaticUpdate: Boolean = false;
 
         @FormField(R.string.visibility, "group", R.string.enable_where_this_plugins_content_are_visible, 2)
         var tabEnabled = TabEnabled();
diff --git a/app/src/main/java/com/futo/platformplayer/dialogs/PluginUpdateDialog.kt b/app/src/main/java/com/futo/platformplayer/dialogs/PluginUpdateDialog.kt
new file mode 100644
index 00000000..b7109a81
--- /dev/null
+++ b/app/src/main/java/com/futo/platformplayer/dialogs/PluginUpdateDialog.kt
@@ -0,0 +1,253 @@
+package com.futo.platformplayer.dialogs
+
+import android.app.AlertDialog
+import android.content.Context
+import android.content.Intent
+import android.graphics.Color
+import android.graphics.drawable.Animatable
+import android.media.MediaCas.PluginDescriptor
+import android.net.Uri
+import android.os.Bundle
+import android.text.Spannable
+import android.text.SpannableString
+import android.text.method.ScrollingMovementMethod
+import android.text.style.ForegroundColorSpan
+import android.view.LayoutInflater
+import android.view.View
+import android.view.WindowManager
+import android.widget.Button
+import android.widget.FrameLayout
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.core.view.isVisible
+import com.bumptech.glide.Glide
+import com.futo.platformplayer.R
+import com.futo.platformplayer.UIDialogs
+import com.futo.platformplayer.activities.AddSourceActivity
+import com.futo.platformplayer.api.http.ManagedHttpClient
+import com.futo.platformplayer.api.media.exceptions.NoPlatformClientException
+import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
+import com.futo.platformplayer.api.media.platforms.js.SourcePluginDescriptor
+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.states.StatePlugins
+import com.futo.platformplayer.stores.v2.ManagedStore
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class PluginUpdateDialog : AlertDialog {
+    companion object {
+        private val TAG = "PluginUpdateDialog";
+    }
+    private val _context: Context;
+
+    private lateinit var _buttonCancel1: Button;
+    private lateinit var _buttonCancel2: Button;
+    private lateinit var _buttonUpdate: LinearLayout;
+
+    private lateinit var _buttonOk: LinearLayout;
+    private lateinit var _buttonInstall: LinearLayout;
+
+    private lateinit var _textPlugin: TextView;
+    private lateinit var _textProgres: TextView;
+    private lateinit var _textError: TextView;
+    private lateinit var _textResult: TextView;
+
+    private lateinit var _uiChoiceTop: FrameLayout;
+    private lateinit var _uiProgressTop: FrameLayout;
+    private lateinit var _uiRiskTop: FrameLayout;
+
+    private lateinit var _uiChoiceBot: LinearLayout;
+    private lateinit var _uiResultBot: LinearLayout;
+    private lateinit var _uiRiskBot: LinearLayout;
+    private lateinit var _uiProgressBot: LinearLayout;
+
+    private lateinit var _iconPlugin: ImageView;
+    private lateinit var _updateSpinner: ImageView;
+
+    private var _isUpdating = false;
+
+    private val _oldConfig: SourcePluginConfig;
+    private val _newConfig: SourcePluginConfig;
+
+
+    constructor(context: Context, oldConfig: SourcePluginConfig, newConfig: SourcePluginConfig): super(context) {
+        _context = context;
+        _oldConfig = oldConfig;
+        _newConfig = newConfig;
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState);
+        setContentView(LayoutInflater.from(context).inflate(R.layout.dialog_plugin_update, null));
+
+        _buttonCancel1 = findViewById(R.id.button_cancel_1);
+        _buttonCancel2 = findViewById(R.id.button_cancel_2);
+        _buttonUpdate = findViewById(R.id.button_update);
+
+        _buttonOk = findViewById(R.id.button_ok);
+        _buttonInstall = findViewById(R.id.button_install);
+
+        _textPlugin = findViewById(R.id.text_plugin);
+        _textProgres = findViewById(R.id.text_progress);
+        _textError = findViewById(R.id.text_error);
+        _textResult = findViewById(R.id.text_result);
+
+        _uiChoiceTop = findViewById(R.id.dialog_ui_choice_top);
+        _uiProgressTop = findViewById(R.id.dialog_ui_progress_top);
+        _uiRiskTop = findViewById(R.id.dialog_ui_risk_top);
+
+        _uiChoiceBot = findViewById(R.id.dialog_ui_bottom_choice);
+        _uiResultBot = findViewById(R.id.dialog_ui_bottom_result);
+        _uiRiskBot = findViewById(R.id.dialog_ui_bottom_risk);
+        _uiProgressBot = findViewById(R.id.dialog_ui_bottom_progress);
+
+        _updateSpinner = findViewById(R.id.update_spinner);
+        _iconPlugin = findViewById(R.id.icon_plugin);
+
+        _buttonCancel1.setOnClickListener {
+            dismiss();
+        };
+        _buttonCancel2.setOnClickListener {
+            dismiss();
+        };
+        _buttonUpdate.setOnClickListener {
+            if (_isUpdating)
+                return@setOnClickListener;
+            _isUpdating = true;
+            update();
+        };
+
+        Glide.with(_iconPlugin)
+            .load(_oldConfig.absoluteIconUrl)
+            .fallback(R.drawable.ic_sources)
+            .into(_iconPlugin);
+        _textPlugin.text = _oldConfig.name;
+
+        val descriptor = StatePlugins.instance.getPlugin(_oldConfig.id);
+        if(descriptor != null) {
+            if(descriptor.appSettings.automaticUpdate) {
+                if (_isUpdating)
+                    return;
+                _isUpdating = true;
+                update();
+            }
+        }
+    }
+
+    override fun dismiss() {
+        super.dismiss();
+    }
+
+    private fun update() {
+        _uiChoiceTop.visibility = View.GONE;
+        _uiRiskTop.visibility = View.GONE;
+        _uiChoiceBot.visibility = View.GONE;
+        _uiResultBot.visibility = View.GONE;
+        _uiRiskBot.visibility = View.GONE;
+        _uiProgressTop.visibility = View.VISIBLE;
+        _uiProgressBot.visibility = View.VISIBLE;
+
+        setCancelable(false);
+        setCanceledOnTouchOutside(false);
+
+        Logger.i(TAG, "Keep screen on set import")
+        window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+        _updateSpinner.drawable?.assume<Animatable>()?.start();
+
+        val scope = StateApp.instance.scopeOrNull;
+        scope?.launch(Dispatchers.IO) {
+            try {
+                val client = ManagedHttpClient();
+                val script = StatePlugins.instance.getScript(_oldConfig.id) ?: "";
+
+                val newScript = client.get(_newConfig.absoluteScriptUrl)?.body?.string();
+                if(newScript.isNullOrEmpty())
+                    throw IllegalStateException("No script found");
+
+                if(_oldConfig.isLowRiskUpdate(script, _newConfig, newScript)){
+
+                    StatePlugins.instance.installPluginBackground(context, StateApp.instance.scope, _newConfig, newScript,
+                        { text: String, progress: Double ->
+                            _textProgres.setText(text);
+                        },
+                        { ex ->
+                            if(ex == null) {
+                                StatePlugins.instance.clearUpdateAvailable(_newConfig);
+                                _iconPlugin.setImageResource(R.drawable.ic_check);
+                                _textError.visibility = View.GONE;
+                                _textResult.visibility = View.VISIBLE;
+                            }
+                            else {
+                                _iconPlugin.setImageResource(R.drawable.ic_error_pred);
+                                _textError.text = ex.message + "\n\nYou can retry inside the sources tab";
+                                _textError.visibility = View.VISIBLE;
+                                _textResult.visibility = View.GONE;
+                            }
+                            try {
+                                _buttonOk.setOnClickListener {
+                                    dismiss();
+                                }
+                                _uiProgressTop.visibility = View.GONE;
+                                _uiProgressBot.visibility = View.GONE;
+                                _uiChoiceTop.visibility = View.VISIBLE;
+                                _uiResultBot.visibility = View.VISIBLE;
+                            } catch (e: Throwable) {
+                                Logger.e(TAG, "Failed to update UI.", e)
+                            } finally {
+                                Logger.i(TAG, "Keep screen on unset update")
+                                window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+                            }
+                        });
+
+                }
+                else {
+                    withContext(Dispatchers.Main) {
+                        try {
+                            _buttonInstall.setOnClickListener {
+                                dismiss();
+
+                                val intent = Intent(_context, AddSourceActivity::class.java).apply {
+                                    data = Uri.parse(_newConfig.sourceUrl)
+                                };
+
+                                _context.startActivity(intent);
+                            }
+
+                            _uiProgressTop.visibility = View.GONE;
+                            _uiProgressBot.visibility = View.GONE;
+                            _uiRiskTop.visibility = View.VISIBLE;
+                            _uiRiskBot.visibility = View.VISIBLE;
+                        } catch (e: Throwable) {
+                            Logger.e(TAG, "Failed to update UI.", e)
+                        } finally {
+                            Logger.i(TAG, "Keep screen on unset update")
+                            window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+                        }
+                    }
+                }
+            } catch (e: Throwable) {
+                Logger.e(TAG, "Failed to update.", e);
+                withContext(Dispatchers.Main) {
+                    _buttonOk.setOnClickListener {
+                        dismiss();
+                    }
+                    _iconPlugin.setImageResource(R.drawable.ic_error_pred);
+                    _textResult.visibility = View.GONE;
+                    _uiProgressTop.visibility = View.GONE;
+                    _uiProgressBot.visibility = View.GONE;
+                    _uiChoiceTop.visibility = View.VISIBLE;
+                    _uiResultBot.visibility = View.VISIBLE;
+                    _textError.visibility = View.VISIBLE;
+                    _textError.text = e.message + "\n\nYou can retry inside the sources tab"
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt
index 937e2d23..b1b7f460 100644
--- a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt
+++ b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt
@@ -316,7 +316,7 @@ class PackageHttp: V8Package {
             return result
         }
 
-        /*private fun logRequest(method: String, url: String, headers: Map<String, String> = HashMap(), body: String?) {
+        private fun logRequest(method: String, url: String, headers: Map<String, String> = HashMap(), body: String?) {
             Logger.v(TAG) {
                 val stringBuilder = StringBuilder();
                 stringBuilder.appendLine("HTTP request (useAuth = )");
@@ -333,7 +333,7 @@ class PackageHttp: V8Package {
 
                 return@v stringBuilder.toString();
             };
-        }*/
+        }
 
         /*private fun logResponse(method: String, url: String, responseCode: Int? = null, responseHeaders: Map<String, List<String>> = HashMap(), responseBody: String? = null) {
             Logger.v(TAG) {
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ChannelFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ChannelFragment.kt
index 602620ad..3359119f 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ChannelFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ChannelFragment.kt
@@ -152,7 +152,7 @@ class ChannelFragment : MainFragment() {
                 }
                 .exception<Throwable> {
                     Logger.e(TAG, "Failed to load channel.", it);
-                    UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadChannel() });
+                    UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadChannel() }, null, fragment);
                 }
 
             val tabs: TabLayout = findViewById(R.id.tabs);
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentSearchResultsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentSearchResultsFragment.kt
index 82831686..f7a34777 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentSearchResultsFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentSearchResultsFragment.kt
@@ -99,7 +99,7 @@ class ContentSearchResultsFragment : MainFragment() {
             .success { loadedResult(it); }.exception<ScriptCaptchaRequiredException> {  }
             .exception<Throwable> {
                 Logger.w(TAG, "Failed to load results.", it);
-                UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults() });
+                UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults() }, null, fragment);
             }
 
             setPreviewsEnabled(Settings.instance.search.previewFeedItems);
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CreatorSearchResultsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CreatorSearchResultsFragment.kt
index eac18ba9..a7570846 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CreatorSearchResultsFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CreatorSearchResultsFragment.kt
@@ -60,7 +60,7 @@ class CreatorSearchResultsFragment : MainFragment() {
                 .exception<ScriptCaptchaRequiredException> {  }
                 .exception<Throwable> {
                     Logger.w(ChannelFragment.TAG, "Failed to load results.", it);
-                    UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults() });
+                    UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults() }, null, fragment);
                 }
         }
 
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/FeedView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/FeedView.kt
index 78459af4..7f0e1ccc 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/FeedView.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/FeedView.kt
@@ -144,7 +144,7 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
             Logger.w(TAG, "Failed to load next page.", it);
             UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_next_page), it, {
                 loadNextPage();
-            });
+            }, null, fragment);
             //UIDialogs.showDataRetryDialog(layoutInflater, it.message, { loadNextPage() });
         };
 
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HistoryFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HistoryFragment.kt
index fcbec07c..2da46620 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HistoryFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HistoryFragment.kt
@@ -174,7 +174,7 @@ class HistoryFragment : MainFragment() {
                 Logger.w(TAG, "Failed to load next page.", it);
                 UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_next_page), it, {
                     loadNextPage();
-                });
+                }, null, fragment);
             };
         }
 
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt
index 3e60c4eb..d0994783 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt
@@ -126,10 +126,10 @@ class HomeFragment : MainFragment() {
                 Logger.w(TAG, "Failed to load channel.", it);
                 UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_get_home), it, {
                     loadResults()
-                }) {
+                }, {
                     finishRefreshLayoutLoader();
                     setLoading(false);
-                };
+                }, fragment);
             };
 
             setPreviewsEnabled(Settings.instance.home.previewFeedItems);
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt
index ca7a57fe..d938e970 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt
@@ -146,7 +146,7 @@ class PlaylistFragment : MainFragment() {
                 .exception<Throwable> {
                     Logger.w(TAG, "Failed to load playlist.", it);
                     val c = context ?: return@exception;
-                    UIDialogs.showGeneralRetryErrorDialog(c, context.getString(R.string.failed_to_load_playlist), it, ::fetchPlaylist);
+                    UIDialogs.showGeneralRetryErrorDialog(c, context.getString(R.string.failed_to_load_playlist), it, ::fetchPlaylist, null, fragment);
                 };
         }
 
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistSearchResultsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistSearchResultsFragment.kt
index ec01bb80..7900ff16 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistSearchResultsFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistSearchResultsFragment.kt
@@ -69,7 +69,7 @@ class PlaylistSearchResultsFragment : MainFragment() {
                 .success { loadedResult(it); }
                 .exception<Throwable> {
                     Logger.w(ChannelFragment.TAG, "Failed to load results.", it);
-                    UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults() });
+                    UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults() }, null, fragment);
                 }
         }
 
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PostDetailFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PostDetailFragment.kt
index f149b675..22ad5e93 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PostDetailFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PostDetailFragment.kt
@@ -162,7 +162,7 @@ class PostDetailFragment : MainFragment {
             .success { setPostDetails(it) }
             .exception<Throwable> {
                 Logger.w(ChannelFragment.TAG, context.getString(R.string.failed_to_load_post), it);
-                UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_post), it, ::fetchPost);
+                UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_post), it, ::fetchPost, null, _fragment);
             } else TaskHandler(IPlatformPostDetails::class.java) { _fragment.lifecycleScope };
 
         private val _taskLoadPolycentricProfile = TaskHandler<PlatformID, PolycentricCache.CachedPolycentricProfile?>(StateApp.instance.scopeGetter, { PolycentricCache.instance.getProfileAsync(it) })
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt
index 3099638f..03d9a626 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt
@@ -262,7 +262,7 @@ class SubscriptionsFeedFragment : MainFragment() {
             .exception<Throwable> {
                 Logger.w(ChannelFragment.TAG, "Failed to load channel.", it);
                 if(it !is CancellationException)
-                    UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults(true) });
+                    UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults(true) }, null, fragment);
                 else {
                     finishRefreshLayoutLoader();
                     setLoading(false);
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SuggestionsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SuggestionsFragment.kt
index e5499062..2f7254dc 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SuggestionsFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SuggestionsFragment.kt
@@ -40,7 +40,7 @@ class SuggestionsFragment : MainFragment {
     .success { suggestions -> updateSuggestions(suggestions, false) }
     .exception<Throwable> {
         Logger.w(ChannelFragment.TAG, "Failed to load suggestions.", it);
-        UIDialogs.showGeneralRetryErrorDialog(requireContext(), it.message ?: "", it, { loadSuggestions() });
+        UIDialogs.showGeneralRetryErrorDialog(requireContext(), it.message ?: "", it, { loadSuggestions() }, null, this);
     };
 
     constructor(): super() {
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt
index 9017ebc4..6d0901e3 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt
@@ -2476,7 +2476,7 @@ class VideoDetailView : ConstraintLayout {
             Logger.w(TAG, "exception<ScriptImplementationException>", it)
 
             if (!nextVideo()) {
-                UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_video_scriptimplementationexception), it, ::fetchVideo);
+                UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_video_scriptimplementationexception), it, ::fetchVideo, null, fragment);
             } else {
                 StateAnnouncement.instance.registerAnnouncement(video?.id?.value + "_Q_INVALIDVIDEO", context.getString(R.string.invalid_video), context.getString(
                                     R.string.there_was_an_invalid_video_in_your_queue_videoname_by_authorname_playback_was_skipped).replace("{videoName}", video?.name ?: "").replace("{authorName}", video?.author?.name ?: ""), AnnouncementType.SESSION)
@@ -2512,7 +2512,7 @@ class VideoDetailView : ConstraintLayout {
                 _retryJob = null;
                 _liveTryJob?.cancel();
                 _liveTryJob = null;
-                UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_video_scriptexception), it, ::fetchVideo);
+                UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_video_scriptexception), it, ::fetchVideo, null, fragment);
             }
         }
         .exception<Throwable> {
@@ -2524,7 +2524,7 @@ class VideoDetailView : ConstraintLayout {
                 _retryJob = null;
                 _liveTryJob?.cancel();
                 _liveTryJob = null;
-                UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_video), it, ::fetchVideo);
+                UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_video), it, ::fetchVideo, null, fragment);
             }
         } else TaskHandler(IPlatformVideoDetails::class.java, {fragment.lifecycleScope});
 
diff --git a/app/src/main/java/com/futo/platformplayer/states/StateApp.kt b/app/src/main/java/com/futo/platformplayer/states/StateApp.kt
index 1142310c..7fd26d63 100644
--- a/app/src/main/java/com/futo/platformplayer/states/StateApp.kt
+++ b/app/src/main/java/com/futo/platformplayer/states/StateApp.kt
@@ -571,18 +571,22 @@ class StateApp {
         StateAnnouncement.instance.deleteAnnouncement("plugin-update")
 
         scopeOrNull?.launch(Dispatchers.IO) {
-            val updateAvailable = StatePlatform.instance.checkForUpdates()
+            val updateAvailable = StatePlugins.instance.checkForUpdates()
 
             withContext(Dispatchers.Main) {
                 if (updateAvailable.isNotEmpty()) {
                     UIDialogs.appToast(
                         ToastView.Toast(updateAvailable
-                            .map { " - " + it.name }
+                            .map { " - " + it.first.name }
                             .joinToString("\n"),
                             true,
                             null,
                             "Plugin updates available"
                         ));
+
+                    for(update in updateAvailable)
+                        if(StatePlatform.instance.isClientEnabled(update.first.id))
+                            UIDialogs.showPluginUpdateDialog(context, update.first, update.second);
                 }
             }
         }
diff --git a/app/src/main/java/com/futo/platformplayer/states/StatePlatform.kt b/app/src/main/java/com/futo/platformplayer/states/StatePlatform.kt
index 1a3132a3..0b03bab1 100644
--- a/app/src/main/java/com/futo/platformplayer/states/StatePlatform.kt
+++ b/app/src/main/java/com/futo/platformplayer/states/StatePlatform.kt
@@ -80,7 +80,6 @@ class StatePlatform {
     private val _clientsLock = Object();
     private val _availableClients : ArrayList<IPlatformClient> = ArrayList();
     private val _enabledClients : ArrayList<IPlatformClient> = ArrayList();
-    private var _updatesAvailableMap: HashSet<String> = hashSetOf();
 
     //ClientPools are used to isolate plugin usage of certain components from others
     //This prevents for example a background task like subscriptions from blocking a user from opening a video
@@ -925,66 +924,7 @@ class StatePlatform {
         }
     }
 
-    fun hasUpdateAvailable(c: SourcePluginConfig): Boolean {
-        val updatesAvailableMap = _updatesAvailableMap
-        synchronized(updatesAvailableMap) {
-            return updatesAvailableMap.contains(c.id)
-        }
-    }
-
-    suspend fun checkForUpdates(): List<SourcePluginConfig> = withContext(Dispatchers.IO) {
-        var configs = mutableListOf<SourcePluginConfig>()
-        val updatesAvailableFor = hashSetOf<String>()
-        for (availableClient in getAvailableClients().filter { it is JSClient && it.descriptor.appSettings.checkForUpdates }) {
-            if (availableClient !is JSClient) {
-                continue
-            }
-
-            if (checkForUpdates(availableClient.config)) {
-                configs.add(availableClient.config);
-                updatesAvailableFor.add(availableClient.config.id)
-            }
-        }
-
-        _updatesAvailableMap = updatesAvailableFor
-        return@withContext configs;
-    }
-
-    fun clearUpdateAvailable(c: SourcePluginConfig) {
-        val updatesAvailableMap = _updatesAvailableMap
-        synchronized(updatesAvailableMap) {
-            updatesAvailableMap.remove(c.id)
-        }
-    }
 
-    private suspend fun checkForUpdates(c: SourcePluginConfig): Boolean = withContext(Dispatchers.IO) {
-        val sourceUrl = c.sourceUrl ?: return@withContext false;
-
-        Logger.i(TAG, "Check for source updates '${c.name}'.");
-        try {
-            val client = ManagedHttpClient();
-            val response = client.get(sourceUrl);
-            Logger.i(TAG, "Downloading source config '$sourceUrl'.");
-
-            if (!response.isOk || response.body == null) {
-                return@withContext false;
-            }
-
-            val configJson = response.body.string();
-            Logger.i(TAG, "Downloaded source config ($sourceUrl):\n${configJson}");
-
-            val config = SourcePluginConfig.fromJson(configJson);
-            if (config.version <= c.version) {
-                return@withContext false;
-            }
-
-            Logger.i(TAG, "Update is available (config.version=${config.version}, source.config.version=${c.version}).");
-            return@withContext true;
-        } catch (e: Throwable) {
-            Logger.e(TAG, "Failed to check for updates.", e);
-            return@withContext false;
-        }
-    }
 
     companion object {
         private var _instance : StatePlatform? = null;
diff --git a/app/src/main/java/com/futo/platformplayer/states/StatePlugins.kt b/app/src/main/java/com/futo/platformplayer/states/StatePlugins.kt
index d0c2d8be..420a3721 100644
--- a/app/src/main/java/com/futo/platformplayer/states/StatePlugins.kt
+++ b/app/src/main/java/com/futo/platformplayer/states/StatePlugins.kt
@@ -43,6 +43,7 @@ class StatePlugins {
     private var _embeddedSourcesDefault: List<String>? = null
     private var _sourcesUnderConstruction: Map<String, ImageVariable>? = null
 
+    private var _updatesAvailableMap: HashSet<String> = hashSetOf();
 
     fun getPluginIconOrNull(id: String): ImageVariable? {
         if(iconsDir.hasIcon(id))
@@ -55,6 +56,70 @@ class StatePlugins {
             .load();
     }
 
+
+    suspend fun checkForUpdates(): List<Pair<SourcePluginConfig, SourcePluginConfig>> = withContext(Dispatchers.IO) {
+        var configs = mutableListOf<Pair<SourcePluginConfig, SourcePluginConfig>>()
+        val updatesAvailableFor = hashSetOf<String>()
+        for (availableClient in StatePlatform.instance.getAvailableClients().filter { it is JSClient && it.descriptor.appSettings.checkForUpdates }) {
+            if (availableClient !is JSClient) {
+                continue
+            }
+
+            val newConfig = checkForUpdates(availableClient.config);
+            if (newConfig != null) {
+                configs.add(Pair(availableClient.config, newConfig));
+                updatesAvailableFor.add(availableClient.config.id)
+            }
+        }
+
+        _updatesAvailableMap = updatesAvailableFor
+        return@withContext configs;
+    }
+    private suspend fun checkForUpdates(c: SourcePluginConfig): SourcePluginConfig? = withContext(Dispatchers.IO) {
+        val sourceUrl = c.sourceUrl ?: return@withContext null;
+
+        Logger.i(TAG, "Check for source updates '${c.name}'.");
+        try {
+            val client = ManagedHttpClient();
+            val response = client.get(sourceUrl);
+            Logger.i(TAG, "Downloading source config '$sourceUrl'.");
+
+            if (!response.isOk || response.body == null) {
+                return@withContext null;
+            }
+
+            val configJson = response.body.string();
+            Logger.i(TAG, "Downloaded source config ($sourceUrl):\n${configJson}");
+
+            val config = SourcePluginConfig.fromJson(configJson);
+            if (config.version <= c.version) {
+                return@withContext null;
+            }
+
+            Logger.i(TAG, "Update is available (config.version=${config.version}, source.config.version=${c.version}).");
+            return@withContext config;
+        } catch (e: Throwable) {
+            Logger.e(TAG, "Failed to check for updates.", e);
+            return@withContext null;
+        }
+    }
+    fun hasUpdateAvailable(c: SourcePluginConfig): Boolean {
+        val updatesAvailableMap = _updatesAvailableMap
+        synchronized(updatesAvailableMap) {
+            return updatesAvailableMap.contains(c.id)
+        }
+    }
+    fun clearUpdateAvailable(c: SourcePluginConfig) {
+        val updatesAvailableMap = _updatesAvailableMap
+        synchronized(updatesAvailableMap) {
+            updatesAvailableMap.remove(c.id)
+        }
+    }
+
+
+
+
+
     fun loginPlugin(context: Context, id: String, afterLogin: ()->Unit): Boolean {
         val descriptor = getPlugin(id) ?: return false;
         val config = descriptor.config;
@@ -353,6 +418,49 @@ class StatePlugins {
         else verifyCanInstall();
     }
 
+    fun installPluginBackground(context: Context, scope: CoroutineScope, config: SourcePluginConfig, script: String, onProgress: (text: String, progress: Double)->Unit, onConcluded: (ex: Throwable?)->Unit) {
+        scope.launch(Dispatchers.IO) {
+            val client = ManagedHttpClient();
+            try {
+                withContext(Dispatchers.Main) {
+                    onProgress.invoke("Validating script", 0.25);
+                }
+
+                val tempDescriptor = SourcePluginDescriptor(config);
+                val plugin = JSClient(context, tempDescriptor, null, script);
+                plugin.validate();
+
+                withContext(Dispatchers.Main) {
+                    onProgress.invoke("Downloading Icon", 0.5);
+                }
+
+                val icon = config.absoluteIconUrl?.let { absIconUrl ->
+                    withContext(Dispatchers.Main) {
+                        onProgress.invoke("Saving plugin", 0.75);
+                    }
+                    val iconResp = client.get(absIconUrl);
+                    if(iconResp.isOk)
+                        return@let iconResp.body?.byteStream()?.use { it.readBytes() };
+                    return@let null;
+                }
+                val installEx = StatePlugins.instance.createPlugin(config, script, icon, true);
+                if(installEx != null)
+                    throw installEx;
+                StatePlatform.instance.updateAvailableClients(context);
+
+                withContext(Dispatchers.Main) {
+                    onProgress.invoke("Finished", 1.0)
+                    onConcluded.invoke(null);
+                }
+            } catch (ex: Exception) {
+                Logger.e(TAG, ex.message ?: "null", ex);
+                withContext(Dispatchers.Main) {
+                    onConcluded.invoke(ex);
+                }
+            }
+        }
+    }
+
     fun getPlugin(id: String): SourcePluginDescriptor? {
         if(id == StateDeveloper.DEV_ID)
             throw IllegalStateException("Attempted to retrieve a persistent developer plugin, this is not allowed");
diff --git a/app/src/main/java/com/futo/platformplayer/views/adapters/DisabledSourceView.kt b/app/src/main/java/com/futo/platformplayer/views/adapters/DisabledSourceView.kt
index a7194ae7..b2768d5e 100644
--- a/app/src/main/java/com/futo/platformplayer/views/adapters/DisabledSourceView.kt
+++ b/app/src/main/java/com/futo/platformplayer/views/adapters/DisabledSourceView.kt
@@ -10,6 +10,7 @@ import com.futo.platformplayer.api.media.platforms.js.JSClient
 import com.futo.platformplayer.constructs.Event0
 import com.futo.platformplayer.constructs.Event1
 import com.futo.platformplayer.states.StatePlatform
+import com.futo.platformplayer.states.StatePlugins
 
 class DisabledSourceView : LinearLayout {
     private val _root: LinearLayout;
@@ -37,7 +38,7 @@ class DisabledSourceView : LinearLayout {
 
         _textSource.text = client.name;
 
-        if (client is JSClient && StatePlatform.instance.hasUpdateAvailable(client.config)) {
+        if (client is JSClient && StatePlugins.instance.hasUpdateAvailable(client.config)) {
             _textSourceSubtitle.text = context.getString(R.string.update_available_exclamation)
             _textSourceSubtitle.setTextColor(context.getColor(R.color.light_blue_400))
             _textSourceSubtitle.typeface = resources.getFont(R.font.inter_regular)
diff --git a/app/src/main/java/com/futo/platformplayer/views/adapters/EnabledSourceViewHolder.kt b/app/src/main/java/com/futo/platformplayer/views/adapters/EnabledSourceViewHolder.kt
index 9eed743b..d2cc258b 100644
--- a/app/src/main/java/com/futo/platformplayer/views/adapters/EnabledSourceViewHolder.kt
+++ b/app/src/main/java/com/futo/platformplayer/views/adapters/EnabledSourceViewHolder.kt
@@ -13,6 +13,7 @@ import com.futo.platformplayer.api.media.IPlatformClient
 import com.futo.platformplayer.api.media.platforms.js.JSClient
 import com.futo.platformplayer.constructs.Event1
 import com.futo.platformplayer.states.StatePlatform
+import com.futo.platformplayer.states.StatePlugins
 
 class EnabledSourceViewHolder : ViewHolder {
     private val _imageSource: ImageView;
@@ -61,7 +62,7 @@ class EnabledSourceViewHolder : ViewHolder {
 
         _textSource.text = client.name
 
-        if (client is JSClient && StatePlatform.instance.hasUpdateAvailable(client.config)) {
+        if (client is JSClient && StatePlugins.instance.hasUpdateAvailable(client.config)) {
             _textSourceSubtitle.text = itemView.context.getString(R.string.update_available_exclamation)
             _textSourceSubtitle.setTextColor(itemView.context.getColor(R.color.light_blue_400))
             _textSourceSubtitle.typeface = itemView.resources.getFont(R.font.inter_regular)
diff --git a/app/src/main/res/layout/dialog_plugin_update.xml b/app/src/main/res/layout/dialog_plugin_update.xml
new file mode 100644
index 00000000..7c89e8bc
--- /dev/null
+++ b/app/src/main/res/layout/dialog_plugin_update.xml
@@ -0,0 +1,315 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center"
+    android:background="@color/gray_1d">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:gravity="center"
+        android:paddingTop="30dp"
+        android:paddingBottom="30dp">
+
+        <FrameLayout
+            android:id="@+id/dialog_ui_choice_top"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="visible">
+            <ImageView
+                android:id="@+id/icon_plugin"
+                android:layout_width="100dp"
+                android:layout_height="100dp"
+                app:srcCompat="@drawable/ic_sources" />
+
+        </FrameLayout>
+        <FrameLayout
+            android:id="@+id/dialog_ui_risk_top"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="gone">
+            <ImageView
+                android:layout_width="100dp"
+                android:layout_height="100dp"
+                app:srcCompat="@drawable/ic_warning_yellow" />
+
+        </FrameLayout>
+        <FrameLayout
+            android:id="@+id/dialog_ui_progress_top"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="gone">
+
+            <ImageView
+                android:id="@+id/update_spinner"
+                android:layout_width="100dp"
+                android:layout_height="100dp"
+                app:srcCompat="@drawable/ic_update_animated"
+                android:visibility="visible" />
+
+        </FrameLayout>
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Plugin Update"
+            android:textSize="15sp"
+            android:textColor="@color/white"
+            android:fontFamily="@font/inter_extra_light"
+            android:layout_marginTop="15dp"
+            android:layout_marginStart="30dp"
+            android:layout_marginEnd="30dp" />
+        <TextView
+            android:id="@+id/text_plugin"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Some Plugin Name"
+            android:textSize="18sp"
+            android:textColor="@color/white"
+            android:fontFamily="@font/inter_regular"
+            android:layout_marginStart="30dp"
+            android:layout_marginEnd="30dp" />
+
+        <LinearLayout
+            android:id="@+id/dialog_ui_bottom_choice"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="visible"
+            android:orientation="vertical">
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="center"
+                android:text="A new update is available.\nWould you like to update this plugin?"
+                android:textSize="14sp"
+                android:textColor="@color/white"
+                android:fontFamily="@font/inter_regular"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="30dp"
+                android:layout_marginEnd="30dp" />
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="center"
+                android:text="Updates may be critical to functionality"
+                android:textSize="13sp"
+                android:textColor="@color/pastel_red"
+                android:fontFamily="@font/inter_regular"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="30dp"
+                android:layout_marginEnd="30dp" />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                android:gravity="center"
+                android:layout_marginTop="28dp">
+
+                <Space
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1" />
+
+                <Button
+                    android:id="@+id/button_cancel_1"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/cancel"
+                    android:textSize="14dp"
+                    android:fontFamily="@font/inter_regular"
+                    android:textColor="@color/colorPrimary"
+                    android:background="@color/transparent" />
+
+                <LinearLayout
+                    android:id="@+id/button_update"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:background="@drawable/background_button_primary"
+                    android:layout_marginEnd="28dp"
+                    android:clickable="true">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="Update"
+                        android:textSize="14dp"
+                        android:textColor="@color/white"
+                        android:fontFamily="@font/inter_regular"
+                        android:paddingTop="10dp"
+                        android:paddingBottom="10dp"
+                        android:paddingStart="28dp"
+                        android:paddingEnd="28dp"/>
+                </LinearLayout>
+            </LinearLayout>
+        </LinearLayout>
+        <LinearLayout
+            android:id="@+id/dialog_ui_bottom_progress"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            android:orientation="vertical">
+            <TextView
+                android:layout_width="match_parent"
+                android:id="@+id/text_progress"
+                android:layout_height="wrap_content"
+                android:textAlignment="center"
+                android:text="This plugin has modified its permissions"
+                android:textSize="14sp"
+                android:textColor="@color/white"
+                android:fontFamily="@font/inter_regular"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="30dp"
+                android:layout_marginEnd="30dp" />
+
+        </LinearLayout>
+        <LinearLayout
+            android:id="@+id/dialog_ui_bottom_risk"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            android:orientation="vertical">
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="center"
+                android:text="This plugin has modified its permissions"
+                android:textSize="14sp"
+                android:textColor="@color/white"
+                android:fontFamily="@font/inter_regular"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="30dp"
+                android:layout_marginEnd="30dp" />
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="center"
+                android:text="Make sure you read the installation screen"
+                android:textSize="13sp"
+                android:textColor="@color/pastel_red"
+                android:fontFamily="@font/inter_regular"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="30dp"
+                android:layout_marginEnd="30dp" />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                android:gravity="center"
+                android:layout_marginTop="28dp">
+
+                <Space
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1" />
+
+                <Button
+                    android:id="@+id/button_cancel_2"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/cancel"
+                    android:textSize="14dp"
+                    android:fontFamily="@font/inter_regular"
+                    android:textColor="@color/colorPrimary"
+                    android:background="@color/transparent" />
+
+                <LinearLayout
+                    android:id="@+id/button_install"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:background="@drawable/background_button_primary"
+                    android:layout_marginEnd="28dp"
+                    android:clickable="true">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="Reinstall"
+                        android:textSize="14dp"
+                        android:textColor="@color/white"
+                        android:fontFamily="@font/inter_regular"
+                        android:paddingTop="10dp"
+                        android:paddingBottom="10dp"
+                        android:paddingStart="28dp"
+                        android:paddingEnd="28dp"/>
+                </LinearLayout>
+            </LinearLayout>
+        </LinearLayout>
+        <LinearLayout
+            android:id="@+id/dialog_ui_bottom_result"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            android:orientation="vertical">
+            <TextView
+                android:id="@+id/text_error"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="center"
+                android:text=""
+                android:textSize="13sp"
+                android:textColor="@color/pastel_red"
+                android:fontFamily="@font/inter_regular"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="30dp"
+                android:layout_marginEnd="30dp" />
+
+            <TextView
+                android:id="@+id/text_result"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="center"
+                android:text="Succesfully updated plugin."
+                android:textSize="13sp"
+                android:textColor="@color/white"
+                android:fontFamily="@font/inter_regular"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="30dp"
+                android:layout_marginEnd="30dp" />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                android:gravity="center"
+                android:layout_marginTop="28dp">
+
+                <Space
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1" />
+
+                <LinearLayout
+                    android:id="@+id/button_ok"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:background="@drawable/background_button_primary"
+                    android:layout_marginEnd="28dp"
+                    android:clickable="true">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="Ok"
+                        android:textSize="14dp"
+                        android:textColor="@color/white"
+                        android:fontFamily="@font/inter_regular"
+                        android:paddingTop="10dp"
+                        android:paddingBottom="10dp"
+                        android:paddingStart="28dp"
+                        android:paddingEnd="28dp"/>
+                </LinearLayout>
+            </LinearLayout>
+        </LinearLayout>
+
+
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index caf59143..786fbd99 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -489,6 +489,8 @@
     <string name="visibility">Visibility</string>
     <string name="check_for_updates_setting">Check for updates</string>
     <string name="check_for_updates_setting_description">If a plugin should be checked for updates on startup</string>
+    <string name="automatic_update_setting">Automatic Update</string>
+    <string name="automatic_update_setting_description">Update automatically on boot if no permissions changed and plugin is enabled</string>
     <string name="allow_developer_submit">Allow Developer Submissions</string>
     <string name="allow_developer_submit_description">Allows the developer to send data to their server, be careful as this might include sensitive data.</string>
     <string name="allow_developer_submit_warning">Make sure you trust the developer. They may gain access to sensitive data. Only enable this when you are trying to help the developer fix a bug.</string>
diff --git a/app/src/unstable/assets/sources/test/TestConfig.json b/app/src/unstable/assets/sources/test/TestConfig.json
deleted file mode 100644
index 86eed6ee..00000000
--- a/app/src/unstable/assets/sources/test/TestConfig.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-	"name": "Testing",
-	"description": "Just for testing.",
-	"author": "FUTO",
-	"authorUrl": "https://futo.org",
-
-	"platformUrl": "https://odysee.com",
-	"sourceUrl": "https://plugins.grayjay.app/Test/TestConfig.json",
-	"repositoryUrl": "https://futo.org",
-	"scriptUrl": "./TestScript.js",
-	"version": 31,
-	
-	"iconUrl": "./odysee.png",
-	"id": "1c05bfc3-08b9-42d0-93d3-6d52e0fd34d8",
-	
-	"scriptSignature": "",
-	"scriptPublicKey": "",
-	"packages": ["Http"],
-	
-	"allowEval": false,
-	"allowUrls": [],
-
-	"supportedClaimTypes": []
-}
diff --git a/app/src/unstable/assets/sources/test/TestScript.js b/app/src/unstable/assets/sources/test/TestScript.js
deleted file mode 100644
index 45c47d8f..00000000
--- a/app/src/unstable/assets/sources/test/TestScript.js
+++ /dev/null
@@ -1,45 +0,0 @@
-var config = {};
-
-//Source Methods
-source.enable = function(conf){
-	config = conf ?? {};
-	//log(config);
-}
-source.getHome = function() {
-    return new ContentPager([
-        source.getContentDetails("whatever")
-    ]);
-};
-
-//Video
-source.isContentDetailsUrl = function(url) {
-	return REGEX_DETAILS_URL.test(url)
-};
-source.getContentDetails = function(url) {
-	return new PlatformVideoDetails({
-		id: new PlatformID("Test", "Something", config.id),
-		name: "Test Video",
-		thumbnails: new Thumbnails([]),
-		author: new PlatformAuthorLink(new PlatformID("Test", "TestID", config.id),
-			"TestAuthor",
-			"None",
-			""),
-		datetime: parseInt(new Date().getTime() / 1000),
-		duration: 0,
-		viewCount: 0,
-		url: "",
-		isLive: false,
-		description: "",
-		rating: new RatingLikes(0),
-		video: new VideoSourceDescriptor([
-			new HLSSource({
-				name: "HLS",
-				url: "",
-				duration: 0,
-				priority: true
-			})
-		])
-	});
-};
-
-log("LOADED");
\ No newline at end of file
diff --git a/app/src/unstable/assets/sources/test/odysee.png b/app/src/unstable/assets/sources/test/odysee.png
deleted file mode 100644
index 472960d00a49401c1d97199ff6fa90cc337bd9bc..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 47198
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

diff --git a/app/src/unstable/assets/sources/youtube b/app/src/unstable/assets/sources/youtube
index cac27408..d1058f0b 160000
--- a/app/src/unstable/assets/sources/youtube
+++ b/app/src/unstable/assets/sources/youtube
@@ -1 +1 @@
-Subproject commit cac27408440f5586c1c68d846456792041403d35
+Subproject commit d1058f0b6ccf8cbebe4eed2afba145899e6dba00
-- 
GitLab