From 206c3884e9bf7ff1edb0e3bdf37251901d84f078 Mon Sep 17 00:00:00 2001 From: Koen Date: Wed, 25 Oct 2023 14:53:50 +0200 Subject: [PATCH] Finished moving strings to strings.xml for activities and fragments. --- .../activities/AddSourceActivity.kt | 18 +- .../activities/AddSourceOptionsActivity.kt | 8 +- .../activities/ExceptionActivity.kt | 16 +- .../platformplayer/activities/MainActivity.kt | 18 +- .../activities/PolycentricBackupActivity.kt | 6 +- .../PolycentricCreateProfileActivity.kt | 6 +- .../activities/PolycentricHomeActivity.kt | 2 +- .../PolycentricImportProfileActivity.kt | 10 +- .../activities/PolycentricProfileActivity.kt | 18 +- .../activities/SettingsActivity.kt | 2 +- .../channel/tab/ChannelAboutFragment.kt | 4 +- .../channel/tab/ChannelListFragment.kt | 2 +- .../fragment/mainactivity/main/BuyFragment.kt | 16 +- .../mainactivity/main/ChannelFragment.kt | 10 +- .../mainactivity/main/ContentFeedView.kt | 18 +- .../main/ContentSearchResultsFragment.kt | 2 +- .../mainactivity/main/DownloadsFragment.kt | 8 +- .../fragment/mainactivity/main/FeedView.kt | 8 +- .../mainactivity/main/HomeFragment.kt | 16 +- .../main/ImportPlaylistsFragment.kt | 8 +- .../main/ImportSubscriptionsFragment.kt | 10 +- .../mainactivity/main/PlaylistFragment.kt | 20 +- .../mainactivity/main/PlaylistsFragment.kt | 6 +- .../mainactivity/main/PostDetailFragment.kt | 10 +- .../mainactivity/main/SourceDetailFragment.kt | 50 ++--- .../main/SubscriptionsFeedFragment.kt | 21 +-- .../mainactivity/main/VideoDetailView.kt | 105 ++++++----- .../mainactivity/main/VideoListEditorView.kt | 4 +- .../topbar/GeneralTopBarFragment.kt | 2 +- .../topbar/SearchTopBarFragment.kt | 2 +- app/src/main/res/values/strings.xml | 174 +++++++++++++++++- dep/futopay | 2 +- lint.xml | 4 + 33 files changed, 393 insertions(+), 213 deletions(-) create mode 100644 lint.xml diff --git a/app/src/main/java/com/futo/platformplayer/activities/AddSourceActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/AddSourceActivity.kt index 620df73f..fc987cec 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/AddSourceActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/AddSourceActivity.kt @@ -96,8 +96,8 @@ class AddSourceActivity : AppCompatActivity() { var url = intent?.dataString; if(url == null) - UIDialogs.showDialog(this, R.drawable.ic_error, "No valid URL provided..", null, null, - 0, UIDialogs.Action("Ok", { finish() }, UIDialogs.ActionStyle.PRIMARY)); + UIDialogs.showDialog(this, R.drawable.ic_error, getString(R.string.no_valid_url_provided), null, null, + 0, UIDialogs.Action(getString(R.string.ok), { finish() }, UIDialogs.ActionStyle.PRIMARY)); else { if(url.startsWith("vfuto://")) url = "https://" + url.substring("vfuto://".length); @@ -129,14 +129,14 @@ class AddSourceActivity : AppCompatActivity() { Logger.e(TAG, "Failed decode config", ex); withContext(Dispatchers.Main) { UIDialogs.showDialog(this@AddSourceActivity, R.drawable.ic_error, - "Invalid Config Format", null, null, + getString(R.string.invalid_config_format), null, null, 0, UIDialogs.Action("Ok", { finish() }, UIDialogs.ActionStyle.PRIMARY)); }; return@launch; } catch(ex: Exception) { Logger.e(TAG, "Failed fetch config", ex); withContext(Dispatchers.Main) { - UIDialogs.showGeneralErrorDialog(this@AddSourceActivity, "Failed to fetch configuration", ex); + UIDialogs.showGeneralErrorDialog(this@AddSourceActivity, getString(R.string.failed_to_fetch_configuration), ex); }; return@launch; } @@ -152,7 +152,7 @@ class AddSourceActivity : AppCompatActivity() { } catch (ex: Exception) { Logger.e(TAG, "Failed fetch script", ex); withContext(Dispatchers.Main) { - UIDialogs.showGeneralErrorDialog(this@AddSourceActivity, "Failed to fetch script", ex); + UIDialogs.showGeneralErrorDialog(this@AddSourceActivity, getString(R.string.failed_to_fetch_script), ex); }; return@launch; } @@ -175,8 +175,8 @@ class AddSourceActivity : AppCompatActivity() { _sourcePermissions.addView( SourceInfoView(this, R.drawable.ic_language, - "URL Access", - "The plugin will have access to the following domains", + getString(R.string.url_access), + getString(R.string.the_plugin_will_have_access_to_the_following_domains), config.allowUrls, true) ) @@ -184,8 +184,8 @@ class AddSourceActivity : AppCompatActivity() { _sourcePermissions.addView( SourceInfoView(this, R.drawable.ic_code, - "Eval Access", - "The plugin will have access to eval capability (remote injection)", + getString(R.string.eval_access), + getString(R.string.the_plugin_will_have_access_to_eval_capability_remote_injection), config.allowUrls, true) ) diff --git a/app/src/main/java/com/futo/platformplayer/activities/AddSourceOptionsActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/AddSourceOptionsActivity.kt index e34916e4..043b0661 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/AddSourceOptionsActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/AddSourceOptionsActivity.kt @@ -22,7 +22,7 @@ class AddSourceOptionsActivity : AppCompatActivity() { scanResult?.let { val content = it.contents if (content == null) { - UIDialogs.toast(this, "Failed to scan QR code") + UIDialogs.toast(this, getString(R.string.failed_to_scan_qr_code)) return@let } @@ -31,7 +31,7 @@ class AddSourceOptionsActivity : AppCompatActivity() { } else if (content.startsWith("grayjay://plugin/")) { content.substring("grayjay://plugin/".length) } else { - UIDialogs.toast(this, "Not a plugin URL") + UIDialogs.toast(this, getString(R.string.not_a_plugin_url)) return@let; } @@ -59,7 +59,7 @@ class AddSourceOptionsActivity : AppCompatActivity() { _buttonQR.onClick.subscribe { val integrator = IntentIntegrator(this); integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE) - integrator.setPrompt("Scan a QR Code") + integrator.setPrompt(getString(R.string.scan_a_qr_code)) integrator.setOrientationLocked(true); integrator.setCameraId(0) integrator.setBeepEnabled(false) @@ -69,7 +69,7 @@ class AddSourceOptionsActivity : AppCompatActivity() { } _buttonURL.onClick.subscribe { - UIDialogs.toast(this, "Not implemented yet.."); + UIDialogs.toast(this, getString(R.string.not_implemented_yet)); } } diff --git a/app/src/main/java/com/futo/platformplayer/activities/ExceptionActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/ExceptionActivity.kt index 7e4967fa..85f2d32c 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/ExceptionActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/ExceptionActivity.kt @@ -38,8 +38,8 @@ class ExceptionActivity : AppCompatActivity() { _buttonRestart = findViewById(R.id.button_restart); _buttonClose = findViewById(R.id.button_close); - val context = intent.getStringExtra(EXTRA_CONTEXT) ?: "Unknown Context"; - val stack = intent.getStringExtra(EXTRA_STACK) ?: "Something went wrong... missing stack trace?"; + val context = intent.getStringExtra(EXTRA_CONTEXT) ?: getString(R.string.unknown_context); + val stack = intent.getStringExtra(EXTRA_STACK) ?: getString(R.string.something_went_wrong_missing_stack_trace); val exceptionString = "Version information (version_name = ${BuildConfig.VERSION_NAME}, version_code = ${BuildConfig.VERSION_CODE}, flavor = ${BuildConfig.FLAVOR}, build_type = ${BuildConfig.BUILD_TYPE})\n" + "Device information (brand= ${Build.BRAND}, manufacturer = ${Build.MANUFACTURER}, device = ${Build.DEVICE}, version-sdk = ${Build.VERSION.SDK_INT}, version-os = ${Build.VERSION.BASE_OS})\n\n" + @@ -79,13 +79,13 @@ class ExceptionActivity : AppCompatActivity() { private fun submitFile() { if (_submitted) { - Toast.makeText(this, "Logs already submitted.", Toast.LENGTH_LONG).show(); + Toast.makeText(this, getString(R.string.logs_already_submitted), Toast.LENGTH_LONG).show(); return; } val file = _file; if (file == null) { - Toast.makeText(this, "No logs found.", Toast.LENGTH_LONG).show(); + Toast.makeText(this, getString(R.string.no_logs_found), Toast.LENGTH_LONG).show(); return; } @@ -101,14 +101,14 @@ class ExceptionActivity : AppCompatActivity() { withContext(Dispatchers.Main) { if (id == null) { try { - Toast.makeText(this@ExceptionActivity, "Failed automated share, share manually?", Toast.LENGTH_LONG).show(); + Toast.makeText(this@ExceptionActivity, getString(R.string.failed_automated_share_share_manually), Toast.LENGTH_LONG).show(); } catch (e: Throwable) { //Ignored } } else { _submitted = true; file.delete(); - Toast.makeText(this@ExceptionActivity, "Shared $id", Toast.LENGTH_LONG).show(); + Toast.makeText(this@ExceptionActivity, getString(R.string.shared_id).replace("{id}", id), Toast.LENGTH_LONG).show(); } } } @@ -119,10 +119,10 @@ class ExceptionActivity : AppCompatActivity() { val i = Intent(Intent.ACTION_SEND); i.type = "text/plain"; i.putExtra(Intent.EXTRA_EMAIL, arrayOf("grayjay@futo.org")); - i.putExtra(Intent.EXTRA_SUBJECT, "Unhandled exception in VS"); + i.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.unhandled_exception_in_vs)); i.putExtra(Intent.EXTRA_TEXT, exceptionString); - startActivity(Intent.createChooser(i, "Send exception to developers...")); + startActivity(Intent.createChooser(i, getString(R.string.send_exception_to_developers))); } catch (e: Throwable) { //Ignored diff --git a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt index 13982583..04df3b59 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt @@ -478,13 +478,13 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { if(targetData.startsWith("grayjay://license/")) { if(StatePayment.instance.setPaymentLicenseUrl(targetData)) { - UIDialogs.showDialogOk(this, R.drawable.ic_check, "Your license key has been set!\nAn app restart might be required."); + UIDialogs.showDialogOk(this, R.drawable.ic_check, getString(R.string.your_license_key_has_been_set_an_app_restart_might_be_required)); if(fragCurrent is BuyFragment) closeSegment(fragCurrent); } else - UIDialogs.toast("Invalid license format"); + UIDialogs.toast(getString(R.string.invalid_license_format)); } else if(targetData.startsWith("grayjay://plugin/")) { @@ -499,7 +499,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { UIDialogs.showSingleButtonDialog( this, R.drawable.ic_play, - "Unknown content format [${targetData}]", + getString(R.string.unknown_content_format) + " [${targetData}]", "Ok", { }); } @@ -509,7 +509,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { UIDialogs.showSingleButtonDialog( this, R.drawable.ic_play, - "Unknown file format [${targetData}]", + getString(R.string.unknown_file_format) + " [${targetData}]", "Ok", { }); } @@ -519,7 +519,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { UIDialogs.showSingleButtonDialog( this, R.drawable.ic_play, - "Unknown Polycentric format [${targetData}]", + getString(R.string.unknown_polycentric_format) + " [${targetData}]", "Ok", { }); } @@ -529,7 +529,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { UIDialogs.showSingleButtonDialog( this, R.drawable.ic_play, - "Unknown url format [${targetData}]", + getString(R.string.unknown_url_format) + " [${targetData}]", "Ok", { }); } @@ -538,7 +538,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { } } catch(ex: Throwable) { - UIDialogs.showGeneralErrorDialog(this, "Failed to handle file", ex); + UIDialogs.showGeneralErrorDialog(this, getString(R.string.failed_to_handle_file), ex); } } @@ -603,7 +603,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { val store: ManagedStore<*> = when(type) { "Playlist" -> StatePlaylists.instance.playlistStore else -> { - UIDialogs.toast("Unknown reconstruction type ${type}", false); + UIDialogs.toast(getString(R.string.unknown_reconstruction_type) + " ${type}", false); return; }; }; @@ -646,7 +646,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { } catch(ex: Exception) { Logger.e(TAG, ex.message, ex); - UIDialogs.showGeneralErrorDialog(context, "Failed to parse NewPipe Subscriptions", ex); + UIDialogs.showGeneralErrorDialog(context, getString(R.string.failed_to_parse_newpipe_subscriptions), ex); } /* diff --git a/app/src/main/java/com/futo/platformplayer/activities/PolycentricBackupActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/PolycentricBackupActivity.kt index 4413eb97..39cbf27c 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/PolycentricBackupActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/PolycentricBackupActivity.kt @@ -53,7 +53,7 @@ class PolycentricBackupActivity : AppCompatActivity() { val qrCodeBitmap = generateQRCode(_exportBundle, dimension, dimension); _imageQR.setImageBitmap(qrCodeBitmap); } catch (e: Exception) { - Logger.e(TAG, "Failed to generate QR code", e); + Logger.e(TAG, getString(R.string.failed_to_generate_qr_code), e); _imageQR.visibility = View.INVISIBLE; _textQR.visibility = View.INVISIBLE; } @@ -63,12 +63,12 @@ class PolycentricBackupActivity : AppCompatActivity() { type = "text/plain"; putExtra(Intent.EXTRA_TEXT, _exportBundle); } - startActivity(Intent.createChooser(shareIntent, "Share Text")); + startActivity(Intent.createChooser(shareIntent, getString(R.string.share_text))); }; _buttonCopy.onClick.subscribe { val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager; - val clip = ClipData.newPlainText("Copied Text", _exportBundle); + val clip = ClipData.newPlainText(getString(R.string.copied_text), _exportBundle); clipboard.setPrimaryClip(clip); }; } diff --git a/app/src/main/java/com/futo/platformplayer/activities/PolycentricCreateProfileActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/PolycentricCreateProfileActivity.kt index a8889ad9..f2adef70 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/PolycentricCreateProfileActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/PolycentricCreateProfileActivity.kt @@ -54,7 +54,7 @@ class PolycentricCreateProfileActivity : AppCompatActivity() { try { val username = _profileName.text.toString(); if (username.length < 3) { - UIDialogs.toast(this@PolycentricCreateProfileActivity, "Must be at least 3 characters long."); + UIDialogs.toast(this@PolycentricCreateProfileActivity, getString(R.string.must_be_at_least_3_characters_long)); return@setOnClickListener; } @@ -68,7 +68,7 @@ class PolycentricCreateProfileActivity : AppCompatActivity() { processHandle.setUsername(username); StatePolycentric.instance.setProcessHandle(processHandle); } catch (e: Throwable) { - Logger.e(TAG, "Failed to create profile .", e); + Logger.e(TAG, getString(R.string.failed_to_create_profile), e); return@launch; } finally { _creating = false; @@ -77,7 +77,7 @@ class PolycentricCreateProfileActivity : AppCompatActivity() { try { processHandle.fullyBackfillServers(); } catch (e: Throwable) { - Logger.e(TAG, "Failed to fully backfill servers."); + Logger.e(TAG, getString(R.string.failed_to_fully_backfill_servers)); } withContext(Dispatchers.Main) { diff --git a/app/src/main/java/com/futo/platformplayer/activities/PolycentricHomeActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/PolycentricHomeActivity.kt index 2f691c80..cca48515 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/PolycentricHomeActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/PolycentricHomeActivity.kt @@ -47,7 +47,7 @@ class PolycentricHomeActivity : AppCompatActivity() { this.setMargins(0, 0, 0, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f, resources.displayMetrics).toInt()); }; profileButton.withPrimaryText(systemState.username); - profileButton.withSecondaryText("Sign in to this identity"); + profileButton.withSecondaryText(getString(R.string.sign_in_to_this_identity)); profileButton.onClick.subscribe { StatePolycentric.instance.setProcessHandle(processHandle); startActivity(Intent(this@PolycentricHomeActivity, PolycentricProfileActivity::class.java)); diff --git a/app/src/main/java/com/futo/platformplayer/activities/PolycentricImportProfileActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/PolycentricImportProfileActivity.kt index 68ec7609..8a3d8fd7 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/PolycentricImportProfileActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/PolycentricImportProfileActivity.kt @@ -59,7 +59,7 @@ class PolycentricImportProfileActivity : AppCompatActivity() { _buttonScanProfile.setOnClickListener { val integrator = IntentIntegrator(this) integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE) - integrator.setPrompt("Scan a QR code") + integrator.setPrompt(getString(R.string.scan_a_qr_code)) integrator.setOrientationLocked(true); integrator.setCameraId(0) integrator.setBeepEnabled(false) @@ -70,7 +70,7 @@ class PolycentricImportProfileActivity : AppCompatActivity() { _buttonImportProfile.setOnClickListener { if (_editProfile.text.isEmpty()) { - UIDialogs.toast(this, "Text field does not contain any data"); + UIDialogs.toast(this, getString(R.string.text_field_does_not_contain_any_data)); return@setOnClickListener; } @@ -85,7 +85,7 @@ class PolycentricImportProfileActivity : AppCompatActivity() { private fun import(url: String) { if (!url.startsWith("polycentric://")) { - UIDialogs.toast(this, "Not a valid URL"); + UIDialogs.toast(this, getString(R.string.not_a_valid_url)); return; } @@ -101,7 +101,7 @@ class PolycentricImportProfileActivity : AppCompatActivity() { val existingProcessSecret = Store.instance.getProcessSecret(keyPair.publicKey); if (existingProcessSecret != null) { - UIDialogs.toast(this, "This profile is already imported"); + UIDialogs.toast(this, getString(R.string.this_profile_is_already_imported)); return; } @@ -124,7 +124,7 @@ class PolycentricImportProfileActivity : AppCompatActivity() { finish(); } catch (e: Throwable) { Logger.w(TAG, "Failed to import profile", e); - UIDialogs.toast(this, "Failed to import profile: '${e.message}'"); + UIDialogs.toast(this, getString(R.string.failed_to_import_profile) + " '${e.message}'"); } } diff --git a/app/src/main/java/com/futo/platformplayer/activities/PolycentricProfileActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/PolycentricProfileActivity.kt index 67c66aae..266e51bf 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/PolycentricProfileActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/PolycentricProfileActivity.kt @@ -72,7 +72,7 @@ class PolycentricProfileActivity : AppCompatActivity() { } } catch (e: Throwable) { withContext(Dispatchers.Main) { - UIDialogs.toast(this@PolycentricProfileActivity, "Failed to backfill client"); + UIDialogs.toast(this@PolycentricProfileActivity, getString(R.string.failed_to_backfill_client)); } } } @@ -101,10 +101,10 @@ class PolycentricProfileActivity : AppCompatActivity() { } _buttonDelete.onClick.subscribe { - UIDialogs.showConfirmationDialog(this, "Are you sure you want to remove this profile?", { + UIDialogs.showConfirmationDialog(this, getString(R.string.are_you_sure_you_want_to_remove_this_profile), { val processHandle = StatePolycentric.instance.processHandle; if (processHandle == null) { - UIDialogs.toast(this, "No process handle set"); + UIDialogs.toast(this, getString(R.string.no_process_handle_set)); return@showConfirmationDialog; } @@ -122,13 +122,13 @@ class PolycentricProfileActivity : AppCompatActivity() { var hasChanges = false; val username = _editName.text.toString(); if (username.length < 3) { - UIDialogs.toast(this@PolycentricProfileActivity, "Name must be at least 3 characters long"); + UIDialogs.toast(this@PolycentricProfileActivity, getString(R.string.name_must_be_at_least_3_characters_long)); return@launch; } val processHandle = StatePolycentric.instance.processHandle; if (processHandle == null) { - UIDialogs.toast(this@PolycentricProfileActivity, "Process handle unset"); + UIDialogs.toast(this@PolycentricProfileActivity, getString(R.string.process_handle_unset)); return@launch; } @@ -143,7 +143,7 @@ class PolycentricProfileActivity : AppCompatActivity() { val bytes = readBytesFromUri(applicationContext.contentResolver, avatarUri); if (bytes == null) { withContext(Dispatchers.Main) { - UIDialogs.toast(this@PolycentricProfileActivity, "Failed to read image"); + UIDialogs.toast(this@PolycentricProfileActivity, getString(R.string.failed_to_read_image)); } return@launch; @@ -188,12 +188,12 @@ class PolycentricProfileActivity : AppCompatActivity() { try { processHandle.fullyBackfillServers(); withContext(Dispatchers.Main) { - UIDialogs.toast(this@PolycentricProfileActivity, "Changes have been saved"); + UIDialogs.toast(this@PolycentricProfileActivity, getString(R.string.changes_have_been_saved)); } } catch (e: Throwable) { Logger.w(TAG, "Failed to synchronize changes", e); withContext(Dispatchers.Main) { - UIDialogs.toast(this@PolycentricProfileActivity, "Failed to synchronize changes"); + UIDialogs.toast(this@PolycentricProfileActivity, getString(R.string.failed_to_synchronize_changes)); } } } @@ -235,7 +235,7 @@ class PolycentricProfileActivity : AppCompatActivity() { } else if (resultCode == ImagePicker.RESULT_ERROR) { UIDialogs.toast(this, ImagePicker.getError(data)); } else { - UIDialogs.toast(this, "Image picker cancelled"); + UIDialogs.toast(this, getString(R.string.image_picker_cancelled)); } } diff --git a/app/src/main/java/com/futo/platformplayer/activities/SettingsActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/SettingsActivity.kt index 4266ad89..ce9b12e1 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/SettingsActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/SettingsActivity.kt @@ -70,7 +70,7 @@ class SettingsActivity : AppCompatActivity(), IWithResultLauncher { SettingsDev.instance.developerMode = true; SettingsDev.instance.save(); updateDevMode(); - UIDialogs.toast(this, "You are now in developer mode"); + UIDialogs.toast(this, getString(R.string.you_are_now_in_developer_mode)); } }; }; diff --git a/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelAboutFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelAboutFragment.kt index bd027ba6..97cdf812 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelAboutFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelAboutFragment.kt @@ -77,7 +77,7 @@ class ChannelAboutFragment : Fragment, IChannelTabFragment { }; _textName?.text = channel.name; - val metadata = if(channel.subscribers > 0) "${channel.subscribers.toHumanNumber()} subscribers" else ""; + val metadata = if(channel.subscribers > 0) "${channel.subscribers.toHumanNumber()} " + getString(R.string.subscribers).lowercase() else ""; _textMetadata?.text = metadata; _lastChannel = channel; setLinks(channel.links, channel.name); @@ -91,7 +91,7 @@ class ChannelAboutFragment : Fragment, IChannelTabFragment { l.removeAllViews(); if (links.isNotEmpty()) { - _textFindOn?.text = "Find $name on"; + _textFindOn?.text = getString(R.string.find_name_on).replace("{name}", name); _textFindOn?.visibility = View.VISIBLE; for (pair in links) { diff --git a/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelListFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelListFragment.kt index 42e52e7f..4ce5337d 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelListFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelListFragment.kt @@ -56,7 +56,7 @@ class ChannelListFragment : Fragment, IChannelTabFragment { }.exception { } .exceptionWithParameter { ex, para -> Logger.w(ChannelFragment.TAG, "Failed to load results.", ex); - UIDialogs.toast(requireContext(), "Failed to fetch\n${para}", false) + UIDialogs.toast(requireContext(), getString(R.string.failed_to_fetch) + "\n " + para, false) loadNext(); }; diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/BuyFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/BuyFragment.kt index db93fce9..d2e0fdc9 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/BuyFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/BuyFragment.kt @@ -60,12 +60,12 @@ class BuyFragment : MainFragment() { _paymentManager = PaymentManager(StatePayment.instance, fragment, _overlayPaying) { success, purchaseId, exception -> if(success) { - UIDialogs.showDialog(context, R.drawable.ic_check, "Payment succeeded", "Thanks for your purchase, a key will be sent to your email after your payment has been received!", null, 0, + UIDialogs.showDialog(context, R.drawable.ic_check, context.getString(R.string.payment_succeeded), context.getString(R.string.thanks_for_your_purchase_a_key_will_be_sent_to_your_email_after_your_payment_has_been_received), null, 0, UIDialogs.Action("Ok", {}, UIDialogs.ActionStyle.PRIMARY)); _fragment.close(true); } else { - UIDialogs.showGeneralErrorDialog(context, "Payment failed", exception); + UIDialogs.showGeneralErrorDialog(context, context.getString(R.string.payment_failed), exception); } } @@ -107,12 +107,12 @@ class BuyFragment : MainFragment() { } private fun paid() { - val licenseInput = SlideUpMenuTextInput(context, "License"); - val productLicenseDialog = SlideUpMenuOverlay(context, findViewById(R.id.overlay_paid), "Enter license key", "Ok", true, licenseInput); + val licenseInput = SlideUpMenuTextInput(context, context.getString(R.string.license)); + val productLicenseDialog = SlideUpMenuOverlay(context, findViewById(R.id.overlay_paid), context.getString(R.string.enter_license_key), context.getString(R.string.ok), true, licenseInput); productLicenseDialog.onOK.subscribe { val licenseText = licenseInput.text; if (licenseText.isNullOrEmpty()) { - UIDialogs.showDialogOk(context, R.drawable.ic_error_pred, "Invalid license key"); + UIDialogs.showDialogOk(context, R.drawable.ic_error_pred, context.getString(R.string.invalid_license_key)); return@subscribe; } @@ -127,19 +127,19 @@ class BuyFragment : MainFragment() { licenseInput.clear(); productLicenseDialog.hide(true); - UIDialogs.showDialogOk(context, R.drawable.ic_check, "Your license key has been set!\nAn app restart might be required."); + UIDialogs.showDialogOk(context, R.drawable.ic_check, context.getString(R.string.your_license_key_has_been_set_an_app_restart_might_be_required)); _fragment.close(true); } else { - UIDialogs.showDialogOk(context, R.drawable.ic_error_pred, "Invalid license key"); + UIDialogs.showDialogOk(context, R.drawable.ic_error_pred, context.getString(R.string.invalid_license_key)); } } } catch(ex: Throwable) { Logger.e("BuyFragment", "Failed to activate key", ex); withContext(Dispatchers.Main) { - UIDialogs.showGeneralErrorDialog(context, "Failed to activate key", ex); + UIDialogs.showGeneralErrorDialog(context, context.getString(R.string.failed_to_activate_key), ex); } } } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ChannelFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ChannelFragment.kt index 16af0595..bfc938af 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ChannelFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ChannelFragment.kt @@ -141,7 +141,7 @@ class ChannelFragment : MainFragment() { UIDialogs.showDialog(context, R.drawable.ic_sources, - "No source enabled to support this channel\n(${_url})", null, null, + context.getString(R.string.no_source_enabled_to_support_this_channel) + "\n(${_url})", null, null, 0, UIDialogs.Action("Back", { fragment.close(true); @@ -344,19 +344,19 @@ class ChannelFragment : MainFragment() { _fragment.topBar?.onShown(channel); val buttons = arrayListOf(Pair(R.drawable.ic_playlist_add) { - UIDialogs.showConfirmationDialog(context, "Do you want to convert channel ${channel.name} to a playlist?", { + UIDialogs.showConfirmationDialog(context, context.getString(R.string.do_you_want_to_convert_channel_channelname_to_a_playlist).replace("{channelName}", channel.name), { UIDialogs.showDialogProgress(context) { _fragment.lifecycleScope.launch(Dispatchers.IO) { try { StatePlaylists.instance.createPlaylistFromChannel(channel) { page -> _fragment.lifecycleScope.launch(Dispatchers.Main) { - it.setText("${channel.name}\nPage ${page}"); + it.setText("${channel.name}\n" + context.getString(R.string.page) + " $page"); } }; } catch(ex: Exception) { Logger.e(TAG, "Error", ex); - UIDialogs.showGeneralErrorDialog(context, "Failed to convert channel", ex); + UIDialogs.showGeneralErrorDialog(context, context.getString(R.string.failed_to_convert_channel), ex); } withContext(Dispatchers.Main) { @@ -377,7 +377,7 @@ class ChannelFragment : MainFragment() { _fragment.topBar?.assume()?.setMenuItems(buttons); _buttonSubscribe.setSubscribeChannel(channel); - _textChannelSub.text = if(channel.subscribers > 0) "${channel.subscribers.toHumanNumber()} subscribers" else ""; + _textChannelSub.text = if(channel.subscribers > 0) "${channel.subscribers.toHumanNumber()} " + context.getString(R.string.subscribers).lowercase() else ""; //TODO: Find a better way to access the adapter fragments.. diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentFeedView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentFeedView.kt index d64dd6aa..2a827322 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentFeedView.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentFeedView.kt @@ -72,7 +72,7 @@ abstract class ContentFeedView : FeedView : FeedView() - .filter { it != content }; - StatePlayer.instance.setQueue(newQueue, StatePlayer.TYPE_QUEUE, "Feed Queue", true, false); - }) + SlideUpMenuItem(context, R.drawable.ic_playlist, context.getString(R.string.play_feed_as_queue), context.getString(R.string.play_entire_feed), "playFeed", + { + val newQueue = listOf(content) + recyclerData.results + .filterIsInstance() + .filter { it != content }; + StatePlayer.instance.setQueue(newQueue, StatePlayer.TYPE_QUEUE, "Feed Queue", true, false); + }) ); } }; @@ -96,7 +96,7 @@ abstract class ContentFeedView : FeedView 20) (it.name.subSequence(0, 20).toString() + "...") else it.name; - UIDialogs.toast(context, "Queued [$name]", false); + UIDialogs.toast(context, context.getString(R.string.queued) + " [$name]", false); } }; } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentSearchResultsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentSearchResultsFragment.kt index 0ac5577f..a22c2ab3 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentSearchResultsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentSearchResultsFragment.kt @@ -89,7 +89,7 @@ class ContentSearchResultsFragment : MainFragment() { }) .success { loadedResult(it); }.exception { } .exception { - Logger.w(ChannelFragment.TAG, "Failed to load results.", it); + Logger.w(TAG, "Failed to load results.", it); UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults() }); } } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/DownloadsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/DownloadsFragment.kt index fa1159bf..6fdf009d 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/DownloadsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/DownloadsFragment.kt @@ -136,8 +136,8 @@ class DownloadsFragment : MainFragment() { fun reloadUI() { val usage = StateDownloads.instance.getTotalUsage(true); - _usageUsed.text = "${usage.usage.toHumanBytesSize()} Used"; - _usageAvailable.text = "${usage.available.toHumanBytesSize()} Available"; + _usageUsed.text = "${usage.usage.toHumanBytesSize()} " + context.getString(R.string.used); + _usageAvailable.text = "${usage.available.toHumanBytesSize()} " + context.getString(R.string.available); _usageProgress.progress = usage.percentage.toFloat(); @@ -161,7 +161,7 @@ class DownloadsFragment : MainFragment() { _listPlaylistsContainer.visibility = GONE; else { _listPlaylistsContainer.visibility = VISIBLE; - _listPlaylistsMeta.text = "(${playlists.size} playlists, ${playlists.sumOf { it.playlist.videos.size }} videos)"; + _listPlaylistsMeta.text = "(${playlists.size} ${context.getString(R.string.playlists).lowercase()}, ${playlists.sumOf { it.playlist.videos.size }} ${context.getString(R.string.videos).lowercase()})"; _listPlaylists.removeAllViews(); for(view in playlists.map { PlaylistDownloadItem(context, it) }) { @@ -176,7 +176,7 @@ class DownloadsFragment : MainFragment() { _listDownloadedHeader.visibility = GONE; } else { _listDownloadedHeader.visibility = VISIBLE; - _listDownloadedMeta.text = "(${downloaded.size} videos)"; + _listDownloadedMeta.text = "(${downloaded.size} ${context.getString(R.string.videos).lowercase()})"; } _listDownloaded.setData(downloaded); diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/FeedView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/FeedView.kt index 1f061d14..3f0938cc 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/FeedView.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/FeedView.kt @@ -144,7 +144,7 @@ abstract class FeedView : L recyclerData.adapter.notifyItemRangeInserted(recyclerData.adapter.childToParentPosition(posBefore), filteredResults.size); }.exception { Logger.w(TAG, "Failed to load next page.", it); - UIDialogs.showGeneralRetryErrorDialog(context, "Failed to load next page", it, { + UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_next_page), it, { loadNextPage(); }); //UIDialogs.showDataRetryDialog(layoutInflater, it.message, { loadNextPage() }); @@ -256,7 +256,7 @@ abstract class FeedView : L fragment.lifecycleScope.launch(Dispatchers.Main) { try { if(jsVideoPager != null) - UIDialogs.toast(it, "Plugin ${jsVideoPager.getPluginConfig().name} failed:\n${kv.value.message}", false); + UIDialogs.toast(it, context.getString(R.string.plugin_pluginname_failed_message).replace("{pluginName}", jsVideoPager.getPluginConfig().name).replace("{message}", kv.value.message ?: ""), false); else UIDialogs.toast(it, kv.value.message ?: "", false); } catch (e: Throwable) { @@ -333,11 +333,11 @@ abstract class FeedView : L parentPager.onPagerError.subscribe(this) { Logger.e(TAG, "Search pager failed: ${it.message}", it); when (it) { - is PluginException -> UIDialogs.toast("Plugin [${it.config.name}] failed due to:\n${it.message}") + is PluginException -> UIDialogs.toast("Plugin [{pluginName}] failed due to:\n{exceptionMessage}".replace("{pluginName}", it.config.name).replace("{exceptionMessage}", it.message ?: "")) is CancellationException -> { //Hide cancelled toast } - else -> UIDialogs.toast("Plugin failed due to:\n${it.message}") + else -> UIDialogs.toast(context.getString(R.string.plugin_failed_due_to) + "\n${it.message}") }; }; } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt index 80d6c376..12e6550c 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt @@ -101,21 +101,21 @@ class HomeFragment : MainFragment() { .exception { } .exception { Logger.w(ChannelFragment.TAG, "Plugin failure.", it); - UIDialogs.showDialog(context, R.drawable.ic_error_pred, "Failed to get Home\nPlugin [${it.config.name}]", it.message, null, 0, - UIDialogs.Action("Ignore", {}), - UIDialogs.Action("Sources", { fragment.navigate() }, UIDialogs.ActionStyle.PRIMARY) + UIDialogs.showDialog(context, R.drawable.ic_error_pred, context.getString(R.string.failed_to_get_home_plugin) + " [${it.config.name}]", it.message, null, 0, + UIDialogs.Action(context.getString(R.string.ignore), {}), + UIDialogs.Action(context.getString(R.string.sources), { fragment.navigate() }, UIDialogs.ActionStyle.PRIMARY) ); } .exception { Logger.w(TAG, "Plugin failure.", it); - UIDialogs.showDialog(context, R.drawable.ic_error_pred, "Failed to get Home\nPlugin [${it.config.name}]", it.message, null, 0, - UIDialogs.Action("Ignore", {}), - UIDialogs.Action("Sources", { fragment.navigate() }, UIDialogs.ActionStyle.PRIMARY) + UIDialogs.showDialog(context, R.drawable.ic_error_pred, context.getString(R.string.failed_to_get_home_plugin) + " [${it.config.name}]", it.message, null, 0, + UIDialogs.Action(context.getString(R.string.ignore), {}), + UIDialogs.Action(context.getString(R.string.sources), { fragment.navigate() }, UIDialogs.ActionStyle.PRIMARY) ); } .exception { Logger.w(TAG, "Failed to load channel.", it); - UIDialogs.showGeneralRetryErrorDialog(context, "Failed to get Home", it, { + UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_get_home), it, { loadResults() }) { finishRefreshLayoutLoader(); @@ -159,7 +159,7 @@ class HomeFragment : MainFragment() { } private fun loadedResult(pager : IPager) { if (pager is EmptyPager) { - StateAnnouncement.instance.registerAnnouncement(UUID.randomUUID().toString(), "No home available", "No home page is available, please check if you are connected to the internet and refresh.", AnnouncementType.SESSION); + StateAnnouncement.instance.registerAnnouncement(UUID.randomUUID().toString(), context.getString(R.string.no_home_available), context.getString(R.string.no_home_page_is_available_please_check_if_you_are_connected_to_the_internet_and_refresh), AnnouncementType.SESSION); } Logger.i(TAG, "Got new home pager ${pager}"); diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ImportPlaylistsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ImportPlaylistsFragment.kt index 8c503318..588d2bb8 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ImportPlaylistsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ImportPlaylistsFragment.kt @@ -113,7 +113,7 @@ class ImportPlaylistsFragment : MainFragment() { }.exceptionWithParameter { ex, para -> //setLoading(false); Logger.w(ChannelFragment.TAG, "Failed to load results.", ex); - UIDialogs.toast(context, "Failed to fetch\n${para}", false) + UIDialogs.toast(context, context.getString(R.string.failed_to_fetch) + "\n${para}", false) //UIDialogs.showDataRetryDialog(layoutInflater, { load(); }); loadNext(); }; @@ -144,14 +144,14 @@ class ImportPlaylistsFragment : MainFragment() { val tb = _fragment.topBar as ImportTopBarFragment?; tb?.let { - it.title = "Import Playlists"; + it.title = context.getString(R.string.import_playlists); it.onImport.subscribe(this) { val playlistsToImport = _items.filter { i -> i.selected }.toList(); for (playlistToImport in playlistsToImport) { StatePlaylists.instance.createOrUpdatePlaylist(playlistToImport.playlist); } - UIDialogs.toast("${playlistsToImport.size} playlists imported."); + UIDialogs.toast("${playlistsToImport.size} " + context.getString(R.string.playlists_imported)); _fragment.closeSegment(); }; } @@ -175,7 +175,7 @@ class ImportPlaylistsFragment : MainFragment() { val itemsSelected = _items.count { i -> i.selected }; if (itemsSelected > 0) { _textSelectDeselectAll.text = context.getString(R.string.deselect_all); - _textCounter.text = "$itemsSelected out of ${_items.size} selected"; + _textCounter.text = context.getString(R.string.index_out_of_size_selected).replace("{index}", itemsSelected.toString()).replace("{size}", _items.size.toString()); (_fragment.topBar as ImportTopBarFragment?)?.setImportEnabled(true); } else { _textSelectDeselectAll.text = context.getString(R.string.select_all); diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ImportSubscriptionsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ImportSubscriptionsFragment.kt index 4a6912ec..423faf0e 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ImportSubscriptionsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ImportSubscriptionsFragment.kt @@ -116,7 +116,7 @@ class ImportSubscriptionsFragment : MainFragment() { }.exceptionWithParameter { ex, para -> //setLoading(false); Logger.w(ChannelFragment.TAG, "Failed to load results.", ex); - UIDialogs.toast(context, "Failed to fetch\n${para}", false) + UIDialogs.toast(context, context.getString(R.string.failed_to_fetch) + "\n${para}", false) //UIDialogs.showDataRetryDialog(layoutInflater, { load(); }); loadNext(); }; @@ -147,14 +147,14 @@ class ImportSubscriptionsFragment : MainFragment() { val tb = _fragment.topBar as ImportTopBarFragment?; tb?.let { - it.title = "Import Subscriptions"; + it.title = context.getString(R.string.import_subscriptions); it.onImport.subscribe(this) { val subscriptionsToImport = _items.filter { i -> i.selected }.toList(); for (subscriptionToImport in subscriptionsToImport) { StateSubscriptions.instance.addSubscription(subscriptionToImport.channel); } - UIDialogs.toast("${subscriptionsToImport.size} subscriptions imported."); + UIDialogs.toast("${subscriptionsToImport.size} " + context.getString(R.string.subscriptions_imported)); _fragment.closeSegment(); }; } @@ -165,7 +165,7 @@ class ImportSubscriptionsFragment : MainFragment() { if (_counter >= MAXIMUM_BATCH_SIZE) { if (!_limitToastShown) { _limitToastShown = true; - UIDialogs.toast(context, "Stopped after $MAXIMUM_BATCH_SIZE to avoid rate limit, re-enter to import rest"); + UIDialogs.toast(context, "Stopped after {requestCount} to avoid rate limit, re-enter to import rest".replace("{requestCount}", MAXIMUM_BATCH_SIZE.toString())); } setLoading(false); @@ -187,7 +187,7 @@ class ImportSubscriptionsFragment : MainFragment() { val itemsSelected = _items.count { i -> i.selected }; if (itemsSelected > 0) { _textSelectDeselectAll.text = context.getString(R.string.deselect_all); - _textCounter.text = "$itemsSelected out of ${_items.size} selected"; + _textCounter.text = context.getString(R.string.index_out_of_size_selected).replace("{index}", itemsSelected.toString()).replace("{size}", _items.size.toString()); (_fragment.topBar as ImportTopBarFragment?)?.setImportEnabled(true); } else { _textSelectDeselectAll.text = context.getString(R.string.select_all); diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt index 350c3075..a15e0377 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt @@ -80,8 +80,8 @@ class PlaylistFragment : MainFragment() { constructor(fragment: PlaylistFragment, inflater: LayoutInflater) : super(inflater) { _fragment = fragment; - val nameInput = SlideUpMenuTextInput(context, "Name"); - val editPlaylistOverlay = SlideUpMenuOverlay(context, overlayContainer, "Edit playlist", "Ok", false, nameInput); + val nameInput = SlideUpMenuTextInput(context, context.getString(R.string.name)); + val editPlaylistOverlay = SlideUpMenuOverlay(context, overlayContainer, context.getString(R.string.edit_playlist), context.getString(R.string.ok), false, nameInput); _buttonDownload.visibility = View.VISIBLE; editPlaylistOverlay.onOK.subscribe { @@ -113,14 +113,14 @@ class PlaylistFragment : MainFragment() { val playlist = _playlist ?: return@setOnShare; val reconstruction = StatePlaylists.instance.playlistStore.getReconstructionString(playlist); - UISlideOverlays.showOverlay(overlayContainer, "Playlist [${playlist.name}]", null, {}, - SlideUpMenuItem(context, R.drawable.ic_list, "Share as Text", "Share as a list of video urls", 1, { + UISlideOverlays.showOverlay(overlayContainer, context.getString(R.string.playlist) + " [${playlist.name}]", null, {}, + SlideUpMenuItem(context, R.drawable.ic_list, context.getString(R.string.share_as_text), context.getString(R.string.share_as_a_list_of_video_urls), 1, { _fragment.startActivity(ShareCompat.IntentBuilder(context) .setType("text/plain") .setText(reconstruction) .intent); }), - SlideUpMenuItem(context, R.drawable.ic_move_up, "Share as Import", "Share as a import file for Grayjay", 2, { + SlideUpMenuItem(context, R.drawable.ic_move_up, context.getString(R.string.share_as_import), context.getString(R.string.share_as_a_import_file_for_grayjay), 2, { val shareUri = StatePlaylists.instance.createPlaylistShareJsonUri(context, playlist); _fragment.startActivity(ShareCompat.IntentBuilder(context) .setType("application/json") @@ -146,7 +146,7 @@ class PlaylistFragment : MainFragment() { .exception { Logger.w(TAG, "Failed to load playlist.", it); val c = context ?: return@exception; - UIDialogs.showGeneralRetryErrorDialog(c, "Failed to load playlist", it, ::fetchPlaylist); + UIDialogs.showGeneralRetryErrorDialog(c, context.getString(R.string.failed_to_load_playlist), it, ::fetchPlaylist); }; } @@ -234,7 +234,7 @@ class PlaylistFragment : MainFragment() { _fragment.topBar?.assume()?.setMenuItems(arrayListOf(Pair(R.drawable.ic_copy) { val remotePlaylist = _remotePlaylist; if (remotePlaylist == null) { - UIDialogs.toast("Please wait for playlist to finish loading"); + UIDialogs.toast(context.getString(R.string.please_wait_for_playlist_to_finish_loading)); return@Pair; } @@ -245,7 +245,7 @@ class PlaylistFragment : MainFragment() { withContext(Dispatchers.Main) { setLoading(false); - UIDialogs.toast("Playlist copied as local playlist"); + UIDialogs.toast(context.getString(R.string.playlist_copied_as_local_playlist)); } } catch (e: Throwable) { withContext(Dispatchers.Main) { @@ -284,7 +284,7 @@ class PlaylistFragment : MainFragment() { _buttonDownload.setImageResource(R.drawable.ic_loader_animated); _buttonDownload.drawable.assume { it.start() }; _buttonDownload.setOnClickListener { - UIDialogs.showConfirmationDialog(context, "Are you sure you want to delete the downloaded videos?", { + UIDialogs.showConfirmationDialog(context, context.getString(R.string.are_you_sure_you_want_to_delete_the_downloaded_videos), { StateDownloads.instance.deleteCachedPlaylist(playlist.id); }); } @@ -292,7 +292,7 @@ class PlaylistFragment : MainFragment() { else if(isDownloaded) { _buttonDownload.setImageResource(R.drawable.ic_download_off); _buttonDownload.setOnClickListener { - UIDialogs.showConfirmationDialog(context, "Are you sure you want to delete the downloaded videos?", { + UIDialogs.showConfirmationDialog(context, context.getString(R.string.are_you_sure_you_want_to_delete_the_downloaded_videos), { StateDownloads.instance.deleteCachedPlaylist(playlist.id); }); } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistsFragment.kt index 622e98fe..e0d7c68b 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistsFragment.kt @@ -92,8 +92,8 @@ class PlaylistsFragment : MainFragment() { recyclerPlaylists.adapter = _adapterPlaylist; recyclerPlaylists.layoutManager = LinearLayoutManager(context); - val nameInput = SlideUpMenuTextInput(context, "Name"); - val addPlaylistOverlay = SlideUpMenuOverlay(context, findViewById(R.id.overlay_create_playlist), "Create new playlist", "Ok", false, nameInput); + val nameInput = SlideUpMenuTextInput(context, context.getString(R.string.name)); + val addPlaylistOverlay = SlideUpMenuOverlay(context, findViewById(R.id.overlay_create_playlist), context.getString(R.string.create_new_playlist), context.getString(R.string.ok), false, nameInput); _adapterPlaylist.onClick.subscribe { p -> _fragment.navigate(p); }; _adapterPlaylist.onPlay.subscribe { p -> @@ -130,7 +130,7 @@ class PlaylistsFragment : MainFragment() { _appBar = findViewById(R.id.app_bar); _layoutWatchlist = findViewById(R.id.layout_watchlist); - findViewById(R.id.text_view_all).setOnClickListener { _fragment.navigate("Watch Later"); }; + findViewById(R.id.text_view_all).setOnClickListener { _fragment.navigate(context.getString(R.string.watch_later)); }; StatePlaylists.instance.onWatchLaterChanged.subscribe(this) { updateWatchLater(); }; diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PostDetailFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PostDetailFragment.kt index 88dfbf2f..7f7e6109 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PostDetailFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PostDetailFragment.kt @@ -154,13 +154,13 @@ class PostDetailFragment : MainFragment { { val result = StatePlatform.instance.getContentDetails(it).await(); if(result !is IPlatformPostDetails) - throw IllegalStateException("Expected media content, found ${result.contentType}"); + throw IllegalStateException(context.getString(R.string.expected_media_content_found) + " ${result.contentType}"); return@TaskHandler result; }) .success { setPostDetails(it) } .exception { - Logger.w(ChannelFragment.TAG, "Failed to load post.", it); - UIDialogs.showGeneralRetryErrorDialog(context, "Failed to load post", it, ::fetchPost); + Logger.w(ChannelFragment.TAG, context.getString(R.string.failed_to_load_post), it); + UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_post), it, ::fetchPost); } else TaskHandler(IPlatformPostDetails::class.java) { _fragment.lifecycleScope }; private val _taskLoadPolycentricProfile = TaskHandler(StateApp.instance.scopeGetter, { PolycentricCache.instance.getProfileAsync(it) }) @@ -222,7 +222,7 @@ class PostDetailFragment : MainFragment { val replyCount = c.replyCount ?: 0; var metadata = ""; if (replyCount > 0) { - metadata += "$replyCount replies"; + metadata += "$replyCount " + context.getString(R.string.replies); } if (c is PolycentricPlatformComment) { @@ -601,7 +601,7 @@ class PostDetailFragment : MainFragment { val subscribers = value?.author?.subscribers; if(subscribers != null && subscribers > 0) { _channelMeta.visibility = View.VISIBLE; - _channelMeta.text = if((value.author?.subscribers ?: 0) > 0) value.author.subscribers!!.toHumanNumber() + " subscribers" else ""; + _channelMeta.text = if((value.author.subscribers ?: 0) > 0) value.author.subscribers!!.toHumanNumber() + " " + context.getString(R.string.subscribers) else ""; } else { _channelMeta.visibility = View.GONE; _channelMeta.text = ""; diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SourceDetailFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SourceDetailFragment.kt index 8c9604aa..66b4f33b 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SourceDetailFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SourceDetailFragment.kt @@ -107,7 +107,7 @@ class SourceDetailFragment : MainFragment() { StatePlugins.instance.setPluginSettings(id, _settings!!); reloadSource(id); - UIDialogs.toast("Plugin settings saved", false); + UIDialogs.toast(context.getString(R.string.plugin_settings_saved), false); } if(_settingsAppChanged) { _settingsAppForm.setObjectValues(); @@ -144,8 +144,8 @@ class SourceDetailFragment : MainFragment() { try { _settings = settingValues; _settingsForm.fromPluginSettings( - settings, settingValues, "Plugin settings", - "These settings are defined by the plugin" + settings, settingValues, context.getString(R.string.plugin_settings), + context.getString(R.string.these_settings_are_defined_by_the_plugin) ); _settingsForm.onChanged.clear(); _settingsForm.onChanged.subscribe { field, value -> @@ -158,7 +158,7 @@ class SourceDetailFragment : MainFragment() { } catch(ex: Throwable) { Logger.e(TAG, "Failed to load source", ex); - UIDialogs.toast("Failed to loast source"); + UIDialogs.toast(context.getString(R.string.failed_to_load_source)); } } } @@ -204,8 +204,8 @@ class SourceDetailFragment : MainFragment() { val isEnabled = StatePlatform.instance.isClientEnabled(source); groups.add( - BigButtonGroup(c, "Update", - BigButton(c, "Check for updates", "Checks for new versions of the source", R.drawable.ic_update) { + BigButtonGroup(c, context.getString(R.string.update), + BigButton(c, context.getString(R.string.check_for_updates), context.getString(R.string.checks_for_new_versions_of_the_source), R.drawable.ic_update) { checkForUpdatesSource(); } ) @@ -213,8 +213,8 @@ class SourceDetailFragment : MainFragment() { if (source.isLoggedIn) { groups.add( - BigButtonGroup(c, "Authentication", - BigButton(c, "Logout", "Sign out of the platform", R.drawable.ic_logout) { + BigButtonGroup(c, context.getString(R.string.authentication), + BigButton(c, context.getString(R.string.logout), context.getString(R.string.sign_out_of_the_platform), R.drawable.ic_logout) { logoutSource(); } ) @@ -223,7 +223,7 @@ class SourceDetailFragment : MainFragment() { val migrationButtons = mutableListOf(); if (isEnabled && source.capabilities.hasGetUserSubscriptions) { migrationButtons.add( - BigButton(c, "Import Subscriptions", "Import your subscriptions from this source", R.drawable.ic_subscriptions) { + BigButton(c, context.getString(R.string.import_subscriptions), context.getString(R.string.import_your_subscriptions_from_this_source), R.drawable.ic_subscriptions) { Logger.i(TAG, "Import subscriptions clicked."); importSubscriptionsSource(); } @@ -231,7 +231,7 @@ class SourceDetailFragment : MainFragment() { } if (isEnabled && source.capabilities.hasGetUserPlaylists && source.capabilities.hasGetPlaylist) { - val bigButton = BigButton(c, "Import Playlists", "Import your playlists from this source", R.drawable.ic_playlist) { + val bigButton = BigButton(c, context.getString(R.string.import_playlists), context.getString(R.string.import_your_playlists_from_this_source), R.drawable.ic_playlist) { Logger.i(TAG, "Import playlists clicked."); importPlaylistsSource(); }; @@ -244,13 +244,13 @@ class SourceDetailFragment : MainFragment() { } if (migrationButtons.size > 0) { - groups.add(BigButtonGroup(c, "Migration", *migrationButtons.toTypedArray())); + groups.add(BigButtonGroup(c, context.getString(R.string.migration), *migrationButtons.toTypedArray())); } } else { if(config.authentication != null) { groups.add( - BigButtonGroup(c, "Authentication", - BigButton(c, "Login", "Sign into the platform of this source", R.drawable.ic_login) { + BigButtonGroup(c, context.getString(R.string.authentication), + BigButton(c, context.getString(R.string.login), context.getString(R.string.sign_into_the_platform_of_this_source), R.drawable.ic_login) { loginSource(); } ) @@ -260,8 +260,8 @@ class SourceDetailFragment : MainFragment() { val clientIfExists = StatePlugins.instance.getPlugin(config.id); groups.add( - BigButtonGroup(c, "Management", - BigButton(c, "Uninstall", "Removes the plugin from the app", R.drawable.ic_block) { + BigButtonGroup(c, context.getString(R.string.management), + BigButton(c, context.getString(R.string.uninstall), context.getString(R.string.removes_the_plugin_from_the_app), R.drawable.ic_block) { uninstallSource(); }.withBackground(R.drawable.background_big_button_red).apply { this.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply { @@ -269,8 +269,8 @@ class SourceDetailFragment : MainFragment() { }; }, if(clientIfExists?.captchaEncrypted != null) - BigButton(c, "Delete Captcha", "Deletes stored captcha answer for this plugin", R.drawable.ic_block) { - clientIfExists?.updateCaptcha(null); + BigButton(c, context.getString(R.string.delete_captcha), context.getString(R.string.deletes_stored_captcha_answer_for_this_plugin), R.drawable.ic_block) { + clientIfExists.updateCaptcha(null); }.apply { this.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply { setMargins(0, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5f, resources.displayMetrics).toInt(), 0, 0); @@ -329,7 +329,7 @@ class SourceDetailFragment : MainFragment() { } } catch (e: Throwable) { withContext(Dispatchers.Main) { - context?.let { UIDialogs.showGeneralErrorDialog(it, "Failed to retrieve playlists.", e) } + context?.let { UIDialogs.showGeneralErrorDialog(it, it.getString(R.string.failed_to_retrieve_playlists), e) } } } finally { setLoading(false); @@ -354,14 +354,14 @@ class SourceDetailFragment : MainFragment() { fragment.lifecycleScope.launch(Dispatchers.IO) { try { val subscriptions = source.getUserSubscriptions().distinct(); - Logger.i(TAG, "${subscriptions.size} user subscriptions retrieved."); + Logger.i(TAG, context.getString(R.string.subscriptioncount_user_subscriptions_retrieved).replace("{subscriptionCount}", subscriptions.size.toString())); withContext(Dispatchers.Main) { fragment.navigate(subscriptions); } } catch(e: Throwable) { withContext(Dispatchers.Main) { - context?.let { UIDialogs.showGeneralErrorDialog(it, "Failed to retrieve subscriptions.", e) } + context?.let { UIDialogs.showGeneralErrorDialog(it, context.getString(R.string.failed_to_retrieve_subscriptions), e) } } } finally { setLoading(false); @@ -375,7 +375,7 @@ class SourceDetailFragment : MainFragment() { val config = _config ?: return; val source = StatePlatform.instance.getClient(config.id); - UIDialogs.showConfirmationDialog(context, "Are you sure you want to uninstall ${source.name}", { + UIDialogs.showConfirmationDialog(context, context.getString(R.string.are_you_sure_you_want_to_uninstall) + " ${source.name}", { StatePlugins.instance.deletePlugin(source.id); fragment.lifecycleScope.launch(Dispatchers.IO) { @@ -386,7 +386,7 @@ class SourceDetailFragment : MainFragment() { } withContext(Dispatchers.Main) { - UIDialogs.toast(context, "Uninstalled ${source.name}"); + UIDialogs.toast(context, context.getString(R.string.uninstalled) + " ${source.name}"); fragment.closeSegment(); } } @@ -405,7 +405,7 @@ class SourceDetailFragment : MainFragment() { if (!response.isOk || response.body == null) { Logger.w(TAG, "Failed to check for updates (sourceUrl=${sourceUrl}, response.isOk=${response.isOk}, response.body=${response.body})."); - withContext(Dispatchers.Main) { UIDialogs.toast("Failed to check for updates"); }; + withContext(Dispatchers.Main) { UIDialogs.toast(context.getString(R.string.failed_to_check_for_updates)); }; return@launch; } @@ -415,7 +415,7 @@ class SourceDetailFragment : MainFragment() { val config = SourcePluginConfig.fromJson(configJson); if (config.version <= c.version) { Logger.i(TAG, "Plugin is up to date."); - withContext(Dispatchers.Main) { UIDialogs.toast("Plugin is fully up to date"); }; + withContext(Dispatchers.Main) { UIDialogs.toast(context.getString(R.string.plugin_is_fully_up_to_date)); }; return@launch; } @@ -430,7 +430,7 @@ class SourceDetailFragment : MainFragment() { Logger.i(TAG, "Started add source activity."); } catch (e: Throwable) { Logger.e(TAG, "Failed to check for updates.", e); - withContext(Dispatchers.Main) { UIDialogs.toast("Failed to check for updates"); }; + withContext(Dispatchers.Main) { UIDialogs.toast(context.getString(R.string.failed_to_check_for_updates)); }; } } } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt index 5cd2c3fb..f65c6931 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt @@ -195,9 +195,8 @@ class SubscriptionsFeedFragment : MainFragment() { withContext(Dispatchers.Main) { UIDialogs.showDialog(context, R.drawable.ic_security_pred, - "Rate Limit Warning", "This is a temporary measure to prevent people from hitting rate limit until we have better support for lots of subscriptions." + - "\n\nYou have too many subscriptions for the following plugins:\n", - subsByLimited.map { "${it.first.config.name}: ${it.second.size} Subscriptions" } .joinToString("\n"), 0, UIDialogs.Action("Refresh Anyway", { + context.getString(R.string.rate_limit_warning), context.getString(R.string.this_is_a_temporary_measure_to_prevent_people_from_hitting_rate_limit_until_we_have_better_support_for_lots_of_subscriptions) + context.getString(R.string.you_have_too_many_subscriptions_for_the_following_plugins), + subsByLimited.map { it.first.config.name + ": " + it.second.size + " " + context.getString(R.string.subscriptions) } .joinToString("\n"), 0, UIDialogs.Action("Refresh Anyway", { _bypassRateLimit = true; loadResults(); }, UIDialogs.ActionStyle.DANGEROUS_TEXT), @@ -226,10 +225,10 @@ class SubscriptionsFeedFragment : MainFragment() { synchronized(_filterLock) { _subscriptionBar?.setToggles( - SubscriptionBar.Toggle("Videos", _filterSettings.allowContentTypes.contains(ContentType.MEDIA)) { toggleFilterContentTypes(listOf(ContentType.MEDIA, ContentType.NESTED_VIDEO), it); }, - SubscriptionBar.Toggle("Posts", _filterSettings.allowContentTypes.contains(ContentType.POST)) { toggleFilterContentType(ContentType.POST, it); }, - SubscriptionBar.Toggle("Live", _filterSettings.allowLive) { _filterSettings.allowLive = it; _filterSettings.save(); loadResults(false); }, - SubscriptionBar.Toggle("Planned", _filterSettings.allowPlanned) { _filterSettings.allowPlanned = it; _filterSettings.save(); loadResults(false); } + SubscriptionBar.Toggle(context.getString(R.string.videos), _filterSettings.allowContentTypes.contains(ContentType.MEDIA)) { toggleFilterContentTypes(listOf(ContentType.MEDIA, ContentType.NESTED_VIDEO), it); }, + SubscriptionBar.Toggle(context.getString(R.string.posts), _filterSettings.allowContentTypes.contains(ContentType.POST)) { toggleFilterContentType(ContentType.POST, it); }, + SubscriptionBar.Toggle(context.getString(R.string.live), _filterSettings.allowLive) { _filterSettings.allowLive = it; _filterSettings.save(); loadResults(false); }, + SubscriptionBar.Toggle(context.getString(R.string.planned), _filterSettings.allowPlanned) { _filterSettings.allowPlanned = it; _filterSettings.save(); loadResults(false); } ); } @@ -283,7 +282,7 @@ class SubscriptionsFeedFragment : MainFragment() { val cachePager = ChannelContentCache.instance.getSubscriptionCachePager(); val results = cachePager.getResults(); Logger.i(TAG, "Subscription show cache (${results.size})"); - setTextCentered(if (results.isEmpty()) "No results found\nSwipe down to refresh" else null); + setTextCentered(if (results.isEmpty()) context.getString(R.string.no_results_found_swipe_down_to_refresh) else null); setPager(cachePager); } else { setTextCentered(null); @@ -299,7 +298,7 @@ class SubscriptionsFeedFragment : MainFragment() { finishRefreshLayoutLoader(); setLoading(false); setPager(pager); - setTextCentered(if (pager.getResults().isEmpty()) "No results found\nSwipe down to refresh" else null); + setTextCentered(if (pager.getResults().isEmpty()) context.getString(R.string.no_results_found_swipe_down_to_refresh) else null); } catch (e: Throwable) { Logger.e(TAG, "Failed to finish loading", e) } @@ -326,7 +325,7 @@ class SubscriptionsFeedFragment : MainFragment() { if (toShow is PluginException) UIDialogs.toast( it, - "Plugin [${toShow.config.name}] (${channel}) failed:\n${toShow.message}" + context.getString(R.string.plugin_pluginname_failed_message).replace("{pluginName}", toShow.config.name).replace("{message}", toShow.message ?: "") ); else UIDialogs.toast(it, ex.message ?: ""); @@ -340,7 +339,7 @@ class SubscriptionsFeedFragment : MainFragment() { .map { it!! } .toList(); for(distinctPluginFail in failedPlugins) - UIDialogs.toast(it, "Plugin [${distinctPluginFail.config.name}] failed:\n${distinctPluginFail.message}"); + UIDialogs.toast(it, context.getString(R.string.plugin_pluginname_failed_message).replace("{pluginName}", distinctPluginFail.config.name).replace("{message}", distinctPluginFail.message ?: "")); } } catch (e: Throwable) { Logger.e(TAG, "Failed to handle exceptions", e) diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt index ce230698..9b578127 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt @@ -541,7 +541,7 @@ class VideoDetailView : ConstraintLayout { val replyCount = c.replyCount ?: 0; var metadata = ""; if (replyCount > 0) { - metadata += "$replyCount replies"; + metadata += "$replyCount " + context.getString(R.string.replies); } if (c is PolycentricPlatformComment) { @@ -579,13 +579,13 @@ class VideoDetailView : ConstraintLayout { } fun updateMoreButtons() { - val buttons = listOf(RoundButton(context, R.drawable.ic_add, "Add", TAG_ADD) { + val buttons = listOf(RoundButton(context, R.drawable.ic_add, context.getString(R.string.add), TAG_ADD) { (video ?: _searchVideo)?.let { _slideUpOverlay = UISlideOverlays.showAddToOverlay(it, _overlayContainer); } }, if(video?.isLive ?: false) - RoundButton(context, R.drawable.ic_chat, "Live Chat", TAG_LIVECHAT) { + RoundButton(context, R.drawable.ic_chat, context.getString(R.string.live_chat), TAG_LIVECHAT) { video?.let { try { loadLiveChat(it); @@ -595,7 +595,7 @@ class VideoDetailView : ConstraintLayout { } } } else null, - RoundButton(context, R.drawable.ic_screen_share, "Background", TAG_BACKGROUND) { + RoundButton(context, R.drawable.ic_screen_share, context.getString(R.string.background), TAG_BACKGROUND) { if(!allowBackground) { _player.switchToAudioMode(); allowBackground = true; @@ -607,31 +607,31 @@ class VideoDetailView : ConstraintLayout { it.text.text = resources.getString(R.string.background); } }, - RoundButton(context, R.drawable.ic_download, "Download", TAG_DOWNLOAD) { + RoundButton(context, R.drawable.ic_download, context.getString(R.string.download), TAG_DOWNLOAD) { video?.let { _slideUpOverlay = UISlideOverlays.showDownloadVideoOverlay(it, _overlayContainer, context.contentResolver); }; }, - RoundButton(context, R.drawable.ic_share, "Share", TAG_SHARE) { + RoundButton(context, R.drawable.ic_share, context.getString(R.string.share), TAG_SHARE) { video?.let { Logger.i(TAG, "Share preventPictureInPicture = true"); preventPictureInPicture = true; shareVideo(); }; }, - RoundButton(context, R.drawable.ic_screen_share, "Overlay", TAG_OVERLAY) { + RoundButton(context, R.drawable.ic_screen_share, context.getString(R.string.overlay), TAG_OVERLAY) { this.startPictureInPicture(); fragment.forcePictureInPicture(); //PiPActivity.startPiP(context); }, - RoundButton(context, R.drawable.ic_export, "Page", TAG_OPEN) { + RoundButton(context, R.drawable.ic_export, context.getString(R.string.page), TAG_OPEN) { video?.let { val url = video?.shareUrl ?: _searchVideo?.shareUrl ?: _url; fragment.navigate(url); fragment.minimizeVideoDetail(); }; }, - RoundButton(context, R.drawable.ic_refresh, "Reload", "Reload") { + RoundButton(context, R.drawable.ic_refresh, context.getString(R.string.reload), "Reload") { reloadVideo(); }).filterNotNull(); if(!_buttonPinStore.getAllValues().any()) @@ -857,7 +857,7 @@ class VideoDetailView : ConstraintLayout { val subTitleSegments : ArrayList = ArrayList(); if(video.viewCount > 0) - subTitleSegments.add("${video.viewCount.toHumanNumber()} ${if(video.isLive) "watching now" else "views"}"); + subTitleSegments.add("${video.viewCount.toHumanNumber()} ${if(video.isLive) context.getString(R.string.watching_now) else context.getString(R.string.views)}"); if(video.datetime != null) { val diff = video.datetime?.getNowDiffSeconds() ?: 0; val ago = video.datetime?.toHumanNowDiffString(true) @@ -873,7 +873,7 @@ class VideoDetailView : ConstraintLayout { _subTitle.text = subTitleSegments.joinToString(" • "); _playWhenReady = true; if(video.author.subscribers != null) { - _channelMeta.text = if((video.author.subscribers ?: 0) > 0) video.author.subscribers!!.toHumanNumber() + " subscribers" else ""; + _channelMeta.text = if((video.author.subscribers ?: 0) > 0) video.author.subscribers!!.toHumanNumber() + " " + context.getString(R.string.subscribers)else ""; (_channelName.layoutParams as MarginLayoutParams).setMargins(0, (DP_5 * -1).toInt(), 0, 0); } else { _channelMeta.text = ""; @@ -933,7 +933,7 @@ class VideoDetailView : ConstraintLayout { } if(videoDetail.datetime != null && videoDetail.datetime!! > OffsetDateTime.now()) - UIDialogs.toast(context, "Planned in ${videoDetail.datetime?.toHumanNowDiffString(true)}") + UIDialogs.toast(context, context.getString(R.string.planned_in) + " ${videoDetail.datetime?.toHumanNowDiffString(true)}") if (!videoDetail.isLive) { _player.setPlaybackRate(Settings.instance.playback.getDefaultPlaybackSpeed()); @@ -965,7 +965,7 @@ class VideoDetailView : ConstraintLayout { } catch(ex: Throwable) { withContext(Dispatchers.Main) { - UIDialogs.showGeneralErrorDialog(context, "Failed to get Playback Tracker", ex); + UIDialogs.showGeneralErrorDialog(context, context.getString(R.string.failed_to_get_playback_tracker), ex); }; } }; @@ -983,7 +983,7 @@ class VideoDetailView : ConstraintLayout { _title.text = video.name; _channelName.text = video.author.name; if(video.author.subscribers != null) { - _channelMeta.text = if((video.author.subscribers ?: 0) > 0) video.author.subscribers!!.toHumanNumber() + " subscribers" else ""; + _channelMeta.text = if((video.author.subscribers ?: 0) > 0) video.author.subscribers!!.toHumanNumber() + " " + context.getString(R.string.subscribers) else ""; (_channelName.layoutParams as MarginLayoutParams).setMargins(0, (DP_5 * -1).toInt(), 0, 0); } else { _channelMeta.text = ""; @@ -1008,7 +1008,7 @@ class VideoDetailView : ConstraintLayout { _platform.setPlatformFromClientID(video.id.pluginId); val subTitleSegments : ArrayList = ArrayList(); if(video.viewCount > 0) - subTitleSegments.add("${video.viewCount.toHumanNumber()} ${if(video.isLive) "watching now" else "views"}"); + subTitleSegments.add("${video.viewCount.toHumanNumber()} ${if(video.isLive) context.getString(R.string.watching_now) else context.getString(R.string.views)}"); if(video.datetime != null) { val diff = video.datetime?.getNowDiffSeconds() ?: 0; val ago = video.datetime?.toHumanNowDiffString(true) @@ -1167,7 +1167,7 @@ class VideoDetailView : ConstraintLayout { livePager = StatePlatform.instance.getLiveEvents(video.url); } catch (ex: Throwable) { livePager = null; - UIDialogs.toast("Exception retrieving live events:\n" + ex.message); + UIDialogs.toast(context.getString(R.string.exception_retrieving_live_events) + "\n" + ex.message); Logger.e(TAG, "Failed to retrieve live chat events", ex); } try { @@ -1178,7 +1178,7 @@ class VideoDetailView : ConstraintLayout { } catch(ex: Throwable) { liveChatWindow = null; - UIDialogs.toast("Exception retrieving live chat window:\n" + ex.message); + UIDialogs.toast(context.getString(R.string.exception_retrieving_live_chat_window) + "\n" + ex.message); Logger.e(TAG, "Failed to retrieve live chat window", ex); } val liveChat = livePager?.let { @@ -1200,7 +1200,7 @@ class VideoDetailView : ConstraintLayout { catch(ex: Throwable) { Logger.e(TAG, "Failed to load live chat", ex); - UIDialogs.toast("Live chat failed to load\n" + ex.message); + UIDialogs.toast(context.getString(R.string.live_chat_failed_to_load) + "\n" + ex.message); //_liveChat?.handleEvents(listOf(LiveEventComment("SYSTEM", null, "Failed to load live chat:\n" + ex.message, "#FF0000"))) /* fragment.lifecycleScope.launch(Dispatchers.Main) { @@ -1257,11 +1257,11 @@ class VideoDetailView : ConstraintLayout { } catch(ex: UnsupportedCastException) { Logger.e(TAG, "Failed to load cast media", ex); - UIDialogs.showGeneralErrorDialog(context, "Unsupported Cast format", ex); + UIDialogs.showGeneralErrorDialog(context, context.getString(R.string.unsupported_cast_format), ex); } catch(ex: Throwable) { Logger.e(TAG, "Failed to load media", ex); - UIDialogs.showGeneralErrorDialog(context, "Failed to load media", ex); + UIDialogs.showGeneralErrorDialog(context, context.getString(R.string.failed_to_load_media), ex); } } private fun loadCurrentVideoCast(video: IPlatformVideoDetails, videoSource: IVideoSource?, audioSource: IAudioSource?, subtitleSource: ISubtitleSource?, resumePositionMs: Long) { @@ -1279,7 +1279,7 @@ class VideoDetailView : ConstraintLayout { Logger.i(TAG, "onSourceChanged(videoSource=$videoSource, audioSource=$audioSource, resume=$resume)") if((videoSource == null || videoSource is LocalVideoSource) && (audioSource == null || audioSource is LocalAudioSource)) - UIDialogs.toast(context, "Offline Playback", false); + UIDialogs.toast(context, context.getString(R.string.offline_playback), false); //If LiveStream, set to end if(videoSource is IDashManifestSource || videoSource is IHLSManifestSource) { if (video?.isLive == true) { @@ -1320,12 +1320,12 @@ class VideoDetailView : ConstraintLayout { _didTriggerDatasourceError = true; UIDialogs.showDialog(context, R.drawable.ic_error_pred, - "Media Error", - "The media source encountered an unauthorized error.\nThis might be solved by a plugin reload.\nWould you like to reload?\n(Experimental)", + context.getString(R.string.media_error), + context.getString(R.string.the_media_source_encountered_an_unauthorized_error_this_might_be_solved_by_a_plugin_reload_would_you_like_to_reload_experimental), null, 0, - UIDialogs.Action("No", { _didTriggerDatasourceError = false }), - UIDialogs.Action("Yes", { + UIDialogs.Action(context.getString(R.string.no), { _didTriggerDatasourceError = false }), + UIDialogs.Action(context.getString(R.string.yes), { fragment.lifecycleScope.launch(Dispatchers.IO) { try { StatePlatform.instance.reloadClient(context, config.id); @@ -1423,8 +1423,9 @@ class VideoDetailView : ConstraintLayout { ?.filter { it.container == bestAudioContainer } ?.toList() ?: listOf(); - _overlay_quality_selector = SlideUpMenuOverlay(this.context, _overlay_quality_container, "Quality", null, true, - if (!_isCasting) SlideUpMenuTitle(this.context).apply { setTitle("Playback Rate") } else null, + _overlay_quality_selector = SlideUpMenuOverlay(this.context, _overlay_quality_container, context.getString( + R.string.quality), null, true, + if (!_isCasting) SlideUpMenuTitle(this.context).apply { setTitle(context.getString(R.string.playback_rate)) } else null, if (!_isCasting) SlideUpMenuButtonList(this.context).apply { setButtons(listOf("0.25", "0.5", "0.75", "1.0", "1.25", "1.5", "1.75", "2.0", "2.25"), _player.getPlaybackRate().toString()); onClick.subscribe { v -> @@ -1438,7 +1439,7 @@ class VideoDetailView : ConstraintLayout { } else null, if(localVideoSources?.isNotEmpty() == true) - SlideUpMenuGroup(this.context, "Offline Video", "video", + SlideUpMenuGroup(this.context, context.getString(R.string.offline_video), "video", *localVideoSources.stream() .map { SlideUpMenuItem(this.context, R.drawable.ic_movie, it!!.name, "${it.width}x${it.height}", it, @@ -1446,7 +1447,7 @@ class VideoDetailView : ConstraintLayout { }.toList().toTypedArray()) else null, if(localAudioSource?.isNotEmpty() == true) - SlideUpMenuGroup(this.context, "Offline Audio", "audio", + SlideUpMenuGroup(this.context, context.getString(R.string.offline_audio), "audio", *localAudioSource.stream() .map { SlideUpMenuItem(this.context, R.drawable.ic_music, it.name, it.bitrate.toHumanBitrate(), it, @@ -1454,7 +1455,7 @@ class VideoDetailView : ConstraintLayout { }.toList().toTypedArray()) else null, if(localSubtitleSources?.isNotEmpty() == true) - SlideUpMenuGroup(this.context, "Offline Subtitles", "subtitles", + SlideUpMenuGroup(this.context, context.getString(R.string.offline_subtitles), "subtitles", *localSubtitleSources .map { SlideUpMenuItem(this.context, R.drawable.ic_edit, it.name, "", it, @@ -1462,7 +1463,7 @@ class VideoDetailView : ConstraintLayout { }.toList().toTypedArray()) else null, if(liveStreamVideoFormats?.isEmpty() == false) - SlideUpMenuGroup(this.context, "Stream Video", "video", + SlideUpMenuGroup(this.context, context.getString(R.string.stream_video), "video", *liveStreamVideoFormats.stream() .map { SlideUpMenuItem(this.context, R.drawable.ic_movie, it?.label ?: it.containerMimeType ?: it.bitrate.toString(), "${it.width}x${it.height}", it, @@ -1470,7 +1471,7 @@ class VideoDetailView : ConstraintLayout { }.toList().toTypedArray()) else null, if(liveStreamAudioFormats?.isEmpty() == false) - SlideUpMenuGroup(this.context, "Stream Audio", "audio", + SlideUpMenuGroup(this.context, context.getString(R.string.stream_audio), "audio", *liveStreamAudioFormats.stream() .map { SlideUpMenuItem(this.context, R.drawable.ic_music, "${it?.label ?: it.containerMimeType} ${it.bitrate}", "", it, @@ -1479,7 +1480,7 @@ class VideoDetailView : ConstraintLayout { else null, if(bestVideoSources.isNotEmpty()) - SlideUpMenuGroup(this.context, "Video", "video", + SlideUpMenuGroup(this.context, context.getString(R.string.video), "video", *bestVideoSources.stream() .map { SlideUpMenuItem(this.context, R.drawable.ic_movie, it!!.name, if (it.width > 0 && it.height > 0) "${it.width}x${it.height}" else "", it, @@ -1487,7 +1488,7 @@ class VideoDetailView : ConstraintLayout { }.toList().toTypedArray()) else null, if(bestAudioSources.isNotEmpty()) - SlideUpMenuGroup(this.context, "Audio", "audio", + SlideUpMenuGroup(this.context, context.getString(R.string.audio), "audio", *bestAudioSources.stream() .map { SlideUpMenuItem(this.context, R.drawable.ic_music, it.name, it.bitrate.toHumanBitrate(), it, @@ -1495,7 +1496,7 @@ class VideoDetailView : ConstraintLayout { }.toList().toTypedArray()) else null, if(video?.subtitles?.isNotEmpty() ?: false && video != null) - SlideUpMenuGroup(this.context, "Subtitles", "subtitles", + SlideUpMenuGroup(this.context, context.getString(R.string.subtitles), "subtitles", *video.subtitles .map { SlideUpMenuItem(this.context, R.drawable.ic_edit, it.name, "", it, @@ -1618,12 +1619,13 @@ class VideoDetailView : ConstraintLayout { private fun handleUnavailableVideo(msg: String? = null) { if (!nextVideo()) { if(video?.datetime == null || video?.datetime!! < OffsetDateTime.now().minusHours(1)) - UIDialogs.showDialog(context, R.drawable.ic_lock, "Unavailable video", msg ?: "This video is unavailable.", null, 0, - UIDialogs.Action("Back", { + UIDialogs.showDialog(context, R.drawable.ic_lock, context.getString(R.string.unavailable_video), msg ?: context.getString(R.string.this_video_is_unavailable), null, 0, + UIDialogs.Action(context.getString(R.string.back), { this@VideoDetailView.onClose.emit(); - }, UIDialogs.ActionStyle.PRIMARY)); + }, UIDialogs.ActionStyle.PRIMARY) + ); } else { - StateAnnouncement.instance.registerAnnouncement(video?.id?.value + "_Q_UNAVAILABLE", "Unavailable video", "There was an unavailable video in your queue [${video?.name}] by [${video?.author?.name}].", AnnouncementType.SESSION) + StateAnnouncement.instance.registerAnnouncement(video?.id?.value + "_Q_UNAVAILABLE", context.getString(R.string.unavailable_video), context.getString(R.string.there_was_an_unavailable_video_in_your_queue_videoname_by_authorname).replace("{videoName}", video?.name ?: "").replace("{authorName}", video?.author?.name ?: ""), AnnouncementType.SESSION) } video?.let { StatePlatform.instance.clearContentDetailCache(it.url) }; @@ -1875,9 +1877,9 @@ class VideoDetailView : ConstraintLayout { _player.getGlobalVisibleRect(r); r.right = r.right - _player.paddingEnd; val playpauseAction = if(_player.playing) - RemoteAction(Icon.createWithResource(context, R.drawable.ic_pause_notif), "Pause", "Pauses the video", MediaControlReceiver.getPauseIntent(context, 5)); + RemoteAction(Icon.createWithResource(context, R.drawable.ic_pause_notif), context.getString(R.string.pause), context.getString(R.string.pauses_the_video), MediaControlReceiver.getPauseIntent(context, 5)); else - RemoteAction(Icon.createWithResource(context, R.drawable.ic_play_notif), "Play", "Resumes the video", MediaControlReceiver.getPlayIntent(context, 6)); + RemoteAction(Icon.createWithResource(context, R.drawable.ic_play_notif), context.getString(R.string.play), context.getString(R.string.resumes_the_video), MediaControlReceiver.getPlayIntent(context, 6)); return PictureInPictureParams.Builder() .setAspectRatio(Rational(videoSourceWidth, videoSourceHeight)) @@ -2066,7 +2068,7 @@ class VideoDetailView : ConstraintLayout { }, UIDialogs.ActionStyle.PRIMARY) ); } else { - StateAnnouncement.instance.registerAnnouncement(video?.id?.value + "_Q_NOSOURCES", "Video without source", "There was a in your queue [${video?.name}] by [${video?.author?.name}] without the required source being enabled, playback was skipped.", AnnouncementType.SESSION) + StateAnnouncement.instance.registerAnnouncement(video?.id?.value + "_Q_NOSOURCES", context.getString(R.string.video_without_source), context.getString(R.string.there_was_a_in_your_queue_videoname_by_authorname_without_the_required_source_being_enabled_playback_was_skipped).replace("{videoName}", video?.name ?: "").replace("{authorName}", video?.author?.name ?: ""), AnnouncementType.SESSION) } } .exception { @@ -2085,9 +2087,10 @@ class VideoDetailView : ConstraintLayout { Logger.w(TAG, "exception", it) if (!nextVideo()) { - UIDialogs.showGeneralRetryErrorDialog(context, "Failed to load video (ScriptImplementationException)", it, ::fetchVideo); + UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_video_scriptimplementationexception), it, ::fetchVideo); } else { - StateAnnouncement.instance.registerAnnouncement(video?.id?.value + "_Q_INVALIDVIDEO", "Invalid video", "There was an invalid video in your queue [${video?.name}] by [${video?.author?.name}], playback was skipped.", AnnouncementType.SESSION) + StateAnnouncement.instance.registerAnnouncement(video?.id?.value + "_Q_INVALIDVIDEO", context.getString(R.string.invalid_video), context.getString( + R.string.there_was_an_invalid_video_in_your_queue_videoname_by_authorname_playback_was_skipped).replace("{videoName}", video?.name ?: "").replace("{authorName}", video?.author?.name ?: ""), AnnouncementType.SESSION) } } .exception { @@ -2102,7 +2105,9 @@ class VideoDetailView : ConstraintLayout { this@VideoDetailView.onClose.emit(); }, UIDialogs.ActionStyle.PRIMARY)); } else { - StateAnnouncement.instance.registerAnnouncement(video?.id?.value + "_Q_AGERESTRICT", "Age restricted video", "There was an age restricted video in your queue [${video?.name}] by [${video?.author?.name}], this video was not accessible and playback was skipped.", AnnouncementType.SESSION) + StateAnnouncement.instance.registerAnnouncement(video?.id?.value + "_Q_AGERESTRICT", context.getString(R.string.age_restricted_video), + context.getString(R.string.there_was_an_age_restricted_video_in_your_queue_videoname_by_authorname_this_video_was_not_accessible_and_playback_was_skipped).replace("{videoName}", video?.name ?: "").replace("{authorName}", video?.author?.name ?: ""), + AnnouncementType.SESSION) } } .exception { @@ -2118,7 +2123,7 @@ class VideoDetailView : ConstraintLayout { _retryJob = null; _liveTryJob?.cancel(); _liveTryJob = null; - UIDialogs.showGeneralRetryErrorDialog(context, "Failed to load video (ScriptException)", it, ::fetchVideo); + UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_video_scriptexception), it, ::fetchVideo); } } .exception { @@ -2130,7 +2135,7 @@ class VideoDetailView : ConstraintLayout { _retryJob = null; _liveTryJob?.cancel(); _liveTryJob = null; - UIDialogs.showGeneralRetryErrorDialog(context, "Failed to load video", it, ::fetchVideo); + UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_video), it, ::fetchVideo); } } else TaskHandler(IPlatformVideoDetails::class.java, {fragment.lifecycleScope}); @@ -2171,7 +2176,7 @@ class VideoDetailView : ConstraintLayout { val toWait = _liveStreamCheckInterval.toList().sortedBy { abs(diffSeconds - it.first) }.firstOrNull()?.second?.toLong() ?: return; fragment.lifecycleScope.launch(Dispatchers.Main){ - UIDialogs.toast(context, "Not yet available, retrying in ${toWait}s"); + UIDialogs.toast(context, context.getString(R.string.not_yet_available_retrying_in_time_s).replace("{time}", toWait.toString())); } _liveTryJob?.cancel(); @@ -2185,7 +2190,7 @@ class VideoDetailView : ConstraintLayout { if(videoDetail.datetime != null && videoDetail.live == null && !videoDetail.video.videoSources.any()) { if(videoDetail.datetime!! > OffsetDateTime.now()) withContext(Dispatchers.Main) { - UIDialogs.toast(context, "Planned in ${videoDetail.datetime?.toHumanNowDiffString(true)}"); + UIDialogs.toast(context, context.getString(R.string.planned_in) + " ${videoDetail.datetime?.toHumanNowDiffString(true)}"); } startLiveTry(liveTryVideo); } @@ -2198,7 +2203,7 @@ class VideoDetailView : ConstraintLayout { catch(ex: Throwable) { Logger.e(TAG, "Failed to live try fetch video.", ex); withContext(Dispatchers.Main) { - UIDialogs.toast(context, "Failed to retry for live stream"); + UIDialogs.toast(context, context.getString(R.string.failed_to_retry_for_live_stream)); } } } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoListEditorView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoListEditorView.kt index a853d25f..c43d926c 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoListEditorView.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoListEditorView.kt @@ -91,7 +91,7 @@ abstract class VideoListEditorView : LinearLayout { } protected fun setVideoCount(videoCount: Int = -1) { - _textMetadata.text = if (videoCount == -1) "" else "${videoCount} videos"; + _textMetadata.text = if (videoCount == -1) "" else "${videoCount} " + context.getString(R.string.videos); } protected fun setVideos(videos: List?, canEdit: Boolean) { @@ -105,7 +105,7 @@ abstract class VideoListEditorView : LinearLayout { .into(it); }; } else { - _textMetadata.text = "0 videos"; + _textMetadata.text = "0 " + context.getString(R.string.videos); if(_imagePlaylistThumbnail != null) { Glide.with(_imagePlaylistThumbnail) .load(R.drawable.placeholder_video_thumbnail) diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/topbar/GeneralTopBarFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/topbar/GeneralTopBarFragment.kt index 2b0a0f4a..597fc9c7 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/topbar/GeneralTopBarFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/topbar/GeneralTopBarFragment.kt @@ -35,7 +35,7 @@ class GeneralTopBarFragment : TopFragment() { val view = inflater.inflate(R.layout.fragment_overview_top_bar, container, false); view.findViewById(R.id.app_icon).setOnClickListener { - UIDialogs.toast("This app is in development. Please submit bug reports and understand that many features are incomplete.", true); + UIDialogs.toast(getString(R.string.this_app_is_in_development_please_submit_bug_reports_and_understand_that_many_features_are_incomplete), true); }; val buttonSearch: ImageButton = view.findViewById(R.id.button_search); diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/topbar/SearchTopBarFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/topbar/SearchTopBarFragment.kt index 511abd3a..bb3af1ae 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/topbar/SearchTopBarFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/topbar/SearchTopBarFragment.kt @@ -194,7 +194,7 @@ class SearchTopBarFragment : TopFragment() { if (editSearch != null) { val text = editSearch.text.toString(); if (text.length < 3) { - UIDialogs.toast("Please use at least 3 characters"); + UIDialogs.toast(getString(R.string.please_use_at_least_3_characters)); return; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6cdfacea..e3a145ae 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -161,7 +161,8 @@ The operation failed because it is fundamentally incompatible with this device The operation failed because one or more of the APKs was invalid The operation failed because of storage issues - LIVE + LIVE + Live Click to read more Click to hide Version @@ -184,6 +185,7 @@ Create OK Yes + No Confirm Are you sure you want to delete this playlist? Are you sure you want to delete this subscription? @@ -512,6 +514,176 @@ Enable where this plugin\'s content are visible Show content in home tab Show content in search results + No valid URL provided.. + Invalid Config Format + Failed to fetch configuration + Failed to fetch script + URL Access + The plugin will have access to the following domains + Eval Access + The plugin will have access to eval capability (remote injection) + Failed to scan QR code + Not a plugin URL + Scan a QR Code + Not implemented yet.. + Unknown Context + Something went wrong... missing stack trace? + Logs already submitted. + No logs found. + Failed automated share, share manually? + Shared {id} + Unhandled exception in VS + Send exception to developers... + Your license key has been set!\nAn app restart might be required. + Invalid license format + Unknown content format + Unknown file format + Unknown Polycentric format + Unknown url format + Failed to handle file + Unknown reconstruction type + Failed to parse NewPipe Subscriptions + Failed to generate QR code + Share Text + Copied Text + Must be at least 3 characters long. + Failed to create profile. + Failed to fully backfill servers. + Sign in to this identity + Text field does not contain any data + Not a valid URL + This profile is already imported + Failed to import profile: + Failed to backfill client + Are you sure you want to remove this profile? + No process handle set + Name must be at least 3 characters long + Process handle unset + Failed to read image + Changes have been saved + Failed to synchronize changes + Image picker cancelled + You are now in developer mode + Subscribers + Find {name} on + Failed to fetch + Thanks for your purchase, a key will be sent to your email after your payment has been received! + Payment failed + Payment succeeded + Enter license key + Invalid license key + License + Failed to activate key + No source enabled to support this channel + Do you want to convert channel {channelName} to a playlist? + Failed to convert channel + Page + Hide + Hide from Home + Play Feed as Queue + Play entire feed + Queued + Used + Available + Failed to load next page + Plugin {pluginName} failed:\n{message} + Plugin failed due to: + Failed to get Home\nPlugin + Failed to get Home + No home available + No home page is available, please check if you are connected to the internet and refresh. + Import Playlists + playlists imported. + {index} out of {size} selected + Import Subscriptions + subscriptions imported. + Edit playlist + Share as Text + Share as a list of video urls + Share as Import + Share as a import file for Grayjay + Failed to load playlist + Please wait for playlist to finish loading + Playlist copied as local playlist + Are you sure you want to delete the downloaded videos? + Create new playlist + Expected media content, found + Failed to load post. + replies + Plugin settings saved + Plugin settings + These settings are defined by the plugin + Failed to load source + Check for updates + Checks for new versions of the source + Authentication + Sign out of the platform + Import your subscriptions from this source + Import your playlists from this source + Login + Sign into the platform of this source + Management + Uninstall + Removes the plugin from the app + Delete Captcha + Deletes stored captcha answer for this plugin + Failed to retrieve playlists. + {subscriptionCount} user subscriptions retrieved. + Failed to retrieve subscriptions. + Are you sure you want to uninstall + Uninstalled + Failed to check for updates + Plugin is fully up to date + Rate Limit Warning + This is a temporary measure to prevent people from hitting rate limit until we have better support for lots of subscriptions. + \n\nYou have too many subscriptions for the following plugins:\n + Posts + Planned + No results found\nSwipe down to refresh + Overlay + Reload + watching now + views + Planned in + Failed to get Playback Tracker + Exception retrieving live events: + Exception retrieving live chat window: + Live chat failed to load + Unsupported Cast format + Failed to load media + Offline Playback + Media Error + The media source encountered an unauthorized error.\nThis might be solved by a plugin reload.\nWould you like to reload?\n(Experimental) + Playback Rate + Quality + Offline Video + Offline Audio + Offline Subtitles + Stream Video + Stream Audio + Audio + Subtitles + Unavailable video + This video is unavailable. + There was an unavailable video in your queue [{videoName}] by [{authorName}]. + Back + Pause + Play + Pauses the video + Resumes the video + Video without source + There was a in your queue [{videoName}] by [{authorName}] without the required source being enabled, playback was skipped. + Failed to load video (ScriptImplementationException) + Invalid video + There was an invalid video in your queue [{videoName}] by [{authorName}], playback was skipped. + Age restricted video + There was an age restricted video in your queue [{videoName}] by [{authorName}], this video was not accessible and playback was skipped. + Failed to load video (ScriptException) + Failed to load video + Not yet available, retrying in {time}s + Failed to retry for live stream + This app is in development. Please submit bug reports and understand that many features are incomplete. + Please use at least 3 characters FastCast ChromeCast diff --git a/dep/futopay b/dep/futopay index 3090ca3a..dfecd646 160000 --- a/dep/futopay +++ b/dep/futopay @@ -1 +1 @@ -Subproject commit 3090ca3af03ce276fc167d47f49daa76a5b67dd7 +Subproject commit dfecd64655d1434d5d9345acadade6388942dc7b diff --git a/lint.xml b/lint.xml new file mode 100644 index 00000000..6e599f67 --- /dev/null +++ b/lint.xml @@ -0,0 +1,4 @@ + + + +