Spaces:
Runtime error
Runtime error
File size: 5,935 Bytes
7bf1507 17a7bb7 7bf1507 17a7bb7 7bf1507 17a7bb7 7bf1507 17a7bb7 7bf1507 17a7bb7 7bf1507 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
<script lang="ts">
import Modal from "$lib/components/Modal.svelte";
import { base } from "$app/paths";
import { page } from "$app/state";
import CarbonLink from "~icons/carbon/link";
import CarbonCheckmark from "~icons/carbon/checkmark";
import EosIconsLoading from "~icons/eos-icons/loading";
import CopyToClipBoardBtn from "$lib/components/CopyToClipBoardBtn.svelte";
import { onMount } from "svelte";
import { createShareLink } from "$lib/createShareLink";
interface Props {
open?: boolean;
onclose?: () => void;
oncopied?: () => void;
}
let { open = false, onclose, oncopied }: Props = $props();
let creating = $state(false);
let createdUrl: string | null = $state(null);
let errorMsg: string | null = $state(null);
let justCopied = $state(false);
async function handleCreate() {
try {
creating = true;
errorMsg = null;
createdUrl = await createShareLink(page.params.id);
} catch (e) {
errorMsg = (e as Error).message || "Could not create link";
} finally {
creating = false;
}
}
function close() {
open = false;
onclose?.();
}
// If the current page is already a shared chat (7-char id), pre-fill the link
onMount(async () => {
if (page.params.id && page.params.id.length === 7) {
try {
createdUrl = await createShareLink(page.params.id);
} catch (e) {
// ignore
}
}
});
function withLeafId(url: string | null): string | null {
if (!url) return url;
try {
const leafId = localStorage.getItem("leafId");
if (!leafId) return url;
const u = new URL(url);
u.searchParams.set("leafId", leafId);
return u.toString();
} catch (e) {
return url;
}
}
</script>
{#if open}
<Modal onclose={close} width="w-[90dvh] md:w-[500px]">
<div class="flex w-full flex-col gap-3 p-5 sm:gap-5 sm:p-6">
<!-- Header + copy -->
{#if createdUrl}
<div class="flex items-start justify-between">
<div class="text-xl font-semibold text-gray-800 dark:text-gray-200">
Public link created
</div>
<button type="button" class="group" onclick={close} aria-label="Close">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 32 32"
class="size-5 text-gray-700 group-hover:text-gray-500 dark:text-gray-300 dark:group-hover:text-gray-400"
>
<path
d="M24 9.41 22.59 8 16 14.59 9.41 8 8 9.41 14.59 16 8 22.59 9.41 24 16 17.41 22.59 24 24 22.59 17.41 16 24 9.41z"
fill="currentColor"
/>
</svg>
</button>
</div>
<div class="text-sm text-gray-600 dark:text-gray-400">
A public link to your chat has been created.
</div>
{:else}
<div class="flex items-start justify-between">
<div class="text-xl font-semibold text-gray-800 dark:text-gray-200">
Share public link to chat
</div>
<button type="button" class="group" onclick={close} aria-label="Close">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 32 32"
class="size-5 text-gray-700 group-hover:text-gray-500 dark:text-gray-300 dark:group-hover:text-gray-400"
>
<path
d="M24 9.41 22.59 8 16 14.59 9.41 8 8 9.41 14.59 16 8 22.59 9.41 24 16 17.41 22.59 24 24 22.59 17.41 16 24 9.41z"
fill="currentColor"
/>
</svg>
</button>
</div>
<div class="text-sm text-gray-600 dark:text-gray-400">
Any messages you add after sharing stay private.
</div>
{/if}
{#if errorMsg}
<div
class="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-700 dark:bg-red-500/10 dark:text-red-300"
>
{errorMsg}
</div>
{/if}
<!-- URL row -->
<div
class="flex h-12 items-center gap-2 whitespace-nowrap rounded-2xl border border-gray-200 bg-gray-50 p-2.5 dark:border-gray-700 dark:bg-gray-800"
>
<input
class="w-full truncate bg-transparent text-[15px] text-gray-700 outline-none placeholder:text-gray-400 dark:text-gray-200 dark:placeholder:text-gray-500 max-sm:text-sm"
readonly
value={createdUrl ??
`${page.data.publicConfig.PUBLIC_SHARE_PREFIX || `${page.data.publicConfig.PUBLIC_ORIGIN || page.url.origin}${base}`}/r/...`}
/>
{#if createdUrl}
<CopyToClipBoardBtn
classNames="inline-flex items-center rounded-xl -mr-1 border border-gray-300 bg-white px-3 py-1.5 text-sm font-medium text-gray-900 shadow enabled:hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-700 dark:text-gray-100 dark:enabled:hover:bg-gray-600"
showTooltip={false}
value={withLeafId(createdUrl) ?? createdUrl}
onClick={() => {
justCopied = true;
oncopied?.();
setTimeout(() => (justCopied = false), 1200);
}}
>
{#snippet children()}
<span class="inline-flex items-center gap-1.5">
{#if justCopied}
<CarbonCheckmark class="text-[.95em] text-green-600 dark:text-green-400" />
Copied
{:else}
<!-- Use the copy icon provided by CopyToClipBoardBtn default otherwise -->
<svg width="1em" height="1em" viewBox="0 0 32 32" class="text-[.95em]"
><path
fill="currentColor"
d="M28 10v18H10V10zm-2 2H12v14h14zm-4-8v2H6v14H4V4z"
/></svg
>
Copy link
{/if}
</span>
{/snippet}
</CopyToClipBoardBtn>
{:else}
<button
class="-mr-1 inline-flex items-center gap-2 rounded-xl border border-gray-300 bg-white px-3 py-1.5 text-sm font-medium text-gray-900 shadow hover:bg-gray-50 disabled:opacity-50 dark:border-gray-700 dark:bg-gray-700 dark:text-gray-100 dark:hover:bg-gray-600"
type="button"
disabled={creating}
onclick={handleCreate}
>
{#if creating}
<EosIconsLoading class="text-[1.05em]" />
Creating…
{:else}
<CarbonLink class="text-[1.05em]" />
Create link
{/if}
</button>
{/if}
</div>
</div>
</Modal>
{/if}
|