From 070ec701fe2983acf68944fb0e43dc0b0702e61d Mon Sep 17 00:00:00 2001 From: MrBoomDev Date: Sat, 11 Jan 2025 06:22:03 +0100 Subject: [PATCH] shit --- androidApp/build.gradle.kts | 2 + .../mobile/src/main/AndroidManifest.xml | 4 +- androidApp/src/main/AndroidManifest.xml | 2 +- .../screens/catalog => }/MainActivity.kt | 29 ++-- .../main/java/com/mrboomdev/awery/app/App.kt | 96 +++--------- .../com/mrboomdev/awery/app/AweryLifecycle.kt | 96 +----------- .../awery/app/AweryNotifications.java | 2 +- .../com/mrboomdev/awery/app/CrashHandler.kt | 62 ++------ .../awery/app/update/UpdatesManager.kt | 19 ++- .../awery/data/settings/SettingsData.java | 9 +- .../awery/data/settings/SettingsItem.java | 11 +- .../awery/extensions/ExtensionSettings.java | 33 ++-- .../support/internal/InternalProviders.java | 7 +- .../extensions/support/yomi/YomiManager.kt | 118 +++++++------- .../support/yomi/aniyomi/AniyomiProvider.java | 7 +- .../awery/sources/yomi/YomiManager.kt | 4 +- .../sources/yomi/aniyomi/AniyomiSource.kt | 7 +- .../sources/yomi/tachiyomi/TachiyomiSource.kt | 6 +- .../ui/mobile/components/EmptyStateView.kt | 2 +- .../mobile/components/ExpandableTextView.kt | 16 +- .../ui/mobile/components/MobileSetting.kt | 9 +- .../awery/ui/mobile/dialogs/FiltersDialog.kt | 7 +- .../ui/mobile/dialogs/MediaActionsDialog.kt | 14 +- .../ui/mobile/dialogs/MediaBookmarkDialog.kt | 24 +-- .../ui/mobile/screens/BrowserActivity.kt | 12 +- .../ui/mobile/screens/GalleryActivity.kt | 5 +- .../mobile/screens/IntentHandlerActivity.kt | 37 +++-- .../awery/ui/mobile/screens/SplashActivity.kt | 24 +-- .../screens/catalog/MediaCatalogAdapter.java | 2 +- .../screens/catalog/MediaCategoriesAdapter.kt | 2 +- .../catalog/feeds/FailedFeedViewHolder.kt | 7 +- .../catalog/feeds/ListFeedViewHolder.kt | 7 +- .../catalog/feeds/PagesFeedViewHolder.kt | 21 +-- .../ui/mobile/screens/media/MediaActivity.kt | 9 +- .../screens/media/MediaCommentsFragment.java | 2 +- .../mobile/screens/media/MediaInfoFragment.kt | 38 ++--- .../media/MediaPlayEpisodesAdapter.java | 2 +- .../mobile/screens/media/MediaPlayFragment.kt | 61 ++++---- .../mobile/screens/player/PlayerActivity.kt | 30 ++-- .../screens/player/PlayerController.java | 11 -- .../mobile/screens/search/SearchActivity.kt | 34 ++--- .../mobile/screens/settings/AboutActivity.kt | 7 +- .../screens/settings/SettingsActivity.java | 2 +- .../screens/settings/SettingsActivity2.kt | 2 + .../screens/settings/SettingsAdapter.java | 6 +- .../mobile/screens/settings/TabsSettings.java | 14 +- .../ui/mobile/screens/setup/SetupActivity.kt | 87 +++++------ .../mobile/screens/setup/SetupTabsAdapter.kt | 3 +- .../mobile/screens/setup/SetupThemeAdapter.kt | 8 +- .../mrboomdev/awery/ui/tv/TvMainActivity.kt | 2 + .../awery/ui/tv/components/FeedsGroup.kt | 6 +- .../awery/ui/tv/screens/home/HomeScreen.kt | 6 +- .../awery/ui/tv/screens/home/HomeViewModel.kt | 10 +- .../ui/tv/screens/media/MediaInfoScreen.kt | 46 +++--- .../awery/ui/tv/screens/media/MediaScreen.kt | 8 +- .../com/mrboomdev/awery/util/IconStateful.kt | 6 +- .../com/mrboomdev/awery/util/NiceUtils.java | 1 + .../util/exceptions/LocalizedException.java | 1 + .../util/exceptions/OkiThrowableMessage.kt | 67 ++++---- .../util/exceptions/ZeroResultsException.java | 52 ------- .../util/extensions/ActivityExtensions.kt | 101 +----------- .../util/extensions/ContextExtensions.kt | 108 ------------- .../awery/util/extensions/DialogExtensions.kt | 3 +- .../awery/util/extensions/ViewExtensions.kt | 3 + .../util/ui/dialog/BaseDialogBuilder.java | 20 --- .../util/ui/dialog/IconPickerDialog.java | 5 +- .../awery/util/ui/dialog/SelectionDialog.java | 10 +- .../awery/util/ui/fields/EditTextField.java | 9 -- .../com/mrboomdev/awery/app/AweryLocales.kt | 53 +++---- .../mrboomdev/awery/app/ExtensionsManager.kt | 15 +- .../awery/app/services/BackupService.kt | 6 +- .../awery/platform/PlatformSettingHandler.kt | 88 +++++------ .../res/layout-land/feed_featured_item.xml | 4 +- .../res/layout-land/layout_header_home.xml | 10 +- .../res/layout-land/layout_media_details.xml | 8 +- .../src/main/res/layout-land/screen_about.xml | 4 +- .../src/main/res/layout-land/screen_setup.xml | 8 +- .../main/res/layout/feed_featured_item.xml | 7 +- .../res/layout/layout_comments_header.xml | 16 +- .../main/res/layout/layout_header_home.xml | 10 +- .../main/res/layout/layout_header_search.xml | 8 +- .../main/res/layout/layout_media_details.xml | 8 +- .../res/layout/layout_tracking_options.xml | 12 +- .../main/res/layout/layout_watch_variants.xml | 16 +- .../layout/media_details_overview_layout.xml | 2 +- .../main/res/layout/popup_media_actions.xml | 8 +- .../main/res/layout/popup_media_bookmark.xml | 4 +- .../main/res/layout/popup_simple_header.xml | 2 +- .../src/main/res/layout/screen_about.xml | 4 +- .../src/main/res/layout/screen_feed.xml | 2 +- .../src/main/res/layout/screen_settings.xml | 4 +- .../src/main/res/layout/screen_setup.xml | 8 +- .../src/main/res/menu/manga_menu_detail.xml | 4 +- .../src/main/res/menu/media_details_menu.xml | 8 +- androidApp/tv/src/main/AndroidManifest.xml | 4 +- desktopApp/build.gradle.kts | 2 +- .../com/mrboomdev/awery/desktop/Main.kt | 3 + .../com/mrboomdev/awery/ext/AweryClient.kt | 5 + .../mrboomdev/awery/ext/util/LocaleAware.kt | 6 + .../exceptions/ExtensionInstallException.kt | 6 +- .../util/exceptions/ExtensionLoadException.kt | 6 +- .../util/exceptions/ZeroResultsException.kt | 12 ++ gradle.properties | 37 +++-- settings.gradle.kts | 9 +- shared/build.gradle.kts | 1 + .../PlatformInternalization.android.kt | 37 +++-- .../mrboomdev/awery/utils/ActivityUtils.kt | 144 ++++++++++++++++++ .../com/mrboomdev/awery/utils/ContextUtils.kt | 40 +++++ .../com/mrboomdev/awery/utils/IntentUtils.kt | 75 +++++++++ .../awery/utils}/UniqueIdGenerator.kt | 2 +- .../composeResources}/values-as/strings.xml | 13 +- .../composeResources}/values-bg/strings.xml | 0 .../composeResources}/values-bn/strings.xml | 0 .../composeResources}/values-cs/strings.xml | 0 .../composeResources}/values-da/strings.xml | 0 .../composeResources}/values-de/strings.xml | 2 +- .../composeResources}/values-el/strings.xml | 0 .../values-en-rIN/strings.xml | 0 .../composeResources}/values-es/strings.xml | 0 .../composeResources}/values-fil/strings.xml | 0 .../composeResources}/values-fr/strings.xml | 2 +- .../composeResources}/values-gu/strings.xml | 0 .../composeResources}/values-hi/strings.xml | 0 .../composeResources}/values-hu/strings.xml | 0 .../composeResources}/values-hy/strings.xml | 0 .../composeResources}/values-in/strings.xml | 0 .../composeResources}/values-it/strings.xml | 0 .../composeResources}/values-iw/strings.xml | 0 .../composeResources}/values-ja/strings.xml | 2 +- .../composeResources}/values-ko/strings.xml | 2 +- .../composeResources}/values-mr/strings.xml | 0 .../composeResources}/values-nl/strings.xml | 0 .../composeResources}/values-pl/strings.xml | 0 .../composeResources}/values-pt/strings.xml | 0 .../composeResources}/values-ro/strings.xml | 0 .../composeResources}/values-ru/strings.xml | 0 .../composeResources}/values-sa/strings.xml | 0 .../composeResources}/values-ta/strings.xml | 2 +- .../composeResources}/values-th/strings.xml | 0 .../composeResources}/values-tr/strings.xml | 0 .../composeResources}/values-vi/strings.xml | 0 .../values-zh-rCN/strings.xml | 2 +- .../composeResources}/values/strings.xml | 134 +--------------- .../awery/platform/PlatformResources.kt | 46 +++++- .../ui/screens/settings/SettingsScreen.kt | 2 +- .../platform/PlatformResources.desktop.kt | 10 +- 146 files changed, 1089 insertions(+), 1319 deletions(-) rename androidApp/src/main/java/com/mrboomdev/awery/{ui/mobile/screens/catalog => }/MainActivity.kt (95%) delete mode 100644 androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/ZeroResultsException.java create mode 100644 ext/src/main/kotlin/com/mrboomdev/awery/ext/util/LocaleAware.kt create mode 100644 ext/src/main/kotlin/com/mrboomdev/awery/ext/util/exceptions/ZeroResultsException.kt create mode 100644 shared/src/androidMain/kotlin/com/mrboomdev/awery/utils/ActivityUtils.kt create mode 100644 shared/src/androidMain/kotlin/com/mrboomdev/awery/utils/ContextUtils.kt create mode 100644 shared/src/androidMain/kotlin/com/mrboomdev/awery/utils/IntentUtils.kt rename {androidApp/src/main/java/com/mrboomdev/awery/util => shared/src/androidMain/kotlin/com/mrboomdev/awery/utils}/UniqueIdGenerator.kt (97%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-as/strings.xml (98%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-bg/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-bn/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-cs/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-da/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-de/strings.xml (99%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-el/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-en-rIN/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-es/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-fil/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-fr/strings.xml (99%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-gu/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-hi/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-hu/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-hy/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-in/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-it/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-iw/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-ja/strings.xml (99%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-ko/strings.xml (99%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-mr/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-nl/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-pl/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-pt/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-ro/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-ru/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-sa/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-ta/strings.xml (99%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-th/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-tr/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-vi/strings.xml (100%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values-zh-rCN/strings.xml (99%) rename {androidApp/src/main/res => shared/src/commonMain/composeResources}/values/strings.xml (75%) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 13d4c337..0c0ddf19 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -10,6 +10,7 @@ plugins { alias(libs.plugins.android.kotlin) alias(libs.plugins.kotlin.ksp) alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.compose) alias(libs.plugins.compose.compiler) alias(libs.plugins.room) } @@ -166,6 +167,7 @@ dependencies { implementation(libs.androidx.adaptive) implementation(libs.androidx.adaptive.layout) implementation(libs.androidx.adaptive.navigation) + implementation(compose.components.resources) // Markdown implementation(libs.markwon.core) diff --git a/androidApp/mobile/src/main/AndroidManifest.xml b/androidApp/mobile/src/main/AndroidManifest.xml index 38e59aee..dd4fa415 100644 --- a/androidApp/mobile/src/main/AndroidManifest.xml +++ b/androidApp/mobile/src/main/AndroidManifest.xml @@ -4,14 +4,14 @@ diff --git a/androidApp/src/main/AndroidManifest.xml b/androidApp/src/main/AndroidManifest.xml index c1e81c7e..8727928a 100644 --- a/androidApp/src/main/AndroidManifest.xml +++ b/androidApp/src/main/AndroidManifest.xml @@ -153,7 +153,7 @@ tools:ignore="DiscouragedApi" /> diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MainActivity.kt b/androidApp/src/main/java/com/mrboomdev/awery/MainActivity.kt similarity index 95% rename from androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MainActivity.kt rename to androidApp/src/main/java/com/mrboomdev/awery/MainActivity.kt index 9ca472b8..7bb1bcea 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MainActivity.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/MainActivity.kt @@ -1,4 +1,4 @@ -package com.mrboomdev.awery.ui.mobile.screens.catalog +package com.mrboomdev.awery import android.content.Intent import android.os.Bundle @@ -14,7 +14,6 @@ import androidx.lifecycle.lifecycleScope import androidx.viewpager2.adapter.FragmentStateAdapter import com.google.android.material.elevation.SurfaceColors import com.google.android.material.navigationrail.NavigationRailView -import com.mrboomdev.awery.R import com.mrboomdev.awery.app.App.Companion.database import com.mrboomdev.awery.app.App.Companion.getMoshi import com.mrboomdev.awery.app.App.Companion.isLandscape @@ -29,7 +28,9 @@ import com.mrboomdev.awery.data.settings.SettingsList import com.mrboomdev.awery.databinding.LayoutHeaderHomeBinding import com.mrboomdev.awery.databinding.ScreenMainBinding import com.mrboomdev.awery.generated.AwerySettings -import com.mrboomdev.awery.platform.PlatformResources.i18n +import com.mrboomdev.awery.generated.Res +import com.mrboomdev.awery.generated.back_to_exit +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.components.EmptyStateView import com.mrboomdev.awery.ui.mobile.screens.catalog.feeds.FeedsFragment import com.mrboomdev.awery.ui.mobile.screens.search.MultiSearchActivity @@ -38,15 +39,12 @@ import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsActivity2 import com.mrboomdev.awery.util.IconStateful import com.mrboomdev.awery.util.TabsTemplate import com.mrboomdev.awery.util.extensions.UI_INSETS -import com.mrboomdev.awery.util.extensions.addOnBackPressedListener import com.mrboomdev.awery.util.extensions.applyInsets import com.mrboomdev.awery.util.extensions.bottomMargin import com.mrboomdev.awery.util.extensions.bottomPadding import com.mrboomdev.awery.util.extensions.dpPx import com.mrboomdev.awery.util.extensions.enableEdgeToEdge -import com.mrboomdev.awery.util.extensions.inflater import com.mrboomdev.awery.util.extensions.leftPadding -import com.mrboomdev.awery.util.extensions.removeOnBackPressedListener import com.mrboomdev.awery.util.extensions.resolveAttrColor import com.mrboomdev.awery.util.extensions.rightPadding import com.mrboomdev.awery.util.extensions.setContentViewCompat @@ -55,7 +53,12 @@ import com.mrboomdev.awery.util.extensions.startActivity import com.mrboomdev.awery.util.extensions.topPadding import com.mrboomdev.awery.util.io.FileUtil.readAssets import com.mrboomdev.awery.util.ui.FadeTransformer +import com.mrboomdev.awery.utils.addOnBackPressedListener +import com.mrboomdev.awery.utils.buildIntent import com.mrboomdev.awery.utils.div +import com.mrboomdev.awery.utils.dpPx +import com.mrboomdev.awery.utils.inflater +import com.mrboomdev.awery.utils.removeOnBackPressedListener import com.squareup.moshi.adapter import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.Dispatchers @@ -82,7 +85,7 @@ class MainActivity : AppCompatActivity() { } doubleBackToExitPressedOnce = true - toast(R.string.back_to_exit) + toast(Res.string.back_to_exit) runDelayed({ doubleBackToExitPressedOnce = false }, 2000) } } @@ -95,7 +98,7 @@ class MainActivity : AppCompatActivity() { if(savedInstanceState != null) { tabIndex = savedInstanceState.getInt(SAVED_TAB_INDEX, -1) } - + AwerySettings.TABS_TEMPLATE.value.also { if(it == "custom") loadCustomTabs() else loadTemplateTabs(it) } @@ -173,7 +176,7 @@ class MainActivity : AppCompatActivity() { val tab = tabs[i] val icon = icons[tab.icon] - val drawable = icon?.getDrawable(this) + val drawable = icon?.getDrawable(this) ?: ContextCompat.getDrawable(this, R.drawable.ic_view_cozy)!! if(tabIndex == -1 && tab.id == savedDefaultTab) { @@ -201,7 +204,7 @@ class MainActivity : AppCompatActivity() { "No tabs found", "Please selecting an template or either create your own tabs to see anything here.", "Go to settings" - ) { startActivity(clazz = SettingsActivity::class) } + ) { startActivity(buildIntent(SettingsActivity::class)) } setContentViewCompat(binding.root) } @@ -404,9 +407,9 @@ class MainActivity : AppCompatActivity() { override fun getFilters() = SettingsList() override fun getMaxLoadsAtSameTime() = 1 override fun loadOnStartup() = true - - override fun getCacheFile() = requireContext().cacheDir / - Constants.DIRECTORY_NET_CACHE / + + override fun getCacheFile() = requireContext().cacheDir / + Constants.DIRECTORY_NET_CACHE / Constants.FILE_FEEDS_NET_CACHE } } \ No newline at end of file diff --git a/androidApp/src/main/java/com/mrboomdev/awery/app/App.kt b/androidApp/src/main/java/com/mrboomdev/awery/app/App.kt index 9c3d63d4..a323afd6 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/app/App.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/app/App.kt @@ -63,18 +63,16 @@ import com.mrboomdev.awery.data.Constants import com.mrboomdev.awery.data.db.AweryDB import com.mrboomdev.awery.data.db.item.DBCatalogList import com.mrboomdev.awery.extensions.data.CatalogList -import com.mrboomdev.awery.generated.AwerySettings -import com.mrboomdev.awery.generated.GeneratedSetting -import com.mrboomdev.awery.platform.PlatformResources +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.screens.BrowserActivity import com.mrboomdev.awery.ui.mobile.screens.IntentHandlerActivity import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsActivity import com.mrboomdev.awery.ui.tv.TvExperimentsActivity -import com.mrboomdev.awery.util.extensions.configuration -import com.mrboomdev.awery.util.extensions.startActivity import com.mrboomdev.awery.util.ui.dialog.DialogBuilder import com.mrboomdev.awery.util.ui.markdown.LinkifyPlugin import com.mrboomdev.awery.util.ui.markdown.SpoilerPlugin +import com.mrboomdev.awery.utils.buildIntent import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import dev.mihon.injekt.patchInjekt @@ -88,6 +86,8 @@ import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +import org.jetbrains.compose.resources.StringResource +import org.jetbrains.compose.resources.stringResource import java.util.WeakHashMap class App : Application() { @@ -130,16 +130,16 @@ class App : Application() { if(AwerySettings.USE_DARK_THEME.value == null) { AwerySettings.USE_DARK_THEME.value = ThemeManager.isDarkModeEnabled } - + if(AwerySettings.LAST_OPENED_VERSION.value < 1) { CoroutineScope(Dispatchers.IO).launch { database.listDao.insert( - DBCatalogList.fromCatalogList(CatalogList(getString(R.string.currently_watching), "1")), - DBCatalogList.fromCatalogList(CatalogList(getString(R.string.planning_watch), "2")), - DBCatalogList.fromCatalogList(CatalogList(getString(R.string.delayed), "3")), - DBCatalogList.fromCatalogList(CatalogList(getString(R.string.completed), "4")), - DBCatalogList.fromCatalogList(CatalogList(getString(R.string.dropped), "5")), - DBCatalogList.fromCatalogList(CatalogList(getString(R.string.favourites), "6")), + DBCatalogList.fromCatalogList(CatalogList(i18n(Res.string.currently_watching), "1")), + DBCatalogList.fromCatalogList(CatalogList(i18n(Res.string.planning_watch), "2")), + DBCatalogList.fromCatalogList(CatalogList(i18n(Res.string.delayed), "3")), + DBCatalogList.fromCatalogList(CatalogList(i18n(Res.string.completed), "4")), + DBCatalogList.fromCatalogList(CatalogList(i18n(Res.string.dropped), "5")), + DBCatalogList.fromCatalogList(CatalogList(i18n(Res.string.favourites), "6")), DBCatalogList.fromCatalogList(CatalogList("Hidden", Constants.CATALOG_LIST_BLACKLIST)), DBCatalogList.fromCatalogList(CatalogList("History", Constants.CATALOG_LIST_HISTORY)) ) @@ -244,7 +244,7 @@ class App : Application() { // Android 13 and higher shows a visual confirmation of copied contents // https://developer.android.com/about/versions/13/features/copy-paste if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { - toast(R.string.copied_to_clipboard) + toast(i18n(Res.string.copied_to_clipboard)) } } @@ -257,6 +257,7 @@ class App : Application() { } @JvmStatic + @Deprecated("Old java shit") fun getResourceId(type: Class<*>, res: String?): Int { if(res == null) return 0 @@ -280,33 +281,6 @@ class App : Application() { } } - inline fun getResourceId(res: String?): Int { - return getResourceId(T::class.java, res) - } - - @JvmStatic - @Deprecated("old shit", ReplaceWith( - "PlatformResources.i18n(string, *args)", - "com.mrboomdev.awery.platform.PlatformResources")) - fun i18n(clazz: Class<*>, string: String?, vararg args: Any): String? { - val id = getResourceId(clazz, string) - return if(id == 0) null else PlatformResources.i18n(id, *args) - } - - @Deprecated("old shit", ReplaceWith( - "PlatformResources.i18n(resourceId, *args)", - "com.mrboomdev.awery.platform.PlatformResources")) - inline fun i18n(resourceId: String, vararg args: Any): String? { - return PlatformResources.i18n(resourceId, *args) - } - - @JvmStatic - @Deprecated("old shit", ReplaceWith( - "PlatformResources.i18n(res, *params)", - "com.mrboomdev.awery.platform.PlatformResources")) - fun i18n(@StringRes res: Int, vararg params: Any) = - ContextCompat.getContextForLanguage(appContext).getString(res, *params) - private fun toastImpl(context: Context?, text: Any?, duration: Int = 0) { runOnUiThread { Toast.makeText(context, text.toString(), duration).show() } } @@ -317,12 +291,6 @@ class App : Application() { toastImpl(appContext, text, duration) } - @JvmStatic - @JvmOverloads - fun toast(@StringRes res: Int, duration: Int = 0) { - toast(appContext.getString(res), duration) - } - /** * There is a bug in an appcompat library which sometimes throws an [NullPointerException]. * This method tries to do it without throwing any exceptions. @@ -415,7 +383,7 @@ class App : Application() { @JvmStatic fun isLandscape(context: Context): Boolean { - return context.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE + return context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE } @JvmStatic @@ -435,10 +403,10 @@ class App : Application() { @JvmStatic @JvmOverloads - fun openUrl(context: Context, url: String, forceInternal: Boolean = false) { + fun openUrl(context: Context, url: String, forceInternal: Boolean = false) = with(context) { if(forceInternal) { - context.startActivity(BrowserActivity::class, BrowserActivity.Extras(url)) - return + startActivity(buildIntent(BrowserActivity::class, BrowserActivity.Extras(url))) + return@with } val customTabsIntent = CustomTabsIntent.Builder().apply { @@ -449,11 +417,11 @@ class App : Application() { intent.data = Uri.parse(url) } - customTabsIntent.intent.resolveActivity(context.packageManager)?.also { - context.startActivity(customTabsIntent.intent, customTabsIntent.startAnimationBundle) + customTabsIntent.intent.resolveActivity(packageManager)?.also { + startActivity(customTabsIntent.intent, customTabsIntent.startAnimationBundle) } ?: run { Log.e(TAG, "No external browser was found, launching a internal one.") - context.startActivity(BrowserActivity::class, BrowserActivity.Extras(url)) + startActivity(buildIntent(BrowserActivity::class, BrowserActivity.Extras(url))) } } @@ -487,7 +455,7 @@ class App : Application() { runOnUiThread { DialogBuilder(getAnyActivity()!!) .setTitle("StrictMode.VmPolicy Violation!") .setMessage(Log.getStackTraceString(violation)) - .setPositiveButton(R.string.ok) { it.dismiss() } + .setPositiveButton(i18n(Res.string.ok)) { it.dismiss() } .show() } } catch(e: Throwable) { Log.e(TAG, "Failed to warn about an strict mode violation!", e) @@ -507,26 +475,6 @@ class App : Application() { if(isTv) AwerySettings.NavigationStyleValue.MATERIAL else it } - @Deprecated(message = "java shit") - fun getConfiguration(context: Context): Configuration { - return context.configuration - } - - val configuration: Configuration - get() = anyContext.configuration - - @JvmStatic - @JvmOverloads - fun snackbar( - activity: Activity, - @StringRes title: Int, - @StringRes button: Int, - buttonCallback: Runnable?, - duration: Int = Snackbar.LENGTH_SHORT - ) { - snackbar(activity, activity.getString(title), activity.getString(button), buttonCallback, duration) - } - @JvmStatic fun snackbar(activity: Activity, title: Any?, button: Any?, buttonCallback: Runnable?, duration: Int) { runOnUiThread { diff --git a/androidApp/src/main/java/com/mrboomdev/awery/app/AweryLifecycle.kt b/androidApp/src/main/java/com/mrboomdev/awery/app/AweryLifecycle.kt index ebb024ec..932b9f97 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/app/AweryLifecycle.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/app/AweryLifecycle.kt @@ -6,7 +6,6 @@ import android.app.Application.ActivityLifecycleCallbacks import android.content.Context import android.content.ContextWrapper import android.content.Intent -import android.content.pm.PackageManager import android.os.Bundle import android.os.Handler import android.os.Looper @@ -14,10 +13,10 @@ import android.util.Log import androidx.annotation.MainThread import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity -import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.RecyclerView import com.mrboomdev.awery.app.App.Companion.toast -import com.mrboomdev.awery.util.UniqueIdGenerator +import com.mrboomdev.awery.platform.PlatformResources +import com.mrboomdev.awery.utils.UniqueIdGenerator import org.jetbrains.annotations.Contract import java.lang.ref.WeakReference import java.lang.reflect.InvocationTargetException @@ -43,6 +42,8 @@ open class AweryLifecycle private constructor() : ActivityLifecycleCallbacks { override fun onActivityStarted(activity: Activity) {} override fun onActivityResumed(activity: Activity) { + PlatformResources.load(activity) + getActivityInfo(activity).apply { isPaused = false lastActiveTime = System.currentTimeMillis() @@ -63,43 +64,6 @@ open class AweryLifecycle private constructor() : ActivityLifecycleCallbacks { getActivityInfo(activity).isPaused = true } - /** - * DO NOT EVER USE DIRECTLY THIS CLASS! - * It was made just for the Android Framework to work properly! - */ - @Suppress("OVERRIDE_DEPRECATION") - internal class CallbackFragment : Fragment() { - internal lateinit var fragmentManager: FragmentManager - internal var requestCode: Int = 0 - internal var activityResultCallback: ((Int, Intent?) -> Unit)? = null - internal var permissionsResultCallback: ((didGranted: Boolean) -> Unit)? = null - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if(requestCode != this.requestCode) return - activityResultCallback?.invoke(resultCode, data) - finish() - } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - if(requestCode != this.requestCode) return - - if(permissions.isEmpty()) { - permissionsResultCallback?.invoke(false) - } else if(permissions.size == 1) { - permissionsResultCallback?.invoke(grantResults[0] == PackageManager.PERMISSION_GRANTED) - } else { - throw IllegalStateException("Somehow you've requested multiple permissions at once. This behaviour isn't supported.") - } - - finish() - } - - private fun finish() { - fragmentManager.beginTransaction().remove(this).commit() - fragmentManager.executePendingTransactions() - } - } - private class ActivityInfo(activity: A) : Comparable?> { val activity = WeakReference(activity) var lastActiveTime = 0L @@ -173,14 +137,6 @@ open class AweryLifecycle private constructor() : ActivityLifecycleCallbacks { private const val TAG = "AweryLifecycle" private var handler: Handler? = null - private val activityRequestCodes = UniqueIdGenerator( - 1, UniqueIdGenerator.OverflowMode.RESET) - - @JvmStatic - fun generateRequestCode(): Int { - return activityRequestCodes.integer - } - @JvmStatic fun restartApp() { Log.i(TAG, "restartApp() has been invoked!") @@ -203,50 +159,6 @@ open class AweryLifecycle private constructor() : ActivityLifecycleCallbacks { else Runtime.getRuntime().exit(0) } - @MainThread - fun addActivityResultListener( - activity: Activity, - requestCode: Int, - activityResultCallback: ((resultCode: Int, data: Intent?) -> Unit)?, - permissionsResultCallback: ((didGranted: Boolean) -> Unit)? - ): Fragment { - if(activity is FragmentActivity) { - return activity.supportFragmentManager.let { fragmentManager -> - val fragment = CallbackFragment().apply { - this.fragmentManager = fragmentManager - this.requestCode = requestCode - this.activityResultCallback = activityResultCallback - this.permissionsResultCallback = permissionsResultCallback - } - - fragmentManager.beginTransaction().add(fragment, null).commit() - fragmentManager.executePendingTransactions() - return@let fragment - } - } else { - throw IllegalArgumentException("Activity must be an instance of FragmentActivity!") - } - } - - /** - * This method is a little bit hacky so after library update it may break. - * @param context Context from the [FragmentActivity] - * @author MrBoomDev - */ - @JvmStatic - @Suppress("deprecation") - @MainThread - @JvmOverloads - fun startActivityForResult( - context: Activity, - intent: Intent, - activityResultCallback: ((resultCode: Int, data: Intent?) -> Unit), - requestCode: Int = generateRequestCode() - ) { - addActivityResultListener(context, requestCode, activityResultCallback, null) - .startActivityForResult(intent, requestCode) - } - @JvmStatic @Deprecated(message = "Java") fun getActivity(context: Context): Activity? { diff --git a/androidApp/src/main/java/com/mrboomdev/awery/app/AweryNotifications.java b/androidApp/src/main/java/com/mrboomdev/awery/app/AweryNotifications.java index 44c73c8e..d7ac7198 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/app/AweryNotifications.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/app/AweryNotifications.java @@ -11,7 +11,7 @@ import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; -import com.mrboomdev.awery.util.UniqueIdGenerator; +import com.mrboomdev.awery.utils.UniqueIdGenerator; import org.jetbrains.annotations.Contract; diff --git a/androidApp/src/main/java/com/mrboomdev/awery/app/CrashHandler.kt b/androidApp/src/main/java/com/mrboomdev/awery/app/CrashHandler.kt index 32529e7b..03107903 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/app/CrashHandler.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/app/CrashHandler.kt @@ -6,7 +6,6 @@ import android.content.pm.PackageManager import android.net.Uri import android.util.Log import android.widget.Toast -import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.core.content.FileProvider import androidx.core.view.setPadding @@ -14,21 +13,20 @@ import androidx.core.widget.NestedScrollView import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.textview.MaterialTextView import com.mrboomdev.awery.BuildConfig -import com.mrboomdev.awery.R -import com.mrboomdev.awery.app.App.Companion.i18n import com.mrboomdev.awery.app.App.Companion.isTv import com.mrboomdev.awery.app.App.Companion.toast -import com.mrboomdev.awery.app.AweryLifecycle.Companion.anyContext import com.mrboomdev.awery.app.AweryLifecycle.Companion.appContext import com.mrboomdev.awery.app.AweryLifecycle.Companion.getAnyActivity import com.mrboomdev.awery.app.AweryLifecycle.Companion.restartApp import com.mrboomdev.awery.app.AweryLifecycle.Companion.runOnUiThread +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.exceptions.OkiThrowableMessage -import com.mrboomdev.awery.util.extensions.activity import com.mrboomdev.awery.util.extensions.dpPx import com.mrboomdev.awery.util.extensions.fixAndShow import com.mrboomdev.awery.util.extensions.toChooser import com.mrboomdev.awery.util.ui.dialog.DialogBuilder +import com.mrboomdev.awery.utils.activity import xcrash.Errno import xcrash.XCrash import xcrash.XCrash.InitParameters @@ -55,7 +53,8 @@ object CrashHandler { // This library doesn't check if an ANR has happened // properly on Android TV, so we disable it. - setAnrCheckProcessState(!isTv) + // Also while debugging an ANR may be triggered, so we disable it in the dev build. + setAnrCheckProcessState(!isTv && !BuildConfig.DEBUG) // Crash logs are too long so we do strip all non-relevant dumps. setJavaDumpNetworkInfo(false) @@ -100,14 +99,14 @@ object CrashHandler { } private fun handleError(type: CrashType, message: String?) { - toast(appContext.getString(when(type) { + toast(i18n(when(type) { CrashType.ANR -> { Log.e(TAG, "ANR error has happened. $message") - R.string.app_not_responding_restart + Res.string.app_not_responding_restart } - CrashType.JAVA -> R.string.app_crash - CrashType.NATIVE -> R.string.something_terrible_happened + CrashType.JAVA -> Res.string.app_crash + CrashType.NATIVE -> Res.string.something_terrible_happened }), 1) restartApp() @@ -147,9 +146,8 @@ object CrashHandler { files.forEachIndexed { index, file -> showDialog( context = context, - titleRes = if(files.size == 1) R.string.app_crash else null, - title = if(files.size == 1) null else "Awery crash report #${index + 1}", - messagePrefixRes = R.string.please_report_bug_app, + title = i18n(Res.string.app_crash), + messagePrefix = i18n(Res.string.please_report_bug_app), file = file, dismissCallback = if(index == 0) {{ crashLogsDirectory.delete() @@ -162,11 +160,8 @@ object CrashHandler { fun showDialog( context: Context? = null, title: String? = null, - @StringRes titleRes: Int? = null, message: String? = null, - @StringRes messageRes: Int? = null, messagePrefix: String? = null, - @StringRes messagePrefixRes: Int? = null, throwable: Throwable? = null, file: File? = null, dismissCallback: () -> Unit = {} @@ -177,7 +172,7 @@ object CrashHandler { runOnUiThread { DialogBuilder(mContext?.activity ?: activity!!).apply { - setTitle(title ?: titleRes?.let { i18n(it) } ?: oki?.title) + setTitle(title ?: oki?.title) setMessage(buildString { if(messagePrefix != null) { @@ -185,21 +180,11 @@ object CrashHandler { append("\n\n") } - if(messagePrefixRes != null) { - append(i18n(messagePrefixRes)) - append("\n\n") - } - if(message != null) { append(message.trim()) append("\n\n") } - if(messageRes != null) { - append(i18n(messageRes)) - append("\n\n") - } - if(oki != null) { append(oki.message.trim()) } @@ -210,12 +195,12 @@ object CrashHandler { dismissCallback() } - setPositiveButton(R.string.ok) { + setPositiveButton(i18n(Res.string.ok)) { it.dismiss() } if(file?.exists() == true || message != null || oki != null) { - setNegativeButton(R.string.share) { + setNegativeButton(i18n(Res.string.share)) { val mFile = file ?: File((mContext ?: appContext).filesDir, "crash_report.txt").apply { delete() createNewFile() @@ -255,7 +240,7 @@ object CrashHandler { }.also { (mContext ?: appContext).startActivity(it) } } - setNeutralButton(R.string.see_error) { + setNeutralButton(i18n(Res.string.see_error)) { BottomSheetDialog(mContext?.activity ?: activity!!).apply { setContentView(NestedScrollView(mContext!!).apply { addView(MaterialTextView(mContext).apply { @@ -264,7 +249,7 @@ object CrashHandler { text = if(file?.exists() == true) { file.readText() - } else (oki?.print() ?: message ?: i18n(messageRes!!)).trim() + } else (oki?.print() ?: message!!).trim() }) }) }.fixAndShow() @@ -293,16 +278,6 @@ object CrashHandler { return this } - fun setMessage(@StringRes prefix: Int): Builder { - report.message = anyContext.getString(prefix) - return this - } - - fun setPrefix(@StringRes prefix: Int): Builder { - report.prefix = anyContext.getString(prefix) - return this - } - fun setThrowable(throwable: Throwable?): Builder { report.throwable = throwable return this @@ -313,11 +288,6 @@ object CrashHandler { return this } - fun setTitle(@StringRes title: Int): Builder { - report.title = anyContext.getString(title) - return this - } - fun build(): CrashReport { return report } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/app/update/UpdatesManager.kt b/androidApp/src/main/java/com/mrboomdev/awery/app/update/UpdatesManager.kt index bb76049e..9b8c8c97 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/app/update/UpdatesManager.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/app/update/UpdatesManager.kt @@ -7,21 +7,26 @@ import androidx.core.content.FileProvider import com.mrboomdev.awery.BuildConfig import com.mrboomdev.awery.R import com.mrboomdev.awery.app.App.Companion.getMoshi -import com.mrboomdev.awery.app.App.Companion.i18n import com.mrboomdev.awery.app.App.Companion.showLoadingWindow import com.mrboomdev.awery.app.App.Companion.toast import com.mrboomdev.awery.app.AweryLifecycle.Companion.runOnUiThread import com.mrboomdev.awery.app.CrashHandler +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException +import com.mrboomdev.awery.generated.Res +import com.mrboomdev.awery.generated.dismiss +import com.mrboomdev.awery.generated.download +import com.mrboomdev.awery.generated.size +import com.mrboomdev.awery.generated.update_available +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.ContentType import com.mrboomdev.awery.util.NiceUtils -import com.mrboomdev.awery.util.exceptions.ZeroResultsException import com.mrboomdev.awery.util.extensions.formatFileSize import com.mrboomdev.awery.util.extensions.removeIndent -import com.mrboomdev.awery.util.extensions.startActivityForResult import com.mrboomdev.awery.util.io.HttpClient.download import com.mrboomdev.awery.util.io.HttpClient.fetch import com.mrboomdev.awery.util.io.HttpRequest import com.mrboomdev.awery.util.ui.dialog.DialogBuilder +import com.mrboomdev.awery.utils.startActivityForResult import com.squareup.moshi.Json import com.squareup.moshi.adapter import kotlinx.coroutines.CancellationException @@ -43,15 +48,15 @@ object UpdatesManager { fun showUpdateDialog(context: Activity, update: Update) { runOnUiThread { DialogBuilder(context) - .setTitle(R.string.update_available) + .setTitle(i18n(Res.string.update_available)) .setMessage(""" ${update.title} - ${i18n(R.string.size)}: ${update.size.formatFileSize()} + ${i18n(Res.string.size)}: ${update.size.formatFileSize()} ${update.body} """.trim().removeIndent()) - .setNeutralButton(R.string.dismiss) { it.dismiss() } - .setPositiveButton(R.string.download) { dialog -> + .setNeutralButton(i18n(Res.string.dismiss)) { it.dismiss() } + .setPositiveButton(i18n(Res.string.download)) { dialog -> val window = showLoadingWindow() CoroutineScope(Dispatchers.IO + CoroutineExceptionHandler { _, t -> diff --git a/androidApp/src/main/java/com/mrboomdev/awery/data/settings/SettingsData.java b/androidApp/src/main/java/com/mrboomdev/awery/data/settings/SettingsData.java index c7e65d52..fb06f2b8 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/data/settings/SettingsData.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/data/settings/SettingsData.java @@ -2,12 +2,12 @@ import static com.mrboomdev.awery.app.AweryLifecycle.getAppContext; import static com.mrboomdev.awery.app.AweryLifecycle.runOnUiThread; +import static com.mrboomdev.awery.platform.PlatformResourcesKt.i18n; import static com.mrboomdev.awery.util.NiceUtils.formatFileSize; import static com.mrboomdev.awery.util.NiceUtils.stream; import static com.mrboomdev.awery.util.async.AsyncUtils.thread; import static com.mrboomdev.awery.util.io.FileUtil.getFileSize; -import android.content.Context; import android.util.Log; import androidx.annotation.MainThread; @@ -19,15 +19,17 @@ import com.mrboomdev.awery.BuildConfig; import com.mrboomdev.awery.R; import com.mrboomdev.awery.data.Constants; +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException; import com.mrboomdev.awery.extensions.ExtensionSettings; import com.mrboomdev.awery.extensions.ExtensionsFactory; import com.mrboomdev.awery.extensions.ExtensionsManager; import com.mrboomdev.awery.extensions.support.yomi.aniyomi.AniyomiManager; import com.mrboomdev.awery.extensions.support.yomi.tachiyomi.TachiyomiManager; +import com.mrboomdev.awery.generated.Res; +import com.mrboomdev.awery.generated.String0_commonMainKt; import com.mrboomdev.awery.ui.mobile.screens.settings.TabsSettings; import com.mrboomdev.awery.util.Selection; import com.mrboomdev.awery.util.async.AsyncFuture; -import com.mrboomdev.awery.util.exceptions.ZeroResultsException; import org.jetbrains.annotations.Contract; @@ -58,7 +60,6 @@ public static String resolveValue(@NonNull String key) { } public static void getSelectionList( - Context context, @NonNull String listId, Errorable>, Throwable> callback ) { @@ -186,7 +187,7 @@ public void onFailure(@NonNull Throwable t) { } }); } else { - callback.onError(new ZeroResultsException("Can't find any items", R.string.no)); + callback.onError(new ZeroResultsException("Can't find any items", i18n(String0_commonMainKt.getNo(Res.string.INSTANCE)))); } } } \ No newline at end of file diff --git a/androidApp/src/main/java/com/mrboomdev/awery/data/settings/SettingsItem.java b/androidApp/src/main/java/com/mrboomdev/awery/data/settings/SettingsItem.java index b4481bbe..7acbdfb5 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/data/settings/SettingsItem.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/data/settings/SettingsItem.java @@ -1,18 +1,18 @@ package com.mrboomdev.awery.data.settings; -import static com.mrboomdev.awery.app.App.i18n; import static com.mrboomdev.awery.app.AweryLifecycle.getAnyContext; +import static com.mrboomdev.awery.platform.PlatformResourcesKt.i18n; import android.content.Context; import android.graphics.drawable.Drawable; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; -import androidx.annotation.StringRes; import androidx.appcompat.content.res.AppCompatResources; import com.mrboomdev.awery.R; import com.mrboomdev.awery.app.App; +import com.mrboomdev.awery.generated.Res; import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsActions; import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsDataHandler; import com.mrboomdev.awery.util.Parser; @@ -259,7 +259,7 @@ public boolean isRestartRequired() { } public String getTitle(Context context) { - var got = i18n(R.string.class, title); + var got = i18n(title); return got != null ? got : title; } @@ -429,11 +429,6 @@ public Builder setValue(Selection.State state) { return this; } - public Builder setTitle(@StringRes int title) { - item.title = getAnyContext().getString(title); - return this; - } - public Builder setDescription(String description) { item.description = description; return this; diff --git a/androidApp/src/main/java/com/mrboomdev/awery/extensions/ExtensionSettings.java b/androidApp/src/main/java/com/mrboomdev/awery/extensions/ExtensionSettings.java index a0b8451b..a104ee1c 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/extensions/ExtensionSettings.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/extensions/ExtensionSettings.java @@ -6,6 +6,7 @@ import static com.mrboomdev.awery.app.AweryLifecycle.getActivity; import static com.mrboomdev.awery.app.AweryLifecycle.runOnUiThread; import static com.mrboomdev.awery.data.settings.NicePreferences.getPrefs; +import static com.mrboomdev.awery.platform.PlatformResourcesKt.i18n; import static com.mrboomdev.awery.util.NiceUtils.cleanString; import static com.mrboomdev.awery.util.NiceUtils.cleanUrl; import static com.mrboomdev.awery.util.NiceUtils.compareVersions; @@ -42,6 +43,8 @@ import com.mrboomdev.awery.data.settings.ObservableSettingsItem; import com.mrboomdev.awery.data.settings.SettingsItem; import com.mrboomdev.awery.data.settings.SettingsItemType; +import com.mrboomdev.awery.generated.Res; +import com.mrboomdev.awery.generated.String0_commonMainKt; import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsActivity; import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsDataHandler; import com.mrboomdev.awery.util.async.AsyncFuture; @@ -129,7 +132,7 @@ public void onSuccess(@NonNull Extension extension) { public void onSuccess(@NonNull String s) { runOnUiThread(() -> new DialogBuilder(activity) .setTitle(extension.getVersion() + " Changelog") - .setPositiveButton(R.string.ok, DialogBuilder::dismiss) + .setPositiveButton(i18n(String0_commonMainKt.getNo(Res.string.INSTANCE)), DialogBuilder::dismiss) .setMessage(cleanString(s)) .show()); } @@ -151,7 +154,7 @@ public void onFailure(@NonNull Throwable t) { Log.e(TAG, "Failed to install an extension!", t); CrashHandler.showErrorDialog(new CrashHandler.CrashReport.Builder() - .setTitle(R.string.extension_installed_failed) + .setTitle(i18n(String0_commonMainKt.getExtension_installed_failed(Res.string.INSTANCE))) .setThrowable(t) .build()); } @@ -166,25 +169,25 @@ public Drawable getIcon(@NonNull Context context) { @Override public void onClick(Context context) { - var inputField = new EditTextField(context, R.string.repository_url); + var inputField = new EditTextField(context, i18n(String0_commonMainKt.getRepository_url(Res.string.INSTANCE))); inputField.setLinesCount(1); currentDialog = new DialogBuilder(context) - .setTitle(R.string.add_extension) + .setTitle(i18n(String0_commonMainKt.getAdd_extension(Res.string.INSTANCE))) .addView(inputField.getView()) .setOnDismissListener(dialog -> currentDialog = dialog) - .setNegativeButton(R.string.cancel, DialogBuilder::dismiss) - .setNeutralButton(R.string.pick_from_storage, dialog -> pickLauncher.launch("*/*")) - .setPositiveButton(R.string.ok, dialog -> { + .setNegativeButton(i18n(String0_commonMainKt.getCancel(Res.string.INSTANCE)), DialogBuilder::dismiss) + .setNeutralButton(i18n(String0_commonMainKt.getPick_from_storage(Res.string.INSTANCE)), dialog -> pickLauncher.launch("*/*")) + .setPositiveButton(i18n(String0_commonMainKt.getOk(Res.string.INSTANCE)), dialog -> { var text = cleanUrl(inputField.getText()); if(text.isBlank()) { - inputField.setError(R.string.text_cant_empty); + inputField.setError(i18n(String0_commonMainKt.getText_cant_empty(Res.string.INSTANCE))); return; } if(!isUrlValid(text)) { - inputField.setError(R.string.invalid_url); + inputField.setError(i18n(String0_commonMainKt.getInvalid_url(Res.string.INSTANCE))); return; } @@ -256,7 +259,7 @@ public void loadData() { } copyFrom(new Builder(SettingsItemType.SCREEN) - .setTitle(manager.getName() + " " + activity.getString(R.string.extensions)) + .setTitle(i18n(String0_commonMainKt.getExtensions(Res.string.INSTANCE))) .setItems(items) .build()); } @@ -316,7 +319,7 @@ public void onClick(Context context) { }, new CustomSettingsItem(new SettingsItem.Builder(SettingsItemType.ACTION) - .setTitle(R.string.delete).setIcon(R.drawable.ic_delete_outlined).build()) { + .setTitle(i18n(String0_commonMainKt.getDelete(Res.string.INSTANCE))).setIcon(R.drawable.ic_delete_outlined).build()) { @Override public void onClick(Context context) { @@ -398,7 +401,7 @@ public void onSuccess(@NonNull File file) { @Override public void onSuccess(@NonNull Extension result) { window.dismiss(); - toast(R.string.extension_installed_successfully); + toast(i18n(String0_commonMainKt.getExtension_installed_successfully(Res.string.INSTANCE))); runOnUiThread(() -> ((RepositorySetting) RepositoryItem.this.getParent()).onSettingChange(RepositoryItem.this)); } @@ -416,7 +419,7 @@ public void onFailure(@NonNull Throwable t) { var dialog = new DialogBuilder() .setTitle("Failed to install an extension") .setNeutralButton("Dismiss", DialogBuilder::dismiss) - .setPositiveButton(R.string.uninstall_extension, d -> { + .setPositiveButton(i18n(String0_commonMainKt.getUninstall_extension(Res.string.INSTANCE)), d -> { var window1 = showLoadingWindow(); manager.uninstallExtension(context, extension.getId()).addCallback(new AsyncFuture.Callback<>() { @@ -614,7 +617,7 @@ public void onFailure(Throwable e) { @Override public String getTitle(android.content.Context context) { - return context.getString(R.string.uninstall_extension); + return i18n(String0_commonMainKt.getUninstall_extension(Res.string.INSTANCE)); } @Override @@ -651,7 +654,7 @@ public void onFailure(@NonNull Throwable e) { CrashHandler.showErrorDialog(new CrashHandler.CrashReport.Builder() .setTitle("Failed to uninstall an extension") - .setPrefix(R.string.please_report_bug_app) + .setPrefix(i18n(String0_commonMainKt.getPlease_report_bug_app(Res.string.INSTANCE))) .setThrowable(e) .build()); } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/internal/InternalProviders.java b/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/internal/InternalProviders.java index 0c5fe484..55c52a25 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/internal/InternalProviders.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/internal/InternalProviders.java @@ -1,5 +1,6 @@ package com.mrboomdev.awery.extensions.support.internal; +import static com.mrboomdev.awery.platform.PlatformResourcesKt.i18n; import static com.mrboomdev.awery.util.NiceUtils.stream; import static com.mrboomdev.awery.util.async.AsyncUtils.thread; @@ -8,13 +9,15 @@ import com.mrboomdev.awery.R; import com.mrboomdev.awery.app.App; import com.mrboomdev.awery.data.settings.SettingsList; +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException; import com.mrboomdev.awery.extensions.Extension; import com.mrboomdev.awery.extensions.ExtensionProvider; import com.mrboomdev.awery.extensions.ExtensionsManager; import com.mrboomdev.awery.ext.data.CatalogMedia; import com.mrboomdev.awery.extensions.data.CatalogSearchResults; +import com.mrboomdev.awery.generated.Res; +import com.mrboomdev.awery.generated.String0_commonMainKt; import com.mrboomdev.awery.util.async.AsyncFuture; -import com.mrboomdev.awery.util.exceptions.ZeroResultsException; import java.util.Set; @@ -51,7 +54,7 @@ public AsyncFuture> searchMedia(@No var progresses = App.Companion.getDatabase().getMediaProgressDao().getAllFromList(feed); if(progresses.isEmpty()) { - throw new ZeroResultsException("No bookmarks", R.string.no_media_found); + throw new ZeroResultsException("No bookmarks", i18n(String0_commonMainKt.getNo_media_found(Res.string.INSTANCE))); } return CatalogSearchResults.of(stream(progresses) diff --git a/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/yomi/YomiManager.kt b/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/yomi/YomiManager.kt index aa06bc8f..87f7f287 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/yomi/YomiManager.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/yomi/YomiManager.kt @@ -12,10 +12,10 @@ import android.net.Uri import android.os.Build import android.provider.Settings import android.util.Log +import androidx.core.app.ActivityCompat.startActivityForResult import com.mrboomdev.awery.app.App.Companion.getMoshi import com.mrboomdev.awery.app.AweryLifecycle.Companion.anyContext import com.mrboomdev.awery.app.AweryLifecycle.Companion.runOnUiThread -import com.mrboomdev.awery.app.AweryLifecycle.Companion.startActivityForResult import com.mrboomdev.awery.data.settings.NicePreferences import com.mrboomdev.awery.extensions.Extension import com.mrboomdev.awery.extensions.ExtensionProvider @@ -24,12 +24,16 @@ import com.mrboomdev.awery.extensions.ExtensionsManager import com.mrboomdev.awery.util.ContentType import com.mrboomdev.awery.util.NiceUtils import com.mrboomdev.awery.ext.util.Progress +import com.mrboomdev.awery.ext.util.exceptions.ExtensionInstallException import com.mrboomdev.awery.util.async.AsyncFuture import com.mrboomdev.awery.util.async.AsyncUtils import com.mrboomdev.awery.util.async.ControllableAsyncFuture -import com.mrboomdev.awery.util.extensions.activity import com.mrboomdev.awery.util.io.HttpClient.fetchSync import com.mrboomdev.awery.util.io.HttpRequest +import com.mrboomdev.awery.utils.activity +import com.mrboomdev.awery.utils.buildIntent +import com.mrboomdev.awery.utils.getPackageUri +import com.mrboomdev.awery.utils.startActivityForResult import com.squareup.moshi.adapter import dalvik.system.PathClassLoader import java.io.FileOutputStream @@ -37,34 +41,25 @@ import java.io.IOException import java.util.concurrent.CancellationException import java.util.concurrent.atomic.AtomicReference +private const val PM_FLAGS = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_META_DATA +private const val TAG = "YomiManager" + abstract class YomiManager : ExtensionsManager() { private val extensions: MutableMap = HashMap() - private var progress: Progress? = null - abstract val mainClassMeta: String? - abstract val nsfwMeta: String? - abstract val requiredFeature: String - abstract val prefix: String - abstract val minVersion: Double - abstract val maxVersion: Double - abstract val baseFeatures: Set? abstract fun createProviders(extension: Extension?, main: Any?): List - override fun getExtension(id: String): Extension { - return extensions[id]!! - } + override fun getExtension(id: String) = extensions[id]!! - override fun getAllExtensions(): Collection { - return extensions.values - } + override fun getAllExtensions() = extensions.values override fun getProgress(): Progress { if(progress == null) { @@ -245,7 +240,7 @@ abstract class YomiManager : ExtensionsManager() { } } - private fun installApk(context: Context, uri: Uri, future: ControllableAsyncFuture) { + private fun installApk(context: Context, uri: Uri, future: ControllableAsyncFuture) = with(context.activity) { val tempFile = NiceUtils.getTempFile() try { @@ -258,45 +253,42 @@ abstract class YomiManager : ExtensionsManager() { os.write(buffer, 0, read) } - runOnUiThread { - val intent = Intent(Intent.ACTION_VIEW) - intent.putExtra(Intent.EXTRA_RETURN_RESULT, true) - intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true) - intent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, context.packageName) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - intent.setDataAndType(uri, ContentType.APK.mimeType) - - val pm = context.packageManager - val info = pm.getPackageArchiveInfo(tempFile.path, PM_FLAGS) - - if(info == null) { - future.fail(NullPointerException("Failed to parse an APK!")) - return@runOnUiThread - } + val info = packageManager.getPackageArchiveInfo(tempFile.path, PM_FLAGS) ?: run { + future.fail(ExtensionInstallException("Failed to parse an APK!")) + return@with + } - runOnUiThread { - startActivityForResult(context.activity, intent, { resultCode, _ -> - when(resultCode) { - Activity.RESULT_OK, Activity.RESULT_FIRST_USER -> { - try { - val got = pm.getPackageInfo(info.packageName, PM_FLAGS) - - if(info.versionCode != got.versionCode) { - future.fail(IllegalStateException("Failed to install an APK!")) - return@startActivityForResult - } - - initExtension(got, context) - future.complete(getExtension(info.packageName)) - } catch(e: Throwable) { - future.fail(e) + runOnUiThread { + startActivityForResult(buildIntent( + action = Intent.ACTION_VIEW, + data = uri, + type = ContentType.APK.mimeType + ) { + putExtra(Intent.EXTRA_RETURN_RESULT, true) + putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true) + putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, packageName) + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + }, { resultCode, _ -> + when(resultCode) { + Activity.RESULT_OK, Activity.RESULT_FIRST_USER -> { + try { + val got = packageManager.getPackageInfo(info.packageName, PM_FLAGS) + + if(info.versionCode != got.versionCode) { + future.fail(IllegalStateException("Failed to install an APK!")) + return@startActivityForResult } - } - Activity.RESULT_CANCELED -> future.fail(CancellationException("Install cancelled")) + initExtension(got, context) + future.complete(getExtension(info.packageName)) + } catch(e: Throwable) { + future.fail(e) + } } - }) - } + + Activity.RESULT_CANCELED -> future.fail(CancellationException("Install cancelled")) + } + }) } } } @@ -305,16 +297,15 @@ abstract class YomiManager : ExtensionsManager() { } } - override fun installExtension(context: Context, uri: Uri): AsyncFuture { - return AsyncUtils.controllableFuture { future -> + override fun installExtension(context: Context, uri: Uri) = with(context.activity) { + return@with AsyncUtils.controllableFuture { future -> if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O || context.packageManager.canRequestPackageInstalls()) { installApk(context, uri, future) return@controllableFuture } - val settingsIntent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES) - settingsIntent.setData(Uri.parse("package:" + context.packageName)) + runOnUiThread { - startActivityForResult(context.activity, settingsIntent, { resultCode, _ -> + startActivityForResult(buildIntent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, getPackageUri()), { resultCode, _ -> when(resultCode) { Activity.RESULT_OK -> AsyncUtils.thread { installApk(context, uri, future) } Activity.RESULT_CANCELED -> future.fail(CancellationException("Permission denied!")) @@ -325,12 +316,10 @@ abstract class YomiManager : ExtensionsManager() { } } - override fun uninstallExtension(context: Context, id: String): AsyncFuture { - return AsyncUtils.controllableFuture { future -> - val intent = Intent(Intent.ACTION_DELETE) - intent.setData(Uri.parse("package:$id")) + override fun uninstallExtension(context: Context, id: String) = with(context.activity) { + return@with AsyncUtils.controllableFuture { future -> runOnUiThread { - startActivityForResult(context.activity, intent, { _, _ -> + startActivityForResult(buildIntent(Intent.ACTION_DELETE, getPackageUri()), { _, _ -> //Ignore the resultCode, it always equal to 0 try { @@ -352,9 +341,4 @@ abstract class YomiManager : ExtensionsManager() { } } } - - companion object { - private const val PM_FLAGS = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_META_DATA - private const val TAG = "YomiManager" - } } \ No newline at end of file diff --git a/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/yomi/aniyomi/AniyomiProvider.java b/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/yomi/aniyomi/AniyomiProvider.java index 1420c049..e8ff5637 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/yomi/aniyomi/AniyomiProvider.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/extensions/support/yomi/aniyomi/AniyomiProvider.java @@ -1,6 +1,7 @@ package com.mrboomdev.awery.extensions.support.yomi.aniyomi; import static com.mrboomdev.awery.app.App.toast; +import static com.mrboomdev.awery.platform.PlatformResourcesKt.i18n; import static com.mrboomdev.awery.util.NiceUtils.find; import static com.mrboomdev.awery.util.NiceUtils.findIndex; import static com.mrboomdev.awery.util.NiceUtils.requireNonNullElse; @@ -20,6 +21,7 @@ import com.mrboomdev.awery.data.settings.SettingsItemType; import com.mrboomdev.awery.data.settings.SettingsList; import com.mrboomdev.awery.ext.data.CatalogMedia; +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException; import com.mrboomdev.awery.extensions.Extension; import com.mrboomdev.awery.extensions.ExtensionProvider; import com.mrboomdev.awery.extensions.data.CatalogFeed; @@ -28,11 +30,12 @@ import com.mrboomdev.awery.extensions.data.CatalogVideo; import com.mrboomdev.awery.extensions.data.CatalogVideoFile; import com.mrboomdev.awery.extensions.support.yomi.YomiProvider; +import com.mrboomdev.awery.generated.Res; +import com.mrboomdev.awery.generated.String0_commonMainKt; import com.mrboomdev.awery.util.Selection; import com.mrboomdev.awery.util.adapters.MediaAdapter; import com.mrboomdev.awery.util.async.AsyncFuture; import com.mrboomdev.awery.util.async.AsyncUtils; -import com.mrboomdev.awery.util.exceptions.ZeroResultsException; import org.jetbrains.annotations.Contract; @@ -222,7 +225,7 @@ public AsyncFuture> getVideos(@NonNull SettingsList var episodes = AniyomiKotlinBridge.getEpisodesList(source, AniyomiMediaKt.toSAnime(media)).await(); if(episodes == null || episodes.isEmpty()) { - throw new ZeroResultsException("Aniyomi: No episodes found", R.string.no_episodes_found); + throw new ZeroResultsException("Aniyomi: No episodes found", i18n(String0_commonMainKt.getNo_episodes_found(Res.string.INSTANCE))); } return stream(episodes) diff --git a/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/YomiManager.kt b/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/YomiManager.kt index 28c97897..e7f7dfed 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/YomiManager.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/YomiManager.kt @@ -11,7 +11,6 @@ import android.content.pm.PackageManager import android.os.Build import android.util.Log import com.mrboomdev.awery.app.App.Companion.toast -import com.mrboomdev.awery.app.AweryLifecycle.Companion.generateRequestCode import com.mrboomdev.awery.app.ExtensionsManager.isEnabled import com.mrboomdev.awery.ext.constants.AweryFeature import com.mrboomdev.awery.ext.source.Context @@ -21,7 +20,8 @@ import com.mrboomdev.awery.ext.source.SourcesManager import com.mrboomdev.awery.ext.util.Image import com.mrboomdev.awery.ext.util.Progress import com.mrboomdev.awery.ext.util.exceptions.ExtensionInstallException -import com.mrboomdev.awery.util.UniqueIdGenerator +import com.mrboomdev.awery.utils.UniqueIdGenerator +import com.mrboomdev.awery.utils.generateRequestCode import dalvik.system.PathClassLoader import eu.kanade.tachiyomi.network.NetworkHelper import kotlinx.coroutines.async diff --git a/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/aniyomi/AniyomiSource.kt b/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/aniyomi/AniyomiSource.kt index 10fa8d13..385f447f 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/aniyomi/AniyomiSource.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/aniyomi/AniyomiSource.kt @@ -10,9 +10,12 @@ import com.mrboomdev.awery.ext.data.CatalogMedia import com.mrboomdev.awery.ext.data.CatalogSearchResults import com.mrboomdev.awery.ext.data.Setting import com.mrboomdev.awery.ext.data.get +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException +import com.mrboomdev.awery.generated.Res +import com.mrboomdev.awery.generated.no_media_found +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.sources.yomi.YomiManager import com.mrboomdev.awery.sources.yomi.YomiSource -import com.mrboomdev.awery.util.exceptions.ZeroResultsException import com.mrboomdev.awery.util.extensions.mapOfNotNull import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource import eu.kanade.tachiyomi.animesource.AnimeSource @@ -100,7 +103,7 @@ class AniyomiSource( return when(catalog) { is Catalog.Media -> getAnimesPage(filters).let { page -> if(page.animes.isEmpty()) { - throw ZeroResultsException("Zero media results!", R.string.no_media_found) + throw ZeroResultsException("Zero media results!", i18n(Res.string.no_media_found)) } CatalogSearchResults(page.animes.map { anime -> diff --git a/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/tachiyomi/TachiyomiSource.kt b/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/tachiyomi/TachiyomiSource.kt index 0cc6b4ad..d3a74692 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/tachiyomi/TachiyomiSource.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/sources/yomi/tachiyomi/TachiyomiSource.kt @@ -10,10 +10,12 @@ import com.mrboomdev.awery.ext.data.CatalogMedia import com.mrboomdev.awery.ext.data.CatalogSearchResults import com.mrboomdev.awery.ext.data.Setting import com.mrboomdev.awery.ext.data.get +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.sources.yomi.YomiManager import com.mrboomdev.awery.sources.yomi.YomiSource import com.mrboomdev.awery.sources.yomi.aniyomi.AniyomiManager -import com.mrboomdev.awery.util.exceptions.ZeroResultsException import com.mrboomdev.awery.util.extensions.awaitSingle import com.mrboomdev.awery.util.extensions.mapOfNotNull import eu.kanade.tachiyomi.source.CatalogueSource @@ -102,7 +104,7 @@ class TachiyomiSource( return when(catalog) { Catalog.Media -> getMangasPage(filters).let { page -> if(page.mangas.isEmpty()) { - throw ZeroResultsException("Zero media results!", R.string.no_media_found) + throw ZeroResultsException("Zero media results!", i18n(Res.string.no_media_found)) } CatalogSearchResults(page.mangas.map { manga -> diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/EmptyStateView.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/EmptyStateView.kt index ecbeb2a0..37112943 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/EmptyStateView.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/EmptyStateView.kt @@ -11,7 +11,7 @@ import androidx.annotation.StringRes import androidx.viewbinding.ViewBinding import com.google.android.material.progressindicator.CircularProgressIndicator import com.mrboomdev.awery.databinding.LayoutLoadingBinding -import com.mrboomdev.awery.util.extensions.inflater +import com.mrboomdev.awery.utils.inflater class EmptyStateView(private val binding: LayoutLoadingBinding) : ViewBinding { val title: TextView = binding.title diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/ExpandableTextView.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/ExpandableTextView.kt index 2eba9b68..6ddb1398 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/ExpandableTextView.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/ExpandableTextView.kt @@ -17,6 +17,8 @@ import android.util.AttributeSet import android.view.MotionEvent import com.google.android.material.textview.MaterialTextView import com.mrboomdev.awery.R +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import java.lang.Integer.min import kotlin.math.max import kotlin.math.roundToInt @@ -167,8 +169,8 @@ class ExpandableTextView @JvmOverloads constructor( try { mCollapsedLines = getInt(R.styleable.ExpandableTextView_collapsedLines, COLLAPSED_MAX_LINES) mAnimationDuration = getInt(R.styleable.ExpandableTextView_animDuration, DEFAULT_ANIM_DURATION) - mReadMoreText = getString(R.styleable.ExpandableTextView_readMoreText) ?: " ${context.getString(R.string.read_more)}" - mReadLessText = getString(R.styleable.ExpandableTextView_readLessText) ?: " ${context.getString(R.string.read_less)}" + mReadMoreText = getString(R.styleable.ExpandableTextView_readMoreText) ?: " ${i18n(Res.string.read_more)}" + mReadLessText = getString(R.styleable.ExpandableTextView_readLessText) ?: " ${i18n(Res.string.read_less)}" foregroundColor = getColor(R.styleable.ExpandableTextView_foregroundColor, Color.TRANSPARENT) isUnderlined = getBoolean(R.styleable.ExpandableTextView_isUnderlined, false) isExpanded = getBoolean(R.styleable.ExpandableTextView_textIsExpanded, false) @@ -182,12 +184,9 @@ class ExpandableTextView @JvmOverloads constructor( } private fun setEllipsizedText(isExpanded: Boolean) { - if(initialText.isBlank()) - return + if(initialText.isBlank()) return - text = if(collapsedVisibleText.isAllTextVisible()) { - initialText - } else { + text = if(collapsedVisibleText.isAllTextVisible()) initialText else { if(isExpanded) getExpandText() else getCollapseText() } } @@ -199,7 +198,6 @@ class ExpandableTextView @JvmOverloads constructor( } private fun getCollapseText(): SpannableStringBuilder { - val ellipseTextLength = ((mReadMoreText.length + DEFAULT_ELLIPSIZED_TEXT.length) * ELLIPSIZE_TEXT_LENGTH_MULTIPLIER).roundToInt() val textAvailableLength = max(0, collapsedVisibleText.length - ellipseTextLength) val ellipsizeAvailableLength = min(collapsedVisibleText.length, DEFAULT_ELLIPSIZED_TEXT.length) @@ -225,7 +223,7 @@ class ExpandableTextView @JvmOverloads constructor( } else { return initialText } - } catch (e: Exception) { + } catch(e: Exception) { e.printStackTrace() return initialText } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/MobileSetting.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/MobileSetting.kt index 10da9be3..e00d23c4 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/MobileSetting.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/components/MobileSetting.kt @@ -32,7 +32,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.state.ToggleableState import androidx.compose.ui.text.input.ImeAction @@ -40,12 +39,14 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import com.mrboomdev.awery.R import com.mrboomdev.awery.ext.data.Setting -import com.mrboomdev.awery.platform.PlatformResources.i18n +import com.mrboomdev.awery.generated.* import com.mrboomdev.awery.platform.PlatformSetting import com.mrboomdev.awery.platform.PlatformSettingHandler +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.components.MaterialDialog import com.mrboomdev.awery.utils.compareTo import com.mrboomdev.awery.utils.toStrippedString +import org.jetbrains.compose.resources.stringResource @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -206,7 +207,7 @@ fun MobileSetting( dismissButton = { TextButton(onClick = this@MaterialDialog::requestDismiss) { - Text(text = stringResource(R.string.cancel)) + Text(text = stringResource(Res.string.cancel)) } }, @@ -216,7 +217,7 @@ fun MobileSetting( setting.value = newValue requestDismiss() }) { - Text(text = stringResource(R.string.confirm)) + Text(text = stringResource(Res.string.confirm)) } } ) { diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/FiltersDialog.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/FiltersDialog.kt index be8da9da..9ee3c28c 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/FiltersDialog.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/FiltersDialog.kt @@ -20,6 +20,8 @@ import com.mrboomdev.awery.data.settings.SettingsItem import com.mrboomdev.awery.data.settings.SettingsItemType import com.mrboomdev.awery.data.settings.SettingsList import com.mrboomdev.awery.extensions.ExtensionProvider +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsAdapter import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsDataHandler import com.mrboomdev.awery.util.async.AsyncFuture @@ -84,7 +86,7 @@ class FiltersDialog( linear.addView(this, MATCH_PARENT, WRAP_CONTENT) addView(MaterialButton(context).apply { - setText(R.string.cancel) + text = i18n(Res.string.cancel) setOnClickListener { dismiss() } }, 0, WRAP_CONTENT) { cancel -> cancel.useLayoutParams { it.weight = 1f } @@ -92,7 +94,8 @@ class FiltersDialog( } addView(MaterialButton(context).apply { - setText(R.string.save) + text = i18n(Res.string.save) + setOnClickListener { applyCallback.invoke(this@FiltersDialog.filters) dismiss() diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/MediaActionsDialog.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/MediaActionsDialog.kt index bc85c77c..bc6424a6 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/MediaActionsDialog.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/MediaActionsDialog.kt @@ -9,13 +9,13 @@ import com.mrboomdev.awery.databinding.PopupMediaActionsBinding import com.mrboomdev.awery.ext.data.CatalogMedia import com.mrboomdev.awery.ui.mobile.screens.media.MediaActivity import com.mrboomdev.awery.util.MediaUtils -import com.mrboomdev.awery.util.extensions.inflater -import com.mrboomdev.awery.util.extensions.startActivity +import com.mrboomdev.awery.utils.buildIntent +import com.mrboomdev.awery.utils.inflater class MediaActionsDialog(val media: CatalogMedia) : BasePanelDialog() { var updateCallback: (() -> Unit)? = null - override fun getView(context: Context): View { + override fun getView(context: Context) = with(context) { val binding = PopupMediaActionsBinding.inflate(context.inflater) if(media.url == null) binding.share.visibility = View.GONE binding.title.text = media.title @@ -26,10 +26,8 @@ class MediaActionsDialog(val media: CatalogMedia) : BasePanelDialog() { binding.close.setOnClickListener { dismiss() } binding.play.setOnClickListener { - context.startActivity( - MediaActivity::class, MediaActivity.Extras( - media = media, action = MediaActivity.Action.WATCH - )) + context.startActivity(buildIntent(MediaActivity::class, + MediaActivity.Extras(media, MediaActivity.Action.WATCH))) dismiss() } @@ -47,6 +45,6 @@ class MediaActionsDialog(val media: CatalogMedia) : BasePanelDialog() { .into(binding.poster) } - return binding.root + return@with binding.root } } \ No newline at end of file diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/MediaBookmarkDialog.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/MediaBookmarkDialog.kt index 19ae516d..853e6452 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/MediaBookmarkDialog.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/dialogs/MediaBookmarkDialog.kt @@ -10,7 +10,6 @@ import androidx.appcompat.widget.LinearLayoutCompat import com.google.android.material.checkbox.MaterialCheckBox import com.mrboomdev.awery.R import com.mrboomdev.awery.app.App.Companion.database -import com.mrboomdev.awery.app.App.Companion.i18n import com.mrboomdev.awery.app.App.Companion.showLoadingWindow import com.mrboomdev.awery.app.App.Companion.toast import com.mrboomdev.awery.data.Constants.HIDDEN_LISTS @@ -20,12 +19,15 @@ import com.mrboomdev.awery.databinding.PopupMediaBookmarkBinding import com.mrboomdev.awery.extensions.data.CatalogList import com.mrboomdev.awery.ext.data.CatalogMedia import com.mrboomdev.awery.extensions.data.CatalogMediaProgress +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.extensions.dpPx -import com.mrboomdev.awery.util.extensions.inflater import com.mrboomdev.awery.util.extensions.setImageTintAttr import com.mrboomdev.awery.util.extensions.setPadding import com.mrboomdev.awery.util.ui.dialog.DialogBuilder import com.mrboomdev.awery.util.ui.fields.EditTextField +import com.mrboomdev.awery.utils.dpPx +import com.mrboomdev.awery.utils.inflater import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -128,18 +130,18 @@ class MediaBookmarkDialog(val media: CatalogMedia): BasePanelDialog() { private const val TAG = "MediaBookmarkDialog" fun requestCreateNewList(context: Context, callback: (list: CatalogList) -> Unit) { - val input = EditTextField(context, R.string.list_name) + val input = EditTextField(context, i18n(Res.string.list_name)) input.setLinesCount(1) val dialog = DialogBuilder(context) - .setTitle(R.string.create_list) + .setTitle(i18n(Res.string.create_list)) .addView(input.view) - .setNegativeButton(R.string.cancel) { it.dismiss() } - .setPositiveButton(R.string.create) { dialog -> + .setNegativeButton(i18n(Res.string.cancel)) { it.dismiss() } + .setPositiveButton(i18n(Res.string.create)) { dialog -> val text = input.text.trim { it <= ' ' } if(text.isBlank()) { - input.setError(R.string.text_cant_empty) + input.setError(i18n(Res.string.text_cant_empty)) return@setPositiveButton } @@ -163,10 +165,10 @@ class MediaBookmarkDialog(val media: CatalogMedia): BasePanelDialog() { fun requestDeleteList(context: Context, list: CatalogList, callback: () -> Unit) { DialogBuilder(context) - .setTitle(i18n(R.string.delete_confirmation, list.title)) - .setMessage(R.string.sure_delete_list_description) - .setNegativeButton(R.string.cancel) { it.dismiss() } - .setPositiveButton(R.string.delete) { dialog -> + .setTitle(i18n(Res.string.delete_confirmation, list.title)) + .setMessage(i18n(Res.string.sure_delete_list_description)) + .setNegativeButton(i18n(Res.string.cancel)) { it.dismiss() } + .setPositiveButton(i18n(Res.string.delete)) { dialog -> val window = showLoadingWindow() CoroutineScope(Dispatchers.IO).launch { diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/BrowserActivity.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/BrowserActivity.kt index 9d81ce9f..85601fc3 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/BrowserActivity.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/BrowserActivity.kt @@ -25,16 +25,18 @@ import com.mrboomdev.awery.app.App import com.mrboomdev.awery.app.theme.ThemeManager.applyTheme import com.mrboomdev.awery.data.Constants import com.mrboomdev.awery.databinding.ScreenBrowserBinding +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.extensions.UI_INSETS -import com.mrboomdev.awery.util.extensions.addOnBackPressedListener import com.mrboomdev.awery.util.extensions.applyInsets import com.mrboomdev.awery.util.extensions.cleanUrl import com.mrboomdev.awery.util.extensions.enableEdgeToEdge import com.mrboomdev.awery.util.extensions.isValidUrl import com.mrboomdev.awery.util.extensions.resolveAttrColor import com.mrboomdev.awery.util.extensions.setMargin -import com.mrboomdev.awery.util.extensions.startActivityForResult import com.mrboomdev.awery.util.ui.dialog.DialogBuilder +import com.mrboomdev.awery.utils.addOnBackPressedListener +import com.mrboomdev.awery.utils.startActivityForResult import com.mrboomdev.safeargsnext.owner.SafeArgsActivity import eu.kanade.tachiyomi.util.system.WebViewClientCompat import java.net.URISyntaxException @@ -87,8 +89,8 @@ class BrowserActivity : AppCompatActivity(), SafeArgsActivity PopupMenu(this, v).apply { - menu.add(0, 0, 0, R.string.copy_link_to_clipboard) - menu.add(0, 1, 0, R.string.open_link_externally) + menu.add(0, 0, 0, i18n(Res.string.copy_link_to_clipboard)) + menu.add(0, 1, 0, i18n(Res.string.open_link_externally)) setOnMenuItemClickListener { item -> when(item.itemId) { 0 -> { @@ -226,7 +228,7 @@ class BrowserActivity : AppCompatActivity(), SafeArgsActivity + setPositiveButton(i18n(Res.string.ok)) { dialog -> result.confirm() didPressButton = true dialog.dismiss() diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/GalleryActivity.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/GalleryActivity.kt index 7ad05b1c..94a12eb6 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/GalleryActivity.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/GalleryActivity.kt @@ -18,9 +18,8 @@ import com.github.piasy.biv.view.GlideImageViewFactory import com.github.piasy.biv.view.ImageSaveCallback import com.google.android.material.progressindicator.CircularProgressIndicator import com.mrboomdev.awery.app.App -import com.mrboomdev.awery.util.exceptions.ZeroResultsException +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException import com.mrboomdev.awery.util.extensions.enableEdgeToEdge -import com.mrboomdev.awery.util.extensions.screenHeight import com.mrboomdev.safeargsnext.owner.SafeArgsActivity import com.mrboomdev.safeargsnext.util.rememberSafeArgs import java.io.File @@ -57,7 +56,7 @@ class GalleryActivity : AppCompatActivity(), SafeArgsActivity { (DialogBuilder(this).apply { - setTitle(R.string.restore_backup) + setTitle(i18n(Res.string.restore_backup)) setMessage("Are you sure want to restore an backup from Dantotsu? All your current data will be erased!") setCancelable(false) - setNegativeButton(R.string.cancel) { finish() } - - setPositiveButton(R.string.confirm) { - startService(BackupService::class, BackupService.Args( - BackupService.Action.RESTORE, uri, FileType.DANTOTSU_BACKUP)) + setNegativeButton(i18n(Res.string.cancel)) { finish() } + setPositiveButton(i18n(Res.string.confirm)) { + startService(buildIntent(BackupService::class, BackupService.Args( + BackupService.Action.RESTORE, uri, FileType.DANTOTSU_BACKUP))) dialog.dismiss() } @@ -82,14 +83,13 @@ class IntentHandlerActivity : AppCompatActivity() { FileType.YOMI_BACKUP -> { (DialogBuilder(this).apply { - setTitle(R.string.restore_backup) + setTitle(i18n(Res.string.restore_backup)) setMessage("Are you sure want to restore an backup from Tachiyomi? All your current data will be erased!") setCancelable(false) - setNegativeButton(R.string.cancel) { finish() } - - setPositiveButton(R.string.confirm) { - startService(BackupService::class, BackupService.Args( - BackupService.Action.RESTORE, uri, FileType.YOMI_BACKUP)) + setNegativeButton(i18n(Res.string.cancel)) { finish() } + setPositiveButton(i18n(Res.string.confirm)) { + startService(buildIntent(BackupService::class, BackupService.Args( + BackupService.Action.RESTORE, uri, FileType.YOMI_BACKUP))) dialog.dismiss() } @@ -105,14 +105,13 @@ class IntentHandlerActivity : AppCompatActivity() { FileType.AWERY_BACKUP -> { (DialogBuilder(this).apply { - setTitle(R.string.restore_backup) + setTitle(i18n(Res.string.restore_backup)) setMessage("Are you sure want to restore an saved backup? All your current data will be erased!") setCancelable(false) - setNegativeButton(R.string.cancel) { finish() } - - setPositiveButton(R.string.confirm) { - startService(BackupService::class, BackupService.Args( - BackupService.Action.RESTORE, uri)) + setNegativeButton(i18n(Res.string.cancel)) { finish() } + setPositiveButton(i18n(Res.string.confirm)) { + startService(buildIntent(BackupService::class, BackupService.Args( + BackupService.Action.RESTORE, uri))) dialog.dismiss() } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/SplashActivity.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/SplashActivity.kt index 566a343e..d8a1f8bd 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/SplashActivity.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/SplashActivity.kt @@ -16,14 +16,16 @@ import com.mrboomdev.awery.app.ExtensionsManager import com.mrboomdev.awery.app.theme.ThemeManager.applyTheme import com.mrboomdev.awery.databinding.ScreenSplashBinding import com.mrboomdev.awery.extensions.ExtensionsFactory -import com.mrboomdev.awery.generated.AwerySettings -import com.mrboomdev.awery.ui.mobile.screens.catalog.MainActivity +import com.mrboomdev.awery.MainActivity +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.screens.setup.SetupActivity import com.mrboomdev.awery.ui.tv.TvMainActivity import com.mrboomdev.awery.util.async.AsyncFuture import com.mrboomdev.awery.util.extensions.enableEdgeToEdge import com.mrboomdev.awery.util.extensions.resolveAttrColor import com.mrboomdev.awery.util.extensions.startActivity +import com.mrboomdev.awery.utils.buildIntent import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach @@ -47,14 +49,14 @@ class SplashActivity : AppCompatActivity() { binding = ScreenSplashBinding.inflate(layoutInflater).apply { root.setBackgroundColor(resolveAttrColor(android.R.attr.colorBackground)) - status.setText(R.string.checking_if_crash_occurred) + status.text = i18n(Res.string.checking_if_crash_occurred) } window.navigationBarColor = resolveAttrColor(android.R.attr.colorBackground) setContentView(binding.root) CrashHandler.showDialogIfCrashHappened(this) { - binding.status.setText(R.string.checking_database) + binding.status.text = i18n(Res.string.checking_database) lifecycleScope.launch(Dispatchers.IO) { try { @@ -64,7 +66,7 @@ class SplashActivity : AppCompatActivity() { CrashHandler.showDialog( context = this@SplashActivity, - titleRes = R.string.database_corrupted, + title = i18n(Res.string.database_corrupted), throwable = e, dismissCallback = ::exitApp) @@ -75,7 +77,7 @@ class SplashActivity : AppCompatActivity() { while(!App.didInit) {} if(AwerySettings.SETUP_VERSION_FINISHED.value < SetupActivity.SETUP_VERSION) { - startActivity(SetupActivity::class) + startActivity(buildIntent(SetupActivity::class)) finish() return@launch } @@ -84,7 +86,7 @@ class SplashActivity : AppCompatActivity() { try { ExtensionsManager.init(applicationContext).data.onEach { launch(Dispatchers.Main) { - binding.status.text = getString(R.string.loading_extensions_n, it.value, it.max) + binding.status.text = i18n(Res.string.loading_extensions_n, it.value, it.max) } }.collect() } catch(t: Throwable) { @@ -99,7 +101,7 @@ class SplashActivity : AppCompatActivity() { return@launch } - startActivity(if(/*isTv*/AwerySettings.EXPERIMENT_TV_COMPOSE.value) TvMainActivity::class else MainActivity::class) + startActivity(buildIntent(if(/*isTv*/AwerySettings.EXPERIMENT_TV_COMPOSE.value) TvMainActivity::class else MainActivity::class)) finish() return@launch @@ -107,7 +109,7 @@ class SplashActivity : AppCompatActivity() { ExtensionsFactory.getInstance().addCallback(object : AsyncFuture.Callback { override fun onSuccess(result: ExtensionsFactory) { - startActivity(if(/*isTv*/AwerySettings.EXPERIMENT_TV_COMPOSE.value) TvMainActivity::class else MainActivity::class) + startActivity(buildIntent(if(/*isTv*/AwerySettings.EXPERIMENT_TV_COMPOSE.value) TvMainActivity::class else MainActivity::class)) finish() } @@ -132,7 +134,7 @@ class SplashActivity : AppCompatActivity() { val factory = ExtensionsFactory.getInstanceNow() if(factory == null) { - binding.status.setText(R.string.loading_extensions) + binding.status.text = i18n(Res.string.loading_extensions) return } @@ -145,7 +147,7 @@ class SplashActivity : AppCompatActivity() { total += managerProgress.max } - binding.status.text = getString(R.string.loading_extensions_n, progress, total) + binding.status.text = i18n(Res.string.loading_extensions_n, progress, total) runDelayed({ this.update() }, 100) } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MediaCatalogAdapter.java b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MediaCatalogAdapter.java index 52eccfc6..3abd71cf 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MediaCatalogAdapter.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MediaCatalogAdapter.java @@ -20,7 +20,7 @@ import com.mrboomdev.awery.ext.data.CatalogMedia; import com.mrboomdev.awery.ui.mobile.dialogs.MediaActionsDialog; import com.mrboomdev.awery.util.MediaUtils; -import com.mrboomdev.awery.util.UniqueIdGenerator; +import com.mrboomdev.awery.utils.UniqueIdGenerator; import java.util.List; import java.util.WeakHashMap; diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MediaCategoriesAdapter.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MediaCategoriesAdapter.kt index a4e4c218..87baa7ea 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MediaCategoriesAdapter.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/MediaCategoriesAdapter.kt @@ -9,7 +9,7 @@ import com.mrboomdev.awery.ui.mobile.screens.catalog.feeds.FeedViewHolder import com.mrboomdev.awery.ui.mobile.screens.catalog.feeds.FeedViewHolder.Feed import com.mrboomdev.awery.ui.mobile.screens.catalog.feeds.ListFeedViewHolder import com.mrboomdev.awery.ui.mobile.screens.catalog.feeds.PagesFeedViewHolder -import com.mrboomdev.awery.util.UniqueIdGenerator +import com.mrboomdev.awery.utils.UniqueIdGenerator import java.util.WeakHashMap class MediaCategoriesAdapter : RecyclerView.Adapter() { diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/FailedFeedViewHolder.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/FailedFeedViewHolder.kt index a204bfa4..174bdc54 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/FailedFeedViewHolder.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/FailedFeedViewHolder.kt @@ -8,17 +8,18 @@ import com.mrboomdev.awery.app.App.Companion.navigationStyle import com.mrboomdev.awery.app.App.Companion.openUrl import com.mrboomdev.awery.databinding.FeedFailedBinding import com.mrboomdev.awery.extensions.ExtensionProvider -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.exceptions.ExtensionNotInstalledException import com.mrboomdev.awery.util.exceptions.explain import com.mrboomdev.awery.util.extensions.UI_INSETS import com.mrboomdev.awery.util.extensions.applyInsets import com.mrboomdev.awery.util.extensions.context import com.mrboomdev.awery.util.extensions.dpPx -import com.mrboomdev.awery.util.extensions.inflater import com.mrboomdev.awery.util.extensions.leftMargin import com.mrboomdev.awery.util.extensions.rightMargin import com.mrboomdev.awery.util.extensions.setHorizontalMargin +import com.mrboomdev.awery.utils.inflater class FailedFeedViewHolder private constructor( private val binding: FeedFailedBinding, parent: ViewGroup @@ -75,7 +76,7 @@ class FailedFeedViewHolder private constructor( if(feed.throwable != null) { binding.errorMessage.text = feed.throwable!!.explain().print() } else { - binding.errorMessage.text = binding.context.getString(R.string.nothing_found) + binding.errorMessage.text = i18n(Res.string.nothing_found) } if(feed.isLoading) { diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/ListFeedViewHolder.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/ListFeedViewHolder.kt index e6e1e65e..0b37b226 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/ListFeedViewHolder.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/ListFeedViewHolder.kt @@ -14,7 +14,6 @@ import com.mrboomdev.awery.util.WeakLazy import com.mrboomdev.awery.util.extensions.UI_INSETS import com.mrboomdev.awery.util.extensions.applyInsets import com.mrboomdev.awery.util.extensions.dpPx -import com.mrboomdev.awery.util.extensions.inflater import com.mrboomdev.awery.util.extensions.leftMargin import com.mrboomdev.awery.util.extensions.leftPadding import com.mrboomdev.awery.util.extensions.rightMargin @@ -22,6 +21,8 @@ import com.mrboomdev.awery.util.extensions.rightPadding import com.mrboomdev.awery.util.extensions.setHorizontalMargin import com.mrboomdev.awery.util.extensions.setHorizontalPadding import com.mrboomdev.awery.util.extensions.startActivity +import com.mrboomdev.awery.utils.buildIntent +import com.mrboomdev.awery.utils.inflater import org.jetbrains.annotations.Contract class ListFeedViewHolder private constructor( @@ -74,12 +75,12 @@ class ListFeedViewHolder private constructor( binding.header.isClickable = true binding.expand.setOnClickListener { v -> - v.context.startActivity( + v.context.startActivity(v.context.buildIntent( SearchActivity::class, args = SearchActivity.Extras( sourceGlobalId = feed.sourceFeed.providerGlobalId, filters = feed.sourceFeed.filters, preloadedItems = feed.items - )) + ))) } } else { binding.header.isClickable = false diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/PagesFeedViewHolder.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/PagesFeedViewHolder.kt index 6a750cab..c064aa77 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/PagesFeedViewHolder.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/catalog/feeds/PagesFeedViewHolder.kt @@ -17,21 +17,22 @@ import com.mrboomdev.awery.app.theme.ThemeManager import com.mrboomdev.awery.databinding.FeedFeaturedItemBinding import com.mrboomdev.awery.databinding.FeedFeaturedWrapperBinding import com.mrboomdev.awery.ext.data.CatalogMedia -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.dialogs.MediaActionsDialog import com.mrboomdev.awery.ui.mobile.dialogs.MediaBookmarkDialog import com.mrboomdev.awery.ui.mobile.screens.media.MediaActivity import com.mrboomdev.awery.util.MediaUtils -import com.mrboomdev.awery.util.UniqueIdGenerator +import com.mrboomdev.awery.utils.UniqueIdGenerator import com.mrboomdev.awery.util.extensions.UI_INSETS import com.mrboomdev.awery.util.extensions.applyInsets import com.mrboomdev.awery.util.extensions.dpPx -import com.mrboomdev.awery.util.extensions.inflater import com.mrboomdev.awery.util.extensions.leftMargin import com.mrboomdev.awery.util.extensions.limit import com.mrboomdev.awery.util.extensions.rightMargin -import com.mrboomdev.awery.util.extensions.startActivity import com.mrboomdev.awery.util.extensions.topMargin +import com.mrboomdev.awery.utils.buildIntent +import com.mrboomdev.awery.utils.inflater import org.jetbrains.annotations.Contract import java.util.WeakHashMap import kotlin.math.min @@ -83,13 +84,13 @@ class PagesFeedViewHolder private constructor( val holder = PagerViewHolder(binding) binding.root.setOnClickListener { - parent.context.startActivity(MediaActivity::class, MediaActivity.Extras( - media = holder.item!!, action = MediaActivity.Action.INFO)) + parent.context.startActivity(parent.context.buildIntent(MediaActivity::class, MediaActivity.Extras( + media = holder.item!!, action = MediaActivity.Action.INFO))) } binding.watch.setOnClickListener { - parent.context.startActivity(MediaActivity::class, MediaActivity.Extras( - media = holder.item!!, action = MediaActivity.Action.WATCH)) + parent.context.startActivity(parent.context.buildIntent(MediaActivity::class, MediaActivity.Extras( + media = holder.item!!, action = MediaActivity.Action.WATCH))) } binding.bookmark.setOnClickListener { @@ -179,12 +180,12 @@ class PagesFeedViewHolder private constructor( when(item.type ?: CatalogMedia.Type.TV) { CatalogMedia.Type.TV, CatalogMedia.Type.MOVIE -> { - binding.watch.setText(R.string.watch_now) + binding.watch.text = i18n(Res.string.watch_now) binding.watch.setIconResource(R.drawable.ic_play_filled) } CatalogMedia.Type.BOOK, CatalogMedia.Type.POST -> { - binding.watch.setText(R.string.read_now) + binding.watch.text = i18n(Res.string.read_now) binding.watch.setIconResource(R.drawable.ic_book_filled) } } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaActivity.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaActivity.kt index e8e92569..cb227fd5 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaActivity.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaActivity.kt @@ -21,7 +21,8 @@ import com.mrboomdev.awery.app.theme.ThemeManager.applyTheme import com.mrboomdev.awery.databinding.ScreenMediaDetailsBinding import com.mrboomdev.awery.ext.data.CatalogMedia import com.mrboomdev.awery.extensions.data.CatalogVideo -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.MediaUtils import com.mrboomdev.awery.util.extensions.UI_INSETS import com.mrboomdev.awery.util.extensions.applyInsets @@ -115,7 +116,7 @@ class MediaActivity : AppCompatActivity(), SafeArgsActivity when(item.itemId) { diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaCommentsFragment.java b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaCommentsFragment.java index 1c20c6bf..ea33706b 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaCommentsFragment.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaCommentsFragment.java @@ -56,7 +56,7 @@ import com.mrboomdev.awery.extensions.request.PostMediaCommentRequest; import com.mrboomdev.awery.extensions.request.ReadMediaCommentsRequest; import com.mrboomdev.awery.util.NiceUtils; -import com.mrboomdev.awery.util.UniqueIdGenerator; +import com.mrboomdev.awery.utils.UniqueIdGenerator; import com.mrboomdev.awery.util.async.AsyncFuture; import com.mrboomdev.awery.util.exceptions.ExceptionDescriptor; import com.mrboomdev.awery.util.ui.adapter.DropdownAdapter; diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaInfoFragment.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaInfoFragment.kt index a96a6a34..acb748d3 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaInfoFragment.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaInfoFragment.kt @@ -22,6 +22,8 @@ import com.mrboomdev.awery.databinding.MediaDetailsOverviewLayoutBinding import com.mrboomdev.awery.ext.data.CatalogMedia import com.mrboomdev.awery.ext.data.CatalogTag import com.mrboomdev.awery.extensions.ExtensionProvider +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.screens.GalleryActivity import com.mrboomdev.awery.ui.mobile.screens.media.MediaActivity.Companion.handleOptionsClick import com.mrboomdev.awery.ui.mobile.screens.search.SearchActivity @@ -57,9 +59,9 @@ class MediaInfoFragment: Fragment(), SafeArgsFragment { val title = media.title ?: "No title" val meta = generateGeneralMetaString(media) - binding.details.play.setText(when(type) { - CatalogMedia.Type.TV, CatalogMedia.Type.MOVIE -> R.string.watch - CatalogMedia.Type.BOOK, CatalogMedia.Type.POST -> R.string.read + binding.details.play.text = i18n(when(type) { + CatalogMedia.Type.TV, CatalogMedia.Type.MOVIE -> Res.string.watch + CatalogMedia.Type.BOOK, CatalogMedia.Type.POST -> Res.string.read }) binding.details.play.icon = ContextCompat.getDrawable(requireContext(), when(type) { @@ -146,7 +148,7 @@ class MediaInfoFragment: Fragment(), SafeArgsFragment { spoilerChip.chipBackgroundColor = requireContext().resolveAttrColor( com.google.android.material.R.attr.colorSecondaryContainer).toColorState() - spoilerChip.setText(R.string.show_spoilers) + spoilerChip.text = i18n(Res.string.show_spoilers) binding.details.tags.addView(spoilerChip) spoilerChip.setOnClickListener { @@ -186,21 +188,21 @@ class MediaInfoFragment: Fragment(), SafeArgsFragment { val metas = mutableListOf() if(media.episodesCount != null) { - metas.add(media.episodesCount + " " + getString( - if(media.episodesCount == 1) R.string.episode - else R.string.episodes) + metas.add(media.episodesCount + " " + i18n( + if(media.episodesCount == 1) Res.string.episode + else Res.string.episodes) ) } if(media.duration != null) { metas.add(media.duration!!.let { return@let if(it < 60) { - "$it${getString(R.string.minute_short)}" + "$it${i18n(Res.string.minute_short)}" } else { - "${it / 60}${getString(R.string.hour_short)} " + - "${it % 60}${getString(R.string.minute_short)}" + "${it / 60}${i18n(Res.string.hour_short)} " + + "${it % 60}${i18n(Res.string.minute_short)}" } - } + " " + getString(R.string.duration)) + } + " " + i18n(Res.string.duration)) } if(media.releaseDate != null) { @@ -208,16 +210,16 @@ class MediaInfoFragment: Fragment(), SafeArgsFragment { } if(media.country != null) { - metas.add(AweryLocales.translateCountryName(requireContext(), media.country!!)) + metas.add(AweryLocales.i18nCountryName(media.country!!)) } if(metas.size < 4 && media.status != null) { - metas.add(getString(when(media.status!!) { - CatalogMedia.Status.ONGOING -> R.string.status_releasing - CatalogMedia.Status.COMPLETED -> R.string.status_finished - CatalogMedia.Status.COMING_SOON -> R.string.status_not_yet_released - CatalogMedia.Status.PAUSED -> R.string.status_hiatus - CatalogMedia.Status.CANCELLED -> R.string.status_cancelled + metas.add(i18n(when(media.status!!) { + CatalogMedia.Status.ONGOING -> Res.string.status_releasing + CatalogMedia.Status.COMPLETED -> Res.string.status_finished + CatalogMedia.Status.COMING_SOON -> Res.string.status_not_yet_released + CatalogMedia.Status.PAUSED -> Res.string.status_hiatus + CatalogMedia.Status.CANCELLED -> Res.string.status_cancelled })) } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaPlayEpisodesAdapter.java b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaPlayEpisodesAdapter.java index b597da63..f25a827d 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaPlayEpisodesAdapter.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaPlayEpisodesAdapter.java @@ -27,7 +27,7 @@ import com.mrboomdev.awery.ext.data.CatalogMedia; import com.mrboomdev.awery.extensions.data.CatalogMediaProgress; import com.mrboomdev.awery.extensions.data.CatalogVideo; -import com.mrboomdev.awery.util.UniqueIdGenerator; +import com.mrboomdev.awery.utils.UniqueIdGenerator; import java.util.ArrayList; import java.util.Calendar; diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaPlayFragment.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaPlayFragment.kt index 419f462f..b547a530 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaPlayFragment.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/media/MediaPlayFragment.kt @@ -21,9 +21,7 @@ import com.mrboomdev.awery.app.App.Companion.getMoshi import com.mrboomdev.awery.app.App.Companion.openUrl import com.mrboomdev.awery.app.App.Companion.toast import com.mrboomdev.awery.app.AweryLifecycle.Companion.runOnUiThread -import com.mrboomdev.awery.app.AweryLifecycle.Companion.startActivityForResult import com.mrboomdev.awery.data.Constants -import com.mrboomdev.awery.data.settings.NicePreferences import com.mrboomdev.awery.data.settings.SettingsItem import com.mrboomdev.awery.data.settings.SettingsItemType import com.mrboomdev.awery.data.settings.SettingsList @@ -33,18 +31,19 @@ import com.mrboomdev.awery.extensions.Extension import com.mrboomdev.awery.extensions.ExtensionProvider import com.mrboomdev.awery.extensions.ExtensionsFactory import com.mrboomdev.awery.ext.data.CatalogMedia +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException import com.mrboomdev.awery.extensions.data.CatalogMediaProgress import com.mrboomdev.awery.extensions.data.CatalogSearchResults import com.mrboomdev.awery.extensions.data.CatalogVideo +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.screens.player.PlayerActivity import com.mrboomdev.awery.ui.mobile.screens.search.SearchActivity import com.mrboomdev.awery.ui.mobile.screens.media.MediaPlayEpisodesAdapter.OnEpisodeSelectedListener -import com.mrboomdev.awery.util.NiceUtils import com.mrboomdev.awery.util.adapters.MediaAdapter import com.mrboomdev.awery.util.async.AsyncFuture import com.mrboomdev.awery.util.exceptions.ExtensionNotInstalledException import com.mrboomdev.awery.util.exceptions.OkiThrowableMessage -import com.mrboomdev.awery.util.exceptions.ZeroResultsException import com.mrboomdev.awery.util.exceptions.isNetworkException import com.mrboomdev.awery.util.extensions.UI_INSETS import com.mrboomdev.awery.util.extensions.applyInsets @@ -53,7 +52,6 @@ import com.mrboomdev.awery.util.extensions.dpPx import com.mrboomdev.awery.util.extensions.get import com.mrboomdev.awery.util.extensions.leftPadding import com.mrboomdev.awery.util.extensions.rightPadding -import com.mrboomdev.awery.util.extensions.screenWidth import com.mrboomdev.awery.util.extensions.setImageTintColor import com.mrboomdev.awery.util.extensions.setVerticalPadding import com.mrboomdev.awery.util.extensions.startActivity @@ -64,6 +62,8 @@ import com.mrboomdev.awery.util.ui.adapter.DropdownAdapter import com.mrboomdev.awery.util.ui.adapter.DropdownBindingAdapter import com.mrboomdev.awery.util.ui.adapter.SingleViewAdapter import com.mrboomdev.awery.util.ui.adapter.SingleViewAdapter.BindingSingleViewAdapter +import com.mrboomdev.awery.utils.buildIntent +import com.mrboomdev.awery.utils.startActivityForResult import com.mrboomdev.safeargsnext.SafeArgsIntent import com.mrboomdev.safeargsnext.owner.SafeArgsFragment import com.mrboomdev.safeargsnext.util.rememberSafeArgs @@ -83,7 +83,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O private var episodesAdapter: MediaPlayEpisodesAdapter? = null private var recycler: RecyclerView? = null private var selectedSource: ExtensionProvider? = null - private var viewMode: ViewMode? = null + private var viewMode: AwerySettings.EpisodesDisplayModeValue? = null private var searchId: String? = null private var searchTitle: String? = null private var autoChangeSource = true @@ -93,13 +93,8 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O private var loadId = 0L private var media: CatalogMedia? = null - private val queryFilter = - SettingsItem(SettingsItemType.STRING, ExtensionProvider.FILTER_QUERY) - private val filters = SettingsList( - queryFilter, SettingsItem( - SettingsItemType.INTEGER, ExtensionProvider.FILTER_PAGE, 0 - ) - ) + private val queryFilter = SettingsItem(SettingsItemType.STRING, ExtensionProvider.FILTER_QUERY) + private val filters = SettingsList(queryFilter, SettingsItem(SettingsItemType.INTEGER, ExtensionProvider.FILTER_PAGE, 0)) class Args(val media: CatalogMedia) @@ -137,15 +132,14 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O if(Constants.alwaysTrue()) return if(changeSettings) { - val prefs = NicePreferences.getPrefs() - val viewMode = NiceUtils.parseEnum(prefs.getString("settings_ui_episodes_mode"), ViewMode.LIST)!! + val viewMode = AwerySettings.EPISODES_DISPLAY_MODE.value if(viewMode != this.viewMode) { this.viewMode = viewMode recycler!!.layoutManager = when(viewMode) { - ViewMode.LIST -> LinearLayoutManager(requireContext()) - ViewMode.GRID -> { + AwerySettings.EpisodesDisplayModeValue.LIST -> LinearLayoutManager(requireContext()) + AwerySettings.EpisodesDisplayModeValue.GRID -> { val columnsCount = AtomicInteger(3) val layoutManager = GridLayoutManager(requireContext(), columnsCount.get()) @@ -155,7 +149,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O view.rightPadding = insets.right + dpPx(8f) val columnSize = dpPx(80f) - val freeSpace = (requireContext().screenWidth - dpPx(16f) - insets.left - insets.right).toFloat() + val freeSpace = (requireContext().resources.displayMetrics.widthPixels - dpPx(16f) - insets.left - insets.right).toFloat() columnsCount.set((freeSpace / columnSize).toInt()) layoutManager.spanCount = columnsCount.get() true @@ -177,7 +171,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O changeSettings = false } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?): Unit = with(view.context) { if(media == null) { media = rememberSafeArgs!!.media } @@ -237,7 +231,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O } } - val more = getString(R.string.manual_search) + val more = i18n(Res.string.manual_search) val titles = media!!.titles!!.toMutableList() titles.add(more) @@ -284,12 +278,11 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O if(title == more) { binding.searchDropdown.setText(queryFilter.stringValue, false) - startActivityForResult(requireActivity(), SafeArgsIntent( - requireContext(), SearchActivity::class, SearchActivity.Extras( - action = SearchActivity.Action.PICK_MEDIA, - sourceGlobalId = selectedSource!!.globalId, - filters = filters - )), { _, result -> + requireActivity().startActivityForResult(buildIntent(SearchActivity::class, SearchActivity.Extras( + action = SearchActivity.Action.PICK_MEDIA, + sourceGlobalId = selectedSource!!.globalId, + filters = filters + )), { _, result -> if(result == null) return@startActivityForResult val media = result.get(SearchActivity.RESULT_EXTRA_MEDIA) ?: return@startActivityForResult @@ -299,7 +292,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O binding.searchDropdown.setText(media.title, false) queryFilter.setValue(media.title) - placeholderAdapter!!.getBinding { placeholder: EmptyStateView -> + placeholderAdapter!!.getBinding { placeholder -> placeholder.startLoading() placeholderAdapter!!.isEnabled = true episodesAdapter!!.setItems(media, emptyList()) @@ -327,7 +320,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O queryFilter.setValue(media!!.title) if(providers?.isEmpty() == true) { - handleExceptionUi(ZeroResultsException("No extensions was found", R.string.no_extensions_found)) + handleExceptionUi(ZeroResultsException("No extensions was found", i18n(Res.string.no_extensions_found))) variantsAdapter!!.isEnabled = false return } @@ -409,7 +402,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O variantsAdapter!!.getBinding { binding -> runOnUiThread { - binding.searchStatus.text = getString(R.string.searching_episodes_for, media.title) + binding.searchStatus.text = i18n(Res.string.searching_episodes_for, media.title) binding.searchStatus.setOnClickListener { startActivity(MediaActivity::class, MediaActivity.Extras(media)) } } @@ -449,7 +442,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O runOnUiThread { variantsAdapter!!.getBinding { binding -> - binding.searchStatus.text = getString(R.string.selected_s, media.title) + binding.searchStatus.text = i18n(Res.string.selected_s, media.title) } placeholderAdapter!!.isEnabled = false @@ -515,7 +508,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O variantsAdapter!!.getBinding { binding -> runOnUiThread { - binding.searchStatus.text = getString(R.string.searching_for, queryFilter.stringValue) + binding.searchStatus.text = i18n(Res.string.searching_for, queryFilter.stringValue) binding.searchStatus.setOnClickListener(null) } } @@ -539,7 +532,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O if(searchId != null) { variantsAdapter!!.getBinding { binding -> runOnUiThread { - binding.searchStatus.text = getString(R.string.searching_for, searchTitle) + binding.searchStatus.text = i18n(Res.string.searching_for, searchTitle) binding.searchStatus.setOnClickListener(null) } } @@ -556,7 +549,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O variantsAdapter!!.getBinding { binding -> runOnUiThread { - binding.searchStatus.text = getString(R.string.searching_for, queryFilter.stringValue) + binding.searchStatus.text = i18n(Res.string.searching_for, queryFilter.stringValue) binding.searchStatus.setOnClickListener(null) } } @@ -567,7 +560,7 @@ class MediaPlayFragment: Fragment(), SafeArgsFragment, O } else { variantsAdapter!!.getBinding { binding -> runOnUiThread { - binding.searchStatus.text = getString(R.string.searching_for, queryFilter.stringValue) + binding.searchStatus.text = i18n(Res.string.searching_for, queryFilter.stringValue) binding.searchStatus.setOnClickListener(null) } } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/player/PlayerActivity.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/player/PlayerActivity.kt index a04fcebc..9246dcb9 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/player/PlayerActivity.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/player/PlayerActivity.kt @@ -41,7 +41,6 @@ import androidx.media3.ui.TimeBar.OnScrubListener import com.bumptech.glide.Glide import com.mrboomdev.awery.R import com.mrboomdev.awery.app.App.Companion.copyToClipboard -import com.mrboomdev.awery.app.App.Companion.i18n import com.mrboomdev.awery.app.App.Companion.toast import com.mrboomdev.awery.app.AweryLifecycle.Companion.cancelDelayed import com.mrboomdev.awery.app.AweryLifecycle.Companion.runDelayed @@ -54,7 +53,8 @@ import com.mrboomdev.awery.extensions.ExtensionProvider import com.mrboomdev.awery.extensions.data.CatalogSubtitle import com.mrboomdev.awery.extensions.data.CatalogVideo import com.mrboomdev.awery.extensions.data.CatalogVideoFile -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.NiceUtils import com.mrboomdev.awery.util.async.AsyncFuture import com.mrboomdev.awery.util.exceptions.explain @@ -290,7 +290,7 @@ class PlayerActivity : AppCompatActivity(), SafeArgsActivity 0) { val time = NiceUtils.formatTimer(bigSeek * 1000L) - binding.quickSkip.text = "${i18n(R.string.skip)} $time" + binding.quickSkip.text = "${i18n(Res.string.skip)} $time" setupButton(binding.quickSkip) { player?.seekTo(player!!.currentPosition + bigSeek * 1000L) @@ -370,9 +370,9 @@ class PlayerActivity : AppCompatActivity(), SafeArgsActivity + .setMessage(i18n(Res.string.torrent_unsupported_message)) + .setPositiveButton(i18n(Res.string.ok)) { dialog -> dialog.dismiss() finish() } - .setNeutralButton(R.string.copy) { copyToClipboard(uri) } + .setNeutralButton(i18n(Res.string.copy)) { copyToClipboard(uri) } .show() } @@ -440,7 +440,7 @@ class PlayerActivity : AppCompatActivity(), SafeArgsActivity { isVideoBuffering = true - binding.loadingStatus.setText(R.string.buffering_video) + binding.loadingStatus.text = i18n(Res.string.buffering_video) binding.loadingCircle.visibility = View.VISIBLE binding.loadingStatus.visibility = View.VISIBLE @@ -580,11 +580,11 @@ class PlayerActivity : AppCompatActivity(), SafeArgsActivity getString(R.string.connection_timeout) + PlaybackException.ERROR_CODE_TIMEOUT -> i18n(Res.string.connection_timeout) PlaybackException.ERROR_CODE_DECODING_FAILED -> "Video decoding failed, please try again later" PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND -> "Video not found, please try again later" - PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED -> getString(R.string.connection_error) - else -> getString(R.string.unknown_error) + PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED -> i18n(Res.string.connection_error) + else -> i18n(Res.string.unknown_error) + " (${e.errorCode})" }, 1) finish() diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/player/PlayerController.java b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/player/PlayerController.java index 519ff7f6..96c7cabd 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/player/PlayerController.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/player/PlayerController.java @@ -460,17 +460,6 @@ public class PopupItem { private String title; private int id, icon; - public PopupItem(@StringRes int title, @DrawableRes int icon) { - this.title = activity.getString(title); - this.icon = icon; - } - - public PopupItem(@StringRes int title) { - this.title = activity.getString(title); - } - - public PopupItem() {} - public PopupItem setTitle(String title) { this.title = title; return this; diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/search/SearchActivity.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/search/SearchActivity.kt index 7655c414..033d486b 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/search/SearchActivity.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/search/SearchActivity.kt @@ -1,9 +1,7 @@ package com.mrboomdev.awery.ui.mobile.screens.search import android.annotation.SuppressLint -import android.content.Intent import android.os.Bundle -import android.os.Parcelable import android.util.Log import android.view.View import android.view.ViewGroup @@ -18,7 +16,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions -import com.mrboomdev.awery.R import com.mrboomdev.awery.app.App.Companion.isLandscape import com.mrboomdev.awery.app.App.Companion.toast import com.mrboomdev.awery.app.AweryLifecycle @@ -31,33 +28,33 @@ import com.mrboomdev.awery.databinding.GridMediaCatalogBinding import com.mrboomdev.awery.databinding.ScreenSearchBinding import com.mrboomdev.awery.extensions.ExtensionProvider import com.mrboomdev.awery.ext.data.CatalogMedia +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException import com.mrboomdev.awery.extensions.data.CatalogSearchResults -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.screens.media.MediaActivity import com.mrboomdev.awery.ui.mobile.dialogs.FiltersDialog import com.mrboomdev.awery.ui.mobile.dialogs.MediaActionsDialog import com.mrboomdev.awery.util.MediaUtils import com.mrboomdev.awery.util.Selection -import com.mrboomdev.awery.util.UniqueIdGenerator +import com.mrboomdev.awery.utils.UniqueIdGenerator import com.mrboomdev.awery.util.async.AsyncFuture import com.mrboomdev.awery.util.exceptions.ExceptionDescriptor import com.mrboomdev.awery.util.exceptions.ExtensionNotInstalledException -import com.mrboomdev.awery.util.exceptions.ZeroResultsException import com.mrboomdev.awery.util.extensions.UI_INSETS import com.mrboomdev.awery.util.extensions.applyInsets -import com.mrboomdev.awery.util.extensions.dpPx import com.mrboomdev.awery.util.extensions.enableEdgeToEdge -import com.mrboomdev.awery.util.extensions.inflater import com.mrboomdev.awery.util.extensions.leftMargin import com.mrboomdev.awery.util.extensions.resolveAttrColor import com.mrboomdev.awery.util.extensions.rightMargin -import com.mrboomdev.awery.util.extensions.screenWidth -import com.mrboomdev.awery.util.extensions.startActivity import com.mrboomdev.awery.util.extensions.topMargin import com.mrboomdev.awery.util.extensions.useLayoutParams import com.mrboomdev.awery.ui.mobile.components.EmptyStateView import com.mrboomdev.awery.util.ui.adapter.SingleViewAdapter import com.mrboomdev.awery.util.ui.adapter.SingleViewAdapter.BindingSingleViewAdapter +import com.mrboomdev.awery.utils.buildIntent +import com.mrboomdev.awery.utils.dpPx +import com.mrboomdev.awery.utils.inflater import com.mrboomdev.safeargsnext.owner.SafeArgsActivity import com.mrboomdev.safeargsnext.util.asSafeArgs import com.mrboomdev.safeargsnext.util.putSafeArgs @@ -238,11 +235,11 @@ class SearchActivity : AppCompatActivity(), SafeArgsActivity if(filteredItems.isEmpty()) { - throw ZeroResultsException("No media was found", R.string.no_media_found) + throw ZeroResultsException("No media was found", i18n(Res.string.no_media_found)) } for(item in filteredItems) { ids[item] = idGenerator.long @@ -560,12 +557,15 @@ class SearchActivity : AppCompatActivity(), SafeArgsActivity { + SettingsData.getSelectionList(setting.getBehaviour(), (items, e) -> { if(!dialog.isShown()) return; if(e != null) { @@ -455,7 +455,7 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { .show(); if(setting.getBehaviour() != null) { - SettingsData.getSelectionList(context, setting.getBehaviour(), (items, e) -> { + SettingsData.getSelectionList(setting.getBehaviour(), (items, e) -> { if(!dialog.isShown()) return; if(e != null) { diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/settings/TabsSettings.java b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/settings/TabsSettings.java index fedc42ad..80531d17 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/settings/TabsSettings.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/settings/TabsSettings.java @@ -4,9 +4,9 @@ import static com.mrboomdev.awery.app.App.toast; import static com.mrboomdev.awery.app.AweryLifecycle.getActivity; import static com.mrboomdev.awery.app.AweryLifecycle.runOnUiThread; -import static com.mrboomdev.awery.app.AweryLifecycle.startActivityForResult; import static com.mrboomdev.awery.data.Constants.alwaysTrue; import static com.mrboomdev.awery.data.settings.NicePreferences.getPrefs; +import static com.mrboomdev.awery.platform.PlatformResourcesKt.i18n; import static com.mrboomdev.awery.util.NiceUtils.find; import static com.mrboomdev.awery.util.NiceUtils.requireNonNull; import static com.mrboomdev.awery.util.NiceUtils.stream; @@ -32,6 +32,8 @@ import com.mrboomdev.awery.data.settings.SettingsItemType; import com.mrboomdev.awery.databinding.WidgetIconEdittextBinding; import com.mrboomdev.awery.generated.AwerySettings; +import com.mrboomdev.awery.generated.Res; +import com.mrboomdev.awery.generated.String0_commonMainKt; import com.mrboomdev.awery.ui.mobile.screens.setup.SetupActivity; import com.mrboomdev.awery.util.IconStateful; import com.mrboomdev.awery.util.Parser; @@ -95,15 +97,15 @@ public IconStateful getIcon(Map.Entry item) { icon.set(item.getKey()); }).show()); - binding.get().editText.setHint(R.string.enter_text); + binding.get().editText.setHint(i18n(String0_commonMainKt.getEnter_text(Res.string.INSTANCE))); return binding.get().getRoot(); }) - .setNegativeButton(R.string.cancel, BaseDialogBuilder::dismiss) - .setPositiveButton(R.string.create, dialog -> { + .setNegativeButton(i18n(String0_commonMainKt.getCancel(Res.string.INSTANCE)), BaseDialogBuilder::dismiss) + .setPositiveButton(i18n(String0_commonMainKt.getCreate(Res.string.INSTANCE)), dialog -> { var text = binding.get().editText.getText(); if(text == null || text.toString().isBlank()) { - binding.get().editText.setError(context.getString(R.string.tab_name_empty_error)); + binding.get().editText.setError(i18n(String0_commonMainKt.getTab_name_empty_error(Res.string.INSTANCE))); return; } @@ -124,7 +126,7 @@ public IconStateful getIcon(Map.Entry item) { runOnUiThread(() -> { if(items.size() == 2) { var title = new SettingsItem.Builder(SettingsItemType.CATEGORY) - .setTitle(R.string.custom_tabs) + .setTitle(i18n(String0_commonMainKt.getCustom_tabs(Res.string.INSTANCE))) .build(); items.add(title); diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupActivity.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupActivity.kt index ecf61783..e88fc597 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupActivity.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupActivity.kt @@ -11,8 +11,9 @@ import com.mrboomdev.awery.R import com.mrboomdev.awery.app.App.Companion.database import com.mrboomdev.awery.app.theme.ThemeManager.applyTheme import com.mrboomdev.awery.databinding.ScreenSetupBinding -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.generated.* import com.mrboomdev.awery.platform.PlatformSettingHandler +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.screens.SplashActivity import com.mrboomdev.awery.ui.mobile.screens.setup.SetupThemeAdapter.Companion.create import com.mrboomdev.awery.util.extensions.UI_INSETS @@ -26,6 +27,10 @@ import com.mrboomdev.awery.util.extensions.startActivity import com.mrboomdev.awery.util.ui.RecyclerItemDecoration import com.mrboomdev.awery.util.ui.adapter.SingleViewAdapter import com.mrboomdev.awery.util.ui.dialog.DialogBuilder +import com.mrboomdev.awery.utils.buildIntent +import com.mrboomdev.awery.utils.dpPx +import com.mrboomdev.safeargsnext.owner.SafeArgsActivity +import com.mrboomdev.safeargsnext.util.rememberSafeArgs import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import nl.dionsegijn.konfetti.core.Party @@ -37,9 +42,11 @@ import nl.dionsegijn.konfetti.core.models.Shape.Square import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean -class SetupActivity : AppCompatActivity() { +class SetupActivity : AppCompatActivity(), SafeArgsActivity { private lateinit var binding: ScreenSetupBinding + data class Extras(val step: Int, val finishOnComplete: Boolean = false) + override fun onCreate(savedInstanceState: Bundle?) { applyTheme() enableEdgeToEdge() @@ -56,21 +63,21 @@ class SetupActivity : AppCompatActivity() { binding.continueButton.setOnClickListener { tryToStartNextStep() } binding.backButton.setOnClickListener { finish() } - if(intent.getBooleanExtra(EXTRA_FINISH_ON_COMPLETE, false)) { + if(rememberSafeArgs?.finishOnComplete == true) { binding.backButton.visibility = View.GONE - binding.continueButton.setText(R.string.done) + binding.continueButton.text = i18n(Res.string.done) } when(intent.getIntExtra("step", STEP_WELCOME)) { STEP_WELCOME -> { if(AwerySettings.SETUP_VERSION_FINISHED.value != -1) { - binding.title.setText(R.string.awery_updated_title) - binding.message.setText(R.string.awery_updated_description) + binding.title.text = i18n(Res.string.awery_updated_title) + binding.message.text = i18n(Res.string.awery_updated_description) binding.backButton.visibility = View.GONE } - binding.backButton.setText(R.string.restore_backup) - binding.continueButton.setText(R.string.lets_begin) + binding.backButton.text = i18n(Res.string.restore_backup) + binding.continueButton.text = i18n(Res.string.lets_begin) binding.backButton.setOnClickListener { PlatformSettingHandler.handlePlatformClick(this, AwerySettings.RESTORE.asPlatformSetting()) @@ -81,8 +88,8 @@ class SetupActivity : AppCompatActivity() { } STEP_THEMING -> { - binding.title.setText(R.string.color_palette) - binding.message.setText(R.string.color_palette_description) + binding.title.text = i18n(Res.string.color_palette) + binding.message.text = i18n(Res.string.color_palette_description) binding.recycler.layoutManager = LinearLayoutManager(this) binding.recycler.adapter = create(this) @@ -96,8 +103,8 @@ class SetupActivity : AppCompatActivity() { } STEP_TEMPLATE -> { - binding.title.setText(R.string.select_template) - binding.message.text = getString(R.string.generic_message) + binding.title.text = i18n(Res.string.select_template) + binding.message.text = i18n(Res.string.generic_message) binding.recycler.layoutManager = LinearLayoutManager(this) binding.recycler.addItemDecoration(RecyclerItemDecoration(dpPx(8f))) @@ -110,29 +117,25 @@ class SetupActivity : AppCompatActivity() { } STEP_SOURCES -> { - val template = AwerySettings.TABS_TEMPLATE.value - val discordUrl = getString(R.string.discord_link) - val telegramUrl = getString(R.string.telegram_link) - - if(template == "dantotsu") { - binding.message.setMarkwon(getString(R.string.dantotsu_message, discordUrl, telegramUrl)) + if(AwerySettings.TABS_TEMPLATE.value == "dantotsu") { + binding.message.setMarkwon(i18n(Res.string.dantotsu_message, "https://discord.com/invite/yspVzD4Kbm", "https://t.me/mrboomdev_awery")) } else { - binding.message.setMarkwon(getString(R.string.generic_message, discordUrl, telegramUrl)) + binding.message.setMarkwon(i18n(Res.string.generic_message, "https://discord.com/invite/yspVzD4Kbm", "https://t.me/mrboomdev_awery")) } - binding.title.setText(R.string.extensions) + binding.title.text = i18n(Res.string.extensions) binding.icon.visibility = View.VISIBLE binding.icon.setImageResource(R.drawable.ic_extension_filled) binding.icon.setImageTintAttr(com.google.android.material.R.attr.colorOnSecondaryContainer) } STEP_ANALYTICS -> { - binding.title.text = getString(R.string.analytics_title) - binding.message.text = getString(R.string.analytics_message) + binding.title.text = i18n(Res.string.analytics_title) + binding.message.text = i18n(Res.string.analytics_message) binding.recycler.visibility = View.VISIBLE binding.recycler.adapter = SingleViewAdapter.fromView(MaterialSwitch(this).apply { - text = getString(R.string.automatically_send_reports) + text = i18n(Res.string.automatically_send_reports) isChecked = true }) } @@ -143,9 +146,9 @@ class SetupActivity : AppCompatActivity() { createParty(275, 225, 300, 200, 150, .4), createParty(275, 225, 300, 200, 330, .6)) - binding.title.setText(R.string.were_done) - binding.message.setText(R.string.setup_finished_description) - binding.continueButton.setText(R.string.finish) + binding.title.text = i18n(Res.string.were_done) + binding.message.text = i18n(Res.string.setup_finished_description) + binding.continueButton.text = i18n(Res.string.finish) binding.icon.visibility = View.VISIBLE binding.icon.setImageResource(R.drawable.ic_done) @@ -159,7 +162,7 @@ class SetupActivity : AppCompatActivity() { } private fun tryToStartNextStep() { - when(intent.getIntExtra(EXTRA_STEP, STEP_WELCOME)) { + when(rememberSafeArgs?.step ?: STEP_WELCOME) { STEP_TEMPLATE -> { val selected = (binding.recycler.adapter as SetupTabsAdapter).selected @@ -183,16 +186,16 @@ class SetupActivity : AppCompatActivity() { runOnUiThread { DialogBuilder(this@SetupActivity) - .setTitle(getString(R.string.existing_custom_tabs_title)) - .setMessage(getString(R.string.existing_custom_tabs_message)) + .setTitle(i18n(Res.string.existing_custom_tabs_title)) + .setMessage(i18n(Res.string.existing_custom_tabs_message)) .setOnDismissListener { if (!didDeleted.get()) { binding.backButton.isEnabled = true binding.continueButton.isEnabled = true } } - .setNegativeButton(R.string.cancel) { it.dismiss() } - .setPositiveButton(R.string.delete) { dialog -> + .setNegativeButton(i18n(Res.string.cancel)) { it.dismiss() } + .setPositiveButton(i18n(Res.string.delete)) { dialog -> didDeleted.set(true) dialog.dismiss() @@ -227,13 +230,13 @@ class SetupActivity : AppCompatActivity() { } private fun startNextStep() { - if(intent.getBooleanExtra(EXTRA_FINISH_ON_COMPLETE, false)) { + if(rememberSafeArgs?.finishOnComplete == true) { setResult(RESULT_OK) finish() return } - val nextStep = when(intent.getIntExtra(EXTRA_STEP, STEP_WELCOME)) { + val nextStep = when(rememberSafeArgs?.step ?: STEP_WELCOME) { STEP_WELCOME -> STEP_THEMING STEP_THEMING -> STEP_TEMPLATE STEP_TEMPLATE -> STEP_SOURCES @@ -243,20 +246,14 @@ class SetupActivity : AppCompatActivity() { STEP_FINISH -> { AwerySettings.SETUP_VERSION_FINISHED.value = SETUP_VERSION finishAffinity() - startActivity(SplashActivity::class) + startActivity(buildIntent(SplashActivity::class)) return } else -> throw IllegalArgumentException("Unknown step!") } - startStep(nextStep) - } - - private fun startStep(step: Int) { - val intent = Intent(this, SetupActivity::class.java) - intent.putExtra(EXTRA_STEP, step) - startActivity(intent) + startActivity(buildIntent(SetupActivity::class, Extras(nextStep))) } private fun createParty(durationMs: Int, amountPerSec: Int, delayMs: Int, spread: Int, angle: Int, x: Double): Party { @@ -272,13 +269,9 @@ class SetupActivity : AppCompatActivity() { } companion object { - /** - * Note: Please increment this value by one every time when a new step is being added - */ + // Note: Please increment this value by one every time when a new step is being added const val SETUP_VERSION = 2 - - const val EXTRA_STEP = "step" - const val EXTRA_FINISH_ON_COMPLETE = "finish_on_complete" + const val STEP_WELCOME = 0 const val STEP_FINISH = 1 const val STEP_TEMPLATE = 2 diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupTabsAdapter.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupTabsAdapter.kt index f4042279..40b3df22 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupTabsAdapter.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupTabsAdapter.kt @@ -17,13 +17,14 @@ import com.mrboomdev.awery.util.TabsTemplate import com.mrboomdev.awery.util.extensions.clearImageTint import com.mrboomdev.awery.util.extensions.context import com.mrboomdev.awery.util.extensions.dpPx -import com.mrboomdev.awery.util.extensions.inflater import com.mrboomdev.awery.util.extensions.readAssets import com.mrboomdev.awery.util.extensions.resolveAttrColor import com.mrboomdev.awery.util.extensions.resolveDrawable import com.mrboomdev.awery.util.extensions.scale import com.mrboomdev.awery.util.extensions.setImageTintAttr import com.mrboomdev.awery.util.extensions.topMargin +import com.mrboomdev.awery.utils.dpPx +import com.mrboomdev.awery.utils.inflater import com.squareup.moshi.adapter import java.io.File diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupThemeAdapter.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupThemeAdapter.kt index dfc81327..473d044b 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupThemeAdapter.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/mobile/screens/setup/SetupThemeAdapter.kt @@ -27,8 +27,9 @@ import com.mrboomdev.awery.data.settings.SettingsItem import com.mrboomdev.awery.databinding.WidgetCircleButtonBinding import com.mrboomdev.awery.ext.data.Setting import com.mrboomdev.awery.ext.data.getRecursively -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.generated.* import com.mrboomdev.awery.platform.PlatformResources +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsAdapter import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsDataHandler import com.mrboomdev.awery.util.extensions.balloon @@ -38,6 +39,7 @@ import com.mrboomdev.awery.util.extensions.resolveAttrColor import com.mrboomdev.awery.util.extensions.setHorizontalMargin import com.mrboomdev.awery.util.ui.RecyclerItemDecoration import com.mrboomdev.awery.util.ui.adapter.SingleViewAdapter +import com.mrboomdev.awery.utils.dpPx import com.skydoves.balloon.BalloonAlign class SetupThemeAdapter private constructor(context: Context) : RecyclerView.Adapter() { @@ -142,13 +144,13 @@ class SetupThemeAdapter private constructor(context: Context) : RecyclerView.Ada } if(theme.palette == AwerySettings.ThemeColorPaletteValue.MATERIAL_YOU && !AwerySettings.DID_SUGGEST_MATERIAL_YOU.value) { - binding.root.balloon(PlatformResources.i18n(R.string.wallpaper_based_colors), BalloonAlign.BOTTOM) + binding.root.balloon(i18n(Res.string.wallpaper_based_colors), BalloonAlign.BOTTOM) AwerySettings.DID_SUGGEST_MATERIAL_YOU.value = true } binding.root.setOnLongClickListener { if(theme.palette == AwerySettings.ThemeColorPaletteValue.MATERIAL_YOU) { - binding.root.balloon(PlatformResources.i18n(R.string.wallpaper_based_colors), BalloonAlign.BOTTOM) + binding.root.balloon(i18n(Res.string.wallpaper_based_colors), BalloonAlign.BOTTOM) return@setOnLongClickListener true } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/TvMainActivity.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/TvMainActivity.kt index b41f6ce5..3e734e4b 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/TvMainActivity.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/TvMainActivity.kt @@ -1,6 +1,7 @@ package com.mrboomdev.awery.ui.tv import android.app.Activity +import android.content.res.Configuration import android.os.Bundle import androidx.activity.ComponentActivity import androidx.compose.foundation.background @@ -16,6 +17,7 @@ import androidx.navigation.toRoute import com.mrboomdev.awery.app.theme.ThemeManager.setThemedContent import com.mrboomdev.awery.data.settings.NicePreferences import com.mrboomdev.awery.ext.data.CatalogMedia +import com.mrboomdev.awery.platform.PlatformResources import com.mrboomdev.awery.platform.PlatformSetting import com.mrboomdev.awery.ui.mobile.components.MobileSetting import com.mrboomdev.awery.ui.mobile.screens.settings.SettingsActivity diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/components/FeedsGroup.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/components/FeedsGroup.kt index 29958f7e..e40657d6 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/components/FeedsGroup.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/components/FeedsGroup.kt @@ -23,6 +23,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.CircularProgressIndicator import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -40,7 +41,7 @@ import androidx.tv.material3.Text import com.mrboomdev.awery.ext.data.CatalogFeed import com.mrboomdev.awery.ext.data.CatalogMedia import com.mrboomdev.awery.ext.data.get -import com.mrboomdev.awery.util.exceptions.ZeroResultsException +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlin.math.abs @@ -54,14 +55,13 @@ fun FeedsGroup( listState: LazyListState = rememberLazyListState(), isLoading: Boolean = false ) { - val coroutineScope = rememberCoroutineScope() var didWaitToFixScroll by remember { mutableStateOf(false) } var didFixScroll by remember { mutableStateOf(false) } if((sections?.size ?: 0) > 0 && !didWaitToFixScroll && !didFixScroll) { didFixScroll = true - coroutineScope.launch { + LaunchedEffect(true) { delay(500L) didWaitToFixScroll = true } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/home/HomeScreen.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/home/HomeScreen.kt index c9a0f771..9a31b393 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/home/HomeScreen.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/home/HomeScreen.kt @@ -30,6 +30,7 @@ import com.mrboomdev.awery.ui.tv.Screens import com.mrboomdev.awery.ui.tv.components.FeedsGroup import com.mrboomdev.awery.util.IconStateful import com.mrboomdev.awery.util.extensions.startActivity +import com.mrboomdev.awery.utils.buildIntent @Composable fun HomeScreen( @@ -83,7 +84,10 @@ fun HomeScreen( return@NavigationDrawerItem } - getAnyActivity()!!.startActivity(SettingsActivity::class) + getAnyActivity()!!.apply { + startActivity(buildIntent(SettingsActivity::class)) + } + return@NavigationDrawerItem } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/home/HomeViewModel.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/home/HomeViewModel.kt index 45c72a11..cd52e7ed 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/home/HomeViewModel.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/home/HomeViewModel.kt @@ -11,12 +11,12 @@ import androidx.tv.material3.DrawerState import androidx.tv.material3.DrawerValue import com.mrboomdev.awery.R import com.mrboomdev.awery.app.App.Companion.getMoshi -import com.mrboomdev.awery.app.App.Companion.i18n import com.mrboomdev.awery.app.ExtensionsManager.loadAll import com.mrboomdev.awery.ext.data.CatalogFeed -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.IconStateful -import com.mrboomdev.awery.util.exceptions.ZeroResultsException import com.mrboomdev.awery.util.extensions.ensureSize import com.mrboomdev.awery.util.io.FileUtil.readAssets import com.squareup.moshi.Json @@ -92,12 +92,12 @@ class HomeViewModel : ViewModel() { }!! tabs.addAll(dbTabs.map { - it.title = i18n(it.title) ?: it.title + it.title = i18n(it.title) ?: it.title it to (icons[it.icon] ?: IconStateful(activeId = R.drawable.ic_view_cozy)) }) tabs.add(__DBTab__().apply { - title = i18n(R.string.settings) + title = i18n(Res.string.settings) id = "settings" } to IconStateful(activeId = R.drawable.ic_settings_filled)) diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/media/MediaInfoScreen.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/media/MediaInfoScreen.kt index 8978b1fb..8d98756d 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/media/MediaInfoScreen.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/media/MediaInfoScreen.kt @@ -16,9 +16,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shadow import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview @@ -38,11 +36,14 @@ import com.mrboomdev.awery.app.AweryLifecycle.Companion.getAnyActivity import com.mrboomdev.awery.app.AweryLocales import com.mrboomdev.awery.app.ExtensionsManager import com.mrboomdev.awery.ext.data.CatalogMedia +import com.mrboomdev.awery.generated.* import com.mrboomdev.awery.ui.mobile.dialogs.MediaBookmarkDialog import com.mrboomdev.awery.ui.mobile.screens.BrowserActivity import com.mrboomdev.awery.util.extensions.plus import com.mrboomdev.awery.util.extensions.startActivity import com.mrboomdev.awery.util.extensions.toCalendar +import com.mrboomdev.awery.utils.buildIntent +import org.jetbrains.compose.resources.stringResource import java.util.Calendar enum class MediaInfoAction { @@ -61,7 +62,7 @@ fun MediaInfoScreen( ) { Text( modifier = Modifier.widthIn(max = maxTextWidth), - text = media.title ?: stringResource(R.string.no_title), + text = media.title ?: stringResource(Res.string.no_title), maxLines = 2, color = Color.White, style = TextStyle( @@ -82,20 +83,20 @@ fun MediaInfoScreen( text = mutableListOf().apply { if(media.episodesCount != null) { add(media.episodesCount + " " + stringResource( - if(media.episodesCount == 1) R.string.episode - else R.string.episodes) + if(media.episodesCount == 1) Res.string.episode + else Res.string.episodes) ) } if(media.duration != null) { add(media.duration!!.let { return@let if(it < 60) { - "$it${stringResource(R.string.minute_short)}" + "$it${stringResource(Res.string.minute_short)}" } else { - "${it / 60}${stringResource(R.string.hour_short)} " + - "${it % 60}${stringResource(R.string.minute_short)}" + "${it / 60}${stringResource(Res.string.hour_short)} " + + "${it % 60}${stringResource(Res.string.minute_short)}" } - } + " " + stringResource(R.string.duration)) + } + " " + stringResource(Res.string.duration)) } if(media.releaseDate != null) { @@ -103,26 +104,27 @@ fun MediaInfoScreen( } if(media.country != null) { - add(AweryLocales.translateCountryName( - LocalContext.current, media.country!!)) + add(AweryLocales.i18nCountryName( + media.country!! + )) } if(size < 3 && media.status != null) { add(stringResource(when(media.status!!) { CatalogMedia.Status.ONGOING -> - R.string.status_releasing + Res.string.status_releasing CatalogMedia.Status.COMPLETED -> - R.string.status_finished + Res.string.status_finished CatalogMedia.Status.COMING_SOON -> - R.string.status_not_yet_released + Res.string.status_not_yet_released CatalogMedia.Status.PAUSED -> - R.string.status_hiatus + Res.string.status_hiatus CatalogMedia.Status.CANCELLED -> - R.string.status_cancelled + Res.string.status_cancelled })) } @@ -140,7 +142,7 @@ fun MediaInfoScreen( modifier = Modifier.widthIn(max = maxTextWidth), overflow = TextOverflow.Ellipsis, maxLines = 3, - text = media.description ?: stringResource(R.string.no_description_available), + text = media.description ?: stringResource(Res.string.no_description_available), color = Color.White, style = TextStyle( fontSize = 18.sp, @@ -159,9 +161,9 @@ fun MediaInfoScreen( fontSize = 17.sp, text = when(media.type) { CatalogMedia.Type.BOOK, CatalogMedia.Type.POST -> - stringResource(R.string.read_now) + stringResource(Res.string.read_now) - else -> stringResource(R.string.watch_now) + else -> stringResource(Res.string.watch_now) } ) } @@ -186,7 +188,7 @@ fun MediaInfoScreen( Icon( modifier = Modifier.padding(8.dp), painter = painterResource(R.drawable.ic_bookmark_filled), - contentDescription = stringResource(R.string.bookmark) + contentDescription = stringResource(Res.string.bookmark) ) } @@ -194,8 +196,8 @@ fun MediaInfoScreen( Spacer(Modifier.width(10.dp)) IconButton(onClick = { - getAnyActivity()!!.also { - it.startActivity(BrowserActivity::class, BrowserActivity.Extras(media.url!!)) + getAnyActivity()!!.apply { + startActivity(buildIntent(BrowserActivity::class, BrowserActivity.Extras(media.url!!))) } }) { Icon( diff --git a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/media/MediaScreen.kt b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/media/MediaScreen.kt index bab8cee7..aed5b183 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/media/MediaScreen.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/ui/tv/screens/media/MediaScreen.kt @@ -18,7 +18,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.tv.material3.AssistChip @@ -32,7 +31,8 @@ import com.mrboomdev.awery.app.App.Companion.toast import com.mrboomdev.awery.app.theme.TvTheme import com.mrboomdev.awery.ext.data.CatalogMedia import com.mrboomdev.awery.ext.data.CatalogTag -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.generated.* +import org.jetbrains.compose.resources.stringResource private val SHADOW_COLOR = Color(0xBB000000) @@ -101,7 +101,7 @@ fun MediaScreen(media: CatalogMedia) { .fillMaxWidth(), style = MaterialTheme.typography.titleLarge, color = Color.White, - text = stringResource(R.string.genres) + text = stringResource(Res.string.genres) ) } @@ -134,7 +134,7 @@ fun MediaScreen(media: CatalogMedia) { .fillMaxWidth(), style = MaterialTheme.typography.titleLarge, color = Color.White, - text = stringResource(R.string.tags) + text = stringResource(Res.string.tags) ) } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/IconStateful.kt b/androidApp/src/main/java/com/mrboomdev/awery/util/IconStateful.kt index e02692b6..60bc2044 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/IconStateful.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/IconStateful.kt @@ -8,7 +8,7 @@ import androidx.annotation.DrawableRes import androidx.appcompat.graphics.drawable.StateListDrawableCompat import androidx.core.content.ContextCompat import com.mrboomdev.awery.R -import com.mrboomdev.awery.app.App.Companion.getResourceId +import com.mrboomdev.awery.app.App import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) @@ -66,7 +66,7 @@ class IconStateful( } if(active != null) { - activeId = getResourceId(active) + activeId = App.getResourceId(R.drawable::class.java, active) return activeId!! } } @@ -77,7 +77,7 @@ class IconStateful( } if(inActive != null) { - inActiveId = getResourceId(inActive) + inActiveId = App.getResourceId(R.drawable::class.java, inActive) return inActiveId!! } } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/NiceUtils.java b/androidApp/src/main/java/com/mrboomdev/awery/util/NiceUtils.java index 13cac32a..8a273afa 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/NiceUtils.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/NiceUtils.java @@ -15,6 +15,7 @@ import androidx.media3.common.MimeTypes; import com.mrboomdev.awery.util.io.FileUtil; +import com.mrboomdev.awery.utils.UniqueIdGenerator; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/LocalizedException.java b/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/LocalizedException.java index 339b4aa3..2f60c15e 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/LocalizedException.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/LocalizedException.java @@ -2,6 +2,7 @@ import android.content.Context; +@Deprecated(forRemoval = true) public interface LocalizedException { default String getDescription(Context context) { return getLocalizedMessage(); diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/OkiThrowableMessage.kt b/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/OkiThrowableMessage.kt index a76549bf..5350ffa7 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/OkiThrowableMessage.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/OkiThrowableMessage.kt @@ -2,12 +2,14 @@ package com.mrboomdev.awery.util.exceptions import android.util.Log import com.mrboomdev.awery.R -import com.mrboomdev.awery.app.App.Companion.i18n import com.mrboomdev.awery.app.AweryLifecycle.Companion.appContext +import com.mrboomdev.awery.ext.util.LocaleAware import com.mrboomdev.awery.ext.util.exceptions.ExtensionInstallException import com.mrboomdev.awery.ext.util.exceptions.ExtensionLoadException +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import eu.kanade.tachiyomi.network.HttpException -import java9.util.Objects import kotlinx.coroutines.CancellationException import java.net.SocketException import java.net.SocketTimeoutException @@ -36,58 +38,55 @@ class OkiThrowableMessage( val title: String get() = (when(t) { - is LocalizedException -> t.getTitle(appContext) - is SocketTimeoutException -> i18n(R.string.timed_out) - is SSLHandshakeException -> i18n(R.string.failed_handshake) + is SocketTimeoutException -> i18n(Res.string.timed_out) + is SSLHandshakeException -> i18n(Res.string.failed_handshake) is SocketException -> t.message is UnknownHostException -> t.message - is BotSecurityBypassException -> i18n(R.string.failed_to_bypass, t.blockerName) - is ExtensionInstallException -> i18n(R.string.extension_installed_failed) - is ExtensionLoadException -> i18n(R.string.extension_load_failed) + is BotSecurityBypassException -> i18n(Res.string.failed_to_bypass, t.blockerName) + is ExtensionInstallException -> i18n(Res.string.extension_installed_failed) + is ExtensionLoadException -> i18n(Res.string.extension_load_failed) is CancellationException -> "Operation cancelled" is UnsupportedOperationException -> "Unsupported action" is NotImplementedError -> "Unsupported action" is HttpException -> when(t.code) { - 400, 422 -> i18n(R.string.bad_request) - 403 -> i18n(R.string.access_denied) - 404 -> i18n(R.string.nothing_found) - 429 -> i18n(R.string.too_much_requests) - 500, 503 -> i18n(R.string.server_down) - 504 -> i18n(R.string.timed_out) - else -> i18n(R.string.unknown_net_error) + 400, 422 -> i18n(Res.string.bad_request) + 403 -> i18n(Res.string.access_denied) + 404 -> i18n(Res.string.nothing_found) + 429 -> i18n(Res.string.too_much_requests) + 500, 503 -> i18n(Res.string.server_down) + 504 -> i18n(Res.string.timed_out) + else -> i18n(Res.string.unknown_net_error) } else -> null }) ?: run { if(t.message?.contains(ROOM_EXCEPTION) == true) { - return i18n(R.string.database_corrupted) + return i18n(Res.string.database_corrupted) } - return@run i18n(R.string.something_went_wrong) + return@run i18n(Res.string.something_went_wrong) } val message: String get() = when(t) { - is LocalizedException -> t.getDescription(appContext) - is SocketTimeoutException -> i18n(R.string.connection_timeout) - is BotSecurityBypassException -> i18n(R.string.failed_bypass_detailed, t.blockerName) - is SocketException -> i18n(R.string.failed_to_connect_to_server) - is SSLHandshakeException -> i18n(R.string.failed_to_connect_to_server) + is LocaleAware -> t.localizedMessage + is SocketTimeoutException -> i18n(Res.string.connection_timeout) + is BotSecurityBypassException -> i18n(Res.string.failed_bypass_detailed, t.blockerName) + is SocketException -> i18n(Res.string.failed_to_connect_to_server) + is SSLHandshakeException -> i18n(Res.string.failed_to_connect_to_server) is NotImplementedError -> t.message - is ExtensionInstallException -> t.userReadableMessage - is ExtensionLoadException -> t.userReadableMessage is HttpException -> "(${t.code}) " + when(t.code) { - 400, 422 -> i18n(R.string.request_invalid_detailed) - 401 -> i18n(R.string.not_logged_detailed) - 403 -> i18n(R.string.no_access_detailed) - 404 -> i18n(R.string.not_found_detailed) - 429 -> i18n(R.string.rate_limited_detailed) - 500 -> i18n(R.string.server_internal_error) - 503 -> i18n(R.string.server_unavailable) - 504 -> i18n(R.string.connection_timeout) - else -> i18n(R.string.unknown_error) + 400, 422 -> i18n(Res.string.request_invalid_detailed) + 401 -> i18n(Res.string.not_logged_detailed) + 403 -> i18n(Res.string.no_access_detailed) + 404 -> i18n(Res.string.not_found_detailed) + 429 -> i18n(Res.string.rate_limited_detailed) + 500 -> i18n(Res.string.server_internal_error) + 503 -> i18n(Res.string.server_unavailable) + 504 -> i18n(Res.string.connection_timeout) + else -> i18n(Res.string.unknown_error) } else -> null @@ -150,13 +149,13 @@ private val Throwable.mayDescribe: Boolean || this is UnsupportedOperationException || this is HttpException || this is CancellationException - || this is LocalizedException || this is NotImplementedError || this is SocketTimeoutException || this is BotSecurityBypassException || this is SSLHandshakeException || this is SocketException || this is UnknownHostException + || this is LocaleAware private val Throwable.isNetworkExceptionImpl get() = this is SocketTimeoutException || diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/ZeroResultsException.java b/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/ZeroResultsException.java deleted file mode 100644 index 1d738cab..00000000 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/exceptions/ZeroResultsException.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.mrboomdev.awery.util.exceptions; - -import android.content.Context; - -import androidx.annotation.NonNull; -import androidx.annotation.StringRes; - -import com.mrboomdev.awery.R; - -/** - * Being thrown if no results was found. - * @author MrBoomDev - */ -public class ZeroResultsException extends RuntimeException implements LocalizedException { - private final int description, title; - - public ZeroResultsException(String message, @StringRes int localizedTitle, @StringRes int localizedDescription) { - super(message); - this.title = localizedTitle; - this.description = localizedDescription; - } - - public ZeroResultsException(String message, @StringRes int localizedDescription) { - super(message); - this.title = localizedDescription; - this.description = localizedDescription; - } - - public ZeroResultsException(String message) { - super(message); - this.title = -1; - this.description = -1; - } - - @Override - public String getDescription(@NonNull Context context) { - if(description == -1) { - return getLocalizedMessage(); - } - - return context.getString(description); - } - - @Override - public String getTitle(@NonNull Context context) { - if(title == -1) { - return getLocalizedMessage(); - } - - return context.getString(R.string.nothing_found); - } -} \ No newline at end of file diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ActivityExtensions.kt b/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ActivityExtensions.kt index 3eef3a15..61b32d5f 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ActivityExtensions.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ActivityExtensions.kt @@ -1,114 +1,15 @@ package com.mrboomdev.awery.util.extensions import android.app.Activity -import android.content.ComponentName -import android.content.Intent import android.graphics.Color -import android.os.Build import android.util.Log import android.view.View import androidx.activity.ComponentActivity -import androidx.activity.OnBackPressedCallback -import androidx.activity.OnBackPressedDispatcherOwner import androidx.activity.SystemBarStyle import androidx.activity.enableEdgeToEdge -import androidx.core.app.ActivityCompat -import com.mrboomdev.awery.app.AweryLifecycle -import com.mrboomdev.awery.app.AweryLifecycle.Companion.addActivityResultListener -import com.mrboomdev.awery.app.AweryLifecycle.Companion.generateRequestCode import com.mrboomdev.awery.app.AweryLifecycle.Companion.postRunnable -import com.mrboomdev.awery.app.theme.ThemeManager -import java.util.WeakHashMap -import kotlin.reflect.KClass private const val TAG = "ActivityExtensions" -private val backPressedCallbacks = WeakHashMap<() -> Unit, Any>() - -fun Activity.requestPermission( - permission: String, - callback: (didGrant: Boolean) -> Unit, - requestCode: Int = generateRequestCode() -) { - if(hasPermission(permission)) { - callback(true) - return - } - - addActivityResultListener(this, requestCode, null, callback) - ActivityCompat.requestPermissions(this, arrayOf(permission), requestCode) -} - -fun Activity.startActivityForResult( - clazz: KClass<*>? = null, - action: String? = null, - type: String? = null, - categories: Array? = null, - extras: Map? = null, - callback: (resultCode: Int, result: Intent?) -> Unit, - requestCode: Int = generateRequestCode() -) { - val activity = this - - startActivityForResult(Intent(action).apply { - setType(type) - - if(categories != null) { - for(category in categories) { - addCategory(category) - } - } - - if(extras != null) { - for((key, value) in extras) { - put(key, value) - } - } - - if(clazz != null) { - component = ComponentName(activity, clazz.java) - } - }, callback, requestCode) -} - -fun Activity.startActivityForResult( - intent: Intent, - callback: (resultCode: Int, result: Intent?) -> Unit, - requestCode: Int = generateRequestCode() -) { - runOnUiThread { - AweryLifecycle.startActivityForResult(this, intent, callback, requestCode) - } -} - -fun Activity.removeOnBackPressedListener(callback: () -> Unit) { - val onBackInvokedCallback = backPressedCallbacks.remove(callback) ?: return - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - onBackInvokedDispatcher.unregisterOnBackInvokedCallback(callback) - } else { - (onBackInvokedCallback as OnBackPressedCallback).remove() - } -} - -fun Activity.addOnBackPressedListener(callback: () -> Unit) { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - backPressedCallbacks[callback] = callback - onBackInvokedDispatcher.registerOnBackInvokedCallback(0, callback) - } else { - if(this is OnBackPressedDispatcherOwner) { - val onBackInvokedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - callback() - } - } - - onBackPressedDispatcher.addCallback(this, onBackInvokedCallback) - backPressedCallbacks[callback] = onBackInvokedCallback - } else { - throw IllegalArgumentException("Activity must implement OnBackPressedDispatcherOwner!") - } - } -} /** * There is a bug in an appcompat library which sometimes throws an [NullPointerException]. @@ -116,7 +17,7 @@ fun Activity.addOnBackPressedListener(callback: () -> Unit) { */ fun Activity.setContentViewCompat(view: View) { try { - activity.setContentView(view) + setContentView(view) } catch (e: NullPointerException) { Log.e(TAG, "Failed to setContentView!", e) diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ContextExtensions.kt b/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ContextExtensions.kt index 96800ed3..76d26783 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ContextExtensions.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ContextExtensions.kt @@ -28,114 +28,6 @@ import org.jetbrains.annotations.Contract import java.io.File import kotlin.reflect.KClass -private const val TAG = "ContextExtensions" - -fun Context.hasPermission(permission: String): Boolean { - return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED -} - -val Context.configuration: Configuration - get() = resources.configuration - -inline fun Context.startService(clazz: KClass>, args: T) { - startService(Intent(this, clazz.java).apply { - putSafeArgs(args as Any) - }) -} - -inline fun Context.startService( - action: String? = null, - extras: Map? = null, - data: Uri? = null -) { - val intent = Intent(this, T::class.java) - intent.action = action - intent.data = data - - if(extras != null) { - for(extra in extras) { - intent.put(extra.key, extra.value) - } - } - - startService(intent) -} - -fun Context.startActivity( - clazz: KClass>, - args: A, - action: String? = null, - data: Uri? = null -) { - startActivity(SafeArgsIntent(this, clazz, args).also { - it.action = action - it.data = data - }) -} - -fun Context.startActivity( - clazz: KClass<*>? = null, - action: String? = null, - extras: Map? = null, - data: Uri? = null -) { - val intent = Intent() - intent.action = action - intent.data = data - - if(clazz != null) { - intent.component = ComponentName(this, clazz.java) - } - - if(extras != null) { - for((key, value) in extras) { - intent.put(key, value) - } - } - - startActivity(intent) -} - -val Context.screenWidth: Int - get() = resources.displayMetrics.widthPixels - -val Context.screenHeight: Int - get() = resources.displayMetrics.heightPixels - -fun Context.getCacheFile(path: String): File { - return File(cacheDir, path) -} - -fun Context.getFile(path: String): File { - return File(filesDir, path) -} - -fun Context.dpPx(dp: Float): Int { - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics).toInt() -} - -fun Context.spPx(sp: Float): Float { - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, resources.displayMetrics) -} - -val Context.inflater: LayoutInflater - get() = LayoutInflater.from(this) - -val Context.activity: Activity - get() { - var context = this - - while(context is ContextWrapper) { - if(context is Activity) { - return context - } - - context = context.baseContext - } - - throw IllegalStateException("Context is not an Activity!") - } - /** * Possible name param syntax: *

`my_awesome_icon` - Will return an icon from the drawable directory

diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/DialogExtensions.kt b/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/DialogExtensions.kt index 7cbc5889..5a80fd33 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/DialogExtensions.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/DialogExtensions.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.elevation.SurfaceColors import com.google.android.material.sidesheet.SideSheetDialog +import com.mrboomdev.awery.utils.dpPx import com.google.android.material.R as MaterialR private const val MAX_SIDE_WIDTH = 400f @@ -39,7 +40,7 @@ fun Dialog.fix() { /* If we'll try to do this shit with the SideSheetDialog, it will get centered, so we use different approaches for different dialog types.*/ - if(context.configuration.screenWidthDp > MAX_WIDTH) { + if(context.resources.configuration.screenWidthDp > MAX_WIDTH) { window.setLayout(context.dpPx(MAX_WIDTH), MATCH_PARENT) } } diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ViewExtensions.kt b/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ViewExtensions.kt index 7a697b47..e94c353a 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ViewExtensions.kt +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/extensions/ViewExtensions.kt @@ -23,6 +23,9 @@ import androidx.viewbinding.ViewBinding import com.google.android.material.R import com.mrboomdev.awery.app.App.Companion.getMarkwon import com.mrboomdev.awery.app.AweryLifecycle.Companion.runDelayed +import com.mrboomdev.awery.utils.activity +import com.mrboomdev.awery.utils.dpPx +import com.mrboomdev.awery.utils.spPx import com.skydoves.balloon.ArrowOrientation import com.skydoves.balloon.Balloon import com.skydoves.balloon.BalloonAlign diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/BaseDialogBuilder.java b/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/BaseDialogBuilder.java index 405c9c2f..9c133f98 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/BaseDialogBuilder.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/BaseDialogBuilder.java @@ -52,19 +52,11 @@ public T setTitle(String title) { return (T) this; } - public T setTitle(@StringRes int res) { - return setTitle(context.getString(res)); - } - public T setMessage(String message) { this.message = message; return (T) this; } - public T setMessage(@StringRes int res) { - return setMessage(context.getString(res)); - } - public T setPositiveButton(String label, OnButtonClickListener listener) { this.okListener = listener; this.okButtonLabel = label; @@ -75,20 +67,12 @@ public interface Callback1 { void run(T arg); } - public T setPositiveButton(@StringRes int label, OnButtonClickListener listener) { - return setPositiveButton(context.getString(label), listener); - } - public T setNeutralButton(String label, OnButtonClickListener listener) { this.neutralListener = listener; this.neutralButtonLabel = label; return (T) this; } - public T setNeutralButton(@StringRes int label, OnButtonClickListener listener) { - return setNeutralButton(context.getString(label), listener); - } - public T setCancelable(boolean isCancelable) { this.isCancelable = isCancelable; return (T) this; @@ -118,10 +102,6 @@ public T setNegativeButton(String label, OnButtonClickListener listener) { return (T) this; } - public T setNegativeButton(@StringRes int label, OnButtonClickListener listener) { - return setNegativeButton(context.getString(label), listener); - } - public T setOnDismissListener(Callback1 listener) { this.dismissListener = listener; return (T) this; diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/IconPickerDialog.java b/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/IconPickerDialog.java index ad40d585..d1ad4b9f 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/IconPickerDialog.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/IconPickerDialog.java @@ -2,6 +2,7 @@ import static com.mrboomdev.awery.app.App.resolveAttrColor; import static com.mrboomdev.awery.app.AweryLifecycle.postRunnable; +import static com.mrboomdev.awery.platform.PlatformResourcesKt.i18n; import static com.mrboomdev.awery.util.ui.ViewUtil.dpPx; import static com.mrboomdev.awery.util.ui.ViewUtil.setOnApplyUiInsetsListener; import static com.mrboomdev.awery.util.ui.ViewUtil.setPadding; @@ -19,6 +20,8 @@ import androidx.recyclerview.widget.RecyclerView; import com.mrboomdev.awery.R; +import com.mrboomdev.awery.generated.Res; +import com.mrboomdev.awery.generated.String0_commonMainKt; import com.mrboomdev.awery.util.IconStateful; import java.util.ArrayList; @@ -36,7 +39,7 @@ public abstract class IconPickerDialog extends BaseDialogBuilder setSelectionListener(SelectionListener selectCallback) { diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/SelectionDialog.java b/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/SelectionDialog.java index 262b202a..7f39021d 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/SelectionDialog.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/ui/dialog/SelectionDialog.java @@ -2,7 +2,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; -import static com.mrboomdev.awery.app.App.i18n; +import static com.mrboomdev.awery.platform.PlatformResourcesKt.i18n; import static com.mrboomdev.awery.util.ui.ViewUtil.dpPx; import android.content.Context; @@ -72,7 +72,7 @@ private void setRadioItems(@NonNull Selection items) { for(var item : items) { var originalTitle = Selection.Selectable.getTitle(item.getKey()); - var title = Objects.requireNonNullElse(i18n(R.string.class, originalTitle), originalTitle); + var title = Objects.requireNonNullElse(i18n(originalTitle), originalTitle); var radio = new MaterialRadioButton(getContext()); radio.setText(title); @@ -146,12 +146,6 @@ public SelectionDialog setPositiveButton(String label, SelectionListener l }); } - public SelectionDialog setPositiveButton(@StringRes int label, SelectionListener listener) { - return setPositiveButton(label, dialog -> { - if(listener != null) listener.onSelected(this, getSelection()); - }); - } - public Selection getSelection() { if(items == null) { return Selection.empty(); diff --git a/androidApp/src/main/java/com/mrboomdev/awery/util/ui/fields/EditTextField.java b/androidApp/src/main/java/com/mrboomdev/awery/util/ui/fields/EditTextField.java index e0a989ee..2d467baf 100644 --- a/androidApp/src/main/java/com/mrboomdev/awery/util/ui/fields/EditTextField.java +++ b/androidApp/src/main/java/com/mrboomdev/awery/util/ui/fields/EditTextField.java @@ -26,11 +26,6 @@ public class EditTextField extends FancyField { private int type = EditorInfo.TYPE_CLASS_TEXT; private int lines; - public EditTextField(@NonNull Context context, @StringRes int hint) { - this.hint = ContextCompat.getString(context, hint); - this.context = context; - } - public EditTextField(Context context, String hint) { this.hint = hint; this.context = context; @@ -48,10 +43,6 @@ public void setHint(String hint) { } } - public void setError(@StringRes int res) { - setError(context.getString(res)); - } - public void setError(@Nullable String error) { this.error = error; diff --git a/androidApp/src/main/kotlin/com/mrboomdev/awery/app/AweryLocales.kt b/androidApp/src/main/kotlin/com/mrboomdev/awery/app/AweryLocales.kt index 4fffb37a..de206688 100644 --- a/androidApp/src/main/kotlin/com/mrboomdev/awery/app/AweryLocales.kt +++ b/androidApp/src/main/kotlin/com/mrboomdev/awery/app/AweryLocales.kt @@ -7,8 +7,9 @@ import androidx.core.os.LocaleListCompat import com.mrboomdev.awery.R import com.mrboomdev.awery.app.App.Companion.getResourceId import com.mrboomdev.awery.app.AweryLifecycle.Companion.restartApp +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.Selection -import com.mrboomdev.awery.util.extensions.letWith import com.mrboomdev.awery.util.ui.dialog.SelectionDialog import org.xmlpull.v1.XmlPullParser import java.util.Locale @@ -16,31 +17,29 @@ import java.util.Locale object AweryLocales { private const val ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android" - fun translateCountryName(context: Context, input: String): String { + fun i18nCountryName(input: String): String { return when(input.lowercase(Locale.ROOT)) { - "us", "usa" -> context.getString(R.string.us) - "china", "cn", "ch", "chinese", "zh" -> context.getString(R.string.china) - "ja", "jp", "japan", "jpn", "jap" -> context.getString(R.string.japan) - "ru", "russia", "rus" -> context.getString(R.string.russia) - "ko", "korea", "kor", "kr" -> context.getString(R.string.korea) - - else -> Locale.forLanguageTag(input).letWith { - displayCountry.replaceFirstChar { it.uppercase(this) } - } + "us", "usa" -> Locale.US + "china", "cn", "ch", "chinese", "zh" -> Locale.CHINA + "ja", "jp", "japan", "jpn", "jap" -> Locale.JAPAN + "ru", "russia", "rus" -> Locale.forLanguageTag("ru") + "ko", "korea", "kor", "kr" -> Locale.KOREA + else -> Locale.forLanguageTag(input) + }.let { locale -> + locale.displayCountry.replaceFirstChar { it.uppercase(locale) } } } - fun translateLangName(context: Context, input: String): String { + fun i18nLanguageName(input: String): String { return when(input.lowercase(Locale.ROOT)) { - "en", "us-US", "eng", "english" -> context.getString(R.string.english) - "zh", "chs", "chinese" -> context.getString(R.string.chinese) - "ja", "jp", "japanese" -> context.getString(R.string.japanese) - "ru", "rus", "russian" -> context.getString(R.string.russian) - "ko", "kor", "korean" -> context.getString(R.string.korean) - - else -> Locale.forLanguageTag(input).letWith { - displayLanguage.replaceFirstChar { it.uppercase(this) } - } + "en", "us-US", "eng", "english" -> Locale.ENGLISH + "zh", "chs", "chinese" -> Locale.CHINESE + "ja", "jp", "japanese" -> Locale.JAPANESE + "ru", "rus", "russian" -> Locale.forLanguageTag("ru") + "ko", "kor", "korean" -> Locale.KOREAN + else -> Locale.forLanguageTag(input) + }.let { locale -> + locale.displayLanguage.replaceFirstChar { it.uppercase(locale) } } } @@ -73,8 +72,8 @@ object AweryLocales { SelectionDialog.single(context, Selection(availableLocales.map { Selection.Selectable(it.first, it.first.toString(), it.second, if(it.first.areMostlySame(currentLocale)) Selection.State.SELECTED else Selection.State.UNSELECTED) - })).setTitle(R.string.select_language) - .setPositiveButton(R.string.save) { dialog, selection -> + })).setTitle(i18n(Res.string.select_language)) + .setPositiveButton(i18n(Res.string.save)) { dialog, selection -> selection.get(Selection.State.SELECTED)?.let { AppCompatDelegate.setApplicationLocales(LocaleListCompat.create(it.item)) restartApp() @@ -82,7 +81,7 @@ object AweryLocales { dialog.dismiss() } - .setNegativeButton(R.string.cancel) { it.dismiss() } + .setNegativeButton(i18n(Res.string.cancel)) { it.dismiss() } .show() } @@ -90,7 +89,7 @@ object AweryLocales { return mutableListOf>().apply { // All locales are being stored in this little file. // It is being auto-generated, so we need to use some reflection. - val fileId = getResourceId("_generated_res_locale_config") + val fileId = getResourceId(R.xml::class.java, "_generated_res_locale_config") context.resources.getXml(fileId).use { while(it.eventType != XmlPullParser.END_DOCUMENT) { @@ -100,7 +99,9 @@ object AweryLocales { XmlPullParser.START_TAG -> { if(it.name == "locale") { val value = it.getAttributeValue(ANDROID_NAMESPACE, "name") - add(MutablePair(Locale.forLanguageTag(value), translateLangName(context, value))) + add(MutablePair(Locale.forLanguageTag(value), i18nLanguageName( + value + ))) } } } diff --git a/androidApp/src/main/kotlin/com/mrboomdev/awery/app/ExtensionsManager.kt b/androidApp/src/main/kotlin/com/mrboomdev/awery/app/ExtensionsManager.kt index 56d08f15..d556ff11 100644 --- a/androidApp/src/main/kotlin/com/mrboomdev/awery/app/ExtensionsManager.kt +++ b/androidApp/src/main/kotlin/com/mrboomdev/awery/app/ExtensionsManager.kt @@ -2,17 +2,17 @@ package com.mrboomdev.awery.app import android.annotation.SuppressLint import android.content.Context -import com.mrboomdev.awery.R import com.mrboomdev.awery.app.App.Companion.database -import com.mrboomdev.awery.data.settings.NicePreferences.getPrefs import com.mrboomdev.awery.ext.data.CatalogFeed import com.mrboomdev.awery.ext.data.CatalogSearchResults import com.mrboomdev.awery.ext.data.Setting import com.mrboomdev.awery.ext.source.AbstractSource import com.mrboomdev.awery.ext.source.Source import com.mrboomdev.awery.ext.source.SourcesManager +import com.mrboomdev.awery.ext.util.exceptions.ZeroResultsException +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.sources.BootstrapManager -import com.mrboomdev.awery.util.exceptions.ZeroResultsException import kotlinx.coroutines.channels.SendChannel import kotlinx.coroutines.flow.channelFlow import kotlin.reflect.KClass @@ -49,7 +49,7 @@ object ExtensionsManager { if(media.isEmpty()) { channel.send(CatalogFeed.Loaded( - throwable = ZeroResultsException("No bookmarks", R.string.no_media_found), + throwable = ZeroResultsException("No bookmarks", i18n(Res.string.no_media_found)), feed = CatalogFeed( title = list.name, hideIfEmpty = true @@ -146,7 +146,8 @@ object ExtensionsManager { * @author MrBoomDev */ fun SourcesManager.setEnabled(sourceId: String, enable: Boolean) { - getPrefs().setValue("ext_${context.id}_${sourceId}", enable).saveSync() + PlatformPreferences["ext_${context.id}_${sourceId}"] = enable + PlatformPreferences.save() } /** @@ -154,9 +155,7 @@ object ExtensionsManager { * This function just checks the settings and doesn't check if an extension is loaded or not. * @author MrBoomDev */ - fun SourcesManager.isEnabled(sourceId: String): Boolean { - return getPrefs().getBoolean("ext_${context.id}_${sourceId}", true) - } + fun SourcesManager.isEnabled(sourceId: String) = PlatformPreferences.getBoolean("ext_${context.id}_${sourceId}") ?: true private fun SourcesManager.getAllManagers(): List { return mutableListOf().apply { diff --git a/androidApp/src/main/kotlin/com/mrboomdev/awery/app/services/BackupService.kt b/androidApp/src/main/kotlin/com/mrboomdev/awery/app/services/BackupService.kt index 22adc360..d20a4a3d 100644 --- a/androidApp/src/main/kotlin/com/mrboomdev/awery/app/services/BackupService.kt +++ b/androidApp/src/main/kotlin/com/mrboomdev/awery/app/services/BackupService.kt @@ -10,6 +10,8 @@ import com.mrboomdev.awery.app.App.Companion.toast import com.mrboomdev.awery.app.AweryLifecycle.Companion.restartApp import com.mrboomdev.awery.app.AweryLifecycle.Companion.runOnUiThread import com.mrboomdev.awery.app.CrashHandler +import com.mrboomdev.awery.generated.* +import com.mrboomdev.awery.platform.i18n import com.mrboomdev.awery.util.FileType import com.mrboomdev.awery.util.io.unzipFiles import com.mrboomdev.awery.util.io.zipFiles @@ -71,7 +73,7 @@ class BackupService : SafeArgsService() { else -> TODO("Unsupported backup type: $fileType") } - toast(R.string.backup_success) + toast(i18n(Res.string.backup_success)) runOnUiThread { popup.dismiss() } stopSelf() } @@ -97,7 +99,7 @@ class BackupService : SafeArgsService() { else -> TODO("Unsupported restore type: $fileType") } - toast(R.string.restore_success) + toast(i18n(Res.string.restore_success)) restartApp() stopSelf() } diff --git a/androidApp/src/main/kotlin/com/mrboomdev/awery/platform/PlatformSettingHandler.kt b/androidApp/src/main/kotlin/com/mrboomdev/awery/platform/PlatformSettingHandler.kt index 50d1a2b3..781e6535 100644 --- a/androidApp/src/main/kotlin/com/mrboomdev/awery/platform/PlatformSettingHandler.kt +++ b/androidApp/src/main/kotlin/com/mrboomdev/awery/platform/PlatformSettingHandler.kt @@ -17,19 +17,19 @@ import com.mrboomdev.awery.app.update.UpdatesManager import com.mrboomdev.awery.app.update.UpdatesManager.showUpdateDialog import com.mrboomdev.awery.data.Constants import com.mrboomdev.awery.data.Constants.DIRECTORY_IMAGE_CACHE -import com.mrboomdev.awery.generated.AwerySettings +import com.mrboomdev.awery.generated.* import com.mrboomdev.awery.ui.mobile.screens.settings.AboutActivity import com.mrboomdev.awery.ui.mobile.screens.setup.SetupActivity import com.mrboomdev.awery.util.ContentType import com.mrboomdev.awery.util.exceptions.explain -import com.mrboomdev.awery.util.extensions.activity -import com.mrboomdev.awery.util.extensions.hasPermission -import com.mrboomdev.awery.util.extensions.requestPermission -import com.mrboomdev.awery.util.extensions.startActivity -import com.mrboomdev.awery.util.extensions.startActivityForResult -import com.mrboomdev.awery.util.extensions.startService import com.mrboomdev.awery.util.extensions.toChooser import com.mrboomdev.awery.util.ui.dialog.DialogBuilder +import com.mrboomdev.awery.utils.activity +import com.mrboomdev.awery.utils.buildIntent +import com.mrboomdev.awery.utils.getPackageUri +import com.mrboomdev.awery.utils.hasPermission +import com.mrboomdev.awery.utils.requestPermission +import com.mrboomdev.awery.utils.startActivityForResult import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope @@ -43,7 +43,7 @@ import kotlin.concurrent.thread object PlatformSettingHandler { private const val TAG = "PlatformSettingHandler" - fun handlePlatformClick(context: Context, setting: PlatformSetting) { + fun handlePlatformClick(context: Context, setting: PlatformSetting): Unit = with(context) { when(setting.key) { AwerySettings.TRY_CRASH_NATIVE.key -> XCrash.testNativeCrash(false) @@ -58,36 +58,36 @@ object PlatformSettingHandler { thread { XCrash.testJavaCrash(false) } AwerySettings.ABOUT.key -> - context.startActivity(AboutActivity::class) + startActivity(buildIntent(AboutActivity::class)) AwerySettings.START_ONBOARDING.key -> - context.startActivity(SetupActivity::class) + startActivity(buildIntent(SetupActivity::class)) AwerySettings.UI_LANGUAGE.key -> AweryLocales.showPicker(context) AwerySettings.PLAYER_SYSTEM_SUBTITLES.key -> - context.startActivity(action = Settings.ACTION_CAPTIONING_SETTINGS) + startActivity(buildIntent(Settings.ACTION_CAPTIONING_SETTINGS)) AwerySettings.SETUP_THEME.key -> - context.startActivity(SetupActivity::class, extras = mapOf( - SetupActivity.EXTRA_STEP to SetupActivity.STEP_THEMING, - SetupActivity.EXTRA_FINISH_ON_COMPLETE to true - )) + startActivity(buildIntent(SetupActivity::class, SetupActivity.Extras( + step = SetupActivity.STEP_THEMING, + finishOnComplete = true + ))) AwerySettings.CLEAR_IMAGE_CACHE.key -> { File(context.cacheDir, DIRECTORY_IMAGE_CACHE).deleteRecursively() - toast(R.string.cleared_successfully) + toast(i18n(Res.string.cleared_successfully)) } AwerySettings.CLEAR_WEBVIEW_CACHE.key -> { File(context.cacheDir, Constants.DIRECTORY_WEBVIEW_CACHE).deleteRecursively() - toast(R.string.cleared_successfully) + toast(i18n(Res.string.cleared_successfully)) } AwerySettings.CLEAR_NET_CACHE.key -> { File(context.cacheDir, Constants.DIRECTORY_NET_CACHE).deleteRecursively() - toast(R.string.cleared_successfully) + toast(i18n(Res.string.cleared_successfully)) } AwerySettings.BACKUP.key -> { @@ -124,37 +124,34 @@ object PlatformSettingHandler { DialogBuilder(context).apply { setTitle("Permission required!") setMessage("Sorry, but you cannot create files without an storage permission.") - setNegativeButton(R.string.dismiss) { dismiss() } + setNegativeButton(i18n(Res.string.dismiss)) { dismiss() } setPositiveButton("Open settings") { - context.startActivity( - action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS, - data = Uri.parse("package:${context.packageName}") - ) - + startActivity(buildIntent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, getPackageUri())) dismiss() } }.show() } }) - return + return@with } - activity.startActivityForResult( + activity.startActivityForResult(buildIntent( action = Intent.ACTION_CREATE_DOCUMENT, - type = ContentType.ANY.mimeType, - categories = arrayOf(Intent.CATEGORY_OPENABLE), - extras = mapOf(Intent.EXTRA_TITLE to fileName), - callback = { resultCode, result -> - if(resultCode != Activity.RESULT_OK) { - return@startActivityForResult - } + type = ContentType.ANY.mimeType + ) { + addCategory(Intent.CATEGORY_OPENABLE) + putExtra(Intent.EXTRA_TITLE, fileName) + }, { resultCode, result -> + if(resultCode != Activity.RESULT_OK) { + return@startActivityForResult + } - context.startService( - BackupService::class, BackupService.Args( - BackupService.Action.BACKUP, result!!.data!!)) - }) + startService(buildIntent( + BackupService::class, BackupService.Args( + BackupService.Action.BACKUP, result!!.data!!))) + }) } AwerySettings.RESTORE.key -> { @@ -170,13 +167,13 @@ object PlatformSettingHandler { DialogBuilder(context).apply { setTitle("Permission required!") setMessage("Sorry, but you cannot select files without an storage permission.") - setNegativeButton(R.string.dismiss) { dismiss() } + setNegativeButton(i18n(Res.string.dismiss)) { dismiss() } setPositiveButton("Open settings") { - context.startActivity( - action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS, - data = Uri.parse("package:${context.packageName}") - ) + startActivity(buildIntent( + Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Uri.parse("package:${context.packageName}") + )) dismiss() } @@ -192,9 +189,8 @@ object PlatformSettingHandler { }.toChooser("Choose a backup file"), { resultCode, result -> if(resultCode != Activity.RESULT_OK) return@startActivityForResult - context.startService( - BackupService::class, BackupService.Args( - BackupService.Action.RESTORE, result!!.data!!)) + startService(buildIntent(BackupService::class, BackupService.Args( + BackupService.Action.RESTORE, result!!.data!!))) }) } @@ -216,7 +212,7 @@ object PlatformSettingHandler { CrashHandler.showDialog( title = "Failed to check for updates", - messagePrefixRes = R.string.please_report_bug_app, + messagePrefix = i18n(Res.string.please_report_bug_app), throwable = t) }).launch { val update = UpdatesManager.fetchLatestAppUpdate() diff --git a/androidApp/src/main/res/layout-land/feed_featured_item.xml b/androidApp/src/main/res/layout-land/feed_featured_item.xml index 08de5302..c79eecd6 100644 --- a/androidApp/src/main/res/layout-land/feed_featured_item.xml +++ b/androidApp/src/main/res/layout-land/feed_featured_item.xml @@ -80,7 +80,7 @@ android:id="@+id/description" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="@string/app_name" + android:text="app_name" android:textSize="15sp" android:alpha=".95" android:shadowColor="#000000" @@ -151,7 +151,7 @@ android:layout_marginBottom="16dp" app:icon="@drawable/ic_round_play_arrow_24" app:iconSize="26dp" - android:text="@string/watch_now" /> + android:text="watch_now" /> + android:contentDescription="app_name" /> @@ -32,7 +32,7 @@ android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:fontFamily="@font/century_gothic_bold" - android:text="@string/app_name" + android:text="app_name" android:textAppearance="@style/TextAppearance.Material3.TitleLarge" app:layout_constraintBottom_toBottomOf="@id/logo" app:layout_constraintLeft_toRightOf="@id/logo" @@ -65,7 +65,7 @@ android:visibility="gone" tools:visibility="visible" android:src="@drawable/ic_search" - android:contentDescription="@string/search" /> + android:contentDescription="search" /> + android:contentDescription="settings" /> + android:contentDescription="account" /> diff --git a/androidApp/src/main/res/layout-land/layout_media_details.xml b/androidApp/src/main/res/layout-land/layout_media_details.xml index d6f63b92..59fc34bb 100644 --- a/androidApp/src/main/res/layout-land/layout_media_details.xml +++ b/androidApp/src/main/res/layout-land/layout_media_details.xml @@ -62,7 +62,7 @@ app:iconPadding="8dp" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/watch" + android:text="watch" android:paddingRight="36dp" android:layout_marginRight="8dp"> @@ -79,7 +79,7 @@ app:iconSize="25dp" app:iconPadding="8dp" app:icon="@drawable/ic_sync" - android:text="@string/tracking" /> + android:text="tracking" /> @@ -88,7 +88,7 @@ android:id="@+id/continueButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/continue_action" + android:text="continue_action" android:paddingHorizontal="32dp" android:layout_marginLeft="16dp" android:layout_marginTop="8dp" /> diff --git a/androidApp/src/main/res/layout/feed_featured_item.xml b/androidApp/src/main/res/layout/feed_featured_item.xml index c0347b39..c37fdeef 100644 --- a/androidApp/src/main/res/layout/feed_featured_item.xml +++ b/androidApp/src/main/res/layout/feed_featured_item.xml @@ -90,13 +90,14 @@ android:maxLines="2" android:shadowColor="#000000" android:shadowRadius="2" - android:text="@string/app_name" + android:text="Awery" android:textSize="16sp" android:ellipsize="end" app:layout_constraintBottom_toTopOf="@id/meta" app:layout_constraintLeft_toRightOf="@id/left_side_barrier" app:layout_constraintRight_toLeftOf="@id/right_side_barrier" - tools:text="@tools:sample/lorem/random" /> + tools:text="@tools:sample/lorem/random" + tools:ignore="HardcodedText" /> diff --git a/androidApp/src/main/res/layout/layout_comments_header.xml b/androidApp/src/main/res/layout/layout_comments_header.xml index 57c35a5d..2b1feddd 100644 --- a/androidApp/src/main/res/layout/layout_comments_header.xml +++ b/androidApp/src/main/res/layout/layout_comments_header.xml @@ -32,10 +32,10 @@ android:layout_height="wrap_content" app:layout_flexGrow="1" android:layout_marginRight="8dp" - android:hint="@string/source"> + android:hint="Source"> + android:hint="Season"> + android:hint="Episode"> + android:hint="Search"> + android:contentDescription="Awery" /> @@ -32,7 +32,7 @@ android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:fontFamily="@font/century_gothic_bold" - android:text="@string/app_name" + android:text="Awery" android:textAppearance="@style/TextAppearance.Material3.TitleLarge" app:layout_constraintBottom_toBottomOf="@id/logo" app:layout_constraintLeft_toRightOf="@id/logo" @@ -48,7 +48,7 @@ android:layout_width="42dp" android:layout_height="42dp" android:src="@drawable/ic_search" - android:contentDescription="@string/search" /> + android:contentDescription="Search" /> + android:contentDescription="Settings" /> + android:contentDescription="Account" /> diff --git a/androidApp/src/main/res/layout/layout_header_search.xml b/androidApp/src/main/res/layout/layout_header_search.xml index 9ecf8c79..23025aa9 100644 --- a/androidApp/src/main/res/layout/layout_header_search.xml +++ b/androidApp/src/main/res/layout/layout_header_search.xml @@ -20,7 +20,7 @@ app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" android:src="@drawable/ic_back" - android:contentDescription="@string/back" /> + android:contentDescription="Back" /> + android:contentDescription="Clear" /> + android:contentDescription="Filter" /> @@ -68,7 +68,7 @@ app:icon="@drawable/ic_sync" app:iconSize="25dp" app:iconPadding="8dp" - android:text="@string/tracking" /> + android:text="Tracking" /> diff --git a/androidApp/src/main/res/layout/layout_watch_variants.xml b/androidApp/src/main/res/layout/layout_watch_variants.xml index 3bc0cf29..eafcb992 100644 --- a/androidApp/src/main/res/layout/layout_watch_variants.xml +++ b/androidApp/src/main/res/layout/layout_watch_variants.xml @@ -48,10 +48,10 @@ android:layout_height="wrap_content" app:layout_flexGrow="1" android:layout_marginRight="8dp" - android:hint="@string/source"> + android:hint="source"> + android:hint="season"> + android:hint="variant"> + android:hint="search"> + android:contentDescription="back" />