WIP views

This commit is contained in:
Kelvin 2023-12-12 22:20:38 +01:00
parent 5d7dc1fdcb
commit 27eb5aa6e1
13 changed files with 829 additions and 2 deletions

View file

@ -46,7 +46,7 @@ class UISlideOverlays {
companion object {
private const val TAG = "UISlideOverlays";
fun showOverlay(container: ViewGroup, title: String, okButton: String?, onOk: ()->Unit, vararg views: View) {
fun showOverlay(container: ViewGroup, title: String, okButton: String?, onOk: ()->Unit, vararg views: View): SlideUpMenuOverlay {
var menu = SlideUpMenuOverlay(container.context, container, title, okButton, true, *views);
menu.onOK.subscribe {
@ -54,6 +54,7 @@ class UISlideOverlays {
onOk.invoke();
};
menu.show();
return menu;
}
fun showSubscriptionOptionsOverlay(subscription: Subscription, container: ViewGroup) {

View file

@ -0,0 +1,211 @@
package com.futo.platformplayer.fragment.mainactivity.main
import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
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.recyclerview.widget.RecyclerView
import com.futo.platformplayer.R
import com.futo.platformplayer.UISlideOverlays
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
import com.futo.platformplayer.models.Subscription
import com.futo.platformplayer.models.SubscriptionGroup
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.adapters.AnyAdapter
import com.futo.platformplayer.views.adapters.viewholders.CreatorBarViewHolder
import com.futo.platformplayer.views.overlays.ImageVariableOverlay
import com.futo.platformplayer.views.overlays.slideup.SlideUpMenuTextInput
import com.google.android.material.imageview.ShapeableImageView
class SubscriptionGroupFragment : MainFragment() {
override val isMainView : Boolean = true;
override val isTab: Boolean = false;
override val hasBottomBar: Boolean get() = true;
private var _view: SubscriptionGroupView? = null;
override fun onShownWithView(parameter: Any?, isBack: Boolean) {
super.onShownWithView(parameter, isBack);
if(parameter is SubscriptionGroup)
_view?.setGroup(parameter);
else
_view?.setGroup(null);
}
override fun onCreateMainView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view = SubscriptionGroupView(requireContext(), this);
_view = view;
return view;
}
companion object {
private const val TAG = "SourcesFragment";
fun newInstance() = SubscriptionGroupFragment().apply {}
}
private class SubscriptionGroupView: ConstraintLayout {
private val _fragment: SubscriptionGroupFragment;
private val _textGroupTitleContainer: LinearLayout;
private val _textGroupTitle: TextView;
private val _imageGroup: ShapeableImageView;
private val _buttonEditImage: LinearLayout;
private val _textGroupMeta: TextView;
private val _buttonSettings: ImageView;
private val _enabledCreators: ArrayList<IPlatformChannel> = arrayListOf();
private val _disabledCreators: ArrayList<IPlatformChannel> = arrayListOf();
private val _containerEnabled: LinearLayout;
private val _containerDisabled: LinearLayout;
private val _recyclerCreatorsEnabled: AnyAdapterView<IPlatformChannel, CreatorBarViewHolder>;
private val _recyclerCreatorsDisabled: AnyAdapterView<IPlatformChannel, CreatorBarViewHolder>;
private val _overlay: FrameLayout;
private var _group: SubscriptionGroup? = null;
private val _editNameOverlayField: SlideUpMenuTextInput;
constructor(context: Context, fragment: SubscriptionGroupFragment): super(context) {
inflate(context, R.layout.fragment_subscriptions_group, this);
_fragment = fragment;
_editNameOverlayField = SlideUpMenuTextInput(context, "Group name");
_overlay = findViewById(R.id.overlay);
_textGroupTitleContainer = findViewById(R.id.text_group_title_container);
_textGroupTitle = findViewById(R.id.text_group_title);
_imageGroup = findViewById(R.id.image_group);
_buttonEditImage = findViewById(R.id.button_edit_image);
_textGroupMeta = findViewById(R.id.text_group_meta);
_buttonSettings = findViewById(R.id.button_settings);
_containerEnabled = findViewById(R.id.container_enabled);
_containerDisabled = findViewById(R.id.container_disabled);
_recyclerCreatorsEnabled = findViewById<RecyclerView>(R.id.recycler_creators_enabled).asAny(_enabledCreators) {
it.onClick.subscribe { channel ->
disableCreator(channel);
};
}
_recyclerCreatorsDisabled = findViewById<RecyclerView>(R.id.recycler_creators_disabled).asAny(_disabledCreators) {
it.onClick.subscribe { channel ->
enableCreator(channel);
};
}
_textGroupTitleContainer.setOnClickListener {
_group?.let { editName(it) };
};
_imageGroup.setOnClickListener {
_group?.let { editImage(it) };
};
_buttonEditImage.setOnClickListener {
_group?.let { editImage(it) }
};
setGroup(null);
}
fun editName(group: SubscriptionGroup) {
UISlideOverlays.showOverlay(_overlay, "Edit name", "Save", {
val text = _editNameOverlayField.text;
if(!text.isNullOrEmpty()) {
group.name = text;
_textGroupTitle.text = text;
//TODO: Save
}
}, _editNameOverlayField);
}
fun editImage(group: SubscriptionGroup) {
val overlay = ImageVariableOverlay(context);
val view = UISlideOverlays.showOverlay(_overlay, "Temp", null, {},
overlay);
overlay.onSelected.subscribe {
view.hide(true);
group.image = it;
it.setImageView(_imageGroup);
//TODO: Save
};
}
fun setGroup(group: SubscriptionGroup?) {
_group = group;
_textGroupTitle.text = group?.name;
val image = group?.image;
if(image != null)
image.setImageView(_imageGroup);
else
_imageGroup.setImageResource(0);
updateMeta();
reloadCreators(group);
}
@SuppressLint("NotifyDataSetChanged")
private fun reloadCreators(group: SubscriptionGroup?) {
_enabledCreators.clear();
_disabledCreators.clear();
if(group != null) {
val urls = group.urls.toList();
val subs = StateSubscriptions.instance.getSubscriptions().map { it.channel }
_enabledCreators.addAll(subs.filter { urls.contains(it.url) });
_disabledCreators.addAll(subs.filter { !urls.contains(it.url) });
}
}
private fun enableCreator(channel: IPlatformChannel) {
val index = _disabledCreators.indexOf(channel);
if (index >= 0) {
_disabledCreators.removeAt(index)
_recyclerCreatorsDisabled.adapter.notifyItemRangeRemoved(index);
_enabledCreators.add(channel);
_recyclerCreatorsEnabled.adapter.notifyItemInserted(_enabledCreators.size - 1);
_group?.let {
it.urls.remove(channel.url);
//TODO: Save
}
updateMeta();
}
}
private fun disableCreator(channel: IPlatformChannel) {
val index = _disabledCreators.indexOf(channel);
if (index >= 0) {
_disabledCreators.removeAt(index)
_recyclerCreatorsDisabled.adapter.notifyItemRangeRemoved(index);
_enabledCreators.add(channel);
_recyclerCreatorsEnabled.adapter.notifyItemInserted(_enabledCreators.size - 1);
_group?.let {
it.urls.remove(channel.url);
//TODO: Save
}
updateMeta();
}
}
private fun updateMeta() {
_textGroupMeta.text = "${_group?.urls?.size} creators";
}
}
}

View file

@ -5,9 +5,17 @@ import android.graphics.BitmapFactory
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.futo.platformplayer.R
import kotlinx.serialization.Contextual
import kotlinx.serialization.Transient
import java.io.File
data class ImageVariable(val url: String? = null, val resId: Int? = null, val bitmap: Bitmap? = null) {
@kotlinx.serialization.Serializable
data class ImageVariable(
val url: String? = null,
val resId: Int? = null,
@Transient
@Contextual
private val bitmap: Bitmap? = null) {
fun setImageView(imageView: ImageView, fallbackResId: Int = -1) {
if(bitmap != null) {

View file

@ -0,0 +1,15 @@
package com.futo.platformplayer.models
import java.util.UUID
@kotlinx.serialization.Serializable
class SubscriptionGroup {
val id: String = UUID.randomUUID().toString();
var name: String;
var image: ImageVariable? = null;
var urls: MutableList<String> = mutableListOf();
constructor(name: String) {
this.name = name;
}
}

View file

@ -0,0 +1,33 @@
package com.futo.platformplayer.views
import android.content.Context
import android.util.AttributeSet
import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.widget.addTextChangedListener
import com.futo.platformplayer.R
import com.futo.platformplayer.constructs.Event0
import com.futo.platformplayer.constructs.Event1
class SearchView : FrameLayout {
val textSearch: TextView;
val buttonClear: ImageButton;
var onSearchChanged = Event1<String>();
constructor(context: Context, attrs: AttributeSet? = null) : super(context, attrs) {
inflate(context, R.layout.view_search_bar, this);
textSearch = findViewById(R.id.edit_search)
buttonClear = findViewById(R.id.button_clear_search)
buttonClear.setOnClickListener { textSearch.text = "" };
textSearch.addTextChangedListener {
onSearchChanged.emit(it.toString());
};
}
}

View file

@ -0,0 +1,89 @@
package com.futo.platformplayer.views.adapters.viewholders
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.LinearLayout
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.api.media.models.channels.SerializedChannel
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.Subscription
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
class CreatorBarViewHolder(private val _viewGroup: ViewGroup) : AnyAdapter.AnyViewHolder<IPlatformChannel>(
LayoutInflater.from(_viewGroup.context).inflate(R.layout.view_subscription_bar_icon, _viewGroup, false)) {
private val _creatorThumbnail: CreatorThumbnail;
private val _name: TextView;
private var _channel: IPlatformChannel? = null;
val onClick = Event1<IPlatformChannel>();
private val _taskLoadProfile = TaskHandler<PlatformID, PolycentricCache.CachedPolycentricProfile?>(
StateApp.instance.scopeGetter,
{ PolycentricCache.instance.getProfileAsync(it) })
.success { onProfileLoaded(it, true) }
.exception<Throwable> {
Logger.w(TAG, "Failed to load profile.", it);
};
init {
_creatorThumbnail = _view.findViewById(R.id.creator_thumbnail);
_name = _view.findViewById(R.id.text_channel_name);
_view.findViewById<LinearLayout>(R.id.root).setOnClickListener {
val s = _channel ?: return@setOnClickListener;
onClick.emit(s);
}
}
override fun bind(value: IPlatformChannel) {
_taskLoadProfile.cancel();
_channel = value;
_creatorThumbnail.setThumbnail(value.thumbnail, false);
_name.text = value.name;
val cachedProfile = PolycentricCache.instance.getCachedProfile(value.url, true);
if (cachedProfile != null) {
onProfileLoaded(cachedProfile, false);
if (cachedProfile.expired) {
_taskLoadProfile.run(value.id);
}
} else {
_taskLoadProfile.run(value.id);
}
}
private fun onProfileLoaded(cachedPolycentricProfile: PolycentricCache.CachedPolycentricProfile?, animate: Boolean) {
val dp_55 = 55.dp(itemView.context.resources)
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(profile != null, animate);
}
if (profile != null) {
_name.text = profile.systemState.username;
}
}
companion object {
private const val TAG = "CreatorBarViewHolder";
}
}

View file

@ -0,0 +1,118 @@
package com.futo.platformplayer.views.overlays
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.widget.Button
import androidx.activity.result.contract.ActivityResultContracts
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.futo.platformplayer.R
import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.activities.IWithResultLauncher
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.models.ImageVariable
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.views.AnyAdapterView
import com.futo.platformplayer.views.AnyAdapterView.Companion.asAny
import com.futo.platformplayer.views.adapters.AnyAdapter
import com.futo.platformplayer.views.adapters.viewholders.CreatorBarViewHolder
import com.futo.platformplayer.views.buttons.BigButton
import com.google.android.material.imageview.ShapeableImageView
class ImageVariableOverlay: ConstraintLayout {
private val _buttonGallery: BigButton;
private val _buttonSelect: Button;
private val _recyclerPresets: AnyAdapterView<Int, PresetViewHolder>;
private val _recyclerCreators: AnyAdapterView<IPlatformChannel, CreatorBarViewHolder>;
private val _creators: ArrayList<IPlatformChannel> = arrayListOf();
private val _presets: ArrayList<Int> = arrayListOf();
private var _selected: ImageVariable? = null;
val onSelected = Event1<ImageVariable>();
constructor(context: Context): super(context) {
inflate(context, R.layout.overlay_image_variable, this);
}
constructor(context: Context, attrs: AttributeSet?): super(context, attrs) {
inflate(context, R.layout.overlay_image_variable, this);
}
init {
_buttonGallery = findViewById(R.id.button_gallery);
_buttonSelect = findViewById(R.id.button_select);
_recyclerPresets = findViewById<RecyclerView>(R.id.recycler_presets).asAny(_presets, RecyclerView.HORIZONTAL) {
it.onClick.subscribe {
_selected = ImageVariable(null, it);
updateSelected();
};
};
_recyclerCreators = findViewById<RecyclerView>(R.id.recycler_creators).asAny(_creators, RecyclerView.HORIZONTAL) { creatorView ->
creatorView.onClick.subscribe {
if(it.thumbnail == null) {
UIDialogs.toast(context, "No thumbnail found");
return@subscribe;
}
_selected = ImageVariable(it.thumbnail);
updateSelected();
};
};
_buttonGallery.setOnClickListener {
val context = StateApp.instance.contextOrNull;
if(context is IWithResultLauncher) {
val intent = Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
context.launchForResult(intent, 888) {
if(it.resultCode == 888) {
val url = it.data?.data ?: return@launchForResult;
//TODO: Write to local storage
_selected = ImageVariable(url.toString());
updateSelected();
}
};
}
};
_buttonSelect.setOnClickListener {
_selected?.let {
select(it);
}
};
}
fun updateSelected() {
if(_selected != null)
_buttonSelect.alpha = 1f;
else
_buttonSelect.alpha = 0.5f;
}
fun select(variable: ImageVariable) {
onSelected.emit(variable);
}
class PresetViewHolder(context: Context) : AnyAdapter.AnyViewHolder<Int>(ShapeableImageView(context)) {
private val view = _view as ShapeableImageView;
private var value: Int = 0;
val onClick = Event1<Int>();
init {
view.setOnClickListener {
onClick.emit(value);
}
}
override fun bind(value: Int) {
view.setImageResource(value);
this.value = value;
}
}
}

View file

@ -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="M164.62,720Q137.96,720 118.98,701.02Q100,682.04 100,655.39L100,304.61Q100,277.96 118.98,258.98Q137.96,240 164.62,240L515.39,240Q542.04,240 561.02,258.98Q580,277.96 580,304.61L580,655.39Q580,682.04 561.02,701.02Q542.04,720 515.39,720L164.62,720ZM692.69,440Q678.39,440 669.19,430.81Q660,421.61 660,407.31L660,272.69Q660,258.38 669.19,249.19Q678.39,240 692.69,240L827.31,240Q841.62,240 850.81,249.19Q860,258.38 860,272.69L860,407.31Q860,421.61 850.81,430.81Q841.62,440 827.31,440L692.69,440ZM700,400L820,400L820,280L700,280L700,400ZM164.62,680L515.39,680Q526.15,680 533.08,673.08Q540,666.15 540,655.39L540,304.61Q540,293.85 533.08,286.92Q526.15,280 515.39,280L164.62,280Q153.85,280 146.92,286.92Q140,293.85 140,304.61L140,655.39Q140,666.15 146.92,673.08Q153.85,680 164.62,680ZM187.69,596.15L492.31,596.15L395,466.15L320,566.15L265,493.15L187.69,596.15ZM692.69,720Q678.39,720 669.19,710.81Q660,701.62 660,687.31L660,552.69Q660,538.39 669.19,529.19Q678.39,520 692.69,520L827.31,520Q841.62,520 850.81,529.19Q860,538.39 860,552.69L860,687.31Q860,701.62 850.81,710.81Q841.62,720 827.31,720L692.69,720ZM700,680L820,680L820,560L700,560L700,680ZM140,680Q140,680 140,673.08Q140,666.15 140,655.39L140,304.61Q140,293.85 140,286.92Q140,280 140,280L140,280Q140,280 140,286.92Q140,293.85 140,304.61L140,655.39Q140,666.15 140,673.08Q140,680 140,680L140,680ZM700,400L700,280L700,280L700,400L700,400ZM700,680L700,560L700,560L700,680L700,680Z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View file

@ -0,0 +1,194 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:animateLayoutChanges="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#222222">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#55000000">
<ImageButton
android:id="@+id/button_settings"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_settings"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:padding="5dp"
android:background="@color/transparent"
android:scaleType="fitCenter" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/image_group"
android:layout_width="110dp"
android:layout_height="70dp"
android:adjustViewBounds="true"
app:circularflow_defaultRadius="10dp"
android:layout_marginLeft="30dp"
android:src="@drawable/xp_book"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent" />
<LinearLayout
android:id="@+id/button_edit_image"
android:layout_width="30dp"
android:layout_height="30dp"
app:layout_constraintBottom_toTopOf="@id/image_group"
app:layout_constraintLeft_toRightOf="@id/image_group"
android:layout_marginLeft="-15dp"
android:layout_marginBottom="-15dp"
android:background="@drawable/background_pill">
<ImageButton
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:scaleType="fitCenter"
android:background="@color/transparent"
android:src="@drawable/ic_edit"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@id/image_group"
app:layout_constraintTop_toTopOf="@id/image_group"
app:layout_constraintBottom_toBottomOf="@id/image_group"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginStart="25dp"
android:layout_marginTop="10dp"
android:orientation="vertical">
<LinearLayout
android:id="@+id/text_group_title_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/text_group_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/inter_bold"
android:textSize="15dp"
android:text="News" />
<ImageButton
android:layout_width="20dp"
android:layout_height="20dp"
android:padding="2dp"
android:layout_marginStart="5dp"
android:layout_marginBottom="-5dp"
android:scaleType="fitCenter"
android:background="@color/transparent"
android:src="@drawable/ic_edit"/>
</LinearLayout>
<TextView
android:id="@+id/text_group_meta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/inter_light"
android:textSize="12dp"
android:text="42 creators" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<com.futo.platformplayer.views.SearchView
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<LinearLayout
android:id="@+id/container_enabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16dp"
android:textColor="@color/white"
android:fontFamily="@font/inter_light"
android:text="@string/enabled" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12dp"
android:textColor="@color/gray_ac"
android:fontFamily="@font/inter_extra_light"
android:text="@string/these_creators_in_group" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_creators_enabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:paddingBottom="10dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/container_disabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16dp"
android:textColor="@color/white"
android:fontFamily="@font/inter_light"
android:text="@string/disabled" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12dp"
android:textColor="@color/gray_ac"
android:fontFamily="@font/inter_extra_light"
android:text="@string/these_creators_not_in_group" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_creators_disabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:paddingBottom="10dp" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
<FrameLayout
android:id="@+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/black"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.futo.platformplayer.views.overlays.OverlayTopbar
android:id="@+id/topbar"
android:layout_width="match_parent"
android:layout_height="40dp"
app:title="Select an Image"
app:metadata=""
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/topbar"
app:layout_constraintBottom_toTopOf="@id/container_select"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.futo.platformplayer.views.buttons.BigButton
android:id="@+id/button_gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:buttonIcon="@drawable/ic_gallery"
app:buttonText="Open Photo Gallery"
app:buttonSubText="Pick an image from the gallery" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/inter_regular"
android:textSize="20dp"
android:text="Preset" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:textColor="@color/gray_ac"
android:textSize="12dp"
android:text="Pick a preset image" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_presets"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/inter_regular"
android:textSize="20dp"
android:text="Creator" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:textColor="@color/gray_ac"
android:textSize="12dp"
android:text="Pick a creator as group image" />
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
</LinearLayout>
</ScrollView>
<LinearLayout
android:id="@+id/container_select"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<Button
android:id="@+id/button_select"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:text="Select" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:orientation="vertical"
android:id="@+id/root">
<EditText
android:id="@+id/edit_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:imeOptions="actionDone"
android:singleLine="true"
android:hint="Search"
android:paddingEnd="46dp" />
<ImageButton
android:id="@+id/button_clear_search"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingStart="18dp"
android:paddingEnd="18dp"
android:layout_gravity="right|center_vertical"
android:visibility="invisible"
android:src="@drawable/ic_clear_16dp" />
</FrameLayout>

View file

@ -69,6 +69,8 @@
<string name="discover">Discover</string>
<string name="find_new_video_sources_to_add">Find new video sources to add</string>
<string name="these_sources_have_been_disabled">These sources have been disabled</string>
<string name="these_creators_in_group">These are the creators that are visible for this group.</string>
<string name="these_creators_not_in_group">These creators are not in this group.</string>
<string name="disabled">Disabled</string>
<string name="watch_later">Watch Later</string>
<string name="create">Create</string>