mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-24 21:44:49 +00:00
Simplified all searches to use ContentSearchResultsFragment.
This commit is contained in:
parent
d10026acd1
commit
63761cfc9a
16 changed files with 230 additions and 18 deletions
|
@ -1,5 +1,6 @@
|
||||||
package com.futo.platformplayer.api.media
|
package com.futo.platformplayer.api.media
|
||||||
|
|
||||||
|
import com.futo.platformplayer.api.media.models.IPlatformChannelContent
|
||||||
import com.futo.platformplayer.api.media.models.PlatformAuthorLink
|
import com.futo.platformplayer.api.media.models.PlatformAuthorLink
|
||||||
import com.futo.platformplayer.api.media.models.ResultCapabilities
|
import com.futo.platformplayer.api.media.models.ResultCapabilities
|
||||||
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
|
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
|
||||||
|
@ -66,6 +67,11 @@ interface IPlatformClient {
|
||||||
*/
|
*/
|
||||||
fun searchChannels(query: String): IPager<PlatformAuthorLink>;
|
fun searchChannels(query: String): IPager<PlatformAuthorLink>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for channels and returns a content pager
|
||||||
|
*/
|
||||||
|
fun searchChannelsAsContent(query: String): IPager<IPlatformContent>;
|
||||||
|
|
||||||
|
|
||||||
//Video Pages
|
//Video Pages
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,7 +2,10 @@ package com.futo.platformplayer.api.media.models
|
||||||
|
|
||||||
import com.caoccao.javet.values.reference.V8ValueObject
|
import com.caoccao.javet.values.reference.V8ValueObject
|
||||||
import com.futo.platformplayer.api.media.PlatformID
|
import com.futo.platformplayer.api.media.PlatformID
|
||||||
|
import com.futo.platformplayer.api.media.models.contents.ContentType
|
||||||
|
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
||||||
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
||||||
|
import com.futo.platformplayer.api.media.platforms.js.models.JSContent
|
||||||
import com.futo.platformplayer.getOrDefault
|
import com.futo.platformplayer.getOrDefault
|
||||||
import com.futo.platformplayer.getOrThrow
|
import com.futo.platformplayer.getOrThrow
|
||||||
|
|
||||||
|
@ -42,4 +45,21 @@ open class PlatformAuthorLink {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IPlatformChannelContent : IPlatformContent {
|
||||||
|
val thumbnail: String?
|
||||||
|
val subscribers: Long?
|
||||||
|
}
|
||||||
|
|
||||||
|
open class JSChannelContent : JSContent, IPlatformChannelContent {
|
||||||
|
override val contentType: ContentType get() = ContentType.CHANNEL
|
||||||
|
override val thumbnail: String?
|
||||||
|
override val subscribers: Long?
|
||||||
|
|
||||||
|
constructor(config: SourcePluginConfig, obj: V8ValueObject) : super(config, obj) {
|
||||||
|
val contextName = "Channel";
|
||||||
|
thumbnail = obj.getOrDefault<String>(config, "thumbnail", contextName, null)
|
||||||
|
subscribers = if(obj.has("subscribers")) obj.getOrThrow(config,"subscribers", contextName) else null
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,6 +12,7 @@ enum class ContentType(val value: Int) {
|
||||||
URL(9),
|
URL(9),
|
||||||
|
|
||||||
NESTED_VIDEO(11),
|
NESTED_VIDEO(11),
|
||||||
|
CHANNEL(60),
|
||||||
|
|
||||||
LOCKED(70),
|
LOCKED(70),
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.caoccao.javet.values.reference.V8ValueObject
|
||||||
import com.futo.platformplayer.api.http.ManagedHttpClient
|
import com.futo.platformplayer.api.http.ManagedHttpClient
|
||||||
import com.futo.platformplayer.api.media.IPlatformClient
|
import com.futo.platformplayer.api.media.IPlatformClient
|
||||||
import com.futo.platformplayer.api.media.PlatformClientCapabilities
|
import com.futo.platformplayer.api.media.PlatformClientCapabilities
|
||||||
|
import com.futo.platformplayer.api.media.models.IPlatformChannelContent
|
||||||
import com.futo.platformplayer.api.media.models.PlatformAuthorLink
|
import com.futo.platformplayer.api.media.models.PlatformAuthorLink
|
||||||
import com.futo.platformplayer.api.media.models.ResultCapabilities
|
import com.futo.platformplayer.api.media.models.ResultCapabilities
|
||||||
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
|
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
|
||||||
|
@ -31,6 +32,7 @@ import com.futo.platformplayer.api.media.platforms.js.internal.JSParameterDocs
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.IJSContent
|
import com.futo.platformplayer.api.media.platforms.js.models.IJSContent
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.IJSContentDetails
|
import com.futo.platformplayer.api.media.platforms.js.models.IJSContentDetails
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSChannel
|
import com.futo.platformplayer.api.media.platforms.js.models.JSChannel
|
||||||
|
import com.futo.platformplayer.api.media.platforms.js.models.JSChannelContentPager
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSChannelPager
|
import com.futo.platformplayer.api.media.platforms.js.models.JSChannelPager
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSChapter
|
import com.futo.platformplayer.api.media.platforms.js.models.JSChapter
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSComment
|
import com.futo.platformplayer.api.media.platforms.js.models.JSComment
|
||||||
|
@ -361,6 +363,10 @@ open class JSClient : IPlatformClient {
|
||||||
return@isBusyWith JSChannelPager(config, this,
|
return@isBusyWith JSChannelPager(config, this,
|
||||||
plugin.executeTyped("source.searchChannels(${Json.encodeToString(query)})"));
|
plugin.executeTyped("source.searchChannels(${Json.encodeToString(query)})"));
|
||||||
}
|
}
|
||||||
|
override fun searchChannelsAsContent(query: String): IPager<IPlatformContent> = isBusyWith("searchChannels") {
|
||||||
|
ensureEnabled();
|
||||||
|
return@isBusyWith JSChannelContentPager(config, this, plugin.executeTyped("source.searchChannels(${Json.encodeToString(query)})"), );
|
||||||
|
}
|
||||||
|
|
||||||
@JSDocs(6, "source.isChannelUrl(url)", "Validates if an channel url is for this platform")
|
@JSDocs(6, "source.isChannelUrl(url)", "Validates if an channel url is for this platform")
|
||||||
@JSDocsParameter("url", "A channel url (May not be your platform)")
|
@JSDocsParameter("url", "A channel url (May not be your platform)")
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.futo.platformplayer.api.media.platforms.js.models
|
package com.futo.platformplayer.api.media.platforms.js.models
|
||||||
|
|
||||||
import com.caoccao.javet.values.reference.V8ValueObject
|
import com.caoccao.javet.values.reference.V8ValueObject
|
||||||
|
import com.futo.platformplayer.api.media.models.JSChannelContent
|
||||||
import com.futo.platformplayer.api.media.models.contents.ContentType
|
import com.futo.platformplayer.api.media.models.contents.ContentType
|
||||||
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
||||||
import com.futo.platformplayer.api.media.platforms.js.JSClient
|
import com.futo.platformplayer.api.media.platforms.js.JSClient
|
||||||
|
@ -26,6 +27,7 @@ interface IJSContent: IPlatformContent {
|
||||||
ContentType.NESTED_VIDEO -> JSNestedMediaContent(config, obj);
|
ContentType.NESTED_VIDEO -> JSNestedMediaContent(config, obj);
|
||||||
ContentType.PLAYLIST -> JSPlaylist(config, obj);
|
ContentType.PLAYLIST -> JSPlaylist(config, obj);
|
||||||
ContentType.LOCKED -> JSLockedContent(config, obj);
|
ContentType.LOCKED -> JSLockedContent(config, obj);
|
||||||
|
ContentType.CHANNEL -> JSChannelContent(config, obj)
|
||||||
else -> throw NotImplementedError("Unknown content type ${type}");
|
else -> throw NotImplementedError("Unknown content type ${type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import com.futo.platformplayer.api.media.models.PlatformAuthorLink
|
||||||
import com.futo.platformplayer.api.media.platforms.js.JSClient
|
import com.futo.platformplayer.api.media.platforms.js.JSClient
|
||||||
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
||||||
import com.futo.platformplayer.api.media.structures.IPager
|
import com.futo.platformplayer.api.media.structures.IPager
|
||||||
import com.futo.platformplayer.engine.V8Plugin
|
|
||||||
|
|
||||||
class JSChannelPager : JSPager<PlatformAuthorLink>, IPager<PlatformAuthorLink> {
|
class JSChannelPager : JSPager<PlatformAuthorLink>, IPager<PlatformAuthorLink> {
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,8 @@ open class JSContent : IPlatformContent, IPluginSourced {
|
||||||
else
|
else
|
||||||
author = PlatformAuthorLink.UNKNOWN;
|
author = PlatformAuthorLink.UNKNOWN;
|
||||||
|
|
||||||
val datetimeInt = _content.getOrThrow<Int>(config, "datetime", contextName).toLong();
|
val datetimeInt = _content.getOrDefault<Int>(config, "datetime", contextName, null)?.toLong();
|
||||||
if(datetimeInt == 0.toLong())
|
if(datetimeInt == null || datetimeInt == 0.toLong())
|
||||||
datetime = null;
|
datetime = null;
|
||||||
else
|
else
|
||||||
datetime = OffsetDateTime.of(LocalDateTime.ofEpochSecond(datetimeInt, 0, ZoneOffset.UTC), ZoneOffset.UTC);
|
datetime = OffsetDateTime.of(LocalDateTime.ofEpochSecond(datetimeInt, 0, ZoneOffset.UTC), ZoneOffset.UTC);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.futo.platformplayer.api.media.platforms.js.models
|
||||||
|
|
||||||
import com.caoccao.javet.values.reference.V8ValueObject
|
import com.caoccao.javet.values.reference.V8ValueObject
|
||||||
import com.futo.platformplayer.api.media.IPluginSourced
|
import com.futo.platformplayer.api.media.IPluginSourced
|
||||||
|
import com.futo.platformplayer.api.media.models.JSChannelContent
|
||||||
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
||||||
import com.futo.platformplayer.api.media.platforms.js.JSClient
|
import com.futo.platformplayer.api.media.platforms.js.JSClient
|
||||||
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
||||||
|
@ -15,4 +16,14 @@ class JSContentPager : JSPager<IPlatformContent>, IPluginSourced {
|
||||||
override fun convertResult(obj: V8ValueObject): IPlatformContent {
|
override fun convertResult(obj: V8ValueObject): IPlatformContent {
|
||||||
return IJSContent.fromV8(plugin, obj);
|
return IJSContent.fromV8(plugin, obj);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JSChannelContentPager : JSPager<IPlatformContent>, IPluginSourced {
|
||||||
|
override val sourceConfig: SourcePluginConfig get() = config;
|
||||||
|
|
||||||
|
constructor(config: SourcePluginConfig, plugin: JSClient, pager: V8ValueObject) : super(config, plugin, pager) {}
|
||||||
|
|
||||||
|
override fun convertResult(obj: V8ValueObject): IPlatformContent {
|
||||||
|
return JSChannelContent(config, obj);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -201,11 +201,12 @@ abstract class ContentFeedView<TFragment> : FeedView<TFragment, IPlatformContent
|
||||||
protected open fun onContentUrlClicked(url: String, contentType: ContentType) {
|
protected open fun onContentUrlClicked(url: String, contentType: ContentType) {
|
||||||
when(contentType) {
|
when(contentType) {
|
||||||
ContentType.MEDIA -> {
|
ContentType.MEDIA -> {
|
||||||
StatePlayer.instance.clearQueue();
|
StatePlayer.instance.clearQueue()
|
||||||
fragment.navigate<VideoDetailFragment>(url).maximizeVideoDetail();
|
fragment.navigate<VideoDetailFragment>(url).maximizeVideoDetail()
|
||||||
};
|
}
|
||||||
ContentType.PLAYLIST -> fragment.navigate<RemotePlaylistFragment>(url);
|
ContentType.PLAYLIST -> fragment.navigate<RemotePlaylistFragment>(url)
|
||||||
ContentType.URL -> fragment.navigate<BrowserFragment>(url);
|
ContentType.URL -> fragment.navigate<BrowserFragment>(url)
|
||||||
|
ContentType.CHANNEL -> fragment.navigate<ChannelFragment>(url)
|
||||||
else -> {};
|
else -> {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.futo.platformplayer.UIDialogs
|
||||||
import com.futo.platformplayer.UISlideOverlays
|
import com.futo.platformplayer.UISlideOverlays
|
||||||
import com.futo.platformplayer.activities.MainActivity
|
import com.futo.platformplayer.activities.MainActivity
|
||||||
import com.futo.platformplayer.api.media.models.ResultCapabilities
|
import com.futo.platformplayer.api.media.models.ResultCapabilities
|
||||||
|
import com.futo.platformplayer.api.media.models.contents.ContentType
|
||||||
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
||||||
import com.futo.platformplayer.api.media.structures.IPager
|
import com.futo.platformplayer.api.media.structures.IPager
|
||||||
import com.futo.platformplayer.constructs.TaskHandler
|
import com.futo.platformplayer.constructs.TaskHandler
|
||||||
|
@ -18,6 +19,7 @@ import com.futo.platformplayer.engine.exceptions.ScriptCaptchaRequiredException
|
||||||
import com.futo.platformplayer.fragment.mainactivity.topbar.SearchTopBarFragment
|
import com.futo.platformplayer.fragment.mainactivity.topbar.SearchTopBarFragment
|
||||||
import com.futo.platformplayer.isHttpUrl
|
import com.futo.platformplayer.isHttpUrl
|
||||||
import com.futo.platformplayer.logging.Logger
|
import com.futo.platformplayer.logging.Logger
|
||||||
|
import com.futo.platformplayer.models.SearchType
|
||||||
import com.futo.platformplayer.states.StateMeta
|
import com.futo.platformplayer.states.StateMeta
|
||||||
import com.futo.platformplayer.states.StatePlatform
|
import com.futo.platformplayer.states.StatePlatform
|
||||||
import com.futo.platformplayer.views.FeedStyle
|
import com.futo.platformplayer.views.FeedStyle
|
||||||
|
@ -84,6 +86,7 @@ class ContentSearchResultsFragment : MainFragment() {
|
||||||
private var _filterValues: HashMap<String, List<String>> = hashMapOf();
|
private var _filterValues: HashMap<String, List<String>> = hashMapOf();
|
||||||
private var _enabledClientIds: List<String>? = null;
|
private var _enabledClientIds: List<String>? = null;
|
||||||
private var _channelUrl: String? = null;
|
private var _channelUrl: String? = null;
|
||||||
|
private var _searchType: SearchType? = null;
|
||||||
|
|
||||||
private val _taskSearch: TaskHandler<String, IPager<IPlatformContent>>;
|
private val _taskSearch: TaskHandler<String, IPager<IPlatformContent>>;
|
||||||
override val shouldShowTimeBar: Boolean get() = Settings.instance.search.progressBar
|
override val shouldShowTimeBar: Boolean get() = Settings.instance.search.progressBar
|
||||||
|
@ -95,7 +98,13 @@ class ContentSearchResultsFragment : MainFragment() {
|
||||||
if (channelUrl != null) {
|
if (channelUrl != null) {
|
||||||
StatePlatform.instance.searchChannel(channelUrl, query, null, _sortBy, _filterValues, _enabledClientIds)
|
StatePlatform.instance.searchChannel(channelUrl, query, null, _sortBy, _filterValues, _enabledClientIds)
|
||||||
} else {
|
} else {
|
||||||
StatePlatform.instance.searchRefresh(fragment.lifecycleScope, query, null, _sortBy, _filterValues, _enabledClientIds)
|
when (_searchType)
|
||||||
|
{
|
||||||
|
SearchType.VIDEO -> StatePlatform.instance.searchRefresh(fragment.lifecycleScope, query, null, _sortBy, _filterValues, _enabledClientIds)
|
||||||
|
SearchType.CREATOR -> StatePlatform.instance.searchChannelsAsContent(query)
|
||||||
|
SearchType.PLAYLIST -> StatePlatform.instance.searchPlaylist(query)
|
||||||
|
else -> throw Exception("Search type must be specified")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.success { loadedResult(it); }.exception<ScriptCaptchaRequiredException> { }
|
.success { loadedResult(it); }.exception<ScriptCaptchaRequiredException> { }
|
||||||
|
@ -116,6 +125,7 @@ class ContentSearchResultsFragment : MainFragment() {
|
||||||
if(parameter is SuggestionsFragmentData) {
|
if(parameter is SuggestionsFragmentData) {
|
||||||
setQuery(parameter.query, false);
|
setQuery(parameter.query, false);
|
||||||
setChannelUrl(parameter.channelUrl, false);
|
setChannelUrl(parameter.channelUrl, false);
|
||||||
|
setSearchType(parameter.searchType, false)
|
||||||
|
|
||||||
fragment.topBar?.apply {
|
fragment.topBar?.apply {
|
||||||
if (this is SearchTopBarFragment) {
|
if (this is SearchTopBarFragment) {
|
||||||
|
@ -258,6 +268,15 @@ class ContentSearchResultsFragment : MainFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setSearchType(searchType: SearchType, updateResults: Boolean = true) {
|
||||||
|
_searchType = searchType
|
||||||
|
|
||||||
|
if (updateResults) {
|
||||||
|
clearResults();
|
||||||
|
loadResults();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setSortBy(sortBy: String?, updateResults: Boolean = true) {
|
private fun setSortBy(sortBy: String?, updateResults: Boolean = true) {
|
||||||
_sortBy = sortBy;
|
_sortBy = sortBy;
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,6 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
||||||
_toolbarContentView = findViewById(R.id.container_toolbar_content);
|
_toolbarContentView = findViewById(R.id.container_toolbar_content);
|
||||||
|
|
||||||
_nextPageHandler = TaskHandler<TPager, List<TResult>>({fragment.lifecycleScope}, {
|
_nextPageHandler = TaskHandler<TPager, List<TResult>>({fragment.lifecycleScope}, {
|
||||||
|
|
||||||
if (it is IAsyncPager<*>)
|
if (it is IAsyncPager<*>)
|
||||||
it.nextPageAsync();
|
it.nextPageAsync();
|
||||||
else
|
else
|
||||||
|
|
|
@ -49,14 +49,7 @@ class SuggestionsFragment : MainFragment {
|
||||||
_adapterSuggestions.onClicked.subscribe { suggestion ->
|
_adapterSuggestions.onClicked.subscribe { suggestion ->
|
||||||
val storage = FragmentedStorage.get<SearchHistoryStorage>();
|
val storage = FragmentedStorage.get<SearchHistoryStorage>();
|
||||||
storage.add(suggestion);
|
storage.add(suggestion);
|
||||||
|
navigate<ContentSearchResultsFragment>(SuggestionsFragmentData(suggestion, _searchType, _channelUrl));
|
||||||
if (_searchType == SearchType.CREATOR) {
|
|
||||||
navigate<CreatorSearchResultsFragment>(suggestion);
|
|
||||||
} else if (_searchType == SearchType.PLAYLIST) {
|
|
||||||
navigate<PlaylistSearchResultsFragment>(suggestion);
|
|
||||||
} else {
|
|
||||||
navigate<ContentSearchResultsFragment>(SuggestionsFragmentData(suggestion, SearchType.VIDEO, _channelUrl));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_adapterSuggestions.onRemove.subscribe { suggestion ->
|
_adapterSuggestions.onRemove.subscribe { suggestion ->
|
||||||
val index = _suggestions.indexOf(suggestion);
|
val index = _suggestions.indexOf(suggestion);
|
||||||
|
|
|
@ -632,6 +632,27 @@ class StatePlatform {
|
||||||
return pager;
|
return pager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun searchChannelsAsContent(query: String): IPager<IPlatformContent> {
|
||||||
|
Logger.i(TAG, "Platform - searchChannels");
|
||||||
|
val pagers = mutableMapOf<IPager<IPlatformContent>, Float>();
|
||||||
|
getSortedEnabledClient().parallelStream().forEach {
|
||||||
|
try {
|
||||||
|
if (it.capabilities.hasChannelSearch)
|
||||||
|
pagers.put(it.searchChannelsAsContent(query), 1f);
|
||||||
|
}
|
||||||
|
catch(ex: Throwable) {
|
||||||
|
Logger.e(TAG, "Failed search channels", ex)
|
||||||
|
UIDialogs.toast("Failed search channels on [${it.name}]\n(${ex.message})");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if(pagers.isEmpty())
|
||||||
|
return EmptyPager<IPlatformContent>();
|
||||||
|
|
||||||
|
val pager = MultiDistributionContentPager(pagers);
|
||||||
|
pager.initialize();
|
||||||
|
return pager;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Video
|
//Video
|
||||||
fun hasEnabledVideoClient(url: String) : Boolean = getEnabledClients().any { it.isContentDetailsUrl(url) };
|
fun hasEnabledVideoClient(url: String) : Boolean = getEnabledClients().any { it.isContentDetailsUrl(url) };
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package com.futo.platformplayer.views.adapters
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import com.futo.platformplayer.R
|
||||||
|
import com.futo.platformplayer.api.media.models.IPlatformChannelContent
|
||||||
|
import com.futo.platformplayer.api.media.models.PlatformAuthorLink
|
||||||
|
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
||||||
|
import com.futo.platformplayer.constructs.Event1
|
||||||
|
import com.futo.platformplayer.toHumanNumber
|
||||||
|
import com.futo.platformplayer.views.FeedStyle
|
||||||
|
import com.futo.platformplayer.views.others.CreatorThumbnail
|
||||||
|
import com.futo.platformplayer.views.platform.PlatformIndicator
|
||||||
|
import com.futo.platformplayer.views.subscriptions.SubscribeButton
|
||||||
|
|
||||||
|
|
||||||
|
open class ChannelView : LinearLayout {
|
||||||
|
protected val _feedStyle : FeedStyle;
|
||||||
|
protected val _tiny: Boolean
|
||||||
|
|
||||||
|
private val _textName: TextView;
|
||||||
|
private val _creatorThumbnail: CreatorThumbnail;
|
||||||
|
private val _textMetadata: TextView;
|
||||||
|
private val _buttonSubscribe: SubscribeButton;
|
||||||
|
private val _platformIndicator: PlatformIndicator;
|
||||||
|
|
||||||
|
val onClick = Event1<IPlatformChannelContent>();
|
||||||
|
|
||||||
|
var currentChannel: IPlatformChannelContent? = null
|
||||||
|
private set
|
||||||
|
|
||||||
|
val content: IPlatformContent? get() = currentChannel;
|
||||||
|
|
||||||
|
constructor(context: Context, feedStyle: FeedStyle, tiny: Boolean) : super(context) {
|
||||||
|
inflate(feedStyle);
|
||||||
|
_feedStyle = feedStyle;
|
||||||
|
_tiny = tiny
|
||||||
|
|
||||||
|
_textName = findViewById(R.id.text_channel_name);
|
||||||
|
_creatorThumbnail = findViewById(R.id.creator_thumbnail);
|
||||||
|
_textMetadata = findViewById(R.id.text_channel_metadata);
|
||||||
|
_buttonSubscribe = findViewById(R.id.button_subscribe);
|
||||||
|
_platformIndicator = findViewById(R.id.platform_indicator);
|
||||||
|
|
||||||
|
if (_tiny) {
|
||||||
|
_buttonSubscribe.visibility = View.GONE;
|
||||||
|
_textMetadata.visibility = View.GONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
findViewById<ConstraintLayout>(R.id.root).setOnClickListener {
|
||||||
|
val s = currentChannel ?: return@setOnClickListener;
|
||||||
|
onClick.emit(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun inflate(feedStyle: FeedStyle) {
|
||||||
|
inflate(context, when(feedStyle) {
|
||||||
|
FeedStyle.PREVIEW -> R.layout.list_creator
|
||||||
|
else -> R.layout.list_creator
|
||||||
|
}, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun bind(content: IPlatformContent) {
|
||||||
|
isClickable = true;
|
||||||
|
|
||||||
|
if(content !is IPlatformChannelContent)
|
||||||
|
return
|
||||||
|
|
||||||
|
_creatorThumbnail.setThumbnail(content.thumbnail, false);
|
||||||
|
_textName.text = content.name;
|
||||||
|
|
||||||
|
if(content.subscribers == null || (content.subscribers ?: 0) <= 0L)
|
||||||
|
_textMetadata.visibility = View.GONE;
|
||||||
|
else {
|
||||||
|
_textMetadata.text = if((content.subscribers ?: 0) > 0) content.subscribers!!.toHumanNumber() + " " + context.getString(R.string.subscribers) else "";
|
||||||
|
_textMetadata.visibility = View.VISIBLE;
|
||||||
|
}
|
||||||
|
_buttonSubscribe.setSubscribeChannel(content.url);
|
||||||
|
_platformIndicator.setPlatformFromClientID(content.id.pluginId);
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = "ChannelView"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.futo.platformplayer.views.adapters.feedtypes
|
||||||
|
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.futo.platformplayer.api.media.models.IPlatformChannelContent
|
||||||
|
import com.futo.platformplayer.api.media.models.PlatformAuthorLink
|
||||||
|
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
||||||
|
import com.futo.platformplayer.api.media.models.contents.IPlatformContentDetails
|
||||||
|
import com.futo.platformplayer.api.media.models.playlists.IPlatformPlaylist
|
||||||
|
import com.futo.platformplayer.constructs.Event1
|
||||||
|
import com.futo.platformplayer.fragment.mainactivity.main.CreatorFeedView
|
||||||
|
import com.futo.platformplayer.views.FeedStyle
|
||||||
|
import com.futo.platformplayer.views.adapters.ChannelView
|
||||||
|
import com.futo.platformplayer.views.adapters.ContentPreviewViewHolder
|
||||||
|
import com.futo.platformplayer.views.adapters.PlaylistView
|
||||||
|
|
||||||
|
|
||||||
|
class PreviewChannelViewHolder : ContentPreviewViewHolder {
|
||||||
|
val onClick = Event1<IPlatformChannelContent>();
|
||||||
|
|
||||||
|
val currentChannel: IPlatformChannelContent? get() = view.currentChannel;
|
||||||
|
|
||||||
|
override val content: IPlatformContent? get() = currentChannel;
|
||||||
|
|
||||||
|
private val view: ChannelView get() = itemView as ChannelView;
|
||||||
|
|
||||||
|
constructor(viewGroup: ViewGroup, feedStyle: FeedStyle, tiny: Boolean): super(ChannelView(viewGroup.context, feedStyle, tiny)) {
|
||||||
|
view.onClick.subscribe(onClick::emit);
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bind(content: IPlatformContent) = view.bind(content);
|
||||||
|
|
||||||
|
override fun preview(details: IPlatformContentDetails?, paused: Boolean) = Unit;
|
||||||
|
override fun stopPreview() = Unit;
|
||||||
|
override fun pausePreview() = Unit;
|
||||||
|
override fun resumePreview() = Unit;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = "PreviewChannelViewHolder"
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import com.futo.platformplayer.views.FeedStyle
|
||||||
import com.futo.platformplayer.views.adapters.ContentPreviewViewHolder
|
import com.futo.platformplayer.views.adapters.ContentPreviewViewHolder
|
||||||
import com.futo.platformplayer.views.adapters.EmptyPreviewViewHolder
|
import com.futo.platformplayer.views.adapters.EmptyPreviewViewHolder
|
||||||
import com.futo.platformplayer.views.adapters.InsertedViewAdapterWithLoader
|
import com.futo.platformplayer.views.adapters.InsertedViewAdapterWithLoader
|
||||||
|
import okhttp3.internal.platform.Platform
|
||||||
|
|
||||||
class PreviewContentListAdapter : InsertedViewAdapterWithLoader<ContentPreviewViewHolder> {
|
class PreviewContentListAdapter : InsertedViewAdapterWithLoader<ContentPreviewViewHolder> {
|
||||||
private var _initialPlay = true;
|
private var _initialPlay = true;
|
||||||
|
@ -82,6 +83,7 @@ class PreviewContentListAdapter : InsertedViewAdapterWithLoader<ContentPreviewVi
|
||||||
ContentType.PLAYLIST -> createPlaylistViewHolder(viewGroup);
|
ContentType.PLAYLIST -> createPlaylistViewHolder(viewGroup);
|
||||||
ContentType.NESTED_VIDEO -> createNestedViewHolder(viewGroup);
|
ContentType.NESTED_VIDEO -> createNestedViewHolder(viewGroup);
|
||||||
ContentType.LOCKED -> createLockedViewHolder(viewGroup);
|
ContentType.LOCKED -> createLockedViewHolder(viewGroup);
|
||||||
|
ContentType.CHANNEL -> createChannelViewHolder(viewGroup)
|
||||||
else -> EmptyPreviewViewHolder(viewGroup)
|
else -> EmptyPreviewViewHolder(viewGroup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,6 +117,10 @@ class PreviewContentListAdapter : InsertedViewAdapterWithLoader<ContentPreviewVi
|
||||||
this.onPlaylistClicked.subscribe { this@PreviewContentListAdapter.onContentClicked.emit(it, 0L) };
|
this.onPlaylistClicked.subscribe { this@PreviewContentListAdapter.onContentClicked.emit(it, 0L) };
|
||||||
this.onChannelClicked.subscribe(this@PreviewContentListAdapter.onChannelClicked::emit);
|
this.onChannelClicked.subscribe(this@PreviewContentListAdapter.onChannelClicked::emit);
|
||||||
};
|
};
|
||||||
|
private fun createChannelViewHolder(viewGroup: ViewGroup): PreviewChannelViewHolder = PreviewChannelViewHolder(viewGroup, _feedStyle, false).apply {
|
||||||
|
//TODO: Maybe PlatformAuthorLink as is needs to be phased out?
|
||||||
|
this.onClick.subscribe { this@PreviewContentListAdapter.onChannelClicked.emit(PlatformAuthorLink(it.id, it.name, it.url, it.thumbnail, it.subscribers)) };
|
||||||
|
};
|
||||||
|
|
||||||
override fun bindChild(holder: ContentPreviewViewHolder, pos: Int) {
|
override fun bindChild(holder: ContentPreviewViewHolder, pos: Int) {
|
||||||
val value = _dataSet[pos];
|
val value = _dataSet[pos];
|
||||||
|
|
Loading…
Add table
Reference in a new issue