mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-18 19:23:40 +00:00
Fix some layout stuff with replies
This commit is contained in:
parent
d9ab565b5f
commit
b9b669af7c
@ -1,12 +1,9 @@
|
||||
# Current
|
||||
|
||||
- [ ] Refactor
|
||||
- Split out Note pieces
|
||||
- Move global modals to child components?
|
||||
- Combine app/agent, rename app2
|
||||
- Some elements bleed through reply image modal
|
||||
- DM view pushes user back to the bottom
|
||||
- note.replies might be empty in note detail pre-load
|
||||
- [ ] Improve topic suggestions and rendering
|
||||
- [ ] Add topic search
|
||||
- [ ] Relays bounty
|
||||
|
@ -31,6 +31,7 @@
|
||||
export let invertColors = false
|
||||
|
||||
let reply = null
|
||||
let replyIsActive = false
|
||||
let actions = null
|
||||
let visibleNotes = []
|
||||
let collapsed = false
|
||||
@ -106,123 +107,140 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<div bind:this={noteContainer} class="note group relative">
|
||||
<Card class="relative flex gap-4" on:click={onClick} {interactive} {invertColors}>
|
||||
{#if !showParent}
|
||||
<div class={`absolute -ml-4 h-px w-4 bg-${borderColor} z-10`} style="left: 0px; top: 27px;" />
|
||||
{/if}
|
||||
<div>
|
||||
<Anchor class="text-lg font-bold" href={routes.person($author.pubkey)}>
|
||||
<PersonCircle size={10} person={$author} />
|
||||
</Anchor>
|
||||
</div>
|
||||
<div class="flex min-w-0 flex-grow flex-col gap-2">
|
||||
<div class="flex flex-col items-start justify-between sm:flex-row sm:items-center">
|
||||
<Popover triggerType={isMobile ? "click" : "mouseenter"}>
|
||||
<div slot="trigger">
|
||||
<Anchor
|
||||
type="unstyled"
|
||||
class="flex items-center gap-2 pr-16 text-lg font-bold sm:pr-0"
|
||||
href={isMobile ? null : routes.person($author.pubkey)}>
|
||||
<span>{displayPerson($author)}</span>
|
||||
{#if $author.verified_as}
|
||||
<i class="fa fa-circle-check text-sm text-accent" />
|
||||
{/if}
|
||||
</Anchor>
|
||||
</div>
|
||||
<div slot="tooltip">
|
||||
<PersonSummary pubkey={$author.pubkey} />
|
||||
</div>
|
||||
</Popover>
|
||||
<Anchor
|
||||
href={"/" + nip19.neventEncode({id: note.id, relays: note.seen_on})}
|
||||
class="text-sm text-gray-1"
|
||||
type="unstyled">
|
||||
{timestamp}
|
||||
<div class="note">
|
||||
<div bind:this={noteContainer} class="group relative">
|
||||
<Card class="relative flex gap-4" on:click={onClick} {interactive} {invertColors}>
|
||||
{#if !showParent}
|
||||
<div
|
||||
class={`absolute -ml-4 h-px w-4 bg-${borderColor} z-10`}
|
||||
style="left: 0px; top: 27px;" />
|
||||
{/if}
|
||||
<div>
|
||||
<Anchor class="text-lg font-bold" href={routes.person($author.pubkey)}>
|
||||
<PersonCircle size={10} person={$author} />
|
||||
</Anchor>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">
|
||||
{#if findReplyId(note) && showParent}
|
||||
<small class="text-gray-1">
|
||||
<i class="fa fa-code-merge" />
|
||||
<Anchor on:click={goToParent}>View Parent</Anchor>
|
||||
</small>
|
||||
{/if}
|
||||
{#if findRootId(note) && findRootId(note) !== findReplyId(note) && showParent}
|
||||
<small class="text-gray-1">
|
||||
<i class="fa fa-code-pull-request" />
|
||||
<Anchor on:click={goToRoot}>View Thread</Anchor>
|
||||
</small>
|
||||
{/if}
|
||||
<div class="flex min-w-0 flex-grow flex-col gap-2">
|
||||
<div class="flex flex-col items-start justify-between sm:flex-row sm:items-center">
|
||||
<Popover triggerType={isMobile ? "click" : "mouseenter"}>
|
||||
<div slot="trigger">
|
||||
<Anchor
|
||||
type="unstyled"
|
||||
class="flex items-center gap-2 pr-16 text-lg font-bold sm:pr-0"
|
||||
href={isMobile ? null : routes.person($author.pubkey)}>
|
||||
<span>{displayPerson($author)}</span>
|
||||
{#if $author.verified_as}
|
||||
<i class="fa fa-circle-check text-sm text-accent" />
|
||||
{/if}
|
||||
</Anchor>
|
||||
</div>
|
||||
<div slot="tooltip">
|
||||
<PersonSummary pubkey={$author.pubkey} />
|
||||
</div>
|
||||
</Popover>
|
||||
<Anchor
|
||||
href={"/" + nip19.neventEncode({id: note.id, relays: note.seen_on})}
|
||||
class="text-sm text-gray-1"
|
||||
type="unstyled">
|
||||
{timestamp}
|
||||
</Anchor>
|
||||
</div>
|
||||
{#if muted}
|
||||
<p class="border-l-2 border-solid border-gray-6 pl-4 text-gray-1">
|
||||
You have muted this note.
|
||||
</p>
|
||||
{:else}
|
||||
<NoteContent {note} {showEntire} />
|
||||
{/if}
|
||||
<NoteActions
|
||||
bind:this={actions}
|
||||
{note}
|
||||
{author}
|
||||
{reply}
|
||||
{muted}
|
||||
{setFeedRelay}
|
||||
{showEntire} />
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">
|
||||
{#if findReplyId(note) && showParent}
|
||||
<small class="text-gray-1">
|
||||
<i class="fa fa-code-merge" />
|
||||
<Anchor on:click={goToParent}>View Parent</Anchor>
|
||||
</small>
|
||||
{/if}
|
||||
{#if findRootId(note) && findRootId(note) !== findReplyId(note) && showParent}
|
||||
<small class="text-gray-1">
|
||||
<i class="fa fa-code-pull-request" />
|
||||
<Anchor on:click={goToRoot}>View Thread</Anchor>
|
||||
</small>
|
||||
{/if}
|
||||
</div>
|
||||
{#if muted}
|
||||
<p class="border-l-2 border-solid border-gray-6 pl-4 text-gray-1">
|
||||
You have muted this note.
|
||||
</p>
|
||||
{:else}
|
||||
<NoteContent {note} {showEntire} />
|
||||
{/if}
|
||||
<NoteActions
|
||||
bind:this={actions}
|
||||
{note}
|
||||
{reply}
|
||||
{author}
|
||||
{muted}
|
||||
{setFeedRelay}
|
||||
{showEntire} />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{#if !replyIsActive && visibleNotes.length > 0 && !showEntire && depth > 0 && !muted}
|
||||
<div class="relative">
|
||||
<div
|
||||
class="absolute top-0 right-0 z-10 -mt-4 -mr-2 flex h-6 w-6 cursor-pointer items-center
|
||||
justify-center rounded-full border border-solid border-gray-7 bg-gray-8 text-gray-3"
|
||||
on:click={() => {
|
||||
collapsed = !collapsed
|
||||
}}>
|
||||
<Popover triggerType="mouseenter">
|
||||
<div slot="trigger">
|
||||
{#if collapsed}
|
||||
<i class="fa fa-xs fa-up-right-and-down-left-from-center" />
|
||||
{:else}
|
||||
<i class="fa fa-xs fa-down-left-and-up-right-to-center" />
|
||||
{/if}
|
||||
</div>
|
||||
<div slot="tooltip">
|
||||
{collapsed ? "Show replies" : "Hide replies"}
|
||||
</div>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
{/if}
|
||||
|
||||
<NoteReply
|
||||
bind:this={reply}
|
||||
on:start={() => {
|
||||
replyIsActive = true
|
||||
}}
|
||||
on:reset={() => {
|
||||
replyIsActive = false
|
||||
}}
|
||||
{note}
|
||||
{borderColor} />
|
||||
|
||||
{#if !collapsed && visibleNotes.length > 0 && depth > 0 && !muted}
|
||||
<div class="relative mt-4">
|
||||
<div class={`absolute w-px bg-${borderColor} z-10 -mt-4 ml-4 h-0`} bind:this={border} />
|
||||
<div class="note-children relative ml-8 flex flex-col gap-4" bind:this={childrenContainer}>
|
||||
{#if !showEntire && note.replies.length > visibleNotes.length}
|
||||
<button class="ml-5 cursor-pointer py-2 text-gray-1 outline-0" on:click={onClick}>
|
||||
<i class="fa fa-up-down pr-2 text-sm" />
|
||||
Show {quantify(
|
||||
note.replies.length - visibleNotes.length,
|
||||
"other reply",
|
||||
"more replies"
|
||||
)}
|
||||
</button>
|
||||
{/if}
|
||||
{#each visibleNotes as r (r.id)}
|
||||
<svelte:self
|
||||
showParent={false}
|
||||
note={r}
|
||||
depth={depth - 1}
|
||||
{feedRelay}
|
||||
{setFeedRelay}
|
||||
{invertColors}
|
||||
{anchorId}
|
||||
{showContext} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<NoteReply bind:this={reply} {note} {borderColor} />
|
||||
|
||||
{#if !reply?.isActive() && visibleNotes.length > 0 && !showEntire && depth > 0 && !muted}
|
||||
<div class="relative -mt-4">
|
||||
<div
|
||||
class="absolute top-0 right-0 z-10 -mt-4 -mr-2 flex h-6 w-6 cursor-pointer items-center
|
||||
justify-center rounded-full border border-solid border-gray-7 bg-gray-8 text-gray-3"
|
||||
on:click={() => {
|
||||
collapsed = !collapsed
|
||||
}}>
|
||||
<Popover triggerType="mouseenter">
|
||||
<div slot="trigger">
|
||||
{#if collapsed}
|
||||
<i class="fa fa-xs fa-up-right-and-down-left-from-center" />
|
||||
{:else}
|
||||
<i class="fa fa-xs fa-down-left-and-up-right-to-center" />
|
||||
{/if}
|
||||
</div>
|
||||
<div slot="tooltip">
|
||||
{collapsed ? "Show replies" : "Hide replies"}
|
||||
</div>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !collapsed && visibleNotes.length > 0 && depth > 0 && !muted}
|
||||
<div class="relative">
|
||||
<div class={`absolute w-px bg-${borderColor} z-10 -mt-4 ml-4 h-0`} bind:this={border} />
|
||||
<div class="note-children relative ml-8 flex flex-col gap-4" bind:this={childrenContainer}>
|
||||
{#if !showEntire && note.replies.length > visibleNotes.length}
|
||||
<button class="ml-5 cursor-pointer py-2 text-gray-1" on:click={onClick}>
|
||||
<i class="fa fa-up-down pr-2 text-sm" />
|
||||
Show {quantify(note.replies.length - visibleNotes.length, "other reply", "more replies")}
|
||||
</button>
|
||||
{/if}
|
||||
{#each visibleNotes as r (r.id)}
|
||||
<svelte:self
|
||||
showParent={false}
|
||||
note={r}
|
||||
depth={depth - 1}
|
||||
{feedRelay}
|
||||
{setFeedRelay}
|
||||
{invertColors}
|
||||
{anchorId}
|
||||
{showContext} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -2,7 +2,7 @@
|
||||
import {objOf, reverse} from "ramda"
|
||||
import {navigate} from "svelte-routing"
|
||||
import {fly} from "svelte/transition"
|
||||
import {splice} from 'hurdak/lib/hurdak'
|
||||
import {splice} from "hurdak/lib/hurdak"
|
||||
import {warn} from "src/util/logger"
|
||||
import {displayPerson, parseContent, Tags} from "src/util/nostr"
|
||||
import MediaSet from "src/partials/MediaSet.svelte"
|
||||
@ -38,7 +38,7 @@
|
||||
(type === "link" && !value.startsWith("ws")) ||
|
||||
["nostr:note", "nostr:nevent"].includes(type)
|
||||
) {
|
||||
if (type === 'link') {
|
||||
if (type === "link") {
|
||||
links.push(value)
|
||||
} else {
|
||||
entities.push({type, value})
|
||||
@ -72,11 +72,11 @@
|
||||
// Truncate content if needed
|
||||
let l = 0
|
||||
if (shouldTruncate) {
|
||||
for (const i in content) {
|
||||
for (let i = 0; i < content.length; i++) {
|
||||
const prev = content[i - 1]
|
||||
|
||||
// Avoid adding an ellipsis right after a newline
|
||||
if (l > truncateAt && prev?.type != 'newline') {
|
||||
if (l > truncateAt && prev?.type != "newline") {
|
||||
content = content.slice(0, i).concat({type: "text", value: "..."})
|
||||
|
||||
break
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {nip19} from "nostr-tools"
|
||||
import {createEventDispatcher} from "svelte"
|
||||
import {without, pluck, uniq} from "ramda"
|
||||
import {slide} from "svelte/transition"
|
||||
import {Tags, displayPerson} from "src/util/nostr"
|
||||
@ -16,13 +17,15 @@
|
||||
export let note
|
||||
export let borderColor
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let data = null
|
||||
let reply = null
|
||||
let container = null
|
||||
|
||||
export const isActive = () => Boolean(reply)
|
||||
|
||||
export const start = () => {
|
||||
dispatch("start")
|
||||
|
||||
data = {
|
||||
image: null,
|
||||
mentions: without(
|
||||
@ -33,6 +36,8 @@
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
dispatch("reset")
|
||||
|
||||
data = null
|
||||
reply = null
|
||||
}
|
||||
@ -90,7 +95,7 @@
|
||||
{#if data}
|
||||
<div
|
||||
transition:slide
|
||||
class="note-reply relative z-10 flex flex-col gap-1"
|
||||
class="note-reply relative z-10 my-2 flex flex-col gap-1"
|
||||
bind:this={container}
|
||||
on:click|stopPropagation>
|
||||
<div class={`border border-${borderColor} rounded border-solid`}>
|
||||
|
Loading…
Reference in New Issue
Block a user