From 6f7304f59c019b0f0d528ac3782f46bdbc2492e2 Mon Sep 17 00:00:00 2001 From: Koen <koen@pop-os.localdomain> Date: Mon, 15 Jan 2024 18:06:57 +0100 Subject: [PATCH] Added ability to click on a comment to view where the comment was placed and the ability to navigate upwards in the replies overlay by clicking the parent comment. --- .../platformplayer/activities/MainActivity.kt | 4 +- .../comments/PolycentricPlatformComment.kt | 7 +- .../platformplayer/dialogs/CommentDialog.kt | 3 +- .../mainactivity/main/CommentsFragment.kt | 12 ++ .../mainactivity/main/VideoDetailFragment.kt | 6 +- .../platformplayer/states/StatePolycentric.kt | 78 ++++++++- .../CommentWithReferenceViewHolder.kt | 6 + .../views/overlays/RepliesOverlay.kt | 164 +++++++++++++++++- .../views/segments/CommentsList.kt | 9 +- app/src/main/res/layout/fragment_comments.xml | 9 +- app/src/main/res/layout/overlay_loader.xml | 3 +- app/src/main/res/layout/overlay_replies.xml | 13 +- 12 files changed, 288 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt index c37f882a..b1f74e13 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt @@ -810,11 +810,9 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { if(_fragBotBarMenu.onBackPressed()) return; - if(_fragVideoDetail.state == VideoDetailFragment.State.MAXIMIZED && - _fragVideoDetail.onBackPressed()) + if(_fragVideoDetail.state == VideoDetailFragment.State.MAXIMIZED && _fragVideoDetail.onBackPressed()) return; - if(!fragCurrent.onBackPressed()) closeSegment(); } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/comments/PolycentricPlatformComment.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/comments/PolycentricPlatformComment.kt index 90a65e00..c45bdfeb 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/models/comments/PolycentricPlatformComment.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/models/comments/PolycentricPlatformComment.kt @@ -19,8 +19,9 @@ class PolycentricPlatformComment : IPlatformComment { val eventPointer: Pointer; val reference: Reference; + val parentReference: Reference?; - constructor(contextUrl: String, author: PlatformAuthorLink, msg: String, rating: IRating, date: OffsetDateTime, eventPointer: Pointer, replyCount: Int? = null) { + constructor(contextUrl: String, author: PlatformAuthorLink, msg: String, rating: IRating, date: OffsetDateTime, eventPointer: Pointer, parentReference: Reference?, replyCount: Int? = null) { this.contextUrl = contextUrl; this.author = author; this.message = msg; @@ -29,6 +30,7 @@ class PolycentricPlatformComment : IPlatformComment { this.replyCount = replyCount; this.eventPointer = eventPointer; this.reference = eventPointer.toReference(); + this.parentReference = parentReference; } override fun getReplies(client: IPlatformClient): IPager<IPlatformComment> { @@ -36,10 +38,11 @@ class PolycentricPlatformComment : IPlatformComment { } fun cloneWithUpdatedReplyCount(replyCount: Int?): PolycentricPlatformComment { - return PolycentricPlatformComment(contextUrl, author, message, rating, date, eventPointer, replyCount); + return PolycentricPlatformComment(contextUrl, author, message, rating, date, eventPointer, parentReference, replyCount); } companion object { + private const val TAG = "PolycentricPlatformComment" val MAX_COMMENT_SIZE = 2000 } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/dialogs/CommentDialog.kt b/app/src/main/java/com/futo/platformplayer/dialogs/CommentDialog.kt index f369f481..580bd508 100644 --- a/app/src/main/java/com/futo/platformplayer/dialogs/CommentDialog.kt +++ b/app/src/main/java/com/futo/platformplayer/dialogs/CommentDialog.kt @@ -123,7 +123,8 @@ class CommentDialog(context: Context?, val contextUrl: String, val ref: Protocol msg = comment, rating = RatingLikeDislikes(0, 0), date = OffsetDateTime.now(), - eventPointer = eventPointer + eventPointer = eventPointer, + parentReference = ref )); dismiss(); diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CommentsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CommentsFragment.kt index c81ac8de..b2f548b7 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CommentsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/CommentsFragment.kt @@ -117,6 +117,7 @@ class CommentsFragment : MainFragment() { val holder = CommentWithReferenceViewHolder(viewGroup, _cache); holder.onDelete.subscribe(::onDelete); holder.onRepliesClick.subscribe(::onRepliesClick); + holder.onClick.subscribe(::onClick); return@InsertedViewAdapterWithLoader holder; } ); @@ -200,6 +201,17 @@ class CommentsFragment : MainFragment() { return false } + private fun onClick(c: IPlatformComment) { + if (c !is PolycentricPlatformComment) { + return + } + + val parentRef = c.parentReference + if (parentRef != null && _repliesOverlay.handleParentClick(c.contextUrl, parentRef)) { + setRepliesOverlayVisible(true, true) + } + } + private fun onRepliesClick(c: IPlatformComment) { val replyCount = c.replyCount ?: 0; var metadata = ""; diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt index 48783233..ddb21815 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt @@ -169,14 +169,14 @@ class VideoDetailFragment : MainFragment { _view!!.transitionToStart(); } fun maximizeVideoDetail(instant: Boolean = false) { - if(_maximizeProgress > 0.9f && state != State.MAXIMIZED) { + if((_maximizeProgress > 0.9f || instant) && state != State.MAXIMIZED) { state = State.MAXIMIZED; onMaximized.emit(); } _view?.let { - if(!instant) + if(!instant) { it.transitionToEnd(); - else { + } else { it.progress = 1f; onTransitioning.emit(true); } diff --git a/app/src/main/java/com/futo/platformplayer/states/StatePolycentric.kt b/app/src/main/java/com/futo/platformplayer/states/StatePolycentric.kt index 984c6b4f..b81b08c0 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StatePolycentric.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StatePolycentric.kt @@ -48,6 +48,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking import userpackage.Protocol +import userpackage.Protocol.Reference import java.time.Instant import java.time.OffsetDateTime import java.time.ZoneOffset @@ -287,7 +288,8 @@ class StatePolycentric { rating = RatingLikeDislikes(0, 0), date = if (ev.unixMilliseconds != null) Instant.ofEpochMilli(ev.unixMilliseconds!!).atOffset(ZoneOffset.UTC) else OffsetDateTime.MIN, replyCount = 0, - eventPointer = se.toPointer() + eventPointer = se.toPointer(), + parentReference = se.event.references.getOrNull(0) )) } @@ -328,6 +330,77 @@ class StatePolycentric { return LikesDislikesReplies(likes, dislikes, replyCount) } + suspend fun getComment(contextUrl: String, reference: Reference): PolycentricPlatformComment { + ensureEnabled() + + if (reference.referenceType != 2L) { + throw Exception("Not a pointer") + } + + val pointer = Protocol.Pointer.parseFrom(reference.reference) + val events = ApiMethods.getEvents(PolycentricCache.SERVER, pointer.system, Protocol.RangesForSystem.newBuilder() + .addRangesForProcesses(Protocol.RangesForProcess.newBuilder() + .setProcess(pointer.process) + .addRanges(Protocol.Range.newBuilder() + .setLow(pointer.logicalClock) + .setHigh(pointer.logicalClock) + .build()) + .build()) + .build()) + + val sev = SignedEvent.fromProto(events.getEvents(0)) + val ev = sev.event + + if (ev.contentType != ContentType.POST.value) { + throw Exception("This is not a comment") + } + + val post = Protocol.Post.parseFrom(ev.content); + val systemLinkUrl = ev.system.systemToURLInfoSystemLinkUrl(listOf(PolycentricCache.SERVER)); + val dp_25 = 25.dp(StateApp.instance.context.resources) + + val profileEvents = ApiMethods.getQueryLatest( + PolycentricCache.SERVER, + ev.system.toProto(), + listOf( + ContentType.AVATAR.value, + ContentType.USERNAME.value + ) + ).eventsList.map { e -> SignedEvent.fromProto(e) }.groupBy { e -> e.event.contentType } + .map { (_, events) -> events.maxBy { x -> x.event.unixMilliseconds ?: 0 } }; + + val nameEvent = profileEvents.firstOrNull { e -> e.event.contentType == ContentType.USERNAME.value }; + val avatarEvent = profileEvents.firstOrNull { e -> e.event.contentType == ContentType.AVATAR.value }; + val imageBundle = if (avatarEvent != null) { + val lwwElementValue = avatarEvent.event.lwwElement?.value; + if (lwwElementValue != null) { + Protocol.ImageBundle.parseFrom(lwwElementValue) + } else { + null + } + } else { + null + } + + val ldr = getLikesDislikesReplies(reference) + return PolycentricPlatformComment( + contextUrl = contextUrl, + author = PlatformAuthorLink( + id = PlatformID("polycentric", systemLinkUrl, null, ClaimType.POLYCENTRIC.value.toInt()), + name = nameEvent?.event?.lwwElement?.value?.decodeToString() ?: "Unknown", + url = systemLinkUrl, + thumbnail = imageBundle?.selectBestImage(dp_25 * dp_25)?.let { img -> img.toURLInfoSystemLinkUrl(ev.system.toProto(), img.process, listOf(PolycentricCache.SERVER)) }, + subscribers = null + ), + msg = if (post.content.count() > PolycentricPlatformComment.MAX_COMMENT_SIZE) post.content.substring(0, PolycentricPlatformComment.MAX_COMMENT_SIZE) else post.content, + rating = RatingLikeDislikes(ldr.likes, ldr.dislikes), + date = if (ev.unixMilliseconds != null) Instant.ofEpochMilli(ev.unixMilliseconds!!).atOffset(ZoneOffset.UTC) else OffsetDateTime.MIN, + replyCount = ldr.replyCount.toInt(), + eventPointer = sev.toPointer(), + parentReference = sev.event.references.getOrNull(0) + ) + } + suspend fun getCommentPager(contextUrl: String, reference: Protocol.Reference, extraByteReferences: List<ByteArray>? = null): IPager<IPlatformComment> { if (!enabled) { return EmptyPager() @@ -453,7 +526,8 @@ class StatePolycentric { rating = RatingLikeDislikes(likes, dislikes), date = if (unixMilliseconds != null) Instant.ofEpochMilli(unixMilliseconds).atOffset(ZoneOffset.UTC) else OffsetDateTime.MIN, replyCount = replies.toInt(), - eventPointer = sev.toPointer() + eventPointer = sev.toPointer(), + parentReference = sev.event.references.getOrNull(0) ); } catch (e: Throwable) { return@mapNotNull null; diff --git a/app/src/main/java/com/futo/platformplayer/views/adapters/CommentWithReferenceViewHolder.kt b/app/src/main/java/com/futo/platformplayer/views/adapters/CommentWithReferenceViewHolder.kt index f1fc07da..6b40bbb2 100644 --- a/app/src/main/java/com/futo/platformplayer/views/adapters/CommentWithReferenceViewHolder.kt +++ b/app/src/main/java/com/futo/platformplayer/views/adapters/CommentWithReferenceViewHolder.kt @@ -55,6 +55,7 @@ class CommentWithReferenceViewHolder : ViewHolder { var onRepliesClick = Event1<IPlatformComment>(); var onDelete = Event1<IPlatformComment>(); + var onClick = Event1<IPlatformComment>(); var comment: IPlatformComment? = null private set; @@ -108,6 +109,11 @@ class CommentWithReferenceViewHolder : ViewHolder { onDelete.emit(c); } + _layoutComment.setOnClickListener { + val c = comment ?: return@setOnClickListener; + onClick.emit(c); + } + _textBody.setPlatformPlayerLinkMovementMethod(viewGroup.context); } diff --git a/app/src/main/java/com/futo/platformplayer/views/overlays/RepliesOverlay.kt b/app/src/main/java/com/futo/platformplayer/views/overlays/RepliesOverlay.kt index 4d2a7fb9..19c5dd22 100644 --- a/app/src/main/java/com/futo/platformplayer/views/overlays/RepliesOverlay.kt +++ b/app/src/main/java/com/futo/platformplayer/views/overlays/RepliesOverlay.kt @@ -1,6 +1,7 @@ package com.futo.platformplayer.views.overlays import android.content.Context +import android.net.Uri import android.util.AttributeSet import android.view.View import android.widget.LinearLayout @@ -8,11 +9,15 @@ import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import com.futo.platformplayer.R import com.futo.platformplayer.UIDialogs +import com.futo.platformplayer.activities.MainActivity +import com.futo.platformplayer.api.http.ManagedHttpClient import com.futo.platformplayer.api.media.models.comments.IPlatformComment import com.futo.platformplayer.api.media.models.comments.PolycentricPlatformComment import com.futo.platformplayer.api.media.structures.IPager import com.futo.platformplayer.constructs.Event0 import com.futo.platformplayer.fixHtmlLinks +import com.futo.platformplayer.logging.Logger +import com.futo.platformplayer.states.StateApp import com.futo.platformplayer.states.StatePlatform import com.futo.platformplayer.states.StatePolycentric import com.futo.platformplayer.toHumanNowDiffString @@ -20,6 +25,13 @@ import com.futo.platformplayer.views.behavior.NonScrollingTextView import com.futo.platformplayer.views.comments.AddCommentView import com.futo.platformplayer.views.others.CreatorThumbnail import com.futo.platformplayer.views.segments.CommentsList +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import userpackage.Protocol class RepliesOverlay : LinearLayout { @@ -34,7 +46,11 @@ class RepliesOverlay : LinearLayout { private val _creatorThumbnail: CreatorThumbnail; private val _layoutParentComment: ConstraintLayout; private var _readonly = false; + private var _loading = true; + private var _parentComment: IPlatformComment? = null; private var _onCommentAdded: ((comment: IPlatformComment) -> Unit)? = null; + private val _loaderOverlay: LoaderOverlay + private val _client = ManagedHttpClient() constructor(context: Context, attrs: AttributeSet? = null) : super(context, attrs) { inflate(context, R.layout.overlay_replies, this) @@ -46,6 +62,8 @@ class RepliesOverlay : LinearLayout { _textAuthor = findViewById(R.id.text_author) _creatorThumbnail = findViewById(R.id.image_thumbnail) _layoutParentComment = findViewById(R.id.layout_parent_comment) + _loaderOverlay = findViewById(R.id.loader_overlay) + setLoading(false); _addCommentView.onCommentAdded.subscribe { _commentsList.addComment(it); @@ -72,11 +90,21 @@ class RepliesOverlay : LinearLayout { } }; + _layoutParentComment.setOnClickListener { + val p = _parentComment + if (p !is PolycentricPlatformComment) { + return@setOnClickListener + } + + val ref = p.parentReference ?: return@setOnClickListener + handleParentClick(p.contextUrl, ref) + } + _topbar.onClose.subscribe(this, onClose::emit); _topbar.setInfo(context.getString(R.string.Replies), ""); } - fun load(readonly: Boolean, metadata: String, contextUrl: String?, ref: Protocol.Reference?, parentComment: IPlatformComment? = null, loader: suspend () -> IPager<IPlatformComment>, onCommentAdded: ((comment: IPlatformComment) -> Unit)? = null) { + fun load(readonly: Boolean, metadata: String, contextUrl: String?, ref: Protocol.Reference?, parentComment: IPlatformComment? = null, loader: suspend () -> IPager<IPlatformComment>, onCommentAdded: ((comment: IPlatformComment) -> Unit)? = null, onParentClick: ((comment: IPlatformComment) -> Unit)? = null) { _readonly = readonly; if (readonly) { _addCommentView.visibility = View.GONE; @@ -109,6 +137,136 @@ class RepliesOverlay : LinearLayout { _topbar.setInfo(context.getString(R.string.Replies), metadata); _commentsList.load(readonly, loader); _onCommentAdded = onCommentAdded; + _parentComment = parentComment; + } + + fun handleParentClick(contextUrl: String, ref: Protocol.Reference): Boolean { + val ctx = context + if (ctx !is MainActivity) { + return false + } + + return when (ref.referenceType) { + 2L -> { + setLoading(true) + + StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { + try { + val parentComment = StatePolycentric.instance.getComment(contextUrl, ref) + val replyCount = parentComment.replyCount ?: 0; + var metadata = ""; + if (replyCount > 0) { + metadata += "$replyCount " + context.getString(R.string.replies); + } + + withContext(Dispatchers.Main) { + setLoading(false) + + load(false, metadata, parentComment.contextUrl, parentComment.reference, parentComment, + { StatePolycentric.instance.getCommentPager(contextUrl, ref) }) + } + } catch (e: Throwable) { + withContext(Dispatchers.Main) { + setLoading(false) + } + + Logger.e(TAG, "Failed to load parent comment.", e) + UIDialogs.toast("Failed to load comment") + } + } + + true + } + 3L -> { + StateApp.instance.scopeOrNull?.launch { + try { + val url = referenceToUrl(_client, ref) ?: return@launch + withContext(Dispatchers.Main) { + ctx.handleUrl(url) + onClose.emit() + } + } catch (e: Throwable) { + Logger.i(TAG, "Failed to open ref.", e) + } + } + + false + } + else -> false + } + } + + private fun referenceToUrl(client: ManagedHttpClient, parentRef: Protocol.Reference): String? { + val refBytes = parentRef.reference?.toByteArray() ?: return null + val ref = refBytes.decodeToString() + + try { + Uri.parse(ref) + return ref + } catch (e: Throwable) { + try { + return oldReferenceToUrl(client, ref) + } catch (f: Throwable) { + Logger.i(TAG, "Failed to handle URL.", f) + } + } + + return null + } + + private fun oldReferenceToUrl(client: ManagedHttpClient, reference: String): String? { + return when { + reference.startsWith("video_episode:") -> { + val response = client.get("https://content.api.nebula.app/video_episodes/$reference") + if (!response.isOk) { + throw Exception("Failed to resolve nebula video (${response.code}).") + } + + val respString = response.body?.string() + val jsonElement = respString?.let { Json.parseToJsonElement(it) } + return jsonElement?.jsonObject?.get("share_url")?.jsonPrimitive?.content + } + + reference.length == 11 -> "https://www.youtube.com/watch?v=$reference" + + reference.length == 40 -> { + val response = client.post("https://api.na-backend.odysee.com/api/v1/proxy?m=claim_search", hashMapOf( + "Content-Type" to "application/json" + )) + + if (!response.isOk) { + throw Exception("Failed to resolve claim (${response.code}).") + } + + val jsonElement = response.body?.string()?.let { Json.parseToJsonElement(it) } + val canonicalUrl = jsonElement?.jsonObject?.get("result") + ?.jsonObject?.get("items") + ?.jsonArray?.get(0) + ?.jsonObject?.get("canonical_url") + ?.jsonPrimitive?.content + + canonicalUrl ?: throw Exception("Failed to get canonical URL.") + } + + reference.startsWith("v") && (reference.length == 7 || reference.length == 6) -> "https://rumble.com/$reference" + + Regex("^\\d+\$").matches(reference) -> "https://www.twitch.tv/videos/$reference" + + else -> null + } + } + + private fun setLoading(loading: Boolean) { + if (_loading == loading) { + return; + } + + _loading = loading; + if (!loading) { + _loaderOverlay.hide() + } else { + _loaderOverlay.show() + } } fun cleanup() { @@ -116,4 +274,8 @@ class RepliesOverlay : LinearLayout { _onCommentAdded = null; _commentsList.cancel(); } + + companion object { + private const val TAG = "RepliesOverlay" + } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/views/segments/CommentsList.kt b/app/src/main/java/com/futo/platformplayer/views/segments/CommentsList.kt index e02205b7..57732acb 100644 --- a/app/src/main/java/com/futo/platformplayer/views/segments/CommentsList.kt +++ b/app/src/main/java/com/futo/platformplayer/views/segments/CommentsList.kt @@ -4,7 +4,6 @@ import android.content.Context import android.graphics.Color import android.util.AttributeSet import android.view.Gravity -import android.view.KeyCharacterMap.UnavailableException import android.view.LayoutInflater import android.view.View import android.widget.FrameLayout @@ -12,10 +11,8 @@ import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.futo.platformplayer.logging.Logger -import com.futo.platformplayer.UIDialogs import com.futo.platformplayer.R -import com.futo.platformplayer.states.StateApp +import com.futo.platformplayer.UIDialogs import com.futo.platformplayer.api.media.models.comments.IPlatformComment import com.futo.platformplayer.api.media.models.comments.PolycentricPlatformComment import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails @@ -25,6 +22,8 @@ import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.TaskHandler import com.futo.platformplayer.engine.exceptions.ScriptUnavailableException import com.futo.platformplayer.fullyBackfillServersAnnounceExceptions +import com.futo.platformplayer.logging.Logger +import com.futo.platformplayer.states.StateApp import com.futo.platformplayer.states.StatePolycentric import com.futo.platformplayer.views.adapters.CommentViewHolder import com.futo.platformplayer.views.adapters.InsertedViewAdapterWithLoader @@ -87,8 +86,6 @@ class CommentsList : ConstraintLayout { var onRepliesClick = Event1<IPlatformComment>(); var onCommentsLoaded = Event1<Int>(); - - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { LayoutInflater.from(context).inflate(R.layout.view_comments_list, this, true); diff --git a/app/src/main/res/layout/fragment_comments.xml b/app/src/main/res/layout/fragment_comments.xml index 0e49ff19..29fe4c04 100644 --- a/app/src/main/res/layout/fragment_comments.xml +++ b/app/src/main/res/layout/fragment_comments.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + xmlns:app="http://schemas.android.com/apk/res-auto"> <LinearLayout android:id="@+id/layout_header" @@ -65,7 +65,8 @@ android:id="@+id/replies_overlay" android:visibility="gone" android:layout_width="match_parent" - android:layout_height="match_parent" /> + android:layout_height="match_parent" + android:clickable="true" /> <LinearLayout android:id="@+id/layout_not_logged_in" android:layout_width="match_parent" diff --git a/app/src/main/res/layout/overlay_loader.xml b/app/src/main/res/layout/overlay_loader.xml index c16a6bda..dafc34c6 100644 --- a/app/src/main/res/layout/overlay_loader.xml +++ b/app/src/main/res/layout/overlay_loader.xml @@ -8,7 +8,8 @@ android:orientation="vertical" android:id="@+id/container" android:background="#77000000" - android:elevation="4dp"> + android:elevation="4dp" + android:clickable="true"> <ImageView android:id="@+id/loader" android:layout_width="80dp" diff --git a/app/src/main/res/layout/overlay_replies.xml b/app/src/main/res/layout/overlay_replies.xml index c683b38a..51bb4b4c 100644 --- a/app/src/main/res/layout/overlay_replies.xml +++ b/app/src/main/res/layout/overlay_replies.xml @@ -50,7 +50,7 @@ android:textSize="14sp" app:layout_constraintLeft_toRightOf="@id/image_thumbnail" app:layout_constraintTop_toTopOf="@id/image_thumbnail" - android:text="ShortCircuit" /> + tools:text="ShortCircuit" /> <TextView android:id="@+id/text_metadata" @@ -66,7 +66,7 @@ app:layout_constraintLeft_toRightOf="@id/text_author" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="@id/text_author" - android:text=" • 3 years ago" /> + tools:text=" • 3 years ago" /> <com.futo.platformplayer.views.behavior.NonScrollingTextView android:id="@+id/text_body" @@ -84,7 +84,7 @@ app:layout_constraintTop_toBottomOf="@id/text_metadata" app:layout_constraintLeft_toRightOf="@id/image_thumbnail" app:layout_constraintRight_toRightOf="parent" - android:text="@string/lorem_ipsum" /> + tools:text="@string/lorem_ipsum" /> </androidx.constraintlayout.widget.ConstraintLayout> @@ -107,4 +107,11 @@ app:layout_constraintBottom_toBottomOf="parent" android:layout_marginTop="12dp" /> + <com.futo.platformplayer.views.overlays.LoaderOverlay + android:id="@+id/loader_overlay" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:clickable="true" /> + </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file -- GitLab