feat: Add import from & export settings to a file
Co-authored-by: ILoveOpenSourceApplications <117499019+iloveopensourceapplications@users.noreply.github.com>
This commit is contained in:
parent
f063cf69bd
commit
1ebd990051
5 changed files with 290 additions and 120 deletions
|
|
@ -2,7 +2,7 @@ package app.revanced.extension.shared.settings;
|
|||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.content.Context;
|
||||
import android.app.Activity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
|
@ -122,18 +122,18 @@ public abstract class Setting<T> {
|
|||
/**
|
||||
* Called after all settings have been imported.
|
||||
*/
|
||||
void settingsImported(@Nullable Context context);
|
||||
void settingsImported(@Nullable Activity context);
|
||||
|
||||
/**
|
||||
* Called after all settings have been exported.
|
||||
*/
|
||||
void settingsExported(@Nullable Context context);
|
||||
void settingsExported(@Nullable Activity context);
|
||||
}
|
||||
|
||||
private static final List<ImportExportCallback> importExportCallbacks = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Adds a callback for {@link #importFromJSON(Context, String)} and {@link #exportToJson(Context)}.
|
||||
* Adds a callback for {@link #importFromJSON(Activity, String)} and {@link #exportToJson(Activity)}.
|
||||
*/
|
||||
public static void addImportExportCallback(ImportExportCallback callback) {
|
||||
importExportCallbacks.add(Objects.requireNonNull(callback));
|
||||
|
|
@ -413,7 +413,7 @@ public abstract class Setting<T> {
|
|||
json.put(importExportKey, value);
|
||||
}
|
||||
|
||||
public static String exportToJson(@Nullable Context alertDialogContext) {
|
||||
public static String exportToJson(@Nullable Activity alertDialogContext) {
|
||||
try {
|
||||
JSONObject json = new JSONObject();
|
||||
for (Setting<?> setting : allLoadedSettingsSorted()) {
|
||||
|
|
@ -439,11 +439,17 @@ public abstract class Setting<T> {
|
|||
|
||||
String export = json.toString(0);
|
||||
|
||||
// Remove the outer JSON braces to make the output more compact,
|
||||
// and leave less chance of the user forgetting to copy it
|
||||
return export.substring(2, export.length() - 2);
|
||||
if (export.startsWith("{") && export.endsWith("}")) {
|
||||
// Remove the outer JSON braces to make the output more compact,
|
||||
// and leave less chance of the user forgetting to copy it
|
||||
export = export.substring(1, export.length() - 1);
|
||||
}
|
||||
|
||||
export = export.replaceAll("^\\n+", "").replaceAll("\\n+$", "");
|
||||
|
||||
return export + ",";
|
||||
} catch (JSONException e) {
|
||||
Logger.printException(() -> "Export failure", e); // should never happen
|
||||
Logger.printException(() -> "Export failure", e); // Should never happen
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -451,10 +457,16 @@ public abstract class Setting<T> {
|
|||
/**
|
||||
* @return if any settings that require a reboot were changed.
|
||||
*/
|
||||
public static boolean importFromJSON(Context alertDialogContext, String settingsJsonString) {
|
||||
public static boolean importFromJSON(Activity alertDialogContext, String settingsJsonString) {
|
||||
try {
|
||||
if (!settingsJsonString.matches("[\\s\\S]*\\{")) {
|
||||
settingsJsonString = '{' + settingsJsonString + '}'; // Restore outer JSON braces
|
||||
settingsJsonString = settingsJsonString.trim();
|
||||
|
||||
if (settingsJsonString.endsWith(",")) {
|
||||
settingsJsonString = settingsJsonString.substring(0, settingsJsonString.length() - 1);
|
||||
}
|
||||
|
||||
if (!settingsJsonString.trim().startsWith("{")) {
|
||||
settingsJsonString = "{\n" + settingsJsonString + "\n}"; // Restore outer JSON braces
|
||||
}
|
||||
JSONObject json = new JSONObject(settingsJsonString);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ package app.revanced.extension.shared.settings.preference;
|
|||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
|
|
@ -16,11 +18,18 @@ import android.preference.SwitchPreference;
|
|||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.Scanner;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
|
|
@ -33,6 +42,9 @@ import app.revanced.extension.shared.ui.CustomDialog;
|
|||
@SuppressWarnings("deprecation")
|
||||
public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public static AbstractPreferenceFragment instance;
|
||||
|
||||
/**
|
||||
* Indicates that if a preference changes,
|
||||
* to apply the change from the Setting to the UI component.
|
||||
|
|
@ -56,6 +68,12 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||
@Nullable
|
||||
protected static CharSequence restartDialogTitle, restartDialogMessage, restartDialogButtonText, confirmDialogTitle;
|
||||
|
||||
private static final int READ_REQUEST_CODE = 42;
|
||||
private static final int WRITE_REQUEST_CODE = 43;
|
||||
private String existingSettings = "";
|
||||
|
||||
private EditText currentImportExportEditText;
|
||||
|
||||
private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> {
|
||||
try {
|
||||
if (updatingPreference) {
|
||||
|
|
@ -198,8 +216,7 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||
return listPref.getValue().equals(defaultValueString);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Must override method to handle "
|
||||
+ "preference type: " + pref.getClass());
|
||||
throw new IllegalStateException("Must override method to handle preference type: " + pref.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -332,10 +349,230 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||
dialogPair.first.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Import / Export Subroutines
|
||||
*/
|
||||
@NonNull
|
||||
private Button createDialogButton(Context context, String text, int marginLeft, int marginRight, View.OnClickListener listener) {
|
||||
int height = (int) android.util.TypedValue.applyDimension(android.util.TypedValue.COMPLEX_UNIT_DIP, 36f, context.getResources().getDisplayMetrics());
|
||||
int paddingHorizontal = (int) android.util.TypedValue.applyDimension(android.util.TypedValue.COMPLEX_UNIT_DIP, 16f, context.getResources().getDisplayMetrics());
|
||||
float radius = android.util.TypedValue.applyDimension(android.util.TypedValue.COMPLEX_UNIT_DIP, 20f, context.getResources().getDisplayMetrics());
|
||||
|
||||
Button btn = new Button(context, null, 0);
|
||||
btn.setText(text);
|
||||
btn.setAllCaps(false);
|
||||
btn.setTextSize(14);
|
||||
btn.setSingleLine(true);
|
||||
btn.setEllipsize(android.text.TextUtils.TruncateAt.END);
|
||||
btn.setGravity(android.view.Gravity.CENTER);
|
||||
btn.setPadding(paddingHorizontal, 0, paddingHorizontal, 0);
|
||||
btn.setTextColor(Utils.isDarkModeEnabled() ? android.graphics.Color.WHITE : android.graphics.Color.BLACK);
|
||||
|
||||
android.graphics.drawable.GradientDrawable bg = new android.graphics.drawable.GradientDrawable();
|
||||
bg.setCornerRadius(radius);
|
||||
bg.setColor(Utils.getCancelOrNeutralButtonBackgroundColor());
|
||||
btn.setBackground(bg);
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, height, 1.0f);
|
||||
params.setMargins(marginLeft, 0, marginRight, 0);
|
||||
btn.setLayoutParams(params);
|
||||
btn.setOnClickListener(listener);
|
||||
|
||||
return btn;
|
||||
}
|
||||
public void showImportExportTextDialog() {
|
||||
try {
|
||||
Activity context = getActivity();
|
||||
// Must set text before showing dialog,
|
||||
// otherwise text is non-selectable if this preference is later reopened.
|
||||
existingSettings = Setting.exportToJson(context);
|
||||
currentImportExportEditText = getEditText(context);
|
||||
|
||||
// Create a custom dialog with the EditText.
|
||||
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
|
||||
context,
|
||||
str("revanced_pref_import_export_title"), // Title.
|
||||
null, // No message (EditText replaces it).
|
||||
currentImportExportEditText, // Pass the EditText.
|
||||
str("revanced_settings_save"), // OK button text.
|
||||
() -> importSettingsText(context, currentImportExportEditText.getText().toString()), // OK button action.
|
||||
() -> {}, // Cancel button action (dismiss only).
|
||||
str("revanced_settings_import_copy"), // Neutral button (Copy) text.
|
||||
() -> Utils.setClipboard(currentImportExportEditText.getText().toString()), // Neutral button (Copy) action. Show the user the settings in JSON format.
|
||||
true // Dismiss dialog when onNeutralClick.
|
||||
);
|
||||
|
||||
LinearLayout fileButtonsContainer = getLinearLayout(context);
|
||||
int margin = (int) android.util.TypedValue.applyDimension(android.util.TypedValue.COMPLEX_UNIT_DIP, 4f, context.getResources().getDisplayMetrics());
|
||||
|
||||
Button btnExport = createDialogButton(context, str("revanced_settings_export_file"), 0, margin, v -> exportActivity());
|
||||
Button btnImport = createDialogButton(context, str("revanced_settings_import_file"), margin, 0, v -> importActivity());
|
||||
|
||||
fileButtonsContainer.addView(btnExport);
|
||||
fileButtonsContainer.addView(btnImport);
|
||||
|
||||
dialogPair.second.addView(fileButtonsContainer, 2);
|
||||
|
||||
dialogPair.first.setOnDismissListener(d -> currentImportExportEditText = null);
|
||||
|
||||
// If there are no settings yet, then show the on-screen keyboard and bring focus to
|
||||
// the edit text. This makes it easier to paste saved settings after a reinstallation.
|
||||
dialogPair.first.setOnShowListener(dialogInterface -> {
|
||||
if (existingSettings.isEmpty() && currentImportExportEditText != null) {
|
||||
currentImportExportEditText.postDelayed(() -> {
|
||||
if (currentImportExportEditText != null) {
|
||||
currentImportExportEditText.requestFocus();
|
||||
android.view.inputmethod.InputMethodManager imm = (android.view.inputmethod.InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (imm != null) imm.showSoftInput(currentImportExportEditText, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
// Show the dialog.
|
||||
dialogPair.first.show();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "showImportExportTextDialog failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static LinearLayout getLinearLayout(Context context) {
|
||||
LinearLayout fileButtonsContainer = new LinearLayout(context);
|
||||
fileButtonsContainer.setOrientation(LinearLayout.HORIZONTAL);
|
||||
LinearLayout.LayoutParams fbParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
int marginTop = (int) android.util.TypedValue.applyDimension(android.util.TypedValue.COMPLEX_UNIT_DIP, 16f, context.getResources().getDisplayMetrics());
|
||||
fbParams.setMargins(0, marginTop, 0, 0);
|
||||
fileButtonsContainer.setLayoutParams(fbParams);
|
||||
return fileButtonsContainer;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private EditText getEditText(Context context) {
|
||||
EditText editText = new EditText(context);
|
||||
editText.setText(existingSettings);
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
editText.setAutofillHints((String) null);
|
||||
}
|
||||
editText.setInputType(android.text.InputType.TYPE_CLASS_TEXT |
|
||||
android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS |
|
||||
android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE);
|
||||
editText.setSingleLine(false);
|
||||
editText.setTextSize(14);
|
||||
return editText;
|
||||
}
|
||||
|
||||
public void exportActivity() {
|
||||
try {
|
||||
Setting.exportToJson(getActivity());
|
||||
|
||||
String formatDate = new java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.US).format(new java.util.Date());
|
||||
String fileName = "revanced_Settings_" + formatDate + ".txt";
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("text/plain");
|
||||
intent.putExtra(Intent.EXTRA_TITLE, fileName);
|
||||
startActivityForResult(intent, WRITE_REQUEST_CODE);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "exportActivity failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void importActivity() {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
startActivityForResult(intent, READ_REQUEST_CODE);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "importActivity failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == WRITE_REQUEST_CODE && resultCode == android.app.Activity.RESULT_OK && data != null) {
|
||||
exportTextToFile(data.getData());
|
||||
} else if (requestCode == READ_REQUEST_CODE && resultCode == android.app.Activity.RESULT_OK && data != null) {
|
||||
importTextFromFile(data.getData());
|
||||
}
|
||||
}
|
||||
|
||||
protected static void showLocalizedToast(String resourceKey, String fallbackMessage) {
|
||||
if (ResourceUtils.getIdentifier(ResourceType.STRING, resourceKey) != 0) {
|
||||
Utils.showToastLong(str(resourceKey));
|
||||
} else {
|
||||
Utils.showToastLong(fallbackMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void exportTextToFile(android.net.Uri uri) {
|
||||
try {
|
||||
OutputStream out = getContext().getContentResolver().openOutputStream(uri);
|
||||
if (out != null) {
|
||||
String textToExport = existingSettings;
|
||||
if (currentImportExportEditText != null) {
|
||||
textToExport = currentImportExportEditText.getText().toString();
|
||||
}
|
||||
out.write(textToExport.getBytes(StandardCharsets.UTF_8));
|
||||
out.close();
|
||||
|
||||
showLocalizedToast("revanced_settings_export_file_success", "Settings exported successfully");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
showLocalizedToast("revanced_settings_export_file_failed", "Failed to export settings");
|
||||
Logger.printException(() -> "exportTextToFile failure", e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("CharsetObjectCanBeUsed")
|
||||
private void importTextFromFile(android.net.Uri uri) {
|
||||
try {
|
||||
InputStream in = getContext().getContentResolver().openInputStream(uri);
|
||||
if (in != null) {
|
||||
Scanner scanner = new Scanner(in, StandardCharsets.UTF_8.name()).useDelimiter("\\A");
|
||||
String result = scanner.hasNext() ? scanner.next() : "";
|
||||
in.close();
|
||||
|
||||
if (currentImportExportEditText != null) {
|
||||
currentImportExportEditText.setText(result);
|
||||
showLocalizedToast("revanced_settings_import_file_success", "Settings imported successfully, tap Save to apply");
|
||||
} else {
|
||||
importSettingsText(getContext(), result);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
showLocalizedToast("revanced_settings_import_file_failed", "Failed to import settings");
|
||||
Logger.printException(() -> "importTextFromFile failure", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void importSettingsText(Context context, String replacementSettings) {
|
||||
try {
|
||||
existingSettings = Setting.exportToJson(null);
|
||||
if (replacementSettings.equals(existingSettings)) {
|
||||
return;
|
||||
}
|
||||
settingImportInProgress = true;
|
||||
final boolean rebootNeeded = Setting.importFromJSON(getActivity(), replacementSettings);
|
||||
if (rebootNeeded) {
|
||||
showRestartDialog(context);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "importSettingsText failure", ex);
|
||||
} finally {
|
||||
settingImportInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
instance = this;
|
||||
try {
|
||||
PreferenceManager preferenceManager = getPreferenceManager();
|
||||
preferenceManager.setSharedPreferencesName(Setting.preferences.name);
|
||||
|
|
@ -354,6 +591,9 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (instance == this) {
|
||||
instance = null;
|
||||
}
|
||||
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(listener);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,40 +4,13 @@ import static app.revanced.extension.shared.StringRef.str;
|
|||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.Preference;
|
||||
import android.text.InputType;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.ui.CustomDialog;
|
||||
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
public class ImportExportPreference extends EditTextPreference implements Preference.OnPreferenceClickListener {
|
||||
|
||||
private String existingSettings;
|
||||
|
||||
private void init() {
|
||||
setSelectable(true);
|
||||
|
||||
EditText editText = getEditText();
|
||||
editText.setTextIsSelectable(true);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
editText.setAutofillHints((String) null);
|
||||
}
|
||||
editText.setInputType(editText.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
editText.setTextSize(14);
|
||||
|
||||
setOnPreferenceClickListener(this);
|
||||
}
|
||||
public class ImportExportPreference extends Preference implements Preference.OnPreferenceClickListener {
|
||||
|
||||
public ImportExportPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
|
|
@ -56,78 +29,20 @@ public class ImportExportPreference extends EditTextPreference implements Prefer
|
|||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setOnPreferenceClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
try {
|
||||
// Must set text before showing dialog,
|
||||
// otherwise text is non-selectable if this preference is later reopened.
|
||||
existingSettings = Setting.exportToJson(getContext());
|
||||
getEditText().setText(existingSettings);
|
||||
if (AbstractPreferenceFragment.instance != null) {
|
||||
AbstractPreferenceFragment.instance.showImportExportTextDialog();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "showDialog failure", ex);
|
||||
Logger.printException(() -> "onPreferenceClick failure", ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showDialog(Bundle state) {
|
||||
try {
|
||||
Context context = getContext();
|
||||
EditText editText = getEditText();
|
||||
|
||||
// Create a custom dialog with the EditText.
|
||||
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
|
||||
context,
|
||||
str("revanced_pref_import_export_title"), // Title.
|
||||
null, // No message (EditText replaces it).
|
||||
editText, // Pass the EditText.
|
||||
str("revanced_settings_import"), // OK button text.
|
||||
() -> importSettings(context, editText.getText().toString()), // OK button action.
|
||||
() -> {}, // Cancel button action (dismiss only).
|
||||
str("revanced_settings_import_copy"), // Neutral button (Copy) text.
|
||||
() -> {
|
||||
// Neutral button (Copy) action. Show the user the settings in JSON format.
|
||||
Utils.setClipboard(editText.getText());
|
||||
},
|
||||
true // Dismiss dialog when onNeutralClick.
|
||||
);
|
||||
|
||||
// If there are no settings yet, then show the on screen keyboard and bring focus to
|
||||
// the edit text. This makes it easier to paste saved settings after a reinstall.
|
||||
dialogPair.first.setOnShowListener(dialogInterface -> {
|
||||
if (existingSettings.isEmpty()) {
|
||||
editText.postDelayed(() -> {
|
||||
editText.requestFocus();
|
||||
|
||||
InputMethodManager inputMethodManager = (InputMethodManager)
|
||||
editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
// Show the dialog.
|
||||
dialogPair.first.show();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "showDialog failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void importSettings(Context context, String replacementSettings) {
|
||||
try {
|
||||
if (replacementSettings.equals(existingSettings)) {
|
||||
return;
|
||||
}
|
||||
AbstractPreferenceFragment.settingImportInProgress = true;
|
||||
|
||||
final boolean rebootNeeded = Setting.importFromJSON(context, replacementSettings);
|
||||
if (rebootNeeded) {
|
||||
AbstractPreferenceFragment.showRestartDialog(context);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "importSettings failure", ex);
|
||||
} finally {
|
||||
AbstractPreferenceFragment.settingImportInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package app.revanced.extension.youtube.sponsorblock;
|
|||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.util.Pair;
|
||||
import android.util.Patterns;
|
||||
import android.widget.LinearLayout;
|
||||
|
|
@ -34,12 +34,12 @@ public class SponsorBlockSettings {
|
|||
|
||||
public static final Setting.ImportExportCallback SB_IMPORT_EXPORT_CALLBACK = new Setting.ImportExportCallback() {
|
||||
@Override
|
||||
public void settingsImported(@Nullable Context context) {
|
||||
public void settingsImported(@Nullable Activity context) {
|
||||
SegmentCategory.loadAllCategoriesFromSettings();
|
||||
SponsorBlockPreferenceGroup.settingsImported = true;
|
||||
}
|
||||
@Override
|
||||
public void settingsExported(@Nullable Context context) {
|
||||
public void settingsExported(@Nullable Activity context) {
|
||||
showExportWarningIfNeeded(context);
|
||||
}
|
||||
};
|
||||
|
|
@ -184,16 +184,16 @@ public class SponsorBlockSettings {
|
|||
/**
|
||||
* Export the categories using flatten JSON (no embedded dictionaries or arrays).
|
||||
*/
|
||||
private static void showExportWarningIfNeeded(@Nullable Context dialogContext) {
|
||||
private static void showExportWarningIfNeeded(@Nullable Activity activity) {
|
||||
Utils.verifyOnMainThread();
|
||||
initialize();
|
||||
|
||||
// If user has a SponsorBlock user ID then show a warning.
|
||||
if (dialogContext != null && SponsorBlockSettings.userHasSBPrivateID()
|
||||
if (activity != null && SponsorBlockSettings.userHasSBPrivateID()
|
||||
&& !Settings.SB_HIDE_EXPORT_WARNING.get()) {
|
||||
// Create the custom dialog.
|
||||
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
|
||||
dialogContext,
|
||||
activity,
|
||||
null, // No title.
|
||||
str("revanced_sb_settings_revanced_export_user_id_warning"), // Message.
|
||||
null, // No EditText.
|
||||
|
|
@ -205,11 +205,7 @@ public class SponsorBlockSettings {
|
|||
true // Dismiss dialog when onNeutralClick.
|
||||
);
|
||||
|
||||
// Set dialog as non-cancelable.
|
||||
dialogPair.first.setCancelable(false);
|
||||
|
||||
// Show the dialog.
|
||||
dialogPair.first.show();
|
||||
Utils.showDialog(activity, dialogPair.first, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,13 @@ To translate new languages or improve the existing translations, visit translate
|
|||
<string name="revanced_language_DEFAULT">App language</string>
|
||||
<string name="revanced_pref_import_export_title">Import / Export</string>
|
||||
<string name="revanced_pref_import_export_summary">Import / Export ReVanced settings</string>
|
||||
<string name="revanced_settings_import_file">Import from file</string>
|
||||
<string name="revanced_settings_import_file_success">Settings imported successfully, save to apply</string>
|
||||
<string name="revanced_settings_import_file_failed">Failed to import settings</string>
|
||||
<string name="revanced_settings_export_file">Export to file</string>
|
||||
<string name="revanced_settings_export_file_success">Settings exported successfully</string>
|
||||
<string name="revanced_settings_export_file_failed">Failed to export settings</string>
|
||||
|
||||
<!-- Settings about dialog. -->
|
||||
<string name="revanced_settings_about_links_body">You are using ReVanced Patches version <i>%s</i></string>
|
||||
<string name="revanced_settings_about_links_dev_header">Note</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue