diff --git a/CHANGELOG.md b/CHANGELOG.md index dfdd73a..69df113 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/app/components/ChannelMessage.svelte b/src/app/components/ChannelMessage.svelte index 0382e1e..4d4e89a 100644 --- a/src/app/components/ChannelMessage.svelte +++ b/src/app/components/ChannelMessage.svelte @@ -99,15 +99,17 @@
- - {/if} - - + {#if !isMobile} + + {/if} + + + {/if} diff --git a/src/app/components/Chat.svelte b/src/app/components/Chat.svelte index 3cdd35e..09accf0 100644 --- a/src/app/components/Chat.svelte +++ b/src/app/components/Chat.svelte @@ -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,110 +123,113 @@ }, 5000) -
- {#if others.length > 0} - - {#snippet title()} -
- {#if others.length === 1} - {@const pubkey = others[0]} - {@const onClick = () => pushModal(ProfileDetail, {pubkey})} - - {:else} -
- -

- - and - {#if others.length === 2} - - {:else} - {others.length - 1} - {others.length > 2 ? "others" : "other"} - {/if} -

-
- {#if others.length > 2} - - {/if} - {/if} -
- {/snippet} - {#snippet action()} -
- {#if remove($pubkey, missingInboxes).length > 0} - {@const count = remove($pubkey, missingInboxes).length} - {@const label = count > 1 ? "inboxes are" : "inbox is"} -
- - {count} -
- {/if} -
- {/snippet} -
- {/if} -
- {#if missingInboxes.includes($pubkey!)} -
-
-

- - Your inbox is not configured. -

-

- In order to deliver messages, {PLATFORM_NAME} needs to know where to send them. Please visit - your relay settings page to set up your - inbox. -

-
-
- {:else if missingInboxes.length > 0} -
-
-

- - {missingInboxes.length} - {missingInboxes.length > 1 ? "inboxes are" : "inbox is"} not configured. -

-

- In order to deliver messages, {PLATFORM_NAME} needs to know where to send them. Please make - sure everyone in this conversation has set up their inbox relays. -

-
-
- {/if} - {#each elements as { type, id, value, showPubkey } (id)} - {#if type === "date"} - {value} - {:else} - - {/if} - {/each} -

- - {#if loading} - Looking for messages... +{#if others.length > 0} + + {#snippet title()} +

+ {#if others.length === 1} + {@const pubkey = others[0]} + {@const onClick = () => pushModal(ProfileDetail, {pubkey})} + {:else} - End of message history +
+ +

+ + and + {#if others.length === 2} + + {:else} + {others.length - 1} + {others.length > 2 ? "others" : "other"} + {/if} +

+
+ {#if others.length > 2} + + {/if} {/if} - - {@render info?.()} -

-
- {#if parent} - +
+ {/snippet} + {#snippet action()} +
+ {#if remove($pubkey, missingInboxes).length > 0} + {@const count = remove($pubkey, missingInboxes).length} + {@const label = count > 1 ? "inboxes are" : "inbox is"} +
+ + {count} +
+ {/if} +
+ {/snippet} + +{/if} + +
+
+ {#if missingInboxes.includes($pubkey!)} +
+
+

+ + Your inbox is not configured. +

+

+ In order to deliver messages, {PLATFORM_NAME} needs to know where to send them. Please visit + your relay settings page to set up your inbox. +

+
+
+ {:else if missingInboxes.length > 0} +
+
+

+ + {missingInboxes.length} + {missingInboxes.length > 1 ? "inboxes are" : "inbox is"} not configured. +

+

+ In order to deliver messages, {PLATFORM_NAME} needs to know where to send them. Please make + sure everyone in this conversation has set up their inbox relays. +

+
+
{/if} + {#each elements as { type, id, value, showPubkey } (id)} + {#if type === "date"} + {value} + {:else} + + {/if} + {/each} +

+ + {#if loading} + Looking for messages... + {:else} + End of message history + {/if} + + {@render info?.()} +

+
+ +
+
+ {#if parent} + + {/if} +
diff --git a/src/app/components/ChatMessage.svelte b/src/app/components/ChatMessage.svelte index 3b9d86d..8d1e40e 100644 --- a/src/app/components/ChatMessage.svelte +++ b/src/app/components/ChatMessage.svelte @@ -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,31 +74,33 @@ class:chat-start={!isOwn} class:flex-row-reverse={!isOwn} class:chat-end={isOwn}> - - - + {#if !isMobile} + + + + {/if}
{#if showPubkey}
diff --git a/src/app/components/ChatMessageMenuMobile.svelte b/src/app/components/ChatMessageMenuMobile.svelte index aadd9f0..1efa2d7 100644 --- a/src/app/components/ChatMessageMenuMobile.svelte +++ b/src/app/components/ChatMessageMenuMobile.svelte @@ -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 @@ Send Reaction +