diff --git a/app/src/main/java/com/futo/platformplayer/Extensions_Polycentric.kt b/app/src/main/java/com/futo/platformplayer/Extensions_Polycentric.kt index 6d6c076e..77a73917 100644 --- a/app/src/main/java/com/futo/platformplayer/Extensions_Polycentric.kt +++ b/app/src/main/java/com/futo/platformplayer/Extensions_Polycentric.kt @@ -35,4 +35,8 @@ fun Protocol.ImageBundle?.selectHighestResolutionImage(): Protocol.ImageManifest fun Protocol.Claim.resolveChannelUrl(): String? { return StatePlatform.instance.resolveChannelUrlByClaimTemplates(this.claimType.toInt(), this.claimFieldsList.associate { Pair(it.key.toInt(), it.value) }) +} + +fun Protocol.Claim.resolveChannelUrls(): List { + return StatePlatform.instance.resolveChannelUrlsByClaimTemplates(this.claimType.toInt(), this.claimFieldsList.associate { Pair(it.key.toInt(), it.value) }) } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt index 7d774802..0103eb68 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt @@ -568,6 +568,23 @@ open class JSClient : IPlatformClient { }; } + fun resolveChannelUrlsByClaimTemplates(claimType: Int, values: Map): List { + val urls = arrayListOf(); + channelClaimTemplates?.let { + if(it.containsKey(claimType)) { + val templates = it[claimType]; + if(templates != null) + for(value in values.keys.sortedBy { it }) { + if(templates.containsKey(value)) { + urls.add(templates[value]!!.replace("{{CLAIMVALUE}}", values[value]!!)); + } + } + } + }; + + return urls; + } + private fun isBusyWith(handle: ()->T): T { try { 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 c17a0af0..16af0595 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 @@ -246,28 +246,45 @@ class ChannelFragment : MainFragment() { if (parameter is String) { _buttonSubscribe.setSubscribeChannel(parameter); - _textChannel.text = ""; - _textChannelSub.text = ""; + setPolycentricProfileOr(parameter) { + _textChannel.text = ""; + _textChannelSub.text = ""; + _creatorThumbnail.setThumbnail(null, true); + Glide.with(_imageBanner) + .clear(_imageBanner); + }; _url = parameter; loadChannel(); } else if (parameter is SerializedChannel) { showChannel(parameter); _url = parameter.url; - _creatorThumbnail.setThumbnail(parameter.url, false); loadChannel(); } else if (parameter is IPlatformChannel) showChannel(parameter); else if (parameter is PlatformAuthorLink) { - _textChannel.text = parameter.name; - _textChannelSub.text = ""; - _creatorThumbnail.setThumbnail(parameter.url, false); + setPolycentricProfileOr(parameter.url) { + _textChannel.text = parameter.name; + _textChannelSub.text = ""; + _creatorThumbnail.setThumbnail(parameter.thumbnail, true); + Glide.with(_imageBanner) + .clear(_imageBanner); + + _taskLoadPolycentricProfile.run(parameter.id); + }; + _url = parameter.url; loadChannel(); } else if (parameter is Subscription) { - _textChannel.text = parameter.channel.name; - _textChannelSub.text = ""; - _creatorThumbnail.setThumbnail(parameter.channel.thumbnail, false); + setPolycentricProfileOr(parameter.channel.url) { + _textChannel.text = parameter.channel.name; + _textChannelSub.text = ""; + _creatorThumbnail.setThumbnail(parameter.channel.thumbnail, true); + Glide.with(_imageBanner) + .clear(_imageBanner); + + _taskLoadPolycentricProfile.run(parameter.channel.id); + }; _url = parameter.channel.url; loadChannel(); @@ -360,15 +377,8 @@ class ChannelFragment : MainFragment() { _fragment.topBar?.assume()?.setMenuItems(buttons); _buttonSubscribe.setSubscribeChannel(channel); - _textChannel.text = channel.name; _textChannelSub.text = if(channel.subscribers > 0) "${channel.subscribers.toHumanNumber()} subscribers" else ""; - _creatorThumbnail.setThumbnail(channel.thumbnail, true); - Glide.with(_imageBanner) - .load(channel.banner) - .crossfade() - .into(_imageBanner) - //TODO: Find a better way to access the adapter fragments.. (_viewPager.adapter as ChannelViewPagerAdapter?)?.let { @@ -381,51 +391,68 @@ class ChannelFragment : MainFragment() { this.channel = channel; - val cachedProfile = PolycentricCache.instance.getCachedProfile(channel.url); + setPolycentricProfileOr(channel.url) { + _textChannel.text = channel.name; + _creatorThumbnail.setThumbnail(channel.thumbnail, true); + Glide.with(_imageBanner) + .load(channel.banner) + .crossfade() + .into(_imageBanner); + + _taskLoadPolycentricProfile.run(channel.id); + }; + } + + private fun setPolycentricProfileOr(url: String, or: () -> Unit) { + val cachedProfile = channel?.let { PolycentricCache.instance.getCachedProfile(it.url) }; if (cachedProfile != null) { setPolycentricProfile(cachedProfile, animate = false); } else { setPolycentricProfile(null, animate = false); - _taskLoadPolycentricProfile.run(channel.id); + or(); } } private fun setPolycentricProfile(cachedPolycentricProfile: PolycentricCache.CachedPolycentricProfile?, animate: Boolean) { Log.i(TAG, "setPolycentricProfile(cachedPolycentricProfile = $cachedPolycentricProfile, animate = $animate)") - val polycentricProfile = cachedPolycentricProfile?.profile; - if (polycentricProfile != null) { - _fragment.topBar?.onShown(polycentricProfile); + val dp_35 = 35.dp(resources) + val profile = cachedPolycentricProfile?.profile; + val avatar = profile?.systemState?.avatar?.selectBestImage(dp_35 * dp_35) + ?.let { it.toURLInfoSystemLinkUrl(profile.system.toProto(), it.process, profile.systemState.servers.toList()) }; - if (polycentricProfile.systemState.username.isNotBlank()) - _textChannel.text = polycentricProfile.systemState.username; + if (avatar != null) { + _creatorThumbnail.setThumbnail(avatar, animate); + } else { + _creatorThumbnail.setThumbnail(channel?.thumbnail, animate); + _creatorThumbnail.setHarborAvailable(profile != null, animate); + } - val dp_35 = 35.dp(resources) - val avatar = polycentricProfile.systemState.avatar?.selectBestImage(dp_35 * dp_35) - ?.let { it.toURLInfoSystemLinkUrl(polycentricProfile.system.toProto(), it.process, polycentricProfile.systemState.servers.toList()) }; + val banner = profile?.systemState?.banner?.selectHighestResolutionImage() + ?.let { it.toURLInfoSystemLinkUrl(profile.system.toProto(), it.process, profile.systemState.servers.toList()) }; - if (avatar != null) { - _creatorThumbnail.setThumbnail(avatar, true); - } else { - _creatorThumbnail.setHarborAvailable(true, true); - } + if (banner != null) { + Glide.with(_imageBanner) + .load(banner) + .crossfade() + .into(_imageBanner); + } else { + Glide.with(_imageBanner) + .load(channel?.banner) + .crossfade() + .into(_imageBanner); + } - val banner = polycentricProfile.systemState.banner?.selectHighestResolutionImage() - ?.let { it.toURLInfoSystemLinkUrl(polycentricProfile.system.toProto(), it.process, polycentricProfile.systemState.servers.toList()) }; - - if (banner != null) { - Glide.with(_imageBanner) - .load(banner) - .crossfade() - .into(_imageBanner); - } + if (profile != null) { + _fragment.topBar?.onShown(profile); + _textChannel.text = profile.systemState.username; } (_viewPager.adapter as ChannelViewPagerAdapter?)?.let { - it.getFragment().setPolycentricProfile(polycentricProfile, animate); - it.getFragment().setPolycentricProfile(polycentricProfile, animate); - it.getFragment().setPolycentricProfile(polycentricProfile, animate); - it.getFragment().setPolycentricProfile(polycentricProfile, animate); + it.getFragment().setPolycentricProfile(profile, animate); + it.getFragment().setPolycentricProfile(profile, animate); + it.getFragment().setPolycentricProfile(profile, animate); + it.getFragment().setPolycentricProfile(profile, animate); //TODO: Call on other tabs as needed } } 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 8603d76f..0ac5577f 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 @@ -101,14 +101,12 @@ class ContentSearchResultsFragment : MainFragment() { fun onShown(parameter: Any?, isBack: Boolean) { if(parameter is SuggestionsFragmentData) { - if(!isBack) { - setQuery(parameter.query, false); - setChannelUrl(parameter.channelUrl, false); + setQuery(parameter.query, false); + setChannelUrl(parameter.channelUrl, false); - fragment.topBar?.apply { - if (this is SearchTopBarFragment) { - this.setText(parameter.query); - } + fragment.topBar?.apply { + if (this is SearchTopBarFragment) { + this.setText(parameter.query); } } } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CreatorSearchResultsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CreatorSearchResultsFragment.kt index 03398a57..a685e73e 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CreatorSearchResultsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CreatorSearchResultsFragment.kt @@ -71,16 +71,14 @@ class CreatorSearchResultsFragment : MainFragment() { fun onShown(parameter: Any?, isBack: Boolean) { if(parameter is String) { - if(!isBack) { - setQuery(parameter); + setQuery(parameter); - fragment.topBar?.apply { - if (this is SearchTopBarFragment) { - setText(parameter); - onSearch.subscribe(this) { - setQuery(it); - }; - } + fragment.topBar?.apply { + if (this is SearchTopBarFragment) { + setText(parameter); + onSearch.subscribe(this) { + setQuery(it); + }; } } } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistSearchResultsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistSearchResultsFragment.kt index 58020c07..03536707 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistSearchResultsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistSearchResultsFragment.kt @@ -73,16 +73,14 @@ class PlaylistSearchResultsFragment : MainFragment() { fun onShown(parameter: Any?, isBack: Boolean) { if(parameter is String) { - if(!isBack) { - setQuery(parameter); + setQuery(parameter); - fragment.topBar?.apply { - if (this is SearchTopBarFragment) { - setText(parameter); - onSearch.subscribe(this) { - setQuery(it); - }; - } + fragment.topBar?.apply { + if (this is SearchTopBarFragment) { + setText(parameter); + onSearch.subscribe(this) { + setQuery(it); + }; } } } 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 11869f35..b92b3e5d 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 @@ -870,7 +870,6 @@ class VideoDetailView : ConstraintLayout { _commentsList.clear(); _platform.setPlatformFromClientID(video.id.pluginId); _subTitle.text = subTitleSegments.joinToString(" • "); - _channelName.text = video.author.name; _playWhenReady = true; if(video.author.subscribers != null) { _channelMeta.text = if((video.author.subscribers ?: 0) > 0) video.author.subscribers!!.toHumanNumber() + " subscribers" else ""; @@ -897,6 +896,7 @@ class VideoDetailView : ConstraintLayout { } else { setPolycentricProfile(null, animate = false); _taskLoadPolycentricProfile.run(video.author.id); + _channelName.text = video.author.name; } _player.clear(); @@ -1971,14 +1971,24 @@ class VideoDetailView : ConstraintLayout { private fun setPolycentricProfile(cachedPolycentricProfile: PolycentricCache.CachedPolycentricProfile?, animate: Boolean) { _polycentricProfile = cachedPolycentricProfile; - if (cachedPolycentricProfile?.profile == null) { - _layoutMonetization.visibility = View.GONE; - _creatorThumbnail.setHarborAvailable(false, animate); - return; + val dp_35 = 35.dp(context.resources) + val profile = cachedPolycentricProfile?.profile; + val avatar = profile?.systemState?.avatar?.selectBestImage(dp_35 * dp_35) + ?.let { it.toURLInfoSystemLinkUrl(profile.system.toProto(), it.process, profile.systemState.servers.toList()) }; + + if (avatar != null) { + _creatorThumbnail.setThumbnail(avatar, animate); + } else { + _creatorThumbnail.setThumbnail(video?.author?.thumbnail, animate); + _creatorThumbnail.setHarborAvailable(profile != null, animate); } - _layoutMonetization.visibility = View.VISIBLE; - _creatorThumbnail.setHarborAvailable(true, animate); + if (profile != null) { + _channelName.text = cachedPolycentricProfile.profile.systemState.username; + _layoutMonetization.visibility = View.VISIBLE; + } else { + _layoutMonetization.visibility = View.GONE; + } } fun setProgressBarOverlayed(isOverlayed: Boolean?) { diff --git a/app/src/main/java/com/futo/platformplayer/polycentric/PolycentricCache.kt b/app/src/main/java/com/futo/platformplayer/polycentric/PolycentricCache.kt index 5854249e..6e29cb3e 100644 --- a/app/src/main/java/com/futo/platformplayer/polycentric/PolycentricCache.kt +++ b/app/src/main/java/com/futo/platformplayer/polycentric/PolycentricCache.kt @@ -8,6 +8,7 @@ import com.futo.platformplayer.fragment.mainactivity.main.PolycentricProfile import com.futo.platformplayer.getNowDiffSeconds import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.resolveChannelUrl +import com.futo.platformplayer.resolveChannelUrls import com.futo.platformplayer.serializers.OffsetDateTimeSerializer import com.futo.platformplayer.stores.CachedPolycentricProfileStorage import com.futo.platformplayer.stores.FragmentedStorage @@ -37,7 +38,8 @@ class PolycentricCache { ContentType.AVATAR.value, ContentType.USERNAME.value, ContentType.DESCRIPTION.value, - ContentType.STORE.value + ContentType.STORE.value, + ContentType.SERVER.value ) ).eventsList.map { e -> SignedEvent.fromProto(e) }; @@ -88,8 +90,9 @@ class PolycentricCache { if (result.profile != null) { for (claim in result.profile.ownedClaims) { - val url = claim.claim.resolveChannelUrl() ?: continue; - _profileUrlCache.map[url] = result; + val urls = claim.claim.resolveChannelUrls(); + for (url in urls) + _profileUrlCache.map[url] = result; } } diff --git a/app/src/main/java/com/futo/platformplayer/states/StatePlatform.kt b/app/src/main/java/com/futo/platformplayer/states/StatePlatform.kt index 68ec3cd4..1f1b38c3 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StatePlatform.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StatePlatform.kt @@ -784,6 +784,15 @@ class StatePlatform { return null; } + fun resolveChannelUrlsByClaimTemplates(claimType: Int, claimValues: Map): List { + val urls = arrayListOf(); + for(client in getClientsByClaimType(claimType).filter { it is JSClient }) { + val res = (client as JSClient).resolveChannelUrlsByClaimTemplates(claimType, claimValues); + urls.addAll(res); + } + return urls; + } + fun getPlaylistClientOrNull(url: String): IPlatformClient? = getEnabledClients().find { it.isPlaylistUrl(url) } fun getPlaylistClient(url: String): IPlatformClient = getEnabledClients().find { it.isPlaylistUrl(url) } ?: throw NoPlatformClientException("No client enabled that supports this playlist url (${url})"); diff --git a/app/src/main/java/com/futo/platformplayer/views/adapters/CommentViewHolder.kt b/app/src/main/java/com/futo/platformplayer/views/adapters/CommentViewHolder.kt index 5860d474..e7443e4c 100644 --- a/app/src/main/java/com/futo/platformplayer/views/adapters/CommentViewHolder.kt +++ b/app/src/main/java/com/futo/platformplayer/views/adapters/CommentViewHolder.kt @@ -93,6 +93,7 @@ class CommentViewHolder : ViewHolder { fun bind(comment: IPlatformComment, readonly: Boolean) { _creatorThumbnail.setThumbnail(comment.author.thumbnail, false); + _creatorThumbnail.setHarborAvailable(comment is PolycentricPlatformComment,false); _textAuthor.text = comment.author.name; val date = comment.date; diff --git a/app/src/main/java/com/futo/platformplayer/views/adapters/PreviewVideoView.kt b/app/src/main/java/com/futo/platformplayer/views/adapters/PreviewVideoView.kt index ebd9e05b..22e66dae 100644 --- a/app/src/main/java/com/futo/platformplayer/views/adapters/PreviewVideoView.kt +++ b/app/src/main/java/com/futo/platformplayer/views/adapters/PreviewVideoView.kt @@ -32,6 +32,7 @@ import com.futo.platformplayer.views.others.CreatorThumbnail import com.futo.platformplayer.views.FeedStyle import com.futo.platformplayer.views.platform.PlatformIndicator import com.futo.platformplayer.views.video.FutoThumbnailPlayer +import com.futo.polycentric.core.toURLInfoSystemLinkUrl open class PreviewVideoView : LinearLayout { @@ -58,11 +59,12 @@ open class PreviewVideoView : LinearLayout { protected val _exoPlayer: PlayerManager?; - private val _taskLoadValidClaims = TaskHandler(StateApp.instance.scopeGetter, - { PolycentricCache.instance.getValidClaimsAsync(it).await() }) - .success { it -> updateClaimsLayout(it, animate = true) } + private val _taskLoadProfile = TaskHandler( + StateApp.instance.scopeGetter, + { PolycentricCache.instance.getProfileAsync(it) }) + .success { it -> onProfileLoaded(it, true) } .exception { - Logger.w(TAG, "Failed to load claims.", it); + Logger.w(TAG, "Failed to load profile.", it); }; val onVideoClicked = Event2(); @@ -145,15 +147,7 @@ open class PreviewVideoView : LinearLayout { open fun bind(content: IPlatformContent) { - _taskLoadValidClaims.cancel(); - - val cachedClaims = PolycentricCache.instance.getCachedValidClaims(content.author.id); - if (cachedClaims != null) { - updateClaimsLayout(cachedClaims, animate = false); - } else { - updateClaimsLayout(null, animate = false); - _taskLoadValidClaims.run(content.author.id); - } + _taskLoadProfile.cancel(); isClickable = true; @@ -161,16 +155,25 @@ open class PreviewVideoView : LinearLayout { stopPreview(); - if(_imageChannel != null) - Glide.with(_imageChannel) - .load(content.author.thumbnail) - .placeholder(R.drawable.placeholder_channel_thumbnail) - .into(_imageChannel); + val cachedProfile = PolycentricCache.instance.getCachedProfile(content.author.url, true); + if (cachedProfile != null) { + onProfileLoaded(cachedProfile, false); + } else { + _imageNeopassChannel?.visibility = View.GONE; + _creatorThumbnail?.setThumbnail(content.author.thumbnail, false); + _imageChannel?.let { + Glide.with(_imageChannel) + .load(content.author.thumbnail) + .placeholder(R.drawable.placeholder_channel_thumbnail) + .into(_imageChannel); + } + _taskLoadProfile.run(content.author.id); + _textChannelName.text = content.author.name + } _imageChannel?.clipToOutline = true; _textVideoName.text = content.name; - _textChannelName.text = content.author.name _layoutDownloaded.visibility = if (StateDownloads.instance.isDownloaded(content.id)) VISIBLE else GONE; _platformIndicator.setPlatformFromClientID(content.id.pluginId); @@ -296,22 +299,50 @@ open class PreviewVideoView : LinearLayout { _playerVideoThumbnail?.setMuteChangedListener(callback); } - private fun updateClaimsLayout(claims: PolycentricCache.CachedOwnedClaims?, animate: Boolean) { + private fun onProfileLoaded(cachedPolycentricProfile: PolycentricCache.CachedPolycentricProfile?, animate: Boolean) { _neopassAnimator?.cancel(); _neopassAnimator = null; - val harborAvailable = claims != null && !claims.ownedClaims.isNullOrEmpty(); - if (harborAvailable) { - _imageNeopassChannel?.visibility = View.VISIBLE - if (animate) { - _neopassAnimator = ObjectAnimator.ofFloat(_imageNeopassChannel, "alpha", 0.0f, 1.0f).setDuration(500) - _neopassAnimator?.start() + val profile = cachedPolycentricProfile?.profile; + if (_creatorThumbnail != null) { + val dp_32 = 32.dp(context.resources); + val avatar = profile?.systemState?.avatar?.selectBestImage(dp_32 * dp_32) + ?.let { it.toURLInfoSystemLinkUrl(profile.system.toProto(), it.process, profile.systemState.servers.toList()) }; + + if (avatar != null) { + _creatorThumbnail.setThumbnail(avatar, animate); + } else { + _creatorThumbnail.setThumbnail(content?.author?.thumbnail, animate); + _creatorThumbnail.setHarborAvailable(profile != null, animate); + } + } else if (_imageChannel != null) { + val dp_28 = 28.dp(context.resources); + val avatar = profile?.systemState?.avatar?.selectBestImage(dp_28 * dp_28) + ?.let { it.toURLInfoSystemLinkUrl(profile.system.toProto(), it.process, profile.systemState.servers.toList()) }; + + if (avatar != null) { + _imageChannel.let { + Glide.with(_imageChannel) + .load(avatar) + .placeholder(R.drawable.placeholder_channel_thumbnail) + .into(_imageChannel); + } + + _imageNeopassChannel?.visibility = View.VISIBLE + if (animate) { + _neopassAnimator = ObjectAnimator.ofFloat(_imageNeopassChannel, "alpha", 0.0f, 1.0f).setDuration(500) + _neopassAnimator?.start() + } else { + _imageNeopassChannel?.alpha = 1.0f; + } + } else { + _imageNeopassChannel?.visibility = View.GONE } - } else { - _imageNeopassChannel?.visibility = View.GONE } - _creatorThumbnail?.setHarborAvailable(harborAvailable, animate) + if (profile != null) { + _textChannelName.text = profile.systemState.username + } } companion object { diff --git a/app/src/main/java/com/futo/platformplayer/views/adapters/SubscriptionViewHolder.kt b/app/src/main/java/com/futo/platformplayer/views/adapters/SubscriptionViewHolder.kt index 0cf36cfa..85ad79b3 100644 --- a/app/src/main/java/com/futo/platformplayer/views/adapters/SubscriptionViewHolder.kt +++ b/app/src/main/java/com/futo/platformplayer/views/adapters/SubscriptionViewHolder.kt @@ -72,22 +72,27 @@ class SubscriptionViewHolder : ViewHolder { } else { _creatorThumbnail.setThumbnail(sub.channel.thumbnail, false); _taskLoadProfile.run(sub.channel.id); + _textName.text = sub.channel.name; } - _textName.text = sub.channel.name; _platformIndicator.setPlatformFromClientID(sub.channel.id.pluginId); } private fun onProfileLoaded(cachedPolycentricProfile: PolycentricCache.CachedPolycentricProfile?, animate: Boolean) { val dp_46 = 46.dp(itemView.context.resources); - val avatar = cachedPolycentricProfile?.profile?.systemState?.avatar?.selectBestImage(dp_46 * dp_46) - ?.let { it.toURLInfoSystemLinkUrl(cachedPolycentricProfile.profile.system.toProto(), it.process, cachedPolycentricProfile.profile.systemState.servers.toList()) }; + val profile = cachedPolycentricProfile?.profile; + val avatar = profile?.systemState?.avatar?.selectBestImage(dp_46 * dp_46) + ?.let { it.toURLInfoSystemLinkUrl(profile.system.toProto(), it.process, profile.systemState.servers.toList()) }; if (avatar != null) { _creatorThumbnail.setThumbnail(avatar, animate); } else { _creatorThumbnail.setThumbnail(this.subscription?.channel?.thumbnail, animate); - _creatorThumbnail.setHarborAvailable(cachedPolycentricProfile?.profile != null, animate); + _creatorThumbnail.setHarborAvailable(profile != null, animate); + } + + if (profile != null) { + _textName.text = profile.systemState.username; } } diff --git a/app/src/main/java/com/futo/platformplayer/views/adapters/viewholders/CreatorViewHolder.kt b/app/src/main/java/com/futo/platformplayer/views/adapters/viewholders/CreatorViewHolder.kt index 5ec43e03..9f75d99b 100644 --- a/app/src/main/java/com/futo/platformplayer/views/adapters/viewholders/CreatorViewHolder.kt +++ b/app/src/main/java/com/futo/platformplayer/views/adapters/viewholders/CreatorViewHolder.kt @@ -6,13 +6,23 @@ import android.view.ViewGroup import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import com.futo.platformplayer.R +import com.futo.platformplayer.api.media.PlatformID import com.futo.platformplayer.api.media.models.PlatformAuthorLink import com.futo.platformplayer.constructs.Event1 +import com.futo.platformplayer.constructs.TaskHandler +import com.futo.platformplayer.dp +import com.futo.platformplayer.logging.Logger +import com.futo.platformplayer.polycentric.PolycentricCache +import com.futo.platformplayer.selectBestImage +import com.futo.platformplayer.states.StateApp +import com.futo.platformplayer.states.StatePolycentric import com.futo.platformplayer.toHumanNumber import com.futo.platformplayer.views.adapters.AnyAdapter +import com.futo.platformplayer.views.adapters.SubscriptionViewHolder import com.futo.platformplayer.views.others.CreatorThumbnail import com.futo.platformplayer.views.platform.PlatformIndicator import com.futo.platformplayer.views.subscriptions.SubscribeButton +import com.futo.polycentric.core.toURLInfoSystemLinkUrl class CreatorViewHolder(private val _viewGroup: ViewGroup, private val _tiny: Boolean) : AnyAdapter.AnyViewHolder( LayoutInflater.from(_viewGroup.context).inflate(R.layout.list_creator, _viewGroup, false)) { @@ -25,7 +35,15 @@ class CreatorViewHolder(private val _viewGroup: ViewGroup, private val _tiny: Bo private var _authorLink: PlatformAuthorLink? = null; val onClick = Event1(); - + + private val _taskLoadProfile = TaskHandler( + StateApp.instance.scopeGetter, + { PolycentricCache.instance.getProfileAsync(it) }) + .success { it -> onProfileLoaded(it, true) } + .exception { + Logger.w(TAG, "Failed to load profile.", it); + }; + init { _textName = _view.findViewById(R.id.text_channel_name); _creatorThumbnail = _view.findViewById(R.id.creator_thumbnail); @@ -45,12 +63,21 @@ class CreatorViewHolder(private val _viewGroup: ViewGroup, private val _tiny: Bo } override fun bind(authorLink: PlatformAuthorLink) { - _textName.text = authorLink.name; - _creatorThumbnail.setThumbnail(authorLink.thumbnail, false); + _taskLoadProfile.cancel(); + + val cachedProfile = PolycentricCache.instance.getCachedProfile(authorLink.url, true); + if (cachedProfile != null) { + onProfileLoaded(cachedProfile, false); + } else { + _creatorThumbnail.setThumbnail(authorLink.thumbnail, false); + _taskLoadProfile.run(authorLink.id); + _textName.text = authorLink.name; + } + if(authorLink.subscribers == null || (authorLink.subscribers ?: 0) <= 0L) _textMetadata.visibility = View.GONE; else { - _textMetadata.text = if(authorLink?.subscribers ?: 0 > 0) authorLink.subscribers!!.toHumanNumber() + " subscribers" else ""; + _textMetadata.text = if((authorLink.subscribers ?: 0) > 0) authorLink.subscribers!!.toHumanNumber() + " subscribers" else ""; _textMetadata.visibility = View.VISIBLE; } _buttonSubscribe.setSubscribeChannel(authorLink.url); @@ -58,6 +85,25 @@ class CreatorViewHolder(private val _viewGroup: ViewGroup, private val _tiny: Bo _authorLink = authorLink; } + private fun onProfileLoaded(cachedPolycentricProfile: PolycentricCache.CachedPolycentricProfile?, animate: Boolean) { + val dp_61 = 61.dp(itemView.context.resources); + + val profile = cachedPolycentricProfile?.profile; + val avatar = profile?.systemState?.avatar?.selectBestImage(dp_61 * dp_61) + ?.let { it.toURLInfoSystemLinkUrl(profile.system.toProto(), it.process, profile.systemState.servers.toList()) }; + + if (avatar != null) { + _creatorThumbnail.setThumbnail(avatar, animate); + } else { + _creatorThumbnail.setThumbnail(_authorLink?.thumbnail, animate); + _creatorThumbnail.setHarborAvailable(profile != null, animate); + } + + if (profile != null) { + _textName.text = profile.systemState.username; + } + } + companion object { private const val TAG = "CreatorViewHolder"; } diff --git a/app/src/main/java/com/futo/platformplayer/views/adapters/viewholders/SubscriptionBarViewHolder.kt b/app/src/main/java/com/futo/platformplayer/views/adapters/viewholders/SubscriptionBarViewHolder.kt index 9e17d945..1b2d9c37 100644 --- a/app/src/main/java/com/futo/platformplayer/views/adapters/viewholders/SubscriptionBarViewHolder.kt +++ b/app/src/main/java/com/futo/platformplayer/views/adapters/viewholders/SubscriptionBarViewHolder.kt @@ -57,22 +57,27 @@ class SubscriptionBarViewHolder(private val _viewGroup: ViewGroup) : AnyAdapter. } else { _creatorThumbnail.setThumbnail(subscription.channel.thumbnail, false); _taskLoadProfile.run(subscription.channel.id); + _name.text = subscription.channel.name; } - _name.text = subscription.channel.name; _subscription = subscription; } private fun onProfileLoaded(cachedPolycentricProfile: PolycentricCache.CachedPolycentricProfile?, animate: Boolean) { val dp_55 = 55.dp(itemView.context.resources) - val avatar = cachedPolycentricProfile?.profile?.systemState?.avatar?.selectBestImage(dp_55 * dp_55) - ?.let { it.toURLInfoSystemLinkUrl(cachedPolycentricProfile.profile.system.toProto(), it.process, cachedPolycentricProfile.profile.systemState.servers.toList()) }; + val profile = cachedPolycentricProfile?.profile; + val avatar = profile?.systemState?.avatar?.selectBestImage(dp_55 * dp_55) + ?.let { it.toURLInfoSystemLinkUrl(profile.system.toProto(), it.process, profile.systemState.servers.toList()) }; if (avatar != null) { _creatorThumbnail.setThumbnail(avatar, animate); } else { _creatorThumbnail.setThumbnail(_channel?.thumbnail, animate); - _creatorThumbnail.setHarborAvailable(cachedPolycentricProfile?.profile != null, animate); + _creatorThumbnail.setHarborAvailable(profile != null, animate); + } + + if (profile != null) { + _name.text = profile.systemState.username; } }