diff --git a/app/src/main/java/com/futo/platformplayer/Settings.kt b/app/src/main/java/com/futo/platformplayer/Settings.kt index 9ef64a86..56aff38d 100644 --- a/app/src/main/java/com/futo/platformplayer/Settings.kt +++ b/app/src/main/java/com/futo/platformplayer/Settings.kt @@ -158,7 +158,11 @@ class Settings : FragmentedStorageFileJson() { var previewFeedItems: Boolean = true; - @FormField(R.string.clear_hidden, FieldForm.BUTTON, R.string.clear_hidden_description, 7) + @FormField(R.string.progress_bar, FieldForm.TOGGLE, R.string.progress_bar_description, 6) + var progressBar: Boolean = false; + + + @FormField(R.string.clear_hidden, FieldForm.BUTTON, R.string.clear_hidden_description, 8) @FormFieldButton(R.drawable.ic_visibility_off) fun clearHidden() { StateMeta.instance.removeAllHiddenCreators(); @@ -185,6 +189,8 @@ class Settings : FragmentedStorageFileJson() { @FormField(R.string.preview_feed_items, FieldForm.TOGGLE, R.string.preview_feed_items_description, 5) var previewFeedItems: Boolean = true; + @FormField(R.string.progress_bar, FieldForm.TOGGLE, R.string.progress_bar_description, 6) + var progressBar: Boolean = false; fun getSearchFeedStyle(): FeedStyle { @@ -195,7 +201,17 @@ class Settings : FragmentedStorageFileJson() { } } - @FormField(R.string.subscriptions, "group", R.string.configure_how_your_subscriptions_works_and_feels, 3) + + @FormField(R.string.channel, "group", -1, 3) + var channel = ChannelSettings(); + @Serializable + class ChannelSettings { + + @FormField(R.string.progress_bar, FieldForm.TOGGLE, R.string.progress_bar_description, 6) + var progressBar: Boolean = false; + } + + @FormField(R.string.subscriptions, "group", R.string.configure_how_your_subscriptions_works_and_feels, 4) var subscriptions = SubscriptionsSettings(); @Serializable class SubscriptionsSettings { @@ -213,14 +229,17 @@ class Settings : FragmentedStorageFileJson() { @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) + @FormField(R.string.progress_bar, FieldForm.TOGGLE, R.string.progress_bar_description, 6) + var progressBar: Boolean = false; + + @FormField(R.string.fetch_on_app_boot, FieldForm.TOGGLE, R.string.shortly_after_opening_the_app_start_fetching_subscriptions, 7) @Serializable(with = FlexibleBooleanSerializer::class) var fetchOnAppBoot: Boolean = true; - @FormField(R.string.fetch_on_tab_opened, FieldForm.TOGGLE, R.string.fetch_on_tab_opened_description, 6) + @FormField(R.string.fetch_on_tab_opened, FieldForm.TOGGLE, R.string.fetch_on_tab_opened_description, 8) var fetchOnTabOpen: Boolean = true; - @FormField(R.string.background_update, FieldForm.DROPDOWN, R.string.experimental_background_update_for_subscriptions_cache, 7) + @FormField(R.string.background_update, FieldForm.DROPDOWN, R.string.experimental_background_update_for_subscriptions_cache, 9) @DropdownFieldOptionsId(R.array.background_interval) var subscriptionsBackgroundUpdateInterval: Int = 0; @@ -236,7 +255,7 @@ class Settings : FragmentedStorageFileJson() { }; - @FormField(R.string.subscription_concurrency, FieldForm.DROPDOWN, R.string.specify_how_many_threads_are_used_to_fetch_channels, 8) + @FormField(R.string.subscription_concurrency, FieldForm.DROPDOWN, R.string.specify_how_many_threads_are_used_to_fetch_channels, 10) @DropdownFieldOptionsId(R.array.thread_count) var subscriptionConcurrency: Int = 3; @@ -244,17 +263,17 @@ class Settings : FragmentedStorageFileJson() { return threadIndexToCount(subscriptionConcurrency); } - @FormField(R.string.show_watch_metrics, FieldForm.TOGGLE, R.string.show_watch_metrics_description, 9) + @FormField(R.string.show_watch_metrics, FieldForm.TOGGLE, R.string.show_watch_metrics_description, 11) var showWatchMetrics: Boolean = false; - @FormField(R.string.track_playtime_locally, FieldForm.TOGGLE, R.string.track_playtime_locally_description, 10) + @FormField(R.string.track_playtime_locally, FieldForm.TOGGLE, R.string.track_playtime_locally_description, 12) var allowPlaytimeTracking: Boolean = true; - @FormField(R.string.always_reload_from_cache, FieldForm.TOGGLE, R.string.always_reload_from_cache_description, 11) + @FormField(R.string.always_reload_from_cache, FieldForm.TOGGLE, R.string.always_reload_from_cache_description, 13) var alwaysReloadFromCache: Boolean = false; - @FormField(R.string.clear_channel_cache, FieldForm.BUTTON, R.string.clear_channel_cache_description, 12) + @FormField(R.string.clear_channel_cache, FieldForm.BUTTON, R.string.clear_channel_cache_description, 14) fun clearChannelCache() { UIDialogs.toast(SettingsActivity.getActivity()!!, "Started clearing.."); ChannelContentCache.instance.clear(); @@ -262,7 +281,7 @@ class Settings : FragmentedStorageFileJson() { } } - @FormField(R.string.player, "group", R.string.change_behavior_of_the_player, 4) + @FormField(R.string.player, "group", R.string.change_behavior_of_the_player, 5) var playback = PlaybackSettings(); @Serializable class PlaybackSettings { @@ -360,7 +379,7 @@ class Settings : FragmentedStorageFileJson() { var backgroundSwitchToAudio: Boolean = true; } - @FormField(R.string.comments, "group", R.string.comments_description, 4) + @FormField(R.string.comments, "group", R.string.comments_description, 6) var comments = CommentSettings(); @Serializable class CommentSettings { @@ -369,7 +388,7 @@ class Settings : FragmentedStorageFileJson() { var defaultCommentSection: Int = 0; } - @FormField(R.string.downloads, "group", R.string.configure_downloading_of_videos, 5) + @FormField(R.string.downloads, "group", R.string.configure_downloading_of_videos, 7) var downloads = Downloads(); @Serializable class Downloads { @@ -409,7 +428,7 @@ class Settings : FragmentedStorageFileJson() { } } - @FormField(R.string.browsing, "group", R.string.configure_browsing_behavior, 6) + @FormField(R.string.browsing, "group", R.string.configure_browsing_behavior, 8) var browsing = Browsing(); @Serializable class Browsing { @@ -418,7 +437,7 @@ class Settings : FragmentedStorageFileJson() { var videoCache: Boolean = true; } - @FormField(R.string.casting, "group", R.string.configure_casting, 7) + @FormField(R.string.casting, "group", R.string.configure_casting, 9) var casting = Casting(); @Serializable class Casting { @@ -446,28 +465,7 @@ class Settings : FragmentedStorageFileJson() { }*/ } - @FormField(R.string.time_bar, "group", R.string.configure_if_historical_time_bar_should_be_shown, 8) - var timeBars = TimeBars(); - @Serializable - class TimeBars { - @FormField(R.string.home, FieldForm.TOGGLE, -1, 0) - @Serializable(with = FlexibleBooleanSerializer::class) - var home: Boolean = true; - - @FormField(R.string.subscriptions, FieldForm.TOGGLE, -1, 1) - @Serializable(with = FlexibleBooleanSerializer::class) - var subscriptions: Boolean = true; - - @FormField(R.string.search, FieldForm.TOGGLE, -1, 2) - @Serializable(with = FlexibleBooleanSerializer::class) - var search: Boolean = true; - - @FormField(R.string.channel, FieldForm.TOGGLE, -1, 3) - @Serializable(with = FlexibleBooleanSerializer::class) - var channel: Boolean = true; - } - - @FormField(R.string.logging, FieldForm.GROUP, -1, 9) + @FormField(R.string.logging, FieldForm.GROUP, -1, 10) var logging = Logging(); @Serializable class Logging { diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt index 134fcb7e..af7291ae 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt @@ -6,10 +6,13 @@ import com.futo.platformplayer.api.http.ManagedHttpClient import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourceAuth import com.futo.platformplayer.api.media.platforms.js.SourceCaptchaData +import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig +import com.futo.platformplayer.engine.exceptions.ScriptImplementationException import com.futo.platformplayer.matchesDomain class JSHttpClient : ManagedHttpClient { private val _jsClient: JSClient?; + private val _jsConfig: SourcePluginConfig?; private val _auth: SourceAuth?; private val _captcha: SourceCaptchaData?; @@ -20,8 +23,9 @@ class JSHttpClient : ManagedHttpClient { private var _currentCookieMap: HashMap>; - constructor(jsClient: JSClient?, auth: SourceAuth? = null, captcha: SourceCaptchaData? = null) : super() { + constructor(jsClient: JSClient?, auth: SourceAuth? = null, captcha: SourceCaptchaData? = null, config: SourcePluginConfig? = null) : super() { _jsClient = jsClient; + _jsConfig = config; _auth = auth; _captcha = captcha; @@ -87,7 +91,11 @@ class JSHttpClient : ManagedHttpClient { } } - _jsClient?.validateUrlOrThrow(request.url.toString()); + if(_jsClient != null) + _jsClient?.validateUrlOrThrow(request.url.toString()); + else if (_jsConfig != null && !_jsConfig.isUrlAllowed(request.url.toString())) + throw ScriptImplementationException(_jsConfig, "Attempted to access non-whitelisted url: ${request.url.toString()}\nAdd it to your config"); + return newBuilder?.let { it.build() } ?: request; } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/structures/DedupContentPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/structures/DedupContentPager.kt index 9839141d..04f0786a 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/structures/DedupContentPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/structures/DedupContentPager.kt @@ -52,7 +52,7 @@ class DedupContentPager : IPager, IAsyncPager items.first() } val bestPlatform = _preferredPlatform.map { it.lowercase() }.firstOrNull { platformItemMap.containsKey(it) } - val bestItem = platformItemMap[bestPlatform] ?: sameItems.first() + val bestItem = platformItemMap[bestPlatform] ?: sameItems.firstOrNull(); resultsToRemove.addAll(sameItems.filter { it != bestItem }); } diff --git a/app/src/main/java/com/futo/platformplayer/developer/DeveloperEndpoints.kt b/app/src/main/java/com/futo/platformplayer/developer/DeveloperEndpoints.kt index 95502b6d..92a48ebf 100644 --- a/app/src/main/java/com/futo/platformplayer/developer/DeveloperEndpoints.kt +++ b/app/src/main/java/com/futo/platformplayer/developer/DeveloperEndpoints.kt @@ -24,6 +24,7 @@ import com.google.gson.JsonArray import com.google.gson.JsonParser import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import java.lang.reflect.InvocationTargetException import java.util.UUID import kotlin.reflect.jvm.jvmErasure @@ -185,7 +186,11 @@ class DeveloperEndpoints(private val context: Context) { val config = context.readContentJson() try { _testPluginVariables.clear(); - _testPlugin = V8Plugin(StateApp.instance.context, config); + + val client = JSHttpClient(null, null, null, config); + val clientAuth = JSHttpClient(null, null, null, config); + _testPlugin = V8Plugin(StateApp.instance.context, config, null, client, clientAuth); + context.respondJson(200, testPluginOrThrow.getPackageVariables()); } catch(ex: Throwable) { @@ -235,7 +240,7 @@ class DeveloperEndpoints(private val context: Context) { } LoginActivity.showLogin(StateApp.instance.context, config) { _testPluginVariables.clear(); - _testPlugin = V8Plugin(StateApp.instance.context, config, null, JSHttpClient(null), JSHttpClient(null, it)); + _testPlugin = V8Plugin(StateApp.instance.context, config, null, JSHttpClient(null, null, null, config), JSHttpClient(null, it, null, config)); }; context.respondCode(200, "Login started"); @@ -311,6 +316,11 @@ class DeveloperEndpoints(private val context: Context) { val json = wrapRemoteResult(callResult, false); context.respondCode(200, json, "application/json"); } + catch(invocation: InvocationTargetException) { + val innerException = invocation.targetException; + Logger.e("DeveloperEndpoints", innerException.message, innerException); + context.respondCode(500, innerException::class.simpleName + ":" + innerException.message ?: "", "text/plain") + } catch(ilEx: IllegalArgumentException) { if(ilEx.message?.contains("does not exist") ?: false) { context.respondCode(400, ilEx.message ?: "", "text/plain"); diff --git a/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelContentsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelContentsFragment.kt index 54a09c43..490e7447 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelContentsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelContentsFragment.kt @@ -153,7 +153,7 @@ class ChannelContentsFragment : Fragment(), IChannelTabFragment { _recyclerResults = view.findViewById(R.id.recycler_videos); - _adapterResults = PreviewContentListAdapter(view.context, FeedStyle.THUMBNAIL, _results, null, Settings.instance.timeBars.channel).apply { + _adapterResults = PreviewContentListAdapter(view.context, FeedStyle.THUMBNAIL, _results, null, Settings.instance.channel.progressBar).apply { this.onContentUrlClicked.subscribe(this@ChannelContentsFragment.onContentUrlClicked::emit); this.onUrlClicked.subscribe(this@ChannelContentsFragment.onUrlClicked::emit); this.onContentClicked.subscribe(this@ChannelContentsFragment.onContentClicked::emit); 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 14eed33d..d5a2c987 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 @@ -84,7 +84,7 @@ class ContentSearchResultsFragment : MainFragment() { private var _channelUrl: String? = null; private val _taskSearch: TaskHandler>; - override val shouldShowTimeBar: Boolean get() = Settings.instance.timeBars.search + override val shouldShowTimeBar: Boolean get() = Settings.instance.search.progressBar constructor(fragment: ContentSearchResultsFragment, inflater: LayoutInflater) : super(fragment, inflater) { _taskSearch = TaskHandler>({fragment.lifecycleScope}, { query -> 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 ee1944e9..dd5f33c3 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 @@ -95,7 +95,7 @@ class HomeFragment : MainFragment() { private var _announcementsView: AnnouncementView; private val _taskGetPager: TaskHandler>; - override val shouldShowTimeBar: Boolean get() = Settings.instance.timeBars.home + override val shouldShowTimeBar: Boolean get() = Settings.instance.home.progressBar constructor(fragment: HomeFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData, LinearLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null) : super(fragment, inflater, cachedRecyclerData) { _announcementsView = AnnouncementView(context, null).apply { 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 7317cb95..21b75c83 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 @@ -93,7 +93,7 @@ class SubscriptionsFeedFragment : MainFragment() { @SuppressLint("ViewConstructor") class SubscriptionsFeedView : ContentFeedView { - override val shouldShowTimeBar: Boolean get() = Settings.instance.timeBars.subscriptions + override val shouldShowTimeBar: Boolean get() = Settings.instance.subscriptions.progressBar constructor(fragment: SubscriptionsFeedFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData, LinearLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null) : super(fragment, inflater, cachedRecyclerData) { Logger.i(TAG, "SubscriptionsFeedFragment constructor()"); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dda12fc9..9198b49a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,6 +10,8 @@ General Channel Home + Progress Bar + If a historical progress bar should be shown Recommendations More Playlists diff --git a/app/src/stable/assets/sources/kick b/app/src/stable/assets/sources/kick index d0b7a2c1..396dd169 160000 --- a/app/src/stable/assets/sources/kick +++ b/app/src/stable/assets/sources/kick @@ -1 +1 @@ -Subproject commit d0b7a2c1b4939c27b4ec04ee52b5a16380c27afb +Subproject commit 396dd16987fba87e6f455a900426a5d7f22cbde3 diff --git a/app/src/stable/assets/sources/patreon b/app/src/stable/assets/sources/patreon index 9e26b703..55aef15f 160000 --- a/app/src/stable/assets/sources/patreon +++ b/app/src/stable/assets/sources/patreon @@ -1 +1 @@ -Subproject commit 9e26b7032e64ed03315a8e75d2174cb4253030d1 +Subproject commit 55aef15f4b4ad1359266bb77908b48726d32594b diff --git a/app/src/unstable/assets/sources/kick b/app/src/unstable/assets/sources/kick index d0b7a2c1..396dd169 160000 --- a/app/src/unstable/assets/sources/kick +++ b/app/src/unstable/assets/sources/kick @@ -1 +1 @@ -Subproject commit d0b7a2c1b4939c27b4ec04ee52b5a16380c27afb +Subproject commit 396dd16987fba87e6f455a900426a5d7f22cbde3 diff --git a/app/src/unstable/assets/sources/patreon b/app/src/unstable/assets/sources/patreon index 339b44e9..55aef15f 160000 --- a/app/src/unstable/assets/sources/patreon +++ b/app/src/unstable/assets/sources/patreon @@ -1 +1 @@ -Subproject commit 339b44e9f00521ab4cfe755a343fd9e6e5338d04 +Subproject commit 55aef15f4b4ad1359266bb77908b48726d32594b