Import dialog

This commit is contained in:
Kelvin 2023-12-04 22:18:07 +01:00
parent c9d5508018
commit 7ee4f411cb
11 changed files with 321 additions and 145 deletions

View file

@ -23,6 +23,7 @@ import com.futo.platformplayer.views.fields.FormField
import com.futo.platformplayer.views.fields.FieldForm
import com.futo.platformplayer.views.fields.FormFieldButton
import com.futo.platformplayer.views.fields.FormFieldWarning
import com.futo.platformplayer.views.overlays.slideup.SlideUpMenuItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -30,7 +31,6 @@ import kotlinx.serialization.*
import kotlinx.serialization.json.*
import java.io.File
import java.time.OffsetDateTime
import java.util.Locale
@Serializable
data class MenuBottomBarSetting(val id: Int, var enabled: Boolean);
@ -45,7 +45,7 @@ class Settings : FragmentedStorageFileJson() {
@Transient
val onTabsChanged = Event0();
@FormField(R.string.manage_polycentric_identity, FieldForm.BUTTON, R.string.manage_your_polycentric_identity, -5)
@FormField(R.string.manage_polycentric_identity, FieldForm.BUTTON, R.string.manage_your_polycentric_identity, -6)
@FormFieldButton(R.drawable.ic_person)
fun managePolycentricIdentity() {
SettingsActivity.getActivity()?.let {
@ -57,7 +57,7 @@ class Settings : FragmentedStorageFileJson() {
}
}
@FormField(R.string.show_faq, FieldForm.BUTTON, R.string.get_answers_to_common_questions, -4)
@FormField(R.string.show_faq, FieldForm.BUTTON, R.string.get_answers_to_common_questions, -5)
@FormFieldButton(R.drawable.ic_quiz)
fun openFAQ() {
try {
@ -67,7 +67,7 @@ class Settings : FragmentedStorageFileJson() {
//Ignored
}
}
@FormField(R.string.show_issues, FieldForm.BUTTON, R.string.a_list_of_user_reported_and_self_reported_issues, -3)
@FormField(R.string.show_issues, FieldForm.BUTTON, R.string.a_list_of_user_reported_and_self_reported_issues, -4)
@FormFieldButton(R.drawable.ic_data_alert)
fun openIssues() {
try {
@ -99,7 +99,7 @@ class Settings : FragmentedStorageFileJson() {
}
}*/
@FormField(R.string.manage_tabs, FieldForm.BUTTON, R.string.change_tabs_visible_on_the_home_screen, -2)
@FormField(R.string.manage_tabs, FieldForm.BUTTON, R.string.change_tabs_visible_on_the_home_screen, -3)
@FormFieldButton(R.drawable.ic_tabs)
fun manageTabs() {
try {
@ -111,6 +111,17 @@ class Settings : FragmentedStorageFileJson() {
}
}
@FormField(R.string.import_data, FieldForm.BUTTON, R.string.import_data_description, -2)
@FormFieldButton(R.drawable.ic_move_up)
fun import() {
val act = SettingsActivity.getActivity() ?: return;
val intent = MainActivity.getImportOptionsIntent(act);
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK;
act.startActivity(intent);
}
@FormField(R.string.link_handling, FieldForm.BUTTON, R.string.allow_grayjay_to_handle_links, -1)
@FormFieldButton(R.drawable.ic_link)
fun manageLinks() {
@ -709,25 +720,16 @@ class Settings : FragmentedStorageFileJson() {
@FormField(R.string.export_data, FieldForm.BUTTON, R.string.creates_a_zip_file_with_your_data_which_can_be_imported_by_opening_it_with_grayjay, 3)
fun export() {
StateBackup.startExternalBackup();
val activity = SettingsActivity.getActivity() ?: return;
UISlideOverlays.showOverlay(activity.overlay, "Select export type", null, {},
SlideUpMenuItem(activity, R.drawable.ic_share, "Share", "", null, {
StateBackup.shareExternalBackup();
}),
SlideUpMenuItem(activity, R.drawable.ic_download, "File", "", null, {
StateBackup.saveExternalBackup(activity);
})
)
}
/*
@FormField(R.string.import_data, FieldForm.BUTTON, R.string.import_data_description, 4)
fun import() {
val act = SettingsActivity.getActivity() ?: return;
StateApp.instance.requestFileReadAccess(act, null) {
if(it != null && it.exists()) {
val name = it.name;
val contents = it.readBytes(act);
if(contents != null) {
if(name != null && name.endsWith(".zip", true))
StateBackup.importZipBytes(act, act.lifecycleScope, contents);
}
}
}
}*/
}
@FormField(R.string.payment, FieldForm.GROUP, -1, 17)

View file

@ -13,6 +13,7 @@ import android.view.View
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.*
import androidx.core.content.ContextCompat
import com.futo.platformplayer.activities.MainActivity
import com.futo.platformplayer.api.media.models.comments.IPlatformComment
import com.futo.platformplayer.casting.StateCasting
import com.futo.platformplayer.dialogs.*
@ -326,6 +327,12 @@ class UIDialogs {
dialog.setOnDismissListener { registerDialogClosed(dialog) };
dialog.show();
}
fun showImportOptionsDialog(context: MainActivity) {
val dialog = ImportOptionsDialog(context);
registerDialogOpened(dialog);
dialog.setOnDismissListener { registerDialogClosed(dialog) };
dialog.show();
}
fun showCastingDialog(context: Context) {

View file

@ -1,30 +1,21 @@
package com.futo.platformplayer
import android.content.ContentResolver
import android.graphics.Color
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.TextView
import com.futo.platformplayer.api.http.ManagedHttpClient
import com.futo.platformplayer.api.media.models.ResultCapabilities
import com.futo.platformplayer.api.media.models.streams.VideoUnMuxedSourceDescriptor
import com.futo.platformplayer.api.media.models.streams.sources.HLSVariantAudioUrlSource
import com.futo.platformplayer.api.media.models.streams.sources.HLSVariantSubtitleUrlSource
import com.futo.platformplayer.api.media.models.streams.sources.HLSVariantVideoUrlSource
import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlSource
import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestAudioSource
import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestSource
import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource
import com.futo.platformplayer.api.media.models.streams.sources.SubtitleRawSource
import com.futo.platformplayer.api.media.models.subtitles.ISubtitleSource
import com.futo.platformplayer.api.media.models.video.IPlatformVideo
import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails
import com.futo.platformplayer.api.media.models.video.SerializedPlatformVideo
import com.futo.platformplayer.casting.StateCasting
import com.futo.platformplayer.downloads.VideoLocal
import com.futo.platformplayer.helpers.VideoHelper
import com.futo.platformplayer.logging.Logger
@ -40,12 +31,10 @@ import com.futo.platformplayer.views.pills.RoundButton
import com.futo.platformplayer.views.pills.RoundButtonGroup
import com.futo.platformplayer.views.overlays.slideup.*
import com.futo.platformplayer.views.video.FutoVideoPlayerBase
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.internal.notifyAll
import java.lang.IllegalStateException
class UISlideOverlays {

View file

@ -515,6 +515,9 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
val url = intent.getStringExtra("VIDEO");
navigate(_fragVideoDetail, url);
}
"IMPORT_OPTIONS" -> {
UIDialogs.showImportOptionsDialog(this);
}
"TAB" -> {
when(intent.getStringExtra("TAB")){
"Sources" -> {
@ -730,18 +733,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
if (!newPipeSubsParsed.has("subscriptions") || !newPipeSubsParsed["subscriptions"].isJsonArray)
return false;//throw IllegalArgumentException("Invalid NewPipe json structure found");
val jsonSubs = newPipeSubsParsed["subscriptions"]
val jsonSubsArray = jsonSubs.asJsonArray;
val jsonSubsArrayItt = jsonSubsArray.iterator();
val subs = mutableListOf<String>()
while(jsonSubsArrayItt.hasNext()) {
val jsonSubObj = jsonSubsArrayItt.next().asJsonObject;
if(jsonSubObj.has("url"))
subs.add(jsonSubObj["url"].asString);
}
navigate(_fragImportSubscriptions, subs);
StateBackup.importNewPipeSubs(this, newPipeSubsParsed);
}
catch(ex: Exception) {
Logger.e(TAG, ex.message, ex);
@ -1054,5 +1046,12 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return sourcesIntent;
}
fun getImportOptionsIntent(context: Context): Intent {
val sourcesIntent = Intent(context, MainActivity::class.java);
sourcesIntent.action = "IMPORT_OPTIONS";
sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return sourcesIntent;
}
}
}

View file

@ -5,6 +5,7 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.LinearLayout
import androidx.activity.result.ActivityResult
@ -30,6 +31,8 @@ class SettingsActivity : AppCompatActivity(), IWithResultLauncher {
private var _isFinished = false;
lateinit var overlay: FrameLayout;
override fun attachBaseContext(newBase: Context?) {
Logger.i("SettingsActivity", "SettingsActivity.attachBaseContext")
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
@ -44,6 +47,7 @@ class SettingsActivity : AppCompatActivity(), IWithResultLauncher {
_buttonDev = findViewById(R.id.button_dev);
_devSets = findViewById(R.id.dev_settings);
_loaderView = findViewById(R.id.loader);
overlay = findViewById(R.id.overlay_container);
_form.onChanged.subscribe { field, value ->
Logger.i("SettingsActivity", "Setting [${field.field?.name}] changed, saving");

View file

@ -0,0 +1,73 @@
package com.futo.platformplayer.dialogs
import android.app.AlertDialog
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.widget.Button
import com.futo.platformplayer.R
import com.futo.platformplayer.activities.MainActivity
import com.futo.platformplayer.readBytes
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.states.StateBackup
import com.futo.platformplayer.views.buttons.BigButton
class ImportOptionsDialog: AlertDialog {
private val _context: MainActivity;
private lateinit var _button_import_zip: BigButton;
private lateinit var _button_import_ezip: BigButton;
private lateinit var _button_import_txt: BigButton;
private lateinit var _button_import_newpipe_subs: BigButton;
private lateinit var _button_close: Button;
constructor(context: MainActivity): super(context) {
_context = context;
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
setContentView(LayoutInflater.from(context).inflate(R.layout.dialog_import_options, null));
_button_import_zip = findViewById(R.id.button_import_zip);
_button_import_ezip = findViewById(R.id.button_import_ezip);
_button_import_txt = findViewById(R.id.button_import_txt);
_button_import_newpipe_subs = findViewById(R.id.button_import_newpipe_subs);
_button_close = findViewById(R.id.button_cancel);
_button_import_zip.onClick.subscribe {
dismiss();
StateApp.instance.requestFileReadAccess(_context, null, "application/zip") {
val zipBytes = it?.readBytes(context) ?: return@requestFileReadAccess;
StateBackup.importZipBytes(_context, StateApp.instance.scope, zipBytes);
};
}
_button_import_ezip.setOnClickListener {
}
_button_import_txt.onClick.subscribe {
dismiss();
StateApp.instance.requestFileReadAccess(_context, null, "text/plain") {
val txtBytes = it?.readBytes(context) ?: return@requestFileReadAccess;
val txt = String(txtBytes);
StateBackup.importTxt(_context, txt);
};
}
_button_import_newpipe_subs.onClick.subscribe {
dismiss();
StateApp.instance.requestFileReadAccess(_context, null, "application/json") {
val jsonBytes = it?.readBytes(context) ?: return@requestFileReadAccess;
val json = String(jsonBytes);
StateBackup.importNewPipeSubs(_context, json);
};
};
_button_close.setOnClickListener {
dismiss();
}
}
override fun dismiss() {
super.dismiss();
}
}

View file

@ -235,14 +235,33 @@ class StateApp {
return state;
}
fun requestFileReadAccess(activity: IWithResultLauncher, path: Uri?, handle: (DocumentFile?)->Unit) {
fun requestFileReadAccess(activity: IWithResultLauncher, path: Uri?, contentType: String, handle: (DocumentFile?)->Unit) {
if(activity is Context) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT);
if(path != null)
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, path);
intent.flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
.or(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType(contentType);
activity.launchForResult(intent, 98) {
if(it.resultCode == Activity.RESULT_OK) {
val uri = it.data?.data;
if(uri != null)
handle(DocumentFile.fromSingleUri(activity, uri));
}
else
UIDialogs.showDialogOk(context, R.drawable.ic_security_pred, "No access granted");
};
}
}
fun requestFileCreateAccess(activity: IWithResultLauncher, path: Uri?, contentType: String, handle: (DocumentFile?)->Unit) {
if(activity is Context) {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT);
if(path != null)
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, path);
intent.flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
.or(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType(contentType);
activity.launchForResult(intent, 98) {
if(it.resultCode == Activity.RESULT_OK) {
val uri = it.data?.data;

View file

@ -8,17 +8,21 @@ import com.futo.platformplayer.R
import com.futo.platformplayer.Settings
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.video.SerializedPlatformVideo
import com.futo.platformplayer.copyTo
import com.futo.platformplayer.encryption.GPasswordEncryptionProvider
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.readBytes
import com.futo.platformplayer.stores.FragmentedStorage
import com.futo.platformplayer.stores.v2.ManagedStore
import com.futo.platformplayer.writeBytes
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -52,15 +56,6 @@ class StateBackup {
val secondaryBackupFile = dir.findFile("GrayjayBackup.ezip.old") ?: if(create) dir.createFile("grayjay/ezip", "GrayjayBackup.ezip.old") else null;
return Pair(mainBackupFile, secondaryBackupFile);
}
/*
private fun getAutomaticBackupFiles(): Pair<File, File> {
val dir = StateApp.instance.getExternalRootDirectory();
if(dir == null)
throw IllegalStateException("Can't access external files");
return Pair(File(dir, "GrayjayBackup.ezip"), File(dir, "GrayjayBackup.ezip.old"))
}*/
fun getAllMigrationStores(): List<ManagedStore<*>> = listOf(
StateSubscriptions.instance.toMigrateCheck(),
StatePlaylists.instance.toMigrateCheck()
@ -192,7 +187,19 @@ class StateBackup {
importZipBytes(context, scope, backupBytes);
}
fun startExternalBackup() {
fun saveExternalBackup(activity: IWithResultLauncher) {
val data = export();
if(activity is Context)
StateApp.instance.requestFileCreateAccess(activity, null, "application/zip") {
if(it == null) {
UIDialogs.toast("Cancelled");
return@requestFileCreateAccess;
}
it.writeBytes(activity, data.asZip());
UIDialogs.toast("Export saved");
};
}
fun shareExternalBackup() {
val data = export();
val now = OffsetDateTime.now();
val exportFile = File(
@ -401,6 +408,46 @@ class StateBackup {
).withCondition { doImport } else null
);
}
fun importTxt(context: MainActivity, text: String, allowFailure: Boolean = false): Boolean {
if(text.startsWith("@/Subscription") || text.startsWith("Subscriptions")) {
val lines = text.split("\n").map { it.trim() }.drop(1).filter { it.isNotEmpty() };
context.navigate(context.getFragment<ImportSubscriptionsFragment>(), lines);
return true;
}
else if(allowFailure) {
UIDialogs.showGeneralErrorDialog(context, "Unknown text header [${text}]");
}
return false;
}
fun importNewPipeSubs(context: MainActivity, json: String) {
val newPipeSubsParsed = JsonParser.parseString(json).asJsonObject;
if (!newPipeSubsParsed.has("subscriptions") || !newPipeSubsParsed["subscriptions"].isJsonArray)
UIDialogs.showGeneralErrorDialog(context, "Invalid json");
else {
importNewPipeSubs(context, newPipeSubsParsed);
}
}
fun importNewPipeSubs(context: MainActivity, obj: JsonObject) {
try {
val jsonSubs = obj["subscriptions"]
val jsonSubsArray = jsonSubs.asJsonArray;
val jsonSubsArrayItt = jsonSubsArray.iterator();
val subs = mutableListOf<String>()
while(jsonSubsArrayItt.hasNext()) {
val jsonSubObj = jsonSubsArrayItt.next().asJsonObject;
if(jsonSubObj.has("url"))
subs.add(jsonSubObj["url"].asString);
}
context.navigate(context.getFragment<ImportSubscriptionsFragment>(), subs);
}
catch(ex: Exception) {
Logger.e("StateBackup", ex.message, ex);
UIDialogs.showGeneralErrorDialog(context, context.getString(R.string.failed_to_parse_newpipe_subscriptions), ex);
}
}
}
class ExportStructure(

View file

@ -25,7 +25,7 @@ class SlideUpMenuItem : RelativeLayout {
init();
}
constructor(context: Context, imageRes: Int = 0, mainText: String, subText: String = "", tag: Any, call: (()->Unit)? = null, invokeParent: Boolean = true): super(context){
constructor(context: Context, imageRes: Int = 0, mainText: String, subText: String = "", tag: Any?, call: (()->Unit)? = null, invokeParent: Boolean = true): super(context){
init();
_image.setImageResource(imageRes);
_text.text = mainText;

View file

@ -1,89 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:background="@color/black">
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingTop="20dp"
android:paddingBottom="15dp">
<ImageButton
android:id="@+id/button_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingRight="20dp"
app:srcCompat="@drawable/ic_back_thin_white_16dp" />
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings"
android:textSize="24dp"
android:textColor="@color/white"
android:fontFamily="@font/inter_extra_light" />
</FrameLayout>
<Space
android:layout_width="20dp"
android:layout_height="match_parent" />
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:background="@color/black">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.futo.platformplayer.views.LoaderView
android:id="@+id/loader"
android:layout_marginBottom="15dp"
android:layout_marginTop="15dp"
android:layout_width="match_parent"
android:layout_height="60dp" />
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingTop="20dp"
android:paddingBottom="15dp">
<com.futo.platformplayer.views.fields.FieldForm
android:id="@+id/settings_form"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageButton
android:id="@+id/button_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingRight="20dp"
app:srcCompat="@drawable/ic_back_thin_white_16dp" />
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings"
android:textSize="24dp"
android:textColor="@color/white"
android:fontFamily="@font/inter_extra_light" />
</FrameLayout>
<Space
android:layout_width="20dp"
android:layout_height="match_parent" />
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/dev_settings"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
<com.futo.platformplayer.views.LoaderView
android:id="@+id/loader"
android:layout_marginBottom="15dp"
android:layout_marginTop="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="14dp"
android:textAlignment="center"
android:layout_margin="5dp"
android:text="@string/you_re_apparantly_a_developer" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_dev"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/developer_settings" />
</LinearLayout>
</LinearLayout>
android:layout_height="60dp" />
</ScrollView>
</LinearLayout>
<com.futo.platformplayer.views.fields.FieldForm
android:id="@+id/settings_form"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/dev_settings"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="14dp"
android:textAlignment="center"
android:layout_margin="5dp"
android:text="@string/you_re_apparantly_a_developer" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_dev"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/developer_settings" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
<FrameLayout
android:id="@+id/overlay_container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone"
android:elevation="15dp">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -4,7 +4,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@color/gray_1d">
@ -13,7 +13,7 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:paddingTop="40dp">
android:paddingTop="20dp">
<FrameLayout
android:layout_width="wrap_content"
@ -21,8 +21,8 @@
<ImageView
android:id="@+id/update_spinner"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_width="70dp"
android:layout_height="70dp"
app:srcCompat="@drawable/ic_move_up" />
<TextView
@ -46,7 +46,19 @@
android:textSize="14dp"
android:textColor="@color/white"
android:fontFamily="@font/inter_regular"
android:layout_marginTop="30dp"
android:layout_marginTop="10dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="You can open and share files directly to Grayjay as well."
android:textAlignment="center"
android:textSize="13dp"
android:textColor="@color/white"
android:fontFamily="@font/inter_regular"
android:layout_marginTop="10dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp" />
@ -55,39 +67,47 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:padding="10dp"
android:layout_marginTop="28dp"
android:layout_marginBottom="28dp">
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="10dp">
<com.futo.platformplayer.views.buttons.BigButton
android:id="@+id/button_import_zip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleY="0.9"
android:scaleX="0.9"
app:buttonIcon="@drawable/ic_zip"
app:buttonText="Import Grayjay export (.zip)"
android:layout_margin="5dp"
app:buttonBackground="@drawable/background_big_button_black"
app:buttonSubText="Pick a Grayjay export zip file" />
<com.futo.platformplayer.views.buttons.BigButton
android:id="@+id/button_import_ezip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:buttonIcon="@drawable/ic_encrypted"
android:scaleY="0.9"
android:scaleX="0.9"
android:alpha="0.5"
app:buttonBackground="@drawable/background_big_button_black"
app:buttonText="Import Grayjay Auto-Backup (.ezip)"
android:layout_margin="5dp"
app:buttonSubText="Pick a Grayjay auto-backup encrypted zip file" />
<com.futo.platformplayer.views.buttons.BigButton
android:id="@+id/button_import_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:scaleY="0.9"
android:scaleX="0.9"
app:buttonIcon="@drawable/ic_lines"
android:alpha="0.5"
app:buttonBackground="@drawable/background_big_button_black"
app:buttonText="Import Line Text file (.txt)"
app:buttonSubText="Pick a text file with one entry per line" />
<com.futo.platformplayer.views.buttons.BigButton
android:id="@+id/button_import_newpipe_subs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:scaleY="0.9"
android:scaleX="0.9"
app:buttonIcon="@drawable/ic_play"
app:buttonBackground="@drawable/background_big_button_black"
app:buttonText="Import NewPipe Subscriptions (.json)"
@ -98,7 +118,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/close"
android:layout_marginTop="20dp"
android:layout_marginTop="10dp"
android:textSize="14dp"
android:fontFamily="@font/inter_regular"
android:textColor="@color/colorPrimary"