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 0000000..6833740 Binary files /dev/null and b/app/src/main/res/drawable/sort_by.png differ 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"/> +