Compare commits

...

20 Commits

Author SHA1 Message Date
Kelvin 6141c36855 Refs 2023-12-21 20:04:53 +01:00
Kelvin 4084ab3ed0 refs 2023-12-21 20:01:51 +01:00
Kelvin 34e733823a Refs 2023-12-21 19:27:13 +01:00
Kelvin f1d01642cd Refs, ui fixes 2023-12-21 19:24:30 +01:00
Kelvin d5551d7118 Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay 2023-12-21 17:24:18 +01:00
Kelvin d079a1e8e4 Add missing channel name setter 2023-12-21 17:24:11 +01:00
Koen c06c00ee9b Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay 2023-12-21 17:19:17 +01:00
Koen 1d8eababc2 Minor casting dialog fixes. 2023-12-21 17:19:05 +01:00
Kelvin 75cf1ffbdd Offline playback fix with remote sources 2023-12-21 17:13:43 +01:00
Kelvin 5499706a9b Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay 2023-12-21 16:14:01 +01:00
Kelvin ba57e32920 Minor queue styling, refs 2023-12-21 16:13:53 +01:00
Koen df96c5b51c Fixed live video previews in preview layout. Fixed time bar spacing at bottom. 2023-12-21 16:07:03 +01:00
Koen 75f81d20db Fixed buttons in subscription groups and made select button click only work when there are things selected. 2023-12-21 13:10:38 +01:00
Koen 3fc92e4065 Fixed rounding of subscription groups. 2023-12-21 12:56:35 +01:00
Koen 8ffd5f411f Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay 2023-12-21 11:21:34 +01:00
Koen 918161a299 Fixed margins for subscription groups and menu bar icons now show filled variant if existing. 2023-12-21 11:20:53 +01:00
Kelvin 9f50f72eaa Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay 2023-12-21 11:12:45 +01:00
Kelvin 2f66f124aa Toast on cancel creation, default subgroup creator image, fix subgroup cache load 2023-12-21 11:12:34 +01:00
Koen 9a11717cf4 Fixed Rumble channel contents having empty author. Changed TutorialVideo so author is not clickable. 2023-12-21 10:20:52 +01:00
Kelvin 0d80424799 Optimized selection creator overlay, global subscription progress listener 2023-12-20 21:54:39 +01:00
39 changed files with 386 additions and 209 deletions
@@ -7,6 +7,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
@@ -26,8 +27,8 @@ import kotlinx.coroutines.launch
class ConnectCastingDialog(context: Context?) : AlertDialog(context) {
private lateinit var _imageLoader: ImageView;
private lateinit var _buttonClose: Button;
private lateinit var _buttonAdd: Button;
private lateinit var _buttonScanQR: Button;
private lateinit var _buttonAdd: ImageButton;
private lateinit var _buttonScanQR: ImageButton;
private lateinit var _textNoDevicesFound: TextView;
private lateinit var _textNoDevicesRemembered: TextView;
private lateinit var _recyclerDevices: RecyclerView;
@@ -297,9 +297,9 @@ class MenuBottomBarFragment : MainActivityFragment() {
}
if (!StatePayment.instance.hasPaid) {
newCurrentButtonDefinitions.add(ButtonDefinition(98, R.drawable.ic_paid, R.drawable.ic_paid, R.string.buy, canToggle = false, { it.currentMain is BuyFragment }, { it.navigate<BuyFragment>() }))
newCurrentButtonDefinitions.add(ButtonDefinition(98, R.drawable.ic_paid, R.drawable.ic_paid_filled, R.string.buy, canToggle = false, { it.currentMain is BuyFragment }, { it.navigate<BuyFragment>() }))
}
newCurrentButtonDefinitions.add(ButtonDefinition(97, R.drawable.ic_quiz, R.drawable.ic_quiz, R.string.faq, canToggle = false, { false }, {
newCurrentButtonDefinitions.add(ButtonDefinition(97, R.drawable.ic_quiz, R.drawable.ic_quiz_fill, R.string.faq, canToggle = false, { false }, {
it.navigate<BrowserFragment>(Settings.URL_FAQ);
}))
@@ -356,8 +356,8 @@ class MenuBottomBarFragment : MainActivityFragment() {
ButtonDefinition(6, R.drawable.ic_download, R.drawable.ic_download, R.string.downloads, canToggle = false, { it.currentMain is DownloadsFragment }, { it.navigate<DownloadsFragment>() }),
ButtonDefinition(8, R.drawable.ic_chat, R.drawable.ic_chat_filled, R.string.comments, canToggle = true, { it.currentMain is CommentsFragment }, { it.navigate<CommentsFragment>() }),
ButtonDefinition(9, R.drawable.ic_subscriptions, R.drawable.ic_subscriptions_filled, R.string.subscription_group_menu, canToggle = true, { it.currentMain is SubscriptionGroupListFragment }, { it.navigate<SubscriptionGroupListFragment>() }),
ButtonDefinition(10, R.drawable.ic_quiz, R.drawable.ic_quiz, R.string.tutorials, canToggle = true, { it.currentMain is TutorialFragment }, { it.navigate<TutorialFragment>() }),
ButtonDefinition(7, R.drawable.ic_settings, R.drawable.ic_settings, R.string.settings, canToggle = false, { false }, {
ButtonDefinition(10, R.drawable.ic_help_square, R.drawable.ic_help_square_fill, R.string.tutorials, canToggle = true, { it.currentMain is TutorialFragment }, { it.navigate<TutorialFragment>() }),
ButtonDefinition(7, R.drawable.ic_settings, R.drawable.ic_settings_filled, R.string.settings, canToggle = false, { false }, {
val c = it.context ?: return@ButtonDefinition;
Logger.i(TAG, "settings preventPictureInPicture()");
it.requireFragment<VideoDetailFragment>().preventPictureInPicture();
@@ -418,6 +418,7 @@ class ChannelFragment : MainFragment() {
_buttonSubscribe.setSubscribeChannel(channel);
_buttonSubscriptionSettings.visibility = if(_buttonSubscribe.isSubscribed) View.VISIBLE else View.GONE;
_textChannel.text = channel.name;
_textChannelSub.text = if(channel.subscribers > 0) "${channel.subscribers.toHumanNumber()} " + context.getString(R.string.subscribers).lowercase() else "";
//TODO: Find a better way to access the adapter fragments..
@@ -4,19 +4,15 @@ import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.os.Bundle
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.Button
import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.getSystemService
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@@ -25,14 +21,13 @@ import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.UISlideOverlays
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
import com.futo.platformplayer.dp
import com.futo.platformplayer.models.Subscription
import com.futo.platformplayer.models.ImageVariable
import com.futo.platformplayer.models.SubscriptionGroup
import com.futo.platformplayer.states.StateSubscriptionGroups
import com.futo.platformplayer.states.StateSubscriptions
import com.futo.platformplayer.views.AnyAdapterView
import com.futo.platformplayer.views.AnyAdapterView.Companion.asAny
import com.futo.platformplayer.views.SearchView
import com.futo.platformplayer.views.adapters.AnyAdapter
import com.futo.platformplayer.views.adapters.viewholders.CreatorBarViewHolder
import com.futo.platformplayer.views.overlays.CreatorSelectOverlay
import com.futo.platformplayer.views.overlays.ImageVariableOverlay
@@ -64,6 +59,11 @@ class SubscriptionGroupFragment : MainFragment() {
return view;
}
override fun onHide() {
super.onHide();
_view?.onHide();
}
companion object {
private const val TAG = "SourcesFragment";
fun newInstance() = SubscriptionGroupFragment().apply {}
@@ -86,7 +86,7 @@ class SubscriptionGroupFragment : MainFragment() {
private val _buttonSettings: ImageButton;
private val _buttonDelete: ImageButton;
private val _buttonAddCreator: Button;
private val _buttonAddCreator: FrameLayout;
private val _enabledCreators: ArrayList<IPlatformChannel> = arrayListOf();
private val _enabledCreatorsFiltered: ArrayList<IPlatformChannel> = arrayListOf();
@@ -97,6 +97,8 @@ class SubscriptionGroupFragment : MainFragment() {
private var _group: SubscriptionGroup? = null;
private var _didDelete: Boolean = false;
constructor(context: Context, fragment: SubscriptionGroupFragment): super(context) {
inflate(context, R.layout.fragment_subscriptions_group, this);
_fragment = fragment;
@@ -137,6 +139,7 @@ class SubscriptionGroupFragment : MainFragment() {
UIDialogs.Action("Delete", {
_group?.let {
it.urls.remove(channel.url);
save();
reloadCreators(it);
}
}, UIDialogs.ActionStyle.DANGEROUS))
@@ -178,6 +181,7 @@ class SubscriptionGroupFragment : MainFragment() {
UIDialogs.Action("Cancel", {}),
UIDialogs.Action("Delete", {
StateSubscriptionGroups.instance.deleteSubscriptionGroup(g.id);
_didDelete = true;
fragment.close(true);
}, UIDialogs.ActionStyle.DANGEROUS))
};
@@ -246,6 +250,18 @@ class SubscriptionGroupFragment : MainFragment() {
_overlay.animate().alpha(1f).setDuration(300).start();
overlay.onSelected.subscribe {
_group?.let { g ->
if(g.urls.isEmpty() && g.image == null) {
//Obtain image
for(sub in it) {
val sub = StateSubscriptions.instance.getSubscription(sub);
if(sub != null && sub.channel.thumbnail != null) {
g.image = ImageVariable.fromUrl(sub.channel.thumbnail!!);
g.image?.setImageView(_imageGroup);
g.image?.setImageView(_imageGroupBackground);
break;
}
}
}
for(url in it) {
if(!g.urls.contains(url))
g.urls.add(url);
@@ -262,6 +278,7 @@ class SubscriptionGroupFragment : MainFragment() {
fun setGroup(group: SubscriptionGroup?) {
_didDelete = false;
_group = group;
_textGroupTitle.text = group?.name;
@@ -278,6 +295,12 @@ class SubscriptionGroupFragment : MainFragment() {
reloadCreators(group);
}
fun onHide() {
if(!_didDelete && _group != null && StateSubscriptionGroups.instance.getSubscriptionGroup(_group!!.id) === null) {
UIDialogs.toast(context, "Group creation cancelled");
}
}
@SuppressLint("NotifyDataSetChanged")
private fun reloadCreators(group: SubscriptionGroup?) {
_enabledCreators.clear();
@@ -17,7 +17,6 @@ import com.futo.platformplayer.api.media.platforms.js.JSClient
import com.futo.platformplayer.api.media.structures.IPager
import com.futo.platformplayer.constructs.TaskHandler
import com.futo.platformplayer.engine.exceptions.PluginException
import com.futo.platformplayer.engine.exceptions.ScriptCaptchaRequiredException
import com.futo.platformplayer.exceptions.ChannelException
import com.futo.platformplayer.exceptions.RateLimitException
import com.futo.platformplayer.logging.Logger
@@ -53,6 +52,7 @@ class SubscriptionsFeedFragment : MainFragment() {
override val hasBottomBar: Boolean get() = true;
private var _view: SubscriptionsFeedView? = null;
private var _group: SubscriptionGroup? = null;
private var _cachedRecyclerData: FeedView.RecyclerData<InsertedViewAdapterWithLoader<ContentPreviewViewHolder>, LinearLayoutManager, IPager<IPlatformContent>, IPlatformContent, IPlatformContent, InsertedViewHolder<ContentPreviewViewHolder>>? = null;
override fun onShownWithView(parameter: Any?, isBack: Boolean) {
@@ -73,6 +73,8 @@ class SubscriptionsFeedFragment : MainFragment() {
override fun onCreateMainView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view = SubscriptionsFeedView(this, inflater, _cachedRecyclerData);
_view = view;
if(_group != null)
view.selectSubgroup(_group);
return view;
}
@@ -81,6 +83,7 @@ class SubscriptionsFeedFragment : MainFragment() {
val view = _view;
if (view != null) {
_cachedRecyclerData = view.recyclerData;
_group = view.subGroup;
view.cleanup();
_view = null;
}
@@ -101,12 +104,12 @@ class SubscriptionsFeedFragment : MainFragment() {
class SubscriptionsFeedView : ContentFeedView<SubscriptionsFeedFragment> {
override val shouldShowTimeBar: Boolean get() = Settings.instance.subscriptions.progressBar
private var _subGroup: SubscriptionGroup? = null;
var subGroup: SubscriptionGroup? = null;
constructor(fragment: SubscriptionsFeedFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData<InsertedViewAdapterWithLoader<ContentPreviewViewHolder>, LinearLayoutManager, IPager<IPlatformContent>, IPlatformContent, IPlatformContent, InsertedViewHolder<ContentPreviewViewHolder>>? = null) : super(fragment, inflater, cachedRecyclerData) {
Logger.i(TAG, "SubscriptionsFeedFragment constructor()");
StateSubscriptions.instance.onFeedProgress.subscribe(this) { id, progress, total ->
if(_subGroup?.id == id)
if(subGroup?.id == id)
fragment.lifecycleScope.launch(Dispatchers.Main) {
try {
setProgress(progress, total);
@@ -141,8 +144,9 @@ class SubscriptionsFeedFragment : MainFragment() {
recyclerData.lastLoad.getNowDiffSeconds() > 60 ) {
recyclerData.lastLoad = OffsetDateTime.now();
if(StateSubscriptions.instance.getOldestUpdateTime().getNowDiffMinutes() > 5 && Settings.instance.subscriptions.fetchOnTabOpen)
if(StateSubscriptions.instance.getOldestUpdateTime().getNowDiffMinutes() > 5 && Settings.instance.subscriptions.fetchOnTabOpen) {
loadResults(false);
}
else if(recyclerData.results.size == 0) {
loadCache();
setLoading(false);
@@ -198,7 +202,7 @@ class SubscriptionsFeedFragment : MainFragment() {
private var _bypassRateLimit = false;
private val _lastExceptions: List<Throwable>? = null;
private val _taskGetPager = TaskHandler<Boolean, IPager<IPlatformContent>>({StateApp.instance.scope}, { withRefresh ->
val group = _subGroup;
val group = subGroup;
if(!_bypassRateLimit) {
val subRequestCounts = StateSubscriptions.instance.getSubscriptionRequestCount(group);
val reqCountStr = subRequestCounts.map { " ${it.key.config.name}: ${it.value}/${it.key.getSubscriptionRateLimit()}" }.joinToString("\n");
@@ -258,6 +262,11 @@ class SubscriptionsFeedFragment : MainFragment() {
}
};
fun selectSubgroup(g: SubscriptionGroup?) {
if(g != null)
_subscriptionBar?.selectGroup(g);
}
private fun initializeToolbarContent() {
_subscriptionBar = SubscriptionBar(context).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
@@ -267,11 +276,17 @@ class SubscriptionsFeedFragment : MainFragment() {
if(g is SubscriptionGroup.Add)
UISlideOverlays.showCreateSubscriptionGroup(_overlayContainer);
else {
_subGroup = g;
subGroup = g;
setProgress(0, 0);
if(Settings.instance.subscriptions.fetchOnTabOpen)
if(Settings.instance.subscriptions.fetchOnTabOpen) {
loadCache();
loadResults(false);
else loadCache();
}
else if(g != null && StateSubscriptions.instance.getFeed(g.id) != null) {
loadResults(false);
}
else
loadCache();
}
};
_subscriptionBar?.onHoldGroup?.subscribe { g ->
@@ -312,7 +327,7 @@ class SubscriptionsFeedFragment : MainFragment() {
override fun filterResults(results: List<IPlatformContent>): List<IPlatformContent> {
val nowSoon = OffsetDateTime.now().plusMinutes(5);
val filterGroup = _subGroup;
val filterGroup = subGroup;
return results.filter {
val allowedContentType = _filterSettings.allowContentTypes.contains(if(it.contentType == ContentType.NESTED_VIDEO || it.contentType == ContentType.LOCKED) ContentType.MEDIA else it.contentType);
@@ -447,6 +447,10 @@ class VideoDetailView : ConstraintLayout {
updateMoreButtons();
_channelButton.setOnClickListener {
if (video is TutorialFragment.TutorialVideo) {
return@setOnClickListener
}
(video?.author ?: _searchVideo?.author)?.let {
fragment.navigate<ChannelFragment>(it);
fragment.lifecycleScope.launch {
@@ -1140,6 +1144,7 @@ class VideoDetailView : ConstraintLayout {
if(videoDetail is VideoLocal) {
videoLocal = videoDetail;
video = videoDetail;
this.video = video;
val videoTask = StatePlatform.instance.getContentDetails(videoDetail.url);
videoTask.invokeOnCompletion { ex ->
if(ex != null) {
@@ -51,10 +51,16 @@ class StateSubscriptions {
val global: CentralizedFeed = CentralizedFeed();
val feeds: HashMap<String, CentralizedFeed> = hashMapOf();
val onFeedProgress = Event3<String, Int, Int>();
val onFeedProgress = Event3<String?, Int, Int>();
val onSubscriptionsChanged = Event2<List<Subscription>, Boolean>();
init {
global.onUpdateProgress.subscribe { progress, total ->
onFeedProgress.emit(null, progress, total);
}
}
fun getOldestUpdateTime(): OffsetDateTime {
val subs = getSubscriptions();
if(subs.size == 0)
@@ -15,6 +15,7 @@ import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.constructs.Event2
import com.futo.platformplayer.constructs.TaskHandler
import com.futo.platformplayer.debug.Stopwatch
import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.states.StatePlatform
import com.futo.platformplayer.video.PlayerManager
@@ -46,7 +47,7 @@ class PreviewContentListAdapter : InsertedViewAdapterWithLoader<ContentPreviewVi
val contentDetails = StatePlatform.instance.getContentDetails(video.url).await();
stopwatch.logAndNext(TAG, "Retrieving video detail (IO thread)")
return@TaskHandler Pair(viewHolder, contentDetails)
}).success { previewContentDetails(it.first, it.second) }
}).exception<Throwable> { Logger.e(TAG, "Failed to retrieve preview content.", it) }.success { previewContentDetails(it.first, it.second) }
constructor(context: Context, feedStyle : FeedStyle, dataSet: ArrayList<IPlatformContent>, exoPlayer: PlayerManager? = null,
initialPlay: Boolean = false, viewsToPrepend: ArrayList<View> = arrayListOf(),
@@ -3,45 +3,31 @@ package com.futo.platformplayer.views.adapters.viewholders
import android.graphics.Color
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.FrameLayout
import android.widget.TextView
import com.futo.platformplayer.R
import com.futo.platformplayer.api.media.PlatformID
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
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.models.SubscriptionGroup
import com.futo.platformplayer.polycentric.PolycentricCache
import com.futo.platformplayer.selectBestImage
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.views.adapters.AnyAdapter
import com.futo.platformplayer.views.others.CreatorThumbnail
import com.futo.polycentric.core.toURLInfoSystemLinkUrl
import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.shape.CornerFamily
import com.google.android.material.shape.ShapeAppearanceModel
class SubscriptionGroupBarViewHolder(private val _viewGroup: ViewGroup) : AnyAdapter.AnyViewHolder<SubscriptionGroup>(
LayoutInflater.from(_viewGroup.context).inflate(R.layout.view_subscription_group_bar, _viewGroup, false)) {
private var _group: SubscriptionGroup? = null;
private val _root: FrameLayout;
private val _image: ShapeableImageView;
private val _textSubGroup: TextView;
val onClick = Event1<SubscriptionGroup>();
val onClickLong = Event1<SubscriptionGroup>();
init {
_root = _view.findViewById(R.id.root);
_image = _view.findViewById(R.id.image);
_textSubGroup = _view.findViewById(R.id.text_sub_group);
val dp6 = 6.dp(_view.resources);
_image.shapeAppearanceModel = ShapeAppearanceModel.builder()
.setAllCorners(CornerFamily.ROUNDED, dp6.toFloat())
.build()
_view.setOnClickListener {
_group?.let {
onClick.emit(it);
@@ -58,9 +44,9 @@ class SubscriptionGroupBarViewHolder(private val _viewGroup: ViewGroup) : AnyAda
override fun bind(value: SubscriptionGroup) {
_group = value;
val img = value.image;
if(img != null)
if(img != null) {
img.setImageView(_image)
else {
} else {
_image.setImageResource(0);
if(value is SubscriptionGroup.Add)
@@ -68,10 +54,11 @@ class SubscriptionGroupBarViewHolder(private val _viewGroup: ViewGroup) : AnyAda
}
_textSubGroup.text = value.name;
if(value is SubscriptionGroup.Selectable && value.selected)
_view.setBackgroundColor(_view.context.resources.getColor(R.color.colorPrimary, null));
else
_view.setBackgroundColor(_view.context.resources.getColor(R.color.transparent, null));
if (value is SubscriptionGroup.Selectable && value.selected) {
_root.setBackgroundResource(R.drawable.background_primary_round_6dp)
} else {
_root.background = null
}
}
companion object {
@@ -1,52 +1,25 @@
package com.futo.platformplayer.views.overlays
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.shapes.Shape
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.activity.result.contract.ActivityResultContracts
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.net.toFile
import androidx.core.net.toUri
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.futo.platformplayer.PresetImages
import com.futo.platformplayer.R
import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.activities.IWithResultLauncher
import com.futo.platformplayer.activities.MainActivity
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
import com.futo.platformplayer.constructs.Event0
import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.dp
import com.futo.platformplayer.models.ImageVariable
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.states.StateSubscriptions
import com.futo.platformplayer.views.AnyAdapterView
import com.futo.platformplayer.views.AnyAdapterView.Companion.asAny
import com.futo.platformplayer.views.SearchView
import com.futo.platformplayer.views.adapters.AnyAdapter
import com.futo.platformplayer.views.adapters.viewholders.CreatorBarViewHolder
import com.futo.platformplayer.views.adapters.viewholders.SelectableCreatorBarViewHolder
import com.futo.platformplayer.views.buttons.BigButton
import com.github.dhaval2404.imagepicker.ImagePicker
import com.google.android.flexbox.FlexboxLayout
import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.shape.CornerFamily
import com.google.android.material.shape.ShapeAppearanceModel
import java.io.File
class CreatorSelectOverlay: ConstraintLayout {
private val _buttonSelect: Button;
private val _buttonSelect: FrameLayout;
private val _topbar: OverlayTopbar;
private val _searchBar: SearchView;
@@ -97,7 +70,7 @@ class CreatorSelectOverlay: ConstraintLayout {
this.orientation = LinearLayoutManager.VERTICAL;
};
_buttonSelect.setOnClickListener {
_selected?.let {
if (_selected.isNotEmpty()) {
select();
}
};
@@ -112,8 +85,18 @@ class CreatorSelectOverlay: ConstraintLayout {
}
fun updateSelected() {
_creators.forEach { p -> p.active = _selected.contains(p.channel.url) };
_recyclerCreators.notifyContentChanged();
val changed = arrayListOf<SelectableCreatorBarViewHolder.Selectable>()
for(creator in _creators) {
val act = _selected.contains(creator.channel.url);
if(creator.active != act) {
creator.active = act;
changed.add(creator);
}
}
for(change in changed) {
val index = _creatorsFiltered.indexOf(change);
_recyclerCreators.notifyContentChanged(index);
}
if(_selected.isNotEmpty())
_buttonSelect.alpha = 1f;
@@ -124,7 +107,7 @@ class CreatorSelectOverlay: ConstraintLayout {
private fun filterCreators(withUpdate: Boolean = true) {
val query = _searchBar.textSearch.text.toString().lowercase();
val filteredEnabled = _creators.filter { query.isNullOrEmpty() || it.channel.name.lowercase().contains(query) };
val filteredEnabled = _creators.filter { query.isEmpty() || it.channel.name.lowercase().contains(query) };
//Optimize
_creatorsFiltered.clear();
@@ -11,6 +11,7 @@ import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.net.toFile
@@ -48,7 +49,7 @@ class ImageVariableOverlay: ConstraintLayout {
private val _buttonGallery: BigButton;
private val _imageGallerySelected: ImageView;
private val _imageGallerySelectedContainer: LinearLayout;
private val _buttonSelect: Button;
private val _buttonSelect: TextView;
private val _topbar: OverlayTopbar;
private val _recyclerPresets: AnyAdapterView<PresetImage, PresetViewHolder>;
private val _recyclerCreators: AnyAdapterView<SelectableCreatorBarViewHolder.Selectable, SelectableCreatorBarViewHolder>;
@@ -88,6 +88,13 @@ class SubscriptionBar : LinearLayout {
updateExplore();
}
fun selectGroup(group: SubscriptionGroup) {
val relevantGroup = _groups.find { it.id == group.id };
if(relevantGroup != null && _group != relevantGroup) {
groupClicked(relevantGroup);
}
}
private fun groupClicked(g: SubscriptionGroup) {
if(g is SubscriptionGroup.Add) {
onToggleGroup.emit(g);
@@ -1,6 +1,9 @@
package com.futo.platformplayer.views.video
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
@@ -11,6 +14,9 @@ import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
import androidx.media3.ui.PlayerControlView
import androidx.media3.ui.PlayerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.futo.platformplayer.R
import com.futo.platformplayer.Settings
import com.futo.platformplayer.api.media.models.streams.sources.IAudioSource
@@ -39,6 +45,14 @@ class FutoThumbnailPlayer : FutoVideoPlayerBase {
//Events
private val _evMuteChanged = mutableListOf<(FutoThumbnailPlayer, Boolean)->Unit>();
private val _loadArtwork = object: CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
setArtwork(BitmapDrawable(resources, resource));
}
override fun onLoadCleared(placeholder: Drawable?) {
setArtwork(null);
}
}
@OptIn(UnstableApi::class)
@@ -113,11 +127,38 @@ class FutoThumbnailPlayer : FutoVideoPlayerBase {
}
fun setPreview(video: IPlatformVideoDetails) {
val videoSource = VideoHelper.selectBestVideoSource(video.video, Settings.instance.playback.getPreferredPreviewQualityPixelCount(), PREFERED_VIDEO_CONTAINERS);
val audioSource = VideoHelper.selectBestAudioSource(video.video, PREFERED_AUDIO_CONTAINERS, Settings.instance.playback.getPrimaryLanguage(context));
setSource(videoSource, audioSource,true, false);
if (video.live != null) {
setSource(video.live, null,true, false);
} else {
val videoSource = VideoHelper.selectBestVideoSource(video.video, Settings.instance.playback.getPreferredPreviewQualityPixelCount(), PREFERED_VIDEO_CONTAINERS);
val audioSource = VideoHelper.selectBestAudioSource(video.video, PREFERED_AUDIO_CONTAINERS, Settings.instance.playback.getPrimaryLanguage(context));
if (videoSource == null && audioSource != null) {
val thumbnail = video.thumbnails.getHQThumbnail();
if (!thumbnail.isNullOrBlank()) {
Glide.with(videoView).asBitmap().load(thumbnail).into(_loadArtwork);
} else {
Glide.with(videoView).clear(_loadArtwork);
setArtwork(null);
}
} else {
Glide.with(videoView).clear(_loadArtwork);
}
setSource(videoSource, audioSource,true, false);
}
}
override fun onSourceChanged(videoSource: IVideoSource?, audioSource: IAudioSource?, resume: Boolean) {
}
@OptIn(UnstableApi::class)
fun setArtwork(drawable: Drawable?) {
if (drawable != null) {
videoView.defaultArtwork = drawable;
videoView.artworkDisplayMode = PlayerView.ARTWORK_DISPLAY_MODE_FILL;
} else {
videoView.defaultArtwork = null;
videoView.artworkDisplayMode = PlayerView.ARTWORK_DISPLAY_MODE_OFF;
}
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#99000000" />
<corners android:radius="6dp" />
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#2D63ED" />
<corners android:radius="6dp" />
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M481.54,685.39Q494.85,685.39 503.96,676.27Q513.08,667.15 513.08,653.85Q513.08,640.54 503.96,631.42Q494.85,622.31 481.54,622.31Q468.23,622.31 459.11,631.42Q450,640.54 450,653.85Q450,667.15 459.11,676.27Q468.23,685.39 481.54,685.39ZM460.92,552.92L499.54,552.92Q501.08,526.15 509.46,510.31Q517.85,494.46 541.54,470.77Q570.39,441.92 583.35,420.73Q596.31,399.54 596.31,372.61Q596.31,325.77 564.15,297.11Q532,268.46 485.61,268.46Q442.92,268.46 412.11,291.23Q381.31,314 367.08,345.85L403.85,361.08Q413.92,337.15 432.61,321.42Q451.31,305.69 483.15,305.69Q520.92,305.69 539.31,326.35Q557.69,347 557.69,373.31Q557.69,393.39 546.69,410.08Q535.69,426.77 515.85,445.15Q483.61,474.92 472.27,498.73Q460.92,522.54 460.92,552.92ZM224.62,800Q197,800 178.5,781.5Q160,763 160,735.39L160,224.61Q160,197 178.5,178.5Q197,160 224.62,160L735.39,160Q763,160 781.5,178.5Q800,197 800,224.61L800,735.39Q800,763 781.5,781.5Q763,800 735.39,800L224.62,800ZM224.62,760L735.39,760Q744.61,760 752.31,752.31Q760,744.61 760,735.39L760,224.61Q760,215.39 752.31,207.69Q744.61,200 735.39,200L224.62,200Q215.38,200 207.69,207.69Q200,215.39 200,224.61L200,735.39Q200,744.61 207.69,752.31Q215.38,760 224.62,760ZM200,200L200,200Q200,200 200,206.92Q200,213.85 200,224.61L200,735.39Q200,746.15 200,753.08Q200,760 200,760L200,760Q200,760 200,753.08Q200,746.15 200,735.39L200,224.61Q200,213.85 200,206.92Q200,200 200,200Z"/>
</vector>
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M481.54,685.39Q494.85,685.39 503.96,676.27Q513.08,667.15 513.08,653.85Q513.08,640.54 503.96,631.42Q494.85,622.31 481.54,622.31Q468.23,622.31 459.11,631.42Q450,640.54 450,653.85Q450,667.15 459.11,676.27Q468.23,685.39 481.54,685.39ZM460.92,552.92L499.54,552.92Q501.08,526.15 509.46,510.31Q517.85,494.46 541.54,470.77Q570.39,441.92 583.35,420.73Q596.31,399.54 596.31,372.61Q596.31,325.77 564.15,297.11Q532,268.46 485.61,268.46Q442.92,268.46 412.11,291.23Q381.31,314 367.08,345.85L403.85,361.08Q413.92,337.15 432.61,321.42Q451.31,305.69 483.15,305.69Q520.92,305.69 539.31,326.35Q557.69,347 557.69,373.31Q557.69,393.39 546.69,410.08Q535.69,426.77 515.85,445.15Q483.61,474.92 472.27,498.73Q460.92,522.54 460.92,552.92ZM224.62,800Q197,800 178.5,781.5Q160,763 160,735.39L160,224.61Q160,197 178.5,178.5Q197,160 224.62,160L735.39,160Q763,160 781.5,178.5Q800,197 800,224.61L800,735.39Q800,763 781.5,781.5Q763,800 735.39,800L224.62,800Z"/>
</vector>
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M459.39,744.61L498.61,744.61L498.61,697.69Q541.69,694.08 581.15,666.77Q620.61,639.46 620.61,582Q620.61,540 595.08,510.39Q569.54,480.77 497.54,454.77Q431.39,431.69 413,415.15Q394.61,398.61 394.61,368Q394.61,337.39 418.5,317Q442.39,296.61 482,296.61Q512.46,296.61 532.77,310.58Q553.08,324.54 565.69,346L600.46,332.31Q586.39,303.46 559.19,284Q532,264.54 500.61,262.31L500.61,215.39L461.39,215.39L461.39,262.31Q409.08,271 382.23,301.31Q355.39,331.61 355.39,368Q355.39,411.15 382.5,437.08Q409.61,463 474,486.31Q538.54,510.08 560.73,529.23Q582.92,548.39 582.92,582Q582.92,624.23 552.11,642.81Q521.31,661.39 486,661.39Q451.46,661.39 423.65,641.27Q395.85,621.15 379.23,584L344,599.23Q361.08,640.31 389.81,663.27Q418.54,686.23 459.39,695.69L459.39,744.61ZM480,840Q405.46,840 339.77,811.58Q274.08,783.15 225.46,734.54Q176.85,685.92 148.42,620.23Q120,554.54 120,480Q120,405.46 148.42,339.77Q176.85,274.08 225.46,225.46Q274.08,176.85 339.77,148.42Q405.46,120 480,120Q554.54,120 620.23,148.42Q685.92,176.85 734.54,225.46Q783.15,274.08 811.58,339.77Q840,405.46 840,480Q840,554.54 811.58,620.23Q783.15,685.92 734.54,734.54Q685.92,783.15 620.23,811.58Q554.54,840 480,840Z"/>
</vector>
+10
View File
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M120,640L120,560L440,560L440,640L120,640ZM120,480L120,400L600,400L600,480L120,480ZM120,320L120,240L600,240L600,320L120,320ZM640,840L640,520L880,680L640,840Z"/>
</vector>
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M540,581.54Q552.39,581.54 561.81,572.11Q571.23,562.69 571.23,550.31Q571.23,537.92 561.81,528.5Q552.39,519.08 540,519.08Q527.61,519.08 518.19,528.5Q508.77,537.92 508.77,550.31Q508.77,562.69 518.19,572.11Q527.61,581.54 540,581.54ZM522.31,468.92L557.69,468.92Q559.23,443.77 565.62,431.04Q572,418.31 596.31,395.54Q621.69,372.46 631.69,354.35Q641.69,336.23 641.69,312.77Q641.69,272.39 612.89,245.42Q584.08,218.46 540,218.46Q506.69,218.46 480.81,236.46Q454.92,254.46 441.39,285.54L473.85,299.85Q485.15,276.39 501.42,264.65Q517.69,252.92 540,252.92Q568.61,252.92 587.46,269.89Q606.31,286.85 606.31,313.69Q606.31,330 597.15,344.04Q588,358.08 565.69,377.85Q540.39,399.92 531.35,418.35Q522.31,436.77 522.31,468.92ZM324.61,680Q297,680 278.5,661.5Q260,643 260,615.39L260,184.61Q260,157 278.5,138.5Q297,120 324.61,120L755.39,120Q783,120 801.5,138.5Q820,157 820,184.61L820,615.39Q820,643 801.5,661.5Q783,680 755.39,680L324.61,680ZM204.62,800Q177,800 158.5,781.5Q140,763 140,735.39L140,264.61L180,264.61L180,735.39Q180,744.62 187.69,752.31Q195.38,760 204.62,760L675.39,760L675.39,800L204.62,800Z"/>
</vector>
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M405.38,840L390.92,724.31Q371.77,718.54 349.5,706.15Q327.23,693.77 311.61,679.62L204.92,725L130.31,595L222.54,525.46Q220.77,514.61 219.62,503.11Q218.46,491.61 218.46,480.77Q218.46,470.69 219.62,459.58Q220.77,448.46 222.54,434.54L130.31,365L204.92,236.54L310.85,281.15Q328.77,266.23 349.61,254.23Q370.46,242.23 390.15,235.69L405.38,120L554.62,120L569.08,236.46Q592.08,244.54 609.73,255Q627.39,265.46 646.08,281.15L755.08,236.54L829.69,365L734.39,436.85Q737.69,449.23 738.08,459.58Q738.46,469.92 738.46,480Q738.46,489.31 737.69,499.65Q736.92,510 734.15,524.69L827.92,595L753.31,725L646.08,678.85Q627.39,694.54 608.46,705.77Q589.54,717 569.08,723.54L554.62,840L405.38,840ZM478.92,580Q520.77,580 549.85,550.92Q578.92,521.85 578.92,480Q578.92,438.15 549.85,409.08Q520.77,380 478.92,380Q436.85,380 407.88,409.08Q378.92,438.15 378.92,480Q378.92,521.85 407.88,550.92Q436.85,580 478.92,580Z"/>
</vector>
@@ -81,43 +81,38 @@
<TextView
android:id="@+id/text_remembered_devices"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_weight="3"
android:layout_height="wrap_content"
android:text="@string/remembered_devices"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:textSize="14dp"
android:ellipsize="end"
android:textColor="@color/white"
android:maxLines="1"
android:fontFamily="@font/inter_regular" />
<Button
<ImageButton
android:id="@+id/button_scan_qr"
android:layout_width="0dp"
android:layout_weight="1.7"
android:layout_height="wrap_content"
android:text="@string/scan_qr"
android:textSize="14dp"
android:textAlignment="center"
android:layout_marginEnd="2dp"
android:ellipsize="end"
android:maxLines="1"
android:fontFamily="@font/inter_regular"
android:textColor="@color/colorPrimary"
android:background="@color/transparent" />
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_qr"
app:tint="@color/primary" />
<Button
<Space android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<ImageButton
android:id="@+id/button_add"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/add"
android:textSize="14dp"
android:textAlignment="textEnd"
android:layout_marginEnd="2dp"
android:ellipsize="end"
android:maxLines="1"
android:fontFamily="@font/inter_regular"
android:textColor="@color/colorPrimary"
android:background="@color/transparent" />
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_add"
app:tint="@color/primary"
android:layout_marginEnd="20dp"/>
</LinearLayout>
<LinearLayout
@@ -180,20 +180,28 @@
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/container_top"
app:layout_constraintBottom_toTopOf="@id/button_creator_add"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:paddingTop="10dp"
android:paddingBottom="10dp" />
<Button
<FrameLayout
android:id="@+id/button_creator_add"
android:layout_width="match_parent"
android:background="@drawable/background_button_primary"
android:layout_height="50dp"
android:layout_margin="10dp"
app:layout_constraintBottom_toBottomOf="parent"
android:text="Add Creator" />
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="@font/inter_regular"
android:text="@string/add_creator"
android:textSize="16dp"
android:layout_gravity="center"
android:gravity="center" />
</FrameLayout>
<FrameLayout
android:id="@+id/overlay"
@@ -128,7 +128,7 @@
android:layout_marginTop="2dp"
android:gravity="top"
android:orientation="horizontal"
android:paddingBottom="5dp">
android:paddingBottom="0dp">
<com.futo.platformplayer.views.others.CreatorThumbnail
android:id="@+id/creator_thumbnail"
@@ -179,6 +179,7 @@
android:gravity="center_vertical"
android:maxLines="1"
android:textColor="@color/gray_e0"
android:layout_marginBottom="5dp"
android:textSize="12dp"
tools:text="57K views • 1 day ago" />
</LinearLayout>
@@ -140,37 +140,22 @@
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp">
<ImageButton
android:id="@+id/button_add_to_queue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="1dp"
android:paddingTop="7dp"
android:paddingStart="6dp"
android:paddingEnd="5dp"
android:paddingBottom="3dp"
app:srcCompat="@drawable/ic_queue_16dp"
android:background="@drawable/edit_text_background"
android:contentDescription="@string/add_to_queue"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<LinearLayout
android:id="@+id/button_add_to"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="27dp"
android:orientation="horizontal"
android:background="@drawable/edit_text_background"
android:layout_marginStart="4dp"
android:gravity="center_vertical"
android:padding="4dp"
app:layout_constraintLeft_toRightOf="@id/button_add_to_queue"
android:padding="5dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
app:srcCompat="@drawable/ic_add_white_8dp"
android:background="@color/transparent"
android:layout_marginStart="4dp"
android:contentDescription="@string/options" />
@@ -185,6 +170,23 @@
android:layout_marginEnd="4dp"/>
</LinearLayout>
<ImageButton
android:id="@+id/button_add_to_queue"
android:layout_width="wrap_content"
android:layout_height="27dp"
android:src="@drawable/ic_queue"
android:paddingTop="4dp"
android:paddingBottom="2dp"
android:paddingLeft="10dp"
android:paddingRight="7dp"
android:layout_marginLeft="7dp"
android:scaleType="fitCenter"
android:background="@drawable/edit_text_background"
android:contentDescription="@string/add_to_queue"
app:layout_constraintLeft_toRightOf="@id/button_add_to"
app:layout_constraintBottom_toBottomOf="parent" />
<TextView
android:id="@+id/text_video_name"
android:layout_width="fill_parent"
@@ -195,8 +197,9 @@
android:textSize="13dp"
android:textColor="@color/white"
android:fontFamily="@font/inter_light"
tools:text="Legendary grant recipient: Marvin Wißfeld of MicroG Very loong title"
tools:text="Legendary grant recipient: Marvin Wißfeld of MicroG Very loong title fff"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent" />
@@ -174,37 +174,23 @@
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp">
<ImageButton
android:id="@+id/button_add_to_queue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="1dp"
android:paddingTop="7dp"
android:paddingStart="6dp"
android:paddingEnd="5dp"
android:paddingBottom="3dp"
app:srcCompat="@drawable/ic_queue_16dp"
android:background="@drawable/edit_text_background"
android:contentDescription="@string/add_to_queue"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<LinearLayout
android:id="@+id/button_add_to"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="27dp"
android:orientation="horizontal"
android:background="@drawable/edit_text_background"
android:layout_marginStart="4dp"
android:gravity="center_vertical"
android:padding="4dp"
app:layout_constraintLeft_toRightOf="@id/button_add_to_queue"
android:padding="5dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
app:srcCompat="@drawable/ic_add_white_8dp"
android:background="@color/transparent"
android:layout_marginStart="4dp"
android:contentDescription="@string/options" />
@@ -219,6 +205,23 @@
android:layout_marginEnd="4dp"/>
</LinearLayout>
<ImageButton
android:id="@+id/button_add_to_queue"
android:layout_width="wrap_content"
android:layout_height="27dp"
android:src="@drawable/ic_queue"
android:paddingTop="4dp"
android:paddingBottom="2dp"
android:paddingLeft="10dp"
android:paddingRight="7dp"
android:layout_marginLeft="7dp"
android:scaleType="fitCenter"
android:background="@drawable/edit_text_background"
android:contentDescription="@string/add_to_queue"
app:layout_constraintLeft_toRightOf="@id/button_add_to"
app:layout_constraintBottom_toBottomOf="parent" />
<TextView
android:id="@+id/text_video_name"
android:layout_width="fill_parent"
@@ -28,25 +28,32 @@
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/search_bar"
app:layout_constraintBottom_toTopOf="@id/container_select"
app:layout_constraintBottom_toTopOf="@id/button_select"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
</androidx.recyclerview.widget.RecyclerView>
<LinearLayout
android:id="@+id/container_select"
<FrameLayout
android:id="@+id/button_select"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="50dp"
android:background="@drawable/background_button_primary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<Button
android:id="@+id/button_select"
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/background_button_primary"
android:text="Select" />
</LinearLayout>
android:layout_height="match_parent"
android:fontFamily="@font/inter_regular"
android:text="@string/select"
android:textSize="16dp"
android:gravity="center"
android:layout_gravity="center" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -116,20 +116,29 @@
</LinearLayout>
</ScrollView>
<LinearLayout
<FrameLayout
android:id="@+id/container_select"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="50dp"
android:background="@drawable/background_button_primary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<Button
<TextView
android:id="@+id/button_select"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/background_button_primary"
android:text="Select" />
</LinearLayout>
android:layout_height="match_parent"
android:fontFamily="@font/inter_regular"
android:text="@string/select"
android:textSize="16dp"
android:gravity="center"
android:layout_gravity="center" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -107,7 +107,7 @@
android:id="@id/exo_progress"
android:layout_width="match_parent"
android:layout_height="16dp"
android:layout_marginBottom="-1dp"
android:layout_marginBottom="-2dp"
android:paddingStart="0dp"
app:scrubber_drawable="@drawable/player_thumb"
app:bar_height="2dp"
+4 -1
View File
@@ -4,7 +4,10 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:orientation="vertical"
android:id="@+id/root">
@@ -1,36 +1,38 @@
<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"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="78dp"
android:layout_height="54dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:gravity="center_horizontal"
android:padding="2dp"
android:layout_margin="2dp"
android:clickable="true"
android:id="@+id/root">
android:id="@+id/root"
android:background="@drawable/background_primary_round_6dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/xp_book" />
<LinearLayout
android:src="@drawable/xp_book"
app:shapeAppearanceOverlay="@style/roundedCorners_6dp"
android:layout_margin="2dp" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#99000000"
android:gravity="center">
<TextView
android:id="@+id/text_sub_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:maxLines="2"
android:ellipsize="end"
android:textSize="12dp"
android:textAlignment="center"
android:text="News" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
android:background="@drawable/background_dark_round_6dp"
android:gravity="center"
android:layout_margin="2dp" />
<TextView
android:id="@+id/text_sub_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:maxLines="2"
android:ellipsize="end"
android:textSize="12dp"
android:textAlignment="center"
android:layout_gravity="center"
tools:text="News" />
</FrameLayout>
+2
View File
@@ -724,6 +724,8 @@
<string name="position">Position</string>
<string name="tutorials">Tutorials</string>
<string name="do_you_want_to_see_the_tutorials_you_can_find_them_at_any_time_through_the_more_button">Do you want to see the tutorials? You can find them at any time through the more button.</string>
<string name="add_creator">Add Creators</string>
<string name="select">Select</string>
<string-array name="home_screen_array">
<item>Recommendations</item>
<item>Subscriptions</item>
+4
View File
@@ -11,6 +11,10 @@
<item name="cornerFamily">rounded</item>
<item name="cornerSize">4dp</item>
</style>
<style name="roundedCorners_6dp" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">6dp</item>
</style>
<style name="roundedCorners_10dp" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">10dp</item>