diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..1ac4798 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index bf1d24f..e9cb941 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,8 @@ apply plugin: 'com.android.application' -apply plugin: "androidx.navigation.safeargs" apply plugin: 'org.greenrobot.greendao' +apply plugin: 'androidx.navigation.safeargs' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 28 @@ -57,14 +59,18 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.google.android.material:material:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'androidx.navigation:navigation-fragment:2.3.0-alpha04' - implementation 'androidx.navigation:navigation-ui:2.3.0-alpha04' + def nav_version = "2.3.0-alpha04" + implementation "androidx.navigation:navigation-fragment:$nav_version" + implementation "androidx.navigation:navigation-ui:$nav_version" implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'com.madgag.spongycastle:core:1.54.0.0' implementation 'com.madgag.spongycastle:prov:1.54.0.0' implementation 'com.madgag.spongycastle:pkix:1.54.0.0' implementation 'com.madgag.spongycastle:pg:1.54.0.0' - implementation 'com.afollestad.material-dialogs:core:0.9.6.0' + implementation 'com.afollestad.material-dialogs:core:3.3.0' + implementation 'com.afollestad.material-dialogs:input:3.3.0' + implementation 'com.afollestad.material-dialogs:lifecycle:3.3.0' + implementation 'com.lmntrx.android.library.livin.missme:missme:0.1.5' // https://mvnrepository.com/artifact/com.jakewharton/butterknife implementation 'com.jakewharton:butterknife:10.2.1' implementation 'androidx.recyclerview:recyclerview:1.1.0' diff --git a/app/src/main/assets/apk/StardewModdingAPI.dll b/app/src/main/assets/apk/StardewModdingAPI.dll index b01596a..02ac08e 100644 Binary files a/app/src/main/assets/apk/StardewModdingAPI.dll and b/app/src/main/assets/apk/StardewModdingAPI.dll differ diff --git a/app/src/main/assets/downloadable_content_list.json b/app/src/main/assets/downloadable_content_list.json index ab02767..ed46605 100644 --- a/app/src/main/assets/downloadable_content_list.json +++ b/app/src/main/assets/downloadable_content_list.json @@ -1,5 +1,5 @@ { - "version": 8, + "version": 9, "contents": [ { "type": "COMPAT", @@ -14,8 +14,8 @@ "name": "SMAPI for Galaxy Store", "assetPath": "compat/samsung_138/", "description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.4.1.1", - "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_3.zip", - "hash": "d559c4b62fbf598eb8fff99ddcd152d7e34f6e30aa32a64d728ce1dd174b0dff" + "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_4.zip", + "hash": "e6d018c164d9f7d482f3d28dddf33dd5d7463bc414b61af9d65e3ca0b1eecc93" }, { "type": "LOCALE", diff --git a/app/src/main/assets/downloadable_content_list.json.en b/app/src/main/assets/downloadable_content_list.json.en index ab02767..ed46605 100644 --- a/app/src/main/assets/downloadable_content_list.json.en +++ b/app/src/main/assets/downloadable_content_list.json.en @@ -1,5 +1,5 @@ { - "version": 8, + "version": 9, "contents": [ { "type": "COMPAT", @@ -14,8 +14,8 @@ "name": "SMAPI for Galaxy Store", "assetPath": "compat/samsung_138/", "description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.4.1.1", - "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_3.zip", - "hash": "d559c4b62fbf598eb8fff99ddcd152d7e34f6e30aa32a64d728ce1dd174b0dff" + "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_4.zip", + "hash": "e6d018c164d9f7d482f3d28dddf33dd5d7463bc414b61af9d65e3ca0b1eecc93" }, { "type": "LOCALE", diff --git a/app/src/main/assets/downloadable_content_list.json.zh b/app/src/main/assets/downloadable_content_list.json.zh index e6959f3..bc749cb 100644 --- a/app/src/main/assets/downloadable_content_list.json.zh +++ b/app/src/main/assets/downloadable_content_list.json.zh @@ -1,5 +1,5 @@ { - "version": 8, + "version": 9, "contents": [ { "type": "COMPAT", @@ -14,8 +14,8 @@ "name": "SMAPI三星商店兼容包", "assetPath": "compat/samsung_138/", "description": "SMAPI三星商店兼容包, 适用版本1.4.4.138至今, SMAPI 3.4.1.1", - "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_3.zip", - "hash": "d559c4b62fbf598eb8fff99ddcd152d7e34f6e30aa32a64d728ce1dd174b0dff" + "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_4.zip", + "hash": "e6d018c164d9f7d482f3d28dddf33dd5d7463bc414b61af9d65e3ca0b1eecc93" }, { "type": "LOCALE", diff --git a/app/src/main/assets/mods/virtual-keyboard.zip b/app/src/main/assets/mods/virtual-keyboard.zip index aed6ba4..bf5e513 100644 Binary files a/app/src/main/assets/mods/virtual-keyboard.zip and b/app/src/main/assets/mods/virtual-keyboard.zip differ diff --git a/app/src/main/java/com/zane/smapiinstaller/MainActivity.java b/app/src/main/java/com/zane/smapiinstaller/MainActivity.java index 2e42a6f..23bfb4e 100644 --- a/app/src/main/java/com/zane/smapiinstaller/MainActivity.java +++ b/app/src/main/java/com/zane/smapiinstaller/MainActivity.java @@ -9,9 +9,9 @@ import android.os.Environment; import android.view.Menu; import android.view.MenuItem; -import com.afollestad.materialdialogs.MaterialDialog; import com.google.android.material.navigation.NavigationView; import com.hjq.language.LanguagesManager; +import com.lmntrx.android.library.livin.missme.ProgressDialog; import com.microsoft.appcenter.AppCenter; import com.microsoft.appcenter.analytics.Analytics; import com.microsoft.appcenter.crashes.Crashes; @@ -25,6 +25,7 @@ import com.zane.smapiinstaller.logic.ConfigManager; import com.zane.smapiinstaller.logic.GameLauncher; import com.zane.smapiinstaller.logic.ModAssetsManager; import com.zane.smapiinstaller.utils.DialogUtils; +import com.zane.smapiinstaller.utils.JSONUtil; import com.zane.smapiinstaller.utils.TranslateUtil; import org.apache.commons.lang3.StringUtils; @@ -128,7 +129,7 @@ public class MainActivity extends AppCompatActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { - if(item.isCheckable()) { + if (item.isCheckable()) { if (item.isChecked()) { item.setChecked(false); } else { @@ -148,16 +149,15 @@ public class MainActivity extends AppCompatActivity { config.setDeveloperMode(item.isChecked()); break; case R.id.settings_set_mod_path: - DialogUtils.showInputDialog(this, R.string.input, R.string.input_mods_path, Constants.MOD_PATH, Constants.MOD_PATH, (dialog, input) -> { - if(StringUtils.isNoneBlank(input)) { + DialogUtils.showInputDialog(toolbar, R.string.input, R.string.input_mods_path, Constants.MOD_PATH, Constants.MOD_PATH, (dialog, input) -> { + if (StringUtils.isNoneBlank(input)) { String pathString = input.toString(); File file = new File(Environment.getExternalStorageDirectory(), pathString); - if(file.exists() && file.isDirectory()) { + if (file.exists() && file.isDirectory()) { Constants.MOD_PATH = pathString; config.setModsPath(pathString); manager.flushConfig(); - } - else { + } else { DialogUtils.showAlertDialog(drawer, R.string.error, R.string.error_illegal_path); } } @@ -180,10 +180,10 @@ public class MainActivity extends AppCompatActivity { } private int getTranslateServiceIndex(AppConfig selectedTranslator) { - if(selectedTranslator == null) { + if (selectedTranslator == null) { return 0; } - switch (selectedTranslator.getValue()){ + switch (selectedTranslator.getValue()) { case "OFF": return 0; case "Google": @@ -194,19 +194,19 @@ public class MainActivity extends AppCompatActivity { } private void selectTranslateServiceLogic() { - DaoSession daoSession = ((MainApplication)this.getApplication()).getDaoSession(); + DaoSession daoSession = ((MainApplication) this.getApplication()).getDaoSession(); AppConfigDao appConfigDao = daoSession.getAppConfigDao(); int index = getTranslateServiceIndex(appConfigDao.queryBuilder().where(AppConfigDao.Properties.Name.eq(AppConfigKey.ACTIVE_TRANSLATOR)).build().unique()); - DialogUtils.setCurrentDialog(new MaterialDialog.Builder(this).title(R.string.settings_translation_service).items(R.array.translators).itemsCallbackSingleChoice(index, (dialog, itemView, position, text) -> { + DialogUtils.showSingleChoiceDialog(toolbar, R.string.settings_translation_service, R.array.translators, index, (dialog, position) -> { AppConfig activeTranslator = appConfigDao.queryBuilder().where(AppConfigDao.Properties.Name.eq(AppConfigKey.ACTIVE_TRANSLATOR)).build().unique(); switch (position) { case 0: - if(activeTranslator != null) { + if (activeTranslator != null) { appConfigDao.delete(activeTranslator); } break; case 1: - if(activeTranslator == null) { + if (activeTranslator == null) { activeTranslator = new AppConfig(null, AppConfigKey.ACTIVE_TRANSLATOR, TranslateUtil.GOOGLE); } else { activeTranslator.setValue(TranslateUtil.GOOGLE); @@ -214,7 +214,7 @@ public class MainActivity extends AppCompatActivity { appConfigDao.insertOrReplace(activeTranslator); break; case 2: - if(activeTranslator == null) { + if (activeTranslator == null) { activeTranslator = new AppConfig(null, AppConfigKey.ACTIVE_TRANSLATOR, TranslateUtil.YOU_DAO); } else { activeTranslator.setValue(TranslateUtil.YOU_DAO); @@ -222,14 +222,12 @@ public class MainActivity extends AppCompatActivity { appConfigDao.insertOrReplace(activeTranslator); break; default: - return false; } - return true; - }).show()); + }); } private void selectLanguageLogic() { - DialogUtils.setCurrentDialog(new MaterialDialog.Builder(this).title(R.string.settings_set_language).items(R.array.languages).itemsCallback((dialog, itemView, position, text) -> { + DialogUtils.showListItemsDialog(toolbar, R.string.settings_set_language, R.array.languages, (dialog, position) -> { boolean restart; switch (position) { case 0: @@ -271,12 +269,19 @@ public class MainActivity extends AppCompatActivity { overridePendingTransition(R.anim.fragment_fade_enter, R.anim.fragment_fade_exit); finish(); } - }).show()); + }); } private void updateCheckLogic() { ModAssetsManager modAssetsManager = new ModAssetsManager(toolbar); - modAssetsManager.checkModUpdate(); + modAssetsManager.checkModUpdate((list) -> { + try { + NavController controller = Navigation.findNavController(toolbar); + controller.navigate(MobileNavigationDirections.actionNavAnyToModUpdateFragment(JSONUtil.toJson(list))); + } catch (Exception e) { + Crashes.trackError(e); + } + }); } @Override @@ -286,6 +291,20 @@ public class MainActivity extends AppCompatActivity { || super.onSupportNavigateUp(); } + @Override + public void onBackPressed() { + Object dialog = DialogUtils.getCurrentDialog(); + if (dialog instanceof ProgressDialog) { + ProgressDialog progressDialog = ((ProgressDialog) dialog); + progressDialog.onBackPressed( + () -> { + super.onBackPressed(); + return null; + } + ); + } + } + @Override protected void attachBaseContext(Context newBase) { // 国际化适配(绑定语种) diff --git a/app/src/main/java/com/zane/smapiinstaller/constant/DialogAction.java b/app/src/main/java/com/zane/smapiinstaller/constant/DialogAction.java new file mode 100644 index 0000000..e49a78f --- /dev/null +++ b/app/src/main/java/com/zane/smapiinstaller/constant/DialogAction.java @@ -0,0 +1,16 @@ +package com.zane.smapiinstaller.constant; + +/** + * @author Zane + */ + +public enum DialogAction { + /** + * 确认 + */ + POSITIVE, + /** + * 取消 + */ + NEGATIVE +} diff --git a/app/src/main/java/com/zane/smapiinstaller/entity/HelpItem.java b/app/src/main/java/com/zane/smapiinstaller/entity/HelpItem.java index 2e34114..472223b 100644 --- a/app/src/main/java/com/zane/smapiinstaller/entity/HelpItem.java +++ b/app/src/main/java/com/zane/smapiinstaller/entity/HelpItem.java @@ -4,6 +4,7 @@ import lombok.Data; /** * 帮助信息 + * @author Zane */ @Data public class HelpItem { diff --git a/app/src/main/java/com/zane/smapiinstaller/dto/TranslationResult.java b/app/src/main/java/com/zane/smapiinstaller/entity/TranslationResult.java similarity index 97% rename from app/src/main/java/com/zane/smapiinstaller/dto/TranslationResult.java rename to app/src/main/java/com/zane/smapiinstaller/entity/TranslationResult.java index de5f2b1..5c308e9 100644 --- a/app/src/main/java/com/zane/smapiinstaller/dto/TranslationResult.java +++ b/app/src/main/java/com/zane/smapiinstaller/entity/TranslationResult.java @@ -1,4 +1,4 @@ -package com.zane.smapiinstaller.dto; +package com.zane.smapiinstaller.entity; import org.greenrobot.greendao.annotation.Entity; import org.greenrobot.greendao.annotation.Id; diff --git a/app/src/main/java/com/zane/smapiinstaller/logic/CommonLogic.java b/app/src/main/java/com/zane/smapiinstaller/logic/CommonLogic.java index 62ad9bc..8608a2e 100644 --- a/app/src/main/java/com/zane/smapiinstaller/logic/CommonLogic.java +++ b/app/src/main/java/com/zane/smapiinstaller/logic/CommonLogic.java @@ -92,6 +92,17 @@ public class CommonLogic { } } + /** + * 在UI线程执行操作 + * @param activity activity + * @param action 操作 + */ + public static void runOnUiThread(Activity activity, Consumer action) { + if (activity != null && !activity.isFinishing()) { + activity.runOnUiThread(() -> action.accept(activity)); + } + } + /** * 打开指定URL * diff --git a/app/src/main/java/com/zane/smapiinstaller/logic/ModAssetsManager.java b/app/src/main/java/com/zane/smapiinstaller/logic/ModAssetsManager.java index dc861c6..e8397cb 100644 --- a/app/src/main/java/com/zane/smapiinstaller/logic/ModAssetsManager.java +++ b/app/src/main/java/com/zane/smapiinstaller/logic/ModAssetsManager.java @@ -6,7 +6,6 @@ import android.os.Environment; import android.util.Log; import android.view.View; -import com.afollestad.materialdialogs.DialogAction; import com.fasterxml.jackson.core.type.TypeReference; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; @@ -19,6 +18,7 @@ import com.lzy.okgo.model.Response; import com.microsoft.appcenter.crashes.Crashes; import com.zane.smapiinstaller.R; import com.zane.smapiinstaller.constant.Constants; +import com.zane.smapiinstaller.constant.DialogAction; import com.zane.smapiinstaller.dto.ModUpdateCheckRequestDto; import com.zane.smapiinstaller.dto.ModUpdateCheckResponseDto; import com.zane.smapiinstaller.entity.ModManifestEntry; @@ -37,8 +37,8 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; -import androidx.core.util.Consumer; import java9.util.Objects; +import java9.util.function.Consumer; import java9.util.function.Predicate; import java9.util.stream.Collectors; import java9.util.stream.StreamSupport; @@ -291,7 +291,7 @@ public class ModAssetsManager { } } - public void checkModUpdate() { + public void checkModUpdate(Consumer> callback) { List list = StreamSupport.stream(findAllInstalledMods(false)) .filter(mod -> mod.getUpdateKeys() != null && !mod.getUpdateKeys().isEmpty()) .map(ModUpdateCheckRequestDto.ModInfo::fromModManifestEntry) @@ -313,7 +313,7 @@ public class ModAssetsManager { List checkResponseDtos = response.body(); if (checkResponseDtos != null) { List list = StreamSupport.stream(checkResponseDtos).filter(dto -> dto.getSuggestedUpdate() != null).collect(Collectors.toList()); - + callback.accept(list); } } }); diff --git a/app/src/main/java/com/zane/smapiinstaller/ui/about/AboutFragment.java b/app/src/main/java/com/zane/smapiinstaller/ui/about/AboutFragment.java index 799a859..fa4ee16 100644 --- a/app/src/main/java/com/zane/smapiinstaller/ui/about/AboutFragment.java +++ b/app/src/main/java/com/zane/smapiinstaller/ui/about/AboutFragment.java @@ -1,6 +1,5 @@ package com.zane.smapiinstaller.ui.about; -import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -14,7 +13,7 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; -import com.afollestad.materialdialogs.MaterialDialog; +import com.microsoft.appcenter.crashes.Crashes; import com.zane.smapiinstaller.R; import com.zane.smapiinstaller.constant.Constants; import com.zane.smapiinstaller.logic.CommonLogic; @@ -50,7 +49,7 @@ public class AboutFragment extends Fragment { void gplay() { try { CommonLogic.doOnNonNull(this.getActivity(), (activity) -> this.openPlayStore("market://details?id=" + activity.getPackageName())); - } catch (ActivityNotFoundException ex) { + } catch (Exception ex) { CommonLogic.doOnNonNull(this.getActivity(), (activity) -> CommonLogic.openUrl(activity, "https://play.google.com/store/apps/details?id=" + activity.getPackageName())); } } @@ -75,11 +74,9 @@ public class AboutFragment extends Fragment { @OnClick(R.id.button_donation) void donation() { - CommonLogic.doOnNonNull(this.getContext(), (context) -> DialogUtils.setCurrentDialog(new MaterialDialog.Builder(context) - .title(R.string.button_donation_text) - .items(R.array.donation_methods) - .itemsCallback((dialog, itemView, position, text) -> - CommonLogic.showAnimation(imgHeart, R.anim.heart_beat, (animation) -> listSelectLogic(context, position))).show())); + DialogUtils.showListItemsDialog(imgHeart, R.string.button_donation_text, R.array.donation_methods, (dialog, position) -> + CommonLogic.showAnimation(imgHeart, R.anim.heart_beat, (animation) -> + CommonLogic.doOnNonNull(this.getActivity(), (activity) -> listSelectLogic(activity, position)))); } private void listSelectLogic(Context context, int position) { @@ -87,7 +84,12 @@ public class AboutFragment extends Fragment { case 0: boolean hasInstalledAlipayClient = AlipayDonate.hasInstalledAlipayClient(context); if (hasInstalledAlipayClient) { - AlipayDonate.startAlipayClient(this.getActivity(), "fkx13570v1pp2xenyrx4y3f"); + try { + AlipayDonate.startAlipayClient(this.getActivity(), "fkx13570v1pp2xenyrx4y3f"); + } catch (Exception e) { + Crashes.trackError(e); + CommonLogic.openUrl(context, "http://dl.zaneyork.cn/alipay.png"); + } } else { CommonLogic.openUrl(context, "http://dl.zaneyork.cn/alipay.png"); } diff --git a/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigEditFragment.java b/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigEditFragment.java index 0e129c6..6cadc24 100644 --- a/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigEditFragment.java +++ b/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigEditFragment.java @@ -10,10 +10,10 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; -import com.afollestad.materialdialogs.DialogAction; import com.zane.smapiinstaller.BuildConfig; import com.zane.smapiinstaller.R; import com.zane.smapiinstaller.constant.Constants; +import com.zane.smapiinstaller.constant.DialogAction; import com.zane.smapiinstaller.logic.CommonLogic; import com.zane.smapiinstaller.utils.DialogUtils; import com.zane.smapiinstaller.utils.FileUtils; diff --git a/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigFragment.java b/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigFragment.java index b3edeee..24f12b6 100644 --- a/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigFragment.java +++ b/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigFragment.java @@ -5,6 +5,11 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.zane.smapiinstaller.R; +import com.zane.smapiinstaller.utils.DialogUtils; + +import java.util.ArrayList; + import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.DividerItemDecoration; @@ -15,13 +20,6 @@ import butterknife.ButterKnife; import butterknife.OnClick; import butterknife.OnTextChanged; -import com.afollestad.materialdialogs.MaterialDialog; -import com.zane.smapiinstaller.R; -import com.zane.smapiinstaller.logic.CommonLogic; -import com.zane.smapiinstaller.utils.DialogUtils; - -import java.util.ArrayList; - /** * @author Zane */ @@ -55,7 +53,7 @@ public class ConfigFragment extends Fragment { @OnClick(R.id.button_sort_by) void onSortByClick() { - int index; + int index = 0; switch (configViewModel.getSortBy()) { case "Name asc": index = 0; @@ -70,29 +68,23 @@ public class ConfigFragment extends Fragment { index = 3; break; default: - index = 0; } - CommonLogic.doOnNonNull(this.getContext(), context -> DialogUtils.setCurrentDialog(new MaterialDialog.Builder(context) - .title(R.string.sort_by) - .items(R.array.mod_list_sort_by) - .itemsCallbackSingleChoice(index, (dialog, itemView, position, text) -> { - switch (position) { - case 0: - configViewModel.switchSortBy("Name asc"); - break; - case 1: - configViewModel.switchSortBy("Name desc"); - break; - case 2: - configViewModel.switchSortBy("Date asc"); - break; - case 3: - configViewModel.switchSortBy("Date desc"); - break; - default: - return false; - } - return true; - }).show())); + DialogUtils.showSingleChoiceDialog(recyclerView, R.string.sort_by, R.array.mod_list_sort_by, index, (dialog, position) -> { + switch (position) { + case 0: + configViewModel.switchSortBy("Name asc"); + break; + case 1: + configViewModel.switchSortBy("Name desc"); + break; + case 2: + configViewModel.switchSortBy("Date asc"); + break; + case 3: + configViewModel.switchSortBy("Date desc"); + break; + default: + } + }); } } diff --git a/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigViewModel.java b/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigViewModel.java index b138073..bb098cc 100644 --- a/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigViewModel.java +++ b/app/src/main/java/com/zane/smapiinstaller/ui/config/ConfigViewModel.java @@ -11,7 +11,7 @@ import com.zane.smapiinstaller.entity.AppConfig; import com.zane.smapiinstaller.entity.AppConfigDao; import com.zane.smapiinstaller.entity.DaoSession; import com.zane.smapiinstaller.entity.ModManifestEntry; -import com.zane.smapiinstaller.dto.TranslationResult; +import com.zane.smapiinstaller.entity.TranslationResult; import com.zane.smapiinstaller.entity.TranslationResultDao; import com.zane.smapiinstaller.logic.CommonLogic; import com.zane.smapiinstaller.logic.ListenableObject; diff --git a/app/src/main/java/com/zane/smapiinstaller/ui/config/ModManifestAdapter.java b/app/src/main/java/com/zane/smapiinstaller/ui/config/ModManifestAdapter.java index da5f9c4..b0b2391 100644 --- a/app/src/main/java/com/zane/smapiinstaller/ui/config/ModManifestAdapter.java +++ b/app/src/main/java/com/zane/smapiinstaller/ui/config/ModManifestAdapter.java @@ -7,9 +7,9 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; -import com.afollestad.materialdialogs.DialogAction; import com.zane.smapiinstaller.R; import com.zane.smapiinstaller.constant.Constants; +import com.zane.smapiinstaller.constant.DialogAction; import com.zane.smapiinstaller.entity.ModManifestEntry; import com.zane.smapiinstaller.utils.DialogUtils; import com.zane.smapiinstaller.utils.FileUtils; diff --git a/app/src/main/java/com/zane/smapiinstaller/ui/download/DownloadableContentAdapter.java b/app/src/main/java/com/zane/smapiinstaller/ui/download/DownloadableContentAdapter.java index 6aa0c16..d018ca0 100644 --- a/app/src/main/java/com/zane/smapiinstaller/ui/download/DownloadableContentAdapter.java +++ b/app/src/main/java/com/zane/smapiinstaller/ui/download/DownloadableContentAdapter.java @@ -13,14 +13,14 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; -import com.afollestad.materialdialogs.DialogAction; -import com.afollestad.materialdialogs.MaterialDialog; +import com.lmntrx.android.library.livin.missme.ProgressDialog; import com.lzy.okgo.OkGo; import com.lzy.okgo.callback.FileCallback; import com.lzy.okgo.model.Progress; import com.lzy.okgo.model.Response; import com.microsoft.appcenter.crashes.Crashes; import com.zane.smapiinstaller.R; +import com.zane.smapiinstaller.constant.DialogAction; import com.zane.smapiinstaller.constant.DownloadableContentTypes; import com.zane.smapiinstaller.entity.DownloadableContent; import com.zane.smapiinstaller.entity.ModManifestEntry; @@ -157,13 +157,13 @@ public class DownloadableContentAdapter extends RecyclerView.Adapter dialogRef = DialogUtils.showProgressDialog(itemView, R.string.progress, ""); + AtomicReference dialogRef = DialogUtils.showProgressDialog(itemView, R.string.progress, ""); OkGo.get(downloadableContent.getUrl()).execute(new FileCallback(file.getParentFile().getAbsolutePath(), file.getName()) { @Override public void onError(Response response) { super.onError(response); - MaterialDialog dialog = dialogRef.get(); - DialogUtils.dismissDialog(itemView, dialog); + ProgressDialog dialog = dialogRef.get(); + dialog.dismiss(); downloading.set(false); DialogUtils.showAlertDialog(itemView, R.string.error, R.string.error_failed_to_download); } @@ -171,17 +171,17 @@ public class DownloadableContentAdapter extends RecyclerView.Adapter response) { - MaterialDialog dialog = dialogRef.get(); - DialogUtils.dismissDialog(itemView, dialog); + ProgressDialog dialog = dialogRef.get(); + dialog.dismiss(); downloading.set(false); File downloadedFile = response.body(); String hash = com.zane.smapiinstaller.utils.FileUtils.getFileHash(downloadedFile); diff --git a/app/src/main/java/com/zane/smapiinstaller/ui/install/InstallFragment.java b/app/src/main/java/com/zane/smapiinstaller/ui/install/InstallFragment.java index f40d0cd..cd8179b 100644 --- a/app/src/main/java/com/zane/smapiinstaller/ui/install/InstallFragment.java +++ b/app/src/main/java/com/zane/smapiinstaller/ui/install/InstallFragment.java @@ -7,11 +7,10 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.afollestad.materialdialogs.DialogAction; -import com.afollestad.materialdialogs.GravityEnum; -import com.afollestad.materialdialogs.MaterialDialog; +import com.lmntrx.android.library.livin.missme.ProgressDialog; import com.microsoft.appcenter.crashes.Crashes; import com.zane.smapiinstaller.R; +import com.zane.smapiinstaller.constant.DialogAction; import com.zane.smapiinstaller.logic.ApkPatcher; import com.zane.smapiinstaller.logic.CommonLogic; import com.zane.smapiinstaller.logic.ModAssetsManager; @@ -19,6 +18,8 @@ import com.zane.smapiinstaller.utils.DialogUtils; import org.apache.commons.lang3.StringUtils; +import java.util.concurrent.atomic.AtomicReference; + import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.navigation.NavController; @@ -63,70 +64,68 @@ public class InstallFragment extends Fragment { * 安装逻辑 */ private void installLogic() { - new MaterialDialog.Builder(context).title(R.string.install_progress_title).content(R.string.extracting_package).contentGravity(GravityEnum.CENTER) - .progress(false, 100, true).cancelable(false).cancelListener(dialog -> { - if (task != null) { - task.interrupt(); + AtomicReference dialogHolder = DialogUtils.showProgressDialog(root, R.string.install_progress_title, context.getString(R.string.extracting_package)); + if (task != null) { + task.interrupt(); + } + task = new Thread(() -> { + ProgressDialog dialog = null; + try { + do { + Thread.sleep(10); + dialog = dialogHolder.get(); + } while (dialog == null); + ApkPatcher patcher = new ApkPatcher(context); + ProgressDialog finalDialog = dialog; + patcher.registerProgressListener((progress) -> DialogUtils.setProgressDialogState(root, finalDialog, null, progress)); + DialogUtils.setProgressDialogState(root, dialog, R.string.extracting_package, null); + String path = patcher.extract(); + if (path == null) { + DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.error_game_not_found))); + return; + } + DialogUtils.setProgressDialogState(root, dialog, R.string.unpacking_smapi_files, null); + if (!CommonLogic.unpackSmapiFiles(context, path, false)) { + DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_unpack_smapi_files))); + return; + } + ModAssetsManager modAssetsManager = new ModAssetsManager(root); + DialogUtils.setProgressDialogState(root, dialog, R.string.unpacking_smapi_files, 6); + modAssetsManager.installDefaultMods(); + DialogUtils.setProgressDialogState(root, dialog, R.string.patching_package, 8); + if (!patcher.patch(path)) { + int target = patcher.getSwitchAction().getAndSet(0); + if (target == R.string.menu_download) { + DialogUtils.showConfirmDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game)), R.string.menu_download, R.string.cancel, (d, which) -> { + if (which == DialogAction.POSITIVE) { + NavController controller = Navigation.findNavController(root); + controller.navigate(InstallFragmentDirections.actionNavInstallToNavDownload()); + } + }); + } else { + DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game))); + } + return; + } + DialogUtils.setProgressDialogState(root, dialog, R.string.signing_package, null); + String signPath = patcher.sign(path); + if (signPath == null) { + DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_sign_game))); + return; + } + DialogUtils.setProgressDialogState(root, dialog, R.string.installing_package, null); + patcher.install(signPath); + } catch (InterruptedException ignored) { + } catch (Exception e) { + Crashes.trackError(e); + DialogUtils.showAlertDialog(root, R.string.error, e.getLocalizedMessage()); + } finally { + if(dialog != null) { + dialog.dismiss(); + } } - }).showListener(dialogInterface -> { - final MaterialDialog dialog = (MaterialDialog) dialogInterface; - DialogUtils.setCurrentDialog(dialog); - if (task != null) { - task.interrupt(); - } - task = new Thread(() -> { - try { - ApkPatcher patcher = new ApkPatcher(context); - patcher.registerProgressListener((progress)-> DialogUtils.setProgressDialogState(root, dialog, null, progress)); - DialogUtils.setProgressDialogState(root, dialog, R.string.extracting_package, null); - String path = patcher.extract(); - if (path == null) { - DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.error_game_not_found))); - return; - } - DialogUtils.setProgressDialogState(root, dialog, R.string.unpacking_smapi_files, null); - if (!CommonLogic.unpackSmapiFiles(context, path, false)) { - DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_unpack_smapi_files))); - return; - } - ModAssetsManager modAssetsManager = new ModAssetsManager(root); - DialogUtils.setProgressDialogState(root, dialog, R.string.unpacking_smapi_files, 6); - modAssetsManager.installDefaultMods(); - DialogUtils.setProgressDialogState(root, dialog, R.string.patching_package, 8); - if (!patcher.patch(path)) { - int target = patcher.getSwitchAction().getAndSet(0); - if(target == R.string.menu_download) { - DialogUtils.showConfirmDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game)), R.string.menu_download, R.string.cancel, (d, which) -> { - if(which == DialogAction.POSITIVE) { - NavController controller = Navigation.findNavController(root); - controller.navigate(InstallFragmentDirections.actionNavInstallToNavDownload()); - } - }); - } - else { - DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game))); - } - return; - } - DialogUtils.setProgressDialogState(root, dialog, R.string.signing_package, null); - String signPath = patcher.sign(path); - if (signPath == null) { - DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_sign_game))); - return; - } - DialogUtils.setProgressDialogState(root, dialog, R.string.installing_package, null); - patcher.install(signPath); - } - catch (Exception e) { - Crashes.trackError(e); - DialogUtils.showAlertDialog(root, R.string.error, e.getLocalizedMessage()); - } - finally { - DialogUtils.dismissDialog(root, dialog); - } - }); - task.start(); - }).show(); + }); + task.start(); } } diff --git a/app/src/main/java/com/zane/smapiinstaller/ui/update/ModUpdateAdapter.java b/app/src/main/java/com/zane/smapiinstaller/ui/update/ModUpdateAdapter.java new file mode 100644 index 0000000..74f470e --- /dev/null +++ b/app/src/main/java/com/zane/smapiinstaller/ui/update/ModUpdateAdapter.java @@ -0,0 +1,63 @@ +package com.zane.smapiinstaller.ui.update; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.zane.smapiinstaller.R; +import com.zane.smapiinstaller.dto.ModUpdateCheckResponseDto; + +import java.util.List; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import butterknife.ButterKnife; + +/** + * {@link RecyclerView.Adapter} that can display a {@link ModUpdateCheckResponseDto.UpdateInfo} + * @author Zane + */ +public class ModUpdateAdapter extends RecyclerView.Adapter { + + private List updateInfoList; + + public void setUpdateInfoList(List updateInfoList) { + this.updateInfoList = updateInfoList; + notifyDataSetChanged(); + } + + public ModUpdateAdapter(List items) { + updateInfoList = items; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.download_content_item, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(final ViewHolder holder, int position) { + holder.setUpdateInfo(updateInfoList.get(position)); + } + + @Override + public int getItemCount() { + return updateInfoList.size(); + } + + static class ViewHolder extends RecyclerView.ViewHolder { + public ModUpdateCheckResponseDto.UpdateInfo updateInfo; + + public void setUpdateInfo(ModUpdateCheckResponseDto.UpdateInfo updateInfo) { + this.updateInfo = updateInfo; + } + + public ViewHolder(View view) { + super(view); + ButterKnife.bind(this, itemView); + } + } +} diff --git a/app/src/main/java/com/zane/smapiinstaller/ui/update/ModUpdateFragment.java b/app/src/main/java/com/zane/smapiinstaller/ui/update/ModUpdateFragment.java new file mode 100644 index 0000000..be1dda7 --- /dev/null +++ b/app/src/main/java/com/zane/smapiinstaller/ui/update/ModUpdateFragment.java @@ -0,0 +1,56 @@ +package com.zane.smapiinstaller.ui.update; + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.zane.smapiinstaller.R; +import com.zane.smapiinstaller.dto.ModUpdateCheckResponseDto; +import com.zane.smapiinstaller.logic.CommonLogic; +import com.zane.smapiinstaller.utils.JSONUtil; + +import java.util.List; + +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +/** + * A fragment representing a list of Items. + * @author Zane + */ +public class ModUpdateFragment extends Fragment { + + /** + * Mandatory empty constructor for the fragment manager to instantiate the + * fragment (e.g. upon screen orientation changes). + */ + public ModUpdateFragment() { + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_mod_update_list, container, false); + + // Set the adapter + if (view instanceof RecyclerView) { + Context context = view.getContext(); + RecyclerView recyclerView = (RecyclerView) view; + recyclerView.setLayoutManager(new LinearLayoutManager(context)); + CommonLogic.doOnNonNull(this.getArguments(), arguments -> { + String updateInfoListJson = arguments.getString("updateInfoListJson", "[]"); + List updateInfos = JSONUtil.fromJson(updateInfoListJson, new TypeReference>() { + }); + ModUpdateAdapter adapter = new ModUpdateAdapter(updateInfos); + recyclerView.setAdapter(adapter); + }); + recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL)); + } + return view; + } +} diff --git a/app/src/main/java/com/zane/smapiinstaller/utils/DialogUtils.java b/app/src/main/java/com/zane/smapiinstaller/utils/DialogUtils.java index b464393..6f03422 100644 --- a/app/src/main/java/com/zane/smapiinstaller/utils/DialogUtils.java +++ b/app/src/main/java/com/zane/smapiinstaller/utils/DialogUtils.java @@ -1,26 +1,40 @@ package com.zane.smapiinstaller.utils; import android.app.Activity; -import android.app.Dialog; import android.text.InputType; import android.view.View; +import android.widget.ProgressBar; import com.afollestad.materialdialogs.MaterialDialog; +import com.afollestad.materialdialogs.input.DialogInputExtKt; +import com.afollestad.materialdialogs.list.DialogListExtKt; +import com.afollestad.materialdialogs.list.DialogSingleChoiceExtKt; +import com.lmntrx.android.library.livin.missme.ProgressDialog; import com.microsoft.appcenter.crashes.Crashes; import com.zane.smapiinstaller.R; +import com.zane.smapiinstaller.constant.DialogAction; import com.zane.smapiinstaller.logic.CommonLogic; import java.util.concurrent.atomic.AtomicReference; +import java9.util.function.BiConsumer; + /** * 对话框相关工具类 + * * @author Zane */ public class DialogUtils { - private static Dialog currentDialog = null; - public static void setCurrentDialog(Dialog currentDialog) { + private static Object currentDialog = null; + + public static Object getCurrentDialog() { + return currentDialog; + } + + public static void setCurrentDialog(Object currentDialog) { DialogUtils.currentDialog = currentDialog; } + /** * 设置进度条状态 * @@ -29,18 +43,15 @@ public class DialogUtils { * @param message 消息 * @param progress 进度 */ - public static void setProgressDialogState(View view, MaterialDialog dialog, Integer message, Integer progress) { - Activity activity = CommonLogic.getActivityFromView(view); - if (activity != null && !activity.isFinishing() && !dialog.isCancelled()) { - activity.runOnUiThread(() -> { - if(progress != null) { - dialog.setProgress(progress); - } - if(message != null) { - dialog.setContent(message); - } - }); - } + public static void setProgressDialogState(View view, ProgressDialog dialog, Integer message, Integer progress) { + CommonLogic.runOnUiThread(CommonLogic.getActivityFromView(view), (activity) -> { + if (progress != null) { + dialog.setProgress(progress); + } + if (message != null) { + dialog.setMessage(activity.getString(message)); + } + }); } /** @@ -51,10 +62,11 @@ public class DialogUtils { * @param message 消息 */ public static void showAlertDialog(View view, int title, String message) { - Activity activity = CommonLogic.getActivityFromView(view); - if (activity != null && !activity.isFinishing()) { - activity.runOnUiThread(() -> DialogUtils.setCurrentDialog(new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.ok).show())); - } + CommonLogic.runOnUiThread(CommonLogic.getActivityFromView(view), (activity) -> { + MaterialDialog materialDialog = new MaterialDialog(activity, MaterialDialog.getDEFAULT_BEHAVIOR()).title(title, null).message(null, message, null).positiveButton(R.string.ok, null, null); + DialogUtils.setCurrentDialog(materialDialog); + materialDialog.show(); + }); } /** @@ -65,10 +77,11 @@ public class DialogUtils { * @param message 消息 */ public static void showAlertDialog(View view, int title, int message) { - Activity activity = CommonLogic.getActivityFromView(view); - if (activity != null && !activity.isFinishing()) { - activity.runOnUiThread(() -> DialogUtils.setCurrentDialog(new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.ok).show())); - } + CommonLogic.runOnUiThread(CommonLogic.getActivityFromView(view), (activity) -> { + MaterialDialog materialDialog = new MaterialDialog(activity, MaterialDialog.getDEFAULT_BEHAVIOR()).title(title, null).message(message, null, null).positiveButton(R.string.ok, null, null); + DialogUtils.setCurrentDialog(materialDialog); + materialDialog.show(); + }); } /** @@ -79,11 +92,18 @@ public class DialogUtils { * @param message 消息 * @param callback 回调 */ - public static void showConfirmDialog(View view, int title, int message, MaterialDialog.SingleButtonCallback callback) { - Activity activity = CommonLogic.getActivityFromView(view); - if (activity != null && !activity.isFinishing()) { - activity.runOnUiThread(() -> DialogUtils.setCurrentDialog(new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.confirm).negativeText(R.string.cancel).onAny(callback).show())); - } + public static void showConfirmDialog(View view, int title, int message, BiConsumer callback) { + CommonLogic.runOnUiThread(CommonLogic.getActivityFromView(view), (activity) -> { + MaterialDialog materialDialog = new MaterialDialog(activity, MaterialDialog.getDEFAULT_BEHAVIOR()).title(title, null).message(message, null, null).positiveButton(R.string.confirm, null, dialog -> { + callback.accept(dialog, DialogAction.POSITIVE); + return null; + }).negativeButton(R.string.cancel, null, dialog -> { + callback.accept(dialog, DialogAction.NEGATIVE); + return null; + }); + DialogUtils.setCurrentDialog(materialDialog); + materialDialog.show(); + }); } /** @@ -94,7 +114,7 @@ public class DialogUtils { * @param message 消息 * @param callback 回调 */ - public static void showConfirmDialog(View view, int title, String message, MaterialDialog.SingleButtonCallback callback) { + public static void showConfirmDialog(View view, int title, String message, BiConsumer callback) { showConfirmDialog(view, title, message, R.string.confirm, R.string.cancel, callback); } @@ -108,11 +128,18 @@ public class DialogUtils { * @param negativeText 取消文本 * @param callback 回调 */ - public static void showConfirmDialog(View view, int title, String message, int positiveText, int negativeText, MaterialDialog.SingleButtonCallback callback) { - Activity activity = CommonLogic.getActivityFromView(view); - if (activity != null && !activity.isFinishing()) { - activity.runOnUiThread(() -> DialogUtils.setCurrentDialog(new MaterialDialog.Builder(activity).title(title).content(message).positiveText(positiveText).negativeText(negativeText).onAny(callback).show())); - } + public static void showConfirmDialog(View view, int title, String message, int positiveText, int negativeText, BiConsumer callback) { + CommonLogic.runOnUiThread(CommonLogic.getActivityFromView(view), (activity) -> { + MaterialDialog materialDialog = new MaterialDialog(activity, MaterialDialog.getDEFAULT_BEHAVIOR()).title(title, null).message(null, message, null).positiveButton(positiveText, null, dialog -> { + callback.accept(dialog, DialogAction.POSITIVE); + return null; + }).negativeButton(negativeText, null, dialog -> { + callback.accept(dialog, DialogAction.NEGATIVE); + return null; + }); + DialogUtils.setCurrentDialog(materialDialog); + materialDialog.show(); + }); } /** @@ -123,58 +150,123 @@ public class DialogUtils { * @param message 消息 * @return 对话框引用 */ - public static AtomicReference showProgressDialog(View view, int title, String message) { - Activity activity = CommonLogic.getActivityFromView(view); - AtomicReference reference = new AtomicReference<>(); - if (activity != null && !activity.isFinishing()) { - activity.runOnUiThread(() -> { - MaterialDialog dialog = new MaterialDialog.Builder(activity) - .title(title) - .content(message) - .progress(false, 100, true) - .cancelable(false) - .show(); - currentDialog = dialog; - reference.set(dialog); - }); - } + public static AtomicReference showProgressDialog(View view, int title, String message) { + AtomicReference reference = new AtomicReference<>(); + CommonLogic.runOnUiThread(CommonLogic.getActivityFromView(view), (activity) -> { + ProgressDialog dialog = new ProgressDialog(activity); + DialogUtils.setCurrentDialog(dialog); + dialog.setMessage(message); + dialog.setCancelable(false); + dialog.setMax(100); + dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + dialog.show(); + reference.set(dialog); + }); return reference; } + /** + * 解散指定对话框 + * + * @param view view + * @param dialog 对话框 + */ public static void dismissDialog(View view, MaterialDialog dialog) { Activity activity = CommonLogic.getActivityFromView(view); if (activity != null && !activity.isFinishing()) { - if (dialog != null && !dialog.isCancelled()) { + if (dialog != null && dialog.isShowing()) { try { dialog.dismiss(); - } - catch (Exception e) { + } catch (Exception e) { Crashes.trackError(e); } } } } + /** + * 解散当前对话框 + */ public static void dismissDialog() { - if (currentDialog != null && currentDialog.isShowing()) { - try { - currentDialog.dismiss(); - } - catch (Exception e) { - Crashes.trackError(e); + if (currentDialog != null) { + if (currentDialog instanceof MaterialDialog) { + MaterialDialog dialog = (MaterialDialog) currentDialog; + if (dialog.isShowing()) { + try { + dialog.dismiss(); + } catch (Exception e) { + Crashes.trackError(e); + } + } + } else if (currentDialog instanceof ProgressDialog) { + ProgressDialog dialog = (ProgressDialog) currentDialog; + dialog.dismiss(); } } } - public static void showInputDialog(Activity activity, int title, int content, String hint, String prefill, MaterialDialog.InputCallback callback) { - if (activity != null && !activity.isFinishing()) { - activity.runOnUiThread(() -> DialogUtils.setCurrentDialog(new MaterialDialog.Builder(activity) - .title(title) - .content(content) - .inputType(InputType.TYPE_CLASS_TEXT) - .input(hint, prefill, callback) - .show()) - ); - } + /** + * 显示输入框 + * + * @param view context容器 + * @param title 标题 + * @param content 内容 + * @param hint 提示 + * @param prefill 预输入 + * @param callback 回调 + */ + public static void showInputDialog(View view, int title, int content, String hint, String prefill, BiConsumer callback) { + CommonLogic.runOnUiThread(CommonLogic.getActivityFromView(view), (activity) -> { + MaterialDialog dialog = new MaterialDialog(activity, MaterialDialog.getDEFAULT_BEHAVIOR()).title(title, null).message(content, null, null); + dialog = DialogInputExtKt.input(dialog, hint, null, prefill, null, + InputType.TYPE_CLASS_TEXT, + null, true, false, (materialDialog, text) -> { + callback.accept(materialDialog, text); + return null; + }); + DialogUtils.setCurrentDialog(dialog); + dialog.show(); + }); + } + + /** + * 显示列表单选框 + * + * @param view context容器 + * @param title 标题 + * @param items 列表 + * @param index 默认选择 + * @param callback 回调 + */ + public static void showSingleChoiceDialog(View view, int title, int items, int index, BiConsumer callback) { + CommonLogic.runOnUiThread(CommonLogic.getActivityFromView(view), (activity) -> { + MaterialDialog materialDialog = new MaterialDialog(activity, MaterialDialog.getDEFAULT_BEHAVIOR()).title(title, null); + materialDialog = DialogSingleChoiceExtKt.listItemsSingleChoice(materialDialog, items, null, null, index, false, (dialog, position, text) -> { + callback.accept(dialog, position); + return null; + }); + DialogUtils.setCurrentDialog(materialDialog); + materialDialog.show(); + }); + } + + /** + * 显示列表选择框 + * + * @param view context容器 + * @param title 标题 + * @param items 列表 + * @param callback 回调 + */ + public static void showListItemsDialog(View view, int title, int items, BiConsumer callback) { + CommonLogic.runOnUiThread(CommonLogic.getActivityFromView(view), (activity) -> { + MaterialDialog materialDialog = new MaterialDialog(activity, MaterialDialog.getDEFAULT_BEHAVIOR()).title(title, null); + materialDialog = DialogListExtKt.listItems(materialDialog, items, null, null, false, (dialog, position, text) -> { + callback.accept(dialog, position); + return null; + }); + DialogUtils.setCurrentDialog(materialDialog); + materialDialog.show(); + }); } } diff --git a/app/src/main/java/com/zane/smapiinstaller/utils/JsonCallback.java b/app/src/main/java/com/zane/smapiinstaller/utils/JsonCallback.java index 26e9973..3968867 100644 --- a/app/src/main/java/com/zane/smapiinstaller/utils/JsonCallback.java +++ b/app/src/main/java/com/zane/smapiinstaller/utils/JsonCallback.java @@ -7,6 +7,9 @@ import com.lzy.okgo.request.base.Request; import okhttp3.Response; import okhttp3.ResponseBody; +/** + * @author Zane + */ public abstract class JsonCallback extends AbsCallback { private TypeReference type; diff --git a/app/src/main/java/com/zane/smapiinstaller/utils/TranslateUtil.java b/app/src/main/java/com/zane/smapiinstaller/utils/TranslateUtil.java index 78e9c8c..e459bc7 100644 --- a/app/src/main/java/com/zane/smapiinstaller/utils/TranslateUtil.java +++ b/app/src/main/java/com/zane/smapiinstaller/utils/TranslateUtil.java @@ -9,7 +9,7 @@ import com.lzy.okgo.callback.StringCallback; import com.lzy.okgo.model.Response; import com.zane.smapiinstaller.constant.Constants; import com.zane.smapiinstaller.dto.GoogleTranslationDto; -import com.zane.smapiinstaller.dto.TranslationResult; +import com.zane.smapiinstaller.entity.TranslationResult; import com.zane.smapiinstaller.dto.YouDaoTranslationDto; import org.apache.commons.lang3.StringUtils; diff --git a/app/src/main/res/layout/fragment_mod_update_list.xml b/app/src/main/res/layout/fragment_mod_update_list.xml new file mode 100644 index 0000000..79d2cad --- /dev/null +++ b/app/src/main/res/layout/fragment_mod_update_list.xml @@ -0,0 +1,12 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/updatable_mod_list_item.xml b/app/src/main/res/layout/updatable_mod_list_item.xml new file mode 100644 index 0000000..61a4490 --- /dev/null +++ b/app/src/main/res/layout/updatable_mod_list_item.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 244c4c3..40283cd 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -52,4 +52,16 @@ android:name="com.zane.smapiinstaller.ui.about.AboutFragment" android:label="@string/menu_about" tools:layout="@layout/fragment_about" /> + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 086f217..5bd5c24 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,8 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.6.1' - classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.0-alpha03" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61" + classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.0-alpha04" classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // NOTE: Do not place your application dependencies here; they belong