Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay

This commit is contained in:
Koen 2023-11-07 16:03:05 +01:00
commit 63137b4c4d
19 changed files with 144 additions and 31 deletions

View file

@ -4,9 +4,7 @@ import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.webkit.CookieManager
import androidx.core.content.ContextCompat.startActivity
import androidx.lifecycle.lifecycleScope
import com.futo.platformplayer.activities.*
import com.futo.platformplayer.api.http.ManagedHttpClient
@ -30,6 +28,7 @@ import kotlinx.serialization.*
import kotlinx.serialization.json.*
import java.io.File
import java.time.OffsetDateTime
import java.util.Locale
@Serializable
data class MenuBottomBarSetting(val id: Int, var enabled: Boolean);
@ -46,7 +45,7 @@ class Settings : FragmentedStorageFileJson() {
@FormField(
R.string.manage_polycentric_identity, FieldForm.BUTTON,
R.string.manage_your_polycentric_identity, -4
R.string.manage_your_polycentric_identity, -5
)
@FormFieldButton(R.drawable.ic_person)
fun managePolycentricIdentity() {
@ -61,7 +60,7 @@ class Settings : FragmentedStorageFileJson() {
@FormField(
R.string.show_faq, FieldForm.BUTTON,
R.string.get_answers_to_common_questions, -3
R.string.get_answers_to_common_questions, -4
)
@FormFieldButton(R.drawable.ic_quiz)
fun openFAQ() {
@ -74,7 +73,7 @@ class Settings : FragmentedStorageFileJson() {
}
@FormField(
R.string.show_issues, FieldForm.BUTTON,
R.string.a_list_of_user_reported_and_self_reported_issues, -2
R.string.a_list_of_user_reported_and_self_reported_issues, -3
)
@FormFieldButton(R.drawable.ic_data_alert)
fun openIssues() {
@ -109,7 +108,7 @@ class Settings : FragmentedStorageFileJson() {
@FormField(
R.string.manage_tabs, FieldForm.BUTTON,
R.string.change_tabs_visible_on_the_home_screen, -1
R.string.change_tabs_visible_on_the_home_screen, -2
)
@FormFieldButton(R.drawable.ic_tabs)
fun manageTabs() {
@ -122,11 +121,39 @@ class Settings : FragmentedStorageFileJson() {
}
}
@FormField(R.string.home, "group", R.string.configure_how_your_home_tab_works_and_feels, 0)
var language = LanguageSettings();
@Serializable
class LanguageSettings {
@FormField(R.string.app_language, FieldForm.DROPDOWN, R.string.may_require_restart, 5, "app_language")
@DropdownFieldOptionsId(R.array.app_languages)
var appLanguage: Int = 0;
fun getAppLanguageLocaleString(): String? {
return when(appLanguage) {
0 -> null
1 -> "en";
2 -> "de";
3 -> "es";
4 -> "pt";
5 -> "fr"
6 -> "ja";
7 -> "ko";
8 -> "zh";
9 -> "ru";
10 -> "ar";
else -> null
}
}
}
@FormField(R.string.home, "group", R.string.configure_how_your_home_tab_works_and_feels, 1)
var home = HomeSettings();
@Serializable
class HomeSettings {
@FormField(R.string.feed_style, FieldForm.DROPDOWN, -1, 5)
@FormField(R.string.feed_style, FieldForm.DROPDOWN, R.string.may_require_restart, 5)
@DropdownFieldOptionsId(R.array.feed_style)
var homeFeedStyle: Int = 1;
@ -136,21 +163,28 @@ class Settings : FragmentedStorageFileJson() {
else
return FeedStyle.THUMBNAIL;
}
@FormField(R.string.preview_feed_items, FieldForm.TOGGLE, R.string.preview_feed_items_description, 6)
var previewFeedItems: Boolean = true;
}
@FormField(R.string.search, "group", -1, 2)
var search = SearchSettings();
@Serializable
class SearchSettings {
@FormField(R.string.search_history, FieldForm.TOGGLE, -1, 4)
@FormField(R.string.search_history, FieldForm.TOGGLE, R.string.may_require_restart, 3)
@Serializable(with = FlexibleBooleanSerializer::class)
var searchHistory: Boolean = true;
@FormField(R.string.feed_style, FieldForm.DROPDOWN, -1, 5)
@FormField(R.string.feed_style, FieldForm.DROPDOWN, -1, 4)
@DropdownFieldOptionsId(R.array.feed_style)
var searchFeedStyle: Int = 1;
@FormField(R.string.preview_feed_items, FieldForm.TOGGLE, R.string.preview_feed_items_description, 5)
var previewFeedItems: Boolean = true;
fun getSearchFeedStyle(): FeedStyle {
if(searchFeedStyle == 0)
@ -164,7 +198,7 @@ class Settings : FragmentedStorageFileJson() {
var subscriptions = SubscriptionsSettings();
@Serializable
class SubscriptionsSettings {
@FormField(R.string.feed_style, FieldForm.DROPDOWN, -1, 5)
@FormField(R.string.feed_style, FieldForm.DROPDOWN, R.string.may_require_restart, 4)
@DropdownFieldOptionsId(R.array.feed_style)
var subscriptionsFeedStyle: Int = 1;
@ -175,6 +209,9 @@ class Settings : FragmentedStorageFileJson() {
return FeedStyle.THUMBNAIL;
}
@FormField(R.string.preview_feed_items, FieldForm.TOGGLE, R.string.preview_feed_items_description, 5)
var previewFeedItems: Boolean = true;
@FormField(R.string.fetch_on_app_boot, FieldForm.TOGGLE, R.string.shortly_after_opening_the_app_start_fetching_subscriptions, 6)
@Serializable(with = FlexibleBooleanSerializer::class)
var fetchOnAppBoot: Boolean = true;
@ -208,6 +245,7 @@ class Settings : FragmentedStorageFileJson() {
@FormField(R.string.track_playtime_locally, FieldForm.TOGGLE, R.string.track_playtime_locally_description, 10)
var allowPlaytimeTracking: Boolean = true;
}
@FormField(R.string.player, "group", R.string.change_behavior_of_the_player, 4)
@ -215,10 +253,10 @@ class Settings : FragmentedStorageFileJson() {
@Serializable
class PlaybackSettings {
@FormField(R.string.primary_language, FieldForm.DROPDOWN, -1, 0)
@DropdownFieldOptionsId(R.array.languages)
@DropdownFieldOptionsId(R.array.audio_languages)
var primaryLanguage: Int = 0;
fun getPrimaryLanguage(context: Context) = context.resources.getStringArray(R.array.languages)[primaryLanguage];
fun getPrimaryLanguage(context: Context) = context.resources.getStringArray(R.array.audio_languages)[primaryLanguage];
@FormField(R.string.default_playback_speed, FieldForm.DROPDOWN, -1, 1)
@DropdownFieldOptionsId(R.array.playback_speeds)
@ -277,10 +315,6 @@ class Settings : FragmentedStorageFileJson() {
@DropdownFieldOptionsId(R.array.resume_after_preview)
var resumeAfterPreview: Int = 1;
@FormField(R.string.live_chat_webview, FieldForm.TOGGLE, R.string.use_the_live_chat_web_window_when_available_over_native_implementation, 8)
var useLiveChatWindow: Boolean = true;
fun shouldResumePreview(previewedPosition: Long): Boolean{
if(resumeAfterPreview == 2)
return true;
@ -288,6 +322,14 @@ class Settings : FragmentedStorageFileJson() {
return true;
return false;
}
@FormField(R.string.live_chat_webview, FieldForm.TOGGLE, R.string.use_the_live_chat_web_window_when_available_over_native_implementation, 8)
var useLiveChatWindow: Boolean = true;
@FormField(R.string.background_switch_audio, FieldForm.TOGGLE, R.string.background_switch_audio_description, 8)
var backgroundSwitchToAudio: Boolean = true;
}
@FormField(R.string.downloads, "group", R.string.configure_downloading_of_videos, 5)

View file

@ -7,6 +7,7 @@ import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.net.Uri
import android.os.Bundle
import android.preference.PreferenceManager
import android.util.TypedValue
import android.view.View
import android.widget.FrameLayout
@ -154,6 +155,11 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
}
}
override fun attachBaseContext(newBase: Context?) {
Logger.i(TAG, "MainActivity.attachBaseContext")
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
StateApp.instance.setGlobalContext(this, lifecycleScope);
StateApp.instance.mainAppStarting(this);

View file

@ -1,6 +1,7 @@
package com.futo.platformplayer.activities
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
@ -13,6 +14,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.futo.platformplayer.*
import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.views.Loader
import com.futo.platformplayer.views.fields.FieldForm
import com.futo.platformplayer.views.fields.ReadOnlyTextField
@ -28,6 +30,10 @@ class SettingsActivity : AppCompatActivity(), IWithResultLauncher {
private var _isFinished = false;
override fun attachBaseContext(newBase: Context?) {
Logger.i("SettingsActivity", "SettingsActivity.attachBaseContext")
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
@ -43,6 +49,11 @@ class SettingsActivity : AppCompatActivity(), IWithResultLauncher {
Logger.i("SettingsActivity", "Setting [${field.field?.name}] changed, saving");
_form.setObjectValues();
Settings.instance.save();
if(field.descriptor?.id == "app_language") {
Logger.i("SettingsActivity", "App language change detected, propogating to shared preferences");
StateApp.instance.setLocaleSetting(this, Settings.instance.language.getAppLanguageLocaleString());
}
};
_buttonBack.setOnClickListener {
finish();

View file

@ -63,7 +63,7 @@ class ContentSearchResultsFragment : MainFragment() {
}
fun setPreviewsEnabled(previewsEnabled: Boolean) {
_view?.setPreviewsEnabled(previewsEnabled);
_view?.setPreviewsEnabled(previewsEnabled && Settings.instance.search.previewFeedItems);
}
@SuppressLint("ViewConstructor")
@ -93,6 +93,8 @@ class ContentSearchResultsFragment : MainFragment() {
Logger.w(TAG, "Failed to load results.", it);
UIDialogs.showGeneralRetryErrorDialog(context, it.message ?: "", it, { loadResults() });
}
setPreviewsEnabled(Settings.instance.search.previewFeedItems);
}
override fun cleanup() {

View file

@ -78,7 +78,7 @@ class HomeFragment : MainFragment() {
}
fun setPreviewsEnabled(previewsEnabled: Boolean) {
_view?.setPreviewsEnabled(previewsEnabled);
_view?.setPreviewsEnabled(previewsEnabled && Settings.instance.home.previewFeedItems);
}
@SuppressLint("ViewConstructor")
@ -122,6 +122,8 @@ class HomeFragment : MainFragment() {
setLoading(false);
};
};
setPreviewsEnabled(Settings.instance.home.previewFeedItems);
}
fun onShown() {

View file

@ -81,7 +81,7 @@ class SubscriptionsFeedFragment : MainFragment() {
}
fun setPreviewsEnabled(previewsEnabled: Boolean) {
_view?.setPreviewsEnabled(previewsEnabled);
_view?.setPreviewsEnabled(previewsEnabled && Settings.instance.subscriptions.previewFeedItems);
}
@SuppressLint("ViewConstructor")
@ -108,6 +108,8 @@ class SubscriptionsFeedFragment : MainFragment() {
};
initializeToolbarContent();
setPreviewsEnabled(Settings.instance.subscriptions.previewFeedItems);
}
fun onShown() {

View file

@ -814,7 +814,7 @@ class VideoDetailView : ConstraintLayout {
when (Settings.instance.playback.backgroundPlay) {
0 -> handlePause();
1 -> {
if(!(video?.isLive ?: false))
if(!(video?.isLive ?: false) && Settings.instance.playback.backgroundSwitchToAudio)
_player.switchToAudioMode();
StatePlayer.instance.startOrUpdateMediaSession(context, video);
}

View file

@ -731,6 +731,34 @@ class StateApp {
}
}
fun getLocaleContext(baseContext: Context?): Context? {
val locale = getLocaleSetting(baseContext);
try {
if (baseContext != null && locale != null) {
val config = baseContext.resources.configuration;
config.setLocale(locale);
return baseContext.createConfigurationContext(config);
}
return baseContext;
}
catch (ex: Throwable) {
Logger.e(TAG, "Failed to load locale", ex);
return baseContext;
}
}
fun getLocaleSetting(context: Context?): Locale? {
return context?.getSharedPreferences("language", Context.MODE_PRIVATE)
?.getString("language", null)
?.let { Locale(it) };
}
fun setLocaleSetting(context: Context?, locale: String?) {
context?.getSharedPreferences("language", Context.MODE_PRIVATE)
?.edit()
?.putString("language", locale)
?.apply();
}
companion object {
private val TAG = "StateApp";
@SuppressLint("StaticFieldLeak") //This is only alive while MainActivity is alive

View file

@ -34,7 +34,8 @@ class CommentsList : ConstraintLayout {
}
.exception<Throwable> {
Logger.e(TAG, "Failed to load comments.", it);
UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_comments) + (it.message ?: ""), it, ::fetchComments);
UIDialogs.toast(context, context.getString(R.string.failed_to_load_comments) + "\n" + (it.message ?: ""));
//UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_comments) + (it.message ?: ""), it, ::fetchComments);
setLoading(false);
} else TaskHandler(IPlatformVideoDetails::class.java, StateApp.instance.scopeGetter);

View file

@ -701,7 +701,7 @@
<item>استئناف بعد 10 ثوان</item>
<item>استئناف دائم</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>الإنجليزية</item>
<item>الإسبانية</item>
<item>الفرنسية</item>

View file

@ -701,7 +701,7 @@
<item>Nach 10 Sekunden fortsetzen</item>
<item>Immer fortsetzen</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>Englisch</item>
<item>Spanisch</item>
<item>Französisch</item>

View file

@ -717,7 +717,7 @@
<item>Reanudar Después de 10s</item>
<item>Siempre Reanudar</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>Inglés</item>
<item>Español</item>
<item>Francés</item>

View file

@ -701,7 +701,7 @@
<item>Reprendre après 10s</item>
<item>Toujours reprendre</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>Anglais</item>
<item>Espagnol</item>
<item>Français</item>

View file

@ -701,7 +701,7 @@
<item>10秒後から再開</item>
<item>常に再開</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>英語</item>
<item>スペイン語</item>
<item>フランス語</item>

View file

@ -701,7 +701,7 @@
<item>10초 후에 이어서</item>
<item>항상 이어서</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>영어</item>
<item>스페인어</item>
<item>프랑스어</item>

View file

@ -701,7 +701,7 @@
<item>Continuar Após 10s</item>
<item>Sempre Continuar</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>Inglês</item>
<item>Espanhol</item>
<item>Francês</item>

View file

@ -701,7 +701,7 @@
<item>Продолжить после 10 секунд</item>
<item>Всегда продолжать</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>Английский</item>
<item>Испанский</item>
<item>Французский</item>

View file

@ -701,7 +701,7 @@
<item>预览后10秒继续</item>
<item>始终继续</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>英语</item>
<item>西班牙语</item>
<item>法语</item>

View file

@ -312,11 +312,17 @@
<string name="import_data_description">Select a file to import, support various files (alternative to opening directly)</string>
<string name="external_storage">External Storage</string>
<string name="feed_style">Feed Style</string>
<string name="app_language">App Language</string>
<string name="may_require_restart">May require restart</string>
<string name="fetch_on_app_boot">Fetch on app boot</string>
<string name="get_answers_to_common_questions">Get answers to common questions</string>
<string name="give_feedback_on_the_application">Give feedback on the application</string>
<string name="info">Info</string>
<string name="live_chat_webview">Live Chat Webview</string>
<string name="background_switch_audio">Switch to Audio in Background</string>
<string name="background_switch_audio_description">Optimize bandwidth usage by switching to audio-only stream in background if available, may cause stutter</string>
<string name="preview_feed_items">Preview Feed Items</string>
<string name="preview_feed_items_description">When the preview feedstyle is used, if items should auto-preview when scrolling over them</string>
<string name="log_level">Log Level</string>
<string name="logging">Logging</string>
<string name="manage_polycentric_identity">Manage Polycentric identity</string>
@ -730,6 +736,19 @@
<item>Preview</item>
<item>List</item>
</string-array>
<string-array name="app_languages">
<item>System</item>
<item>English (EN)</item>
<item>German (DE)</item>
<item>Spanish (ES)</item>
<item>Portuguese (PT)</item>
<item>French (FR)</item>
<item>Japanese (JA)</item>
<item>Korean (KO)</item>
<item>Chinese (ZH)</item>
<item>Russian (RU)</item>
<item>Arabic (AR)</item>
</string-array>
<string-array name="player_background_behavior">
<item>None</item>
<item>Keep Playing</item>
@ -740,7 +759,7 @@
<item>Resume After 10s</item>
<item>Always Resume</item>
</string-array>
<string-array name="languages">
<string-array name="audio_languages">
<item>English</item>
<item>Spanish</item>
<item>French</item>