diff --git a/frontend/app/src/components/App.svelte b/frontend/app/src/components/App.svelte index 613025df2d..29b418cfdd 100644 --- a/frontend/app/src/components/App.svelte +++ b/frontend/app/src/components/App.svelte @@ -108,6 +108,8 @@ setUserUpgradeConcurrency, stakeNeuronForSubmittingProposals, updateMarketMakerConfig, + pauseEventLoop: () => client.pauseEventLoop(), + resumeEventLoop: () => client.resumeEventLoop(), }; framed.set(window.self !== window.top); diff --git a/frontend/app/src/components/home/ChatMessage.svelte b/frontend/app/src/components/home/ChatMessage.svelte index acc0bf580f..a249bf4579 100644 --- a/frontend/app/src/components/home/ChatMessage.svelte +++ b/frontend/app/src/components/home/ChatMessage.svelte @@ -54,6 +54,7 @@ import { filterRightPanelHistory } from "../../stores/rightPanel"; import { removeQueryStringParam } from "../../utils/urls"; import Diamond from "../icons/Diamond.svelte"; + import IntersectionObserverComponent from "./IntersectionObserver.svelte"; const client = getContext("client"); const dispatch = createEventDispatcher(); @@ -359,9 +360,9 @@ }); } - function canShare(): boolean { - return canShareMessage(msg.content); - } + $: canShare = canShareMessage(msg.content); + $: canForward = client.canForward(msg.content); + $: canTranslate = (client.getMessageText(msg.content) ?? "").length > 0; function sendTip(ev: CustomEvent) { tipping = undefined; @@ -373,6 +374,14 @@ } }); } + + function reportMessage() { + showReport = true; + } + + function remindMe() { + showRemindMe = true; + } @@ -422,234 +431,238 @@ {#if expiresAt === undefined || percentageExpired < 100}
-
- {#if showAvatar} -
- {#if first} -
- -
- {/if} -
- {/if} - - +
messageMenu?.showMenu()} - class="message-bubble" - class:focused - class:editing - class:fill={fill && !inert} + bind:this={msgElement} + class="message" class:me - class:inert - class:collapsed - class:first - class:last - class:readByMe - class:crypto - class:failed - class:prizeWinner={isPrizeWinner} - class:proposal={isProposal && !inert} - class:thread={inThread} - class:rtl={$rtlStore}> - {#if first && !isProposal && !isPrize} -
- -

- {senderDisplayName} -

- - - {#if senderTyping} - - - + data-index={failed ? "" : msg.messageIndex} + data-id={failed ? "" : msg.messageId} + id={failed ? "" : `event-${eventIndex}`}> + {#if showAvatar} +
+ {#if first} +
+ +
{/if}
{/if} - {#if msg.forwarded} -
-
- + + +
messageMenu?.showMenu()} + class="message-bubble" + class:focused + class:editing + class:fill={fill && !inert} + class:me + class:inert + class:collapsed + class:first + class:last + class:readByMe + class:crypto + class:failed + class:prizeWinner={isPrizeWinner} + class:proposal={isProposal && !inert} + class:thread={inThread} + class:rtl={$rtlStore}> + {#if first && !isProposal && !isPrize} +
+ +

+ {senderDisplayName} +

+ + + {#if senderTyping} + + + + {/if}
-
{"Forwarded"}
-
- {/if} - {#if msg.repliesTo !== undefined && !inert} - {#if msg.repliesTo.kind === "rehydrated_reply_context"} - - {:else} - {/if} - {/if} + {#if msg.forwarded} +
+
+ +
+
{"Forwarded"}
+
+ {/if} + {#if msg.repliesTo !== undefined && !inert} + {#if msg.repliesTo.kind === "rehydrated_reply_context"} + + {:else} + + {/if} + {/if} - - - {#if !inert && !isPrize} - - {/if} + {intersecting} + messageIndex={msg.messageIndex} + messageId={msg.messageId} + myUserId={user.userId} + content={msg.content} + edited={msg.edited} + height={mediaCalculatedHeight} + on:registerVote={registerVote} + on:goToMessageIndex + on:upgrade + on:expandMessage /> + + {#if !inert && !isPrize} + + {/if} - {#if debug} -
EventIdx: {eventIndex}
-
MsgIdx: {msg.messageIndex}
-
MsgId: {msg.messageId}
-
Confirmed: {confirmed}
-
ReadByThem: {readByThem}
-
ReadByUs: {readByMe}
-
Pinned: {pinned}
-
edited: {msg.edited}
-
failed: {failed}
-
timestamp: {timestamp}
-
expiresAt: {expiresAt}
-
thread: {JSON.stringify(msg.thread, null, 4)}
- {/if} + {#if debug} +
EventIdx: {eventIndex}
+
MsgIdx: {msg.messageIndex}
+
MsgId: {msg.messageId}
+
Confirmed: {confirmed}
+
ReadByThem: {readByThem}
+
ReadByUs: {readByMe}
+
Pinned: {pinned}
+
edited: {msg.edited}
+
failed: {failed}
+
timestamp: {timestamp}
+
expiresAt: {expiresAt}
+
thread: {JSON.stringify(msg.thread, null, 4)}
+ {/if} - {#if showChatMenu} - 0} - {translated} - on:collapseMessage - on:forward - on:reply={reply} - on:retrySend - on:upgrade - on:initiateThread - on:deleteFailedMessage - on:replyPrivately={replyPrivately} - on:editMessage={editMessage} - on:tipMessage={tipMessage} - on:reportMessage={() => (showReport = true)} - on:cancelReminder={cancelReminder} - on:remindMe={() => (showRemindMe = true)} /> + {#if showChatMenu && intersecting} + + {/if} +
+ + {#if !collapsed && !msg.deleted && canReact && !failed} +
+
(showEmojiPicker = true)}> + + + +
+
{/if}
- {#if !collapsed && !msg.deleted && canReact && !failed} -
-
(showEmojiPicker = true)}> - - - -
+ {#if threadSummary !== undefined && !inThread} + + {/if} + + {#if msg.reactions.length > 0 && !inert} +
+ {#each msg.reactions as { reaction, userIds } (reaction)} + toggleReaction(reaction)} + {reaction} + {userIds} + myUserId={user?.userId} /> + {/each}
{/if} -
- - {#if threadSummary !== undefined && !inThread} - - {/if} - - {#if msg.reactions.length > 0 && !inert} -
- {#each msg.reactions as { reaction, userIds } (reaction)} - toggleReaction(reaction)} - {reaction} - {userIds} - myUserId={user?.userId} /> - {/each} -
- {/if} - {#if tips.length > 0 && !inert} -
- {#each tips as [ledger, userTips]} - - {/each} -
- {/if} + {#if tips.length > 0 && !inert} +
+ {#each tips as [ledger, userTips]} + + {/each} +
+ {/if} +
{/if} diff --git a/frontend/app/src/components/home/ChatMessageContent.svelte b/frontend/app/src/components/home/ChatMessageContent.svelte index b9a9f5525d..5ed5522bac 100644 --- a/frontend/app/src/components/home/ChatMessageContent.svelte +++ b/frontend/app/src/components/home/ChatMessageContent.svelte @@ -19,7 +19,6 @@ import MessageReminderContent from "./MessageReminderContent.svelte"; import MessageReminderCreatedContent from "./MessageReminderCreatedContent.svelte"; import ProposalContent from "./proposals/ProposalContent.svelte"; - import IntersectionObserver from "./IntersectionObserver.svelte"; import type { ChatIdentifier, MessageContent } from "openchat-client"; import { _ } from "svelte-i18n"; import PrizeContentInitial from "./PrizeContentInitial.svelte"; @@ -40,14 +39,13 @@ export let messageIndex: number; export let collapsed = false; export let undeleting: boolean = false; + export let intersecting: boolean; {#if content.kind === "text_content"} {:else if content.kind === "image_content"} - - - + {:else if content.kind === "video_content"} {:else if content.kind === "audio_content"} @@ -71,9 +69,7 @@ {:else if content.kind === "poll_content"} {:else if content.kind === "giphy_content"} - - - + {:else if content.kind === "proposal_content"} {:else if content.kind === "meme_fighter_content"} - - - + {:else if content.kind === "user_referral_card"} {/if} diff --git a/frontend/app/src/components/home/ChatMessageMenu.svelte b/frontend/app/src/components/home/ChatMessageMenu.svelte index d3de9b96e8..d17d1ebe19 100644 --- a/frontend/app/src/components/home/ChatMessageMenu.svelte +++ b/frontend/app/src/components/home/ChatMessageMenu.svelte @@ -131,7 +131,7 @@ $user.userId, msg.sender === $user.userId, msg, - $cryptoLookup + $cryptoLookup, ); } diff --git a/frontend/app/src/components/home/RepliesTo.svelte b/frontend/app/src/components/home/RepliesTo.svelte index 0434e91c08..05a97011d7 100644 --- a/frontend/app/src/components/home/RepliesTo.svelte +++ b/frontend/app/src/components/home/RepliesTo.svelte @@ -22,6 +22,7 @@ export let chatId: ChatIdentifier; export let repliesTo: RehydratedReplyContext; export let readonly: boolean; + export let intersecting: boolean; let debug = false; @@ -71,6 +72,7 @@ {me} {readonly} {chatId} + {intersecting} messageId={repliesTo.messageId} messageIndex={repliesTo.messageIndex} senderId={repliesTo.senderId} diff --git a/frontend/app/src/components/home/ReplyingTo.svelte b/frontend/app/src/components/home/ReplyingTo.svelte index 58d0a86eb6..2c866cd0e8 100644 --- a/frontend/app/src/components/home/ReplyingTo.svelte +++ b/frontend/app/src/components/home/ReplyingTo.svelte @@ -51,6 +51,7 @@ {chatId} fill={false} {me} + intersecting={true} messageId={replyingTo.messageId} messageIndex={replyingTo.messageIndex} senderId={replyingTo.senderId} diff --git a/frontend/app/src/components/home/pinned/PinnedMessage.svelte b/frontend/app/src/components/home/pinned/PinnedMessage.svelte index 4b67f3bf25..6956460b47 100644 --- a/frontend/app/src/components/home/pinned/PinnedMessage.svelte +++ b/frontend/app/src/components/home/pinned/PinnedMessage.svelte @@ -12,6 +12,7 @@ import { mobileWidth } from "../../../stores/screenDimensions"; import { createEventDispatcher, getContext } from "svelte"; import type { ProfileLinkClickedEvent } from "../../web-components/profileLink"; + import IntersectionObserver from "../IntersectionObserver.svelte"; const client = getContext("client"); const dispatch = createEventDispatcher(); @@ -37,7 +38,7 @@ new CustomEvent("profile-clicked", { detail: { userId: sender.userId, chatButton: !me, inGlobalContext: false }, bubbles: true, - }) + }), ); } @@ -56,41 +57,49 @@ userId={sender.userId} size={$mobileWidth ? AvatarSize.Small : AvatarSize.Default} />
-
- {#if !deleted} -
- -

{username}

- -
- {/if} - {#if msg.repliesTo !== undefined && !deleted} - {#if msg.repliesTo.kind === "rehydrated_reply_context"} - - {:else} - + +
+ {#if !deleted} +
+ +

{username}

+ +
{/if} - {/if} - - -
+ {#if msg.repliesTo !== undefined && !deleted} + {#if msg.repliesTo.kind === "rehydrated_reply_context"} + + {:else} + + {/if} + {/if} + + +
+