Apply layout changes to chat
This commit is contained in:
parent
1c0b2a09df
commit
a582b1ea73
5 changed files with 177 additions and 140 deletions
|
|
@ -10,6 +10,7 @@
|
|||
* Fix nevent hints for url-specific stuff
|
||||
* Add alerts via Anchor
|
||||
* Fix confirm and reactions on mobile
|
||||
* Add reply to chat on mobile
|
||||
|
||||
# 0.2.11
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
<div class="row-2 ml-10 mt-1">
|
||||
<ReactionSummary {url} {event} {onReactionClick} reactionClass="tooltip-right" />
|
||||
</div>
|
||||
{#if !isMobile}
|
||||
<button
|
||||
class="join absolute right-1 top-1 border border-solid border-neutral text-xs opacity-0 transition-all"
|
||||
class:group-hover:opacity-100={!isMobile}>
|
||||
|
|
@ -110,4 +111,5 @@
|
|||
{/if}
|
||||
<ChannelMessageMenuButton {url} {event} />
|
||||
</button>
|
||||
{/if}
|
||||
</TapTarget>
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@
|
|||
let loading = $state(true)
|
||||
let compose: ChatCompose | undefined = $state()
|
||||
let parent: TrustedEvent | undefined = $state()
|
||||
let parentPreview: HTMLElement | undefined = $state()
|
||||
let dynamicPadding: HTMLElement | undefined = $state()
|
||||
|
||||
const elements = $derived.by(() => {
|
||||
const elements = []
|
||||
|
|
@ -104,6 +106,16 @@
|
|||
onMount(() => {
|
||||
// Don't use loadInboxRelaySelection because we want to force reload
|
||||
load({filters: [{kinds: [INBOX_RELAYS], authors: others}]})
|
||||
|
||||
const observer = new ResizeObserver(() => {
|
||||
dynamicPadding!.style.minHeight = `${parentPreview!.offsetHeight}px`
|
||||
})
|
||||
|
||||
observer.observe(parentPreview!)
|
||||
|
||||
return () => {
|
||||
observer.unobserve(parentPreview!)
|
||||
}
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
|
|
@ -111,9 +123,8 @@
|
|||
}, 5000)
|
||||
</script>
|
||||
|
||||
<div class="relative flex h-full w-full flex-col">
|
||||
{#if others.length > 0}
|
||||
<PageBar>
|
||||
{#if others.length > 0}
|
||||
<PageBar class="chat__page-bar">
|
||||
{#snippet title()}
|
||||
<div class="flex flex-col gap-1 sm:flex-row sm:gap-2">
|
||||
{#if others.length === 1}
|
||||
|
|
@ -159,8 +170,10 @@
|
|||
</div>
|
||||
{/snippet}
|
||||
</PageBar>
|
||||
{/if}
|
||||
<div class="-mt-2 flex flex-grow flex-col-reverse overflow-auto py-2">
|
||||
{/if}
|
||||
|
||||
<div class="chat__messages scroll-container">
|
||||
<div bind:this={dynamicPadding}></div>
|
||||
{#if missingInboxes.includes($pubkey!)}
|
||||
<div class="py-12">
|
||||
<div class="card2 col-2 m-auto max-w-md items-center text-center">
|
||||
|
|
@ -170,8 +183,7 @@
|
|||
</p>
|
||||
<p>
|
||||
In order to deliver messages, {PLATFORM_NAME} needs to know where to send them. Please visit
|
||||
your <Link class="link" href="/settings/relays">relay settings page</Link> to set up your
|
||||
inbox.
|
||||
your <Link class="link" href="/settings/relays">relay settings page</Link> to set up your inbox.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -201,8 +213,7 @@
|
|||
{replyTo} />
|
||||
{/if}
|
||||
{/each}
|
||||
<p
|
||||
class="m-auto flex h-10 max-w-sm flex-col items-center justify-center gap-4 py-20 text-center">
|
||||
<p class="m-auto flex h-10 max-w-sm flex-col items-center justify-center gap-4 py-20 text-center">
|
||||
<Spinner {loading}>
|
||||
{#if loading}
|
||||
Looking for messages...
|
||||
|
|
@ -212,9 +223,13 @@
|
|||
</Spinner>
|
||||
{@render info?.()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chat__compose bg-base-200">
|
||||
<div bind:this={parentPreview}>
|
||||
{#if parent}
|
||||
<ChatComposeParent event={parent} clear={clearParent} verb="Replying to" />
|
||||
{/if}
|
||||
</div>
|
||||
<ChatCompose bind:this={compose} {onSubmit} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@
|
|||
|
||||
interface Props {
|
||||
event: TrustedEvent
|
||||
replyTo?: any
|
||||
replyTo: (event: TrustedEvent) => void
|
||||
pubkeys: string[]
|
||||
showPubkey?: boolean
|
||||
}
|
||||
|
||||
const {event, replyTo = undefined, pubkeys, showPubkey = false}: Props = $props()
|
||||
const {event, replyTo, pubkeys, showPubkey = false}: Props = $props()
|
||||
|
||||
const thunk = $thunks[event.id]
|
||||
const isOwn = event.pubkey === $pubkey
|
||||
|
|
@ -40,6 +40,8 @@
|
|||
const profileDisplay = deriveProfileDisplay(event.pubkey)
|
||||
const [_, colorValue] = colors[parseInt(hash(event.pubkey)) % colors.length]
|
||||
|
||||
const reply = () => replyTo(event)
|
||||
|
||||
const onReactionClick = async (content: string, events: TrustedEvent[]) => {
|
||||
const reaction = events.find(e => e.pubkey === $pubkey)
|
||||
const template = reaction ? makeDelete({event: reaction}) : makeReaction({event, content})
|
||||
|
|
@ -49,7 +51,7 @@
|
|||
|
||||
const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey})
|
||||
|
||||
const showMobileMenu = () => pushModal(ChatMessageMenuMobile, {event, pubkeys})
|
||||
const showMobileMenu = () => pushModal(ChatMessageMenuMobile, {event, pubkeys, reply})
|
||||
|
||||
const togglePopover = () => {
|
||||
if (popoverIsVisible) {
|
||||
|
|
@ -72,6 +74,7 @@
|
|||
class:chat-start={!isOwn}
|
||||
class:flex-row-reverse={!isOwn}
|
||||
class:chat-end={isOwn}>
|
||||
{#if !isMobile}
|
||||
<Tippy
|
||||
bind:popover
|
||||
component={ChatMessageMenu}
|
||||
|
|
@ -94,9 +97,10 @@
|
|||
<Icon icon="menu-dots" size={4} />
|
||||
</button>
|
||||
</Tippy>
|
||||
{/if}
|
||||
<div class="flex min-w-0 flex-col" class:items-end={isOwn}>
|
||||
<TapTarget
|
||||
class="bg-alt chat-bubble mx-1 flex cursor-auto flex-col gap-1 text-left lg:max-w-2xl"
|
||||
class="bg-alt chat-bubble mx-1 mb-2 flex cursor-auto flex-col gap-1 text-left lg:max-w-2xl"
|
||||
onTap={showMobileMenu}>
|
||||
{#if showPubkey}
|
||||
<div class="flex items-center gap-2">
|
||||
|
|
|
|||
|
|
@ -9,7 +9,13 @@
|
|||
import {pushModal} from "@app/modal"
|
||||
import {clip} from "@app/toast"
|
||||
|
||||
const {event, pubkeys} = $props()
|
||||
type Props = {
|
||||
pubkeys: string[]
|
||||
event: TrustedEvent
|
||||
reply: () => void
|
||||
}
|
||||
|
||||
const {event, pubkeys, reply}: Props = $props()
|
||||
|
||||
const onEmoji = ((event: TrustedEvent, emoji: NativeEmoji) => {
|
||||
history.back()
|
||||
|
|
@ -18,6 +24,11 @@
|
|||
|
||||
const showEmojiPicker = () => pushModal(EmojiPicker, {onClick: onEmoji}, {replaceState: true})
|
||||
|
||||
const sendReply = () => {
|
||||
history.back()
|
||||
reply()
|
||||
}
|
||||
|
||||
const copyText = () => {
|
||||
history.back()
|
||||
clip(event.content)
|
||||
|
|
@ -31,6 +42,10 @@
|
|||
<Icon size={4} icon="smile-circle" />
|
||||
Send Reaction
|
||||
</Button>
|
||||
<Button class="btn btn-neutral w-full" onclick={sendReply}>
|
||||
<Icon size={4} icon="reply" />
|
||||
Send Reply
|
||||
</Button>
|
||||
<Button class="btn btn-neutral w-full" onclick={copyText}>
|
||||
<Icon size={4} icon="copy" />
|
||||
Copy Text
|
||||
|
|
|
|||
Loading…
Reference in a new issue