diff --git a/TMessagesProj/proguard-rules.pro b/TMessagesProj/proguard-rules.pro index 58c449209..c378fe225 100644 --- a/TMessagesProj/proguard-rules.pro +++ b/TMessagesProj/proguard-rules.pro @@ -63,6 +63,8 @@ java.lang.Object readResolve(); } +-keep class tw.nekomimi.nekogram.InternalUpdater$ReleaseMetadata { *; } +-keep class tw.nekomimi.nekogram.InternalUpdater$ApkMetadata { *; } # Constant folding for resource integers may mean that a resource passed to this method appears to be unused. Keep the method to prevent this from happening. -keep class com.google.android.exoplayer2.upstream.RawResourceDataSource { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index dafee37d6..490fcc1fe 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -33,13 +33,14 @@ public class BuildVars { public static boolean isUnknown = !BuildConfig.BUILD_TYPE.startsWith("release"); public static boolean isMini = BuildConfig.FLAVOR.startsWith("mini"); public static boolean isPlay = BuildConfig.FLAVOR.endsWith("Play"); + public static boolean isFdroid = BuildConfig.BUILD_TYPE.toLowerCase().contains("fdroid"); static { try { PackageInfo info = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); BUILD_VERSION = info.versionCode; - BUILD_VERSION_STRING = info.packageName; + BUILD_VERSION_STRING = info.versionName; } catch (PackageManager.NameNotFoundException e) { BUILD_VERSION = BuildConfig.VERSION_CODE; BUILD_VERSION_STRING = BuildConfig.VERSION_NAME; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index eb5dd5a36..9ac025eb5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -166,11 +166,15 @@ import org.telegram.ui.Components.ViewPagerFixed; import java.util.ArrayList; +import cn.hutool.core.date.DateTime; import kotlin.Unit; import tw.nekomimi.nekogram.BottomBuilder; +import tw.nekomimi.nekogram.InternalUpdater; import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.NekoXConfig; import tw.nekomimi.nekogram.utils.PrivacyUtil; import tw.nekomimi.nekogram.utils.ProxyUtil; +import tw.nekomimi.nekogram.utils.UIUtil; import tw.nekomimi.nekogram.utils.UpdateUtil; import tw.nekomimi.nekogram.utils.VibrateUtil; @@ -3510,6 +3514,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. PrivacyUtil.postCheckAll(getParentActivity(), currentAccount); UpdateUtil.postCheckFollowChannel(getParentActivity(), currentAccount); + if (!BuildVars.isFdroid && NekoXConfig.autoUpdateReleaseChannel != 0 && DateTime.now().compareTo(NekoXConfig.nextUpdateCheck) > 0) + UIUtil.runOnIoDispatcher(() -> InternalUpdater.checkUpdate(getParentActivity(), true), 6000); return fragmentView; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index de3c8418e..31a2d7a79 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -175,6 +175,7 @@ import cn.hutool.core.util.StrUtil; import kotlin.Unit; import libv2ray.Libv2ray; import tw.nekomimi.nekogram.BottomBuilder; +import tw.nekomimi.nekogram.InternalUpdater; import tw.nekomimi.nekogram.NekoConfig; import tw.nekomimi.nekogram.NekoXConfig; import tw.nekomimi.nekogram.NekoXSettingActivity; @@ -2934,6 +2935,48 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return Unit.INSTANCE; }); + if (!BuildVars.isFdroid) { + builder.addItem(LocaleController.getString("CheckUpdate", R.string.CheckUpdate), R.drawable.baseline_search_24, (it) -> { + UIUtil.runOnIoDispatcher(() -> InternalUpdater.checkUpdate(getParentActivity(), false)); + return Unit.INSTANCE; + }); + + String currentChannel = " - "; + switch (NekoXConfig.autoUpdateReleaseChannel) { + case 0: + currentChannel += LocaleController.getString("AutoCheckUpdateOFF", R.string.AutoCheckUpdateOFF); + break; + case 1: + currentChannel += LocaleController.getString("AutoCheckUpdateStable", R.string.AutoCheckUpdateStable); + break; + case 2: + currentChannel += LocaleController.getString("AutoCheckUpdateRc", R.string.AutoCheckUpdateRc); + break; + } + + builder.addItem(LocaleController.getString("AutoCheckUpdateSwitch", R.string.AutoCheckUpdateSwitch) + currentChannel, R.drawable.update_black_24, (it) -> { + BottomBuilder switchBuilder = new BottomBuilder(getParentActivity()); + switchBuilder.addTitle(LocaleController.getString("AutoCheckUpdateSwitch", R.string.AutoCheckUpdateSwitch)); + switchBuilder.addRadioItem(LocaleController.getString("AutoCheckUpdateOFF", R.string.AutoCheckUpdateOFF), NekoXConfig.autoUpdateReleaseChannel == 0, (radioButtonCell) -> { + NekoXConfig.setAutoUpdateReleaseChannel(0); + switchBuilder.doRadioCheck(radioButtonCell); + return Unit.INSTANCE; + }); + switchBuilder.addRadioItem(LocaleController.getString("AutoCheckUpdateStable", R.string.AutoCheckUpdateStable), NekoXConfig.autoUpdateReleaseChannel == 1, (radioButtonCell) -> { + NekoXConfig.setAutoUpdateReleaseChannel(1); + switchBuilder.doRadioCheck(radioButtonCell); + return Unit.INSTANCE; + }); + switchBuilder.addRadioItem(LocaleController.getString("AutoCheckUpdateRc", R.string.AutoCheckUpdateRc), NekoXConfig.autoUpdateReleaseChannel == 2, (radioButtonCell) -> { + NekoXConfig.setAutoUpdateReleaseChannel(2); + switchBuilder.doRadioCheck(radioButtonCell); + return Unit.INSTANCE; + }); + showDialog(switchBuilder.create()); + return Unit.INSTANCE; + }); + } + if (NekoXConfig.developerModeEntrance || NekoXConfig.developerMode || ArrayUtil.contains(NekoXConfig.developers, getUserConfig().clientUserId)) { builder.addItem(LocaleController.getString("DeveloperSettings", R.string.DeveloperSettings), R.drawable.baseline_developer_mode_24, (it) -> { BottomBuilder devBuilder = new BottomBuilder(ProfileActivity.this.getParentActivity()); @@ -3235,7 +3278,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. avatarContainer = new FrameLayout(context); avatarContainer2 = new FrameLayout(context); AndroidUtilities.updateViewVisibilityAnimated(avatarContainer2, true, 1f, false); - frameLayout.addView(avatarContainer2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + frameLayout.addView(avatarContainer2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); avatarContainer.setPivotX(0); avatarContainer.setPivotY(0); avatarContainer2.addView(avatarContainer, LayoutHelper.createFrame(42, 42, Gravity.TOP | Gravity.LEFT, 64, 0, 0, 0)); @@ -3581,6 +3624,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. pinchToZoomHelper = new PinchToZoomHelper(decorView) { Paint statusBarPaint; + @Override protected void invalidateViews() { super.invalidateViews(); diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/InternalUpdater.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/InternalUpdater.java new file mode 100644 index 000000000..87e48d89f --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/InternalUpdater.java @@ -0,0 +1,108 @@ +package tw.nekomimi.nekogram; + +import android.content.Context; +import android.widget.Toast; + +import com.google.gson.Gson; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildConfig; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.browser.Browser; +import org.telegram.ui.ActionBar.AlertDialog; + +import cn.hutool.core.date.DateField; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateTime; +import cn.hutool.http.HttpRequest; +import tw.nekomimi.nekogram.utils.FileUtil; + + +public class InternalUpdater { + private static final String API_URL_RELEASE = "https://api.github.com/repos/NekoX-Dev/NekoX/releases?per_page=10"; + + private static class ReleaseMetadata { + String name; + String body; + String published_at; + String html_url; + ApkMetadata[] assets; + } + + private static class ApkMetadata { + String name; + String browser_download_url; + } + + private static ApkMetadata matchBuild(ApkMetadata[] apks) { + String target = BuildConfig.FLAVOR + "-" + FileUtil.getAbi() + "-" + BuildConfig.BUILD_TYPE + ".apk"; + FileLog.e(target); + for (ApkMetadata apk : apks) { + if (apk.name.contains(target)) + return apk; + } + return null; + } + + public static void checkUpdate(Context ctx, boolean isAutoCheck) { + if (BuildVars.isFdroid) + return; + try { + NekoXConfig.setNextUpdateCheck(DateTime.now().offsetNew(DateField.HOUR, 24)); + + String ret = HttpRequest.get(API_URL_RELEASE).header("accept", "application/vnd.github.v3+json").execute().body(); + ReleaseMetadata[] releases = new Gson().fromJson(ret, ReleaseMetadata[].class); + + ReleaseMetadata release = null; + for (ReleaseMetadata rel : releases) { + if (rel.name.contains("rc") && NekoXConfig.autoUpdateReleaseChannel < 2 || rel.name.contains("preview") && NekoXConfig.autoUpdateReleaseChannel < 3) + continue; + if (rel.name.equals("v" + BuildConfig.VERSION_NAME)) + break; + release = rel; + break; + } + if (release == null) { + FileLog.d("no update"); + if (!isAutoCheck) + AndroidUtilities.runOnUIThread(() -> Toast.makeText(ctx, LocaleController.getString("VersionUpdateNoUpdate", R.string.VersionUpdateNoUpdate), Toast.LENGTH_SHORT).show()); + return; + } else if (release.name.equals(NekoXConfig.ignoredUpdateTag) && isAutoCheck) { + FileLog.d("ignored tag " + release.name); + return; + } + + final ApkMetadata apk = matchBuild(release.assets); + ReleaseMetadata finalRelease = release; + AndroidUtilities.runOnUIThread(() -> { + AlertDialog.Builder builder = new AlertDialog.Builder(ctx); + builder.setTitle(LocaleController.getString("VersionUpdateTitle", R.string.VersionUpdateTitle)); + + String message = finalRelease.name + " " + LocaleController.formatDateChat(DateTime.of(finalRelease.published_at, DatePattern.UTC_PATTERN).toTimestamp().getTime() / 1000) + "\n\n"; + if (apk == null) + message += LocaleController.getString("VersionUpdateVariantNotMatch", R.string.VersionUpdateVariantNotMatch); + else + message += apk.name.replace(".apk", ""); + builder.setMessage(message); + + builder.setPositiveButton(LocaleController.getString("VersionUpdateConfirm", R.string.VersionUpdateConfirm), (dialog, which) -> { + if (apk != null) + Browser.openUrl(ctx, apk.browser_download_url); + else + Browser.openUrl(ctx, finalRelease.html_url); + }); + builder.setNeutralButton(LocaleController.getString("VersionUpdateIgnore", R.string.VersionUpdateIgnore), (dialog, which) -> NekoXConfig.setIgnoredUpdateTag(finalRelease.name)); + builder.setNegativeButton(LocaleController.getString("VersionUpdateNotNow", R.string.VersionUpdateNotNow), (dialog, which) -> NekoXConfig.setNextUpdateCheck(DateTime.now().offsetNew(DateField.HOUR, 24 * 3))); + builder.show(); + }); + } catch (Exception e) { + FileLog.e(e); + if (!isAutoCheck) + AndroidUtilities.runOnUIThread(() -> Toast.makeText(ctx, "An exception occurred during checking updates.", Toast.LENGTH_SHORT).show()); + } + } + +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoXConfig.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoXConfig.java index cba7fbbf9..ef11b6bd4 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoXConfig.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoXConfig.java @@ -6,6 +6,8 @@ import org.telegram.messenger.BuildConfig; import org.telegram.messenger.BuildVars; import org.telegram.messenger.NotificationCenter; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateTime; import tw.nekomimi.nekogram.database.NitritesKt; public class NekoXConfig { @@ -37,6 +39,10 @@ public class NekoXConfig { public static boolean enableStickerPin = preferences.getBoolean("enableStickerPin", false); + public static int autoUpdateReleaseChannel = preferences.getInt("autoUpdateReleaseChannel", 2); + public static String ignoredUpdateTag = preferences.getString("ignoredUpdateTag", ""); + public static DateTime nextUpdateCheck = DateTime.of(preferences.getString("nextUpdateCheck", "2021-01-01T00:00:00Z"), DatePattern.UTC_PATTERN); + public static void toggleDeveloperMode() { @@ -158,5 +164,17 @@ public class NekoXConfig { } + public static void setAutoUpdateReleaseChannel(int channel) { + preferences.edit().putInt("autoUpdateReleaseChannel", autoUpdateReleaseChannel = channel).apply(); + } + + public static void setIgnoredUpdateTag(String ignored) { + preferences.edit().putString("ignoredUpdateTag", ignoredUpdateTag = ignored).apply(); + } + + public static void setNextUpdateCheck(DateTime dateTime) { + nextUpdateCheck = dateTime; + preferences.edit().putString("nextUpdateCheck", dateTime.toString(DatePattern.UTC_PATTERN)).apply(); + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable-hdpi/update_black_24.png b/TMessagesProj/src/main/res/drawable-hdpi/update_black_24.png new file mode 100644 index 000000000..1c51a6cc6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/update_black_24.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/update_black_24.png b/TMessagesProj/src/main/res/drawable-mdpi/update_black_24.png new file mode 100644 index 000000000..8b9eb203d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/update_black_24.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/update_black_24.png b/TMessagesProj/src/main/res/drawable-xhdpi/update_black_24.png new file mode 100644 index 000000000..77d22daf7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/update_black_24.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/update_black_24.png b/TMessagesProj/src/main/res/drawable-xxhdpi/update_black_24.png new file mode 100644 index 000000000..6b3b2af9a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/update_black_24.png differ diff --git a/TMessagesProj/src/main/res/values/strings_nekox.xml b/TMessagesProj/src/main/res/values/strings_nekox.xml index 94270b6c6..64df5a857 100644 --- a/TMessagesProj/src/main/res/values/strings_nekox.xml +++ b/TMessagesProj/src/main/res/values/strings_nekox.xml @@ -237,4 +237,14 @@ Import settings 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. The payment function has been removed. + New Version Available + Version variants fail to match automatically.\nPlease download manually from GitHub. + UPDATE + Ignore + Not now + No Update. + OFF + Automatic Update + Stable + Release Candidate \ No newline at end of file