import { bindToPage, pageEffect, bindPageTitle, onPageShow, } from "/js/router.js"; import { html, render } from "/js/lib/lit-html.js"; import { headerTemplate } from "/js/templates/header.template.js"; import { formatRelativeTime } from "/js/utils.js"; import { getConvoPreviewText, getDisplayName, getGroupConvoDetails, getLastInteraction, getInteractionTimestamp, MISSING_HANDLE, } from "/js/dataHelpers.js"; import { avatarTemplate } from "/js/templates/avatar.template.js"; import { avatarGroupTemplate } from "/js/templates/avatarGroup.template.js"; import "/js/components/infinite-scroll-container.js"; import "/js/components/container-link.js"; import "/js/components/app-icon.js"; import { tryAgainButtonTemplate } from "/js/templates/tryAgainButton.template.js"; export default async function chatView({ root, router, layout, context: { auth, dataLayer, chatNotificationService, newChatService }, }) { await auth.requireAuth(); async function handleMenuClick() { layout.openSidebar(); } function handleNewChatClick() { newChatService.openNewChatDialog(); } function newChatButtonTemplate() { return html` `; } function convoItemTemplate({ convo, currentUser }) { const groupDetails = getGroupConvoDetails(convo); const lastInteraction = getLastInteraction(convo); const otherMembers = convo.members.filter( (member) => member.did !== currentUser?.did, ); const otherUser = groupDetails ? null : otherMembers[0]; const timeAgo = lastInteraction ? formatRelativeTime(getInteractionTimestamp(lastInteraction)) : ""; const isUnread = convo.unreadCount > 0; return html`
${(() => { if (groupDetails) { return avatarGroupTemplate({ authors: otherMembers }); } return otherUser ? avatarTemplate({ author: otherUser }) : html`
`; })()}
${groupDetails ? groupDetails.name : getDisplayName(otherUser)} ${convo.muted ? html`` : ""}
${timeAgo ? html`
${timeAgo}
` : ""}
${!groupDetails && otherUser?.handle && otherUser?.handle !== MISSING_HANDLE ? `@${otherUser.handle}` : ""}
${lastInteraction ? getConvoPreviewText(lastInteraction, { currentUser, convo, profiles: dataLayer.derived.$convoProfiles.get(convo.id), }) : "No messages yet"}
`; } function convoSkeletonTemplate() { return html` ${Array.from({ length: 8 }).map( () => html`
`, )} `; } function inboxButtonTemplate({ hasUnreadRequests }) { return html` ${hasUnreadRequests ? html`
` : ""}
`; } function convosTemplate({ convos, hasMore, currentUser }) { if (convos.length === 0) { return html`
No conversations yet!
`; } return html` { if (hasMore) { await loadConvoList(); e.detail.resume(); } }} > ${convos.map((convo) => convoItemTemplate({ convo, currentUser }))} ${hasMore ? convoSkeletonTemplate() : ""} `; } function convosErrorTemplate({ error }) { console.error(error); return html`
There was an error loading conversations.
${tryAgainButtonTemplate()}
`; } async function loadPageData() { await loadConvoList({ reload: true }); } onPageShow(root, ({ action }) => { if (action === "restore") return; loadPageData(); }); bindToPage(root, layout, "active-nav-click", () => { loadPageData(); }); bindPageTitle(root, () => "Messages"); pageEffect(root, () => { const currentUser = dataLayer.derived.$currentUser.get(); const convos = dataLayer.derived.$convoList.get(); const convosRequestStatus = dataLayer.requests.statusStore.$statuses.get("loadConvoList"); const cursor = dataLayer.derived.$convoListCursor.get(); const hasMore = !!cursor; const hasUnreadRequests = (chatNotificationService?.$numUnreadRequestConvos.get() ?? 0) > 0; render( html`
${headerTemplate({ title: "Chats", showLoadingSpinner: convosRequestStatus.loading && !!convos, leftButton: "menu", onClickMenuButton: () => handleMenuClick(), rightItemTemplate: () => html`
${inboxButtonTemplate({ hasUnreadRequests })} ${newChatButtonTemplate()}
`, })}
${(() => { if (convosRequestStatus.error) { return convosErrorTemplate({ error: convosRequestStatus.error, }); } else if (convos && currentUser) { const acceptedConvos = convos.filter( (convo) => convo.status === "accepted", ); return convosTemplate({ currentUser, convos: acceptedConvos, hasMore, }); } else { return convoSkeletonTemplate(); } })()}
`, root, ); }); async function loadConvoList({ reload = false } = {}) { await dataLayer.requests.loadConvoList({ reload, limit: 30, }); } }