mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-20 03:24:50 +00:00
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.
This commit is contained in:
parent
84e3373fa7
commit
6f7304f59c
12 changed files with 288 additions and 26 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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 = "";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
Loading…
Add table
Reference in a new issue