Skip to content

Commit

Permalink
Export & Import settings. close #467
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Apr 19, 2021
1 parent 4546cda commit d1b90f2
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 5 deletions.
4 changes: 2 additions & 2 deletions TMessagesProj/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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)")
Expand Down
22 changes: 20 additions & 2 deletions TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@
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;
Expand Down Expand Up @@ -11739,6 +11740,8 @@ private int getMessageType(MessageObject messageObject) {
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;
}
Expand Down Expand Up @@ -19215,14 +19218,17 @@ private void createMenu(View v, boolean single, boolean listView, float x, float
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);
Expand Down Expand Up @@ -20316,6 +20322,12 @@ private void processSelectedOption(int option) {
presentFragment(new StickersActivity(finalLocFile));
});

} else if (locFile.getName().toLowerCase().endsWith(".nekox-settings.json")) {

File finalLocFile = locFile;

NekoSettingsActivity.importSettings(getParentActivity(), finalLocFile);

}
}
break;
Expand Down Expand Up @@ -22948,6 +22960,12 @@ public void didPressImage(ChatMessageCell cell, float x, float y) {
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()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -10,12 +16,24 @@
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;
Expand All @@ -30,10 +48,21 @@
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 {
Expand Down Expand Up @@ -66,12 +95,21 @@ public boolean onFragmentCreate() {
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);
}
Expand All @@ -80,6 +118,35 @@ public View createView(Context context) {
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);
}
}
});
Expand Down Expand Up @@ -120,6 +187,164 @@ public void onItemClick(int id) {
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();
Expand All @@ -139,7 +364,7 @@ private void updateRows() {

aboutRow = rowCount++;
channelRow = rowCount++;
fdroidRow = rowCount ++;
fdroidRow = rowCount++;
if (ExternalGcm.checkPlayServices()) {
googlePlayRow = rowCount++;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -21,4 +22,9 @@ object GsonUtil {
return stringWriter.toString()
}

@JvmStatic
fun toJsonObject(json: String): JsonObject {
return gson.fromJson(json, JsonObject::class.java)
}

}
3 changes: 3 additions & 0 deletions TMessagesProj/src/main/res/values/strings_nekox.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>

0 comments on commit d1b90f2

Please sign in to comment.