feat: set passcode for each account
Co-authored-by: tehcneko <chsqwyx@gmail.com>
This commit is contained in:
parent
5d2ccbae60
commit
eda7eb4cf8
@ -49,6 +49,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.helpers.PasscodeHelper;
|
||||
import xyz.nextalone.nagram.NaConfig;
|
||||
|
||||
public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter implements NotificationCenter.NotificationCenterDelegate {
|
||||
@ -267,6 +268,7 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter imple
|
||||
private void resetItems() {
|
||||
accountNumbers.clear();
|
||||
for (int a : SharedConfig.activeAccounts) {
|
||||
if (PasscodeHelper.isAccountHidden(a)) continue;
|
||||
if (UserConfig.getInstance(a).isClientActivated()) {
|
||||
accountNumbers.add(a);
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.helpers.PasscodeHelper;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
@ -4949,6 +4950,7 @@ public class AlertsCreator {
|
||||
final LinearLayout linearLayout = new LinearLayout(parentActivity);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
for (int a : SharedConfig.activeAccounts) {
|
||||
if (PasscodeHelper.isAccountHidden(a)) continue;
|
||||
TLRPC.User u = UserConfig.getInstance(a).getCurrentUser();
|
||||
if (u != null) {
|
||||
AccountSelectCell cell = new AccountSelectCell(parentActivity, false);
|
||||
|
@ -85,6 +85,7 @@ import java.util.Locale;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.helpers.PasscodeHelper;
|
||||
import tw.nekomimi.nekogram.utils.VibrateUtil;
|
||||
|
||||
import xyz.nextalone.nagram.NaConfig;
|
||||
@ -954,7 +955,7 @@ public class PasscodeView extends FrameLayout implements NotificationCenter.Noti
|
||||
onPasscodeError();
|
||||
return;
|
||||
}
|
||||
if (!SharedConfig.checkPasscode(password)) {
|
||||
if (!PasscodeHelper.checkPasscode((Activity) getContext(), password) && !SharedConfig.checkPasscode(password)) {
|
||||
SharedConfig.increaseBadPasscodeTries();
|
||||
if (SharedConfig.passcodeRetryInMs > 0) {
|
||||
checkRetryTextView();
|
||||
|
@ -193,6 +193,7 @@ import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.helpers.PasscodeHelper;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.InternalUpdater;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
@ -2787,6 +2788,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
|
||||
|
||||
int accounts = 0;
|
||||
for (int a : SharedConfig.activeAccounts) {
|
||||
if (PasscodeHelper.isAccountHidden(a)) continue;
|
||||
TLRPC.User u = AccountInstance.getInstance(a).getUserConfig().getCurrentUser();
|
||||
if (u != null) {
|
||||
AccountSelectCell cell = new AccountSelectCell(context, false);
|
||||
|
@ -185,6 +185,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import kotlin.text.StringsKt;
|
||||
import tw.nekomimi.nekogram.InternalUpdater;
|
||||
import tw.nekomimi.nekogram.helpers.SettingsHelper;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
@ -2051,6 +2052,17 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar
|
||||
sticker = path.replace("addstickers/", "");
|
||||
} else if (path.startsWith("addemoji/")) {
|
||||
emoji = path.replace("addemoji/", "");
|
||||
} else if (path.startsWith("nekosettings/")) {
|
||||
SettingsHelper.processDeepLink(data, fragment -> {
|
||||
AndroidUtilities.runOnUIThread(() -> presentFragment(fragment, false, false));
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
actionBarLayout.showLastFragment();
|
||||
rightActionBarLayout.showLastFragment();
|
||||
drawerLayoutContainer.setAllowOpenDrawer(false, false);
|
||||
} else {
|
||||
drawerLayoutContainer.setAllowOpenDrawer(true, false);
|
||||
}
|
||||
}, () -> showBulletin(factory -> factory.createErrorBulletin(LocaleController.getString("UnknownNekoSettingsOption", R.string.UnknownNekoSettingsOption))));
|
||||
} else if (path.startsWith("msg/") || path.startsWith("share/")) {
|
||||
message = data.getQueryParameter("url");
|
||||
if (message == null) {
|
||||
@ -2421,6 +2433,19 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar
|
||||
}
|
||||
} else if (url.startsWith("tg:upgrade") || url.startsWith("tg://upgrade") || url.startsWith("tg:update") || url.startsWith("tg://update")) {
|
||||
checkAppUpdate(true);
|
||||
} else if (url.startsWith("tg:neko") || url.startsWith("tg://neko")) {
|
||||
url = url.replace("tg:neko", "tg://t.me/nekosettings").replace("tg://neko", "tg://t.me/nekosettings");
|
||||
data = Uri.parse(url);
|
||||
SettingsHelper.processDeepLink(data, fragment -> {
|
||||
AndroidUtilities.runOnUIThread(() -> presentFragment(fragment, false, false));
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
actionBarLayout.showLastFragment();
|
||||
rightActionBarLayout.showLastFragment();
|
||||
drawerLayoutContainer.setAllowOpenDrawer(false, false);
|
||||
} else {
|
||||
drawerLayoutContainer.setAllowOpenDrawer(true, false);
|
||||
}
|
||||
}, () -> showBulletin(factory -> factory.createErrorBulletin(LocaleController.getString("UnknownNekoSettingsOption", R.string.UnknownNekoSettingsOption))));
|
||||
} else if ((url.startsWith("tg:search") || url.startsWith("tg://search"))) {
|
||||
url = url.replace("tg:search", "tg://telegram.org").replace("tg://search", "tg://telegram.org");
|
||||
data = Uri.parse(url);
|
||||
|
@ -173,6 +173,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.DataCenter;
|
||||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.helpers.PasscodeHelper;
|
||||
import tw.nekomimi.nekogram.ui.BottomBuilder;
|
||||
import tw.nekomimi.nekogram.ui.EditTextAutoFill;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
@ -1634,6 +1635,7 @@ R.string.CustomBackend))
|
||||
}
|
||||
|
||||
private void onAuthSuccess(TLRPC.TL_auth_authorization res, boolean afterSignup) {
|
||||
PasscodeHelper.removePasscodeForAccount(currentAccount);
|
||||
MessagesController.getInstance(currentAccount).cleanup();
|
||||
ConnectionsManager.getInstance(currentAccount).setUserId(res.user.id);
|
||||
UserConfig.getInstance(currentAccount).clearConfig();
|
||||
@ -7462,19 +7464,7 @@ R.string.CustomBackend))
|
||||
int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (error == null) {
|
||||
TLRPC.TL_auth_authorization res = (TLRPC.TL_auth_authorization) response;
|
||||
ConnectionsManager.getInstance(currentAccount).setUserId(res.user.id);
|
||||
UserConfig.getInstance(currentAccount).clearConfig();
|
||||
MessagesController.getInstance(currentAccount).cleanup();
|
||||
UserConfig.getInstance(currentAccount).syncContacts = syncContacts;
|
||||
UserConfig.getInstance(currentAccount).setCurrentUser(res.user);
|
||||
UserConfig.getInstance(currentAccount).saveConfig(true);
|
||||
MessagesStorage.getInstance(currentAccount).cleanup(true);
|
||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||
users.add(res.user);
|
||||
MessagesStorage.getInstance(currentAccount).putUsersAndChats(users, null, true, true);
|
||||
MessagesController.getInstance(currentAccount).putUser(res.user, false);
|
||||
ConnectionsManager.getInstance(currentAccount).updateDcSettings();
|
||||
needFinishActivity(false, res.setup_password_required, res.otherwise_relogin_days);
|
||||
onAuthSuccess(res);
|
||||
} else {
|
||||
if (error.code == 401) {
|
||||
ConnectionsManager.native_cleanUp(currentAccount, true);
|
||||
|
@ -97,6 +97,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import tw.nekomimi.nekogram.helpers.PasscodeHelper;
|
||||
import tw.nekomimi.nekogram.utils.VibrateUtil;
|
||||
|
||||
public class PasscodeActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||
@ -167,6 +168,14 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter
|
||||
|
||||
private Runnable onShowKeyboardCallback;
|
||||
|
||||
private int account = -1;
|
||||
|
||||
public PasscodeActivity(@PasscodeActivityType int type, int account) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public PasscodeActivity(@PasscodeActivityType int type) {
|
||||
super();
|
||||
this.type = type;
|
||||
@ -1031,18 +1040,24 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isFirst = SharedConfig.passcodeHash.length() == 0;
|
||||
try {
|
||||
SharedConfig.passcodeSalt = new byte[16];
|
||||
Utilities.random.nextBytes(SharedConfig.passcodeSalt);
|
||||
byte[] passcodeBytes = firstPassword.getBytes("UTF-8");
|
||||
byte[] bytes = new byte[32 + passcodeBytes.length];
|
||||
System.arraycopy(SharedConfig.passcodeSalt, 0, bytes, 0, 16);
|
||||
System.arraycopy(passcodeBytes, 0, bytes, 16, passcodeBytes.length);
|
||||
System.arraycopy(SharedConfig.passcodeSalt, 0, bytes, passcodeBytes.length + 16, 16);
|
||||
SharedConfig.passcodeHash = Utilities.bytesToHex(Utilities.computeSHA256(bytes, 0, bytes.length));
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
boolean isFirst;
|
||||
if (account != -1) {
|
||||
isFirst = false;
|
||||
PasscodeHelper.setPasscodeForAccount(firstPassword, account);
|
||||
} else {
|
||||
isFirst = SharedConfig.passcodeHash.length() == 0;
|
||||
try {
|
||||
SharedConfig.passcodeSalt = new byte[16];
|
||||
Utilities.random.nextBytes(SharedConfig.passcodeSalt);
|
||||
byte[] passcodeBytes = firstPassword.getBytes("UTF-8");
|
||||
byte[] bytes = new byte[32 + passcodeBytes.length];
|
||||
System.arraycopy(SharedConfig.passcodeSalt, 0, bytes, 0, 16);
|
||||
System.arraycopy(passcodeBytes, 0, bytes, 16, passcodeBytes.length);
|
||||
System.arraycopy(SharedConfig.passcodeSalt, 0, bytes, passcodeBytes.length + 16, 16);
|
||||
SharedConfig.passcodeHash = Utilities.bytesToHex(Utilities.computeSHA256(bytes, 0, bytes.length));
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
SharedConfig.allowScreenCapture = true;
|
||||
SharedConfig.passcodeType = currentPasswordType;
|
||||
@ -1080,7 +1095,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter
|
||||
onPasscodeError();
|
||||
return;
|
||||
}
|
||||
if (!SharedConfig.checkPasscode(password)) {
|
||||
if (!PasscodeHelper.checkPasscode(getParentActivity(), password) && !SharedConfig.checkPasscode(password)) {
|
||||
SharedConfig.increaseBadPasscodeTries();
|
||||
passwordEditText.setText("");
|
||||
for (CodeNumberField f : codeFieldContainer.codeField) {
|
||||
|
@ -0,0 +1,155 @@
|
||||
package tw.nekomimi.nekogram.helpers;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.LaunchActivity;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class PasscodeHelper {
|
||||
private static final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("nekopasscode", Context.MODE_PRIVATE);
|
||||
|
||||
public static boolean checkPasscode(Activity activity, String passcode) {
|
||||
if (hasPasscodeForAccount(Integer.MAX_VALUE)) {
|
||||
String passcodeHash = preferences.getString("passcodeHash" + Integer.MAX_VALUE, "");
|
||||
String passcodeSaltString = preferences.getString("passcodeSalt" + Integer.MAX_VALUE, "");
|
||||
if (checkPasscodeHash(passcode, passcodeHash, passcodeSaltString)) {
|
||||
for (int a : SharedConfig.activeAccounts) {
|
||||
if (UserConfig.getInstance(a).isClientActivated() && isAccountAllowPanic(a)) {
|
||||
MessagesController.getInstance(a).performLogout(1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int a : SharedConfig.activeAccounts) {
|
||||
if (UserConfig.getInstance(a).isClientActivated() && hasPasscodeForAccount(a)) {
|
||||
String passcodeHash = preferences.getString("passcodeHash" + a, "");
|
||||
String passcodeSaltString = preferences.getString("passcodeSalt" + a, "");
|
||||
if (checkPasscodeHash(passcode, passcodeHash, passcodeSaltString)) {
|
||||
if (activity instanceof LaunchActivity) {
|
||||
LaunchActivity launchActivity = (LaunchActivity) activity;
|
||||
launchActivity.switchToAccount(a, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean checkPasscodeHash(String passcode, String passcodeHash, String passcodeSaltString) {
|
||||
try {
|
||||
byte[] passcodeSalt;
|
||||
if (passcodeSaltString.length() > 0) {
|
||||
passcodeSalt = Base64.decode(passcodeSaltString, Base64.DEFAULT);
|
||||
} else {
|
||||
passcodeSalt = new byte[0];
|
||||
}
|
||||
byte[] passcodeBytes = passcode.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] bytes = new byte[32 + passcodeBytes.length];
|
||||
System.arraycopy(passcodeSalt, 0, bytes, 0, 16);
|
||||
System.arraycopy(passcodeBytes, 0, bytes, 16, passcodeBytes.length);
|
||||
System.arraycopy(passcodeSalt, 0, bytes, passcodeBytes.length + 16, 16);
|
||||
String hash = Utilities.bytesToHex(Utilities.computeSHA256(bytes, 0, bytes.length));
|
||||
return passcodeHash.equals(hash);
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void removePasscodeForAccount(int account) {
|
||||
preferences.edit()
|
||||
.remove("passcodeHash" + account)
|
||||
.remove("passcodeSalt" + account)
|
||||
.remove("hide" + account)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static boolean isAccountAllowPanic(int account) {
|
||||
return preferences.getBoolean("allowPanic" + account, true);
|
||||
}
|
||||
|
||||
public static boolean isAccountHidden(int account) {
|
||||
return hasPasscodeForAccount(account) && preferences.getBoolean("hide" + account, false);
|
||||
}
|
||||
|
||||
public static void setAccountAllowPanic(int account, boolean panic) {
|
||||
preferences.edit()
|
||||
.putBoolean("allowPanic" + account, panic)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void setHideAccount(int account, boolean hide) {
|
||||
preferences.edit()
|
||||
.putBoolean("hide" + account, hide)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void setPasscodeForAccount(String firstPassword, int account) {
|
||||
try {
|
||||
byte[] passcodeSalt = new byte[16];
|
||||
Utilities.random.nextBytes(passcodeSalt);
|
||||
byte[] passcodeBytes = firstPassword.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] bytes = new byte[32 + passcodeBytes.length];
|
||||
System.arraycopy(passcodeSalt, 0, bytes, 0, 16);
|
||||
System.arraycopy(passcodeBytes, 0, bytes, 16, passcodeBytes.length);
|
||||
System.arraycopy(passcodeSalt, 0, bytes, passcodeBytes.length + 16, 16);
|
||||
preferences.edit()
|
||||
.putString("passcodeHash" + account, Utilities.bytesToHex(Utilities.computeSHA256(bytes, 0, bytes.length)))
|
||||
.putString("passcodeSalt" + account, Base64.encodeToString(passcodeSalt, Base64.DEFAULT))
|
||||
.apply();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasPasscodeForAccount(int account) {
|
||||
return preferences.contains("passcodeHash" + account) && preferences.contains("passcodeSalt" + account);
|
||||
}
|
||||
|
||||
public static boolean hasPanicCode() {
|
||||
return hasPasscodeForAccount(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static String getSettingsKey() {
|
||||
var settingsHash = preferences.getString("settingsHash", "");
|
||||
if (!TextUtils.isEmpty(settingsHash)) {
|
||||
return settingsHash;
|
||||
}
|
||||
byte[] bytes = new byte[8];
|
||||
Utilities.random.nextBytes(bytes);
|
||||
var hash = Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
|
||||
preferences.edit().putString("settingsHash", hash).apply();
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static boolean isSettingsHidden() {
|
||||
return preferences.getBoolean("hideSettings", false);
|
||||
}
|
||||
|
||||
public static void setHideSettings(boolean hide) {
|
||||
preferences.edit()
|
||||
.putBoolean("hideSettings", hide)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
return preferences.getAll().size() != 0;
|
||||
}
|
||||
|
||||
public static void clearAll() {
|
||||
preferences.edit().clear().apply();
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package tw.nekomimi.nekogram.helpers;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
|
||||
import tw.nekomimi.nekogram.settings.NekoChatSettingsActivity;
|
||||
import tw.nekomimi.nekogram.settings.NekoAccountSettingsActivity;
|
||||
import tw.nekomimi.nekogram.settings.NekoExperimentalSettingsActivity;
|
||||
import tw.nekomimi.nekogram.settings.NekoGeneralSettingsActivity;
|
||||
import tw.nekomimi.nekogram.settings.NekoPasscodeSettingsActivity;
|
||||
import tw.nekomimi.nekogram.settings.NekoSettingsActivity;
|
||||
|
||||
public class SettingsHelper {
|
||||
|
||||
public static void processDeepLink(Uri uri, Callback callback, Runnable unknown) {
|
||||
if (uri == null) {
|
||||
unknown.run();
|
||||
return;
|
||||
}
|
||||
var segments = uri.getPathSegments();
|
||||
if (segments.isEmpty() || segments.size() > 2 || !"nekosettings".equals(segments.get(0))) {
|
||||
unknown.run();
|
||||
return;
|
||||
}
|
||||
BaseFragment fragment;
|
||||
if (segments.size() == 1) {
|
||||
fragment = new NekoSettingsActivity();
|
||||
} else if (PasscodeHelper.getSettingsKey().equals(segments.get(1))) {
|
||||
fragment = new NekoPasscodeSettingsActivity();
|
||||
} else {
|
||||
switch (segments.get(1)) {
|
||||
case "a":
|
||||
case "account":
|
||||
fragment = new NekoAccountSettingsActivity();
|
||||
break;
|
||||
case "chat":
|
||||
case "chats":
|
||||
case "c":
|
||||
fragment = new NekoChatSettingsActivity();
|
||||
break;
|
||||
case "experimental":
|
||||
case "e":
|
||||
fragment = new NekoExperimentalSettingsActivity();
|
||||
break;
|
||||
case "general":
|
||||
case "g":
|
||||
fragment = new NekoGeneralSettingsActivity();
|
||||
break;
|
||||
default:
|
||||
unknown.run();
|
||||
return;
|
||||
}
|
||||
}
|
||||
callback.presentFragment(fragment);
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void presentFragment(BaseFragment fragment);
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package tw.nekomimi.nekogram.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ContactsController;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.AvatarDrawable;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
public class AccountCell extends FrameLayout {
|
||||
|
||||
private final TextView textView;
|
||||
private final BackupImageView imageView;
|
||||
private final ImageView checkImageView;
|
||||
private final AvatarDrawable avatarDrawable;
|
||||
private boolean needDivider;
|
||||
|
||||
private int accountNumber;
|
||||
|
||||
public AccountCell(Context context) {
|
||||
super(context);
|
||||
|
||||
avatarDrawable = new AvatarDrawable();
|
||||
avatarDrawable.setTextSize(AndroidUtilities.dp(12));
|
||||
|
||||
imageView = new BackupImageView(context);
|
||||
imageView.setRoundRadius(AndroidUtilities.dp(18));
|
||||
addView(imageView, LayoutHelper.createFrame(36, 36, Gravity.LEFT | Gravity.TOP, 16, 10, 0, 0));
|
||||
|
||||
textView = new TextView(context);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
textView.setLines(1);
|
||||
textView.setMaxLines(1);
|
||||
textView.setSingleLine(true);
|
||||
textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 68, 0, 56, 0));
|
||||
|
||||
checkImageView = new ImageView(context);
|
||||
checkImageView.setImageResource(R.drawable.account_check);
|
||||
checkImageView.setScaleType(ImageView.ScaleType.CENTER);
|
||||
checkImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_switchTrackChecked), PorterDuff.Mode.MULTIPLY));
|
||||
addView(checkImageView, LayoutHelper.createFrame(40, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.TOP, 0, 0, 6, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (needDivider) {
|
||||
canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(68), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
imageView.setAlpha(enabled ? 1.0f : 0.5f);
|
||||
textView.setAlpha(enabled ? 1.0f : 0.5f);
|
||||
checkImageView.setAlpha(enabled ? 1.0f : 0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(56) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setAccount(int account, boolean check, boolean divider) {
|
||||
accountNumber = account;
|
||||
TLRPC.User user = UserConfig.getInstance(accountNumber).getCurrentUser();
|
||||
avatarDrawable.setInfo(user);
|
||||
textView.setText(ContactsController.formatName(user.first_name, user.last_name));
|
||||
imageView.getImageReceiver().setCurrentAccount(account);
|
||||
imageView.setForUserOrChat(user, avatarDrawable);
|
||||
checkImageView.setVisibility(check ? VISIBLE : INVISIBLE);
|
||||
needDivider = divider;
|
||||
setWillNotDraw(!divider);
|
||||
}
|
||||
|
||||
public int getAccountNumber() {
|
||||
return accountNumber;
|
||||
}
|
||||
}
|
@ -330,6 +330,10 @@ public abstract class BaseNekoSettingsActivity extends BaseFragment {
|
||||
view = new TextRadioCell(mContext);
|
||||
view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite));
|
||||
break;
|
||||
case 11:
|
||||
view = new AccountCell(mContext);
|
||||
view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite));
|
||||
break;
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));
|
||||
|
@ -0,0 +1,330 @@
|
||||
package tw.nekomimi.nekogram.settings;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.telegram.messenger.AccountInstance;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.NotificationCenter;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.ui.ActionBar.AlertDialog;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Cells.HeaderCell;
|
||||
import org.telegram.ui.Cells.TextCheckCell;
|
||||
import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
||||
import org.telegram.ui.Cells.TextSettingsCell;
|
||||
import org.telegram.ui.Components.BulletinFactory;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.URLSpanNoUnderline;
|
||||
import org.telegram.ui.PasscodeActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import tw.nekomimi.nekogram.helpers.PasscodeHelper;
|
||||
|
||||
public class NekoPasscodeSettingsActivity extends BaseNekoSettingsActivity {
|
||||
|
||||
private boolean passcodeSet;
|
||||
|
||||
private int showInSettingsRow;
|
||||
private int showInSettings2Row;
|
||||
|
||||
private int accountsStartRow;
|
||||
private int accountsEndRow;
|
||||
|
||||
private int panicCodeRow;
|
||||
private int setPanicCodeRow;
|
||||
private int removePanicCodeRow;
|
||||
private int panicCode2Row;
|
||||
|
||||
private int clearPasscodesRow;
|
||||
private int clearPasscodes2Row;
|
||||
|
||||
private final ArrayList<Integer> accounts = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean onFragmentCreate() {
|
||||
for (int a : SharedConfig.activeAccounts) {
|
||||
var u = AccountInstance.getInstance(a).getUserConfig().getCurrentUser();
|
||||
if (u != null) {
|
||||
accounts.add(a);
|
||||
}
|
||||
}
|
||||
return super.onFragmentCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onItemClick(View view, int position, float x, float y) {
|
||||
if (!passcodeSet) {
|
||||
BulletinFactory.of(this).createErrorBulletin(LocaleController.getString("PasscodeNeeded", R.string.PasscodeNeeded)).show();
|
||||
return;
|
||||
}
|
||||
if (position > accountsStartRow && position < accountsEndRow) {
|
||||
var account = accounts.get(position - accountsStartRow - 1);
|
||||
var builder = new AlertDialog.Builder(getParentActivity());
|
||||
|
||||
var linearLayout = new LinearLayout(getParentActivity());
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
if (PasscodeHelper.hasPasscodeForAccount(account)) {
|
||||
TextCheckCell hideAccount = new TextCheckCell(getParentActivity(), 23, true);
|
||||
hideAccount.setTextAndCheck(LocaleController.getString("PasscodeHideAccount", R.string.PasscodeHideAccount), PasscodeHelper.isAccountHidden(account), false);
|
||||
hideAccount.setOnClickListener(view13 -> {
|
||||
boolean hide = !hideAccount.isChecked();
|
||||
PasscodeHelper.setHideAccount(account, hide);
|
||||
hideAccount.setChecked(hide);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.mainUserInfoChanged);
|
||||
});
|
||||
hideAccount.setBackground(Theme.getSelectorDrawable(false));
|
||||
linearLayout.addView(hideAccount, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
TextCheckCell allowPanic = new TextCheckCell(getParentActivity(), 23, true);
|
||||
allowPanic.setTextAndCheck(LocaleController.getString("PasscodeAllowPanic", R.string.PasscodeAllowPanic), PasscodeHelper.isAccountAllowPanic(account), false);
|
||||
allowPanic.setOnClickListener(view13 -> {
|
||||
boolean hide = !allowPanic.isChecked();
|
||||
PasscodeHelper.setAccountAllowPanic(account, hide);
|
||||
allowPanic.setChecked(hide);
|
||||
});
|
||||
allowPanic.setBackground(Theme.getSelectorDrawable(false));
|
||||
linearLayout.addView(allowPanic, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
AlertDialog.AlertDialogCell editPasscode = new AlertDialog.AlertDialogCell(getParentActivity(), null);
|
||||
editPasscode.setTextAndIcon(PasscodeHelper.hasPasscodeForAccount(account) ? LocaleController.getString("PasscodeEdit", R.string.PasscodeEdit) : LocaleController.getString("PasscodeSet", R.string.PasscodeSet), 0);
|
||||
editPasscode.setOnClickListener(view1 -> {
|
||||
builder.getDismissRunnable().run();
|
||||
presentFragment(new PasscodeActivity(PasscodeActivity.TYPE_SETUP_CODE, account));
|
||||
});
|
||||
editPasscode.setBackground(Theme.getSelectorDrawable(false));
|
||||
linearLayout.addView(editPasscode, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
|
||||
if (PasscodeHelper.hasPasscodeForAccount(account)) {
|
||||
AlertDialog.AlertDialogCell removePasscode = new AlertDialog.AlertDialogCell(getParentActivity(), null);
|
||||
removePasscode.setTextAndIcon(LocaleController.getString("PasscodeRemove", R.string.PasscodeRemove), 0);
|
||||
removePasscode.setOnClickListener(view12 -> {
|
||||
AlertDialog alertDialog = new AlertDialog.Builder(getParentActivity())
|
||||
.setTitle(LocaleController.getString(R.string.PasscodeRemove))
|
||||
.setMessage(LocaleController.getString(R.string.PasscodeRemoveConfirmMessage))
|
||||
.setNegativeButton(LocaleController.getString(R.string.Cancel), null)
|
||||
.setPositiveButton(LocaleController.getString(R.string.DisablePasscodeTurnOff), (dialog, which) -> {
|
||||
var hidden = PasscodeHelper.isAccountHidden(account);
|
||||
PasscodeHelper.removePasscodeForAccount(account);
|
||||
listAdapter.notifyItemChanged(position);
|
||||
if (hidden) {
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.mainUserInfoChanged);
|
||||
}
|
||||
}).create();
|
||||
showDialog(alertDialog);
|
||||
((TextView) alertDialog.getButton(Dialog.BUTTON_POSITIVE)).setTextColor(Theme.getColor(Theme.key_dialogTextRed));
|
||||
});
|
||||
removePasscode.setBackground(Theme.getSelectorDrawable(false));
|
||||
linearLayout.addView(removePasscode, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
builder.setView(linearLayout);
|
||||
showDialog(builder.create());
|
||||
} else if (position == clearPasscodesRow) {
|
||||
PasscodeHelper.clearAll();
|
||||
finishFragment();
|
||||
} else if (position == setPanicCodeRow) {
|
||||
presentFragment(new PasscodeActivity(PasscodeActivity.TYPE_SETUP_CODE, Integer.MAX_VALUE));
|
||||
} else if (position == removePanicCodeRow) {
|
||||
AlertDialog alertDialog = new AlertDialog.Builder(getParentActivity())
|
||||
.setTitle(LocaleController.getString(R.string.PasscodePanicCodeRemove))
|
||||
.setMessage(LocaleController.getString(R.string.PasscodePanicCodeRemoveConfirmMessage))
|
||||
.setNegativeButton(LocaleController.getString(R.string.Cancel), null)
|
||||
.setPositiveButton(LocaleController.getString(R.string.DisablePasscodeTurnOff), (dialog, which) -> {
|
||||
PasscodeHelper.removePasscodeForAccount(Integer.MAX_VALUE);
|
||||
listAdapter.notifyItemChanged(setPanicCodeRow);
|
||||
listAdapter.notifyItemRemoved(removePanicCodeRow);
|
||||
updateRows();
|
||||
}).create();
|
||||
showDialog(alertDialog);
|
||||
((TextView) alertDialog.getButton(Dialog.BUTTON_POSITIVE)).setTextColor(Theme.getColor(Theme.key_dialogTextRed));
|
||||
} else if (position == showInSettingsRow) {
|
||||
PasscodeHelper.setHideSettings(!PasscodeHelper.isSettingsHidden());
|
||||
if (view instanceof TextCheckCell) {
|
||||
((TextCheckCell) view).setChecked(!PasscodeHelper.isSettingsHidden());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseListAdapter createAdapter(Context context) {
|
||||
return new ListAdapter(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getActionBarTitle() {
|
||||
return LocaleController.getString("PasscodeNeko", R.string.PasscodeNeko);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKey() {
|
||||
return PasscodeHelper.getSettingsKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
passcodeSet = SharedConfig.passcodeHash.length() > 0;
|
||||
if (!passcodeSet) {
|
||||
BulletinFactory.of(this).createErrorBulletin(LocaleController.getString("PasscodeNeeded", R.string.PasscodeNeeded)).show();
|
||||
}
|
||||
updateRows();
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateRows() {
|
||||
super.updateRows();
|
||||
|
||||
showInSettingsRow = rowCount++;
|
||||
showInSettings2Row = rowCount++;
|
||||
|
||||
accountsStartRow = rowCount++;
|
||||
rowCount += accounts.size();
|
||||
accountsEndRow = rowCount++;
|
||||
|
||||
panicCodeRow = rowCount++;
|
||||
setPanicCodeRow = rowCount++;
|
||||
if (!PasscodeHelper.hasPanicCode()) {
|
||||
removePanicCodeRow = -1;
|
||||
} else {
|
||||
removePanicCodeRow = rowCount++;
|
||||
}
|
||||
panicCode2Row = rowCount++;
|
||||
|
||||
if (false) {
|
||||
clearPasscodesRow = rowCount++;
|
||||
clearPasscodes2Row = rowCount++;
|
||||
} else {
|
||||
clearPasscodesRow = -1;
|
||||
clearPasscodes2Row = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private class ListAdapter extends BaseListAdapter {
|
||||
|
||||
public ListAdapter(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
switch (holder.getItemViewType()) {
|
||||
case 1: {
|
||||
if (position == clearPasscodes2Row) {
|
||||
holder.itemView.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
|
||||
} else {
|
||||
holder.itemView.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
TextSettingsCell textCell = (TextSettingsCell) holder.itemView;
|
||||
textCell.setCanDisable(true);
|
||||
textCell.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
if (position == setPanicCodeRow) {
|
||||
textCell.setText(PasscodeHelper.hasPanicCode() ? LocaleController.getString("PasscodePanicCodeEdit", R.string.PasscodePanicCodeEdit) : LocaleController.getString("PasscodePanicCodeSet", R.string.PasscodePanicCodeSet), removePanicCodeRow != -1);
|
||||
} else if (position == clearPasscodesRow) {
|
||||
textCell.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText));
|
||||
textCell.setText("Clear passcodes", false);
|
||||
} else if (position == removePanicCodeRow) {
|
||||
textCell.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText));
|
||||
textCell.setText(LocaleController.getString("PasscodePanicCodeRemove", R.string.PasscodePanicCodeRemove), false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
TextCheckCell textCell = (TextCheckCell) holder.itemView;
|
||||
textCell.setEnabled(passcodeSet, null);
|
||||
if (position == showInSettingsRow) {
|
||||
textCell.setTextAndCheck(LocaleController.getString("PasscodeShowInSettings", R.string.PasscodeShowInSettings), !PasscodeHelper.isSettingsHidden(), false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
HeaderCell cell = (HeaderCell) holder.itemView;
|
||||
cell.setEnabled(passcodeSet, null);
|
||||
if (position == accountsStartRow) {
|
||||
cell.setText(LocaleController.getString("Account", R.string.Account));
|
||||
} else if (position == panicCodeRow) {
|
||||
cell.setText(LocaleController.getString("PasscodePanicCode", R.string.PasscodePanicCode));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
TextInfoPrivacyCell cell = (TextInfoPrivacyCell) holder.itemView;
|
||||
cell.setEnabled(passcodeSet, null);
|
||||
cell.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
|
||||
if (position == accountsEndRow) {
|
||||
cell.setText(LocaleController.getString("PasscodeAbout", R.string.PasscodeAbout));
|
||||
} else if (position == panicCode2Row) {
|
||||
cell.setText(LocaleController.getString("PasscodePanicCodeAbout", R.string.PasscodePanicCodeAbout));
|
||||
if (clearPasscodesRow == -1) {
|
||||
cell.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
|
||||
}
|
||||
} else if (position == showInSettings2Row) {
|
||||
var link = String.format(Locale.ENGLISH, "https://t.me/nekosettings/%s", PasscodeHelper.getSettingsKey());
|
||||
var stringBuilder = new SpannableStringBuilder(AndroidUtilities.replaceTags(LocaleController.getString("PasscodeShowInSettingsAbout", R.string.PasscodeShowInSettingsAbout)));
|
||||
stringBuilder.append("\n").append(link);
|
||||
stringBuilder.setSpan(new URLSpanNoUnderline(null) {
|
||||
@Override
|
||||
public void onClick(@NonNull View view) {
|
||||
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
android.content.ClipData clip = android.content.ClipData.newPlainText("label", link);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
BulletinFactory.of(NekoPasscodeSettingsActivity.this).createCopyLinkBulletin().show();
|
||||
}
|
||||
}, stringBuilder.length() - link.length(), stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
cell.setText(stringBuilder);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 11: {
|
||||
AccountCell cell = (AccountCell) holder.itemView;
|
||||
cell.setEnabled(passcodeSet);
|
||||
int account = accounts.get(position - accountsStartRow - 1);
|
||||
cell.setAccount(account, PasscodeHelper.hasPasscodeForAccount(account), position + 1 != accountsEndRow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(RecyclerView.ViewHolder holder) {
|
||||
return passcodeSet && super.isEnabled(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == clearPasscodes2Row) {
|
||||
return 1;
|
||||
} else if (position == clearPasscodesRow || position == setPanicCodeRow || position == removePanicCodeRow) {
|
||||
return 2;
|
||||
} else if (position == showInSettingsRow) {
|
||||
return 3;
|
||||
} else if (position == accountsStartRow || position == panicCodeRow) {
|
||||
return 4;
|
||||
} else if (position == showInSettings2Row || position == accountsEndRow || position == panicCode2Row) {
|
||||
return 7;
|
||||
} else if (position > accountsStartRow && position < accountsEndRow) {
|
||||
return 11;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -60,6 +60,7 @@ import java.util.function.Function;
|
||||
import kotlin.text.StringsKt;
|
||||
|
||||
import tw.nekomimi.nekogram.DatacenterActivity;
|
||||
import tw.nekomimi.nekogram.helpers.PasscodeHelper;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.EnvUtil;
|
||||
import tw.nekomimi.nekogram.utils.FileUtil;
|
||||
@ -77,6 +78,7 @@ public class NekoSettingsActivity extends BaseFragment {
|
||||
private int generalRow;
|
||||
private int accountRow;
|
||||
private int chatRow;
|
||||
private int passcodeRow;
|
||||
private int experimentRow;
|
||||
private int categories2Row;
|
||||
|
||||
@ -172,6 +174,8 @@ public class NekoSettingsActivity extends BaseFragment {
|
||||
presentFragment(new NekoGeneralSettingsActivity());
|
||||
} else if (position == accountRow) {
|
||||
presentFragment(new NekoAccountSettingsActivity());
|
||||
} else if (position == passcodeRow) {
|
||||
presentFragment(new NekoPasscodeSettingsActivity());
|
||||
} else if (position == experimentRow) {
|
||||
presentFragment(new NekoExperimentalSettingsActivity());
|
||||
} else if (position == channelRow) {
|
||||
@ -380,6 +384,11 @@ public class NekoSettingsActivity extends BaseFragment {
|
||||
generalRow = rowCount++;
|
||||
accountRow = rowCount++;
|
||||
chatRow = rowCount++;
|
||||
if (!PasscodeHelper.isSettingsHidden()) {
|
||||
passcodeRow = rowCount++;
|
||||
} else {
|
||||
passcodeRow = -1;
|
||||
}
|
||||
experimentRow = rowCount++;
|
||||
categories2Row = rowCount++;
|
||||
|
||||
@ -472,6 +481,8 @@ public class NekoSettingsActivity extends BaseFragment {
|
||||
textCell.setTextAndIcon(LocaleController.getString("Chat", R.string.Chat), R.drawable.menu_chats, true);
|
||||
} else if (position == generalRow) {
|
||||
textCell.setTextAndIcon(LocaleController.getString("General", R.string.General), R.drawable.msg_theme, true);
|
||||
} else if (position == passcodeRow) {
|
||||
textCell.setTextAndIcon(LocaleController.getString("PasscodeNeko", R.string.PasscodeNeko), R.drawable.msg_permissions, true);
|
||||
} else if (position == experimentRow) {
|
||||
textCell.setTextAndIcon(LocaleController.getString("Experiment", R.string.Experiment), R.drawable.msg_fave, true);
|
||||
} else if (position == accountRow) {
|
||||
@ -555,7 +566,7 @@ public class NekoSettingsActivity extends BaseFragment {
|
||||
public int getItemViewType(int position) {
|
||||
if (position == categories2Row || position == about2Row) {
|
||||
return 1;
|
||||
} else if (position == chatRow || position == accountRow || position == generalRow || position == experimentRow) {
|
||||
} else if (position == chatRow || position == accountRow || position == generalRow || position == passcodeRow || position == experimentRow) {
|
||||
return 2;
|
||||
} else if (position == categoriesRow || position == aboutRow) {
|
||||
return 4;
|
||||
|
@ -149,4 +149,22 @@
|
||||
<string name="DatacenterStatusAbout">检查 Telegram 的**数据中心**的状态。</string>
|
||||
<string name="DatacenterStatus">数据中心状态</string>
|
||||
<string name="enhancedFileLoader">加速上传和下载</string>
|
||||
<string name="UnknownNekoSettingsOption">没有这样的喵设置选项。</string>
|
||||
<string name="PasscodeNeeded">您必须先启用锁定码</string>
|
||||
<string name="PasscodeNeko">锁定码</string>
|
||||
<string name="PasscodeShowInSettings">在喵设置中显示</string>
|
||||
<string name="PasscodeShowInSettingsAbout">隐藏后,您**只能**通过链接打开此页面:</string>
|
||||
<string name="PasscodeSet">设置锁定码</string>
|
||||
<string name="PasscodeEdit">更改锁定码</string>
|
||||
<string name="PasscodeRemove">移除锁定码</string>
|
||||
<string name="PasscodeHideAccount">隐藏账户</string>
|
||||
<string name="PasscodeAllowPanic">使用紧急代码退出登录</string>
|
||||
<string name="PasscodeAbout">为每个账户设置不同的锁定码,并通过输入相应的锁定码在它们之间切换。</string>
|
||||
<string name="PasscodePanicCode">紧急代码</string>
|
||||
<string name="PasscodePanicCodeSet">设置紧急代码</string>
|
||||
<string name="PasscodePanicCodeEdit">更改紧急代码</string>
|
||||
<string name="PasscodePanicCodeRemove">关闭紧急代码</string>
|
||||
<string name="PasscodePanicCodeRemoveConfirmMessage">您确定要关闭紧急代码吗?</string>
|
||||
<string name="PasscodeRemoveConfirmMessage">您确定要移除这个账户的锁定码吗?</string>
|
||||
<string name="PasscodePanicCodeAbout">如果出现问题,使用紧急代码退出登录账户。</string>
|
||||
</resources>
|
||||
|
@ -153,4 +153,22 @@
|
||||
<string name="enhancedFileLoader">Enhance Upload and Download speed</string>
|
||||
<string name="mapDriftingFixForGoogleMaps">Fix Google Maps drifting in China</string>
|
||||
<string name="useOSMDroidMap">Use OSMDroid Map</string>
|
||||
<string name="UnknownNekoSettingsOption">There is no such Neko Settings option.</string>
|
||||
<string name="PasscodeNeeded">You have to enable passcode lock first</string>
|
||||
<string name="PasscodeNeko">Passcode</string>
|
||||
<string name="PasscodeShowInSettings">Show in Neko Settings</string>
|
||||
<string name="PasscodeShowInSettingsAbout">After hiding, you can **ONLY** open this page by link:</string>
|
||||
<string name="PasscodeSet">Set passcode</string>
|
||||
<string name="PasscodeEdit">Change passcode</string>
|
||||
<string name="PasscodeRemove">Remove passcode</string>
|
||||
<string name="PasscodeHideAccount">Hide account</string>
|
||||
<string name="PasscodeAllowPanic">Logout with panic code</string>
|
||||
<string name="PasscodeAbout">Set different passcodes for each account, and switch between them by entering the corresponding passcode.</string>
|
||||
<string name="PasscodePanicCode">Panic code</string>
|
||||
<string name="PasscodePanicCodeSet">Set panic code</string>
|
||||
<string name="PasscodePanicCodeEdit">Change panic code</string>
|
||||
<string name="PasscodePanicCodeRemove">Turn off panic code</string>
|
||||
<string name="PasscodePanicCodeRemoveConfirmMessage">Are you sure you want to turn off panic code?</string>
|
||||
<string name="PasscodeRemoveConfirmMessage">Are you sure you want to remove passcode for this account?</string>
|
||||
<string name="PasscodePanicCodeAbout">Use the panic code to log out accounts if something goes wrong.</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user