refactor: Migrate i18n to use Moko Resources (#110)

* fix(deps): "String index out of range" compile error

REF: https://github.com/icerockdev/moko-resources/issues/732

* refactor(i18n): Simplify gradle

* refactor: Migrate i18n files to moko-resources

Also split plurals to their own files

* fix: Only use firebase on releases

* revert: Revert "fix: Only use firebase on releases"

This reverts commit e4f40b450a.

* ci: Just build standard release

* refactor: Fully migrate to Moko Resources for i18n
This commit is contained in:
Ahmad Ansori Palembani 2024-06-24 13:46:42 +07:00 committed by GitHub
parent dc0a3c3274
commit 875100dd6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
398 changed files with 9369 additions and 7386 deletions

View file

@ -33,8 +33,7 @@ jobs:
cp .github/runner-files/ci-gradle.properties ~/.gradle/gradle.properties
- name: Build and run tests
if: startsWith(env.VERSION_TAG, 'r') != true && startsWith(env.VERSION_TAG, 'v') != true
run: ./gradlew assembleDevDebug testDevDebugUnitTest assembleStandardRelease
run: ./gradlew assembleStandardRelease testStandardReleaseUnitTest
- name: Publish test report
uses: mikepenz/action-junit-report@v4
@ -44,15 +43,6 @@ jobs:
detailed_summary: true
report_paths: '**/build/test-results/test*/TEST-*.xml'
- name: Run tests against release variant
if: startsWith(env.VERSION_TAG, 'r') != true && startsWith(env.VERSION_TAG, 'v') != true
run: ./gradlew testStandardReleaseUnitTest
- name: Upload debug APK to artifact
uses: actions/upload-artifact@v4
with:
path: app/build/outputs/apk/dev/debug/app*-arm64-v8a-*.apk
- name: Upload R8 APK to artifact
uses: actions/upload-artifact@v4
with:

1
.gitignore vendored
View file

@ -8,3 +8,4 @@
*.iml
*/build
*/*/build
.kotlin/

View file

@ -67,6 +67,8 @@ import yokai.core.di.PreferenceModule
import yokai.core.migration.Migrator
import yokai.core.migration.migrations.migrations
import yokai.domain.base.BasePreferences
import yokai.i18n.MR
import yokai.util.lang.getString
import java.security.Security
open class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factory {
@ -130,9 +132,9 @@ open class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.F
disableIncognitoReceiver.register()
val nContext = localeContext
val notification = nContext.notification(Notifications.CHANNEL_INCOGNITO_MODE) {
val incogText = nContext.getString(R.string.incognito_mode)
val incogText = nContext.getString(MR.strings.incognito_mode)
setContentTitle(incogText)
setContentText(nContext.getString(R.string.turn_off_, incogText))
setContentText(nContext.getString(MR.strings.turn_off_, incogText))
setSmallIcon(R.drawable.ic_incognito_24dp)
setOngoing(true)

View file

@ -25,6 +25,8 @@ import coil3.size.Precision
import coil3.size.Scale
import coil3.transform.RoundedCornersTransformation
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import eu.kanade.tachiyomi.appwidget.components.CoverHeight
import eu.kanade.tachiyomi.appwidget.components.CoverWidth
import eu.kanade.tachiyomi.appwidget.components.LockedWidget

View file

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.appwidget.components
import android.content.Intent
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.glance.GlanceModifier
@ -16,12 +17,14 @@ import androidx.glance.text.TextAlign
import androidx.glance.text.TextStyle
import androidx.glance.unit.ColorProvider
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import eu.kanade.tachiyomi.appwidget.ContainerModifier
import eu.kanade.tachiyomi.appwidget.util.stringResource
import eu.kanade.tachiyomi.ui.main.MainActivity
@Composable
fun LockedWidget() {
val context = LocalContext.current
val intent = Intent(LocalContext.current, Class.forName(MainActivity.MAIN_ACTIVITY)).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
@ -33,9 +36,9 @@ fun LockedWidget() {
contentAlignment = Alignment.Center,
) {
Text(
text = stringResource(R.string.appwidget_unavailable_locked),
text = stringResource(MR.strings.appwidget_unavailable_locked),
style = TextStyle(
color = ColorProvider(R.color.appwidget_on_secondary_container),
color = ColorProvider(Color(context.getColor(R.color.appwidget_on_secondary_container))),
fontSize = 12.sp,
textAlign = TextAlign.Center,
),

View file

@ -11,6 +11,8 @@ import androidx.glance.layout.ContentScale
import androidx.glance.layout.fillMaxSize
import androidx.glance.layout.size
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import eu.kanade.tachiyomi.appwidget.util.appWidgetInnerRadius
val CoverWidth = 58.dp

View file

@ -18,6 +18,8 @@ import androidx.glance.layout.fillMaxWidth
import androidx.glance.layout.padding
import androidx.glance.text.Text
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import eu.kanade.tachiyomi.appwidget.ContainerModifier
import eu.kanade.tachiyomi.appwidget.util.calculateRowAndColumnCount
import eu.kanade.tachiyomi.appwidget.util.stringResource
@ -37,7 +39,7 @@ fun UpdatesWidget(data: List<Pair<Long, Bitmap?>>?) {
if (data == null) {
CircularProgressIndicator()
} else if (data.isEmpty()) {
Text(text = stringResource(R.string.no_recent_read_updated_manga))
Text(text = stringResource(MR.strings.no_recent_read_updated_manga))
} else {
(0 until rowCount).forEach { i ->
val coverRow = (0 until columnCount).mapNotNull { j ->

View file

@ -6,7 +6,9 @@ import androidx.compose.ui.unit.DpSize
import androidx.glance.GlanceModifier
import androidx.glance.LocalContext
import androidx.glance.appwidget.cornerRadius
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.R
import yokai.util.lang.getString
fun GlanceModifier.appWidgetBackgroundRadius(): GlanceModifier {
return this.cornerRadius(R.dimen.appwidget_background_radius)
@ -16,6 +18,11 @@ fun GlanceModifier.appWidgetInnerRadius(): GlanceModifier {
return this.cornerRadius(R.dimen.appwidget_inner_radius)
}
@Composable
fun stringResource(id: StringResource): String {
return LocalContext.current.getString(id)
}
@Composable
fun stringResource(@StringRes id: Int): String {
return LocalContext.current.getString(id)

View file

@ -3,7 +3,8 @@ package eu.kanade.tachiyomi.core.storage
import android.content.Context
import android.os.Environment
import androidx.core.net.toUri
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import java.io.File
class AndroidStorageFolderProvider(
@ -13,7 +14,7 @@ class AndroidStorageFolderProvider(
override fun directory(): File {
return File(
Environment.getExternalStorageDirectory().absolutePath + File.separator +
context.getString(R.string.app_normalized_name),
context.getString(MR.strings.app_normalized_name),
)
}

View file

@ -2,12 +2,13 @@ package eu.kanade.tachiyomi.data.backup
import android.content.Context
import android.net.Uri
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.util.BackupUtil
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.i18n.MR
import yokai.util.lang.getString
class BackupFileValidator(
private val sourceManager: SourceManager = Injekt.get(),
@ -28,7 +29,7 @@ class BackupFileValidator(
}
if (backup.backupManga.isEmpty()) {
throw IllegalStateException(context.getString(R.string.backup_has_no_manga))
throw IllegalStateException(context.getString(MR.strings.backup_has_no_manga))
}
val sources = backup.backupSources.map { it.sourceId to it.name }.toMap()

View file

@ -12,6 +12,8 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notificationManager
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.util.lang.getString
import java.io.File
import java.util.concurrent.*
@ -38,7 +40,7 @@ class BackupNotifier(private val context: Context) {
fun showBackupProgress() {
val builder = with(progressNotificationBuilder) {
setContentTitle(context.getString(R.string.creating_backup))
setContentTitle(context.getString(MR.strings.creating_backup))
setProgress(0, 0, true)
setOnlyAlertOnce(true)
@ -51,7 +53,7 @@ class BackupNotifier(private val context: Context) {
context.notificationManager.cancel(Notifications.ID_BACKUP_PROGRESS)
with(completeNotificationBuilder) {
setContentTitle(context.getString(R.string.backup_failed))
setContentTitle(context.getString(MR.strings.backup_failed))
setContentText(error)
show(Notifications.ID_BACKUP_COMPLETE)
@ -62,7 +64,7 @@ class BackupNotifier(private val context: Context) {
context.notificationManager.cancel(Notifications.ID_BACKUP_PROGRESS)
with(completeNotificationBuilder) {
setContentTitle(context.getString(R.string.backup_created))
setContentTitle(context.getString(MR.strings.backup_created))
setContentText(unifile.filePath ?: unifile.name)
// Clear old actions if they exist
@ -70,7 +72,7 @@ class BackupNotifier(private val context: Context) {
addAction(
R.drawable.ic_share_24dp,
context.getString(R.string.share),
context.getString(MR.strings.share),
NotificationReceiver.shareBackupPendingBroadcast(context, unifile.uri, Notifications.ID_BACKUP_COMPLETE),
)
@ -80,7 +82,7 @@ class BackupNotifier(private val context: Context) {
fun showRestoreProgress(content: String = "", progress: Int = 0, maxAmount: Int = 100): NotificationCompat.Builder {
val builder = with(progressNotificationBuilder) {
setContentTitle(context.getString(R.string.restoring_backup))
setContentTitle(context.getString(MR.strings.restoring_backup))
if (!preferences.hideNotificationContent().get()) {
setContentText(content)
@ -94,7 +96,7 @@ class BackupNotifier(private val context: Context) {
addAction(
R.drawable.ic_close_24dp,
context.getString(R.string.stop),
context.getString(MR.strings.stop),
NotificationReceiver.cancelRestorePendingBroadcast(context, Notifications.ID_RESTORE_PROGRESS),
)
}
@ -110,7 +112,7 @@ class BackupNotifier(private val context: Context) {
context.notificationManager.cancel(Notifications.ID_RESTORE_PROGRESS)
with(completeNotificationBuilder) {
setContentTitle(context.getString(R.string.restore_error))
setContentTitle(context.getString(MR.strings.restore_error))
setContentText(error)
show(Notifications.ID_RESTORE_COMPLETE)
@ -121,7 +123,7 @@ class BackupNotifier(private val context: Context) {
context.notificationManager.cancel(Notifications.ID_RESTORE_PROGRESS)
val timeString = context.getString(
R.string.restore_duration,
MR.strings.restore_duration,
TimeUnit.MILLISECONDS.toMinutes(time),
TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(time),
@ -129,8 +131,8 @@ class BackupNotifier(private val context: Context) {
)
with(completeNotificationBuilder) {
setContentTitle(context.getString(R.string.restore_completed))
setContentText(context.resources.getQuantityString(R.plurals.restore_completed_message, errorCount, timeString, errorCount))
setContentTitle(context.getString(MR.strings.restore_completed))
setContentText(context.getString(MR.plurals.restore_completed_message, errorCount, timeString, errorCount))
// Clear old actions if they exist
clearActions()
@ -141,7 +143,7 @@ class BackupNotifier(private val context: Context) {
addAction(
R.drawable.ic_eye_24dp,
context.getString(R.string.open_log),
context.getString(MR.strings.open_log),
NotificationReceiver.openErrorOrSkippedLogPendingActivity(context, uri),
)
}

View file

@ -4,7 +4,6 @@ import android.content.Context
import android.net.Uri
import co.touchlab.kermit.Logger
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
import eu.kanade.tachiyomi.data.backup.create.creators.CategoriesBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.MangaBackupCreator
@ -22,6 +21,8 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import yokai.domain.storage.StorageManager
import yokai.i18n.MR
import yokai.util.lang.getString
import java.io.FileOutputStream
class BackupCreator(
@ -95,7 +96,7 @@ class BackupCreator(
val byteArray = parser.encodeToByteArray(Backup.serializer(), backup!!)
if (byteArray.isEmpty()) {
throw IllegalStateException(context.getString(R.string.empty_backup_error))
throw IllegalStateException(context.getString(MR.strings.empty_backup_error))
}
file.openOutputStream().also {

View file

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.data.backup.create
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
import dev.icerock.moko.resources.StringResource
import kotlinx.collections.immutable.persistentListOf
import yokai.i18n.MR
data class BackupOptions(
val libraryEntries: Boolean = true,
@ -31,72 +31,72 @@ data class BackupOptions(
companion object {
fun getOptions() = persistentListOf(
R.string.library_entries,
R.string.categories,
R.string.chapters,
R.string.tracking,
R.string.history,
R.string.app_settings,
R.string.source_settings,
R.string.custom_manga_info,
R.string.all_read_manga,
R.string.backup_private_pref,
MR.strings.library_entries,
MR.strings.categories,
MR.strings.chapters,
MR.strings.tracking,
MR.strings.history,
MR.strings.app_settings,
MR.strings.source_settings,
MR.strings.custom_manga_info,
MR.strings.all_read_manga,
MR.strings.backup_private_pref,
)
fun getEntries() = persistentListOf(
Entry(
label = R.string.library_entries,
label = MR.strings.library_entries,
getter = BackupOptions::libraryEntries,
setter = { options, enabled -> options.copy(libraryEntries = enabled) },
),
Entry(
label = R.string.categories,
label = MR.strings.categories,
getter = BackupOptions::categories,
setter = { options, enabled -> options.copy(categories = enabled) },
enabled = { it.libraryEntries },
),
Entry(
label = R.string.chapters,
label = MR.strings.chapters,
getter = BackupOptions::chapters,
setter = { options, enabled -> options.copy(chapters = enabled) },
enabled = { it.libraryEntries },
),
Entry(
label = R.string.tracking,
label = MR.strings.tracking,
getter = BackupOptions::tracking,
setter = { options, enabled -> options.copy(tracking = enabled) },
enabled = { it.libraryEntries },
),
Entry(
label = R.string.history,
label = MR.strings.history,
getter = BackupOptions::history,
setter = { options, enabled -> options.copy(history = enabled) },
enabled = { it.libraryEntries },
),
Entry(
label = R.string.custom_manga_info,
label = MR.strings.custom_manga_info,
getter = BackupOptions::customInfo,
setter = { options, enabled -> options.copy(customInfo = enabled) },
enabled = { it.libraryEntries },
),
Entry(
label = R.string.all_read_manga,
label = MR.strings.all_read_manga,
getter = BackupOptions::readManga,
setter = { options, enabled -> options.copy(readManga = enabled) },
enabled = { it.libraryEntries },
),
Entry(
label = R.string.app_settings,
label = MR.strings.app_settings,
getter = BackupOptions::appPrefs,
setter = { options, enabled -> options.copy(appPrefs = enabled) },
),
Entry(
label = R.string.source_settings,
label = MR.strings.source_settings,
getter = BackupOptions::sourcePrefs,
setter = { options, enabled -> options.copy(sourcePrefs = enabled) },
),
Entry(
label = R.string.backup_private_pref,
label = MR.strings.backup_private_pref,
getter = BackupOptions::includePrivate,
setter = { options, enabled -> options.copy(includePrivate = enabled) },
),
@ -117,7 +117,7 @@ data class BackupOptions(
}
data class Entry(
@StringRes val label: Int,
val label: StringResource,
val getter: (BackupOptions) -> Boolean,
val setter: (BackupOptions, Boolean) -> BackupOptions,
val enabled: (BackupOptions) -> Boolean = { true },

View file

@ -12,7 +12,6 @@ import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.BackupConst
import eu.kanade.tachiyomi.data.backup.BackupNotifier
import eu.kanade.tachiyomi.data.notification.Notifications
@ -21,6 +20,8 @@ import eu.kanade.tachiyomi.util.system.localeContext
import eu.kanade.tachiyomi.util.system.tryToSetForeground
import eu.kanade.tachiyomi.util.system.withIOContext
import kotlinx.coroutines.CancellationException
import yokai.i18n.MR
import yokai.util.lang.getString
class BackupRestoreJob(val context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) {
@ -47,11 +48,11 @@ class BackupRestoreJob(val context: Context, workerParams: WorkerParameters) : C
withIOContext {
try {
if (!restorer.restoreBackup(uri)) {
notifier.showRestoreError(context.getString(R.string.restoring_backup_canceled))
notifier.showRestoreError(context.getString(MR.strings.restoring_backup_canceled))
}
} catch (exception: Exception) {
if (exception is CancellationException) {
notifier.showRestoreError(context.getString(R.string.restoring_backup_canceled))
notifier.showRestoreError(context.getString(MR.strings.restoring_backup_canceled))
} else {
restorer.writeErrorLog()
notifier.showRestoreError(exception.message)

View file

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.data.backup.restore
import android.content.Context
import android.net.Uri
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.BackupNotifier
import eu.kanade.tachiyomi.data.backup.models.BackupSource
import eu.kanade.tachiyomi.data.backup.restore.restorers.CategoriesBackupRestorer
@ -12,6 +11,8 @@ import eu.kanade.tachiyomi.util.BackupUtil
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.isActive
import yokai.i18n.MR
import yokai.util.lang.getString
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
@ -65,17 +66,17 @@ class BackupRestorer(
if (backup.backupCategories.isNotEmpty()) {
categoriesBackupRestorer.restoreCategories(backup.backupCategories) {
restoreProgress += 1
showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.categories))
showRestoreProgress(restoreProgress, restoreAmount, context.getString(MR.strings.categories))
}
}
preferenceBackupRestorer.restoreAppPreferences(backup.backupPreferences) {
restoreProgress += 1
showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.app_settings))
showRestoreProgress(restoreProgress, restoreAmount, context.getString(MR.strings.app_settings))
}
preferenceBackupRestorer.restoreSourcePreferences(backup.backupSourcePreferences) {
restoreProgress += 1
showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.source_settings))
showRestoreProgress(restoreProgress, restoreAmount, context.getString(MR.strings.source_settings))
}
// Restore individual manga

View file

@ -5,7 +5,6 @@ import android.text.format.Formatter
import co.touchlab.kermit.Logger
import coil3.imageLoader
import coil3.memory.MemoryCache
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaImpl
@ -19,10 +18,12 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.i18n.MR
import yokai.util.lang.getString
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.util.concurrent.TimeUnit
import java.util.concurrent.*
/**
* Class used to create cover cache.
@ -85,7 +86,7 @@ class CoverCache(val context: Context) {
withUIContext {
context.toast(
context.getString(
R.string.deleted_,
MR.strings.deleted_,
Formatter.formatFileSize(context, deletedSize),
),
)
@ -108,7 +109,7 @@ class CoverCache(val context: Context) {
withContext(Dispatchers.Main) {
context.toast(
context.getString(
R.string.deleted_,
MR.strings.deleted_,
Formatter.formatFileSize(context, deletedSize),
),
)

View file

@ -1,9 +1,10 @@
package eu.kanade.tachiyomi.data.database.models
import android.content.Context
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.ui.library.LibrarySort
import yokai.i18n.MR
import yokai.util.lang.getString
import java.io.Serializable
interface Category : Serializable {
@ -45,8 +46,7 @@ interface Category : Serializable {
mangaSort == LibrarySort.DragAndDrop.categoryValue
) && !isDynamic
@StringRes
fun sortRes(): Int =
fun sortRes(): StringResource =
(LibrarySort.valueOf(mangaSort) ?: LibrarySort.DragAndDrop).stringRes(isDynamic)
fun changeSortTo(sort: Int) {
@ -61,7 +61,7 @@ interface Category : Serializable {
}
fun createDefault(context: Context): Category =
create(context.getString(R.string.default_value)).apply {
create(context.getString(MR.strings.default_value)).apply {
id = 0
isSystem = true
}
@ -77,7 +77,7 @@ interface Category : Serializable {
}
fun createAll(context: Context, libSort: Int, ascending: Boolean): Category =
createCustom(context.getString(R.string.all), libSort, ascending).apply {
createCustom(context.getString(MR.strings.all), libSort, ascending).apply {
id = -1
order = -1
isAlone = true

View file

@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.data.database.models
import android.content.Context
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.SourceManager
@ -138,11 +141,11 @@ interface Manga : SManga {
fun seriesType(context: Context, sourceManager: SourceManager? = null): String {
return context.getString(
when (seriesType(sourceManager = sourceManager)) {
TYPE_WEBTOON -> R.string.webtoon
TYPE_MANHWA -> R.string.manhwa
TYPE_MANHUA -> R.string.manhua
TYPE_COMIC -> R.string.comic
else -> R.string.manga
TYPE_WEBTOON -> MR.strings.webtoon
TYPE_MANHWA -> MR.strings.manhwa
TYPE_MANHUA -> MR.strings.manhua
TYPE_COMIC -> MR.strings.comic
else -> MR.strings.manga
},
).lowercase(Locale.getDefault())
}

View file

@ -13,7 +13,6 @@ import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
@ -27,6 +26,8 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.i18n.MR
import yokai.util.lang.getString
/**
* This worker is used to manage the downloader. The system can decide to stop the worker, in
@ -81,11 +82,11 @@ class DownloadJob(val context: Context, workerParams: WorkerParameters) : Corout
if (isOnline()) {
val noWifi = preferences.downloadOnlyOverWifi().get() && !isConnectedToWifi()
if (noWifi) {
downloadManager.stopDownloads(applicationContext.getString(R.string.no_wifi_connection))
downloadManager.stopDownloads(applicationContext.getString(MR.strings.no_wifi_connection))
}
!noWifi
} else {
downloadManager.stopDownloads(applicationContext.getString(R.string.no_network_connection))
downloadManager.stopDownloads(applicationContext.getString(MR.strings.no_network_connection))
false
}
}

View file

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.download
import android.content.Context
import co.touchlab.kermit.Logger
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.model.Download
@ -18,6 +17,8 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import uy.kohesive.injekt.injectLazy
import yokai.domain.download.DownloadPreferences
import yokai.i18n.MR
import yokai.util.lang.getString
/**
* This class is used to manage chapter downloads in the application. It must be instantiated once
@ -182,7 +183,7 @@ class DownloadManager(val context: Context) {
.filter { "image" in it.type.orEmpty() }
if (files.isEmpty()) {
throw Exception(context.getString(R.string.no_pages_found))
throw Exception(context.getString(MR.strings.no_pages_found))
}
return files.sortedBy { it.name }

View file

@ -19,6 +19,8 @@ import eu.kanade.tachiyomi.util.system.localeContext
import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notificationManager
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.util.lang.getString
import java.util.regex.*
import android.R as AR
@ -82,7 +84,7 @@ internal class DownloadNotifier(private val context: Context) {
// Pause action
addAction(
R.drawable.ic_pause_24dp,
context.getString(R.string.pause),
context.getString(MR.strings.pause),
NotificationReceiver.pauseDownloadsPendingBroadcast(context),
)
}
@ -97,9 +99,9 @@ internal class DownloadNotifier(private val context: Context) {
"",
)
setContentTitle("$title - $chapter".chop(30))
setContentText(context.getString(R.string.downloading))
setContentText(context.getString(MR.strings.downloading))
} else {
setContentTitle(context.getString(R.string.downloading))
setContentTitle(context.getString(MR.strings.downloading))
setContentText(null)
}
setProgress(0, 0, true)
@ -129,13 +131,13 @@ internal class DownloadNotifier(private val context: Context) {
// Pause action
addAction(
R.drawable.ic_pause_24dp,
context.getString(R.string.pause),
context.getString(MR.strings.pause),
NotificationReceiver.pauseDownloadsPendingBroadcast(context),
)
}
val downloadingProgressText =
context.localeContext.getString(R.string.downloading_progress)
context.localeContext.getString(MR.strings.downloading_progress)
.format(download.downloadedImages, download.pages!!.size)
if (preferences.hideNotificationContent().get()) {
@ -164,8 +166,8 @@ internal class DownloadNotifier(private val context: Context) {
fun onDownloadPaused() {
val context = context.localeContext
with(notification) {
setContentTitle(context.getString(R.string.paused))
setContentText(context.getString(R.string.download_paused))
setContentTitle(context.getString(MR.strings.paused))
setContentText(context.getString(MR.strings.download_paused))
setSmallIcon(R.drawable.ic_pause_24dp)
setAutoCancel(false)
setOngoing(false)
@ -177,13 +179,13 @@ internal class DownloadNotifier(private val context: Context) {
// Resume action
addAction(
R.drawable.ic_play_arrow_24dp,
context.getString(R.string.resume),
context.getString(MR.strings.resume),
NotificationReceiver.resumeDownloadsPendingBroadcast(context),
)
// Clear action
addAction(
R.drawable.ic_close_24dp,
context.getString(R.string.cancel_all),
context.getString(MR.strings.cancel_all),
NotificationReceiver.clearDownloadsPendingBroadcast(context),
)
show()
@ -201,7 +203,7 @@ internal class DownloadNotifier(private val context: Context) {
fun onWarning(reason: String) {
val context = context.localeContext
with(notification) {
setContentTitle(context.getString(R.string.downloads))
setContentTitle(context.getString(MR.strings.downloads))
setContentText(reason)
color = ContextCompat.getColor(context, R.color.secondaryTachiyomi)
setSmallIcon(R.drawable.ic_warning_white_24dp)
@ -223,11 +225,11 @@ internal class DownloadNotifier(private val context: Context) {
fun massDownloadWarning() {
val context = context.localeContext
val notification = context.notificationBuilder(Notifications.CHANNEL_DOWNLOADER) {
setContentTitle(context.getString(R.string.warning))
setContentTitle(context.getString(MR.strings.warning))
setSmallIcon(R.drawable.ic_warning_white_24dp)
setStyle(
NotificationCompat.BigTextStyle()
.bigText(context.getString(R.string.download_queue_size_warning)),
.bigText(context.getString(MR.strings.download_queue_size_warning)),
)
setContentIntent(
NotificationHandler.openUrl(
@ -262,12 +264,12 @@ internal class DownloadNotifier(private val context: Context) {
val context = context.localeContext
with(notification) {
setContentTitle(
mangaTitle?.plus(": $chapter") ?: context.getString(R.string.download_error),
mangaTitle?.plus(": $chapter") ?: context.getString(MR.strings.download_error),
)
setContentText(error ?: context.getString(R.string.could_not_download_unexpected_error))
setContentText(error ?: context.getString(MR.strings.could_not_download_unexpected_error))
setStyle(
NotificationCompat.BigTextStyle().bigText(
error ?: context.getString(R.string.could_not_download_unexpected_error),
error ?: context.getString(MR.strings.could_not_download_unexpected_error),
),
)
setSmallIcon(AR.drawable.stat_sys_warning)

View file

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.data.download
import android.content.Context
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
@ -17,6 +16,8 @@ import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.injectLazy
import yokai.domain.download.DownloadPreferences
import yokai.domain.storage.StorageManager
import yokai.i18n.MR
import yokai.util.lang.getString
/**
* This class is used to provide the directories where the downloads should be saved.
@ -56,7 +57,7 @@ class DownloadProvider(private val context: Context) {
return downloadsDir?.createDirectory(getSourceDirName(source))!!
.createDirectory(getMangaDirName(manga))!!
} catch (e: NullPointerException) {
throw Exception(context.getString(R.string.invalid_download_location))
throw Exception(context.getString(MR.strings.invalid_download_location))
}
}

View file

@ -6,7 +6,6 @@ import android.os.Looper
import co.touchlab.kermit.Logger
import com.hippo.unifile.UniFile
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter
@ -52,6 +51,8 @@ import yokai.core.metadata.COMIC_INFO_FILE
import yokai.core.metadata.ComicInfo
import yokai.core.metadata.getComicInfo
import yokai.domain.download.DownloadPreferences
import yokai.i18n.MR
import yokai.util.lang.getString
import java.io.BufferedOutputStream
import java.io.File
import java.util.zip.*
@ -336,7 +337,7 @@ class Downloader(
val chapName = download.chapter.preferredChapterName(context, download.manga, preferences)
if (availSpace != -1L && availSpace < MIN_DISK_SPACE) {
download.status = Download.State.ERROR
notifier.onError(context.getString(R.string.couldnt_download_low_space), chapName)
notifier.onError(context.getString(MR.strings.couldnt_download_low_space), chapName)
return
}
val chapterDirname = provider.getChapterDirName(download.chapter, includeId = downloadPreferences.downloadWithId().get())
@ -349,7 +350,7 @@ class Downloader(
val pages = download.source.getPageList(download.chapter)
if (pages.isEmpty()) {
throw Exception(context.getString(R.string.no_pages_found))
throw Exception(context.getString(MR.strings.no_pages_found))
}
// Don't trust index from source
val reIndexedPages = pages.mapIndexed { index, page ->
@ -549,9 +550,9 @@ class Downloader(
val filename = String.format("%03d", page.number)
val imageFile = tmpDir.listFiles()?.find { it.name.orEmpty().startsWith(filename) }
?: throw Error(context.getString(R.string.download_notifier_split_page_not_found, page.number))
?: throw Error(context.getString(MR.strings.download_notifier_split_page_not_found, page.number))
val imageFilePath = imageFile.filePath
?: throw Error(context.getString(R.string.download_notifier_split_page_not_found, page.number))
?: throw Error(context.getString(MR.strings.download_notifier_split_page_not_found, page.number))
// check if the original page was previously split before then skip.
if (imageFile.name.orEmpty().contains("__")) return true

View file

@ -21,6 +21,9 @@ import coil3.imageLoader
import coil3.request.CachePolicy
import coil3.request.ImageRequest
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
@ -349,7 +352,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
val skippedFile = writeErrorFile(
skippedUpdates,
"skipped",
context.getString(R.string.learn_why) + " - " + LibraryUpdateNotifier.HELP_SKIPPED_URL,
context.getString(MR.strings.learn_why) + " - " + LibraryUpdateNotifier.HELP_SKIPPED_URL,
).getUriCompat(context)
notifier.showUpdateSkippedNotification(skippedUpdates.map { it.key.title }, skippedFile)
}
@ -454,16 +457,16 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
return mangaToAdd.filter { manga ->
when {
MANGA_NON_COMPLETED in restrictions && manga.status == SManga.COMPLETED -> {
skippedUpdates[manga] = context.getString(R.string.skipped_reason_completed)
skippedUpdates[manga] = context.getString(MR.strings.skipped_reason_completed)
}
MANGA_HAS_UNREAD in restrictions && manga.unread != 0 -> {
skippedUpdates[manga] = context.getString(R.string.skipped_reason_not_caught_up)
skippedUpdates[manga] = context.getString(MR.strings.skipped_reason_not_caught_up)
}
MANGA_NON_READ in restrictions && manga.totalChapters > 0 && !manga.hasRead -> {
skippedUpdates[manga] = context.getString(R.string.skipped_reason_not_started)
skippedUpdates[manga] = context.getString(MR.strings.skipped_reason_not_started)
}
manga.update_strategy != UpdateStrategy.ALWAYS_UPDATE -> {
skippedUpdates[manga] = context.getString(R.string.skipped_reason_not_always_update)
skippedUpdates[manga] = context.getString(MR.strings.skipped_reason_not_always_update)
}
else -> {
return@filter true

View file

@ -19,6 +19,9 @@ import coil3.request.ImageRequest
import coil3.request.transformations
import coil3.transform.CircleCropTransformation
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.database.models.Manga
@ -61,7 +64,7 @@ class LibraryUpdateNotifier(private val context: Context) {
*/
val progressNotificationBuilder by lazy {
context.notificationBuilder(Notifications.CHANNEL_LIBRARY_PROGRESS) {
setContentTitle(context.getString(R.string.updating_library))
setContentTitle(context.getString(MR.strings.updating_library))
setSmallIcon(R.drawable.ic_refresh_24dp)
setLargeIcon(notificationBitmap)
setOngoing(true)
@ -83,7 +86,7 @@ class LibraryUpdateNotifier(private val context: Context) {
context.notificationManager.notify(
Notifications.ID_LIBRARY_PROGRESS,
progressNotificationBuilder
.setContentTitle("${context.getString(R.string.updating_library)} (${current + 1}/$total)")
.setContentTitle("${context.getString(MR.strings.updating_library)} (${current + 1}/$total)")
.setContentText(if (preferences.hideNotificationContent().get()) null else manga.title)
.setProgress(total, current, false)
.build(),
@ -104,8 +107,8 @@ class LibraryUpdateNotifier(private val context: Context) {
context.notificationManager.notify(
Notifications.ID_LIBRARY_ERROR,
context.notificationBuilder(Notifications.CHANNEL_LIBRARY_ERROR) {
setContentTitle(context.getString(R.string.notification_update_error, errors.size))
setContentText(context.getString(R.string.tap_to_see_details))
setContentTitle(context.getString(MR.strings.notification_update_error, errors.size))
setContentText(context.getString(MR.strings.tap_to_see_details))
setStyle(
NotificationCompat.BigTextStyle().bigText(
errors.joinToString("\n") {
@ -117,7 +120,7 @@ class LibraryUpdateNotifier(private val context: Context) {
setSmallIcon(R.drawable.ic_yokai)
addAction(
R.drawable.ic_file_open_24dp,
context.getString(R.string.open_log),
context.getString(MR.strings.open_log),
pendingIntent,
)
}
@ -139,8 +142,8 @@ class LibraryUpdateNotifier(private val context: Context) {
context.notificationManager.notify(
Notifications.ID_LIBRARY_SKIPPED,
context.notificationBuilder(Notifications.CHANNEL_LIBRARY_SKIPPED) {
setContentTitle(context.getString(R.string.notification_update_skipped, skips.size))
setContentText(context.getString(R.string.tap_to_learn_more))
setContentTitle(context.getString(MR.strings.notification_update_skipped, skips.size))
setContentText(context.getString(MR.strings.tap_to_learn_more))
setStyle(
NotificationCompat.BigTextStyle().bigText(
skips.joinToString("\n") {
@ -152,12 +155,12 @@ class LibraryUpdateNotifier(private val context: Context) {
setSmallIcon(R.drawable.ic_yokai)
addAction(
R.drawable.ic_file_open_24dp,
context.getString(R.string.open_log),
context.getString(MR.strings.open_log),
NotificationReceiver.openErrorOrSkippedLogPendingActivity(context, uri),
)
addAction(
R.drawable.ic_help_outline_24dp,
context.getString(R.string.learn_why),
context.getString(MR.strings.learn_why),
NotificationHandler.openUrl(context, HELP_SKIPPED_URL),
)
}
@ -205,8 +208,8 @@ class LibraryUpdateNotifier(private val context: Context) {
color = ContextCompat.getColor(context, R.color.secondaryTachiyomi)
val chaptersNames = if (chapterNames.size > MAX_CHAPTERS) {
"${chapterNames.take(MAX_CHAPTERS - 1).joinToString(", ")}, " +
context.resources.getQuantityString(
R.plurals.notification_and_n_more,
context.getString(
MR.plurals.notification_and_n_more,
(chapterNames.size - (MAX_CHAPTERS - 1)),
(chapterNames.size - (MAX_CHAPTERS - 1)),
)
@ -226,7 +229,7 @@ class LibraryUpdateNotifier(private val context: Context) {
)
addAction(
R.drawable.ic_eye_24dp,
context.getString(R.string.mark_as_read),
context.getString(MR.strings.mark_as_read),
NotificationReceiver.markAsReadPendingBroadcast(
context,
manga,
@ -236,7 +239,7 @@ class LibraryUpdateNotifier(private val context: Context) {
)
addAction(
R.drawable.ic_book_24dp,
context.getString(R.string.view_chapters),
context.getString(MR.strings.view_chapters),
NotificationReceiver.openChapterPendingActivity(
context,
manga,
@ -262,12 +265,12 @@ class LibraryUpdateNotifier(private val context: Context) {
context.notification(Notifications.CHANNEL_NEW_CHAPTERS) {
setSmallIcon(R.drawable.ic_yokai)
setLargeIcon(notificationBitmap)
setContentTitle(context.getString(R.string.new_chapters_found))
setContentTitle(context.getString(MR.strings.new_chapters_found))
color = ContextCompat.getColor(context, R.color.secondaryTachiyomi)
if (updates.size > 1) {
setContentText(
context.resources.getQuantityString(
R.plurals.for_n_titles,
context.getString(
MR.plurals.for_n_titles,
updates.size,
updates.size,
),
@ -303,9 +306,9 @@ class LibraryUpdateNotifier(private val context: Context) {
fun showQueueSizeWarningNotification() {
val notification = context.notificationBuilder(Notifications.CHANNEL_LIBRARY_PROGRESS) {
setContentTitle(context.getString(R.string.warning))
setContentTitle(context.getString(MR.strings.warning))
setSmallIcon(R.drawable.ic_warning_white_24dp)
setStyle(NotificationCompat.BigTextStyle().bigText(context.getString(R.string.notification_size_warning)))
setStyle(NotificationCompat.BigTextStyle().bigText(context.getString(MR.strings.notification_size_warning)))
setContentIntent(NotificationHandler.openUrl(context, HELP_WARNING_URL))
setTimeoutAfter(30000)
}

View file

@ -8,6 +8,9 @@ import android.content.Context
import android.os.Build
import androidx.core.app.NotificationManagerCompat
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.util.system.notificationManager
/**
@ -105,25 +108,25 @@ object Notifications {
listOf(
NotificationChannelGroup(
GROUP_BACKUP_RESTORE,
context.getString(R.string.backup_and_restore),
context.getString(MR.strings.backup_and_restore),
),
NotificationChannelGroup(
GROUP_EXTENSION_UPDATES,
context.getString(R.string.extension_updates),
context.getString(MR.strings.extension_updates),
),
NotificationChannelGroup(GROUP_APP_UPDATES, context.getString(R.string.app_updates)),
NotificationChannelGroup(GROUP_LIBRARY, context.getString(R.string.library)),
NotificationChannelGroup(GROUP_APP_UPDATES, context.getString(MR.strings.app_updates)),
NotificationChannelGroup(GROUP_LIBRARY, context.getString(MR.strings.library)),
).forEach(context.notificationManager::createNotificationChannelGroup)
val channels = listOf(
NotificationChannel(
CHANNEL_COMMON,
context.getString(R.string.common),
context.getString(MR.strings.common),
NotificationManager.IMPORTANCE_LOW,
),
NotificationChannel(
CHANNEL_LIBRARY_PROGRESS,
context.getString(R.string.updating_library),
context.getString(MR.strings.updating_library),
NotificationManager.IMPORTANCE_LOW,
).apply {
group = GROUP_LIBRARY
@ -131,7 +134,7 @@ object Notifications {
},
NotificationChannel(
CHANNEL_LIBRARY_ERROR,
context.getString(R.string.channel_errors),
context.getString(MR.strings.channel_errors),
NotificationManager.IMPORTANCE_LOW,
).apply {
group = GROUP_LIBRARY
@ -139,7 +142,7 @@ object Notifications {
},
NotificationChannel(
CHANNEL_LIBRARY_SKIPPED,
context.getString(R.string.channel_skipped),
context.getString(MR.strings.channel_skipped),
NotificationManager.IMPORTANCE_LOW,
).apply {
group = GROUP_LIBRARY
@ -147,28 +150,28 @@ object Notifications {
},
NotificationChannel(
CHANNEL_DOWNLOADER,
context.getString(R.string.downloads),
context.getString(MR.strings.downloads),
NotificationManager.IMPORTANCE_LOW,
).apply {
setShowBadge(false)
},
NotificationChannel(
CHANNEL_UPDATES_TO_EXTS,
context.getString(R.string.extension_updates_pending),
context.getString(MR.strings.extension_updates_pending),
NotificationManager.IMPORTANCE_DEFAULT,
).apply {
group = GROUP_EXTENSION_UPDATES
},
NotificationChannel(
CHANNEL_NEW_CHAPTERS,
context.getString(R.string.new_chapters),
context.getString(MR.strings.new_chapters),
NotificationManager.IMPORTANCE_DEFAULT,
).apply {
group = GROUP_LIBRARY
},
NotificationChannel(
CHANNEL_BACKUP_RESTORE_PROGRESS,
context.getString(R.string.progress),
context.getString(MR.strings.progress),
NotificationManager.IMPORTANCE_LOW,
).apply {
group = GROUP_BACKUP_RESTORE
@ -176,7 +179,7 @@ object Notifications {
},
NotificationChannel(
CHANNEL_BACKUP_RESTORE_COMPLETE,
context.getString(R.string.complete),
context.getString(MR.strings.complete),
NotificationManager.IMPORTANCE_HIGH,
).apply {
group = GROUP_BACKUP_RESTORE
@ -185,19 +188,19 @@ object Notifications {
},
NotificationChannel(
CHANNEL_CRASH_LOGS,
context.getString(R.string.crash_logs),
context.getString(MR.strings.crash_logs),
NotificationManager.IMPORTANCE_HIGH,
),
NotificationChannel(
CHANNEL_INCOGNITO_MODE,
context.getString(R.string.incognito_mode),
context.getString(MR.strings.incognito_mode),
NotificationManager.IMPORTANCE_LOW,
).apply {
lockscreenVisibility = Notification.VISIBILITY_SECRET
},
NotificationChannel(
CHANNEL_EXT_PROGRESS,
context.getString(R.string.updating_extensions),
context.getString(MR.strings.updating_extensions),
NotificationManager.IMPORTANCE_LOW,
).apply {
group = GROUP_EXTENSION_UPDATES
@ -206,14 +209,14 @@ object Notifications {
},
NotificationChannel(
CHANNEL_EXT_UPDATED,
context.getString(R.string.extensions_updated),
context.getString(MR.strings.extensions_updated),
NotificationManager.IMPORTANCE_DEFAULT,
).apply {
group = GROUP_EXTENSION_UPDATES
},
NotificationChannel(
CHANNEL_INSTALLING,
context.getString(R.string.installing),
context.getString(MR.strings.installing),
NotificationManager.IMPORTANCE_HIGH,
).apply {
setShowBadge(false)
@ -223,7 +226,7 @@ object Notifications {
},
NotificationChannel(
CHANNEL_UPDATED,
context.getString(R.string.update_completed),
context.getString(MR.strings.update_completed),
NotificationManager.IMPORTANCE_HIGH,
).apply {
setShowBadge(false)

View file

@ -1,7 +1,11 @@
package eu.kanade.tachiyomi.data.preference
import androidx.annotation.StringRes
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
// Library
const val MANGA_NON_COMPLETED = "manga_ongoing"
@ -14,23 +18,23 @@ const val DEVICE_CHARGING = "ac"
const val DEVICE_BATTERY_NOT_LOW = "battery_not_low"
object PreferenceValues {
enum class SecureScreenMode(val titleResId: Int) {
ALWAYS(R.string.always),
INCOGNITO(R.string.incognito_mode),
NEVER(R.string.never),
enum class SecureScreenMode(val titleResId: StringResource) {
ALWAYS(MR.strings.always),
INCOGNITO(MR.strings.incognito_mode),
NEVER(MR.strings.never),
}
enum class ReaderHideThreshold(val titleResId: Int, val threshold: Int) {
HIGHEST(R.string.pref_highest, 5),
HIGH(R.string.pref_high, 13),
LOW(R.string.pref_low, 31),
LOWEST(R.string.pref_lowest, 47),
enum class ReaderHideThreshold(val titleResId: StringResource, val threshold: Int) {
HIGHEST(MR.strings.pref_highest, 5),
HIGH(MR.strings.pref_high, 13),
LOW(MR.strings.pref_low, 31),
LOWEST(MR.strings.pref_lowest, 47),
}
enum class MigrationSourceOrder(val value: Int, @StringRes val titleResId: Int) {
Alphabetically(0, R.string.alphabetically),
MostEntries(1, R.string.most_entries),
Obsolete(2, R.string.obsolete),
enum class MigrationSourceOrder(val value: Int, val titleResId: StringResource) {
Alphabetically(0, MR.strings.alphabetically),
MostEntries(1, MR.strings.most_entries),
Obsolete(2, MR.strings.obsolete),
;
companion object {

View file

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.track
import androidx.annotation.CallSuper
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.model.TrackSearch
@ -21,8 +22,7 @@ abstract class TrackService(val id: Int) {
get() = networkService.client
// Name of the manga sync service to display
@StringRes
abstract fun nameRes(): Int
abstract fun nameRes(): StringResource
// Application and remote support for reading dates
open val supportsReadingDates: Boolean = false

View file

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.data.track.anilist
import android.content.Context
import android.graphics.Color
import androidx.annotation.StringRes
import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
@ -12,6 +11,8 @@ import eu.kanade.tachiyomi.util.system.e
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.util.lang.getString
class Anilist(private val context: Context, id: Int) : TrackService(id) {
@ -53,8 +54,7 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
}
}
@StringRes
override fun nameRes() = R.string.anilist
override fun nameRes() = MR.strings.anilist
override fun getLogo() = R.drawable.ic_tracker_anilist
@ -72,24 +72,24 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
override fun getStatus(status: Int): String = with(context) {
when (status) {
READING -> getString(R.string.reading)
PLAN_TO_READ -> getString(R.string.plan_to_read)
COMPLETED -> getString(R.string.completed)
PAUSED -> getString(R.string.paused)
DROPPED -> getString(R.string.dropped)
REREADING -> getString(R.string.rereading)
READING -> getString(MR.strings.reading)
PLAN_TO_READ -> getString(MR.strings.plan_to_read)
COMPLETED -> getString(MR.strings.completed)
PAUSED -> getString(MR.strings.paused)
DROPPED -> getString(MR.strings.dropped)
REREADING -> getString(MR.strings.rereading)
else -> ""
}
}
override fun getGlobalStatus(status: Int): String = with(context) {
when (status) {
READING -> getString(R.string.reading)
PLAN_TO_READ -> getString(R.string.plan_to_read)
COMPLETED -> getString(R.string.completed)
PAUSED -> getString(R.string.on_hold)
DROPPED -> getString(R.string.dropped)
REREADING -> getString(R.string.rereading)
READING -> getString(MR.strings.reading)
PLAN_TO_READ -> getString(MR.strings.plan_to_read)
COMPLETED -> getString(MR.strings.completed)
PAUSED -> getString(MR.strings.on_hold)
DROPPED -> getString(MR.strings.dropped)
REREADING -> getString(MR.strings.rereading)
else -> ""
}
}

View file

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.data.track.bangumi
import android.content.Context
import android.graphics.Color
import androidx.annotation.StringRes
import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
@ -13,11 +12,12 @@ import eu.kanade.tachiyomi.util.system.e
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.util.lang.getString
class Bangumi(private val context: Context, id: Int) : TrackService(id) {
@StringRes
override fun nameRes() = R.string.bangumi
override fun nameRes() = MR.strings.bangumi
private val json: Json by injectLazy()
@ -93,22 +93,22 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) {
override fun getStatus(status: Int): String = with(context) {
when (status) {
READING -> getString(R.string.reading)
PLAN_TO_READ -> getString(R.string.plan_to_read)
COMPLETED -> getString(R.string.completed)
ON_HOLD -> getString(R.string.on_hold)
DROPPED -> getString(R.string.dropped)
READING -> getString(MR.strings.reading)
PLAN_TO_READ -> getString(MR.strings.plan_to_read)
COMPLETED -> getString(MR.strings.completed)
ON_HOLD -> getString(MR.strings.on_hold)
DROPPED -> getString(MR.strings.dropped)
else -> ""
}
}
override fun getGlobalStatus(status: Int): String = with(context) {
when (status) {
READING -> getString(R.string.reading)
PLAN_TO_READ -> getString(R.string.plan_to_read)
COMPLETED -> getString(R.string.completed)
ON_HOLD -> getString(R.string.on_hold)
DROPPED -> getString(R.string.dropped)
READING -> getString(MR.strings.reading)
PLAN_TO_READ -> getString(MR.strings.plan_to_read)
COMPLETED -> getString(MR.strings.completed)
ON_HOLD -> getString(MR.strings.on_hold)
DROPPED -> getString(MR.strings.dropped)
else -> ""
}
}

View file

@ -4,6 +4,9 @@ import android.content.Context
import android.graphics.Color
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
@ -32,8 +35,7 @@ class Kavita(private val context: Context, id: Int) : TrackService(id), Enhanced
private val sourceManager: SourceManager by injectLazy()
@StringRes
override fun nameRes() = R.string.kavita
override fun nameRes() = MR.strings.kavita
override fun getLogo(): Int = R.drawable.ic_tracker_kavita
@ -47,18 +49,18 @@ class Kavita(private val context: Context, id: Int) : TrackService(id), Enhanced
override fun getStatus(status: Int): String = with(context) {
when (status) {
UNREAD -> getString(R.string.unread)
READING -> getString(R.string.reading)
COMPLETED -> getString(R.string.completed)
UNREAD -> getString(MR.strings.unread)
READING -> getString(MR.strings.reading)
COMPLETED -> getString(MR.strings.completed)
else -> ""
}
}
override fun getGlobalStatus(status: Int): String = with(context) {
when (status) {
UNREAD -> getString(R.string.plan_to_read)
READING -> getString(R.string.reading)
COMPLETED -> getString(R.string.completed)
UNREAD -> getString(MR.strings.plan_to_read)
READING -> getString(MR.strings.reading)
COMPLETED -> getString(MR.strings.completed)
else -> ""
}
}

View file

@ -5,6 +5,9 @@ import android.graphics.Color
import androidx.annotation.StringRes
import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
@ -28,8 +31,7 @@ class Kitsu(private val context: Context, id: Int) : TrackService(id) {
const val DEFAULT_SCORE = 0f
}
@StringRes
override fun nameRes() = R.string.kitsu
override fun nameRes() = MR.strings.kitsu
override val supportsReadingDates: Boolean = true
@ -57,22 +59,22 @@ class Kitsu(private val context: Context, id: Int) : TrackService(id) {
override fun getStatus(status: Int): String = with(context) {
when (status) {
READING -> getString(R.string.currently_reading)
PLAN_TO_READ -> getString(R.string.want_to_read)
COMPLETED -> getString(R.string.completed)
ON_HOLD -> getString(R.string.on_hold)
DROPPED -> getString(R.string.dropped)
READING -> getString(MR.strings.currently_reading)
PLAN_TO_READ -> getString(MR.strings.want_to_read)
COMPLETED -> getString(MR.strings.completed)
ON_HOLD -> getString(MR.strings.on_hold)
DROPPED -> getString(MR.strings.dropped)
else -> ""
}
}
override fun getGlobalStatus(status: Int): String = with(context) {
when (status) {
READING -> getString(R.string.reading)
PLAN_TO_READ -> getString(R.string.plan_to_read)
COMPLETED -> getString(R.string.completed)
ON_HOLD -> getString(R.string.on_hold)
DROPPED -> getString(R.string.dropped)
READING -> getString(MR.strings.reading)
PLAN_TO_READ -> getString(MR.strings.plan_to_read)
COMPLETED -> getString(MR.strings.completed)
ON_HOLD -> getString(MR.strings.on_hold)
DROPPED -> getString(MR.strings.dropped)
else -> ""
}
}

View file

@ -4,6 +4,9 @@ import android.content.Context
import android.graphics.Color
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
@ -28,8 +31,7 @@ class Komga(private val context: Context, id: Int) : TrackService(id), EnhancedT
val api by lazy { KomgaApi(client) }
@StringRes
override fun nameRes() = R.string.komga
override fun nameRes() = MR.strings.komga
override fun getLogo() = R.drawable.ic_tracker_komga
@ -43,18 +45,18 @@ class Komga(private val context: Context, id: Int) : TrackService(id), EnhancedT
override fun getStatus(status: Int): String = with(context) {
when (status) {
UNREAD -> getString(R.string.unread)
READING -> getString(R.string.currently_reading)
COMPLETED -> getString(R.string.completed)
UNREAD -> getString(MR.strings.unread)
READING -> getString(MR.strings.currently_reading)
COMPLETED -> getString(MR.strings.completed)
else -> ""
}
}
override fun getGlobalStatus(status: Int): String = with(context) {
when (status) {
UNREAD -> getString(R.string.plan_to_read)
READING -> getString(R.string.reading)
COMPLETED -> getString(R.string.completed)
UNREAD -> getString(MR.strings.plan_to_read)
READING -> getString(MR.strings.reading)
COMPLETED -> getString(MR.strings.completed)
else -> ""
}
}

View file

@ -4,6 +4,9 @@ import android.content.Context
import android.graphics.Color
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.mangaupdates.dto.ListItem
@ -31,10 +34,9 @@ class MangaUpdates(private val context: Context, id: Int) : TrackService(id) {
private val api by lazy { MangaUpdatesApi(interceptor, client) }
@StringRes
override fun nameRes(): Int = R.string.manga_updates
override fun nameRes() = MR.strings.manga_updates
override fun getLogo(): Int = R.drawable.ic_tracker_manga_updates
override fun getLogo() = R.drawable.ic_tracker_manga_updates
override fun getTrackerColor() = Color.rgb(251, 148, 46)
@ -52,22 +54,22 @@ class MangaUpdates(private val context: Context, id: Int) : TrackService(id) {
override fun getStatus(status: Int): String = with(context) {
when (status) {
READING_LIST -> getString(R.string.reading_list)
WISH_LIST -> getString(R.string.wish_list)
COMPLETE_LIST -> getString(R.string.complete_list)
ON_HOLD_LIST -> getString(R.string.on_hold_list)
UNFINISHED_LIST -> getString(R.string.unfinished_list)
READING_LIST -> getString(MR.strings.reading_list)
WISH_LIST -> getString(MR.strings.wish_list)
COMPLETE_LIST -> getString(MR.strings.complete_list)
ON_HOLD_LIST -> getString(MR.strings.on_hold_list)
UNFINISHED_LIST -> getString(MR.strings.unfinished_list)
else -> ""
}
}
override fun getGlobalStatus(status: Int) = with(context) {
when (status) {
READING_LIST -> getString(R.string.reading)
COMPLETE_LIST -> getString(R.string.completed)
ON_HOLD_LIST -> getString(R.string.on_hold)
UNFINISHED_LIST -> getString(R.string.dropped)
WISH_LIST -> getString(R.string.plan_to_read)
READING_LIST -> getString(MR.strings.reading)
COMPLETE_LIST -> getString(MR.strings.completed)
ON_HOLD_LIST -> getString(MR.strings.on_hold)
UNFINISHED_LIST -> getString(MR.strings.dropped)
WISH_LIST -> getString(MR.strings.plan_to_read)
else -> ""
}
}

View file

@ -5,6 +5,9 @@ import android.graphics.Color
import androidx.annotation.StringRes
import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
@ -20,8 +23,7 @@ class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
private val interceptor by lazy { MyAnimeListInterceptor(this) }
private val api by lazy { MyAnimeListApi(client, interceptor) }
@StringRes
override fun nameRes() = R.string.myanimelist
override fun nameRes() = MR.strings.myanimelist
override val supportsReadingDates: Boolean = true
@ -33,22 +35,22 @@ class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
override fun getStatus(status: Int): String = with(context) {
when (status) {
READING -> getString(R.string.reading)
COMPLETED -> getString(R.string.completed)
ON_HOLD -> getString(R.string.on_hold)
DROPPED -> getString(R.string.dropped)
PLAN_TO_READ -> getString(R.string.plan_to_read)
READING -> getString(MR.strings.reading)
COMPLETED -> getString(MR.strings.completed)
ON_HOLD -> getString(MR.strings.on_hold)
DROPPED -> getString(MR.strings.dropped)
PLAN_TO_READ -> getString(MR.strings.plan_to_read)
else -> ""
}
}
override fun getGlobalStatus(status: Int): String = with(context) {
when (status) {
READING -> getString(R.string.reading)
PLAN_TO_READ -> getString(R.string.plan_to_read)
COMPLETED -> getString(R.string.completed)
ON_HOLD -> getString(R.string.on_hold)
DROPPED -> getString(R.string.dropped)
READING -> getString(MR.strings.reading)
PLAN_TO_READ -> getString(MR.strings.plan_to_read)
COMPLETED -> getString(MR.strings.completed)
ON_HOLD -> getString(MR.strings.on_hold)
DROPPED -> getString(MR.strings.dropped)
else -> ""
}
}

View file

@ -5,6 +5,9 @@ import android.graphics.Color
import androidx.annotation.StringRes
import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.updateNewTrackInfo
@ -27,8 +30,7 @@ class Shikimori(private val context: Context, id: Int) : TrackService(id) {
const val DEFAULT_SCORE = 0
}
@StringRes
override fun nameRes() = R.string.shikimori
override fun nameRes() = MR.strings.shikimori
private val json: Json by injectLazy()
@ -54,12 +56,12 @@ class Shikimori(private val context: Context, id: Int) : TrackService(id) {
override fun getStatus(status: Int): String = with(context) {
when (status) {
READING -> getString(R.string.reading)
COMPLETED -> getString(R.string.completed)
ON_HOLD -> getString(R.string.on_hold)
DROPPED -> getString(R.string.dropped)
PLAN_TO_READ -> getString(R.string.plan_to_read)
REREADING -> getString(R.string.rereading)
READING -> getString(MR.strings.reading)
COMPLETED -> getString(MR.strings.completed)
ON_HOLD -> getString(MR.strings.on_hold)
DROPPED -> getString(MR.strings.dropped)
PLAN_TO_READ -> getString(MR.strings.plan_to_read)
REREADING -> getString(MR.strings.rereading)
else -> ""
}
}

View file

@ -4,6 +4,9 @@ import android.content.Context
import android.graphics.Color
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
@ -14,8 +17,7 @@ import eu.kanade.tachiyomi.data.track.updateNewTrackInfo
class Suwayomi(private val context: Context, id: Int) : TrackService(id), EnhancedTrackService {
val api by lazy { TachideskApi() }
@StringRes
override fun nameRes() = R.string.suwayomi
override fun nameRes() = MR.strings.suwayomi
override fun getLogo() = R.drawable.ic_tracker_suwayomi
@ -35,18 +37,18 @@ class Suwayomi(private val context: Context, id: Int) : TrackService(id), Enhanc
override fun getStatus(status: Int): String = with(context) {
when (status) {
UNREAD -> getString(R.string.unread)
READING -> getString(R.string.reading)
COMPLETED -> getString(R.string.completed)
UNREAD -> getString(MR.strings.unread)
READING -> getString(MR.strings.reading)
COMPLETED -> getString(MR.strings.completed)
else -> ""
}
}
override fun getGlobalStatus(status: Int): String = with(context) {
when (status) {
UNREAD -> getString(R.string.plan_to_read)
READING -> getString(R.string.reading)
COMPLETED -> getString(R.string.completed)
UNREAD -> getString(MR.strings.plan_to_read)
READING -> getString(MR.strings.reading)
COMPLETED -> getString(MR.strings.completed)
else -> ""
}
}

View file

@ -7,10 +7,10 @@ import android.content.pm.PackageInstaller
import androidx.core.content.edit
import androidx.core.net.toUri
import androidx.preference.PreferenceManager
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.system.getParcelableCompat
import eu.kanade.tachiyomi.util.system.localeContext
import eu.kanade.tachiyomi.util.system.toast
import yokai.i18n.MR
class AppUpdateBroadcast : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@ -37,7 +37,7 @@ class AppUpdateBroadcast : BroadcastReceiver() {
}
PackageInstaller.STATUS_FAILURE, PackageInstaller.STATUS_FAILURE_ABORTED, PackageInstaller.STATUS_FAILURE_BLOCKED, PackageInstaller.STATUS_FAILURE_CONFLICT, PackageInstaller.STATUS_FAILURE_INCOMPATIBLE, PackageInstaller.STATUS_FAILURE_INVALID, PackageInstaller.STATUS_FAILURE_STORAGE -> {
if (status != PackageInstaller.STATUS_FAILURE_ABORTED) {
context.toast(R.string.could_not_install_update)
context.toast(MR.strings.could_not_install_update)
val uri = intent.getStringExtra(AppDownloadInstallJob.EXTRA_FILE_URI) ?: return
val appUpdateNotifier = AppUpdateNotifier(context.localeContext)
appUpdateNotifier.cancelInstallNotification()

View file

@ -15,6 +15,8 @@ import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.notificationManager
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
/**
@ -30,7 +32,7 @@ internal class AppUpdateNotifier(private val context: Context) {
val notificationBuilder by lazy {
NotificationCompat.Builder(context, Notifications.CHANNEL_COMMON).apply {
setSmallIcon(AR.drawable.stat_sys_download)
setContentTitle(context.getString(R.string.app_name))
setContentTitle(context.getString(MR.strings.app_name))
}
}
@ -56,13 +58,13 @@ internal class AppUpdateNotifier(private val context: Context) {
val pendingIntent = NotificationReceiver.openUpdatePendingActivity(context, body, url)
releasePageUrl = releaseUrl
with(notificationBuilder) {
setContentTitle(context.getString(R.string.app_name))
setContentTitle(context.getString(MR.strings.app_name))
setContentText(
context.getString(
if (isBeta) {
R.string.new_beta_version_available
MR.strings.new_beta_version_available
} else {
R.string.new_version_available
MR.strings.new_version_available
},
),
)
@ -75,7 +77,7 @@ internal class AppUpdateNotifier(private val context: Context) {
// Download action
addAction(
AR.drawable.stat_sys_download_done,
context.getString(if (isOnA12) R.string.update else R.string.download),
context.getString(if (isOnA12) MR.strings.update else MR.strings.download),
NotificationReceiver.startAppUpdatePendingJob(context, url, true),
)
addReleasePageAction()
@ -90,7 +92,7 @@ internal class AppUpdateNotifier(private val context: Context) {
}
addAction(
R.drawable.ic_new_releases_24dp,
context.getString(R.string.release_page),
context.getString(MR.strings.release_page),
PendingIntent.getActivity(context, releaseUrl.hashCode(), releaseIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
)
}
@ -103,8 +105,8 @@ internal class AppUpdateNotifier(private val context: Context) {
*/
fun onDownloadStarted(): NotificationCompat.Builder {
with(notificationBuilder) {
setContentTitle(context.getString(R.string.app_name))
setContentText(context.getString(R.string.downloading))
setContentTitle(context.getString(MR.strings.app_name))
setContentText(context.getString(MR.strings.downloading))
setSmallIcon(AR.drawable.stat_sys_download)
setProgress(0, 0, true)
setAutoCancel(false)
@ -112,7 +114,7 @@ internal class AppUpdateNotifier(private val context: Context) {
clearActions()
addAction(
R.drawable.ic_close_24dp,
context.getString(R.string.cancel),
context.getString(MR.strings.cancel),
NotificationReceiver.cancelUpdateDownloadPendingBroadcast(context),
)
addReleasePageAction()
@ -128,15 +130,15 @@ internal class AppUpdateNotifier(private val context: Context) {
*/
fun onProgressChange(progress: Int) {
with(notificationBuilder) {
setContentTitle(context.getString(R.string.app_name))
setContentText(context.getString(R.string.downloading))
setContentTitle(context.getString(MR.strings.app_name))
setContentText(context.getString(MR.strings.downloading))
setSmallIcon(AR.drawable.stat_sys_download)
setProgress(100, progress, false)
setOnlyAlertOnce(true)
clearActions()
addAction(
R.drawable.ic_close_24dp,
context.getString(R.string.cancel),
context.getString(MR.strings.cancel),
NotificationReceiver.cancelUpdateDownloadPendingBroadcast(context),
)
}
@ -145,7 +147,7 @@ internal class AppUpdateNotifier(private val context: Context) {
fun onInstalling() {
with(NotificationCompat.Builder(context, Notifications.CHANNEL_INSTALLING)) {
setContentTitle(context.getString(R.string.installing))
setContentTitle(context.getString(MR.strings.installing))
setSmallIcon(AR.drawable.stat_sys_download)
setProgress(0, 0, true)
setOnlyAlertOnce(true)
@ -161,7 +163,7 @@ internal class AppUpdateNotifier(private val context: Context) {
*/
fun onDownloadFinished(uri: Uri) {
with(notificationBuilder) {
setContentText(context.getString(R.string.download_complete))
setContentText(context.getString(MR.strings.download_complete))
setSmallIcon(AR.drawable.stat_sys_download_done)
setAutoCancel(false)
setOnlyAlertOnce(false)
@ -171,13 +173,13 @@ internal class AppUpdateNotifier(private val context: Context) {
clearActions()
addAction(
R.drawable.ic_system_update_24dp,
context.getString(R.string.install),
context.getString(MR.strings.install),
NotificationHandler.installApkPendingActivity(context, uri),
)
// Cancel action
addAction(
R.drawable.ic_close_24dp,
context.getString(R.string.cancel),
context.getString(MR.strings.cancel),
NotificationReceiver.dismissNotificationPendingBroadcast(context, Notifications.ID_INSTALL),
)
addReleasePageAction()
@ -188,8 +190,8 @@ internal class AppUpdateNotifier(private val context: Context) {
/** Call when apk download is finished. */
fun onInstallFinished() {
with(NotificationCompat.Builder(context, Notifications.CHANNEL_UPDATED)) {
setContentTitle(context.getString(R.string.update_completed))
setContentText(context.getString(R.string.updated_to_, BuildConfig.VERSION_NAME))
setContentTitle(context.getString(MR.strings.update_completed))
setContentText(context.getString(MR.strings.updated_to_, BuildConfig.VERSION_NAME))
setSmallIcon(R.drawable.ic_yokai)
setAutoCancel(true)
setOngoing(false)
@ -204,7 +206,7 @@ internal class AppUpdateNotifier(private val context: Context) {
clearActions()
addAction(
R.drawable.ic_system_update_24dp,
context.getString(R.string.open),
context.getString(MR.strings.open),
pendingIntent,
)
addReleasePageAction()
@ -219,7 +221,7 @@ internal class AppUpdateNotifier(private val context: Context) {
*/
fun onDownloadError(url: String) {
with(notificationBuilder) {
setContentText(context.getString(R.string.download_error))
setContentText(context.getString(MR.strings.download_error))
setSmallIcon(AR.drawable.stat_sys_warning)
setOnlyAlertOnce(false)
setAutoCancel(false)
@ -229,13 +231,13 @@ internal class AppUpdateNotifier(private val context: Context) {
// Retry action
addAction(
R.drawable.ic_refresh_24dp,
context.getString(R.string.retry),
context.getString(MR.strings.retry),
NotificationReceiver.startAppUpdatePendingJob(context, url),
)
// Cancel action
addAction(
R.drawable.ic_close_24dp,
context.getString(R.string.cancel),
context.getString(MR.strings.cancel),
NotificationReceiver.dismissNotificationPendingBroadcast(context, Notifications.ID_UPDATER),
)
addReleasePageAction()
@ -245,8 +247,8 @@ internal class AppUpdateNotifier(private val context: Context) {
fun onInstallError(uri: Uri) {
with(notificationBuilder) {
setContentTitle(context.getString(R.string.app_name))
setContentText(context.getString(R.string.could_not_install_update))
setContentTitle(context.getString(MR.strings.app_name))
setContentText(context.getString(MR.strings.could_not_install_update))
setSmallIcon(AR.drawable.stat_sys_warning)
setOnlyAlertOnce(false)
setAutoCancel(false)
@ -256,13 +258,13 @@ internal class AppUpdateNotifier(private val context: Context) {
// Retry action
addAction(
R.drawable.ic_refresh_24dp,
context.getString(R.string.retry),
context.getString(MR.strings.retry),
NotificationHandler.installApkPendingActivity(context, uri),
)
// Cancel action
addAction(
R.drawable.ic_close_24dp,
context.getString(R.string.cancel),
context.getString(MR.strings.cancel),
NotificationReceiver.dismissNotificationPendingBroadcast(context, Notifications.ID_UPDATER),
)
addReleasePageAction()

View file

@ -8,6 +8,8 @@ import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notificationManager
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
class ExtensionInstallNotifier(private val context: Context) {
@ -31,10 +33,10 @@ class ExtensionInstallNotifier(private val context: Context) {
*/
val progressNotificationBuilder by lazy {
context.notificationBuilder(Notifications.CHANNEL_EXT_PROGRESS) {
setContentTitle(context.getString(R.string.app_name))
setContentTitle(context.getString(MR.strings.app_name))
setSmallIcon(AR.drawable.stat_sys_download)
setLargeIcon(notificationBitmap)
setContentTitle(context.getString(R.string.updating_extensions))
setContentTitle(context.getString(MR.strings.updating_extensions))
setProgress(0, 0, true)
setOngoing(true)
setSilent(true)
@ -56,7 +58,7 @@ class ExtensionInstallNotifier(private val context: Context) {
Notifications.ID_EXTENSION_PROGRESS,
progressNotificationBuilder
.setChannelId(Notifications.CHANNEL_EXT_PROGRESS)
.setContentTitle(context.getString(R.string.updating_extensions))
.setContentTitle(context.getString(MR.strings.updating_extensions))
.setProgress(max, progress, progress == 0)
.build(),
)
@ -68,8 +70,8 @@ class ExtensionInstallNotifier(private val context: Context) {
progressNotificationBuilder
.setChannelId(Notifications.CHANNEL_EXT_UPDATED)
.setContentTitle(
context.resources.getQuantityString(
R.plurals.extensions_updated_plural,
context.getString(
MR.plurals.extensions_updated_plural,
extensions.size,
extensions.size,
),

View file

@ -14,7 +14,6 @@ import androidx.work.WorkManager
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.extension.model.Extension
@ -40,6 +39,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.i18n.MR
import java.lang.ref.WeakReference
import kotlin.math.max
@ -78,7 +78,7 @@ class ExtensionInstallerJob(val context: Context, workerParams: WorkerParameters
val reRunUpdateCheck = showUpdated > 0
if (!showUpdatedNotification && !preferences.hasPromptedBeforeUpdateAll().get()) {
context.toast(R.string.some_extensions_may_prompt)
context.toast(MR.strings.some_extensions_may_prompt)
preferences.hasPromptedBeforeUpdateAll().set(true)
}

View file

@ -39,6 +39,8 @@ import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import yokai.domain.base.BasePreferences
import yokai.domain.base.BasePreferences.ExtensionInstaller
import yokai.i18n.MR
import yokai.util.lang.getString
import java.util.concurrent.*
class ExtensionUpdateJob(private val context: Context, workerParams: WorkerParameters) :
@ -121,8 +123,8 @@ class ExtensionUpdateJob(private val context: Context, workerParams: WorkerParam
context.notification(Notifications.CHANNEL_UPDATES_TO_EXTS) {
val context = context.localeContext
setContentTitle(
context.resources.getQuantityString(
R.plurals.extension_updates_available,
context.getString(
MR.plurals.extension_updates_available,
extensions.size,
extensions.size,
),
@ -144,7 +146,7 @@ class ExtensionUpdateJob(private val context: Context, workerParams: WorkerParam
NotificationReceiver.startExtensionUpdatePendingJob(context, extensions)
addAction(
R.drawable.ic_file_download_24dp,
context.getString(R.string.update_all),
context.getString(MR.strings.update_all),
pendingIntent,
)
}

View file

@ -9,6 +9,9 @@ import android.os.Build
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller.Companion.EXTRA_DOWNLOAD_ID
import eu.kanade.tachiyomi.util.system.getUriSize
import eu.kanade.tachiyomi.util.system.isPackageInstalled
@ -69,7 +72,7 @@ class ShizukuInstaller(private val context: Context, val finishedQueue: (Shizuku
Shizuku.addBinderDeadListener(shizukuDeadListener)
require(Shizuku.pingBinder() && (context.isPackageInstalled(shizukuPkgName) || Sui.isSui())) {
finishedQueue(this)
context.getString(R.string.ext_installer_shizuku_stopped)
context.getString(MR.strings.ext_installer_shizuku_stopped)
}
ready = if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) {
true

View file

@ -1,14 +1,14 @@
package eu.kanade.tachiyomi.extension.model
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import yokai.i18n.MR
enum class InstalledExtensionsOrder(val value: Int, @StringRes val nameRes: Int) {
Name(0, R.string.name),
RecentlyUpdated(1, R.string.recently_updated),
RecentlyInstalled(2, R.string.recently_installed),
Language(3, R.string.language),
enum class InstalledExtensionsOrder(val value: Int, val nameRes: StringResource) {
Name(0, MR.strings.name),
RecentlyUpdated(1, MR.strings.recently_updated),
RecentlyInstalled(2, MR.strings.recently_installed),
Language(3, MR.strings.language),
;
companion object {

View file

@ -13,7 +13,6 @@ import android.os.Build
import android.os.Bundle
import android.widget.Toast
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.extension.util.ExtensionInstallBroadcast.Companion.EXTRA_SESSION_ID
import eu.kanade.tachiyomi.extension.util.ExtensionInstallBroadcast.Companion.PACKAGE_INSTALLED_ACTION
@ -22,6 +21,7 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.getParcelableCompat
import eu.kanade.tachiyomi.util.system.toast
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
/**
* Broadcast used to install extensions, that receives callbacks from package installer.
@ -103,9 +103,9 @@ class ExtensionInstallBroadcast : BroadcastReceiver() {
extensionManager.setInstallationResult(downloadId, false)
if (status != PackageInstaller.STATUS_FAILURE_ABORTED) {
if (DeviceUtil.isMiui) {
context.toast(R.string.extensions_miui_warning, Toast.LENGTH_LONG)
context.toast(MR.strings.extensions_miui_warning, Toast.LENGTH_LONG)
} else {
context.toast(R.string.could_not_install_extension)
context.toast(MR.strings.could_not_install_extension)
}
}
}

View file

@ -6,6 +6,9 @@ import co.touchlab.kermit.Logger
import com.github.junrar.Archive
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
@ -117,7 +120,7 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
private val xml: XML by injectLazy()
override val id = ID
override val name = context.getString(R.string.local_source)
override val name = context.getString(MR.strings.local_source)
override val lang = "other"
override val supportsLatest = true
@ -329,7 +332,7 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
?.findFile(mangaDirName)
?.findFile(chapterName)
if (chapFile == null || !chapFile.exists())
throw Exception(context.getString(R.string.chapter_not_found))
throw Exception(context.getString(MR.strings.chapter_not_found))
return getFormat(chapFile)
}
@ -340,7 +343,7 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
extension.equals("zip", true) || extension.equals("cbz", true) -> Format.Zip(this)
extension.equals("rar", true) || extension.equals("cbr", true) -> Format.Rar(this)
extension.equals("epub", true) -> Format.Epub(this)
else -> throw Exception(context.getString(R.string.local_invalid_format))
else -> throw Exception(context.getString(MR.strings.local_invalid_format))
}
}
@ -432,8 +435,8 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
private val latestFilters = FilterList(OrderBy(context).apply { state = Filter.Sort.Selection(1, false) })
private class OrderBy(context: Context) : Filter.Sort(
context.getString(R.string.order_by),
arrayOf(context.getString(R.string.title), context.getString(R.string.date)),
context.getString(MR.strings.order_by),
arrayOf(context.getString(MR.strings.title), context.getString(MR.strings.date)),
Selection(0, true),
)

View file

@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.source
import android.content.Context
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
@ -131,7 +134,7 @@ class SourceManager(
private fun getSourceNotInstalledException(): Exception {
return SourceNotFoundException(
context.getString(
R.string.source_not_installed_,
MR.strings.source_not_installed_,
extensionManager.getStubSource(id)?.name ?: id.toString(),
),
id,

View file

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.source.online.all
import android.net.Uri
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toChapter
@ -14,6 +13,8 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.i18n.MR
import yokai.util.lang.getString
import java.util.*
class Cubari : DelegatedHttpSource() {
@ -48,7 +49,7 @@ class Cubari : DelegatedHttpSource() {
val context = Injekt.get<PreferencesHelper>().context
val trueChapter = findChapter(chapters, cubariType, chapterNumber)?.toChapter()
?: error(
context.getString(R.string.chapter_not_found),
context.getString(MR.strings.chapter_not_found),
)
if (manga != null) {
Triple(trueChapter, manga, chapters.orEmpty())

View file

@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.source.online.all
import android.net.Uri
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toChapter
@ -70,7 +73,7 @@ class MangaDex : DelegatedHttpSource() {
val chapters = deferredChapters.await()
val context = Injekt.get<PreferencesHelper>().context
val trueChapter = chapters?.find { it.url == "/api$url" }?.toChapter() ?: error(
context.getString(R.string.chapter_not_found),
context.getString(MR.strings.chapter_not_found),
)
if (manga != null) {
Triple(trueChapter, manga, chapters.orEmpty())

View file

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.source.online.english
import android.net.Uri
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaImpl
@ -20,6 +19,8 @@ import okhttp3.FormBody
import okhttp3.Request
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.i18n.MR
import yokai.util.lang.getString
open class FoolSlide(override val domainName: String, private val urlModifier: String = "") :
DelegatedHttpSource
@ -72,7 +73,7 @@ open class FoolSlide(override val domainName: String, private val urlModifier: S
val chapters = deferredChapters.await()
val context = Injekt.get<PreferencesHelper>().context
val trueChapter = chapters?.find { it.url == chapterUrl }?.toChapter() ?: error(
context.getString(R.string.chapter_not_found),
context.getString(MR.strings.chapter_not_found),
)
if (manga != null) Triple(trueChapter, manga, chapters) else null
}

View file

@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.source.online.english
import android.net.Uri
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toChapter
@ -59,7 +62,7 @@ class MangaPlus : DelegatedHttpSource() {
val chapters = deferredChapters.await()
val context = Injekt.get<PreferencesHelper>().context
val trueChapter = chapters?.find { it.url == url }?.toChapter() ?: error(
context.getString(R.string.chapter_not_found),
context.getString(MR.strings.chapter_not_found),
)
if (manga != null) {
Triple(

View file

@ -9,6 +9,9 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import eu.davidea.fastscroller.FastScroller
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.ui.base.controller.BaseLegacyController
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.dpToPxEnd

View file

@ -14,7 +14,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.adapters.ItemAdapter
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.databinding.BottomMenuSheetBinding
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
@ -149,7 +153,7 @@ class MaterialMenuSheet(
data class MenuSheetItem(
val id: Int,
@DrawableRes val drawable: Int = 0,
@StringRes val textRes: Int = 0,
val textRes: StringResource = StringResource(0),
val text: String? = null,
var endDrawableRes: Int = 0,
)

View file

@ -4,6 +4,9 @@ import android.view.View
import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.items.AbstractItem
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.databinding.MenuSheetItemBinding
class MaterialMenuSheetItem(val sheetItem: MaterialMenuSheet.MenuSheetItem) : AbstractItem<MaterialMenuSheetItem.ViewHolder>() {

View file

@ -12,6 +12,9 @@ import android.widget.LinearLayout
import androidx.appcompat.widget.SearchView
import androidx.core.graphics.ColorUtils
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
import kotlinx.coroutines.CoroutineScope

View file

@ -8,7 +8,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.CategoriesControllerBinding
import eu.kanade.tachiyomi.ui.base.SmallToolbarInterface
import eu.kanade.tachiyomi.ui.base.controller.BaseLegacyController
@ -17,7 +16,13 @@ import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.system.materialAlertDialog
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.liftAppbarWith
import eu.kanade.tachiyomi.util.view.setAction
import eu.kanade.tachiyomi.util.view.setMessage
import eu.kanade.tachiyomi.util.view.setPositiveButton
import eu.kanade.tachiyomi.util.view.setTitle
import eu.kanade.tachiyomi.util.view.snack
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
/**
@ -49,7 +54,7 @@ class CategoryController(bundle: Bundle? = null) :
* Returns the toolbar title to show when this controller is attached.
*/
override fun getTitle(): String? {
return resources?.getString(R.string.edit_categories)
return view?.context?.getString(MR.strings.edit_categories)
}
override fun createBinding(inflater: LayoutInflater) = CategoriesControllerBinding.inflate(inflater)
@ -117,7 +122,7 @@ class CategoryController(bundle: Bundle? = null) :
override fun onCategoryRename(position: Int, newName: String): Boolean {
val category = adapter?.getItem(position)?.category ?: return false
if (newName.isBlank()) {
activity?.toast(R.string.category_cannot_be_blank)
activity?.toast(MR.strings.category_cannot_be_blank)
return false
}
if (category.order == CREATE_CATEGORY_ORDER) {
@ -128,9 +133,9 @@ class CategoryController(bundle: Bundle? = null) :
override fun onItemDelete(position: Int) {
activity!!.materialAlertDialog()
.setTitle(R.string.confirm_category_deletion)
.setMessage(R.string.confirm_category_deletion_message)
.setPositiveButton(R.string.delete) { _, _ ->
.setTitle(MR.strings.confirm_category_deletion)
.setMessage(MR.strings.confirm_category_deletion_message)
.setPositiveButton(MR.strings.delete) { _, _ ->
deleteCategory(position)
}
.setNegativeButton(AR.string.cancel, null)
@ -141,9 +146,9 @@ class CategoryController(bundle: Bundle? = null) :
confirmDelete()
adapter?.removeItem(position)
snack =
view?.snack(R.string.category_deleted, Snackbar.LENGTH_INDEFINITE) {
view?.snack(MR.strings.category_deleted, Snackbar.LENGTH_INDEFINITE) {
var undoing = false
setAction(R.string.undo) {
setAction(MR.strings.undo) {
adapter?.restoreDeletedItems()
undoing = true
}
@ -189,6 +194,6 @@ class CategoryController(bundle: Bundle? = null) :
* Called from the presenter when a category with the given name already exists.
*/
fun onCategoryExistsError() {
activity?.toast(R.string.category_with_name_exists)
activity?.toast(MR.strings.category_with_name_exists)
}
}

View file

@ -16,7 +16,7 @@ import eu.kanade.tachiyomi.databinding.CategoriesItemBinding
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.ui.category.CategoryPresenter.Companion.CREATE_CATEGORY_ORDER
import eu.kanade.tachiyomi.util.system.getResourceColor
import java.util.Locale
import java.util.*
/**
* Holder used to display category items.

View file

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.ui.category
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.ui.library.LibrarySort
@ -12,6 +11,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.i18n.MR
import yokai.util.lang.getString
/**
* Presenter of [CategoryController]. Used to manage the categories of the library.
@ -48,7 +49,7 @@ class CategoryPresenter(
private fun newCategory(): Category {
val default =
Category.create(controller.view?.context?.getString(R.string.create_new_category) ?: "")
Category.create(controller.view?.context?.getString(MR.strings.create_new_category) ?: "")
default.order = CREATE_CATEGORY_ORDER
default.id = Int.MIN_VALUE
return default

View file

@ -8,6 +8,9 @@ import androidx.core.view.isVisible
import androidx.core.widget.addTextChangedListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.core.preference.Preference
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
@ -17,6 +20,8 @@ import eu.kanade.tachiyomi.databinding.MangaCategoryDialogBinding
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.library.LibrarySort
import eu.kanade.tachiyomi.util.system.materialAlertDialog
import eu.kanade.tachiyomi.util.view.setPositiveButton
import eu.kanade.tachiyomi.util.view.setTitle
import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.TriStateCheckBox
import uy.kohesive.injekt.injectLazy
@ -52,11 +57,11 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
fun dialog(activity: Activity): MaterialAlertDialogBuilder {
return activity.materialAlertDialog().apply {
setTitle(if (category == null) R.string.new_category else R.string.manage_category)
setTitle(if (category == null) MR.strings.new_category else MR.strings.manage_category)
binding = MangaCategoryDialogBinding.inflate(activity.layoutInflater)
setView(binding.root)
setNegativeButton(AR.string.cancel, null)
setPositiveButton(R.string.save) { dialog, _ ->
setPositiveButton(MR.strings.save) { dialog, _ ->
if (onPositiveButtonClick()) {
dialog.dismiss()
}
@ -94,11 +99,11 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
}
} else if (categoryExists) {
binding.categoryTextLayout.error =
binding.categoryTextLayout.context.getString(R.string.category_with_name_exists)
binding.categoryTextLayout.context.getString(MR.strings.category_with_name_exists)
return false
} else if (text.isBlank()) {
binding.categoryTextLayout.error =
binding.categoryTextLayout.context.getString(R.string.category_cannot_be_blank)
binding.categoryTextLayout.context.getString(MR.strings.category_cannot_be_blank)
return false
}
}
@ -149,7 +154,7 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
binding.categoryTextLayout.error = null
}
binding.title.hint =
category?.name ?: binding.editCategories.context.getString(R.string.category)
category?.name ?: binding.editCategories.context.getString(MR.strings.category)
binding.title.append(category?.name ?: "")
val downloadNew = preferences.downloadNewChapters().get()
setCheckbox(

View file

@ -14,6 +14,9 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.adapters.ItemAdapter
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga
@ -96,11 +99,11 @@ class SetCategoriesSheet(
init {
binding.toolbarTitle.text = context.getString(
if (addingToLibrary) R.string.add_x_to else R.string.move_x_to,
if (addingToLibrary) MR.strings.add_x_to else MR.strings.move_x_to,
if (listManga.size == 1) {
listManga.first().seriesType(context)
} else {
context.getString(R.string.selection).lowercase(Locale.ROOT)
context.getString(MR.strings.selection).lowercase(Locale.ROOT)
},
)
@ -186,16 +189,16 @@ class SetCategoriesSheet(
}
binding.addToCategoriesButton.text = context.getString(
when {
addingToLibrary || (addingMore && !nothingChanged) -> R.string.add_to_
removing -> R.string.remove_from_
nothingChanged -> R.string.keep_in_
else -> R.string.move_to_
addingToLibrary || (addingMore && !nothingChanged) -> MR.strings.add_to_
removing -> MR.strings.remove_from_
nothingChanged -> MR.strings.keep_in_
else -> MR.strings.move_to_
},
when (items.size) {
0 -> context.getString(R.string.default_category).lowercase(Locale.ROOT)
0 -> context.getString(MR.strings.default_category).lowercase(Locale.ROOT)
1 -> items.firstOrNull()?.name ?: ""
else -> context.resources.getQuantityString(
R.plurals.category_plural,
else -> context.getString(
MR.plurals.category_plural,
items.size,
items.size,
)

View file

@ -16,14 +16,14 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import eu.kanade.tachiyomi.R
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.CrashLogUtil
import eu.kanade.tachiyomi.util.system.setThemeByPref
import kotlinx.coroutines.launch
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.presentation.onboarding.InfoScreen
import yokai.presentation.theme.Size
import yokai.presentation.theme.YokaiTheme
@ -43,16 +43,16 @@ class CrashActivity : AppCompatActivity() {
YokaiTheme {
InfoScreen(
icon = Icons.Outlined.BugReport,
headingText = stringResource(R.string.crash_screen_title),
subtitleText = stringResource(R.string.crash_screen_description, stringResource(id = R.string.app_name)),
acceptText = stringResource(id = R.string.dump_crash_logs),
headingText = stringResource(MR.strings.crash_screen_title),
subtitleText = stringResource(MR.strings.crash_screen_description, stringResource(MR.strings.app_name)),
acceptText = stringResource(MR.strings.dump_crash_logs),
onAcceptClick = {
scope.launch {
CrashLogUtil(context).dumpLogs()
}
},
canAccept = true,
rejectText = stringResource(R.string.crash_screen_restart_application),
rejectText = stringResource(MR.strings.crash_screen_restart_application),
onRejectClick = {
finishAffinity()
startActivity(Intent(this@CrashActivity, MainActivity::class.java))

View file

@ -30,6 +30,8 @@ import eu.kanade.tachiyomi.util.view.isExpanded
import eu.kanade.tachiyomi.util.view.isHidden
import eu.kanade.tachiyomi.util.view.toolbarHeight
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.util.lang.getString
class DownloadBottomSheet @JvmOverloads constructor(
context: Context,
@ -124,8 +126,8 @@ class DownloadBottomSheet @JvmOverloads constructor(
private fun updateDLTitle() {
val extCount = presenter.downloadQueue.firstOrNull()
binding.titleText.text = if (extCount != null) {
resources.getString(
R.string.downloading_,
context.getString(
MR.strings.downloading_,
extCount.chapter.preferredChapterName(context, extCount.manga, preferences),
)
} else {
@ -211,7 +213,7 @@ class DownloadBottomSheet @JvmOverloads constructor(
if (presenter.downloadQueue.isEmpty()) {
binding.emptyView.show(
R.drawable.ic_download_off_24dp,
R.string.nothing_is_downloading,
MR.strings.nothing_is_downloading,
)
} else {
binding.emptyView.hide()
@ -229,7 +231,7 @@ class DownloadBottomSheet @JvmOverloads constructor(
}
private fun updateFab() {
binding.downloadFab.text = context.getString(if (isRunning) R.string.pause else R.string.resume)
binding.downloadFab.text = context.getString(if (isRunning) MR.strings.pause else MR.strings.resume)
binding.downloadFab.setIconResource(if (isRunning) R.drawable.ic_pause_24dp else R.drawable.ic_play_arrow_24dp)
}

View file

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.download
import android.view.View
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.isVisible
import androidx.recyclerview.widget.ItemTouchHelper
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download

View file

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.ui.extension
import android.content.pm.PackageInstaller
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.download.model.DownloadQueue
@ -22,6 +21,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.i18n.MR
import yokai.util.lang.getString
typealias ExtensionTuple =
Triple<List<Extension.Installed>, List<Extension.Untrusted>, List<Extension.Available>>
@ -158,8 +159,8 @@ class ExtensionBottomPresenter : BaseMigrationPresenter<ExtensionBottomSheet>(),
if (updatesSorted.isNotEmpty()) {
val header = ExtensionGroupItem(
context.resources.getQuantityString(
R.plurals._updates_pending,
context.getString(
MR.plurals._updates_pending,
updatesSorted.size,
updatesSorted.size,
),
@ -171,7 +172,7 @@ class ExtensionBottomPresenter : BaseMigrationPresenter<ExtensionBottomSheet>(),
}
}
if (installedSorted.isNotEmpty() || untrustedSorted.isNotEmpty()) {
val header = ExtensionGroupItem(context.getString(R.string.installed), installedSorted.size + untrustedSorted.size, installedSorting = preferences.installedExtensionsOrder().get())
val header = ExtensionGroupItem(context.getString(MR.strings.installed), installedSorted.size + untrustedSorted.size, installedSorting = preferences.installedExtensionsOrder().get())
items += installedSorted.map { extension ->
ExtensionItem(extension, header, currentDownloads[extension.pkgName])
}

View file

@ -14,7 +14,6 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.tabs.TabLayout
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.ExtensionsBottomSheetBinding
import eu.kanade.tachiyomi.databinding.RecyclerWithScrollerBinding
@ -39,6 +38,11 @@ import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsetsCompat
import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.isExpanded
import eu.kanade.tachiyomi.util.view.popupMenu
import eu.kanade.tachiyomi.util.view.setMessage
import eu.kanade.tachiyomi.util.view.setNegativeButton
import eu.kanade.tachiyomi.util.view.setPositiveButton
import eu.kanade.tachiyomi.util.view.setText
import eu.kanade.tachiyomi.util.view.setTitle
import eu.kanade.tachiyomi.util.view.smoothScrollToTop
import eu.kanade.tachiyomi.util.view.withFadeTransaction
import uy.kohesive.injekt.Injekt
@ -46,6 +50,8 @@ import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import yokai.domain.base.BasePreferences
import yokai.domain.base.BasePreferences.ExtensionInstaller
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
@ -230,8 +236,8 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
!presenter.preferences.hasPromptedBeforeUpdateAll().get()
) {
controller.activity!!.materialAlertDialog()
.setTitle(R.string.update_all)
.setMessage(R.string.some_extensions_may_prompt)
.setTitle(MR.strings.update_all)
.setMessage(MR.strings.some_extensions_may_prompt)
.setPositiveButton(AR.string.ok) { _, _ ->
presenter.preferences.hasPromptedBeforeUpdateAll().set(true)
updateAllExtensions(position)
@ -329,12 +335,12 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
private fun openTrustDialog(extension: Extension.Untrusted) {
val activity = controller.activity ?: return
activity.materialAlertDialog()
.setTitle(R.string.untrusted_extension)
.setMessage(R.string.untrusted_extension_message)
.setPositiveButton(R.string.trust) { _, _ ->
.setTitle(MR.strings.untrusted_extension)
.setMessage(MR.strings.untrusted_extension_message)
.setPositiveButton(MR.strings.trust) { _, _ ->
trustExtension(extension.pkgName, extension.versionCode, extension.signatureHash)
}
.setNegativeButton(R.string.uninstall) { _, _ ->
.setNegativeButton(MR.strings.uninstall) { _, _ ->
uninstallExtension(extension.pkgName)
}.show()
}
@ -433,7 +439,7 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
} else {
controller.activity!!.materialAlertDialog()
.setTitle(extName)
.setPositiveButton(R.string.remove) { _, _ ->
.setPositiveButton(MR.strings.remove) { _, _ ->
presenter.uninstallExtension(pkgName)
}
.setNegativeButton(AR.string.cancel, null)
@ -458,8 +464,8 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
override fun getPageTitle(position: Int): CharSequence {
return context.getString(
when (position) {
0 -> R.string.extensions
else -> R.string.migration
0 -> MR.strings.extensions
else -> MR.strings.migration
},
)
}

View file

@ -2,22 +2,22 @@ package eu.kanade.tachiyomi.ui.extension
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.core.preference.minusAssign
import eu.kanade.tachiyomi.core.preference.plusAssign
import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.ui.setting.SettingsLegacyController
import eu.kanade.tachiyomi.ui.setting.onChange
import eu.kanade.tachiyomi.ui.setting.titleRes
import eu.kanade.tachiyomi.ui.setting.titleMRes
import eu.kanade.tachiyomi.util.system.LocaleHelper
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
class ExtensionFilterController : SettingsLegacyController() {
private val extensionManager: ExtensionManager by injectLazy()
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
titleRes = R.string.extensions
titleMRes = MR.strings.extensions
val activeLangs = preferences.enabledLanguages().get()

View file

@ -9,6 +9,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.databinding.ExtensionCardHeaderBinding
import eu.kanade.tachiyomi.extension.model.InstalledExtensionsOrder
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.util.view.setText
class ExtensionGroupHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>) :
BaseFlexibleViewHolder(view, adapter) {

View file

@ -24,6 +24,9 @@ import eu.kanade.tachiyomi.util.system.contextCompatDrawable
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.timeSpanFromNow
import eu.kanade.tachiyomi.util.view.resetStrokeColor
import eu.kanade.tachiyomi.util.view.setText
import yokai.i18n.MR
import yokai.util.lang.getString
import java.util.*
import android.R as AR
@ -54,7 +57,7 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
ExtensionLoader.extensionUpdateDate(itemView.context, extension)
.takeUnless { it == 0L }?.let {
binding.date.isVisible = true
binding.date.text = itemView.context.timeSpanFromNow(R.string.updated_, it)
binding.date.text = itemView.context.timeSpanFromNow(MR.strings.updated_, it)
infoText.add("")
}
}
@ -65,9 +68,9 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
binding.date.text =
itemView.context.timeSpanFromNow(
if (extension.isShared) {
R.string.installed_
MR.strings.installed_
} else {
R.string.added_
MR.strings.added_
},
it,
)
@ -96,7 +99,7 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
binding.version.text = infoText.joinToString("")
binding.lang.text = LocaleHelper.getDisplayName(extension.lang)
binding.warning.text = when {
extension.isNsfw -> itemView.context.getString(R.string.nsfw_short)
extension.isNsfw -> itemView.context.getString(MR.strings.nsfw_short)
else -> ""
}.plusRepo(extension).uppercase(Locale.ROOT)
binding.installProgress.progress = item.sessionProgress ?: 0
@ -125,8 +128,8 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
private fun String.plusRepo(extension: Extension): String {
val repoText = when {
extension is Extension.Untrusted -> itemView.context.getString(R.string.untrusted)
extension is Extension.Installed && extension.isObsolete -> itemView.context.getString(R.string.obsolete)
extension is Extension.Untrusted -> itemView.context.getString(MR.strings.untrusted)
extension is Extension.Installed && extension.isObsolete -> itemView.context.getString(MR.strings.obsolete)
else -> ""
}
@ -157,12 +160,12 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
if (installStep != null) {
setText(
when (installStep) {
InstallStep.Pending -> R.string.pending
InstallStep.Downloading -> R.string.downloading
InstallStep.Loading -> R.string.loading
InstallStep.Installing -> R.string.installing
InstallStep.Installed -> R.string.installed
InstallStep.Error -> R.string.retry
InstallStep.Pending -> MR.strings.pending
InstallStep.Downloading -> MR.strings.downloading
InstallStep.Loading -> MR.strings.loading
InstallStep.Installing -> MR.strings.installing
InstallStep.Installed -> MR.strings.installed
InstallStep.Error -> MR.strings.retry
else -> return@with
},
)
@ -176,18 +179,18 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
isActivated = true
stateListAnimator = AnimatorInflater.loadStateListAnimator(context, R.animator.icon_btn_state_list_anim)
rippleColor = ColorStateList.valueOf(context.getColor(R.color.on_secondary_highlight))
setText(R.string.update)
setText(MR.strings.update)
}
else -> {
setText(R.string.settings)
setText(MR.strings.settings)
}
}
} else if (extension is Extension.Untrusted) {
resetStrokeColor()
setText(R.string.trust)
setText(MR.strings.trust)
} else {
resetStrokeColor()
setText(if (adapter.installPrivately) R.string.add else R.string.install)
setText(if (adapter.installPrivately) MR.strings.add else MR.strings.install)
}
}
}

View file

@ -43,6 +43,7 @@ import eu.kanade.tachiyomi.ui.setting.switchPreference
import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.view.openInBrowser
import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.setAction
import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.widget.LinearLayoutManagerAccurateOffset
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
@ -55,6 +56,8 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.util.lang.getString
@SuppressLint("RestrictedApi")
class ExtensionDetailsController(bundle: Bundle? = null) :
@ -85,7 +88,7 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
override val presenter = ExtensionDetailsPresenter(args.getString(PKGNAME_KEY)!!)
override fun getTitle(): String? {
return resources?.getString(R.string.extension_info)
return view?.context?.getString(MR.strings.extension_info)
}
@SuppressLint("PrivateResource")
@ -193,7 +196,7 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
Logger.d { "Cleared $cleared cookies for: ${urls.joinToString()}" }
val context = view?.context ?: return
binding.coordinator.snack(context.getString(R.string.cookies_cleared))
binding.coordinator.snack(context.getString(MR.strings.cookies_cleared))
}
private fun addPreferencesForSource(screen: PreferenceScreen, source: Source, isMultiSource: Boolean, isMultiLangSingleSource: Boolean) {
@ -218,12 +221,12 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
} else {
binding.coordinator.snack(
context.getString(
R.string._must_be_enabled_first,
title,
MR.strings._must_be_enabled_first,
title?.toString() ?: "",
),
Snackbar.LENGTH_LONG,
) {
setAction(R.string.enable) {
setAction(MR.strings.enable) {
preferences.enabledLanguages() += source.lang
isChecked = true
toggleSource(source, true)

View file

@ -13,6 +13,10 @@ import eu.kanade.tachiyomi.ui.extension.getApplicationIcon
import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.materialAlertDialog
import eu.kanade.tachiyomi.util.view.inflate
import eu.kanade.tachiyomi.util.view.setPositiveButton
import eu.kanade.tachiyomi.util.view.setText
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
class ExtensionDetailsHeaderAdapter(private val presenter: ExtensionDetailsPresenter) :
@ -45,8 +49,8 @@ class ExtensionDetailsHeaderAdapter(private val presenter: ExtensionDetailsPrese
extension.getApplicationIcon(context)?.let { binding.extensionIcon.setImageDrawable(it) }
binding.extensionTitle.text = extension.name
binding.extensionVersion.text = context.getString(R.string.version_, extension.versionName)
binding.extensionLang.text = context.getString(R.string.language_, LocaleHelper.getSourceDisplayName(extension.lang, context))
binding.extensionVersion.text = context.getString(MR.strings.version_, extension.versionName)
binding.extensionLang.text = context.getString(MR.strings.language_, LocaleHelper.getSourceDisplayName(extension.lang, context))
binding.extensionNsfw.isVisible = extension.isNsfw
binding.extensionPkg.text = extension.pkgName
@ -56,7 +60,7 @@ class ExtensionDetailsHeaderAdapter(private val presenter: ExtensionDetailsPrese
} else {
context.materialAlertDialog()
.setTitle(extension.name)
.setPositiveButton(R.string.remove) { _, _ ->
.setPositiveButton(MR.strings.remove) { _, _ ->
presenter.uninstallExtension()
}
.setNegativeButton(AR.string.cancel, null)
@ -73,12 +77,12 @@ class ExtensionDetailsHeaderAdapter(private val presenter: ExtensionDetailsPrese
binding.extensionAppInfoButton.isVisible = extension.isShared
if (!extension.isShared) {
binding.extensionUninstallButton.text = context.getString(R.string.remove)
binding.extensionUninstallButton.text = context.getString(MR.strings.remove)
}
if (extension.isObsolete) {
binding.extensionWarningBanner.isVisible = true
binding.extensionWarningBanner.setText(R.string.obsolete_extension_message)
binding.extensionWarningBanner.setText(MR.strings.obsolete_extension_message)
}
}
}

View file

@ -10,6 +10,9 @@ import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.shape.MaterialShapeDrawable
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.databinding.UnreadDownloadBadgeBinding
import eu.kanade.tachiyomi.util.system.contextCompatColor
import eu.kanade.tachiyomi.util.system.dpToPx
@ -67,7 +70,7 @@ class LibraryBadge @JvmOverloads constructor(context: Context, attrs: AttributeS
return@with
}
text = if (downloads == -2) {
resources.getString(R.string.local)
context.getString(MR.strings.local)
} else {
downloads.toString()
}
@ -171,7 +174,7 @@ class LibraryBadge @JvmOverloads constructor(context: Context, attrs: AttributeS
binding.unreadAngle.isVisible = false
binding.unreadText.updatePaddingRelative(start = 5.dpToPx)
binding.unreadText.isVisible = inLibrary
binding.unreadText.text = resources.getText(R.string.in_library)
binding.unreadText.text = context.getString(MR.strings.in_library)
binding.unreadText.background =
MaterialShapeDrawable(makeShapeCorners(radius, radius)).apply {
this.fillColor =

View file

@ -6,6 +6,9 @@ import android.view.View
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -191,7 +194,7 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
val preferences: PreferencesHelper by injectLazy()
val db: DatabaseHelper by injectLazy()
val context = recyclerView.context
if (position == itemCount - 1) return context.getString(R.string.bottom)
if (position == itemCount - 1) return context.getString(MR.strings.bottom)
return when (val item: IFlexible<*>? = getItem(position)) {
is LibraryHeaderItem -> {
vibrateOnCategoryChange(item.category.name)
@ -205,7 +208,7 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
LibrarySort.DragAndDrop -> {
if (item.header.category.isDynamic) {
val category = db.getCategoriesForManga(item.manga).executeAsBlocking().firstOrNull()?.name
category ?: context.getString(R.string.default_value)
category ?: context.getString(MR.strings.default_value)
} else {
val title = item.manga.title
if (preferences.removeArticles().get()) {
@ -219,27 +222,27 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
val id = item.manga.id ?: return ""
val history = db.getChapters(id).executeAsBlocking()
val last = history.maxOfOrNull { it.date_fetch }
context.timeSpanFromNow(R.string.fetched_, last ?: 0)
context.timeSpanFromNow(MR.strings.fetched_, last ?: 0)
}
LibrarySort.LastRead -> {
val id = item.manga.id ?: return ""
val history = db.getHistoryByMangaId(id).executeAsBlocking()
val last = history.maxOfOrNull { it.last_read }
context.timeSpanFromNow(R.string.read_, last ?: 0)
context.timeSpanFromNow(MR.strings.read_, last ?: 0)
}
LibrarySort.Unread -> {
val unread = item.manga.unread
if (unread > 0) {
context.getString(R.string._unread, unread)
context.getString(MR.strings._unread, unread)
} else {
context.getString(R.string.read)
context.getString(MR.strings.read)
}
}
LibrarySort.TotalChapters -> {
val total = item.manga.totalChapters
if (total > 0) {
recyclerView.resources.getQuantityString(
R.plurals.chapters_plural,
recyclerView.context.getString(
MR.plurals.chapters_plural,
total,
total,
)
@ -248,10 +251,10 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
}
}
LibrarySort.LatestChapter -> {
context.timeSpanFromNow(R.string.updated_, item.manga.last_update)
context.timeSpanFromNow(MR.strings.updated_, item.manga.last_update)
}
LibrarySort.DateAdded -> {
context.timeSpanFromNow(R.string.added_, item.manga.date_added)
context.timeSpanFromNow(MR.strings.added_, item.manga.date_added)
}
LibrarySort.Title -> {
val title = if (preferences.removeArticles().get()) {

View file

@ -51,12 +51,16 @@ import com.bluelinelabs.conductor.ControllerChangeType
import com.github.florent37.viewtooltip.ViewTooltip
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import dev.icerock.moko.resources.StringResource
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.flexibleadapter.items.IHeader
import eu.davidea.flexibleadapter.items.ISectionable
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.core.preference.Preference
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.LibraryManga
@ -116,10 +120,15 @@ import eu.kanade.tachiyomi.util.view.isExpanded
import eu.kanade.tachiyomi.util.view.isHidden
import eu.kanade.tachiyomi.util.view.isSettling
import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.setAction
import eu.kanade.tachiyomi.util.view.setMessage
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
import eu.kanade.tachiyomi.util.view.setPositiveButton
import eu.kanade.tachiyomi.util.view.setStyle
import eu.kanade.tachiyomi.util.view.setTitle
import eu.kanade.tachiyomi.util.view.smoothScrollToTop
import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.text
import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.EmptyView
import kotlinx.coroutines.delay
@ -259,7 +268,7 @@ open class LibraryController(
private var showAllCategoriesView: ImageView? = null
override fun getTitle(): String? {
setSubtitle()
return view?.context?.getString(R.string.library)
return view?.context?.getString(MR.strings.library)
}
override fun getSearchTitle(): String? {
@ -270,7 +279,7 @@ open class LibraryController(
) {
"\"${preferences.librarySearchSuggestion().get()}\""
} else {
view?.context?.getString(R.string.your_library)?.lowercase(Locale.ROOT)
view?.context?.getString(MR.strings.your_library)?.lowercase(Locale.ROOT)
},
)
}
@ -501,7 +510,7 @@ open class LibraryController(
filterTooltip =
ViewTooltip.on(activity, icon).autoHide(false, 0L).align(ViewTooltip.ALIGN.START)
.position(ViewTooltip.Position.TOP)
.text(R.string.tap_library_to_show_filters)
.text(MR.strings.tap_library_to_show_filters)
.textColor(activity.getResourceColor(R.attr.colorOnSecondary))
.color(activity.getResourceColor(R.attr.colorSecondary))
.textSize(TypedValue.COMPLEX_UNIT_SP, 15f).withShadow(false)
@ -537,7 +546,7 @@ open class LibraryController(
MaterialMenuSheet(
activity!!,
items,
activity!!.getString(R.string.group_library_by),
activity!!.getString(MR.strings.group_library_by),
presenter.groupType,
) { _, item ->
if (!isSubClass) {
@ -742,7 +751,7 @@ open class LibraryController(
MaterialMenuSheet(
activity!!,
items,
it.context.getString(R.string.jump_to_category),
it.context.getString(MR.strings.jump_to_category),
activeCategory,
300.dpToPx,
) { _, item ->
@ -948,10 +957,10 @@ open class LibraryController(
private fun updateLibrary(category: Category? = null) {
val view = view ?: return
LibraryUpdateJob.startNow(view.context, category)
snack = view.snack(R.string.updating_library) {
snack = view.snack(MR.strings.updating_library) {
anchorView = anchorView()
this.view.elevation = 15f.dpToPx
setAction(R.string.cancel) {
setAction(MR.strings.cancel) {
LibraryUpdateJob.stop(context)
viewScope.launchUI {
NotificationReceiver.dismissNotification(
@ -1116,13 +1125,13 @@ open class LibraryController(
binding.emptyView.show(
R.drawable.ic_heart_off_24dp,
if (hasActiveFilters) {
R.string.no_matches_for_filters
MR.strings.no_matches_for_filters
} else {
R.string.library_is_empty_add_from_browse
MR.strings.library_is_empty_add_from_browse
},
if (!hasActiveFilters) {
listOf(
EmptyView.Action(R.string.getting_started_guide) {
EmptyView.Action(MR.strings.getting_started_guide) {
activity?.openInBrowser("https://tachiyomi.org/docs/guides/getting-started#_2-adding-sources")
},
)
@ -1681,7 +1690,7 @@ open class LibraryController(
} else {
if (presenter.mangaIsInCategory(item.manga, newHeader?.category?.id)) {
adapter.moveItem(position, lastItemPosition!!)
snack = view?.snack(R.string.already_in_category) {
snack = view?.snack(MR.strings.already_in_category) {
anchorView = anchorView()
view.elevation = 15f.dpToPx
}
@ -1719,11 +1728,11 @@ open class LibraryController(
presenter.moveMangaToCategory(manga, category.id, mangaIds)
snack?.dismiss()
snack = view?.snack(
resources!!.getString(R.string.moved_to_, category.name),
view!!.context!!.getString(MR.strings.moved_to_, category.name),
) {
anchorView = anchorView()
view.elevation = 15f.dpToPx
setAction(R.string.undo) {
setAction(MR.strings.undo) {
manga.category = category.id!!
presenter.moveMangaToCategory(manga, oldCatId, mangaIds)
}
@ -1735,11 +1744,11 @@ open class LibraryController(
val inQueue = LibraryUpdateJob.categoryInQueue(category.id)
snack?.dismiss()
snack = view?.snack(
resources!!.getString(
view!!.context!!.getString(
when {
inQueue -> R.string._already_in_queue
LibraryUpdateJob.isRunning(view!!.context) -> R.string.adding_category_to_queue
else -> R.string.updating_
inQueue -> MR.strings._already_in_queue
LibraryUpdateJob.isRunning(view!!.context) -> MR.strings.adding_category_to_queue
else -> MR.strings.updating_
},
category.name,
),
@ -1747,7 +1756,7 @@ open class LibraryController(
) {
anchorView = anchorView()
view.elevation = 15f.dpToPx
setAction(R.string.cancel) {
setAction(MR.strings.cancel) {
LibraryUpdateJob.stop(context)
viewScope.launchUI {
NotificationReceiver.dismissNotification(
@ -1882,7 +1891,7 @@ open class LibraryController(
val searchItem = activityBinding?.searchToolbar?.searchItem
val searchView = activityBinding?.searchToolbar?.searchView
activityBinding?.searchToolbar?.setQueryHint(resources?.getString(R.string.library_search_hint), query.isEmpty())
activityBinding?.searchToolbar?.setQueryHint(view?.context?.getString(MR.strings.library_search_hint), query.isEmpty())
showAllCategoriesView = showAllCategoriesView ?: (searchView as? MiniSearchView)?.addSearchModifierIcon { context ->
ImageView(context).apply {
@ -1898,7 +1907,7 @@ open class LibraryController(
setImageResource(R.drawable.ic_show_all_categories_24dp)
background = context.getResourceDrawable(R.attr.selectableItemBackgroundBorderless)
imageTintList = ColorStateList.valueOf(context.getResourceColor(R.attr.actionBarTintColor))
compatToolTipText = resources?.getText(R.string.show_all_categories)
compatToolTipText = view?.context?.getString(MR.strings.show_all_categories)
}
}!!
@ -2014,7 +2023,7 @@ open class LibraryController(
if (count == 0) {
destroyActionModeIfNeeded()
} else {
mode.title = resources?.getString(R.string.selected_, count)
mode.title = view?.context?.getString(MR.strings.selected_, count)
}
return false
}
@ -2026,12 +2035,12 @@ open class LibraryController(
R.id.action_share -> shareManga()
R.id.action_delete -> {
val options = arrayOf(
R.string.remove_downloads,
R.string.remove_from_library,
MR.strings.remove_downloads,
MR.strings.remove_from_library,
)
.map { activity!!.getString(it) }
activity!!.materialAlertDialog()
.setTitle(R.string.remove)
.setTitle(MR.strings.remove)
.setMultiChoiceItems(
options.toTypedArray(),
options.map { true }.toBooleanArray(),
@ -2041,7 +2050,7 @@ open class LibraryController(
listView.setItemChecked(position, true)
}
}
.setPositiveButton(R.string.remove) { dialog, _ ->
.setPositiveButton(MR.strings.remove) { dialog, _ ->
val listView = (dialog as AlertDialog).listView
if (listView.isItemChecked(1)) {
deleteMangasFromLibrary()
@ -2060,18 +2069,18 @@ open class LibraryController(
}
R.id.action_mark_as_read -> {
activity!!.materialAlertDialog()
.setMessage(R.string.mark_all_chapters_as_read)
.setPositiveButton(R.string.mark_as_read) { _, _ ->
markReadStatus(R.string.marked_as_read, true)
.setMessage(MR.strings.mark_all_chapters_as_read)
.setPositiveButton(MR.strings.mark_as_read) { _, _ ->
markReadStatus(MR.strings.marked_as_read, true)
}
.setNegativeButton(AR.string.cancel, null)
.show()
}
R.id.action_mark_as_unread -> {
activity!!.materialAlertDialog()
.setMessage(R.string.mark_all_chapters_as_unread)
.setPositiveButton(R.string.mark_as_unread) { _, _ ->
markReadStatus(R.string.marked_as_unread, false)
.setMessage(MR.strings.mark_all_chapters_as_unread)
.setPositiveButton(MR.strings.mark_as_unread) { _, _ ->
markReadStatus(MR.strings.marked_as_unread, false)
}
.setNegativeButton(AR.string.cancel, null)
.show()
@ -2090,7 +2099,7 @@ open class LibraryController(
return true
}
private fun markReadStatus(resource: Int, markRead: Boolean) {
private fun markReadStatus(resource: StringResource, markRead: Boolean) {
val mapMangaChapters = presenter.markReadStatus(selectedMangas.toList(), markRead)
destroyActionModeIfNeeded()
snack?.dismiss()
@ -2098,7 +2107,7 @@ open class LibraryController(
anchorView = anchorView()
view.elevation = 15f.dpToPx
var undoing = false
setAction(R.string.undo) {
setAction(MR.strings.undo) {
presenter.undoMarkReadStatus(mapMangaChapters)
undoing = true
}
@ -2132,7 +2141,7 @@ open class LibraryController(
type = "text/*"
putExtra(Intent.EXTRA_TEXT, urls)
}
startActivity(Intent.createChooser(intent, context.getString(R.string.share)))
startActivity(Intent.createChooser(intent, context.getString(MR.strings.share)))
}
open fun deleteMangasFromLibrary() {
@ -2141,13 +2150,13 @@ open class LibraryController(
destroyActionModeIfNeeded()
snack?.dismiss()
snack = view?.snack(
activity?.getString(R.string.removed_from_library) ?: "",
activity?.getString(MR.strings.removed_from_library) ?: "",
Snackbar.LENGTH_INDEFINITE,
) {
anchorView = anchorView()
view.elevation = 15f.dpToPx
var undoing = false
setAction(R.string.undo) {
setAction(MR.strings.undo) {
presenter.reAddMangas(mangas)
undoing = true
}

View file

@ -14,6 +14,9 @@ import coil3.dispose
import coil3.size.Precision
import coil3.size.Scale
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.coil.loadManga
import eu.kanade.tachiyomi.databinding.MangaGridItemBinding

View file

@ -1,6 +1,10 @@
package eu.kanade.tachiyomi.ui.library
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
object LibraryGroup {
@ -13,16 +17,16 @@ object LibraryGroup {
const val BY_LANGUAGE = 7
const val UNGROUPED = 5
fun groupTypeStringRes(type: Int, hasCategories: Boolean = true): Int {
fun groupTypeStringRes(type: Int, hasCategories: Boolean = true): StringResource {
return when (type) {
BY_STATUS -> R.string.status
BY_TAG -> R.string.tag
BY_SOURCE -> R.string.sources
BY_TRACK_STATUS -> R.string.tracking_status
BY_AUTHOR -> R.string.author
BY_LANGUAGE -> R.string.language
UNGROUPED -> R.string.ungrouped
else -> if (hasCategories) R.string.categories else R.string.ungrouped
BY_STATUS -> MR.strings.status
BY_TAG -> MR.strings.tag
BY_SOURCE -> MR.strings.sources
BY_TRACK_STATUS -> MR.strings.tracking_status
BY_AUTHOR -> MR.strings.author
BY_LANGUAGE -> MR.strings.language
UNGROUPED -> MR.strings.ungrouped
else -> if (hasCategories) MR.strings.categories else MR.strings.ungrouped
}
}

View file

@ -18,6 +18,9 @@ import androidx.swiperefreshlayout.widget.CircularProgressDrawable
import com.github.florent37.viewtooltip.ViewTooltip
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -29,6 +32,8 @@ import eu.kanade.tachiyomi.util.system.contextCompatDrawable
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.compatToolTipText
import eu.kanade.tachiyomi.util.view.setText
import eu.kanade.tachiyomi.util.view.text
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -60,7 +65,7 @@ class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) :
}
}
binding.categorySort.setOnClickListener { it.post { showCatSortOptions() } }
binding.categorySort.compatToolTipText = view.context.getString(R.string.sort)
binding.categorySort.compatToolTipText = view.context.getString(MR.strings.sort)
binding.checkbox.setOnClickListener { selectAll() }
runningDrawable.setStyle(CircularProgressDrawable.DEFAULT)
@ -128,7 +133,7 @@ class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) :
if (!tutorial.get()) {
ViewTooltip.on(itemView.context as? Activity, binding.categoryTitle).autoHide(true, 5000L)
.align(ViewTooltip.ALIGN.START).position(ViewTooltip.Position.TOP)
.text(R.string.long_press_category)
.text(MR.strings.long_press_category)
.color(itemView.context.getResourceColor(R.attr.colorSecondary))
.textSize(TypedValue.COMPLEX_UNIT_SP, 15f).textColor(Color.WHITE)
.withShadow(false).corner(30).arrowWidth(15).arrowHeight(15).distanceWithView(0)
@ -282,7 +287,7 @@ class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) :
val sheet = MaterialMenuSheet(
activity,
items,
activity.getString(R.string.sort_by),
activity.getString(MR.strings.sort_by),
sortingMode?.mainValue,
) { sheet, item ->
onCatSortClicked(category, item)

View file

@ -7,6 +7,9 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Category
class LibraryHeaderItem(

View file

@ -5,6 +5,9 @@ import androidx.core.graphics.ColorUtils
import androidx.core.view.isVisible
import com.google.android.material.card.MaterialCardView
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.util.isLocal
import eu.kanade.tachiyomi.util.system.getResourceColor

View file

@ -16,6 +16,9 @@ import eu.davidea.flexibleadapter.items.AbstractSectionableItem
import eu.davidea.flexibleadapter.items.IFilterable
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.MangaGridItemBinding

View file

@ -6,6 +6,9 @@ import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import coil3.dispose
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.coil.loadManga
import eu.kanade.tachiyomi.databinding.MangaListItemBinding
import eu.kanade.tachiyomi.util.lang.highlightText
@ -49,9 +52,9 @@ class LibraryListHolder(
} else {
binding.title.text = itemView.context.getString(
if (adapter.hasActiveFilters && item.manga.realMangaCount >= 1) {
R.string.no_matches_for_filters_short
MR.strings.no_matches_for_filters_short
} else {
R.string.category_is_empty
MR.strings.category_is_empty
},
)
}

View file

@ -1,6 +1,9 @@
package eu.kanade.tachiyomi.ui.library
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.core.preference.minusAssign
import eu.kanade.tachiyomi.core.preference.plusAssign
import eu.kanade.tachiyomi.data.cache.CoverCache
@ -809,7 +812,7 @@ class LibraryPresenter(
return headerItem
}
val unknown = context.getString(R.string.unknown)
val unknown = context.getString(MR.strings.unknown)
val removedManga = mutableListOf<LibraryItem>()
val items = libraryMangaList.mapNotNull map@ { manga ->
when (groupType) {
@ -845,7 +848,7 @@ class LibraryPresenter(
service.getStatus(track.status)
}
} else {
view?.view?.context?.getString(R.string.not_tracked) ?: ""
view?.view?.context?.getString(MR.strings.not_tracked) ?: ""
}
val header = makeOrGetHeader(status)
val item = LibraryItem(manga, header, viewContext)
@ -1167,7 +1170,7 @@ class LibraryPresenter(
return headerItem
}
val unknown = context.getString(R.string.unknown)
val unknown = context.getString(MR.strings.unknown)
val items = libraryManga.map { manga ->
when (groupType) {
BY_TAG -> {
@ -1196,7 +1199,7 @@ class LibraryPresenter(
service.getStatus(track.status)
}
} else {
view?.view?.context?.getString(R.string.not_tracked) ?: ""
view?.view?.context?.getString(MR.strings.not_tracked) ?: ""
}
listOf(LibraryItem(manga, makeOrGetHeader(status), viewContext))
}
@ -1320,12 +1323,12 @@ class LibraryPresenter(
private fun mapTrackingOrder(status: String): String {
with(context) {
return when (status) {
getString(R.string.reading), getString(R.string.currently_reading) -> "1"
getString(R.string.rereading) -> "2"
getString(R.string.plan_to_read), getString(R.string.want_to_read) -> "3"
getString(R.string.on_hold), getString(R.string.paused) -> "4"
getString(R.string.completed) -> "5"
getString(R.string.dropped) -> "6"
getString(MR.strings.reading), getString(MR.strings.currently_reading) -> "1"
getString(MR.strings.rereading) -> "2"
getString(MR.strings.plan_to_read), getString(MR.strings.want_to_read) -> "3"
getString(MR.strings.on_hold), getString(MR.strings.paused) -> "4"
getString(MR.strings.completed) -> "5"
getString(MR.strings.dropped) -> "6"
else -> "7"
}
}

View file

@ -2,31 +2,35 @@ package eu.kanade.tachiyomi.ui.library
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet
enum class LibrarySort(
val mainValue: Int,
@StringRes private val stringRes: Int,
private val stringRes: StringResource,
@DrawableRes private val iconRes: Int,
private val catValue: Int = mainValue,
@StringRes private val dynamicStringRes: Int = stringRes,
private val dynamicStringRes: StringResource = stringRes,
@DrawableRes private val dynamicIconRes: Int = iconRes,
) {
Title(0, R.string.title, R.drawable.ic_sort_by_alpha_24dp),
LastRead(1, R.string.last_read, R.drawable.ic_recent_read_outline_24dp, 3),
LatestChapter(2, R.string.latest_chapter, R.drawable.ic_new_releases_24dp, 1),
Unread(3, R.string.unread, R.drawable.ic_eye_24dp, 2),
TotalChapters(4, R.string.total_chapters, R.drawable.ic_sort_by_numeric_24dp),
DateAdded(5, R.string.date_added, R.drawable.ic_heart_outline_24dp),
DateFetched(6, R.string.date_fetched, R.drawable.ic_calendar_text_outline_24dp),
Title(0, MR.strings.title, R.drawable.ic_sort_by_alpha_24dp),
LastRead(1, MR.strings.last_read, R.drawable.ic_recent_read_outline_24dp, 3),
LatestChapter(2, MR.strings.latest_chapter, R.drawable.ic_new_releases_24dp, 1),
Unread(3, MR.strings.unread, R.drawable.ic_eye_24dp, 2),
TotalChapters(4, MR.strings.total_chapters, R.drawable.ic_sort_by_numeric_24dp),
DateAdded(5, MR.strings.date_added, R.drawable.ic_heart_outline_24dp),
DateFetched(6, MR.strings.date_fetched, R.drawable.ic_calendar_text_outline_24dp),
DragAndDrop(
7,
R.string.drag_and_drop,
MR.strings.drag_and_drop,
R.drawable.ic_swap_vert_24dp,
7,
R.string.category,
MR.strings.category,
R.drawable.ic_label_outline_24dp,
),
@ -51,7 +55,6 @@ enum class LibrarySort(
return "$type,ASCENDING"
}
@StringRes
fun stringRes(isDynamic: Boolean) = if (isDynamic) dynamicStringRes else stringRes
@DrawableRes

View file

@ -10,6 +10,9 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.databinding.MaterialTextButtonBinding
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
@ -77,7 +80,7 @@ class SearchGlobalItem : AbstractFlexibleItem<SearchGlobalItem.Holder>() {
}
fun bind(string: String) {
binding.button.text = view.context.getString(R.string.search_globally, string)
binding.button.text = view.context.getString(MR.strings.search_globally, string)
}
override fun onLongClick(view: View?): Boolean {

View file

@ -3,6 +3,9 @@ package eu.kanade.tachiyomi.ui.library.display
import android.content.Context
import android.util.AttributeSet
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.databinding.LibraryCategoryLayoutBinding
import eu.kanade.tachiyomi.util.bindToPreference
import eu.kanade.tachiyomi.util.lang.withSubtitle
@ -24,8 +27,8 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
categoryShow.bindToPreference(preferences.showCategoryInTitle()) {
controller?.showMiniBar()
}
dynamicToBottom.text = context.getString(R.string.move_dynamic_to_bottom)
.withSubtitle(context, R.string.when_grouping_by_sources_tags)
dynamicToBottom.text = context.getString(MR.strings.move_dynamic_to_bottom)
.withSubtitle(context, MR.strings.when_grouping_by_sources_tags)
dynamicToBottom.bindToPreference(preferences.collapsedDynamicAtBottom()) {
controller?.presenter?.getLibrary()
}

View file

@ -5,6 +5,9 @@ import android.util.AttributeSet
import android.view.View
import com.google.android.material.slider.Slider
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.databinding.LibraryDisplayLayoutBinding
import eu.kanade.tachiyomi.util.bindToPreference
import eu.kanade.tachiyomi.util.lang.addBetaTag
@ -30,7 +33,7 @@ class LibraryDisplayView @JvmOverloads constructor(context: Context, attrs: Attr
binding.staggeredGrid.isEnabled = !it
}
binding.outlineOnCovers.bindToPreference(uiPreferences.outlineOnCovers())
binding.staggeredGrid.text = context.getString(R.string.use_staggered_grid).addBetaTag(context)
binding.staggeredGrid.text = context.getString(MR.strings.use_staggered_grid).addBetaTag(context)
binding.staggeredGrid.isEnabled = !uiPreferences.uniformGrid().get()
binding.staggeredGrid.bindToPreference(preferences.useStaggeredGrid())
binding.gridSeekbar.value = ((preferences.gridSize().get() + .5f) * 2f).roundToInt().toFloat()
@ -43,9 +46,9 @@ class LibraryDisplayView @JvmOverloads constructor(context: Context, attrs: Attr
val mainText = (mainView ?: this@LibraryDisplayView).rowsForValue(it).toString()
val mainOrientation = context.getString(
if (context.isLandscape()) {
R.string.landscape
MR.strings.landscape
} else {
R.string.portrait
MR.strings.portrait
},
)
val alt = (
@ -60,9 +63,9 @@ class LibraryDisplayView @JvmOverloads constructor(context: Context, attrs: Attr
val altText = alt.numberOfRowsForValue(it).toString()
val altOrientation = context.getString(
if (context.isLandscape()) {
R.string.portrait
MR.strings.portrait
} else {
R.string.landscape
MR.strings.landscape
},
)
"$mainOrientation: $mainText$altOrientation: $altText"
@ -95,8 +98,8 @@ class LibraryDisplayView @JvmOverloads constructor(context: Context, attrs: Attr
private fun setGridText(progress: Float) {
with(binding.gridSizeText) {
val rows = (mainView ?: this@LibraryDisplayView).rowsForValue(progress)
val titleText = context.getString(R.string.grid_size)
val subtitleText = context.getString(R.string._per_row, rows)
val titleText = context.getString(MR.strings.grid_size)
val subtitleText = context.getString(MR.strings._per_row, rows)
text = titleText.withSubtitle(context, subtitleText)
}
}

View file

@ -4,7 +4,11 @@ import android.view.View
import android.view.View.inflate
import androidx.core.view.isVisible
import com.bluelinelabs.conductor.Controller
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.ui.library.LibraryController
import eu.kanade.tachiyomi.ui.setting.controllers.SettingsLibraryController
import eu.kanade.tachiyomi.util.system.contextCompatDrawable
@ -27,7 +31,7 @@ open class TabbedLibraryDisplaySheet(val controller: Controller) :
}
displayView.mainView = controller.view
binding.menu.isVisible = controller !is SettingsLibraryController
binding.menu.compatToolTipText = context.getString(R.string.more_library_settings)
binding.menu.compatToolTipText = context.getString(MR.strings.more_library_settings)
binding.menu.setImageDrawable(context.contextCompatDrawable(R.drawable.ic_outline_settings_24dp))
binding.menu.setOnClickListener {
controller.router.pushController(SettingsLibraryController().withFadeTransaction())
@ -47,9 +51,9 @@ open class TabbedLibraryDisplaySheet(val controller: Controller) :
categoryView,
)
override fun getTabTitles(): List<Int> = listOf(
R.string.display,
R.string.badges,
R.string.categories,
override fun getTabTitles(): List<StringResource> = listOf(
MR.strings.display,
MR.strings.badges,
MR.strings.categories,
)
}

View file

@ -14,6 +14,8 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.ExpandedFilterItemBinding
import eu.kanade.tachiyomi.databinding.ExpandedFilterItemTextViewBinding
import eu.kanade.tachiyomi.util.system.dpToPx
import yokai.i18n.MR
import yokai.util.lang.getString
class ExpandedFilterItem(val filter: LibraryFilter) : AbstractItem<FastAdapter.ViewHolder<ExpandedFilterItem>>() {
@ -43,7 +45,7 @@ class ExpandedFilterItem(val filter: LibraryFilter) : AbstractItem<FastAdapter.V
val allTextView =
ExpandedFilterItemTextViewBinding.inflate(LayoutInflater.from(itemView.context)).root
binding.filterLinearLayout.addView(allTextView)
allTextView.text = itemView.context.getString(R.string.all)
allTextView.text = itemView.context.getString(MR.strings.all)
for (i in 0..<item.filter.filters.size) {
val divider = MaterialDivider(itemView.context)
binding.filterLinearLayout.addView(divider)

View file

@ -18,7 +18,6 @@ import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.adapters.ItemAdapter
import com.mikepenz.fastadapter.listeners.ClickEventHook
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.ExpandedFilterSheetBinding
import eu.kanade.tachiyomi.ui.main.MainActivity
@ -27,8 +26,12 @@ import eu.kanade.tachiyomi.util.system.materialAlertDialog
import eu.kanade.tachiyomi.util.system.rootWindowInsetsCompat
import eu.kanade.tachiyomi.util.view.checkHeightThen
import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.setPositiveButton
import eu.kanade.tachiyomi.util.view.setTitle
import eu.kanade.tachiyomi.widget.E2EBottomSheetDialog
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
class ExpandedFilterSheet(
@ -107,7 +110,7 @@ class ExpandedFilterSheet(
item.filter.activeFilter = index
v.isActivated = true
when (filters[position].headerName) {
context.getString(R.string.tracking) -> {
context.getString(MR.strings.tracking) -> {
if (index == 0 && trackerItem != null && itemAdapter.adapterItems.contains(
trackerItem,
)
@ -121,13 +124,13 @@ class ExpandedFilterSheet(
}
}
context.getString(R.string.read_progress), context.getString(R.string.unread) -> {
context.getString(MR.strings.read_progress), context.getString(MR.strings.unread) -> {
if (index != 0) {
val otherName =
if (filters[position].headerName == context.getString(R.string.read_progress)) {
context.getString(R.string.unread)
if (filters[position].headerName == context.getString(MR.strings.read_progress)) {
context.getString(MR.strings.unread)
} else {
context.getString(R.string.read_progress)
context.getString(MR.strings.read_progress)
}
val otherFilter =
filters.find { it.headerName == otherName } ?: return
@ -146,7 +149,7 @@ class ExpandedFilterSheet(
},
)
itemAdapter.set(filters.map(::ExpandedFilterItem))
val trackingFilter = filters.find { it.headerName == context.getString(R.string.tracking) }
val trackingFilter = filters.find { it.headerName == context.getString(MR.strings.tracking) }
if ((trackingFilter?.activeFilter ?: 0) > 0 && trackerItem != null) {
itemAdapter.add(filters.indexOf(trackingFilter) + 1, trackerItem)
}
@ -176,10 +179,10 @@ class ExpandedFilterSheet(
adapter.isHandleDragEnabled = true
adapter.isLongPressDragEnabled = true
context.materialAlertDialog()
.setTitle(R.string.reorder_filters)
.setTitle(MR.strings.reorder_filters)
.setView(recycler)
.setNegativeButton(AR.string.cancel, null)
.setPositiveButton(R.string.reorder) { _, _ ->
.setPositiveButton(MR.strings.reorder) { _, _ ->
val order = adapter.currentItems.map { it.char }.joinToString("")
preferences.filterOrder().set(order)
recycler.adapter = null
@ -234,7 +237,7 @@ class ExpandedFilterSheet(
clearFilterCallback()
}
private fun applyFilters() {
val trackingFilter = filters.find { it.headerName == context.getString(R.string.tracking) }
val trackingFilter = filters.find { it.headerName == context.getString(MR.strings.tracking) }
if (trackingFilter?.activeFilter == 0 && trackerItem != null) {
trackerItem.filter.activeFilter = 0
}

View file

@ -7,12 +7,12 @@ import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.annotation.StringRes
import androidx.core.view.WindowInsetsCompat.Type.systemBars
import androidx.core.view.isVisible
import androidx.core.view.updatePaddingRelative
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
import com.google.android.material.bottomsheet.BottomSheetBehavior
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -34,6 +34,7 @@ import eu.kanade.tachiyomi.util.view.inflate
import eu.kanade.tachiyomi.util.view.isCollapsed
import eu.kanade.tachiyomi.util.view.isExpanded
import eu.kanade.tachiyomi.util.view.isHidden
import eu.kanade.tachiyomi.util.view.setText
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.drop
@ -44,6 +45,8 @@ import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.util.lang.getString
import kotlin.math.max
import kotlin.math.roundToInt
@ -236,7 +239,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
},
trackers?.let {
LibraryFilter(
activity.getString(R.string.trackers),
activity.getString(MR.strings.trackers),
it.items,
it,
it.state + 1,
@ -291,9 +294,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
allExpanded ?: return
binding.expandCategories.setText(
if (!allExpanded) {
R.string.expand_all_categories
MR.strings.expand_all_categories
} else {
R.string.collapse_all_categories
MR.strings.collapse_all_categories
},
)
if (animated) {
@ -331,27 +334,27 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
private fun createTags() {
downloaded = inflate(R.layout.filter_tag_group) as FilterTagGroup
downloaded.setup(this, R.string.downloaded, R.string.not_downloaded)
downloaded.setup(this, MR.strings.downloaded, MR.strings.not_downloaded)
completed = inflate(R.layout.filter_tag_group) as FilterTagGroup
completed.setup(this, R.string.completed, R.string.ongoing)
completed.setup(this, MR.strings.completed, MR.strings.ongoing)
unreadProgress = inflate(R.layout.filter_tag_group) as FilterTagGroup
unreadProgress.setup(this, R.string.not_started, R.string.in_progress)
unreadProgress.setup(this, MR.strings.not_started, MR.strings.in_progress)
unread = inflate(R.layout.filter_tag_group) as FilterTagGroup
unread.setup(this, R.string.unread, R.string.read)
unread.setup(this, MR.strings.unread, MR.strings.read)
bookmarked = inflate(R.layout.filter_tag_group) as FilterTagGroup
bookmarked.setup(this, R.string.bookmarked, R.string.not_bookmarked)
bookmarked.setup(this, MR.strings.bookmarked, MR.strings.not_bookmarked)
if (hasTracking) {
tracked = inflate(R.layout.filter_tag_group) as FilterTagGroup
tracked?.setup(this, R.string.tracked, R.string.not_tracked)
tracked?.setup(this, MR.strings.tracked, MR.strings.not_tracked)
}
contentType = inflate(R.layout.filter_tag_group) as FilterTagGroup
contentType.setup(this, R.string.sfw, R.string.nsfw)
contentType.setup(this, MR.strings.sfw, MR.strings.nsfw)
reSortViews()
@ -366,23 +369,23 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
withIOContext {
val libraryManga = controller?.presenter?.allLibraryItems ?: return@withIOContext
checked = true
var types = mutableSetOf<Int>()
var types = mutableSetOf<StringResource>()
libraryManga.forEach {
when (it.manga.seriesType(sourceManager = sourceManager)) {
Manga.TYPE_MANHWA, Manga.TYPE_WEBTOON -> types.add(R.string.manhwa)
Manga.TYPE_MANHUA -> types.add(R.string.manhua)
Manga.TYPE_COMIC -> types.add(R.string.comic)
Manga.TYPE_MANHWA, Manga.TYPE_WEBTOON -> types.add(MR.strings.manhwa)
Manga.TYPE_MANHUA -> types.add(MR.strings.manhua)
Manga.TYPE_COMIC -> types.add(MR.strings.comic)
}
if (types.size == 3) return@forEach
}
val sortedTypes = arrayOf(R.string.manhwa, R.string.manhua, R.string.comic)
val sortedTypes = arrayOf(MR.strings.manhwa, MR.strings.manhua, MR.strings.comic)
types = types.sortedBy { sortedTypes.indexOf(it) }.toMutableSet()
if (types.isNotEmpty()) {
launchUI {
val mangaType = inflate(R.layout.filter_tag_group) as FilterTagGroup
mangaType.setup(
this@FilterBottomSheet,
R.string.manga,
MR.strings.manga,
*types.toTypedArray(),
)
this@FilterBottomSheet.mangaType = mangaType
@ -393,10 +396,10 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
withUIContext {
mangaType?.setState(
when (preferences.filterMangaType().get()) {
Manga.TYPE_MANGA -> context.getString(R.string.manga)
Manga.TYPE_MANHUA -> context.getString(R.string.manhua)
Manga.TYPE_MANHWA -> context.getString(R.string.manhwa)
Manga.TYPE_COMIC -> context.getString(R.string.comic)
Manga.TYPE_MANGA -> context.getString(MR.strings.manga)
Manga.TYPE_MANHUA -> context.getString(MR.strings.manhua)
Manga.TYPE_MANHWA -> context.getString(MR.strings.manhwa)
Manga.TYPE_COMIC -> context.getString(MR.strings.comic)
else -> ""
},
)
@ -530,10 +533,10 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
tracked -> preferences.filterTracked()
mangaType -> {
val newIndex = when (view.nameOf(index)) {
context.getString(R.string.manga) -> Manga.TYPE_MANGA
context.getString(R.string.manhua) -> Manga.TYPE_MANHUA
context.getString(R.string.manhwa) -> Manga.TYPE_MANHWA
context.getString(R.string.comic) -> Manga.TYPE_COMIC
context.getString(MR.strings.manga) -> Manga.TYPE_MANGA
context.getString(MR.strings.manhua) -> Manga.TYPE_MANHUA
context.getString(MR.strings.manhwa) -> Manga.TYPE_MANHWA
context.getString(MR.strings.comic) -> Manga.TYPE_COMIC
else -> 0
}
preferences.filterMangaType().set(newIndex)
@ -625,15 +628,15 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
var FILTER_TRACKER = ""
}
enum class Filters(val value: Char, @StringRes val stringRes: Int) {
UnreadProgress('u', R.string.read_progress),
Unread('r', R.string.unread),
Downloaded('d', R.string.downloaded),
Completed('c', R.string.status),
SeriesType('m', R.string.series_type),
Bookmarked('b', R.string.bookmarked),
Tracked('t', R.string.tracking),
ContentType('s', R.string.content_type);
enum class Filters(val value: Char, val stringRes: StringResource) {
UnreadProgress('u', MR.strings.read_progress),
Unread('r', MR.strings.unread),
Downloaded('d', MR.strings.downloaded),
Completed('c', MR.strings.status),
SeriesType('m', MR.strings.series_type),
Bookmarked('b', MR.strings.bookmarked),
Tracked('t', MR.strings.tracking),
ContentType('s', MR.strings.content_type);
;
companion object {

View file

@ -6,11 +6,13 @@ import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.view.isVisible
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.core.preference.Preference
import eu.kanade.tachiyomi.databinding.FilterTagGroupBinding
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import yokai.util.lang.getString
class FilterTagGroup@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : LinearLayout
(context, attrs) {
@ -57,6 +59,12 @@ class FilterTagGroup@JvmOverloads constructor(context: Context, attrs: Attribute
fun nameOf(index: Int): String? = buttons.getOrNull(index)?.text as? String
fun setup(root: ViewGroup, firstText: StringResource, vararg extra: StringResource?) {
val text1 = context.getString(firstText)
val strings = extra.mapNotNull { if (it != null) context.getString(it) else null }
setup(root, text1, extra = strings.toTypedArray())
}
fun setup(root: ViewGroup, firstText: Int, vararg extra: Int?) {
val text1 = context.getString(firstText)
val strings = extra.mapNotNull { if (it != null) context.getString(it) else null }

View file

@ -7,8 +7,12 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.databinding.CategoriesItemBinding
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.util.view.setText
/**
* Category item for a recycler view.
@ -83,7 +87,9 @@ class ManageFilterItem(val char: Char) : AbstractFlexibleItem<ManageFilterItem.H
}
fun bind(char: Char) {
binding.title.setText(FilterBottomSheet.Filters.filterOf(char)?.stringRes ?: 0)
FilterBottomSheet.Filters.filterOf(char)?.stringRes?.let {
binding.title.setText(it)
} ?: binding.title.setText("")
}
}
}

View file

@ -69,6 +69,9 @@ import com.google.common.primitives.Floats.max
import com.google.common.primitives.Ints.max
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.download.DownloadJob
import eu.kanade.tachiyomi.data.download.DownloadManager
@ -130,6 +133,9 @@ import eu.kanade.tachiyomi.util.view.findChild
import eu.kanade.tachiyomi.util.view.getItemView
import eu.kanade.tachiyomi.util.view.isCompose
import eu.kanade.tachiyomi.util.view.mainRecyclerView
import eu.kanade.tachiyomi.util.view.setAction
import eu.kanade.tachiyomi.util.view.setMessage
import eu.kanade.tachiyomi.util.view.setTitle
import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.withFadeInTransaction
import eu.kanade.tachiyomi.util.view.withFadeTransaction
@ -197,8 +203,8 @@ open class MainActivity : BaseActivity<MainActivityBinding>() {
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (!isGranted) {
materialAlertDialog()
.setTitle(R.string.warning)
.setMessage(R.string.allow_notifications_recommended)
.setTitle(MR.strings.warning)
.setMessage(MR.strings.allow_notifications_recommended)
.setPositiveButton(AR.string.ok, null)
.show()
}
@ -376,9 +382,9 @@ open class MainActivity : BaseActivity<MainActivityBinding>() {
nav.getItemView(R.id.nav_library)?.setOnLongClickListener {
if (!LibraryUpdateJob.isRunning(this)) {
LibraryUpdateJob.startNow(this)
binding.mainContent.snack(R.string.updating_library) {
binding.mainContent.snack(MR.strings.updating_library) {
anchorView = binding.bottomNav
setAction(R.string.cancel) {
setAction(MR.strings.cancel) {
LibraryUpdateJob.stop(context)
lifecycleScope.launchUI {
NotificationReceiver.dismissNotification(
@ -960,8 +966,8 @@ open class MainActivity : BaseActivity<MainActivityBinding>() {
this,
TapTarget.forView(
recentsItem,
getString(R.string.manage_whats_downloading),
getString(R.string.visit_recents_for_download_queue),
getString(MR.strings.manage_whats_downloading),
getString(MR.strings.visit_recents_for_download_queue),
).outerCircleColorInt(getResourceColor(R.attr.colorSecondary)).outerCircleAlpha(0.95f)
.titleTextSize(
20,
@ -1520,16 +1526,16 @@ open class MainActivity : BaseActivity<MainActivityBinding>() {
listOf(
MaterialMenuSheet.MenuSheetItem(
0,
textRes = R.string.whats_new_this_release,
textRes = MR.strings.whats_new_this_release,
drawable = R.drawable.ic_new_releases_24dp,
),
MaterialMenuSheet.MenuSheetItem(
1,
textRes = R.string.close,
textRes = MR.strings.close,
drawable = R.drawable.ic_close_24dp,
),
),
title = getString(R.string.updated_to_, BuildConfig.VERSION_NAME),
title = getString(MR.strings.updated_to_, BuildConfig.VERSION_NAME),
showDivider = true,
selectedId = 0,
onMenuItemClicked = { _, item ->
@ -1650,7 +1656,7 @@ interface SearchControllerInterface : FloatingSearchInterface, SmallToolbarInter
interface FloatingSearchInterface {
fun searchTitle(title: String?): String? {
if (this is Controller) {
return activity?.getString(R.string.search_, title)
return activity?.getString(MR.strings.search_, title ?: "")
}
return title
}

View file

@ -9,6 +9,9 @@ import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.ui.base.SmallToolbarInterface

View file

@ -35,10 +35,13 @@ import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.isInNightMode
import eu.kanade.tachiyomi.util.system.materialAlertDialog
import eu.kanade.tachiyomi.util.view.setPositiveButton
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
class EditMangaDialog : DialogController {
@ -76,7 +79,7 @@ class EditMangaDialog : DialogController {
val dialog = activity!!.materialAlertDialog().apply {
setView(binding.root)
setNegativeButton(AR.string.cancel, null)
setPositiveButton(R.string.save) { _, _ -> onPositiveButtonClick() }
setPositiveButton(MR.strings.save) { _, _ -> onPositiveButtonClick() }
}
onViewCreated()
val updateScrollIndicators = {
@ -92,6 +95,8 @@ class EditMangaDialog : DialogController {
}
fun onViewCreated() {
val context = binding.root.context
binding.mangaCover.loadManga(manga)
val isLocal = manga.isLocal()
@ -100,7 +105,7 @@ class EditMangaDialog : DialogController {
if (manga.title != manga.url) {
binding.title.append(manga.title)
}
binding.title.hint = "${resources?.getString(R.string.title)}: ${manga.url}"
binding.title.hint = "${context.getString(MR.strings.title)}: ${manga.url}"
binding.mangaAuthor.append(manga.author ?: "")
binding.mangaArtist.append(manga.artist ?: "")
binding.mangaDescription.append(manga.description ?: "")
@ -145,16 +150,16 @@ class EditMangaDialog : DialogController {
binding.mangaAuthor.appendOriginalTextOnLongClick(manga.originalAuthor)
binding.mangaArtist.appendOriginalTextOnLongClick(manga.originalArtist)
binding.mangaDescription.appendOriginalTextOnLongClick(manga.originalDescription)
binding.title.hint = "${resources?.getString(R.string.title)}: ${manga.originalTitle}"
binding.title.hint = "${context.getString(MR.strings.title)}: ${manga.originalTitle}"
if (manga.originalAuthor != null) {
binding.mangaAuthor.hint = "${resources?.getString(R.string.author)}: ${manga.originalAuthor}"
binding.mangaAuthor.hint = "${context.getString(MR.strings.author)}: ${manga.originalAuthor}"
}
if (manga.originalArtist != null) {
binding.mangaArtist.hint = "${resources?.getString(R.string.artist)}: ${manga.originalArtist}"
binding.mangaArtist.hint = "${context.getString(MR.strings.artist)}: ${manga.originalArtist}"
}
if (manga.originalDescription != null) {
binding.mangaDescription.hint =
"${resources?.getString(R.string.description)}: ${manga.originalDescription?.replace(
"${context.getString(MR.strings.description)}: ${manga.originalDescription?.replace(
"\n",
" ",
)?.chop(20)}"
@ -181,11 +186,11 @@ class EditMangaDialog : DialogController {
infoController.changeCover()
}
binding.resetTags.setOnClickListener { resetTags() }
binding.resetTags.text = resources?.getString(
binding.resetTags.text = context.getString(
if (manga.originalGenre.isNullOrBlank() || isLocal) {
R.string.clear_tags
MR.strings.clear_tags
} else {
R.string.reset_tags
MR.strings.reset_tags
},
)
binding.addTagChip.setOnClickListener {

View file

@ -35,6 +35,9 @@ import androidx.transition.TransitionManager
import androidx.transition.TransitionSet
import com.google.android.material.shape.CornerFamily
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.FullCoverDialogBinding
import eu.kanade.tachiyomi.util.system.dpToPx

View file

@ -4,8 +4,12 @@ import android.view.ActionMode
import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.ItemTouchHelper
import dev.icerock.moko.resources.StringResource
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterAdapter
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
@ -78,16 +82,16 @@ class MangaDetailsAdapter(
override fun onCreateBubbleText(position: Int): String {
val chapter =
getItem(position) as? ChapterItem ?: return recyclerView.context.getString(R.string.top)
getItem(position) as? ChapterItem ?: return recyclerView.context.getString(MR.strings.top)
return when (val scrollType = presenter.scrollType) {
MangaDetailsPresenter.MULTIPLE_VOLUMES, MangaDetailsPresenter.MULTIPLE_SEASONS -> {
val volume = ChapterUtil.getGroupNumber(chapter)
if (volume != null) {
recyclerView.context.getString(
if (scrollType == MangaDetailsPresenter.MULTIPLE_SEASONS) {
R.string.season_
MR.strings.season_
} else {
R.string.volume_
MR.strings.volume_
},
volume,
)
@ -96,7 +100,7 @@ class MangaDetailsAdapter(
}
}
MangaDetailsPresenter.TENS_OF_CHAPTERS -> recyclerView.context.getString(
R.string.chapters_,
MR.strings.chapters_,
get10sRange(chapter.chapter_number),
)
else -> getChapterName(chapter)
@ -106,7 +110,7 @@ class MangaDetailsAdapter(
private fun getChapterName(item: ChapterItem): String {
return if (item.chapter_number > 0) {
recyclerView.context.getString(
R.string.chapter_,
MR.strings.chapter_,
decimalFormat.format(item.chapter_number),
)
} else {
@ -138,6 +142,7 @@ class MangaDetailsAdapter(
fun showFloatingActionMode(view: TextView, content: String? = null, isTag: Boolean = false)
fun showChapterFilter()
fun favoriteManga(longPress: Boolean)
fun copyContentToClipboard(content: String, label: StringResource, useToast: Boolean = false)
fun copyContentToClipboard(content: String, label: Int, useToast: Boolean = false)
fun customActionMode(view: TextView): ActionMode.Callback
fun copyContentToClipboard(content: String, label: String?, useToast: Boolean = false)

View file

@ -51,9 +51,13 @@ import com.bluelinelabs.conductor.ControllerChangeType
import com.google.android.material.chip.Chip
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import dev.icerock.moko.resources.StringResource
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.coil.getBestColor
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
@ -122,7 +126,11 @@ import eu.kanade.tachiyomi.util.view.getText
import eu.kanade.tachiyomi.util.view.isControllerVisible
import eu.kanade.tachiyomi.util.view.previousController
import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.setAction
import eu.kanade.tachiyomi.util.view.setMessage
import eu.kanade.tachiyomi.util.view.setNegativeButton
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
import eu.kanade.tachiyomi.util.view.setPositiveButton
import eu.kanade.tachiyomi.util.view.setStyle
import eu.kanade.tachiyomi.util.view.setTextColorAlpha
import eu.kanade.tachiyomi.util.view.snack
@ -726,7 +734,7 @@ class MangaDetailsController :
fun isNotOnline(showSnackbar: Boolean = true): Boolean {
if (activity == null || !activity!!.isOnline()) {
if (showSnackbar) view?.snack(R.string.no_network_connection)
if (showSnackbar) view?.snack(MR.strings.no_network_connection)
return true
}
return false
@ -750,15 +758,15 @@ class MangaDetailsController :
val chapterNames = deletedChapters.map { it.name }
context.materialAlertDialog()
.setCustomTitleAndMessage(
R.string.chapters_removed,
context.resources.getQuantityString(
R.plurals.deleted_chapters,
MR.strings.chapters_removed,
context.getString(
MR.plurals.deleted_chapters,
deletedChapters.size,
deletedChapters.size,
if (deletedChapters.size > 5) {
"${chapterNames.take(5 - 1).joinToString(", ")}, " +
context.resources.getQuantityString(
R.plurals.notification_and_n_more,
context.getString(
MR.plurals.notification_and_n_more,
(chapterNames.size - (4 - 1)),
(chapterNames.size - (4 - 1)),
)
@ -767,15 +775,15 @@ class MangaDetailsController :
},
),
)
.setPositiveButton(R.string.delete) { dialog, _ ->
.addCheckBoxPrompt(MR.strings.remember_this_choice)
.setPositiveButton(MR.strings.delete) { dialog, _ ->
presenter.deleteChapters(deletedChapters, false)
if (dialog.isPromptChecked) deleteRemovedPref.set(2)
}
.setNegativeButton(R.string.keep) { dialog, _ ->
.setNegativeButton(MR.strings.keep) { dialog, _ ->
if (dialog.isPromptChecked) deleteRemovedPref.set(1)
}
.setCancelable(false)
.addCheckBoxPrompt(R.string.remember_this_choice)
.show()
}
}
@ -898,22 +906,22 @@ class MangaDetailsController :
MaterialMenuSheet.MenuSheetItem(
0,
if (descending) R.drawable.ic_eye_down_24dp else R.drawable.ic_eye_up_24dp,
R.string.mark_previous_as_read,
MR.strings.mark_previous_as_read,
),
MaterialMenuSheet.MenuSheetItem(
1,
if (descending) R.drawable.ic_eye_off_down_24dp else R.drawable.ic_eye_off_up_24dp,
R.string.mark_previous_as_unread,
MR.strings.mark_previous_as_unread,
),
MaterialMenuSheet.MenuSheetItem(
2,
R.drawable.ic_eye_range_24dp,
R.string.mark_range_as_read,
MR.strings.mark_range_as_read,
),
MaterialMenuSheet.MenuSheetItem(
3,
R.drawable.ic_eye_off_range_24dp,
R.string.mark_range_as_unread,
MR.strings.mark_range_as_unread,
),
)
if (presenter.getChapterUrl(item.chapter) != null) {
@ -922,12 +930,12 @@ class MangaDetailsController :
MaterialMenuSheet.MenuSheetItem(
4,
R.drawable.ic_open_in_webview_24dp,
R.string.open_in_webview,
MR.strings.open_in_webview,
),
)
}
val lastRead = presenter.allHistory.find { it.chapter_id == item.id }?.let {
activity?.timeSpanFromNow(R.string.read_, it.last_read) + "\n"
activity?.timeSpanFromNow(MR.strings.read_, it.last_read) + "\n"
}
val menuSheet =
MaterialMenuSheet(activity!!, items, item.name, subtitle = lastRead) { _, itemPos ->
@ -982,13 +990,13 @@ class MangaDetailsController :
snack?.dismiss()
snack = view?.snack(
if (bookmarked) {
R.string.removed_bookmark
MR.strings.removed_bookmark
} else {
R.string.bookmarked
MR.strings.bookmarked
},
Snackbar.LENGTH_INDEFINITE,
) {
setAction(R.string.undo) {
setAction(MR.strings.undo) {
bookmarkChapters(listOf(item), bookmarked)
}
}
@ -1007,14 +1015,14 @@ class MangaDetailsController :
snack?.dismiss()
snack = view?.snack(
if (read) {
R.string.marked_as_unread
MR.strings.marked_as_unread
} else {
R.string.marked_as_read
MR.strings.marked_as_read
},
Snackbar.LENGTH_INDEFINITE,
) {
var undoing = false
setAction(R.string.undo) {
setAction(MR.strings.undo) {
presenter.markChaptersRead(listOf(item), read, true, lastRead, pagesLeft)
undoing = true
}
@ -1078,17 +1086,17 @@ class MangaDetailsController :
colorToolbar(binding.recycler.canScrollVertically(-1))
updateMenuVisibility(menu)
menu.findItem(R.id.action_migrate).title = view?.context?.getString(
R.string.migrate_,
MR.strings.migrate_,
presenter.manga.seriesType(view!!.context),
)
menu.findItem(R.id.download_next).title =
view?.resources?.getQuantityString(R.plurals.next_unread_chapters, 1, 1)
view?.context?.getString(MR.plurals.next_unread_chapters, 1, 1)
menu.findItem(R.id.download_next_5).title =
view?.resources?.getQuantityString(R.plurals.next_unread_chapters, 5, 5)
view?.context?.getString(MR.plurals.next_unread_chapters, 5, 5)
val searchItem = menu.findItem(R.id.action_search)
val searchView = searchItem.actionView as SearchView
searchView.queryHint = resources?.getString(R.string.search_chapters)
searchView.queryHint = activity?.getString(MR.strings.search_chapters)
if (query.isNotEmpty() && (!searchItem.isActionViewExpanded || searchView.query != query)) {
searchItem.expandActionView()
setSearchViewListener(searchView)
@ -1158,8 +1166,8 @@ class MangaDetailsController :
}
R.id.action_mark_all_as_read -> {
activity!!.materialAlertDialog()
.setMessage(R.string.mark_all_chapters_as_read)
.setPositiveButton(R.string.mark_as_read) { _, _ ->
.setMessage(MR.strings.mark_all_chapters_as_read)
.setPositiveButton(MR.strings.mark_as_read) { _, _ ->
markAsRead(presenter.chapters)
}
.setNegativeButton(AR.string.cancel, null)
@ -1168,8 +1176,8 @@ class MangaDetailsController :
R.id.remove_all, R.id.remove_read, R.id.remove_non_bookmarked, R.id.remove_custom -> massDeleteChapters(item.itemId)
R.id.action_mark_all_as_unread -> {
activity!!.materialAlertDialog()
.setMessage(R.string.mark_all_chapters_as_unread)
.setPositiveButton(R.string.mark_as_unread) { _, _ ->
.setMessage(MR.strings.mark_all_chapters_as_unread)
.setPositiveButton(MR.strings.mark_as_unread) { _, _ ->
markAsUnread(presenter.chapters)
}
.setNegativeButton(AR.string.cancel, null)
@ -1186,9 +1194,9 @@ class MangaDetailsController :
fun saveCover() {
if (presenter.saveCover()) {
activity?.toast(R.string.cover_saved)
activity?.toast(MR.strings.cover_saved)
} else {
activity?.toast(R.string.error_saving_cover)
activity?.toast(MR.strings.error_saving_cover)
}
}
@ -1202,9 +1210,9 @@ class MangaDetailsController :
clipData = ClipData.newRawUri(null, stream)
type = "image/*"
}
startActivity(Intent.createChooser(intent, activity?.getString(R.string.share)))
startActivity(Intent.createChooser(intent, activity?.getString(MR.strings.share)))
} else {
activity?.toast(R.string.error_sharing_cover)
activity?.toast(MR.strings.error_sharing_cover)
}
}
@ -1233,7 +1241,7 @@ class MangaDetailsController :
}
}
startActivity(
Intent.createChooser(intent, context.getString(R.string.share)).apply {
Intent.createChooser(intent, context.getString(MR.strings.share)).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && stream != null) {
val shareCoverIntent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, stream)
@ -1244,12 +1252,12 @@ class MangaDetailsController :
val pendingIntent = PendingIntent.getActivity(
context,
manga?.id?.hashCode() ?: 0,
Intent.createChooser(shareCoverIntent, context.getString(R.string.share)),
Intent.createChooser(shareCoverIntent, context.getString(MR.strings.share)),
PendingIntent.FLAG_IMMUTABLE,
)
val action = ChooserAction.Builder(
Icon.createWithResource(context, R.drawable.ic_photo_24dp),
context.getString(R.string.share_cover),
context.getString(MR.strings.share_cover),
pendingIntent,
).build()
putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, arrayOf(action))
@ -1313,7 +1321,7 @@ class MangaDetailsController :
massDeleteChapters(chaptersToDelete, choice == R.id.remove_all)
} else {
snack?.dismiss()
snack = view?.snack(R.string.no_chapters_to_delete)
snack = view?.snack(MR.strings.no_chapters_to_delete)
}
}
@ -1322,16 +1330,16 @@ class MangaDetailsController :
context.materialAlertDialog()
.setMessage(
if (isEverything) {
context.getString(R.string.remove_all_downloads)
context.getString(MR.strings.remove_all_downloads)
} else {
context.resources.getQuantityString(
R.plurals.remove_n_chapters,
context.getString(
MR.plurals.remove_n_chapters,
chapters.size,
chapters.size,
)
},
)
.setPositiveButton(R.string.remove) { _, _ ->
.setPositiveButton(MR.strings.remove) { _, _ ->
presenter.deleteChapters(chapters, isEverything = isEverything)
}
.setNegativeButton(AR.string.cancel, null)
@ -1415,7 +1423,7 @@ class MangaDetailsController :
val view = view ?: return
presenter.downloadChapters(chapters)
val text = view.context.getString(
R.string.add_x_to_library,
MR.strings.add_x_to_library,
presenter.manga.seriesType(view.context).lowercase(Locale.ROOT),
)
if (!presenter.manga.favorite && (
@ -1424,7 +1432,7 @@ class MangaDetailsController :
)
) {
snack = view.snack(text, Snackbar.LENGTH_INDEFINITE) {
setAction(R.string.add) {
setAction(MR.strings.add) {
if (!presenter.manga.favorite) {
toggleMangaFavorite()
}
@ -1468,9 +1476,9 @@ class MangaDetailsController :
if (item != null) {
openChapter(item.chapter, readingButton)
} else if (snack == null ||
snack?.getText() != view?.context?.getString(R.string.next_chapter_not_found)
snack?.getText() != view?.context?.getString(MR.strings.next_chapter_not_found)
) {
snack = view?.snack(R.string.next_chapter_not_found, Snackbar.LENGTH_LONG) {
snack = view?.snack(MR.strings.next_chapter_not_found, Snackbar.LENGTH_LONG) {
addCallback(
object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
@ -1610,9 +1618,9 @@ class MangaDetailsController :
private fun makeFavPopup(popupView: View, categories: List<Category>): PopupMenu? {
val view = view ?: return null
val popup = PopupMenu(view.context, popupView)
popup.menu.add(0, 1, 0, R.string.remove_from_library)
popup.menu.add(0, 1, 0, view.context.getString(MR.strings.remove_from_library))
if (categories.isNotEmpty()) {
popup.menu.add(0, 0, 1, R.string.edit_categories)
popup.menu.add(0, 0, 1, view.context.getString(MR.strings.edit_categories))
}
// Set a listener so we are notified if a menu item is clicked
@ -1670,11 +1678,23 @@ class MangaDetailsController :
private fun showAddedSnack() {
val view = view ?: return
snack?.dismiss()
snack = view.snack(view.context.getString(R.string.added_to_library))
snack = view.snack(view.context.getString(MR.strings.added_to_library))
}
override fun mangaPresenter(): MangaDetailsPresenter = presenter
/**
* Copies a string to clipboard
*
* @param content the actual text to copy to the board
* @param label Label to show to the user describing the content
*/
override fun copyContentToClipboard(content: String, label: StringResource, useToast: Boolean) {
val view = view ?: return
val contentType = if (label.resourceId != 0) view.context.getString(label) else null
copyContentToClipboard(content, contentType, useToast)
}
/**
* Copies a string to clipboard
*
@ -1764,9 +1784,9 @@ class MangaDetailsController :
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
mode?.title = view?.context?.getString(
if (startingRangeChapterPos == null) {
R.string.select_starting_chapter
MR.strings.select_starting_chapter
} else {
R.string.select_ending_chapter
MR.strings.select_ending_chapter
},
)
return false
@ -1798,12 +1818,12 @@ class MangaDetailsController :
startActivityForResult(
Intent.createChooser(
intent,
resources?.getString(R.string.select_cover_image),
activity?.getString(MR.strings.select_cover_image),
),
101,
)
} else {
activity?.toast(R.string.must_be_in_library_to_edit)
activity?.toast(MR.strings.must_be_in_library_to_edit)
}
}
@ -1819,7 +1839,7 @@ class MangaDetailsController :
presenter.editCoverWithStream(uri)
}
} catch (error: IOException) {
activity.toast(R.string.failed_to_update_cover)
activity.toast(MR.strings.failed_to_update_cover)
Logger.e(error)
}
}
@ -1895,16 +1915,16 @@ class MangaDetailsController :
val context = view?.context ?: return false
val localItem = menu?.findItem(R.id.action_local_search) ?: return true
localItem.isVisible = previousController !is FilteredLibraryController
val library = context.getString(R.string.library).lowercase(Locale.getDefault())
localItem.title = context.getString(R.string.search_, library)
sourceMenuItem?.title = context.getString(R.string.search_, presenter.source.name)
val library = context.getString(MR.strings.library).lowercase(Locale.getDefault())
localItem.title = context.getString(MR.strings.search_, library)
sourceMenuItem?.title = context.getString(MR.strings.search_, presenter.source.name)
menu.findItem(R.id.action_search_author)?.title = context.getString(
R.string.search_,
context.getString(R.string.author).lowercase(Locale.getDefault()),
MR.strings.search_,
context.getString(MR.strings.author).lowercase(Locale.getDefault()),
)
menu.findItem(R.id.action_search_artist)?.title = context.getString(
R.string.search_,
context.getString(R.string.artist).lowercase(Locale.getDefault()),
MR.strings.search_,
context.getString(MR.strings.artist).lowercase(Locale.getDefault()),
)
if (isTag) {
if (previousController is BrowseSourceController) {

View file

@ -10,8 +10,12 @@ import coil3.request.CachePolicy
import coil3.request.ImageRequest
import coil3.request.SuccessResult
import com.hippo.unifile.UniFile
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
@ -497,7 +501,7 @@ class MangaDetailsPresenter(
} else {
e.message
}
) ?: view?.view?.context?.getString(R.string.unknown_error) ?: ""
) ?: view?.view?.context?.getString(MR.strings.unknown_error) ?: ""
}
/**
@ -678,14 +682,14 @@ class MangaDetailsPresenter(
private fun isScanlatorFiltered() = manga.filtered_scanlators?.isNotEmpty() == true
fun currentFilters(): String {
val filtersId = mutableListOf<Int?>()
filtersId.add(if (manga.readFilter(preferences) == Manga.CHAPTER_SHOW_READ) R.string.read else null)
filtersId.add(if (manga.readFilter(preferences) == Manga.CHAPTER_SHOW_UNREAD) R.string.unread else null)
filtersId.add(if (manga.downloadedFilter(preferences) == Manga.CHAPTER_SHOW_DOWNLOADED) R.string.downloaded else null)
filtersId.add(if (manga.downloadedFilter(preferences) == Manga.CHAPTER_SHOW_NOT_DOWNLOADED) R.string.not_downloaded else null)
filtersId.add(if (manga.bookmarkedFilter(preferences) == Manga.CHAPTER_SHOW_BOOKMARKED) R.string.bookmarked else null)
filtersId.add(if (manga.bookmarkedFilter(preferences) == Manga.CHAPTER_SHOW_NOT_BOOKMARKED) R.string.not_bookmarked else null)
filtersId.add(if (isScanlatorFiltered()) R.string.scanlators else null)
val filtersId = mutableListOf<StringResource?>()
filtersId.add(if (manga.readFilter(preferences) == Manga.CHAPTER_SHOW_READ) MR.strings.read else null)
filtersId.add(if (manga.readFilter(preferences) == Manga.CHAPTER_SHOW_UNREAD) MR.strings.unread else null)
filtersId.add(if (manga.downloadedFilter(preferences) == Manga.CHAPTER_SHOW_DOWNLOADED) MR.strings.downloaded else null)
filtersId.add(if (manga.downloadedFilter(preferences) == Manga.CHAPTER_SHOW_NOT_DOWNLOADED) MR.strings.not_downloaded else null)
filtersId.add(if (manga.bookmarkedFilter(preferences) == Manga.CHAPTER_SHOW_BOOKMARKED) MR.strings.bookmarked else null)
filtersId.add(if (manga.bookmarkedFilter(preferences) == Manga.CHAPTER_SHOW_NOT_BOOKMARKED) MR.strings.not_bookmarked else null)
filtersId.add(if (isScanlatorFiltered()) MR.strings.scanlators else null)
return filtersId.filterNotNull()
.joinToString(", ") { view?.view?.context?.getString(it) ?: "" }
}

View file

@ -31,6 +31,9 @@ import coil3.request.placeholder
import com.google.android.material.button.MaterialButton
import com.google.android.material.chip.Chip
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.coil.loadManga
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.ChapterHeaderItemBinding
@ -143,7 +146,7 @@ class MangaHeaderHolder(
}
title.setOnLongClickListener {
title.text?.toString()?.toNormalized()?.let {
adapter.delegate.copyContentToClipboard(it, R.string.title)
adapter.delegate.copyContentToClipboard(it, MR.strings.title)
}
true
}
@ -154,7 +157,7 @@ class MangaHeaderHolder(
}
mangaAuthor.setOnLongClickListener {
mangaAuthor.text?.toString()?.let {
adapter.delegate.copyContentToClipboard(it, R.string.author)
adapter.delegate.copyContentToClipboard(it, MR.strings.author)
}
true
}
@ -266,7 +269,7 @@ class MangaHeaderHolder(
if (binding != null) {
val desc = adapter.controller.mangaPresenter().manga.description
binding.mangaSummary.text = when {
desc.isNullOrBlank() -> itemView.context.getString(R.string.no_description)
desc.isNullOrBlank() -> itemView.context.getString(MR.strings.no_description)
binding.mangaSummary.maxLines != Int.MAX_VALUE -> desc.replace(
Regex(
"[\\r\\n\\s*]{2,}",
@ -284,11 +287,11 @@ class MangaHeaderHolder(
val count = presenter.chapters.size
if (binding != null) {
binding.chaptersTitle.text =
itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
itemView.context.getString(MR.plurals.chapters_plural, count, count)
binding.filtersText.text = presenter.currentFilters()
} else if (chapterBinding != null) {
chapterBinding.chaptersTitle.text =
itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
itemView.context.getString(MR.plurals.chapters_plural, count, count)
chapterBinding.filtersText.text = presenter.currentFilters()
}
}
@ -300,7 +303,7 @@ class MangaHeaderHolder(
if (chapterBinding != null) {
val count = presenter.chapters.size
chapterBinding.chaptersTitle.text =
itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
itemView.context.getString(MR.plurals.chapters_plural, count, count)
chapterBinding.filtersText.text = presenter.currentFilters()
if (adapter.preferences.themeMangaDetails().get()) {
val accentColor = adapter.delegate.accentColor() ?: return
@ -338,7 +341,7 @@ class MangaHeaderHolder(
}
}
binding.mangaSummaryLabel.text = itemView.context.getString(
R.string.about_this_,
MR.strings.about_this_,
manga.seriesType(itemView.context),
)
with(binding.favoriteButton) {
@ -350,11 +353,11 @@ class MangaHeaderHolder(
else -> R.drawable.ic_heart_outline_24dp
},
)
text = itemView.resources.getString(
text = itemView.context.getString(
when {
item.isLocked -> R.string.unlock
manga.favorite -> R.string.in_library
else -> R.string.add_to_library
item.isLocked -> MR.strings.unlock
manga.favorite -> MR.strings.in_library
else -> MR.strings.add_to_library
},
)
checked(!item.isLocked && manga.favorite)
@ -371,9 +374,9 @@ class MangaHeaderHolder(
isVisible = presenter.hasTrackers()
text = itemView.context.getString(
if (tracked) {
R.string.tracked
MR.strings.tracked
} else {
R.string.tracking
MR.strings.tracking
},
)
@ -392,30 +395,30 @@ class MangaHeaderHolder(
text = if (nextChapter != null) {
val number = adapter.decimalFormat.format(nextChapter.chapter_number.toDouble())
if (nextChapter.chapter_number > 0) {
resources.getString(
context.getString(
if (nextChapter.last_page_read > 0) {
R.string.continue_reading_chapter_
MR.strings.continue_reading_chapter_
} else {
R.string.start_reading_chapter_
MR.strings.start_reading_chapter_
},
number,
)
} else {
resources.getString(
context.getString(
if (nextChapter.last_page_read > 0) {
R.string.continue_reading
MR.strings.continue_reading
} else {
R.string.start_reading
MR.strings.start_reading
},
)
}
} else {
resources.getString(R.string.all_chapters_read)
context.getString(MR.strings.all_chapters_read)
}
}
val count = presenter.chapters.size
binding.chaptersTitle.text = itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
binding.chaptersTitle.text = itemView.context.getString(MR.plurals.chapters_plural, count, count)
binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = adapter.delegate.topCoverHeight()
@ -425,13 +428,13 @@ class MangaHeaderHolder(
binding.mangaStatus.text = (
itemView.context.getString(
when (manga.status) {
SManga.ONGOING -> R.string.ongoing
SManga.COMPLETED -> R.string.completed
SManga.LICENSED -> R.string.licensed
SManga.PUBLISHING_FINISHED -> R.string.publishing_finished
SManga.CANCELLED -> R.string.cancelled
SManga.ON_HIATUS -> R.string.on_hiatus
else -> R.string.unknown_status
SManga.ONGOING -> MR.strings.ongoing
SManga.COMPLETED -> MR.strings.completed
SManga.LICENSED -> MR.strings.licensed
SManga.PUBLISHING_FINISHED -> MR.strings.publishing_finished
SManga.CANCELLED -> MR.strings.cancelled
SManga.ON_HIATUS -> MR.strings.on_hiatus
else -> MR.strings.unknown_status
},
)
)
@ -444,7 +447,7 @@ class MangaHeaderHolder(
presenter.source.name != presenter.source.id.toString()
) {
scale(0.9f) {
append(" (${context.getString(R.string.source_not_installed)})")
append(" (${context.getString(MR.strings.source_not_installed)})")
}
}
}
@ -630,9 +633,9 @@ class MangaHeaderHolder(
with(binding.trackButton) {
text = itemView.context.getString(
if (tracked) {
R.string.tracked
MR.strings.tracked
} else {
R.string.tracking
MR.strings.tracking
},
)

View file

@ -6,6 +6,9 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.models.Manga
class MangaHeaderItem(val manga: Manga, var startExpanded: Boolean) :

Some files were not shown because too many files have changed in this diff Show more