WIP article

This commit is contained in:
Kelvin 2025-05-29 13:05:00 +02:00
commit 9635c95efe
7 changed files with 123 additions and 79 deletions

View file

@ -291,15 +291,23 @@ class PlatformPostDetails extends PlatformPost {
} }
} }
class PlatformArticleDetails extends PlatformContent { class PlatformArticle extends PlatformContent {
constructor(obj) {
super(obj, 3);
obj = obj ?? {};
this.plugin_type = "PlatformArticle";
this.rating = obj.rating ?? new RatingLikes(-1);
this.summary = obj.summary ?? "";
this.thumbnails = obj.thumbnails ?? new Thumbnails([]);
}
}
class PlatformArticleDetails extends PlatformArticle {
constructor(obj) { constructor(obj) {
super(obj, 3); super(obj, 3);
obj = obj ?? {}; obj = obj ?? {};
this.plugin_type = "PlatformArticleDetails"; this.plugin_type = "PlatformArticleDetails";
this.rating = obj.rating ?? new RatingLikes(-1); this.rating = obj.rating ?? new RatingLikes(-1);
this.summary = obj.summary ?? "";
this.segments = obj.segments ?? []; this.segments = obj.segments ?? [];
this.thumbnails = obj.thumbnails ?? new Thumbnails([]);
} }
} }
class ArticleSegment { class ArticleSegment {

View file

@ -43,6 +43,7 @@ import com.futo.platformplayer.casting.StateCasting
import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.dp import com.futo.platformplayer.dp
import com.futo.platformplayer.fragment.mainactivity.bottombar.MenuBottomBarFragment import com.futo.platformplayer.fragment.mainactivity.bottombar.MenuBottomBarFragment
import com.futo.platformplayer.fragment.mainactivity.main.ArticleDetailFragment
import com.futo.platformplayer.fragment.mainactivity.main.BrowserFragment import com.futo.platformplayer.fragment.mainactivity.main.BrowserFragment
import com.futo.platformplayer.fragment.mainactivity.main.BuyFragment import com.futo.platformplayer.fragment.mainactivity.main.BuyFragment
import com.futo.platformplayer.fragment.mainactivity.main.ChannelFragment import com.futo.platformplayer.fragment.mainactivity.main.ChannelFragment
@ -151,6 +152,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
//Frags Main //Frags Main
lateinit var _fragMainHome: HomeFragment; lateinit var _fragMainHome: HomeFragment;
lateinit var _fragPostDetail: PostDetailFragment; lateinit var _fragPostDetail: PostDetailFragment;
lateinit var _fragArticleDetail: ArticleDetailFragment;
lateinit var _fragWebDetail: WebDetailFragment; lateinit var _fragWebDetail: WebDetailFragment;
lateinit var _fragMainVideoSearchResults: ContentSearchResultsFragment; lateinit var _fragMainVideoSearchResults: ContentSearchResultsFragment;
lateinit var _fragMainCreatorSearchResults: CreatorSearchResultsFragment; lateinit var _fragMainCreatorSearchResults: CreatorSearchResultsFragment;
@ -326,6 +328,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
_fragMainPlaylist = PlaylistFragment.newInstance(); _fragMainPlaylist = PlaylistFragment.newInstance();
_fragMainRemotePlaylist = RemotePlaylistFragment.newInstance(); _fragMainRemotePlaylist = RemotePlaylistFragment.newInstance();
_fragPostDetail = PostDetailFragment.newInstance(); _fragPostDetail = PostDetailFragment.newInstance();
_fragArticleDetail = ArticleDetailFragment.newInstance();
_fragWebDetail = WebDetailFragment.newInstance(); _fragWebDetail = WebDetailFragment.newInstance();
_fragWatchlist = WatchLaterFragment.newInstance(); _fragWatchlist = WatchLaterFragment.newInstance();
_fragHistory = HistoryFragment.newInstance(); _fragHistory = HistoryFragment.newInstance();
@ -1221,6 +1224,8 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
PlaylistFragment::class -> _fragMainPlaylist as T; PlaylistFragment::class -> _fragMainPlaylist as T;
RemotePlaylistFragment::class -> _fragMainRemotePlaylist as T; RemotePlaylistFragment::class -> _fragMainRemotePlaylist as T;
PostDetailFragment::class -> _fragPostDetail as T; PostDetailFragment::class -> _fragPostDetail as T;
ArticleDetailFragment::class -> _fragArticleDetail as T;
WebDetailFragment::class -> _fragWebDetail as T;
WatchLaterFragment::class -> _fragWatchlist as T; WatchLaterFragment::class -> _fragWatchlist as T;
HistoryFragment::class -> _fragHistory as T; HistoryFragment::class -> _fragHistory as T;
SourceDetailFragment::class -> _fragSourceDetail as T; SourceDetailFragment::class -> _fragSourceDetail as T;

View file

@ -24,7 +24,7 @@ import com.futo.platformplayer.getOrThrowNullableList
import com.futo.platformplayer.states.StateDeveloper import com.futo.platformplayer.states.StateDeveloper
open class JSArticle : JSContent, IPlatformArticle, IPluginSourced { open class JSArticle : JSContent, IPlatformArticle, IPluginSourced {
final override val contentType: ContentType get() = ContentType.POST; final override val contentType: ContentType get() = ContentType.ARTICLE;
override val summary: String; override val summary: String;
override val thumbnails: Thumbnails?; override val thumbnails: Thumbnails?;

View file

@ -32,6 +32,9 @@ import com.futo.platformplayer.api.media.models.ratings.IRating
import com.futo.platformplayer.api.media.models.ratings.RatingLikeDislikes import com.futo.platformplayer.api.media.models.ratings.RatingLikeDislikes
import com.futo.platformplayer.api.media.models.ratings.RatingLikes import com.futo.platformplayer.api.media.models.ratings.RatingLikes
import com.futo.platformplayer.api.media.platforms.js.models.JSArticleDetails import com.futo.platformplayer.api.media.platforms.js.models.JSArticleDetails
import com.futo.platformplayer.api.media.platforms.js.models.JSImagesSegment
import com.futo.platformplayer.api.media.platforms.js.models.JSTextSegment
import com.futo.platformplayer.api.media.platforms.js.models.SegmentType
import com.futo.platformplayer.constructs.TaskHandler import com.futo.platformplayer.constructs.TaskHandler
import com.futo.platformplayer.dp import com.futo.platformplayer.dp
import com.futo.platformplayer.fixHtmlWhitespace import com.futo.platformplayer.fixHtmlWhitespace
@ -73,7 +76,7 @@ class ArticleDetailFragment : MainFragment {
override val isTab: Boolean = true; override val isTab: Boolean = true;
override val hasBottomBar: Boolean get() = true; override val hasBottomBar: Boolean get() = true;
private var _viewDetail: PostDetailView? = null; private var _viewDetail: ArticleDetailView? = null;
constructor() : super() { } constructor() : super() { }
@ -82,7 +85,7 @@ class ArticleDetailFragment : MainFragment {
} }
override fun onCreateMainView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateMainView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view = PostDetailView(inflater.context).applyFragment(this); val view = ArticleDetailView(inflater.context).applyFragment(this);
_viewDetail = view; _viewDetail = view;
return view; return view;
} }
@ -106,7 +109,7 @@ class ArticleDetailFragment : MainFragment {
} }
} }
private class PostDetailView : ConstraintLayout { private class ArticleDetailView : ConstraintLayout {
private lateinit var _fragment: ArticleDetailFragment; private lateinit var _fragment: ArticleDetailFragment;
private var _url: String? = null; private var _url: String? = null;
private var _isLoading = false; private var _isLoading = false;
@ -124,7 +127,6 @@ class ArticleDetailFragment : MainFragment {
private val _textTitle: TextView; private val _textTitle: TextView;
private val _textMeta: TextView; private val _textMeta: TextView;
private val _containerSegments: LinearLayout; private val _containerSegments: LinearLayout;
private val _textContent: TextView;
private val _platformIndicator: PlatformIndicator; private val _platformIndicator: PlatformIndicator;
private val _buttonShare: ImageButton; private val _buttonShare: ImageButton;
@ -141,9 +143,6 @@ class ArticleDetailFragment : MainFragment {
private val _layoutLoadingOverlay: FrameLayout; private val _layoutLoadingOverlay: FrameLayout;
private val _imageLoader: ImageView; private val _imageLoader: ImageView;
private val _imageActive: ImageView;
private val _layoutThumbnails: FlexboxLayout;
private val _repliesOverlay: RepliesOverlay; private val _repliesOverlay: RepliesOverlay;
private val _commentsList: CommentsList; private val _commentsList: CommentsList;
@ -207,16 +206,12 @@ class ArticleDetailFragment : MainFragment {
_layoutLoadingOverlay = findViewById(R.id.layout_loading_overlay); _layoutLoadingOverlay = findViewById(R.id.layout_loading_overlay);
_imageLoader = findViewById(R.id.image_loader); _imageLoader = findViewById(R.id.image_loader);
_imageActive = findViewById(R.id.image_active);
_layoutThumbnails = findViewById(R.id.layout_thumbnails);
_repliesOverlay = findViewById(R.id.replies_overlay); _repliesOverlay = findViewById(R.id.replies_overlay);
_buttonPolycentric = findViewById(R.id.button_polycentric) _buttonPolycentric = findViewById(R.id.button_polycentric)
_buttonPlatform = findViewById(R.id.button_platform) _buttonPlatform = findViewById(R.id.button_platform)
_textContent.setPlatformPlayerLinkMovementMethod(context);
_buttonSubscribe.onSubscribed.subscribe { _buttonSubscribe.onSubscribed.subscribe {
//TODO: add overlay to layout //TODO: add overlay to layout
//UISlideOverlays.showSubscriptionOptionsOverlay(it, _overlayContainer); //UISlideOverlays.showSubscriptionOptionsOverlay(it, _overlayContainer);
@ -410,7 +405,7 @@ class ArticleDetailFragment : MainFragment {
} }
} }
fun applyFragment(frag: ArticleDetailFragment): PostDetailView { fun applyFragment(frag: ArticleDetailFragment): ArticleDetailView {
_fragment = frag; _fragment = frag;
return this; return this;
} }
@ -431,13 +426,14 @@ class ArticleDetailFragment : MainFragment {
setChannelMeta(null); setChannelMeta(null);
_textTitle.text = ""; _textTitle.text = "";
_textMeta.text = ""; _textMeta.text = "";
_textContent.text = "";
setPlatformRating(null); setPlatformRating(null);
_polycentricProfile = null; _polycentricProfile = null;
_rating.visibility = View.GONE; _rating.visibility = View.GONE;
updatePolycentricRating(); updatePolycentricRating();
setRepliesOverlayVisible(isVisible = false, animate = false); setRepliesOverlayVisible(isVisible = false, animate = false);
_containerSegments.removeAllViews();
_addCommentView.setContext(null, null); _addCommentView.setContext(null, null);
_platformIndicator.clearPlatform(); _platformIndicator.clearPlatform();
} }
@ -457,6 +453,22 @@ class ArticleDetailFragment : MainFragment {
_platformIndicator.setPlatformFromClientID(value.id.pluginId); _platformIndicator.setPlatformFromClientID(value.id.pluginId);
setPlatformRating(value.rating); setPlatformRating(value.rating);
for(seg in value.segments) {
when(seg.type) {
SegmentType.TEXT -> {
if(seg is JSTextSegment) {
}
}
SegmentType.IMAGES -> {
if(seg is JSImagesSegment) {
}
}
else ->{}
}
}
//Fetch only when not already called in setPostOverview //Fetch only when not already called in setPostOverview
if (_articleOverview == null) { if (_articleOverview == null) {
fetchPolycentricProfile(); fetchPolycentricProfile();
@ -647,6 +659,18 @@ class ArticleDetailFragment : MainFragment {
} }
} }
class ArticleTextBlock : View {
constructor(context: Context?) : super(context){
}
}
class ArticleImageBlock: View {
constructor(context: Context?) : super(context){
}
}
companion object { companion object {
const val TAG = "PostDetailFragment" const val TAG = "PostDetailFragment"
} }

View file

@ -10,6 +10,7 @@ import com.futo.platformplayer.R
import com.futo.platformplayer.Settings import com.futo.platformplayer.Settings
import com.futo.platformplayer.UIDialogs import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.UISlideOverlays import com.futo.platformplayer.UISlideOverlays
import com.futo.platformplayer.api.media.models.article.IPlatformArticle
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.models.playlists.IPlatformPlaylist import com.futo.platformplayer.api.media.models.playlists.IPlatformPlaylist
@ -196,7 +197,11 @@ abstract class ContentFeedView<TFragment> : FeedView<TFragment, IPlatformContent
fragment.navigate<RemotePlaylistFragment>(content); fragment.navigate<RemotePlaylistFragment>(content);
} else if (content is IPlatformPost) { } else if (content is IPlatformPost) {
fragment.navigate<PostDetailFragment>(content); fragment.navigate<PostDetailFragment>(content);
} else if(content is IPlatformArticle) {
fragment.navigate<ArticleDetailFragment>(content);
} }
else
UIDialogs.appToast("Unknown content type [" + content.contentType.name + "]");
} }
protected open fun onContentUrlClicked(url: String, contentType: ContentType) { protected open fun onContentUrlClicked(url: String, contentType: ContentType) {
when(contentType) { when(contentType) {

View file

@ -79,6 +79,7 @@ class PreviewContentListAdapter : InsertedViewAdapterWithLoader<ContentPreviewVi
return when(contentType) { return when(contentType) {
ContentType.PLACEHOLDER -> createPlaceholderViewHolder(viewGroup); ContentType.PLACEHOLDER -> createPlaceholderViewHolder(viewGroup);
ContentType.MEDIA -> createVideoPreviewViewHolder(viewGroup); ContentType.MEDIA -> createVideoPreviewViewHolder(viewGroup);
ContentType.ARTICLE -> createPostViewHolder(viewGroup);
ContentType.POST -> createPostViewHolder(viewGroup); ContentType.POST -> createPostViewHolder(viewGroup);
ContentType.PLAYLIST -> createPlaylistViewHolder(viewGroup); ContentType.PLAYLIST -> createPlaylistViewHolder(viewGroup);
ContentType.NESTED_VIDEO -> createNestedViewHolder(viewGroup); ContentType.NESTED_VIDEO -> createNestedViewHolder(viewGroup);

View file

@ -16,68 +16,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="14dp"
android:layout_marginRight="14dp"
android:layout_marginTop="10dp">
<LinearLayout
android:id="@+id/layout_channel_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="@id/button_subscribe">
<com.futo.platformplayer.views.others.CreatorThumbnail
android:id="@+id/creator_thumbnail"
android:layout_width="27dp"
android:layout_height="27dp"
android:contentDescription="@string/cd_creator_thumbnail" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="6dp"
android:orientation="vertical">
<TextView
android:id="@+id/text_channel_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:layout_gravity="center"
android:layout_marginTop="-4dp"
android:ellipsize="end"
android:maxLines="1"
tools:text="Channel Name" />
<TextView
android:id="@+id/text_channel_meta"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textColor="#ACACAC"
android:textSize="9sp"
android:layout_gravity="center"
android:ellipsize="end"
android:maxLines="1"
tools:text="" />
</LinearLayout>
</LinearLayout>
<com.futo.platformplayer.views.subscriptions.SubscribeButton
android:id="@+id/button_subscribe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView <TextView
android:id="@+id/text_title" android:id="@+id/text_title"
@ -175,9 +113,72 @@
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="14dp"
android:layout_marginRight="14dp"
android:layout_marginTop="10dp">
<LinearLayout
android:id="@+id/layout_channel_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="@id/button_subscribe">
<com.futo.platformplayer.views.others.CreatorThumbnail
android:id="@+id/creator_thumbnail"
android:layout_width="27dp"
android:layout_height="27dp"
android:contentDescription="@string/cd_creator_thumbnail" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="6dp"
android:orientation="vertical">
<TextView
android:id="@+id/text_channel_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:layout_gravity="center"
android:layout_marginTop="-4dp"
android:ellipsize="end"
android:maxLines="1"
tools:text="Channel Name" />
<TextView
android:id="@+id/text_channel_meta"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textColor="#ACACAC"
android:textSize="9sp"
android:layout_gravity="center"
android:ellipsize="end"
android:maxLines="1"
tools:text="" />
</LinearLayout>
</LinearLayout>
<com.futo.platformplayer.views.subscriptions.SubscribeButton
android:id="@+id/button_subscribe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout <LinearLayout
android:id="@+id/container_segments" android:id="@+id/container_segments"
android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />