mirror of
https://github.com/MGislv/NekoX.git
synced 2024-07-02 10:33:36 +00:00
Export & Import settings. close #467
This commit is contained in:
parent
4546cdaaa1
commit
d1b90f29e6
|
@ -3,8 +3,8 @@ import cn.hutool.core.util.RuntimeUtil
|
|||
apply plugin: "com.android.application"
|
||||
apply plugin: "kotlin-android"
|
||||
|
||||
def verName = "7.7.2-rc01"
|
||||
def verCode = 290 + 3 * 1
|
||||
def verName = "7.7.2-rc02"
|
||||
def verCode = 290 + 3 * 2
|
||||
|
||||
if (System.getenv("DEBUG_BUILD") == "true") {
|
||||
verName += "-" + RuntimeUtil.execForStr("git log --pretty=format:'%h' -n 1)")
|
||||
|
|
|
@ -254,6 +254,7 @@ import tw.nekomimi.nekogram.NekoConfig;
|
|||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.parts.MessageTransKt;
|
||||
import tw.nekomimi.nekogram.parts.PollTransUpdatesKt;
|
||||
import tw.nekomimi.nekogram.settings.NekoSettingsActivity;
|
||||
import tw.nekomimi.nekogram.transtale.Translator;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.PGPUtil;
|
||||
|
@ -11739,6 +11740,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
return 21;
|
||||
} else if ((messageObject.getDocumentName().toLowerCase().endsWith(".nekox-stickers.json"))) {
|
||||
return 22;
|
||||
} else if ((messageObject.getDocumentName().toLowerCase().endsWith(".nekox-settings.json"))) {
|
||||
return 23;
|
||||
} else if (!messageObject.isNewGif() && mime.endsWith("/mp4") || mime.endsWith("/png") || mime.endsWith("/jpg") || mime.endsWith("/jpeg")) {
|
||||
return 6;
|
||||
}
|
||||
|
@ -19215,14 +19218,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
items.add(LocaleController.getString("ShareFile", R.string.ShareFile));
|
||||
options.add(6);
|
||||
icons.add(R.drawable.baseline_share_24);
|
||||
} else if (type == 21 || type == 22) {
|
||||
} else if (type == 21 || type == 22 || type == 23) {
|
||||
options.add(5);
|
||||
if (type == 21) {
|
||||
items.add(LocaleController.getString("ImportProxyList", R.string.ImportProxyList));
|
||||
icons.add(R.drawable.baseline_security_24);
|
||||
} else {
|
||||
} else if (type == 22) {
|
||||
items.add(LocaleController.getString("ImportStickersList", R.string.ImportStickersList));
|
||||
icons.add(R.drawable.deproko_baseline_stickers_filled_24);
|
||||
} else {
|
||||
items.add(LocaleController.getString("ImportSettings", R.string.ImportSettings));
|
||||
icons.add(R.drawable.baseline_security_24);
|
||||
}
|
||||
items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads));
|
||||
options.add(10);
|
||||
|
@ -20316,6 +20322,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
presentFragment(new StickersActivity(finalLocFile));
|
||||
});
|
||||
|
||||
} else if (locFile.getName().toLowerCase().endsWith(".nekox-settings.json")) {
|
||||
|
||||
File finalLocFile = locFile;
|
||||
|
||||
NekoSettingsActivity.importSettings(getParentActivity(), finalLocFile);
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -22948,6 +22960,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
presentFragment(new StickersActivity(finalLocFile));
|
||||
});
|
||||
|
||||
|
||||
} else if (message.getDocumentName().toLowerCase().endsWith(".nekox-settings.json")) {
|
||||
|
||||
File finalLocFile = locFile;
|
||||
NekoSettingsActivity.importSettings(getParentActivity(), finalLocFile);
|
||||
|
||||
} else {
|
||||
boolean handled = false;
|
||||
if (message.canPreviewDocument()) {
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
package tw.nekomimi.nekogram.settings;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -10,12 +16,24 @@ import android.widget.FrameLayout;
|
|||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.jakewharton.processphoenix.ProcessPhoenix;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SendMessagesHelper;
|
||||
import org.telegram.messenger.browser.Browser;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenu;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.ActionBar.AlertDialog;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
|
@ -30,10 +48,21 @@ import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
|||
import org.telegram.ui.Cells.TextSettingsCell;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.RecyclerListView;
|
||||
import org.telegram.ui.DocumentSelectActivity;
|
||||
import org.telegram.ui.LaunchActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import kotlin.text.StringsKt;
|
||||
import tw.nekomimi.nekogram.ExternalGcm;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.FileUtil;
|
||||
import tw.nekomimi.nekogram.utils.GsonUtil;
|
||||
import tw.nekomimi.nekogram.utils.ShareUtil;
|
||||
|
||||
@SuppressLint("RtlHardcoded")
|
||||
public class NekoSettingsActivity extends BaseFragment {
|
||||
|
@ -66,12 +95,21 @@ public class NekoSettingsActivity extends BaseFragment {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static final int backup_settings = 1;
|
||||
private static final int import_settings = 2;
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public View createView(Context context) {
|
||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||
actionBar.setTitle(LocaleController.getString("NekoSettings", R.string.NekoSettings));
|
||||
|
||||
ActionBarMenu menu = actionBar.createMenu();
|
||||
ActionBarMenuItem otherMenu = menu.addItem(0, R.drawable.ic_ab_other);
|
||||
otherMenu.addSubItem(backup_settings, LocaleController.getString("BackupSettings", R.string.BackupSettings));
|
||||
otherMenu.addSubItem(import_settings, LocaleController.getString("ImportSettings", R.string.ImportSettings));
|
||||
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
actionBar.setOccupyStatusBar(false);
|
||||
}
|
||||
|
@ -80,6 +118,35 @@ public class NekoSettingsActivity extends BaseFragment {
|
|||
public void onItemClick(int id) {
|
||||
if (id == -1) {
|
||||
finishFragment();
|
||||
} else if (id == backup_settings) {
|
||||
backupSettings();
|
||||
} else if (id == import_settings) {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 4);
|
||||
return;
|
||||
}
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
DocumentSelectActivity fragment = new DocumentSelectActivity(false);
|
||||
fragment.setMaxSelectedFiles(1);
|
||||
fragment.setAllowPhoto(false);
|
||||
fragment.setDelegate(new DocumentSelectActivity.DocumentSelectActivityDelegate() {
|
||||
@Override
|
||||
public void didSelectFiles(DocumentSelectActivity activity, ArrayList<String> files, String caption, boolean notify, int scheduleDate) {
|
||||
activity.finishFragment();
|
||||
importSettings(getParentActivity(), new File(files.get(0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didSelectPhotos(ArrayList<SendMessagesHelper.SendingMediaInfo> photos, boolean notify, int scheduleDate) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDocumentSelectActivity() {
|
||||
}
|
||||
});
|
||||
presentFragment(fragment);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -120,6 +187,164 @@ public class NekoSettingsActivity extends BaseFragment {
|
|||
return fragmentView;
|
||||
}
|
||||
|
||||
private void backupSettings() {
|
||||
|
||||
try {
|
||||
File cacheFile = new File(ApplicationLoader.applicationContext.getCacheDir(), new Date().toLocaleString() + ".nekox-settings.json");
|
||||
FileUtil.writeUtf8String(backupSettingsJson(), cacheFile);
|
||||
ShareUtil.shareFile(getParentActivity(), cacheFile);
|
||||
} catch (JSONException e) {
|
||||
AlertUtil.showSimpleAlert(getParentActivity(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String backupSettingsJson() throws JSONException {
|
||||
|
||||
JSONObject configJson = new JSONObject();
|
||||
|
||||
ArrayList<String> userconfig = new ArrayList<>();
|
||||
userconfig.add("saveIncomingPhotos");
|
||||
userconfig.add("passcodeHash");
|
||||
userconfig.add("passcodeType");
|
||||
userconfig.add("passcodeHash");
|
||||
userconfig.add("autoLockIn");
|
||||
userconfig.add("useFingerprint");
|
||||
spToJSON("userconfing", configJson, userconfig::contains);
|
||||
|
||||
ArrayList<String> mainconfig = new ArrayList<>();
|
||||
mainconfig.add("saveToGallery");
|
||||
mainconfig.add("autoplayGifs");
|
||||
mainconfig.add("autoplayVideo");
|
||||
mainconfig.add("mapPreviewType");
|
||||
mainconfig.add("raiseToSpeak");
|
||||
mainconfig.add("customTabs");
|
||||
mainconfig.add("directShare");
|
||||
mainconfig.add("shuffleMusic");
|
||||
mainconfig.add("playOrderReversed");
|
||||
mainconfig.add("inappCamera");
|
||||
mainconfig.add("repeatMode");
|
||||
mainconfig.add("fontSize");
|
||||
mainconfig.add("bubbleRadius");
|
||||
mainconfig.add("ivFontSize");
|
||||
mainconfig.add("allowBigEmoji");
|
||||
mainconfig.add("streamMedia");
|
||||
mainconfig.add("saveStreamMedia");
|
||||
mainconfig.add("smoothKeyboard");
|
||||
mainconfig.add("pauseMusicOnRecord");
|
||||
mainconfig.add("streamAllVideo");
|
||||
mainconfig.add("streamMkv");
|
||||
mainconfig.add("suggestStickers");
|
||||
mainconfig.add("sortContactsByName");
|
||||
mainconfig.add("sortFilesByName");
|
||||
mainconfig.add("noSoundHintShowed");
|
||||
mainconfig.add("directShareHash");
|
||||
mainconfig.add("useThreeLinesLayout");
|
||||
mainconfig.add("archiveHidden");
|
||||
mainconfig.add("distanceSystemType");
|
||||
mainconfig.add("loopStickers");
|
||||
mainconfig.add("keepMedia");
|
||||
mainconfig.add("noStatusBar");
|
||||
mainconfig.add("lastKeepMediaCheckTime");
|
||||
mainconfig.add("searchMessagesAsListHintShows");
|
||||
mainconfig.add("searchMessagesAsListUsed");
|
||||
mainconfig.add("stickersReorderingHintUsed");
|
||||
mainconfig.add("textSelectionHintShows");
|
||||
mainconfig.add("scheduledOrNoSoundHintShows");
|
||||
mainconfig.add("lockRecordAudioVideoHint");
|
||||
mainconfig.add("disableVoiceAudioEffects");
|
||||
mainconfig.add("chatSwipeAction");
|
||||
mainconfig.add("theme");
|
||||
spToJSON("mainconfig", configJson, mainconfig::contains);
|
||||
spToJSON("themeconfig", configJson, null);
|
||||
spToJSON("nekoconfig", configJson, null);
|
||||
|
||||
return configJson.toString(4);
|
||||
}
|
||||
|
||||
private static void spToJSON(String sp, JSONObject object, Function<String, Boolean> filter) throws JSONException {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences(sp, Activity.MODE_PRIVATE);
|
||||
JSONObject jsonConfig = new JSONObject();
|
||||
for (Map.Entry<String, ?> entry : preferences.getAll().entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (filter != null && !filter.apply(key)) continue;
|
||||
if (entry.getValue() instanceof Long) {
|
||||
key = key + "_long";
|
||||
} else if (entry.getValue() instanceof Float) {
|
||||
key = key + "_float";
|
||||
}
|
||||
jsonConfig.put(key, entry.getValue());
|
||||
}
|
||||
object.put(sp, jsonConfig);
|
||||
}
|
||||
|
||||
public static void importSettings(Context context, File settingsFile) {
|
||||
|
||||
AlertUtil.showConfirm(context,
|
||||
LocaleController.getString("ImportSettingsAlert", R.string.ImportSettingsAlert),
|
||||
R.drawable.baseline_security_24,
|
||||
LocaleController.getString("Import", R.string.Import),
|
||||
true,
|
||||
() -> importSettingsConfirmed(context, settingsFile));
|
||||
|
||||
}
|
||||
|
||||
public static void importSettingsConfirmed(Context context, File settingsFile) {
|
||||
|
||||
try {
|
||||
JsonObject configJson = GsonUtil.toJsonObject(FileUtil.readUtf8String(settingsFile));
|
||||
importSettings(configJson);
|
||||
|
||||
AlertDialog restart = new AlertDialog(context, 0);
|
||||
restart.setTitle(LocaleController.getString("NekoX", R.string.NekoX));
|
||||
restart.setMessage(LocaleController.getString("RestartAppToTakeEffect", R.string.RestartAppToTakeEffect));
|
||||
restart.setPositiveButton(LocaleController.getString("OK", R.string.OK), (__, ___) -> {
|
||||
ProcessPhoenix.triggerRebirth(context, new Intent(context, LaunchActivity.class));
|
||||
});
|
||||
restart.show();
|
||||
} catch (Exception e) {
|
||||
AlertUtil.showSimpleAlert(context, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("ApplySharedPref")
|
||||
public static void importSettings(JsonObject configJson) throws JSONException {
|
||||
|
||||
for (Map.Entry<String, JsonElement> element : configJson.entrySet()) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences(element.getKey(), Activity.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
for (Map.Entry<String, JsonElement> config : ((JsonObject) element.getValue()).entrySet()) {
|
||||
String key = config.getKey();
|
||||
JsonPrimitive value = (JsonPrimitive) config.getValue();
|
||||
if (value.isBoolean()) {
|
||||
editor.putBoolean(key, value.getAsBoolean());
|
||||
} else if (value.isNumber()) {
|
||||
boolean isLong = false;
|
||||
boolean isFloat = false;
|
||||
if (key.endsWith("_long")) {
|
||||
key = StringsKt.substringBeforeLast(key, "_long", key);
|
||||
isLong = true;
|
||||
} else if (key.endsWith("_float")) {
|
||||
key = StringsKt.substringBeforeLast(key, "_float", key);
|
||||
isFloat = true;
|
||||
}
|
||||
if (isLong) {
|
||||
editor.putLong(key, value.getAsLong());
|
||||
} else if (isFloat) {
|
||||
editor.putFloat(key, value.getAsFloat());
|
||||
} else {
|
||||
editor.putInt(key, value.getAsInt());
|
||||
}
|
||||
} else {
|
||||
editor.putString(key, value.getAsString());
|
||||
}
|
||||
}
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
@ -139,7 +364,7 @@ public class NekoSettingsActivity extends BaseFragment {
|
|||
|
||||
aboutRow = rowCount++;
|
||||
channelRow = rowCount++;
|
||||
fdroidRow = rowCount ++;
|
||||
fdroidRow = rowCount++;
|
||||
if (ExternalGcm.checkPlayServices()) {
|
||||
googlePlayRow = rowCount++;
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package tw.nekomimi.nekogram.utils
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.internal.Streams
|
||||
import com.google.gson.stream.JsonWriter
|
||||
import java.io.StringWriter
|
||||
|
@ -21,4 +22,9 @@ object GsonUtil {
|
|||
return stringWriter.toString()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toJsonObject(json: String): JsonObject {
|
||||
return gson.fromJson(json, JsonObject::class.java)
|
||||
}
|
||||
|
||||
}
|
|
@ -233,4 +233,7 @@
|
|||
<string name="WsPayload">Payload</string>
|
||||
<string name="AutoLockImmediately">Immediately</string>
|
||||
<string name="WsNeedLogin">Due to technical limitations, Ws Relay cannot be used before logging in.</string>
|
||||
<string name="BackupSettings">Backup settings</string>
|
||||
<string name="ImportSettings">Import settings</string>
|
||||
<string name="ImportSettingsAlert">Are you sure you want to overwrite the settings? Importing settings from unknown sources may cause the pin to be overwritten and cause the application to be locked.</string>
|
||||
</resources>
|
Loading…
Reference in New Issue
Block a user