Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat(web): Convo Viewer #41

Merged
merged 41 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
7b132f9
fix user redirect link
McPizza0 Jan 19, 2024
170a6e5
update avatar component
McPizza0 Jan 24, 2024
3f7953b
new convo redirect
McPizza0 Jan 24, 2024
dbcee16
fix navbar avatar bug
McPizza0 Jan 25, 2024
110bc2d
update UnUiAvatar to accept correct colors
McPizza0 Jan 25, 2024
8fdc567
DB update convo relationships to use "participants"
McPizza0 Jan 25, 2024
c6497a3
dedicated convo avatar
McPizza0 Jan 26, 2024
bd1e820
inital convo messages components
McPizza0 Jan 26, 2024
792beab
update convo page
McPizza0 Jan 26, 2024
09487c9
newConvo page update types
McPizza0 Jan 26, 2024
c73e72e
trpc update convo + entries endpoints
McPizza0 Jan 26, 2024
5844718
remove misc
McPizza0 Jan 26, 2024
d51bdd3
update tailwind safelist
McPizza0 Jan 26, 2024
9ae3f2e
Merge branch 'main' into feat/convoViewer
McPizza0 Jan 29, 2024
e664996
Merge branch 'main' into feat/convoViewer
McPizza0 Jan 29, 2024
60ef701
Merge branch 'main' into feat/convoViewer
McPizza0 Jan 29, 2024
0960be2
Merge branch 'main' into feat/convoViewer
McPizza0 Jan 29, 2024
cb4d766
fix(db): :bug: set convo lastUpdatedAt to notNull
McPizza0 Jan 30, 2024
1ebcd96
feat(web): :sparkles: add getUserQuery trpc endpoint
McPizza0 Jan 30, 2024
181e111
remove avatar list
McPizza0 Jan 30, 2024
b2d03c2
add popover component
McPizza0 Jan 30, 2024
6222f76
add virtualScroller component plugin
McPizza0 Jan 30, 2024
4cfc55c
fix load avatarId
McPizza0 Jan 30, 2024
a6215fe
remove sidebar comment hydration error
McPizza0 Jan 30, 2024
14606a5
remove comment
McPizza0 Jan 30, 2024
1f1f438
switch convo loading to use status
McPizza0 Jan 30, 2024
9d25e13
add query keys
McPizza0 Jan 30, 2024
e6c1b4f
implement convolist
McPizza0 Jan 30, 2024
0303e61
Merge branch 'main' into feat/convoViewer
McPizza0 Jan 30, 2024
df91554
Merge branch 'main' into feat/convoViewer
McPizza0 Jan 31, 2024
bf7b68a
Update apps/web-app/components/convos/convoList.vue
McPizza0 Feb 1, 2024
dab24b7
Update apps/web-app/components/convos/convoMessages.vue
McPizza0 Feb 1, 2024
c7ba605
Update apps/web-app/components/convos/convoMessages.vue
McPizza0 Feb 1, 2024
d2f772c
Update apps/web-app/components/un/ui-avatar-plus.vue
McPizza0 Feb 1, 2024
7937232
Update apps/web-app/components/convos/convoMessages.vue
McPizza0 Feb 1, 2024
224f58b
add new convo util useParticipantData
McPizza0 Feb 1, 2024
f155b4f
update convoAvatar component
McPizza0 Feb 1, 2024
1829d6f
update utils to use types imports
McPizza0 Feb 1, 2024
7a2188d
update convo view to use new util
McPizza0 Feb 1, 2024
8413d86
refactor convoListItem codes
McPizza0 Feb 1, 2024
83686cf
update code/remove comments
McPizza0 Feb 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions apps/web-app/components/convos/convoAvatar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script setup lang="ts">
import type { ConvoParticipantEntry } from '~/composables/types';
type Props = {
participant: ConvoParticipantEntry;
size?: 'xs' | 'sm' | 'md' | 'lg';
};

const props = defineProps<Props>();
</script>
<template>
<UnUiAvatar
v-if="props.participant"
:avatar-id="props.participant.avatarPublicId"
:public-id="props.participant.avatarPublicId"
:alt="props.participant.name"
:type="props.participant.type"
:color="props.participant.color"
:show-icon="true"
:size="props.size ? props.size : 'sm'" />
</template>
186 changes: 107 additions & 79 deletions apps/web-app/components/convos/convoList.vue
Original file line number Diff line number Diff line change
@@ -1,104 +1,132 @@
<script setup lang="ts">
import { useVirtualList, useInfiniteScroll } from '@vueuse/core';
import { useConvoStore } from '@/stores/convoStore';
import { useInfiniteScroll } from '@vueuse/core';
const { $trpc } = useNuxtApp();

// const convoStore = useConvoStore();
// if (process.client && convoStore.convos.length === 0) {
// await convoStore.getInitialConvos();
// }
// console.log(convoStore.convos.length);
const orgSlug = useRoute().params.orgSlug as string;
const infiniteContainer = ref<HTMLElement | null>(null);

const convosPending = ref(true);
const convos = ref<UserConvosDataType>([]);
const convoCursor = {
lastUpdatedAt: null as Date | null,
lastPublicId: null as string | null
};
const getInitialConvos = async () => {
convos.value = [];
if (convos.value.length !== 0) return;
const { data: userConvos } = await $trpc.convos.getUserConvos.useLazyQuery(
{}
);
if (!userConvos.value) {
convosPending.value = false;
return;
}
convos.value.push(...userConvos.value.data);
convoCursor.lastUpdatedAt = userConvos.value.cursor.lastUpdatedAt;
convoCursor.lastPublicId = userConvos.value.cursor.lastPublicId;
convosPending.value = false;
return;
};
const getNextConvos = async () => {
if (
convoCursor.lastUpdatedAt !== null &&
convoCursor.lastPublicId !== null
) {
const { data: userConvos } =
await $trpc.convos.getUserConvos.useLazyQuery({
cursorLastUpdatedAt: convoCursor.lastUpdatedAt,
cursorLastPublicId: convoCursor.lastPublicId
});
if (!userConvos.value) return;
convos.value.push(...userConvos.value.data);
convoCursor.lastUpdatedAt = userConvos.value.cursor.lastUpdatedAt;
convoCursor.lastPublicId = userConvos.value.cursor.lastPublicId;
}
};
const convoCursor = ref<{
cursorLastUpdatedAt: Date | null;
cursorLastPublicId: string | null;
}>({
cursorLastUpdatedAt: null,
cursorLastPublicId: null
});
const userHasMoreConvos = ref(true);
const pauseLoading = ref(false);
const convos = ref<{}[]>([]);

type UserConvoQueryParams =
| {
cursorLastUpdatedAt: Date;
cursorLastPublicId: string;
}
| {};
const userConvoQueryParams = ref<UserConvoQueryParams>({});
const userConvoQueryPending = computed(() => {
return userConvosStatus.value === 'idle';
});
const userHasConvos = computed(() => {
return convos.value.length > 0;
});

const { list, containerProps, wrapperProps } = useVirtualList(convos.value, {
itemHeight: 127 + 16,
overscan: 3
const {
data: userConvosData,
status: userConvosStatus,
execute: getUserConvos
} = await $trpc.convos.getUserConvos.useLazyQuery(userConvoQueryParams, {
server: false,
queryKey: `userConvos-${orgSlug}`,
immediate: false,
watch: [userConvoQueryParams]
});

watch(
userConvosData,
(newVal) => {
if (!newVal) return;
if (!newVal.data || !newVal.cursor || newVal.data.length === 0) {
userHasMoreConvos.value = false;
return;
}
convos.value.push(...newVal.data);
convoCursor.value.cursorLastUpdatedAt = newVal.cursor.lastUpdatedAt;
convoCursor.value.cursorLastPublicId = newVal.cursor.lastPublicId;
},
{
immediate: true,
deep: true
}
);

useInfiniteScroll(
containerProps.ref,
() => {
getNextConvos();
infiniteContainer,
async () => {
if (pauseLoading.value) return;
if (!userHasMoreConvos.value) return;
if (userConvosStatus.value === 'pending') return;
pauseLoading.value = true;
userConvoQueryParams.value = {
cursorLastUpdatedAt: convoCursor.value.cursorLastUpdatedAt,
cursorLastPublicId: convoCursor.value.cursorLastPublicId
};
pauseLoading.value = false;
},
{ distance: 300 }
{ distance: 100, canLoadMore: () => userHasMoreConvos.value }
);
onMounted(async () => {
if (process.client) {
await getInitialConvos();
}

onMounted(() => {
if (convos.value.length === 0) getUserConvos();
});
</script>
<template>
<div
class="h-full max-h-full max-w-full w-full overflow-y-scroll"
v-bind="containerProps">
<div class="h-full max-h-full max-w-full w-full overflow-hidden">
<div
v-if="!convosPending"
class="mb-[48px] flex flex-col items-start gap-4"
v-bind="wrapperProps">
<div
v-if="convosPending"
class="w-full flex flex-row justify-center gap-4 rounded-xl rounded-tl-2xl bg-base-3 p-8">
<UnUiIcon
name="i-svg-spinners:3-dots-fade"
size="24" />
<span>Loading conversations</span>
</div>
v-if="userConvoQueryPending"
class="w-full flex flex-row justify-center gap-4 rounded-xl rounded-tl-2xl bg-base-3 p-8">
<UnUiIcon
name="i-svg-spinners:3-dots-fade"
size="24" />
<span>Loading conversations</span>
</div>
<div
v-if="!userConvoQueryPending"
class="mb-[48px] max-h-full flex flex-col items-start gap-4 overflow-hidden">
<div
v-if="!convosPending && convos.length === 0"
v-if="!userHasConvos"
class="w-full flex flex-row justify-center gap-4 rounded-xl rounded-tl-2xl bg-base-3 p-8">
<UnUiIcon
name="i-ph-chat-circle"
size="24" />
<span>No conversations found</span>
</div>
<div
v-if="!convosPending && convos.length !== 0"
class="max-w-full">
v-if="userHasConvos"
ref="infiniteContainer"
class="h-full max-h-full max-w-full w-full overflow-scroll">
<DynamicScroller
:items="convos"
key-field="publicId"
:min-item-size="48">
<template #default="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependacies="[item.data]"
:data-index="index"
class="pb-4"
@click="navigateTo(`/${orgSlug}/convo/${item.publicId}`)">
<convos-convo-list-item :convo="item" />
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div
v-for="convo of list"
:id="convo.data.publicId"
:key="convo.index"
class="max-w-full"
@click="navigateTo(`/h/convo/${convo.data.publicId}`)">
<convos-convo-list-item :convo="convo.data" />
v-if="userHasMoreConvos && pauseLoading"
class="w-full flex flex-row justify-center gap-4 rounded-xl rounded-tl-2xl bg-base-3 p-8">
<UnUiIcon
name="i-svg-spinners:3-dots-fade"
size="24" />
<span>Loading more conversations</span>
</div>
</div>
</div>
Expand Down
Loading