Skip to content

Commit

Permalink
Add menu with copy text
Browse files Browse the repository at this point in the history
  • Loading branch information
narze committed Aug 15, 2023
1 parent dca75a6 commit 386ac20
Showing 1 changed file with 113 additions and 64 deletions.
177 changes: 113 additions & 64 deletions src/lib/commands/components/ChatMessage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import type { SvelteComponent } from 'svelte';
import { fly } from 'svelte/transition';
import { decodeBase64, decryptMessage, encodeUTF8, secretbox } from '$lib/encryption';
import { decryptMessage } from '$lib/encryption';
export let message: Message;
export let components: Record<string, typeof SvelteComponent<any>>;
Expand All @@ -17,6 +17,7 @@
const isComponent = message.type == 'component';
let fullscreenDialog: HTMLDialogElement;
let fullscreenDialogShown: boolean;
let menu: HTMLDetailsElement;
function getMessage() {
if (message.encrypted) {
Expand Down Expand Up @@ -67,6 +68,21 @@
fullscreenDialogShown = false;
});
}
function copyText() {
const text = getMessage() as string;
navigator.clipboard
.writeText(text)
.then(() => {
// TODO: Add toast or reply
})
.catch((err) => {
console.error('Error copying text: ', err);
});
menu.attributes.removeNamedItem('open');
}
</script>

{#if isComponent}
Expand Down Expand Up @@ -103,83 +119,116 @@
</dialog>
{/if}

<div
class="chat"
class:chat-start={!message.self}
class:chat-end={message.self}
class:chat-bot={!message.self}
class:chat-self={message.self}
transition:fly|global={message.self ? { duration: 0 } : { y: 50, duration: 100 }}
>
<div class="chat-header flex items-center gap-1">
<span class="font-medium">{!message.self ? 'ChatOS' : ''}{guest ? ' *' : ''}</span>
<time class="text-xs text-secondary"
>{message.time?.toDate().toLocaleString('en-US', {
weekday: 'short',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
hour12: true
})}</time
>

{#if message.encrypted}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-3 h-3 inline-block"
<div class="flex w-full">
<div
class="chat grow"
class:chat-start={!message.self}
class:chat-end={message.self}
class:chat-bot={!message.self}
class:chat-self={message.self}
transition:fly|global={message.self ? { duration: 0 } : { y: 50, duration: 100 }}
>
<div class="chat-header flex items-center gap-1">
<span class="font-medium">{!message.self ? 'ChatOS' : ''}{guest ? ' *' : ''}</span>
<time class="text-xs text-secondary"
>{message.time?.toDate().toLocaleString('en-US', {
weekday: 'short',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
hour12: true
})}</time
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z"
/>
</svg>
{/if}
</div>

<div class="chat-bubble chat-bubble-primary relative group" role="log">
{#if isComponent}
<button
class="hidden group-hover:block absolute top-2 right-2 btn btn-xs btn-primary btn-square"
on:click={() => {
fullscreenDialog.showModal();
fullscreenDialogShown = true;
}}
>
{#if message.encrypted}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-6 h-6"
class="w-3 h-3 inline-block"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"
d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z"
/>
</svg>
</button>
{/if}

{#if message.type == 'image'}
<img src={getMessage()} alt={getMeta().alt} />
{:else if message.type == 'link'}
<a href={getMessage()} target="_blank" rel="noreferrer" class="link">{getMessage()}</a>
{:else if message.type == 'component'}
{#if getMessage() in components}
<!-- <Renderer component={components[getMessage()]} props={{}} /> -->
<svelte:component this={components[getMessage()]} options={getMeta()} />
{/if}
{:else}
{#each getMessage().split('\n') as line}
<div>{line}</div>
{/each}
{/if}

<details
class="dropdown dropdown-bottom not-prose"
class:dropdown-end={message.self}
bind:this={menu}
>
<summary class="btn btn-xs btn-ghost w-6 h-6 p-0 rounded-full">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 6.75a.75.75 0 110-1.5.75.75 0 010 1.5zM12 12.75a.75.75 0 110-1.5.75.75 0 010 1.5zM12 18.75a.75.75 0 110-1.5.75.75 0 010 1.5z"
/>
</svg>
</summary>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<ul
tabindex="0"
class="dropdown-content z-[1] menu m-1 shadow bg-base-100 rounded-box text-sm"
>
<li><button on:click={copyText}>Copy</button></li>
<!-- <li><a>Delete</a></li> -->
</ul>
</details>
</div>

<div class="chat-bubble chat-bubble-primary relative group" role="log">
{#if isComponent}
<button
class="hidden group-hover:block absolute top-2 right-2 btn btn-xs btn-primary btn-square"
on:click={() => {
fullscreenDialog.showModal();
fullscreenDialogShown = true;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-6 h-6"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"
/>
</svg>
</button>
{/if}

{#if message.type == 'image'}
<img src={getMessage()} alt={getMeta().alt} />
{:else if message.type == 'link'}
<a href={getMessage()} target="_blank" rel="noreferrer" class="link">{getMessage()}</a>
{:else if message.type == 'component'}
{#if getMessage() in components}
<!-- <Renderer component={components[getMessage()]} props={{}} /> -->
<svelte:component this={components[getMessage()]} options={getMeta()} />
{/if}
{:else}
{#each getMessage().split('\n') as line}
<div>{line}</div>
{/each}
{/if}
</div>
</div>
</div>

1 comment on commit 386ac20

@vercel
Copy link

@vercel vercel bot commented on 386ac20 Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

chat-os – ./

chat-os-git-main-notnarze.vercel.app
chat-os-notnarze.vercel.app
chat.narze.live
chat-os.vercel.app

Please sign in to comment.