Skip to content

Commit

Permalink
Remove link previews (#5085)
Browse files Browse the repository at this point in the history
  • Loading branch information
megrogan authored Jan 2, 2024
1 parent 9f8da57 commit 35407d6
Show file tree
Hide file tree
Showing 29 changed files with 545 additions and 222 deletions.
32 changes: 17 additions & 15 deletions frontend/app/src/components/AreYouSure.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import Input from "./Input.svelte";
import Markdown from "./home/Markdown.svelte";
export let message: string;
export let message: string | undefined = undefined;
export let action: (yes: boolean) => Promise<void>;
export let doubleCheck: { challenge: string; response: string } | undefined = undefined;
export let title: string | undefined = undefined;
Expand All @@ -31,23 +31,25 @@
</script>

<Overlay>
<ModalContent>
<ModalContent hideBody={message === undefined}>
<span slot="header">{title ?? $_("areYouSure")}</span>
<span slot="body">
<Markdown inline={false} text={message} />
{#if message !== undefined}
<Markdown inline={false} text={message} />

{#if doubleCheck !== undefined}
<p class="challenge">
<Markdown text={doubleCheck.challenge} />
</p>
<Input
invalid={false}
disabled={inProgress}
autofocus
bind:value={response}
minlength={0}
maxlength={200}
countdown={false} />
{#if doubleCheck !== undefined}
<p class="challenge">
<Markdown text={doubleCheck.challenge} />
</p>
<Input
invalid={false}
disabled={inProgress}
autofocus
bind:value={response}
minlength={0}
maxlength={200}
countdown={false} />
{/if}
{/if}
</span>
<span slot="footer">
Expand Down
9 changes: 6 additions & 3 deletions frontend/app/src/components/ModalContent.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
export let fill: boolean = false;
export let large: boolean = false;
export let hideHeader: boolean = false;
export let hideBody: boolean = false;
export let hideFooter: boolean = false;
export let compactFooter: boolean = false;
export let fadeDuration = 100;
Expand Down Expand Up @@ -106,9 +107,11 @@
{/if}
</div>
{/if}
<div class="body" class:fill>
<slot name="body" />
</div>
{#if !hideBody}
<div class="body" class:fill>
<slot name="body" />
</div>
{/if}
{#if !hideFooter}
<div class="footer" class:rtl={$rtlStore} class:compact={compactFooter}>
<slot name="footer">
Expand Down
5 changes: 5 additions & 0 deletions frontend/app/src/components/home/ChatEvent.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@
}
}
}
function removePreview(ev: CustomEvent<string>) {
dispatch("removePreview", { event, url: ev.detail });
}
</script>

{#if event.event.kind === "message"}
Expand Down Expand Up @@ -158,6 +162,7 @@
on:forward
on:expandMessage
on:collapseMessage
on:removePreview={removePreview}
on:initiateThread={initiateThread}
on:deleteFailedMessage={deleteFailedMessage}
eventIndex={event.index}
Expand Down
1 change: 1 addition & 0 deletions frontend/app/src/components/home/ChatMessage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@
content={msg.content}
edited={msg.edited}
height={mediaCalculatedHeight}
on:removePreview
on:registerVote={registerVote}
on:goToMessageIndex
on:upgrade
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/src/components/home/ChatMessageContent.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
</script>

{#if content.kind === "text_content"}
<TextContent {me} {fill} {truncate} {pinned} {content} {edited} />
<TextContent {me} {fill} {truncate} {pinned} {content} {edited} on:removePreview />
{:else if content.kind === "image_content"}
<ImageContent {edited} {intersecting} {fill} {content} {reply} {pinned} {height} />
{:else if content.kind === "video_content"}
Expand Down
35 changes: 32 additions & 3 deletions frontend/app/src/components/home/CurrentChat.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from "svelte-i18n";
import CurrentChatHeader from "./CurrentChatHeader.svelte";
import CurrentChatMessages from "./CurrentChatMessages.svelte";
import Footer from "./Footer.svelte";
Expand Down Expand Up @@ -35,6 +36,7 @@
import { rightPanelHistory } from "../../stores/rightPanel";
import { mobileWidth } from "../../stores/screenDimensions";
import PrizeContentBuilder from "./PrizeContentBuilder.svelte";
import AreYouSure from "../AreYouSure.svelte";
export let joining: MultiUserChat | undefined;
export let chat: ChatSummary;
Expand All @@ -59,6 +61,8 @@
let showSearchHeader = false;
let searchTerm = "";
let importToCommunities: CommunityMap<CommunitySummary> | undefined;
let removeLinkPreviewDetails: { event: EventWrapper<Message>; url: string } | undefined =
undefined;
$: user = client.user;
$: suspendedUser = client.suspendedUser;
Expand Down Expand Up @@ -201,7 +205,7 @@
messageContext,
text,
$currentChatAttachment,
$currentChatEditingEvent
$currentChatEditingEvent,
)
.then((success) => {
if (!success) {
Expand All @@ -216,7 +220,7 @@
function sendMessageWithAttachment(
textContent: string | undefined,
attachment: AttachmentContent | undefined,
mentioned: User[] = []
mentioned: User[] = [],
) {
dispatch("sendMessageWithAttachment", { textContent, attachment, mentioned });
}
Expand All @@ -229,6 +233,25 @@
draftMessagesStore.setTextContent({ chatId: chat.id }, ev.detail);
}
function onRemovePreview(ev: CustomEvent<{ event: EventWrapper<Message>; url: string }>): void {
removeLinkPreviewDetails = ev.detail;
}
function removePreview(yes: boolean): Promise<void> {
if (removeLinkPreviewDetails !== undefined && yes) {
const { event, url } = removeLinkPreviewDetails;
client.hideLinkPreview(messageContext, event, url).then((success) => {
if (!success) {
toastStore.showFailureToast("errorRemovingLinkPreview");
}
});
}
removeLinkPreviewDetails = undefined;
return Promise.resolve();
}
function isBlocked(chatSummary: ChatSummary, blockedUsers: Set<string>): boolean {
return chatSummary.kind === "direct_chat" && blockedUsers.has(chatSummary.them.userId);
}
Expand All @@ -240,6 +263,10 @@

<svelte:window on:focus={onWindowFocus} />

{#if removeLinkPreviewDetails !== undefined}
<AreYouSure title={$_("removePreviewQuestion")} action={removePreview} />
{/if}

{#if importToCommunities !== undefined}
<ImportToCommunity
on:successfulImport
Expand Down Expand Up @@ -309,6 +336,7 @@
on:upgrade
on:forward
on:retrySend
on:removePreview={onRemovePreview}
{chat}
{events}
{filteredProposals}
Expand Down Expand Up @@ -338,7 +366,8 @@
on:joinGroup
on:upgrade
on:cancelReply={() => draftMessagesStore.setReplyingTo({ chatId: chat.id }, undefined)}
on:clearAttachment={() => draftMessagesStore.setAttachment({ chatId: chat.id }, undefined)}
on:clearAttachment={() =>
draftMessagesStore.setAttachment({ chatId: chat.id }, undefined)}
on:cancelEditEvent={() => draftMessagesStore.delete({ chatId: chat.id })}
on:setTextContent={setTextContent}
on:startTyping={() => client.startTyping(chat, $user.userId)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@
on:chatWith
on:replyTo={replyTo}
on:replyPrivatelyTo
on:removePreview
on:editEvent={onEditEvent}
on:goToMessageIndex={goToMessageIndex}
on:expandMessage={() => toggleMessageExpansion(evt, true)}
Expand Down
103 changes: 53 additions & 50 deletions frontend/app/src/components/home/GenericPreview.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
<script lang="ts" context="module">
import { waitAll } from "openchat-client";
import { createEventDispatcher, onMount } from "svelte";
<script lang="ts">
import { createEventDispatcher, getContext } from "svelte";
import { eventListScrolling } from "../../stores/scrollPos";
import type { OpenChat } from "openchat-client";
export type LinkInfo = {
type LinkInfo = {
url: string;
title: string | null | undefined;
description: string | null | undefined;
image: string | null | undefined;
removed: boolean;
};
export async function loadPreviews(links: string[]): Promise<LinkInfo[]> {
const res = await waitAll(links.map(loadPreview));
return res.success;
const dispatch = createEventDispatcher();
const client = getContext<OpenChat>("client");
export let url: string;
export let intersecting: boolean;
export let rendered = false;
let previewWrapper: HTMLElement;
let previewPromise: Promise<LinkInfo> | undefined = undefined;
$: offlineStore = client.offlineStore;
$: {
if (intersecting && !$eventListScrolling && !rendered && !$offlineStore) {
// make sure we only actually *load* the preview once
previewPromise = previewPromise ?? loadPreview(url);
previewPromise.then(() => {
// only render the preview if we are *still* intersecting
if (intersecting && !$eventListScrolling) {
rendered = true;
dispatch("rendered", url);
}
});
}
}
async function loadPreview(url: string): Promise<LinkInfo> {
Expand All @@ -29,73 +53,52 @@
const image = doc.querySelector('meta[property="og:image"]')?.getAttribute("content");
return {
url,
title,
description,
image: image ? new URL(image, url).toString() : undefined,
removed: false,
};
}
</script>

<script lang="ts">
const dispatch = createEventDispatcher();
export let previews: (LinkInfo | undefined)[] = [];
export let me: boolean;
let previewsWrapper: HTMLElement;
let numberOfImagesLoaded = 0;
let imageCount = 0;
function imageLoaded() {
numberOfImagesLoaded += 1;
if (numberOfImagesLoaded >= imageCount && previewsWrapper) {
dispatch("rendered", previewsWrapper);
}
dispatch("imageLoaded", previewWrapper);
}
onMount(() => {
imageCount = previews.reduce((count, p) => {
return p?.image ? count + 1 : count;
}, 0);
});
</script>

<div bind:this={previewsWrapper}>
{#each previews as preview}
{#if preview?.title !== undefined || preview?.description !== undefined || preview?.image !== undefined}
<div class="preview" class:me>
{#if rendered}
{#await previewPromise then preview}
{#if preview !== undefined}
<div bind:this={previewWrapper}>
{#if preview.title}
<h3 class="title">{preview.title}</h3>
<a class="title" href={preview.url} target="_blank">{preview.title}</a>
{/if}
{#if preview.description}
<p class="desc">{preview.description}</p>
{/if}
{#if preview.image}
<img
on:load={imageLoaded}
on:error={imageLoaded}
class="image"
src={preview.image}
alt="link preview image" />
<a href={preview.url} target="_blank">
<img
on:load={imageLoaded}
on:error={imageLoaded}
class="image"
src={preview.image}
alt="link preview image" />
</a>
{/if}
</div>
{/if}
{/each}
</div>
{/await}
{/if}

<style lang="scss">
.preview {
margin-top: $sp4;
border-top: 1px solid var(--currentChat-msg-separator);
&.me {
border-color: var(--currentChat-msg-me-separator);
}
}
.title {
@include font(bold, normal, fs-120);
margin: $sp3 0 $sp2 0;
&:hover {
text-decoration: underline;
}
}
.desc {
margin-bottom: $sp3;
Expand Down
Loading

0 comments on commit 35407d6

Please sign in to comment.