-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9236 from vincetzr/Option-to-reset-settings
Option to reset settings
- Loading branch information
Showing
9 changed files
with
311 additions
and
231 deletions.
There are no files selected for viewing
271 changes: 271 additions & 0 deletions
271
app/src/main/java/org/schabi/newpipe/settings/BackupRestoreSettingsFragment.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
package org.schabi.newpipe.settings; | ||
|
||
import static org.schabi.newpipe.extractor.utils.Utils.isBlank; | ||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; | ||
|
||
import android.app.Activity; | ||
import android.app.AlertDialog; | ||
import android.content.Context; | ||
import android.content.Intent; | ||
import android.content.SharedPreferences; | ||
import android.net.Uri; | ||
import android.os.Bundle; | ||
import android.widget.Toast; | ||
|
||
import androidx.activity.result.ActivityResult; | ||
import androidx.activity.result.ActivityResultLauncher; | ||
import androidx.activity.result.contract.ActivityResultContracts; | ||
import androidx.annotation.NonNull; | ||
import androidx.annotation.Nullable; | ||
import androidx.core.content.ContextCompat; | ||
import androidx.preference.Preference; | ||
import androidx.preference.PreferenceManager; | ||
|
||
import org.schabi.newpipe.NewPipeDatabase; | ||
import org.schabi.newpipe.R; | ||
import org.schabi.newpipe.error.ErrorUtil; | ||
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard; | ||
import org.schabi.newpipe.streams.io.StoredFileHelper; | ||
import org.schabi.newpipe.util.NavigationHelper; | ||
import org.schabi.newpipe.util.ZipHelper; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.text.SimpleDateFormat; | ||
import java.util.Date; | ||
import java.util.Locale; | ||
import java.util.Objects; | ||
|
||
public class BackupRestoreSettingsFragment extends BasePreferenceFragment { | ||
|
||
private static final String ZIP_MIME_TYPE = "application/zip"; | ||
|
||
private final SimpleDateFormat exportDateFormat = | ||
new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US); | ||
private ContentSettingsManager manager; | ||
private String importExportDataPathKey; | ||
private final ActivityResultLauncher<Intent> requestImportPathLauncher = | ||
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), | ||
this::requestImportPathResult); | ||
private final ActivityResultLauncher<Intent> requestExportPathLauncher = | ||
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), | ||
this::requestExportPathResult); | ||
|
||
|
||
@Override | ||
public void onCreatePreferences(@Nullable final Bundle savedInstanceState, | ||
@Nullable final String rootKey) { | ||
final File homeDir = ContextCompat.getDataDir(requireContext()); | ||
Objects.requireNonNull(homeDir); | ||
manager = new ContentSettingsManager(new NewPipeFileLocator(homeDir)); | ||
manager.deleteSettingsFile(); | ||
|
||
importExportDataPathKey = getString(R.string.import_export_data_path); | ||
|
||
|
||
addPreferencesFromResourceRegistry(); | ||
|
||
final Preference importDataPreference = requirePreference(R.string.import_data); | ||
importDataPreference.setOnPreferenceClickListener((Preference p) -> { | ||
NoFileManagerSafeGuard.launchSafe( | ||
requestImportPathLauncher, | ||
StoredFileHelper.getPicker(requireContext(), | ||
ZIP_MIME_TYPE, getImportExportDataUri()), | ||
TAG, | ||
getContext() | ||
); | ||
|
||
return true; | ||
}); | ||
|
||
final Preference exportDataPreference = requirePreference(R.string.export_data); | ||
exportDataPreference.setOnPreferenceClickListener((final Preference p) -> { | ||
NoFileManagerSafeGuard.launchSafe( | ||
requestExportPathLauncher, | ||
StoredFileHelper.getNewPicker(requireContext(), | ||
"NewPipeData-" + exportDateFormat.format(new Date()) + ".zip", | ||
ZIP_MIME_TYPE, getImportExportDataUri()), | ||
TAG, | ||
getContext() | ||
); | ||
|
||
return true; | ||
}); | ||
|
||
final Preference resetSettings = findPreference(getString(R.string.reset_settings)); | ||
// Resets all settings by deleting shared preference and restarting the app | ||
// A dialogue will pop up to confirm if user intends to reset all settings | ||
assert resetSettings != null; | ||
resetSettings.setOnPreferenceClickListener(preference -> { | ||
// Show Alert Dialogue | ||
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); | ||
builder.setMessage(R.string.reset_all_settings); | ||
builder.setCancelable(true); | ||
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> { | ||
// Deletes all shared preferences xml files. | ||
final SharedPreferences sharedPreferences = | ||
PreferenceManager.getDefaultSharedPreferences(requireContext()); | ||
sharedPreferences.edit().clear().apply(); | ||
// Restarts the app | ||
if (getActivity() == null) { | ||
return; | ||
} | ||
NavigationHelper.restartApp(getActivity()); | ||
}); | ||
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> { | ||
}); | ||
final AlertDialog alertDialog = builder.create(); | ||
alertDialog.show(); | ||
return true; | ||
}); | ||
} | ||
|
||
private void requestExportPathResult(final ActivityResult result) { | ||
assureCorrectAppLanguage(requireContext()); | ||
if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { | ||
// will be saved only on success | ||
final Uri lastExportDataUri = result.getData().getData(); | ||
|
||
final StoredFileHelper file = new StoredFileHelper( | ||
requireContext(), result.getData().getData(), ZIP_MIME_TYPE); | ||
|
||
exportDatabase(file, lastExportDataUri); | ||
} | ||
} | ||
|
||
private void requestImportPathResult(final ActivityResult result) { | ||
assureCorrectAppLanguage(requireContext()); | ||
if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { | ||
// will be saved only on success | ||
final Uri lastImportDataUri = result.getData().getData(); | ||
|
||
final StoredFileHelper file = new StoredFileHelper( | ||
requireContext(), result.getData().getData(), ZIP_MIME_TYPE); | ||
|
||
new androidx.appcompat.app.AlertDialog.Builder(requireActivity()) | ||
.setMessage(R.string.override_current_data) | ||
.setPositiveButton(R.string.ok, (d, id) -> | ||
importDatabase(file, lastImportDataUri)) | ||
.setNegativeButton(R.string.cancel, (d, id) -> | ||
d.cancel()) | ||
.show(); | ||
} | ||
} | ||
|
||
private void exportDatabase(final StoredFileHelper file, final Uri exportDataUri) { | ||
try { | ||
//checkpoint before export | ||
NewPipeDatabase.checkpoint(); | ||
|
||
final SharedPreferences preferences = PreferenceManager | ||
.getDefaultSharedPreferences(requireContext()); | ||
manager.exportDatabase(preferences, file); | ||
|
||
saveLastImportExportDataUri(exportDataUri); // save export path only on success | ||
Toast.makeText(requireContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT) | ||
.show(); | ||
} catch (final Exception e) { | ||
ErrorUtil.showUiErrorSnackbar(this, "Exporting database", e); | ||
} | ||
} | ||
|
||
private void importDatabase(final StoredFileHelper file, final Uri importDataUri) { | ||
// check if file is supported | ||
if (!ZipHelper.isValidZipFile(file)) { | ||
Toast.makeText(requireContext(), R.string.no_valid_zip_file, Toast.LENGTH_SHORT) | ||
.show(); | ||
return; | ||
} | ||
|
||
try { | ||
if (!manager.ensureDbDirectoryExists()) { | ||
throw new IOException("Could not create databases dir"); | ||
} | ||
|
||
if (!manager.extractDb(file)) { | ||
Toast.makeText(requireContext(), R.string.could_not_import_all_files, | ||
Toast.LENGTH_LONG) | ||
.show(); | ||
} | ||
|
||
// if settings file exist, ask if it should be imported. | ||
if (manager.extractSettings(file)) { | ||
new androidx.appcompat.app.AlertDialog.Builder(requireContext()) | ||
.setTitle(R.string.import_settings) | ||
.setNegativeButton(R.string.cancel, (dialog, which) -> { | ||
dialog.dismiss(); | ||
finishImport(importDataUri); | ||
}) | ||
.setPositiveButton(R.string.ok, (dialog, which) -> { | ||
dialog.dismiss(); | ||
final Context context = requireContext(); | ||
final SharedPreferences prefs = PreferenceManager | ||
.getDefaultSharedPreferences(context); | ||
manager.loadSharedPreferences(prefs); | ||
cleanImport(context, prefs); | ||
finishImport(importDataUri); | ||
}) | ||
.show(); | ||
} else { | ||
finishImport(importDataUri); | ||
} | ||
} catch (final Exception e) { | ||
ErrorUtil.showUiErrorSnackbar(this, "Importing database", e); | ||
} | ||
} | ||
|
||
/** | ||
* Remove settings that are not supposed to be imported on different devices | ||
* and reset them to default values. | ||
* @param context the context used for the import | ||
* @param prefs the preferences used while running the import | ||
*/ | ||
private void cleanImport(@NonNull final Context context, | ||
@NonNull final SharedPreferences prefs) { | ||
// Check if media tunnelling needs to be disabled automatically, | ||
// if it was disabled automatically in the imported preferences. | ||
final String tunnelingKey = context.getString(R.string.disable_media_tunneling_key); | ||
final String automaticTunnelingKey = | ||
context.getString(R.string.disabled_media_tunneling_automatically_key); | ||
// R.string.disable_media_tunneling_key should always be true | ||
// if R.string.disabled_media_tunneling_automatically_key equals 1, | ||
// but we double check here just to be sure and to avoid regressions | ||
// caused by possible later modification of the media tunneling functionality. | ||
// R.string.disabled_media_tunneling_automatically_key == 0: | ||
// automatic value overridden by user in settings | ||
// R.string.disabled_media_tunneling_automatically_key == -1: not set | ||
final boolean wasMediaTunnelingDisabledAutomatically = | ||
prefs.getInt(automaticTunnelingKey, -1) == 1 | ||
&& prefs.getBoolean(tunnelingKey, false); | ||
if (wasMediaTunnelingDisabledAutomatically) { | ||
prefs.edit() | ||
.putInt(automaticTunnelingKey, -1) | ||
.putBoolean(tunnelingKey, false) | ||
.apply(); | ||
NewPipeSettings.setMediaTunneling(context); | ||
} | ||
} | ||
|
||
/** | ||
* Save import path and restart system. | ||
* | ||
* @param importDataUri The import path to save | ||
*/ | ||
private void finishImport(final Uri importDataUri) { | ||
// save import path only on success | ||
saveLastImportExportDataUri(importDataUri); | ||
// restart app to properly load db | ||
NavigationHelper.restartApp(requireActivity()); | ||
} | ||
|
||
private Uri getImportExportDataUri() { | ||
final String path = defaultPreferences.getString(importExportDataPathKey, null); | ||
return isBlank(path) ? null : Uri.parse(path); | ||
} | ||
|
||
private void saveLastImportExportDataUri(final Uri importExportDataUri) { | ||
final SharedPreferences.Editor editor = defaultPreferences.edit() | ||
.putString(importExportDataPathKey, importExportDataUri.toString()); | ||
editor.apply(); | ||
} | ||
} |
Oops, something went wrong.