diff --git a/app/src/main/java/com/futo/platformplayer/UIDialogs.kt b/app/src/main/java/com/futo/platformplayer/UIDialogs.kt
index 7c975bf007b7cb63bdbbc32b78e56816cf32c2b1..e9421cdaa9ddb7ddd101a17f9184d6723a509a21 100644
--- a/app/src/main/java/com/futo/platformplayer/UIDialogs.kt
+++ b/app/src/main/java/com/futo/platformplayer/UIDialogs.kt
@@ -6,6 +6,7 @@ import android.content.Context
 import android.content.Intent
 import android.graphics.Color
 import android.net.Uri
+import android.text.Layout
 import android.text.method.ScrollingMovementMethod
 import android.util.TypedValue
 import android.view.Gravity
@@ -198,7 +199,6 @@ class UIDialogs {
             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);
@@ -214,18 +214,20 @@ class UIDialogs {
                 this.text = text;
             };
             view.findViewById<TextView>(R.id.dialog_text_details).apply {
-                if(textDetails == null)
+                if (textDetails == null)
                     this.visibility = View.GONE;
-                else
+                else {
                     this.text = textDetails;
+                    this.textAlignment = View.TEXT_ALIGNMENT_VIEW_START
+                }
             };
             view.findViewById<TextView>(R.id.dialog_text_code).apply {
-                if(code == null)
-                    this.visibility = View.GONE;
+                if (code == null) this.visibility = View.GONE;
                 else {
                     this.text = code;
                     this.movementMethod = ScrollingMovementMethod.getInstance();
                     this.visibility = View.VISIBLE;
+                    this.textAlignment = View.TEXT_ALIGNMENT_VIEW_START
                 }
             };
             view.findViewById<LinearLayout>(R.id.dialog_buttons).apply {
diff --git a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt
index e4efd6c658738744fb04f1ae2c395c44fa251eb8..06ca95783d41f5b662ef3a473cd93ea296a367cb 100644
--- a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt
+++ b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt
@@ -33,6 +33,7 @@ import com.futo.platformplayer.BuildConfig
 import com.futo.platformplayer.R
 import com.futo.platformplayer.Settings
 import com.futo.platformplayer.UIDialogs
+import com.futo.platformplayer.api.http.ManagedHttpClient
 import com.futo.platformplayer.casting.StateCasting
 import com.futo.platformplayer.constructs.Event1
 import com.futo.platformplayer.fragment.mainactivity.bottombar.MenuBottomBarFragment
@@ -88,6 +89,7 @@ import com.futo.polycentric.core.ApiMethods
 import com.google.gson.JsonParser
 import com.google.zxing.integration.android.IntentIntegrator
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
@@ -101,7 +103,9 @@ import java.lang.reflect.InvocationTargetException
 import java.util.LinkedList
 import java.util.Queue
 import java.util.concurrent.ConcurrentLinkedQueue
-
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.encodeToString
+import org.json.JSONArray
 
 class MainActivity : AppCompatActivity, IWithResultLauncher {
 
@@ -444,7 +448,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
         _fragSubGroupList.topBar = _fragTopBarAdd;
 
         _fragBrowser.topBar = _fragTopBarNavigation;
-        
+
         fragCurrent = _fragMainHome;
 
         val defaultTab = Settings.instance.tabs.mapNotNull {
@@ -507,14 +511,68 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
 
         //startActivity(Intent(this, TestActivity::class.java));
 
-        val sharedPreferences = getSharedPreferences("GrayjayFirstBoot", Context.MODE_PRIVATE)
-        val isFirstBoot = sharedPreferences.getBoolean("IsFirstBoot", true)
+        val sharedPreferencesFirstBoot = getSharedPreferences("GrayjayFirstBoot", Context.MODE_PRIVATE)
+        val isFirstBoot = sharedPreferencesFirstBoot.getBoolean("IsFirstBoot", true)
         if (isFirstBoot) {
             UIDialogs.showConfirmationDialog(this, getString(R.string.do_you_want_to_see_the_tutorials_you_can_find_them_at_any_time_through_the_more_button), {
                 navigate(_fragMainTutorial)
             })
 
-            sharedPreferences.edit().putBoolean("IsFirstBoot", false).apply()
+            sharedPreferencesFirstBoot.edit().putBoolean("IsFirstBoot", false).apply()
+        }
+
+        val sharedPreferencesSubmitSubscriptions =
+            getSharedPreferences("GrayjaySubmitSubscriptions", Context.MODE_PRIVATE)
+        val alreadyViewed = sharedPreferencesSubmitSubscriptions.getBoolean("AlreadyViewed", false)
+
+        @Serializable
+        data class CreatorInfo(val pluginId: String, val plugin: String, val id: String, val name: String, val url: String, val description: String, val subscribers: Long)
+
+        val subscriptions = StateSubscriptions.instance.getSubscriptions().map { original ->
+            CreatorInfo(
+                pluginId = original.channel.id.pluginId ?: "",
+                plugin = original.channel.id.platform,
+                id = original.channel.id.value ?: "",
+                name = original.channel.name,
+                url = original.channel.url,
+                description = original.channel.description ?: "",
+                subscribers = original.channel.subscribers,
+            )
+        }
+
+        val subscriptionsThreshold = 20
+
+        if (
+            !alreadyViewed
+            && StateApp.instance.getCurrentNetworkState() != StateApp.NetworkState.DISCONNECTED
+            && subscriptions.size >= subscriptionsThreshold
+        ) {
+            val json = Json.encodeToString(subscriptions)
+            UIDialogs.showDialog(
+                this,
+                R.drawable.ic_internet,
+                getString(R.string.donate_personal_subscriptions_list),
+                getString(R.string.donate_personal_subscriptions_list_description),
+                JSONArray(json).toString(4),
+                0,
+                UIDialogs.Action("Cancel", { }, UIDialogs.ActionStyle.NONE),
+                UIDialogs.Action("Upload", {
+                    GlobalScope.launch(Dispatchers.IO) {
+                        val url = "https://logs.grayjay.app/subscriptions"
+                        val client = ManagedHttpClient();
+                        val headers = hashMapOf(
+                            "Content-Type" to "application/json"
+                        )
+                        val response = client.post(url, json, headers)
+                        // if it failed retry one time
+                        if (!response.isOk) {
+                            client.post(url, json, headers)
+                        }
+                    }
+                }, UIDialogs.ActionStyle.PRIMARY)
+            )
+
+            sharedPreferencesSubmitSubscriptions.edit().putBoolean("AlreadyViewed", true).apply()
         }
     }
 
@@ -992,7 +1050,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
         Logger.i(TAG, "Navigate to $segment (parameter=$parameter, withHistory=$withHistory, isBack=$isBack)")
 
         if(segment != fragCurrent) {
-            
+
             if(segment is VideoDetailFragment) {
                 if(_fragContainerVideoDetail.visibility != View.VISIBLE)
                     _fragContainerVideoDetail.visibility = View.VISIBLE;
@@ -1004,8 +1062,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
                 segment.onShown(parameter, isBack);
                 return;
             }
-            
-            
+
             fragCurrent.onHide();
 
             if(segment.isMainView) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dbc73061076941ba483a0ab3488ee94d2dc07aa2..736e3130bea9b2e211a82d4853c9aea8d7c2d841 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -803,6 +803,8 @@
     <string name="scroll_to_top">Scroll to top</string>
     <string name="disable_battery_optimization">Disable Battery Optimization</string>
     <string name="click_to_go_to_battery_optimization_settings_disabling_battery_optimization_will_prevent_the_os_from_killing_media_sessions">Click to go to battery optimization settings. Disabling battery optimization will prevent the OS from killing media sessions.</string>
+    <string name="donate_personal_subscriptions_list">Donate Personal Subscriptions List</string>
+    <string name="donate_personal_subscriptions_list_description">\nWould you liked to donate your current creator subscriptions list to Grayjay?\n\nThe data will be handled according to the Grayjay privacy policy. That is the list will be anonymized and stored without any reference to whomever the list of creators belonged to.\n\nThe intention is for Grayjay and FUTO to use these data to build a cross platform creator recommendation system to make it easier to find new creators you might like from within Grayjay.\n\nThe following data will be uploaded:</string>
     <string-array name="home_screen_array">
         <item>Recommendations</item>
         <item>Subscriptions</item>