| <script lang="ts"> |
| import { toast } from 'svelte-sonner'; |
| import { getContext, onMount } from 'svelte'; |
| const i18n = getContext('i18n'); |
| |
| import { getChannelPinnedMessages, pinMessage } from '$lib/apis/channels'; |
| |
| import Spinner from '$lib/components/common/Spinner.svelte'; |
| import Modal from '$lib/components/common/Modal.svelte'; |
| |
| import XMark from '$lib/components/icons/XMark.svelte'; |
| import Message from './Messages/Message.svelte'; |
| import Loader from '../common/Loader.svelte'; |
| |
| export let show = false; |
| export let channel = null; |
| export let onPin = (messageId, pinned) => {}; |
| |
| let page = 1; |
| let pinnedMessages = null; |
| |
| let allItemsLoaded = false; |
| let loading = false; |
| |
| const getPinnedMessages = async () => { |
| if (!channel) return; |
| if (allItemsLoaded) return; |
| |
| loading = true; |
| try { |
| const res = await getChannelPinnedMessages(localStorage.token, channel.id, page).catch( |
| (error) => { |
| toast.error(`${error}`); |
| return null; |
| } |
| ); |
| |
| if (res) { |
| pinnedMessages = [...(pinnedMessages ?? []), ...res]; |
| |
| if (res.length === 0) { |
| allItemsLoaded = true; |
| } |
| } |
| } catch (error) { |
| console.error('Error fetching pinned messages:', error); |
| } finally { |
| loading = false; |
| } |
| }; |
| |
| const init = () => { |
| page = 1; |
| pinnedMessages = null; |
| allItemsLoaded = false; |
| |
| getPinnedMessages(); |
| }; |
| |
| $: if (show) { |
| init(); |
| } |
| |
| onMount(() => { |
| init(); |
| }); |
| </script> |
|
|
| {#if channel} |
| <Modal size="sm" bind:show> |
| <div> |
| <div class=" flex justify-between dark:text-gray-100 px-5 pt-4 mb-1.5"> |
| <div class="self-center text-base"> |
| <div class="flex items-center gap-0.5 shrink-0"> |
| {$i18n.t('Pinned Messages')} |
| </div> |
| </div> |
| <button |
| class="self-center" |
| on:click={() => { |
| show = false; |
| }} |
| > |
| <XMark className={'size-5'} /> |
| </button> |
| </div> |
|
|
| <div class="flex flex-col md:flex-row w-full px-4 pb-4 md:space-x-4 dark:text-gray-200"> |
| <div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6"> |
| <div class="flex flex-col w-full h-full pb-2 gap-1"> |
| {#if pinnedMessages === null} |
| <div class="my-10"> |
| <Spinner className="size-5" /> |
| </div> |
| {:else} |
| <div |
| class="flex flex-col gap-2 max-h-[60vh] overflow-y-auto scrollbar-thin scrollbar-thumb-gray-300 dark:scrollbar-thumb-gray-700 scrollbar-track-transparent py-2" |
| > |
| {#if pinnedMessages.length === 0} |
| <div class=" text-center text-xs text-gray-500 dark:text-gray-400 py-6"> |
| {$i18n.t('No pinned messages')} |
| </div> |
| {:else} |
| {#each pinnedMessages as message, messageIdx (message.id)} |
| <Message |
| className="rounded-xl px-2" |
| {message} |
| {channel} |
| onPin={async (message) => { |
| pinnedMessages = pinnedMessages.filter((m) => m.id !== message.id); |
| onPin(message.id, !message.is_pinned); |
|
|
| const updatedMessage = await pinMessage( |
| localStorage.token, |
| message.channel_id, |
| message.id, |
| !message.is_pinned |
| ).catch((error) => { |
| toast.error(`${error}`); |
| return null; |
| }); |
|
|
| init(); |
| }} |
| onReaction={false} |
| onThread={false} |
| onReply={false} |
| onEdit={false} |
| onDelete={false} |
| /> |
|
|
| {#if messageIdx === pinnedMessages.length - 1 && !allItemsLoaded} |
| <Loader |
| on:visible={(e) => { |
| console.log('visible'); |
| if (!loading) { |
| page += 1; |
| getPinnedMessages(); |
| } |
| }} |
| > |
| <div |
| class="w-full flex justify-center py-1 text-xs animate-pulse items-center gap-2" |
| > |
| <Spinner className=" size-4" /> |
| <div class=" ">{$i18n.t('Loading...')}</div> |
| </div> |
| </Loader> |
| {/if} |
| {/each} |
| {/if} |
| </div> |
| {/if} |
| </div> |
| </div> |
| </div> |
| </div> |
| </Modal> |
| {/if} |
|
|