From 28501ff31b60c430736efa0344d00641ee6d7316 Mon Sep 17 00:00:00 2001 From: KhooLy <73142442+KhooLy@users.noreply.github.com> Date: Mon, 20 Jul 2026 03:15:39 +0300 Subject: [PATCH] Redesign Plugins screen to match Addons screen visuals, rename from Scraper Plugins Scrapers are now grouped under their owning repository instead of two separate flat lists, and the screen reuses AddonStoreScreen's visual language (icon-circle back button, bordered repo cards, icon buttons) instead of its own bespoke plain-text styling. Adds a refreshRepository action reusing the existing re-fetch dispatch. --- .../app/plugins/PluginRepositoryManager.kt | 5 + .../app/ui/settings/PluginsSettingsScreen.kt | 466 ++++++++++-------- .../ui/settings/PluginsSettingsViewModel.kt | 4 + .../commonMain/resources/i18n/english_us.json | 12 +- core/src/commonMain/resources/i18n/tr_tr.json | 12 +- 5 files changed, 290 insertions(+), 209 deletions(-) diff --git a/app/src/main/java/com/fluxa/app/plugins/PluginRepositoryManager.kt b/app/src/main/java/com/fluxa/app/plugins/PluginRepositoryManager.kt index 2d6cc97..4abfb82 100644 --- a/app/src/main/java/com/fluxa/app/plugins/PluginRepositoryManager.kt +++ b/app/src/main/java/com/fluxa/app/plugins/PluginRepositoryManager.kt @@ -133,6 +133,11 @@ class PluginRepositoryManager @Inject constructor( persistCurrentState() } + suspend fun refreshRepository(manifestUrl: String) { + runtime.dispatch(mapOf("type" to "pluginRepositoryAddRequested", "manifestUrl" to manifestUrl)) + persistCurrentState() + } + suspend fun toggleScraper(scraperId: String, enabled: Boolean) { runtime.dispatch(mapOf("type" to "pluginScraperToggled", "scraperId" to scraperId, "enabled" to enabled)) persistCurrentState() diff --git a/app/src/main/java/com/fluxa/app/ui/settings/PluginsSettingsScreen.kt b/app/src/main/java/com/fluxa/app/ui/settings/PluginsSettingsScreen.kt index 06457fa..91c2109 100644 --- a/app/src/main/java/com/fluxa/app/ui/settings/PluginsSettingsScreen.kt +++ b/app/src/main/java/com/fluxa/app/ui/settings/PluginsSettingsScreen.kt @@ -1,10 +1,12 @@ package com.fluxa.app.ui.settings import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -13,17 +15,24 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.AlertDialog +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Refresh +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Switch import androidx.compose.material3.SwitchDefaults import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.material3.TextField -import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -33,14 +42,14 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.Settings -import androidx.compose.material3.Icon import com.fluxa.app.common.AppStrings import com.fluxa.app.plugins.PluginRepositoryUiModel import com.fluxa.app.plugins.PluginScraperUiModel @@ -59,6 +68,7 @@ fun PluginsSettingsRoute( language = language, onAddRepository = viewModel::addRepository, onRemoveRepository = viewModel::removeRepository, + onRefreshRepository = viewModel::refreshRepository, onToggleScraper = viewModel::toggleScraper, onOpenScraperSettings = viewModel::openScraperSettings, onBackRequested = onBackRequested @@ -84,155 +94,233 @@ fun PluginsSettingsScreen( language: String?, onAddRepository: (String) -> Unit, onRemoveRepository: (String) -> Unit, + onRefreshRepository: (String) -> Unit, onToggleScraper: (String, Boolean) -> Unit, onOpenScraperSettings: (PluginScraperUiModel) -> Unit, onBackRequested: () -> Unit, modifier: Modifier = Modifier ) { - var showAddDialog by remember { mutableStateOf(false) } + val scrapersByRepository = state.scrapers.groupBy { it.repositoryUrl } Box(modifier = modifier.fillMaxSize().background(FluxaColors.background)) { - Column(modifier = Modifier.fillMaxSize().padding(horizontal = 20.dp)) { - PluginsTopBar(title = AppStrings.t(language, "settings.plugins.title"), onBack = onBackRequested) - Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) { - PluginsSectionHeader(AppStrings.t(language, "settings.plugins.repositories")) - PluginsActionRow(AppStrings.t(language, "settings.plugins.add_repository")) { showAddDialog = true } - - if (state.addingRepositoryUrl != null) { - Text( - AppStrings.t(language, "settings.plugins.adding"), - color = Color.White.copy(alpha = 0.6f), - fontSize = 13.sp, - modifier = Modifier.padding(vertical = 8.dp) - ) - } - state.error?.let { error -> - Text( - AppStrings.format(language, "settings.plugins.error", error), - color = FluxaColors.errorRed, - fontSize = 13.sp, - modifier = Modifier.padding(vertical = 8.dp) - ) - } - - if (state.repositories.isEmpty()) { - Text( - AppStrings.t(language, "settings.plugins.no_repositories"), - color = Color.White.copy(alpha = 0.5f), - modifier = Modifier.padding(vertical = 12.dp) - ) - } else { - state.repositories.forEach { repository -> - PluginRepositoryRow( - repository = repository, - language = language, - onRemove = { onRemoveRepository(repository.manifestUrl) } - ) - } - } - - Spacer(Modifier.height(20.dp)) - PluginsSectionHeader(AppStrings.t(language, "settings.plugins.scrapers")) - if (state.scrapers.isEmpty()) { - Text( - AppStrings.t(language, "settings.plugins.no_scrapers"), - color = Color.White.copy(alpha = 0.5f), - modifier = Modifier.padding(vertical = 12.dp) - ) - } else { - state.scrapers.forEach { scraper -> - PluginScraperRow( - scraper = scraper, - language = language, - onToggle = { enabled -> onToggleScraper(scraper.id, enabled) }, - onOpenSettings = { onOpenScraperSettings(scraper) } - ) - } - } - Spacer(Modifier.height(120.dp)) - } - } - } - - if (showAddDialog) { - PluginAddRepositoryDialog( - language = language, - onDismiss = { showAddDialog = false }, - onConfirm = { url -> - onAddRepository(url) - showAddDialog = false - } - ) - } -} - -@Composable -private fun PluginsTopBar(title: String, onBack: () -> Unit) { - Row(modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp), verticalAlignment = Alignment.CenterVertically) { - Box( - modifier = Modifier.size(40.dp).clip(CircleShape).background(Color.White.copy(alpha = 0.05f)).clickable(onClick = onBack), - contentAlignment = Alignment.Center + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 20.dp), + verticalArrangement = Arrangement.spacedBy(14.dp) ) { - Text("←", color = Color.White) + item { + Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(18.dp)) { + var backFocused by remember { mutableStateOf(false) } + Box( + modifier = Modifier + .size(40.dp) + .clip(CircleShape) + .onFocusChanged { backFocused = it.isFocused } + .background(if (backFocused) Color.White else Color.White.copy(alpha = 0.05f)) + .clickable(onClick = onBackRequested), + contentAlignment = Alignment.Center + ) { + Icon( + Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = null, + tint = if (backFocused) Color.Black else Color.White, + modifier = Modifier.size(20.dp) + ) + } + Text( + text = AppStrings.t(language, "settings.plugins.title"), + color = Color.White, + fontWeight = FontWeight.Black, + fontSize = 26.sp + ) + } + } + + item { + PluginRepositoryInput(language = language, onSubmit = onAddRepository) + } + + if (state.error != null) { + item { + Text( + text = AppStrings.format(language, "settings.plugins.error", state.error), + color = FluxaColors.errorRed, + fontSize = 13.sp + ) + } + } + + val addingNewRepositoryUrl = state.addingRepositoryUrl + ?.takeIf { url -> state.repositories.none { it.manifestUrl == url } } + if (addingNewRepositoryUrl != null) { + item { + Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp)) { + CircularProgressIndicator(color = Color.White.copy(alpha = 0.68f), strokeWidth = 2.dp, modifier = Modifier.size(16.dp)) + Text( + text = AppStrings.t(language, "settings.plugins.adding"), + color = Color.White.copy(alpha = 0.6f), + fontSize = 13.sp + ) + } + } + } + + item { + Text( + text = AppStrings.t(language, "settings.plugins.installed_repositories"), + color = Color.White, + fontWeight = FontWeight.Bold, + fontSize = 16.sp + ) + } + + if (state.repositories.isEmpty()) { + item { + Text( + text = AppStrings.t(language, "settings.plugins.no_repositories"), + color = Color.White.copy(alpha = 0.5f), + fontSize = 13.sp, + modifier = Modifier.padding(vertical = 8.dp) + ) + } + } else { + items(state.repositories, key = { "repo:${it.manifestUrl}" }) { repository -> + PluginRepositoryGroup( + repository = repository, + scrapers = scrapersByRepository[repository.manifestUrl].orEmpty(), + language = language, + isRefreshing = state.addingRepositoryUrl == repository.manifestUrl, + onRemove = { onRemoveRepository(repository.manifestUrl) }, + onRefresh = { onRefreshRepository(repository.manifestUrl) }, + onToggleScraper = onToggleScraper, + onOpenScraperSettings = onOpenScraperSettings + ) + } + } + + item { Spacer(Modifier.height(80.dp)) } } - Spacer(Modifier.width(12.dp)) - Text(title, color = Color.White, fontWeight = FontWeight.Black, fontSize = 22.sp) } } @Composable -private fun PluginsSectionHeader(title: String) { - Text( - title.uppercase(), - color = Color.White.copy(alpha = 0.4f), - fontSize = 12.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(top = 16.dp, bottom = 8.dp) - ) -} - -@Composable -private fun PluginsActionRow(label: String, onClick: () -> Unit) { - Row( - modifier = Modifier.fillMaxWidth().clickable(onClick = onClick).padding(vertical = 12.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text(label, color = Color.White) - Text("+", color = Color.White.copy(alpha = 0.6f), fontSize = 18.sp) - } -} - -@Composable -private fun PluginRepositoryRow( - repository: PluginRepositoryUiModel, +private fun PluginRepositoryInput( language: String?, - onRemove: () -> Unit + onSubmit: (String) -> Unit ) { - Row( + var url by remember { mutableStateOf("") } + Column( modifier = Modifier .fillMaxWidth() - .padding(vertical = 6.dp) - .clip(RoundedCornerShape(10.dp)) - .background(Color.White.copy(alpha = 0.05f)) - .padding(horizontal = 14.dp, vertical = 12.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically + .clip(RoundedCornerShape(18.dp)) + .background(Color.White.copy(alpha = 0.04f)) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) ) { - Column(modifier = Modifier.weight(1f)) { - Text(repository.name.ifBlank { repository.manifestUrl }, color = Color.White, fontWeight = FontWeight.Bold) - Text( - AppStrings.format(language, "settings.plugins.scraper_count", repository.scraperCount), - color = Color.White.copy(alpha = 0.5f), - fontSize = 12.sp - ) - } - Text( - AppStrings.t(language, "settings.plugins.remove"), - color = FluxaColors.errorRed, - fontSize = 13.sp, - modifier = Modifier.clickable(onClick = onRemove).padding(8.dp) + OutlinedTextField( + value = url, + onValueChange = { url = it }, + modifier = Modifier.fillMaxWidth().height(52.dp), + singleLine = true, + placeholder = { + Text( + AppStrings.t(language, "settings.plugins.repository_url_placeholder"), + color = Color.White.copy(alpha = 0.3f), + fontSize = 13.sp + ) + }, + colors = OutlinedTextFieldDefaults.colors( + unfocusedBorderColor = Color.White.copy(alpha = 0.1f), + focusedTextColor = Color.White, + unfocusedTextColor = Color.White, + cursorColor = Color.White, + focusedContainerColor = Color.Black.copy(alpha = 0.2f), + unfocusedContainerColor = Color.Black.copy(alpha = 0.2f) + ), + shape = RoundedCornerShape(12.dp) ) + androidx.compose.material3.Button( + onClick = { + val trimmed = url.trim() + if (trimmed.isNotEmpty()) { + onSubmit(trimmed) + url = "" + } + }, + enabled = url.isNotBlank(), + modifier = Modifier.fillMaxWidth().height(44.dp), + shape = RoundedCornerShape(12.dp), + colors = androidx.compose.material3.ButtonDefaults.buttonColors(containerColor = Color.White, contentColor = Color.Black) + ) { + Icon(Icons.Filled.Add, contentDescription = null, modifier = Modifier.size(18.dp)) + Spacer(Modifier.width(6.dp)) + Text(AppStrings.t(language, "settings.plugins.add_repository"), fontWeight = FontWeight.Bold, fontSize = 14.sp) + } + } +} + +@Composable +private fun PluginRepositoryGroup( + repository: PluginRepositoryUiModel, + scrapers: List, + language: String?, + isRefreshing: Boolean, + onRemove: () -> Unit, + onRefresh: () -> Unit, + onToggleScraper: (String, Boolean) -> Unit, + onOpenScraperSettings: (PluginScraperUiModel) -> Unit +) { + Column( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(18.dp)) + .background(Color.White.copy(alpha = 0.04f)) + .border(1.dp, Color.White.copy(alpha = 0.06f), RoundedCornerShape(18.dp)) + .padding(vertical = 4.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = repository.name.ifBlank { repository.manifestUrl }, + color = Color.White, + fontWeight = FontWeight.Bold, + fontSize = 15.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = AppStrings.format(language, "settings.plugins.scraper_count", repository.scraperCount), + color = Color.White.copy(alpha = 0.5f), + fontSize = 12.sp + ) + } + if (isRefreshing) { + Box(modifier = Modifier.size(36.dp), contentAlignment = Alignment.Center) { + CircularProgressIndicator(color = Color.White.copy(alpha = 0.68f), strokeWidth = 2.dp, modifier = Modifier.size(18.dp)) + } + } else { + PluginIconButton(icon = Icons.Filled.Refresh, onClick = onRefresh) + } + PluginIconButton(icon = Icons.Filled.Close, tint = Color.White.copy(alpha = 0.5f), onClick = onRemove) + } + + if (scrapers.isNotEmpty()) { + HorizontalDivider(color = Color.White.copy(alpha = 0.06f), thickness = 0.5.dp) + scrapers.forEachIndexed { index, scraper -> + PluginScraperRow( + scraper = scraper, + language = language, + onToggle = { enabled -> onToggleScraper(scraper.id, enabled) }, + onOpenSettings = { onOpenScraperSettings(scraper) } + ) + if (index < scrapers.lastIndex) { + HorizontalDivider(color = Color.White.copy(alpha = 0.06f), thickness = 0.5.dp, modifier = Modifier.padding(horizontal = 16.dp)) + } + } + } } } @@ -244,31 +332,31 @@ private fun PluginScraperRow( onOpenSettings: () -> Unit ) { Row( - modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp), - horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically ) { Column(modifier = Modifier.weight(1f)) { - Text(scraper.name, color = Color.White) - Text(scraper.supportedTypes.joinToString(", "), color = Color.White.copy(alpha = 0.4f), fontSize = 11.sp) + Text( + text = scraper.name, + color = Color.White, + fontWeight = FontWeight.SemiBold, + fontSize = 14.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = scraper.supportedTypes.joinToString(", "), + color = Color.White.copy(alpha = 0.45f), + fontSize = 11.sp + ) } if (scraper.hasSettings) { - Box( - modifier = Modifier - .size(32.dp) - .clip(CircleShape) - .background(Color.White.copy(alpha = 0.05f)) - .clickable(onClick = onOpenSettings), - contentAlignment = Alignment.Center - ) { - Icon( - Icons.Rounded.Settings, - contentDescription = AppStrings.t(language, "settings.plugins.settings"), - tint = Color.White.copy(alpha = 0.7f), - modifier = Modifier.size(18.dp) - ) - } - Spacer(Modifier.width(8.dp)) + PluginIconButton( + icon = Icons.Filled.Settings, + contentDescription = AppStrings.t(language, "settings.plugins.settings"), + onClick = onOpenSettings + ) + Spacer(Modifier.width(4.dp)) } Switch( checked = scraper.enabled, @@ -276,47 +364,35 @@ private fun PluginScraperRow( colors = SwitchDefaults.colors( checkedTrackColor = Color.White, checkedThumbColor = Color.Black, - uncheckedTrackColor = Color.White.copy(alpha = 0.15f), - uncheckedThumbColor = Color.White.copy(alpha = 0.7f) + uncheckedTrackColor = Color.White.copy(alpha = 0.18f), + uncheckedThumbColor = Color.White.copy(alpha = 0.72f) ) ) } } @Composable -private fun PluginAddRepositoryDialog( - language: String?, - onDismiss: () -> Unit, - onConfirm: (String) -> Unit +private fun PluginIconButton( + icon: ImageVector, + contentDescription: String? = null, + tint: Color = Color.White.copy(alpha = 0.68f), + onClick: () -> Unit ) { - var url by remember { mutableStateOf("") } - AlertDialog( - onDismissRequest = onDismiss, - title = { Text(AppStrings.t(language, "settings.plugins.add_repository")) }, - text = { - TextField( - value = url, - onValueChange = { url = it }, - placeholder = { Text(AppStrings.t(language, "settings.plugins.repository_url_placeholder")) }, - label = { Text(AppStrings.t(language, "settings.plugins.repository_url")) }, - singleLine = true, - colors = TextFieldDefaults.colors( - focusedContainerColor = Color.White.copy(alpha = 0.05f), - unfocusedContainerColor = Color.White.copy(alpha = 0.05f), - focusedTextColor = Color.White, - unfocusedTextColor = Color.White - ) - ) - }, - confirmButton = { - TextButton(onClick = { onConfirm(url) }, enabled = url.isNotBlank()) { - Text(AppStrings.t(language, "settings.plugins.add")) - } - }, - dismissButton = { - TextButton(onClick = onDismiss) { - Text(AppStrings.t(language, "settings.plugins.cancel")) - } - } - ) + var focused by remember { mutableStateOf(false) } + Box( + modifier = Modifier + .size(36.dp) + .clip(CircleShape) + .onFocusChanged { focused = it.isFocused } + .background(if (focused) Color.White else Color.Transparent) + .clickable(onClick = onClick), + contentAlignment = Alignment.Center + ) { + Icon( + icon, + contentDescription = contentDescription, + tint = if (focused) Color.Black else tint, + modifier = Modifier.size(18.dp) + ) + } } diff --git a/app/src/main/java/com/fluxa/app/ui/settings/PluginsSettingsViewModel.kt b/app/src/main/java/com/fluxa/app/ui/settings/PluginsSettingsViewModel.kt index 7aa7c8e..5b72f81 100644 --- a/app/src/main/java/com/fluxa/app/ui/settings/PluginsSettingsViewModel.kt +++ b/app/src/main/java/com/fluxa/app/ui/settings/PluginsSettingsViewModel.kt @@ -43,6 +43,10 @@ class PluginsSettingsViewModel @Inject constructor( viewModelScope.launch { manager.removeRepository(manifestUrl) } } + fun refreshRepository(manifestUrl: String) { + viewModelScope.launch { manager.refreshRepository(manifestUrl) } + } + fun toggleScraper(scraperId: String, enabled: Boolean) { viewModelScope.launch { manager.toggleScraper(scraperId, enabled) } } diff --git a/core/src/commonMain/resources/i18n/english_us.json b/core/src/commonMain/resources/i18n/english_us.json index ee5bc12..091b160 100644 --- a/core/src/commonMain/resources/i18n/english_us.json +++ b/core/src/commonMain/resources/i18n/english_us.json @@ -282,9 +282,8 @@ "settings.torrent_speed_default": "Default", "settings.torrent_speed_fast": "Fast", "settings.torrent_speed_ultra_fast": "Ultra Fast", - "settings.plugins.manage": "Scraper Plugins", - "settings.plugins.title": "Scraper Plugins", - "settings.plugins.repositories": "Repositories", + "settings.plugins.manage": "Plugins", + "settings.plugins.title": "Plugins", "settings.plugins.add_repository": "Add Repository", "settings.plugins.repository_url": "Repository manifest URL", "settings.plugins.repository_url_placeholder": "https://example.com/repo.json", @@ -292,11 +291,8 @@ "settings.plugins.cancel": "Cancel", "settings.plugins.remove": "Remove", "settings.plugins.refresh": "Refresh", - "settings.plugins.scrapers": "Scrapers", "settings.plugins.no_repositories": "No repositories added yet.", - "settings.plugins.no_scrapers": "No scrapers available.", "settings.plugins.scraper_count": "%s scrapers", - "settings.plugins.adding": "Adding repository…", "settings.plugins.error": "Failed to add repository: %s", "settings.plugins.settings": "Settings", "settings.plugins.settings_title": "%s Settings", @@ -1128,5 +1124,7 @@ "settings.bottom_bar_labels_desc": "Display destination names below navigation icons.", "settings.home_top_bar": "Home top bar", "settings.home_top_bar_desc": "Show Home, Series, Movies, notifications, and profile above the hero.", - "common.add_to_library": "Add to Library" + "common.add_to_library": "Add to Library", + "settings.plugins.installed_repositories": "Plugin Repositories", + "settings.plugins.adding": "Adding repository…" } diff --git a/core/src/commonMain/resources/i18n/tr_tr.json b/core/src/commonMain/resources/i18n/tr_tr.json index 598c82b..4d58190 100644 --- a/core/src/commonMain/resources/i18n/tr_tr.json +++ b/core/src/commonMain/resources/i18n/tr_tr.json @@ -282,9 +282,8 @@ "settings.torrent_speed_default": "Varsayılan", "settings.torrent_speed_fast": "Hızlı", "settings.torrent_speed_ultra_fast": "Ultra Hızlı", - "settings.plugins.manage": "Kazıyıcı Eklentiler", - "settings.plugins.title": "Kazıyıcı Eklentiler", - "settings.plugins.repositories": "Depolar", + "settings.plugins.manage": "Eklentiler", + "settings.plugins.title": "Eklentiler", "settings.plugins.add_repository": "Depo Ekle", "settings.plugins.repository_url": "Depo manifest URL'si", "settings.plugins.repository_url_placeholder": "https://example.com/repo.json", @@ -292,11 +291,8 @@ "settings.plugins.cancel": "İptal", "settings.plugins.remove": "Kaldır", "settings.plugins.refresh": "Yenile", - "settings.plugins.scrapers": "Kazıyıcılar", "settings.plugins.no_repositories": "Henüz depo eklenmedi.", - "settings.plugins.no_scrapers": "Kullanılabilir kazıyıcı yok.", "settings.plugins.scraper_count": "%s kazıyıcı", - "settings.plugins.adding": "Depo ekleniyor…", "settings.plugins.error": "Depo eklenemedi: %s", "settings.plugins.settings": "Ayarlar", "settings.plugins.settings_title": "%s Ayarları", @@ -1128,5 +1124,7 @@ "settings.bottom_bar_labels_desc": "Gezinme simgelerinin altında hedef adlarını gösterir.", "settings.home_top_bar": "Ana sayfa üst çubuğu", "settings.home_top_bar_desc": "Hero alanının üzerinde Ana Sayfa, Diziler, Filmler, bildirimler ve profili gösterir.", - "common.add_to_library": "Kitaplığa ekle" + "common.add_to_library": "Kitaplığa ekle", + "settings.plugins.installed_repositories": "Eklenti Depoları", + "settings.plugins.adding": "Depo ekleniyor…" }