mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-19 19:14:51 +00:00
Chapter Overlay
This commit is contained in:
parent
034b8b15ae
commit
3c05521a5b
9 changed files with 452 additions and 0 deletions
|
@ -132,6 +132,7 @@ import com.futo.platformplayer.views.behavior.TouchInterceptFrameLayout
|
|||
import com.futo.platformplayer.views.casting.CastView
|
||||
import com.futo.platformplayer.views.comments.AddCommentView
|
||||
import com.futo.platformplayer.views.others.CreatorThumbnail
|
||||
import com.futo.platformplayer.views.overlays.ChaptersOverlay
|
||||
import com.futo.platformplayer.views.overlays.DescriptionOverlay
|
||||
import com.futo.platformplayer.views.overlays.LiveChatOverlay
|
||||
import com.futo.platformplayer.views.overlays.QueueEditorOverlay
|
||||
|
@ -147,6 +148,7 @@ import com.futo.platformplayer.views.pills.PillRatingLikesDislikes
|
|||
import com.futo.platformplayer.views.pills.RoundButton
|
||||
import com.futo.platformplayer.views.pills.RoundButtonGroup
|
||||
import com.futo.platformplayer.views.platform.PlatformIndicator
|
||||
import com.futo.platformplayer.views.segments.ChaptersList
|
||||
import com.futo.platformplayer.views.segments.CommentsList
|
||||
import com.futo.platformplayer.views.subscriptions.SubscribeButton
|
||||
import com.futo.platformplayer.views.video.FutoVideoPlayer
|
||||
|
@ -195,6 +197,8 @@ class VideoDetailView : ConstraintLayout {
|
|||
private var _liveChat: LiveChatManager? = null;
|
||||
private var _videoResumePositionMilliseconds : Long = 0L;
|
||||
|
||||
private var _chapters: List<IChapter>? = null;
|
||||
|
||||
private val _player: FutoVideoPlayer;
|
||||
private val _cast: CastView;
|
||||
private val _playerProgress: PlayerControlView;
|
||||
|
@ -263,6 +267,7 @@ class VideoDetailView : ConstraintLayout {
|
|||
private val _container_content_liveChat: LiveChatOverlay;
|
||||
private val _container_content_browser: WebviewOverlay;
|
||||
private val _container_content_support: SupportOverlay;
|
||||
private val _container_content_chapters: ChaptersOverlay;
|
||||
|
||||
private var _container_content_current: View;
|
||||
|
||||
|
@ -374,6 +379,7 @@ class VideoDetailView : ConstraintLayout {
|
|||
_container_content_liveChat = findViewById(R.id.videodetail_container_livechat);
|
||||
_container_content_support = findViewById(R.id.videodetail_container_support);
|
||||
_container_content_browser = findViewById(R.id.videodetail_container_webview)
|
||||
_container_content_chapters = findViewById(R.id.videodetail_container_chapters);
|
||||
|
||||
_addCommentView = findViewById(R.id.add_comment_view);
|
||||
_commentsList = findViewById(R.id.comments_list);
|
||||
|
@ -686,6 +692,11 @@ class VideoDetailView : ConstraintLayout {
|
|||
_container_content_replies.onClose.subscribe { switchContentView(_container_content_main); };
|
||||
_container_content_support.onClose.subscribe { switchContentView(_container_content_main); };
|
||||
_container_content_browser.onClose.subscribe { switchContentView(_container_content_main); };
|
||||
_container_content_chapters.onClose.subscribe { switchContentView(_container_content_main); };
|
||||
|
||||
_container_content_chapters.onClick.subscribe {
|
||||
handleSeek(it.timeStart.toLong() * 1000);
|
||||
}
|
||||
|
||||
_description_viewMore.setOnClickListener {
|
||||
switchContentView(_container_content_description);
|
||||
|
@ -865,6 +876,21 @@ class VideoDetailView : ConstraintLayout {
|
|||
};
|
||||
}
|
||||
},
|
||||
_chapters?.let {
|
||||
if(it != null && it.size > 0)
|
||||
RoundButton(context, R.drawable.ic_list, "Chapters", TAG_CHAPTERS) {
|
||||
video?.let {
|
||||
try {
|
||||
_container_content_chapters.setChapters(_chapters);
|
||||
switchContentView(_container_content_chapters);
|
||||
}
|
||||
catch(ex: Throwable) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else null
|
||||
},
|
||||
if(video?.isLive ?: false)
|
||||
RoundButton(context, R.drawable.ic_chat, context.getString(R.string.live_chat), TAG_LIVECHAT) {
|
||||
video?.let {
|
||||
|
@ -1340,10 +1366,12 @@ class VideoDetailView : ConstraintLayout {
|
|||
val chapters = null ?: StatePlatform.instance.getContentChapters(video.url);
|
||||
_player.setChapters(chapters);
|
||||
_cast.setChapters(chapters);
|
||||
_chapters = _player.getChapters();
|
||||
} catch (ex: Throwable) {
|
||||
Logger.e(TAG, "Failed to get chapters", ex);
|
||||
_player.setChapters(null);
|
||||
_cast.setChapters(null);
|
||||
_chapters = null;
|
||||
|
||||
/*withContext(Dispatchers.Main) {
|
||||
UIDialogs.toast(context, "Failed to get chapters\n" + ex.message);
|
||||
|
@ -1382,6 +1410,10 @@ class VideoDetailView : ConstraintLayout {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||
updateMoreButtons();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3077,6 +3109,7 @@ class VideoDetailView : ConstraintLayout {
|
|||
const val TAG_SHARE = "share";
|
||||
const val TAG_OVERLAY = "overlay";
|
||||
const val TAG_LIVECHAT = "livechat";
|
||||
const val TAG_CHAPTERS = "chapters";
|
||||
const val TAG_OPEN = "open";
|
||||
const val TAG_SEND_TO_DEVICE = "send_to_device";
|
||||
const val TAG_MORE = "MORE";
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
package com.futo.platformplayer.views.adapters
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.futo.platformplayer.R
|
||||
import com.futo.platformplayer.Settings
|
||||
import com.futo.platformplayer.api.media.models.chapters.ChapterType
|
||||
import com.futo.platformplayer.api.media.models.chapters.IChapter
|
||||
import com.futo.platformplayer.api.media.models.comments.IPlatformComment
|
||||
import com.futo.platformplayer.api.media.models.comments.LazyComment
|
||||
import com.futo.platformplayer.api.media.models.comments.PolycentricPlatformComment
|
||||
import com.futo.platformplayer.api.media.models.ratings.RatingLikeDislikes
|
||||
import com.futo.platformplayer.api.media.models.ratings.RatingLikes
|
||||
import com.futo.platformplayer.constructs.Event1
|
||||
import com.futo.platformplayer.fixHtmlLinks
|
||||
import com.futo.platformplayer.setPlatformPlayerLinkMovementMethod
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StatePolycentric
|
||||
import com.futo.platformplayer.toHumanDuration
|
||||
import com.futo.platformplayer.toHumanNowDiffString
|
||||
import com.futo.platformplayer.toHumanNumber
|
||||
import com.futo.platformplayer.toHumanTime
|
||||
import com.futo.platformplayer.views.LoaderView
|
||||
import com.futo.platformplayer.views.others.CreatorThumbnail
|
||||
import com.futo.platformplayer.views.pills.PillButton
|
||||
import com.futo.platformplayer.views.pills.PillRatingLikesDislikes
|
||||
import com.futo.polycentric.core.ApiMethods
|
||||
import com.futo.polycentric.core.Opinion
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ChapterViewHolder : ViewHolder {
|
||||
|
||||
private val _layoutChapter: ConstraintLayout;
|
||||
|
||||
private val _containerChapter: ConstraintLayout;
|
||||
|
||||
private val _textTitle: TextView;
|
||||
private val _textTimestamp: TextView;
|
||||
private val _textMeta: TextView;
|
||||
|
||||
var onClick = Event1<IChapter>();
|
||||
var chapter: IChapter? = null
|
||||
private set;
|
||||
|
||||
constructor(viewGroup: ViewGroup) : super(LayoutInflater.from(viewGroup.context).inflate(R.layout.list_chapter, viewGroup, false)) {
|
||||
_layoutChapter = itemView.findViewById(R.id.layout_chapter);
|
||||
_containerChapter = itemView.findViewById(R.id.chapter_container);
|
||||
|
||||
_containerChapter.setOnClickListener {
|
||||
chapter?.let {
|
||||
onClick.emit(it);
|
||||
}
|
||||
}
|
||||
|
||||
_textTitle = itemView.findViewById(R.id.text_title);
|
||||
_textTimestamp = itemView.findViewById(R.id.text_timestamp);
|
||||
_textMeta = itemView.findViewById(R.id.text_meta);
|
||||
}
|
||||
|
||||
fun bind(chapter: IChapter) {
|
||||
_textTitle.text = chapter.name;
|
||||
_textTimestamp.text = chapter.timeStart.toLong().toHumanTime(false);
|
||||
|
||||
if(chapter.type == ChapterType.NORMAL) {
|
||||
_textMeta.isVisible = false;
|
||||
}
|
||||
else {
|
||||
_textMeta.isVisible = true;
|
||||
when(chapter.type) {
|
||||
ChapterType.SKIP -> _textMeta.text = "(Skip)";
|
||||
ChapterType.SKIPPABLE -> _textMeta.text = "(Manual Skip)"
|
||||
ChapterType.SKIPONCE -> _textMeta.text = "(Skip Once)"
|
||||
else -> _textMeta.isVisible = false;
|
||||
};
|
||||
}
|
||||
this.chapter = chapter;
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "CommentViewHolder";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.futo.platformplayer.views.overlays
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.util.AttributeSet
|
||||
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.UIDialogs
|
||||
import com.futo.platformplayer.activities.MainActivity
|
||||
import com.futo.platformplayer.api.http.ManagedHttpClient
|
||||
import com.futo.platformplayer.api.media.models.chapters.IChapter
|
||||
import com.futo.platformplayer.api.media.models.comments.IPlatformComment
|
||||
import com.futo.platformplayer.api.media.models.comments.PolycentricPlatformComment
|
||||
import com.futo.platformplayer.api.media.structures.IPager
|
||||
import com.futo.platformplayer.constructs.Event0
|
||||
import com.futo.platformplayer.constructs.Event1
|
||||
import com.futo.platformplayer.fixHtmlLinks
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StatePlatform
|
||||
import com.futo.platformplayer.states.StatePolycentric
|
||||
import com.futo.platformplayer.toHumanNowDiffString
|
||||
import com.futo.platformplayer.views.behavior.NonScrollingTextView
|
||||
import com.futo.platformplayer.views.comments.AddCommentView
|
||||
import com.futo.platformplayer.views.others.CreatorThumbnail
|
||||
import com.futo.platformplayer.views.segments.ChaptersList
|
||||
import com.futo.platformplayer.views.segments.CommentsList
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import userpackage.Protocol
|
||||
|
||||
class ChaptersOverlay : LinearLayout {
|
||||
val onClose = Event0();
|
||||
val onClick = Event1<IChapter>();
|
||||
|
||||
private val _topbar: OverlayTopbar;
|
||||
private val _chaptersList: ChaptersList;
|
||||
private var _onChapterClicked: ((chapter: IChapter) -> Unit)? = null;
|
||||
private val _layoutItems: LinearLayout
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet? = null) : super(context, attrs) {
|
||||
inflate(context, R.layout.overlay_chapters, this)
|
||||
_layoutItems = findViewById(R.id.layout_items)
|
||||
_topbar = findViewById(R.id.topbar);
|
||||
_chaptersList = findViewById(R.id.chapters_list);
|
||||
_chaptersList.onChapterClick.subscribe(onClick::emit);
|
||||
_topbar.onClose.subscribe(this, onClose::emit);
|
||||
_topbar.setInfo(context.getString(R.string.chapters), "");
|
||||
}
|
||||
|
||||
fun setChapters(chapters: List<IChapter>?) {
|
||||
_chaptersList?.setChapters(chapters ?: listOf());
|
||||
}
|
||||
|
||||
|
||||
fun cleanup() {
|
||||
_topbar.onClose.remove(this);
|
||||
_onChapterClicked = null;
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ChaptersOverlay"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package com.futo.platformplayer.views.segments
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.futo.platformplayer.R
|
||||
import com.futo.platformplayer.UIDialogs
|
||||
import com.futo.platformplayer.api.media.models.chapters.IChapter
|
||||
import com.futo.platformplayer.api.media.models.comments.IPlatformComment
|
||||
import com.futo.platformplayer.api.media.models.comments.LazyComment
|
||||
import com.futo.platformplayer.api.media.models.comments.PolycentricPlatformComment
|
||||
import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails
|
||||
import com.futo.platformplayer.api.media.structures.IAsyncPager
|
||||
import com.futo.platformplayer.api.media.structures.IPager
|
||||
import com.futo.platformplayer.constructs.Event1
|
||||
import com.futo.platformplayer.constructs.TaskHandler
|
||||
import com.futo.platformplayer.engine.exceptions.ScriptUnavailableException
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StatePolycentric
|
||||
import com.futo.platformplayer.views.adapters.ChapterViewHolder
|
||||
import com.futo.platformplayer.views.adapters.CommentViewHolder
|
||||
import com.futo.platformplayer.views.adapters.InsertedViewAdapterWithLoader
|
||||
import com.futo.polycentric.core.fullyBackfillServersAnnounceExceptions
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.net.UnknownHostException
|
||||
|
||||
class ChaptersList : ConstraintLayout {
|
||||
private val _llmReplies: LinearLayoutManager;
|
||||
|
||||
private val _adapterChapters: InsertedViewAdapterWithLoader<ChapterViewHolder>;
|
||||
private val _recyclerChapters: RecyclerView;
|
||||
private val _chapters: ArrayList<IChapter> = arrayListOf();
|
||||
private val _prependedView: FrameLayout;
|
||||
private var _readonly: Boolean = false;
|
||||
private val _layoutScrollToTop: FrameLayout;
|
||||
|
||||
var onChapterClick = Event1<IChapter>();
|
||||
var onCommentsLoaded = Event1<Int>();
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
||||
LayoutInflater.from(context).inflate(R.layout.view_chapters_list, this, true);
|
||||
|
||||
_recyclerChapters = findViewById(R.id.recycler_chapters);
|
||||
|
||||
_layoutScrollToTop = findViewById(R.id.layout_scroll_to_top);
|
||||
_layoutScrollToTop.setOnClickListener {
|
||||
_recyclerChapters.smoothScrollToPosition(0)
|
||||
}
|
||||
_layoutScrollToTop.visibility = View.GONE
|
||||
|
||||
_prependedView = FrameLayout(context);
|
||||
_prependedView.layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
_adapterChapters = InsertedViewAdapterWithLoader(context, arrayListOf(_prependedView), arrayListOf(),
|
||||
childCountGetter = { _chapters.size },
|
||||
childViewHolderBinder = { viewHolder, position -> viewHolder.bind(_chapters[position]); },
|
||||
childViewHolderFactory = { viewGroup, _ ->
|
||||
val holder = ChapterViewHolder(viewGroup);
|
||||
holder.onClick.subscribe { c -> onChapterClick.emit(c) };
|
||||
return@InsertedViewAdapterWithLoader holder;
|
||||
}
|
||||
);
|
||||
|
||||
_llmReplies = LinearLayoutManager(context);
|
||||
_recyclerChapters.layoutManager = _llmReplies;
|
||||
_recyclerChapters.adapter = _adapterChapters;
|
||||
}
|
||||
|
||||
fun addChapter(chapter: IChapter) {
|
||||
_chapters.add(0, chapter);
|
||||
_adapterChapters.notifyItemRangeInserted(_adapterChapters.childToParentPosition(0), 1);
|
||||
}
|
||||
|
||||
fun setPrependedView(view: View) {
|
||||
_prependedView.removeAllViews();
|
||||
_prependedView.addView(view);
|
||||
}
|
||||
|
||||
fun setChapters(chapters: List<IChapter>) {
|
||||
_chapters.clear();
|
||||
_chapters.addAll(chapters);
|
||||
_adapterChapters.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
_chapters.clear();
|
||||
_adapterChapters.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "CommentsList";
|
||||
}
|
||||
}
|
|
@ -579,6 +579,12 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.futo.platformplayer.views.overlays.ChaptersOverlay
|
||||
android:id="@+id/videodetail_container_chapters"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.futo.platformplayer.views.overlays.SupportOverlay
|
||||
android:id="@+id/videodetail_container_support"
|
||||
android:visibility="gone"
|
||||
|
|
81
app/src/main/res/layout/list_chapter.xml
Normal file
81
app/src/main/res/layout/list_chapter.xml
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/layout_chapter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginStart="14dp"
|
||||
android:layout_marginEnd="14dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/chapter_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="2dp"
|
||||
android:padding="15dp"
|
||||
android:background="@drawable/background_1b_round_6dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
<TextView
|
||||
android:id="@+id/text_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:fontFamily="@font/inter_regular"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
tools:text="Some chapter text" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_meta"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:fontFamily="@font/inter_regular"
|
||||
android:textColor="@color/text_color_tinted"
|
||||
android:textSize="11sp"
|
||||
tools:text="test" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_timestamp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:fontFamily="@font/inter_regular"
|
||||
android:background="@drawable/background_thumbnail_duration"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:textColor="@color/gray_ac"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="1:23" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
34
app/src/main/res/layout/overlay_chapters.xml
Normal file
34
app/src/main/res/layout/overlay_chapters.xml
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/layout_items">
|
||||
|
||||
<com.futo.platformplayer.views.overlays.OverlayTopbar
|
||||
android:id="@+id/topbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
app:title="Chapters"
|
||||
app:metadata="" />
|
||||
|
||||
|
||||
|
||||
<com.futo.platformplayer.views.segments.ChaptersList
|
||||
android:id="@+id/chapters_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="12dp" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
31
app/src/main/res/layout/view_chapters_list.xml
Normal file
31
app/src/main/res/layout/view_chapters_list.xml
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_chapters"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:paddingBottom="7dp"
|
||||
android:paddingEnd="14dp"
|
||||
android:paddingTop="7dp"
|
||||
android:paddingStart="14dp"
|
||||
android:background="@drawable/background_pill"
|
||||
android:id="@+id/layout_scroll_to_top">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/scroll_to_top"
|
||||
android:textColor="@color/white"
|
||||
android:fontFamily="@font/inter_regular"
|
||||
android:textSize="14dp"/>
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
|
@ -665,6 +665,7 @@
|
|||
<string name="failed_to_load_post">Failed to load post.</string>
|
||||
<string name="replies">replies</string>
|
||||
<string name="Replies">Replies</string>
|
||||
<string name="chapters">Chapters</string>
|
||||
<string name="plugin_settings_saved">Plugin settings saved</string>
|
||||
<string name="plugin_settings">Plugin settings</string>
|
||||
<string name="these_settings_are_defined_by_the_plugin">These settings are defined by the plugin</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue