mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-20 03:24:50 +00:00
WIP views
This commit is contained in:
parent
5d7dc1fdcb
commit
27eb5aa6e1
13 changed files with 829 additions and 2 deletions
|
@ -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) {
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
9
app/src/main/res/drawable/ic_gallery.xml
Normal file
9
app/src/main/res/drawable/ic_gallery.xml
Normal 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>
|
BIN
app/src/main/res/drawable/xp_book.jpg
Normal file
BIN
app/src/main/res/drawable/xp_book.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
194
app/src/main/res/layout/fragment_subscriptions_group.xml
Normal file
194
app/src/main/res/layout/fragment_subscriptions_group.xml
Normal 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>
|
115
app/src/main/res/layout/overlay_image_variable.xml
Normal file
115
app/src/main/res/layout/overlay_image_variable.xml
Normal 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>
|
32
app/src/main/res/layout/view_search_bar.xml
Normal file
32
app/src/main/res/layout/view_search_bar.xml
Normal 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>
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue