From c9938c3b8e59cb9a2723a635b98d5f99c52bb12a Mon Sep 17 00:00:00 2001 From: ZaneYork Date: Sat, 21 Mar 2020 17:15:27 +0800 Subject: [PATCH] 1.Mod list add sort support 2.Bug fix 3.Minor improvement --- app/build.gradle | 4 +- .../com/zane/smapiinstaller/MainActivity.java | 24 ++++- .../smapiinstaller/constant/AppConfigKey.java | 2 + .../entity/ModManifestEntry.java | 5 + .../logic/ModAssetsManager.java | 1 + .../ui/config/ConfigFragment.java | 52 ++++++++++- .../ui/config/ConfigViewModel.java | 88 +++++++++++++++--- app/src/main/res/drawable/sort_by.png | Bin 0 -> 3045 bytes app/src/main/res/layout/fragment_config.xml | 18 +++- app/src/main/res/values-in/strings.xml | 2 +- app/src/main/res/values-zh-rHK/arrays.xml | 6 ++ app/src/main/res/values-zh-rHK/strings.xml | 1 + app/src/main/res/values-zh-rTW/arrays.xml | 6 ++ app/src/main/res/values-zh-rTW/strings.xml | 1 + app/src/main/res/values-zh/arrays.xml | 6 ++ app/src/main/res/values-zh/strings.xml | 1 + app/src/main/res/values/arrays.xml | 6 ++ app/src/main/res/values/strings.xml | 1 + 18 files changed, 198 insertions(+), 26 deletions(-) create mode 100644 app/src/main/res/drawable/sort_by.png diff --git a/app/build.gradle b/app/build.gradle index 7b3d1a5..6a4d6ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.zane.smapiinstaller" minSdkVersion 19 targetSdkVersion 28 - versionCode 17 - versionName "1.3.3" + versionCode 18 + versionName "1.3.4" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true diff --git a/app/src/main/java/com/zane/smapiinstaller/MainActivity.java b/app/src/main/java/com/zane/smapiinstaller/MainActivity.java index ca7af75..505bdbb 100644 --- a/app/src/main/java/com/zane/smapiinstaller/MainActivity.java +++ b/app/src/main/java/com/zane/smapiinstaller/MainActivity.java @@ -174,10 +174,25 @@ public class MainActivity extends AppCompatActivity { return true; } + private int getTranslateServiceIndex(AppConfig selectedTranslator) { + if(selectedTranslator == null) { + return 0; + } + switch (selectedTranslator.getValue()){ + case "OFF": + return 0; + case "Google": + return 1; + default: + return 2; + } + } + private void selectTranslateServiceLogic() { - DialogUtils.setCurrentDialog(new MaterialDialog.Builder(this).title(R.string.settings_translation_service).items(R.array.translators).itemsCallback((dialog, itemView, position, text) -> { - DaoSession daoSession = ((MainApplication)this.getApplication()).getDaoSession(); - AppConfigDao appConfigDao = daoSession.getAppConfigDao(); + 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) -> { AppConfig activeTranslator = appConfigDao.queryBuilder().where(AppConfigDao.Properties.Name.eq(AppConfigKey.ACTIVE_TRANSLATOR)).build().unique(); switch (position) { case 0: @@ -202,8 +217,9 @@ public class MainActivity extends AppCompatActivity { appConfigDao.insertOrReplace(activeTranslator); break; default: - break; + return false; } + return true; }).show()); } diff --git a/app/src/main/java/com/zane/smapiinstaller/constant/AppConfigKey.java b/app/src/main/java/com/zane/smapiinstaller/constant/AppConfigKey.java index ba52032..0a340e5 100644 --- a/app/src/main/java/com/zane/smapiinstaller/constant/AppConfigKey.java +++ b/app/src/main/java/com/zane/smapiinstaller/constant/AppConfigKey.java @@ -2,4 +2,6 @@ package com.zane.smapiinstaller.constant; public class AppConfigKey { public static final String ACTIVE_TRANSLATOR = "ActiveTranslator"; + + public static final String MOD_LIST_SORT_BY = "ModListSortBy"; } diff --git a/app/src/main/java/com/zane/smapiinstaller/entity/ModManifestEntry.java b/app/src/main/java/com/zane/smapiinstaller/entity/ModManifestEntry.java index 5948b3d..11d27ed 100644 --- a/app/src/main/java/com/zane/smapiinstaller/entity/ModManifestEntry.java +++ b/app/src/main/java/com/zane/smapiinstaller/entity/ModManifestEntry.java @@ -1,5 +1,6 @@ package com.zane.smapiinstaller.entity; +import java.util.Date; import java.util.Set; import lombok.Data; @@ -51,4 +52,8 @@ public class ModManifestEntry { * 翻译后的Description */ private transient String translatedDescription; + /** + * 文件修改日期 + */ + private transient Long lastModified; } 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 9aad713..5301499 100644 --- a/app/src/main/java/com/zane/smapiinstaller/logic/ModAssetsManager.java +++ b/app/src/main/java/com/zane/smapiinstaller/logic/ModAssetsManager.java @@ -111,6 +111,7 @@ public class ModAssetsManager { break; } manifest.setAssetPath(file.getParentFile().getAbsolutePath()); + manifest.setLastModified(file.lastModified()); mods.add(manifest); } break; 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 8aace73..83091eb 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 @@ -15,7 +15,12 @@ import butterknife.ButterKnife; import butterknife.OnClick; import butterknife.OnTextChanged; +import com.afollestad.materialdialogs.MaterialDialog; +import com.google.common.collect.Lists; import com.zane.smapiinstaller.R; +import com.zane.smapiinstaller.utils.DialogUtils; + +import java.util.ArrayList; public class ConfigFragment extends Fragment { @@ -30,17 +35,58 @@ public class ConfigFragment extends Fragment { ButterKnife.bind(this, root); recyclerView.setLayoutManager(new LinearLayoutManager(this.getContext())); configViewModel = new ConfigViewModel(root); - ModManifestAdapter modManifestAdapter = new ModManifestAdapter(configViewModel, configViewModel.getModList()); + ModManifestAdapter modManifestAdapter = new ModManifestAdapter(configViewModel, new ArrayList<>(configViewModel.getModList())); recyclerView.setAdapter(modManifestAdapter); configViewModel.registerListChangeListener((list) -> { - modManifestAdapter.setList(list); + modManifestAdapter.setList(new ArrayList<>(list)); return true; }); recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL)); return root; } - @OnTextChanged(R.id.button_search) void onSearchMod(CharSequence text){ + @OnTextChanged(R.id.button_search) + void onSearchMod(CharSequence text) { configViewModel.filter(text); } + + @OnClick(R.id.button_sort_by) + void onSortByClick() { + int index; + switch (configViewModel.getSortBy()){ + case "Name asc": + index = 0; + break; + case "Name desc": + index = 1; + break; + case "Date asc": + index = 2; + break; + case "Date desc": + index = 3; + break; + default: + index = 0; + } + DialogUtils.setCurrentDialog(new MaterialDialog.Builder(this.getContext()).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()); + } } 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 1fd1e6b..d77046d 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 @@ -37,19 +37,79 @@ class ConfigViewModel extends ViewModel { private List modList; private List filteredModList; + private String sortBy = "Name asc"; + public String getSortBy() { + return sortBy; + } + private View root; + private List>> onChangedListener = new ArrayList<>(); ConfigViewModel(View root) { + this.root = root; this.modList = ModAssetsManager.findAllInstalledMods(); translateLogic(root); - Collections.sort(this.modList, (a, b) -> { - if (a.getContentPackFor() != null && b.getContentPackFor() == null) { - return 1; - } else if (b.getContentPackFor() != null) { - return -1; + MainApplication app = CommonLogic.getApplicationFromView(root); + if (null != app) { + AppConfigDao appConfigDao = app.getDaoSession().getAppConfigDao(); + Query query = appConfigDao.queryBuilder().where(AppConfigDao.Properties.Name.eq(AppConfigKey.MOD_LIST_SORT_BY)).build(); + AppConfig appConfig = query.unique(); + if(null != appConfig) { + sortBy = appConfig.getValue(); } - return a.getName().compareTo(b.getName()); - }); + } + sortLogic(sortBy); + } + + public void switchSortBy(String sortBy) { + MainApplication app = CommonLogic.getApplicationFromView(root); + if(null == app) { + return; + } + this.sortBy = sortBy; + AppConfigDao appConfigDao = app.getDaoSession().getAppConfigDao(); + AppConfig appConfig = new AppConfig(null, AppConfigKey.MOD_LIST_SORT_BY, sortBy); + appConfigDao.insertOrReplace(appConfig); + sortLogic(appConfig.getValue()); + } + + private void sortLogic(String sortBy) { + switch (sortBy) { + case "Name asc": + Collections.sort(modList, (a, b) -> a.getName().compareTo(b.getName())); + if(filteredModList != null && filteredModList != modList) { + Collections.sort(filteredModList, (a, b) -> a.getName().compareTo(b.getName())); + } + break; + case "Name desc": + Collections.sort(modList, (a, b) -> b.getName().compareTo(a.getName())); + if(filteredModList != null && filteredModList != modList) { + Collections.sort(filteredModList, (a, b) -> b.getName().compareTo(a.getName())); + } + break; + case "Date asc": + Collections.sort(modList, (a, b) -> a.getLastModified().compareTo(b.getLastModified())); + if(filteredModList != null && filteredModList != modList) { + Collections.sort(filteredModList, (a, b) -> a.getLastModified().compareTo(b.getLastModified())); + } + break; + case "Date desc": + Collections.sort(modList, (a, b) -> b.getLastModified().compareTo(a.getLastModified())); + if(filteredModList != null && filteredModList != modList) { + Collections.sort(filteredModList, (a, b) -> b.getLastModified().compareTo(a.getLastModified())); + } + break; + default: + return; + } + for (Predicate> listener : onChangedListener) { + if(filteredModList != null){ + listener.apply(filteredModList); + } + else { + listener.apply(modList); + } + } } private void translateLogic(View root) { @@ -57,7 +117,7 @@ class ConfigViewModel extends ViewModel { if (null != app) { DaoSession daoSession = app.getDaoSession(); AppConfig activeTranslator = daoSession.getAppConfigDao().queryBuilder().where(AppConfigDao.Properties.Name.eq(AppConfigKey.ACTIVE_TRANSLATOR)).build().unique(); - if(activeTranslator != null) { + if (activeTranslator != null) { String translator = activeTranslator.getValue(); ArrayList descriptions = Lists.newArrayList(Iterables.filter(Iterables.transform(this.modList, ModManifestEntry::getDescription), item -> item != null)); String language = LanguagesManager.getAppLanguage(app).getLanguage(); @@ -119,18 +179,16 @@ class ConfigViewModel extends ViewModel { } public void filter(CharSequence text) { - if(StringUtils.isBlank(text)) { + if (StringUtils.isBlank(text)) { filteredModList = modList; - } - else { + } else { filteredModList = Lists.newArrayList(Iterables.filter(modList, mod -> { - if(StringUtils.containsIgnoreCase(mod.getName(), text)) { + if (StringUtils.containsIgnoreCase(mod.getName(), text)) { return true; } - if(StringUtils.isNoneBlank(mod.getTranslatedDescription())){ + if (StringUtils.isNoneBlank(mod.getTranslatedDescription())) { return StringUtils.containsIgnoreCase(mod.getTranslatedDescription(), text); - } - else { + } else { return StringUtils.containsIgnoreCase(mod.getDescription(), text); } })); diff --git a/app/src/main/res/drawable/sort_by.png b/app/src/main/res/drawable/sort_by.png new file mode 100644 index 0000000000000000000000000000000000000000..68337403599e98af3c74c36b9c0aca99a87f564d GIT binary patch literal 3045 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/fragment_config.xml b/app/src/main/res/layout/fragment_config.xml index 269509a..594ff2c 100644 --- a/app/src/main/res/layout/fragment_config.xml +++ b/app/src/main/res/layout/fragment_config.xml @@ -11,11 +11,20 @@ android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintStart_toEndOf="@id/guideline_v1" - app:layout_constraintEnd_toStartOf="@id/guideline_v2" + app:layout_constraintEnd_toStartOf="@id/guideline_v3" app:layout_constraintTop_toBottomOf="@id/guideline_h1" android:hint="@android:string/search_go" android:inputType="text" android:importantForAutofill="no"/> +