From: Muhammad Rizki <[email protected]>
To: Ammar Faizi <[email protected]>
Cc: Muhammad Rizki <[email protected]>,
Alviro Iskandar Setiawan <[email protected]>,
Irvan Malik Azantha <[email protected]>,
Memet Zx <[email protected]>,
GNU/Weeb Mailing List <[email protected]>
Subject: [PATCH v1 09/13] feat(components): add <RecentMessages/> component
Date: Tue, 3 Oct 2023 09:51:42 +0700 [thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
This commit includes the <RecentMessages/> component, which is for
displaying recent messages from the GNU/Weeb's Telegram group chat.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/lib/components/RecentMessages.svelte | 249 +++++++++++++++++++++++
1 file changed, 249 insertions(+)
create mode 100644 src/lib/components/RecentMessages.svelte
diff --git a/src/lib/components/RecentMessages.svelte b/src/lib/components/RecentMessages.svelte
new file mode 100644
index 0000000..25fb0eb
--- /dev/null
+++ b/src/lib/components/RecentMessages.svelte
@@ -0,0 +1,249 @@
+<script lang="ts">
+ import { STORAGE_URL } from "$lib";
+ import { cleanMessageText, getFixedRandomColor, setupUserName } from "$lib";
+ import { dateFormat, getRepliedMessage } from "$lib/functions";
+ import type { RecentMessagesReturnType } from "$types";
+ import { onMount } from "svelte";
+
+ export let data: RecentMessagesReturnType[];
+ export let innerWidth: number;
+
+ let chatRootEl: HTMLDivElement;
+ let err: any;
+
+ const gotoReply = (msgId: number) => {
+ const targetReply = document.getElementById(msgId.toString());
+ const highlightReply = document.getElementById(`${msgId}-highlight`);
+
+ targetReply?.scrollIntoView({
+ behavior: innerWidth >= 1280 ? "smooth" : "instant",
+ block: "end",
+ inline: "nearest"
+ });
+
+ highlightReply?.classList.add(
+ "!bg-neutral-700", "!scale-105"
+ );
+
+ setTimeout(() => {
+ highlightReply?.classList.remove(
+ "!bg-neutral-700", "!scale-105"
+ );
+ }, 2000);
+ }
+
+ onMount(() => {
+ chatRootEl.lastElementChild?.scrollIntoView({
+ behavior: "smooth", block: "end", inline: "nearest"
+ });
+ })
+</script>
+
+
+<div
+ class="border border-neutral-800 rounded-xl overflow-hidden
+ max-w-xs md:max-w-lg lg:max-w-3xl xl:w-[20rem]"
+>
+
+ <div class="flex px-5 py-2 border-b border-neutral-800 justify-between items-center">
+ <h1 class="text-lg font-bold text-center w-full">Recent Group Messages</h1>
+ </div>
+
+ <div
+ bind:this={chatRootEl}
+ class="px-3 py-2 space-y-1 text-sm max-h-[500px] overflow-y-auto"
+ >
+
+ {#if data.length === 0}
+ <div class="text-red-500 italic text-center p-3">
+ Cannot Connect to the API.<br>API Connection failure.
+ </div>
+
+ {:else}
+ {#each data as msg}
+
+ <div
+ id={msg.message_id.toString()}
+ class="chat chat-start w-full"
+ >
+
+ <div class="chat-image avatar">
+ <div class="w-10 rounded-full">
+ <img
+ src={STORAGE_URL + msg.user_photo}
+ alt=""
+ draggable="false"
+ >
+ </div>
+ </div>
+
+ <div
+ id={msg.message_id.toString() + "-highlight"}
+ class="chat-bubble transition before:transition duration-500
+ before:duration-500 ease-in-out before:ease-in-out
+ delay-200 before:delay-200"
+ >
+
+ <div
+ class="chat-header font-semibold pb-1 line-clamp-1
+ {getFixedRandomColor(msg.first_name)[0]}"
+ >
+ {setupUserName(msg.first_name, msg.last_name).join("")}
+ </div>
+
+ {#if msg.reply_to_message_id !== null}
+ {#each getRepliedMessage(msg, data) as rpl}
+
+ <button
+ on:click={() => gotoReply(msg.reply_to_message_id || 0)}
+ class="flex flex-col w-full !my-2 py-1 pl-2 border-l-2
+ text-start text-sm text-neutral-300 text-opacity-80
+ hover:bg-neutral-800 rounded-r-md rounded-l-sm
+ {getFixedRandomColor(rpl.first_name)[1]}"
+ >
+ <span class="line-clamp-1 font-semibold not-italic select-none
+ {getFixedRandomColor(rpl.first_name)[0]}"
+ >
+ {setupUserName(rpl.first_name, rpl.last_name).join("")}
+ </span>
+ <span class="line-clamp-1 max-w-[200px] xl:max-w-[150px] max-h-min text-start">
+ {cleanMessageText(rpl.text !== null ? rpl.text : "Photo")}
+ </span>
+ </button>
+
+ {/each}
+ {/if}
+
+ {#if msg.message_type === "text"}
+ <div
+ class="text-neutral-300 max-w-[200px] xl:max-w-[150px] max-h-min
+ line-clamp-2"
+ >
+ {cleanMessageText(msg.text !== null ? msg.text : "")}
+ </div>
+
+ {:else if msg.message_type === "photo"}
+ <div>
+ <div class="relative">
+ <img
+ src={STORAGE_URL + msg.file}
+ alt=""
+ width="250"
+ class="rounded-md mt-1 relative"
+ >
+ <a
+ href={STORAGE_URL + msg.file}
+ target="_blank"
+ draggable="false"
+ class="absolute top-0 flex items-center justify-center
+ w-full h-full rounded-md hover:bg-neutral-900
+ uppercase hover:bg-opacity-60 transition duration-200
+ ease-in-out font-bold text-xl text-white opacity-0
+ hover:opacity-100 select-none"
+ >
+ See
+ </a>
+ </div>
+
+ {#if msg.text !== null}
+ <div class="text-neutral-300 line-clamp-2 max-w-[200px] xl:max-w-[150px] mt-2">
+ {cleanMessageText(msg.text)}
+ </div>
+
+ {/if}
+ </div>
+
+ {/if}
+
+ <div class="flex items-center justify-between pt-2 space-x-3">
+ <a
+ href="https://t.me/gnuweeb/{msg.message_id}"
+ draggable="false"
+ target="_blank"
+ class="text-xs text-sky-400 opacity-70 font-semibold select-none"
+ >
+ Read more
+ </a>
+ <div class="flex justify-end space-x-1 text-xs opacity-70">
+ <time datetime={msg.date}>{dateFormat(msg.date)}</time>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+ {/each}
+ {/if}
+
+ </div>
+
+ <a href="https://t.me/gnuweeb" draggable="false" target="_blank">
+ <div
+ class="p-3 border-t border-neutral-800 hover:bg-neutral-800
+ flex justify-center items-center w-full"
+ >
+ <span class="select-none font-semibold text-sky-500 mr-1">Join</span>
+ <svg class="w-3 h-3 text-neutral-500" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
+ <path d="M 40.960938 4.9804688 A 2.0002 2.0002 0 0 0 40.740234 5 L 28 5 A 2.0002 2.0002 0 1 0 28 9 L 36.171875 9 L 22.585938 22.585938 A 2.0002 2.0002 0 1 0 25.414062 25.414062 L 39 11.828125 L 39 20 A 2.0002 2.0002 0 1 0 43 20 L 43 7.2460938 A 2.0002 2.0002 0 0 0 40.960938 4.9804688 z M 12.5 8 C 8.3826878 8 5 11.382688 5 15.5 L 5 35.5 C 5 39.617312 8.3826878 43 12.5 43 L 32.5 43 C 36.617312 43 40 39.617312 40 35.5 L 40 26 A 2.0002 2.0002 0 1 0 36 26 L 36 35.5 C 36 37.446688 34.446688 39 32.5 39 L 12.5 39 C 10.553312 39 9 37.446688 9 35.5 L 9 15.5 C 9 13.553312 10.553312 12 12.5 12 L 22 12 A 2.0002 2.0002 0 1 0 22 8 L 12.5 8 z"></path>
+ </svg>
+ </div>
+ </a>
+
+</div>
+
+
+<style lang="postcss">
+ .chat {
+ @apply grid gap-x-3 py-1
+ }
+
+ .chat-start {
+ @apply place-items-start grid-cols-[auto,1fr];
+ }
+
+ .chat-image {
+ @apply row-span-2 self-end;
+ }
+
+ .chat-start .chat-image {
+ @apply col-start-1;
+ }
+
+ .chat-start .chat-header {
+ @apply col-start-2;
+ }
+
+ .chat-bubble {
+ @apply relative block w-fit px-4 py-2 max-w-[90%] rounded-2xl
+ min-h-[2.75rem] min-w-[2.75rem] bg-neutral-900 text-neutral-500;
+ }
+
+ .chat-bubble::before {
+ @apply absolute bottom-0 h-3 w-3 bg-inherit content-[""];
+ mask-size: contain;
+ -webkit-mask-size: contain;
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-position: center;
+ -webkit-mask-position: center;
+ }
+
+ .chat-start .chat-bubble {
+ @apply col-start-2 rounded-bl-none;
+ }
+
+ .chat-start .chat-bubble::before {
+ @apply content-[""] -left-3;
+ mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
+ -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
+ }
+
+ .avatar {
+ @apply relative inline-flex;
+ }
+
+ .avatar > div {
+ @apply block aspect-square overflow-hidden;
+ }
+</style>
--
Muhammad Rizki
next prev parent reply other threads:[~2023-10-03 2:52 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 01/13] refactor: migrate: migrate to sveltekit framework Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 02/13] feat(app): add app types file Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 03/13] feat(lib): add API_URL and STORAGE_URL constant variable Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 04/13] feat(lib): add lib functions file Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 05/13] feat(lib): add newly created lib constants variables and functions Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 06/13] feat(lib/functions): add getRepliedMessage() function Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 07/13] feat(lib/functions): add dateFormat() function Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 08/13] feat(components): add <OrganizationMembers/> component Muhammad Rizki
2023-10-03 2:51 ` Muhammad Rizki [this message]
2023-10-03 2:51 ` [PATCH v1 10/13] feat(routes): add +page.server.ts Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 11/13] feat(routes/page): add +page.svelte Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 12/13] chore(README): update README.md Muhammad Rizki
2023-10-05 19:29 ` Ammar Faizi
2023-10-07 5:36 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 13/13] chore: remove unused files Muhammad Rizki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox