mirror of
https://codeberg.org/tom79/Fedilab.git
synced 2024-12-23 09:10:04 +02:00
export settings
This commit is contained in:
parent
190b800a6e
commit
7f28d208a3
7 changed files with 217 additions and 0 deletions
|
@ -36,6 +36,8 @@ class SettingsActivity : BaseActivity() {
|
||||||
|
|
||||||
val navController = findNavController(R.id.fragment_container)
|
val navController = findNavController(R.id.fragment_container)
|
||||||
appBarConfiguration = AppBarConfiguration(navController.graph)
|
appBarConfiguration = AppBarConfiguration(navController.graph)
|
||||||
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
setupActionBarWithNavController(navController, appBarConfiguration)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
package app.fedilab.android.helper;
|
||||||
|
/* Copyright 2022 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Fedilab
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import static app.fedilab.android.BaseMainActivity.currentAccount;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Environment;
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import app.fedilab.android.R;
|
||||||
|
|
||||||
|
|
||||||
|
//From https://stackoverflow.com/a/10864463
|
||||||
|
|
||||||
|
public class SettingsStorage {
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean saveSharedPreferencesToFile(Context context) {
|
||||||
|
boolean res = false;
|
||||||
|
ObjectOutputStream output = null;
|
||||||
|
String fileName = "Fedilab_settings_export_" + Helper.dateFileToString(context, new Date()) + ".txt";
|
||||||
|
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
|
||||||
|
String fullPath = filePath + "/" + fileName;
|
||||||
|
File dst = new File(fullPath);
|
||||||
|
try {
|
||||||
|
output = new ObjectOutputStream(new FileOutputStream(dst));
|
||||||
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
output.writeObject(sharedpreferences.getAll());
|
||||||
|
res = true;
|
||||||
|
String message = context.getString(R.string.data_export_theme_success);
|
||||||
|
Intent intentOpen = new Intent();
|
||||||
|
intentOpen.setAction(android.content.Intent.ACTION_VIEW);
|
||||||
|
Uri uri = Uri.parse("file://" + fullPath);
|
||||||
|
intentOpen.setDataAndType(uri, "text/txt");
|
||||||
|
String title = context.getString(R.string.data_export_settings);
|
||||||
|
Helper.notify_user(context, currentAccount, intentOpen, BitmapFactory.decodeResource(context.getResources(),
|
||||||
|
R.mipmap.ic_launcher), Helper.NotifType.BACKUP, title, message);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (output != null) {
|
||||||
|
output.flush();
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ApplySharedPref")
|
||||||
|
@SuppressWarnings({"unchecked", "UnnecessaryUnboxing"})
|
||||||
|
public static boolean loadSharedPreferencesFromFile(Context context, File src) {
|
||||||
|
boolean res = false;
|
||||||
|
ObjectInputStream input = null;
|
||||||
|
try {
|
||||||
|
input = new ObjectInputStream(new FileInputStream(src));
|
||||||
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
SharedPreferences.Editor prefEdit = sharedpreferences.edit();
|
||||||
|
prefEdit.clear();
|
||||||
|
Map<String, ?> entries = (Map<String, ?>) input.readObject();
|
||||||
|
for (Map.Entry<String, ?> entry : entries.entrySet()) {
|
||||||
|
Object v = entry.getValue();
|
||||||
|
String key = entry.getKey();
|
||||||
|
//We skip some values
|
||||||
|
if (key.compareTo(Helper.PREF_USER_ID) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (key.compareTo(Helper.PREF_INSTANCE) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (key.compareTo(Helper.PREF_USER_INSTANCE) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (key.compareTo(Helper.PREF_USER_TOKEN) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (v instanceof Boolean)
|
||||||
|
prefEdit.putBoolean(key, ((Boolean) v).booleanValue());
|
||||||
|
else if (v instanceof Float)
|
||||||
|
prefEdit.putFloat(key, ((Float) v).floatValue());
|
||||||
|
else if (v instanceof Integer)
|
||||||
|
prefEdit.putInt(key, ((Integer) v).intValue());
|
||||||
|
else if (v instanceof Long)
|
||||||
|
prefEdit.putLong(key, ((Long) v).longValue());
|
||||||
|
else if (v instanceof String)
|
||||||
|
prefEdit.putString(key, ((String) v));
|
||||||
|
}
|
||||||
|
prefEdit.commit();
|
||||||
|
res = true;
|
||||||
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (input != null) {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,15 +14,23 @@ package app.fedilab.android.ui.fragment.settings
|
||||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import app.fedilab.android.BaseMainActivity.currentAccount
|
import app.fedilab.android.BaseMainActivity.currentAccount
|
||||||
import app.fedilab.android.R
|
import app.fedilab.android.R
|
||||||
|
import app.fedilab.android.helper.SettingsStorage
|
||||||
|
|
||||||
|
|
||||||
class FragmentSettingsCategories : PreferenceFragmentCompat() {
|
class FragmentSettingsCategories : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
|
private val REQUEST_CODE = 5412
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.pref_categories, rootKey)
|
setPreferencesFromResource(R.xml.pref_categories, rootKey)
|
||||||
|
|
||||||
|
@ -61,6 +69,25 @@ class FragmentSettingsCategories : PreferenceFragmentCompat() {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.pref_export_settings))?.setOnPreferenceClickListener {
|
||||||
|
val permissionLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.RequestPermission()
|
||||||
|
) { isGranted ->
|
||||||
|
if (isGranted) {
|
||||||
|
SettingsStorage.saveSharedPreferencesToFile(context)
|
||||||
|
} else {
|
||||||
|
requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_CODE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
permissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.pref_import_settings))?.setOnPreferenceClickListener {
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
val adminPreference = findPreference<Preference>(getString(R.string.pref_category_key_administration))
|
val adminPreference = findPreference<Preference>(getString(R.string.pref_category_key_administration))
|
||||||
adminPreference?.isVisible = currentAccount.admin
|
adminPreference?.isVisible = currentAccount.admin
|
||||||
adminPreference?.setOnPreferenceClickListener { false }
|
adminPreference?.setOnPreferenceClickListener { false }
|
||||||
|
@ -70,4 +97,16 @@ class FragmentSettingsCategories : PreferenceFragmentCompat() {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
|
when (requestCode) {
|
||||||
|
REQUEST_CODE -> if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
SettingsStorage.saveSharedPreferencesToFile(context)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(context, getString(R.string.permission_missing), Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="#FFFFFF"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M7.41,8.59L12,13.17l4.59,-4.58L18,10l-6,6 -6,-6 1.41,-1.41z" />
|
||||||
|
</vector>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="#FFFFFF"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z" />
|
||||||
|
</vector>
|
|
@ -616,6 +616,7 @@
|
||||||
<string name="pref_custom_theme">Use a custom theme</string>
|
<string name="pref_custom_theme">Use a custom theme</string>
|
||||||
<string name="theming">Theming</string>
|
<string name="theming">Theming</string>
|
||||||
<string name="data_export_theme">The theme was exported</string>
|
<string name="data_export_theme">The theme was exported</string>
|
||||||
|
<string name="data_export_settings">The settings were exported</string>
|
||||||
<string name="data_export_theme_success">The theme has been successfully exported in CSV</string>
|
<string name="data_export_theme_success">The theme has been successfully exported in CSV</string>
|
||||||
<string name="import_theme">Import a theme</string>
|
<string name="import_theme">Import a theme</string>
|
||||||
<string name="import_theme_title">Tap here to import a theme from a previous export</string>
|
<string name="import_theme_title">Tap here to import a theme from a previous export</string>
|
||||||
|
@ -1428,4 +1429,10 @@
|
||||||
<string name="pref_category_key_theming" translatable="false">pref_category_theming</string>
|
<string name="pref_category_key_theming" translatable="false">pref_category_theming</string>
|
||||||
<string name="pref_category_key_administration" translatable="false">pref_category_administration</string>
|
<string name="pref_category_key_administration" translatable="false">pref_category_administration</string>
|
||||||
<string name="pref_category_key_languages" translatable="false">pref_category_languages</string>
|
<string name="pref_category_key_languages" translatable="false">pref_category_languages</string>
|
||||||
|
<string name="pref_export_settings" translatable="false">pref_export_settings</string>
|
||||||
|
<string name="pref_import_settings" translatable="false">pref_import_settings</string>
|
||||||
|
|
||||||
|
<string name="export_settings">Export settings</string>
|
||||||
|
<string name="import_settings">Import settings</string>
|
||||||
|
<string name="permission_missing">Permission not granted!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -67,4 +67,19 @@
|
||||||
app:icon="@drawable/ic_language"
|
app:icon="@drawable/ic_language"
|
||||||
app:key="@string/pref_category_key_languages" />
|
app:key="@string/pref_category_key_languages" />
|
||||||
|
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:title="@string/export_settings"
|
||||||
|
app:icon="@drawable/ic_baseline_keyboard_arrow_down_24"
|
||||||
|
app:key="@string/pref_export_settings" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:title="@string/import_settings"
|
||||||
|
app:icon="@drawable/ic_baseline_keyboard_arrow_up_24"
|
||||||
|
app:key="@string/pref_import_settings" />
|
||||||
|
|
||||||
</androidx.preference.PreferenceScreen>
|
</androidx.preference.PreferenceScreen>
|
||||||
|
|
Loading…
Reference in a new issue