Skip to content

Commit e396022

Browse files
authored
chore(release): v3.0.0 - [CU-869bebnqf] (#169)
2 parents 5046045 + b0f2312 commit e396022

367 files changed

Lines changed: 29711 additions & 4451 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/auto-deploy.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ jobs:
5656
LATEST_TAG=$([[ "${{ github.event.pull_request.base.ref }}" == "main" ]] && echo "latest" || echo "staging-latest")
5757
DEPLOYMENT_URL=$([[ "${{ github.event.pull_request.base.ref }}" == "main" ]] && echo "https://raven.cmp27.space" || echo "https://staging.raven.cmp27.space")
5858
DEPLOYMENT_TARGET=$([[ "${{ github.event.pull_request.base.ref }}" == "main" ]] && echo "Production" || echo "Staging")
59+
DM_WS_URL=$([[ "${{ github.event.pull_request.base.ref }}" == "main" ]] && echo "${{ secrets.NUXT_PUBLIC_DM_WS_URL_MAIN }}" || echo "${{ secrets.NUXT_PUBLIC_DM_WS_URL_DEV }}")
5960
6061
echo "registry=$REGISTRY" >> $GITHUB_OUTPUT
6162
echo "tag=$TAG" >> $GITHUB_OUTPUT
6263
echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
6364
echo "deployment_url=$DEPLOYMENT_URL" >> $GITHUB_OUTPUT
6465
echo "deployment_target=$DEPLOYMENT_TARGET" >> $GITHUB_OUTPUT
66+
echo "dm_ws_url=$DM_WS_URL" >> $GITHUB_OUTPUT
6567
6668
- name: Log in to Docker Hub
6769
uses: docker/login-action@v3
@@ -77,6 +79,7 @@ jobs:
7779
push: true
7880
build-args: |
7981
NUXT_PUBLIC_RECAPTCHA_SITE_KEY=${{ secrets.NUXT_PUBLIC_RECAPTCHA_SITE_KEY }}
82+
NUXT_PUBLIC_DM_WS_URL=${{ steps.image.outputs.dm_ws_url }}
8083
tags: |
8184
"${{ steps.image.outputs.registry }}:${{ steps.image.outputs.tag }}"
8285
"${{ steps.image.outputs.registry }}:${{ steps.image.outputs.latest_tag }}"

.github/workflows/e2e-workflow.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,13 @@ jobs:
6464
6565
- name: Set up Corepack
6666
run: corepack enable
67-
67+
6868
- name: Set up pnpm
6969
run: corepack prepare pnpm@latest --activate
7070

71+
- name: Add pnpm to PATH
72+
run: echo "/home/btngana/.local/share/pnpm" >> $GITHUB_PATH
73+
7174
- uses: actions/setup-node@v4
7275
with:
7376
node-version: 22

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,7 @@ logs
3737
# Cypress screenshots and videos
3838
cypress/screenshots
3939
cypress/videos
40-
.vite-dev-cache
40+
.vite-dev-cache
41+
42+
docs
43+
cypress/results

Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ FROM base AS build
99
ENV NODE_ENV=development
1010

1111
ARG NUXT_PUBLIC_RECAPTCHA_SITE_KEY
12+
ARG NUXT_PUBLIC_DM_WS_URL
1213

1314
ENV NUXT_PUBLIC_RECAPTCHA_SITE_KEY=$NUXT_PUBLIC_RECAPTCHA_SITE_KEY
15+
ENV NUXT_PUBLIC_DM_WS_URL=$NUXT_PUBLIC_DM_WS_URL
1416

1517
# Install dependencies
1618
COPY package.json pnpm-lock.yaml ./
@@ -21,6 +23,12 @@ RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store \
2123
COPY . .
2224
RUN pnpm mock:gen
2325

26+
# change back to production for build
27+
ENV NODE_ENV=production
28+
29+
# Increase memory limit for Node.js during build
30+
ENV NODE_OPTIONS="--max-old-space-size=4096"
31+
2432
# Build Nuxt (SSR)
2533
RUN pnpm build
2634

app/app.vue

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,39 @@ useHead(() => ({
1313
// class: 'dark',
1414
},
1515
}));
16+
17+
const userStore = useUserStore();
18+
19+
const {
20+
connect: connectDmSse,
21+
disconnect: disconnectDmSse,
22+
23+
unseenCount,
24+
lastNewMessageinfo,
25+
lastNotification,
26+
unseenNotificationsCount,
27+
} = useDmSse({
28+
autoReconnect: true,
29+
maxReconnectAttempts: 5,
30+
baseReconnectDelay: 1000,
31+
});
32+
33+
provide('dmUnseenCount', unseenCount);
34+
provide('lastNewMessageinfo', lastNewMessageinfo);
35+
provide('lastNotification', lastNotification);
36+
provide('unseenNotificationsCount', unseenNotificationsCount);
37+
38+
watch(
39+
() => userStore.user,
40+
(newUser, oldUser) => {
41+
if (newUser.username && !oldUser?.username) {
42+
connectDmSse();
43+
} else if (!newUser.username && oldUser?.username) {
44+
disconnectDmSse();
45+
}
46+
},
47+
{ immediate: true },
48+
);
1649
</script>
1750

1851
<template>

app/assets/css/main.css

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
:root {
66
--background: #ffffff;
77
--foreground: #0f1419;
8-
--border: #eff3f4;
8+
--border: #dddddd;
99
--input: #d1d9de;
10+
--muted: #eff3f4;
1011
--muted-foreground: #536471;
12+
--thread-foreground: #cfd9de;
1113
--primary: #1d9bf0;
1214
--brand-red: #f91880;
1315
--brand-blue: #1d9bf0;
@@ -34,8 +36,10 @@
3436
.dark {
3537
--background: #000000;
3638
--foreground: #e7e9ea;
37-
--border: #303336;
39+
--border: #202224;
3840
--input: #536471;
41+
--muted: #202327;
42+
--thread-foreground: #333639;
3943
--muted-foreground: #71767b;
4044
--primary: #3b82f6;
4145
--accent: #16181c;
@@ -63,6 +67,8 @@
6367
--color-background: var(--background);
6468
--color-foreground: var(--foreground);
6569
--color-border: var(--border);
70+
--color-thread-foreground: var(--thread-foreground);
71+
--color-muted: var(--muted);
6672
--color-muted-foreground: var(--muted-foreground);
6773
--color-primary: var(--primary);
6874
--color-accent: var(--accent);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<script setup lang="ts">
2+
const props = defineProps<{
3+
title: string;
4+
subtitle?: string;
5+
to: string;
6+
icon?: string;
7+
}>();
8+
</script>
9+
<template>
10+
<NuxtLink
11+
class="hover:bg-accent flex cursor-pointer items-center justify-between px-4 py-3 transition-colors"
12+
:to="props.to"
13+
>
14+
<div class="flex items-center gap-3">
15+
<Icon v-if="props.icon" :name="props.icon" size="1.2rem" class="text-muted-foreground px-6" />
16+
<div class="flex flex-col">
17+
<span class="text-lg leading-tight font-medium">{{ props.title }}</span>
18+
<span v-if="props.subtitle" class="text-md text-muted-foreground leading-tight">
19+
{{ props.subtitle }}
20+
</span>
21+
</div>
22+
</div>
23+
<Icon :name="$t('setting.item-icon')" size="1.2rem" class="text-muted-foreground" />
24+
</NuxtLink>
25+
</template>
Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,25 @@
11
<script lang="ts" setup>
2-
import { useRouter, useRoute } from 'vue-router';
3-
const router = useRouter();
4-
const route = useRoute();
5-
6-
const isActiveTab = (tabRoute: string) => {
7-
return route.path === tabRoute;
8-
};
2+
import { settingSections } from '~/constants/settings-section';
93
</script>
104
<template>
115
<div>
126
<h2 class="px-4 py-3 text-2xl font-bold">
137
{{ $t('setting.settings') }}
148
</h2>
15-
<div
16-
data-cy="account-settings-btn"
17-
class="text-md mt-10 flex cursor-pointer items-center justify-between px-4 py-[10px] transition-colors"
18-
:class="
19-
isActiveTab('/settings/account')
20-
? 'bg-foreground/10 border-primary border-e-4'
21-
: 'hover:bg-foreground/10'
22-
"
23-
@click="router.push('/settings/account')"
24-
>
25-
<div class="flex flex-col">
26-
<span class="text-lg leading-tight font-medium">{{
27-
$t('setting.account-information')
28-
}}</span>
29-
</div>
30-
<Icon :name="$t('setting.item-icon')" size="1.2rem" class="text-muted-foreground" />
9+
<div class="mt-10 flex flex-col">
10+
<NuxtLink
11+
v-for="settingSetion in settingSections"
12+
:key="settingSetion.route"
13+
:data-cy="settingSetion.cy"
14+
class="text-md hover:bg-accent flex cursor-pointer items-center justify-between border-e-2 border-transparent px-4 py-3 transition-colors"
15+
:to="settingSetion.route"
16+
active-class="border-e-primary bg-accent"
17+
>
18+
<div class="flex flex-col">
19+
<span class="text-lg leading-tight font-medium">{{ $t(settingSetion.title) }}</span>
20+
</div>
21+
<Icon :name="$t('setting.item-icon')" size="1.2rem" class="text-muted-foreground" />
22+
</NuxtLink>
3123
</div>
3224
</div>
3325
</template>

app/components/SideBar/Left/Tab.vue

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<script lang="ts" setup>
2+
import { useNotificationSound } from '@/composables/useNotificationSound';
3+
24
const props = defineProps<{
35
tab: LeftSidebarTab;
46
}>();
@@ -10,18 +12,35 @@ const isActive = computed(() => {
1012
});
1113
const textStyle = computed(() => (isActive.value ? 'font-bold' : 'font-normal'));
1214
const iconType = computed(() => (isActive.value ? '' : 'outline-'));
15+
const { play } = useNotificationSound();
16+
17+
watch(
18+
() => props.tab.badgeCount,
19+
(newCount, oldCount) => {
20+
if (oldCount === undefined || newCount === undefined) return;
21+
if (newCount > oldCount) {
22+
play();
23+
}
24+
},
25+
);
1326
</script>
1427

1528
<template>
1629
<NuxtLink
1730
:to="tab.route"
18-
class="text-foreground hover:bg-foreground/10 flex items-center justify-start rounded-full p-3 xl:w-auto"
31+
class="text-foreground hover:bg-foreground/10 flex items-center justify-start rounded-full p-4 xl:w-auto"
1932
>
20-
<div class="text-foreground flex h-6 w-6 items-center justify-center">
21-
<Icon :name="`ic:${iconType}${tab.icon}`" size="24" />
33+
<div class="text-foreground relative flex h-8 w-8 items-center justify-center">
34+
<Icon :name="`ic:${iconType}${tab.icon}`" size="28" />
35+
<span
36+
v-if="tab.badgeCount && tab.badgeCount > 0"
37+
class="bg-primary text-primary-foreground absolute -top-3 -me-1 inline-flex h-6 min-w-[22px] items-center justify-center rounded-full px-1.5 text-[11px] leading-none font-semibold"
38+
>
39+
{{ tab.badgeCount > 99 ? '99+' : tab.badgeCount }}
40+
</span>
2241
</div>
2342

24-
<div class="ms-3 hidden text-xl xl:block" :class="textStyle">
43+
<div class="ms-4 hidden text-xl xl:block" :class="textStyle">
2544
{{ $t(`leftsidebar.nav.${tab.label}`) }}
2645
</div>
2746
</NuxtLink>

app/components/SideBar/Left/index.vue

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import { useQueryClient } from '@tanstack/vue-query';
44
import { ref } from 'vue';
55
import { useI18n } from '#imports';
66
import { useTheme } from '~/composables/useTheme';
7+
import Avatar from '~/components/ui/Avatar.vue';
8+
9+
const dmUnseenCount = inject<Ref<number>>('dmUnseenCount', ref(0));
10+
const notificationUnseenCount = inject<Ref<number>>('unseenNotificationsCount', ref(0));
711
812
const { locale, setLocale } = useI18n();
913
const { mode, toggleTheme } = useTheme();
@@ -13,7 +17,7 @@ const queryClient = useQueryClient();
1317
1418
const handleLogout = async () => {
1519
await loginService.logout();
16-
queryClient.removeQueries({ queryKey: ['layout-data'] });
20+
await queryClient.clear();
1721
};
1822
1923
const lang = ref(locale.value);
@@ -41,10 +45,20 @@ const switchLanguage = () => {
4145
:tab="{ label: 'explore', icon: 'search', route: '/explore' }"
4246
></SideBarLeftTab>
4347
<SideBarLeftTab
44-
:tab="{ label: 'notifications', icon: 'notifications', route: '/notifications' }"
48+
:tab="{
49+
label: 'notifications',
50+
icon: 'notifications',
51+
route: '/notifications',
52+
badgeCount: notificationUnseenCount,
53+
}"
4554
></SideBarLeftTab>
4655
<SideBarLeftTab
47-
:tab="{ label: 'messages', icon: 'chat', route: '/messages' }"
56+
:tab="{
57+
label: 'messages',
58+
icon: 'chat',
59+
route: '/messages',
60+
badgeCount: dmUnseenCount,
61+
}"
4862
></SideBarLeftTab>
4963
<SideBarLeftTab
5064
:tab="{
@@ -54,7 +68,7 @@ const switchLanguage = () => {
5468
}"
5569
></SideBarLeftTab>
5670
<SideBarLeftTab
57-
:tab="{ label: 'settings', icon: 'settings', route: '/settings/account' }"
71+
:tab="{ label: 'settings', icon: 'settings', route: '/settings' }"
5872
data-cy="sidebar-settings-btn"
5973
></SideBarLeftTab>
6074
<UiButton variant="ghost-default" size="icon-xl" @click="switchLanguage">
@@ -68,14 +82,63 @@ const switchLanguage = () => {
6882
size="24"
6983
/>
7084
</UiButton>
71-
<UiButton
72-
variant="ghost-default"
73-
size="icon-xl"
74-
data-cy="logout-button"
75-
@click="handleLogout"
76-
>
77-
<Icon name="ic:outline-logout" size="24" />
78-
</UiButton>
85+
</div>
86+
<div class="flex w-full flex-grow p-2 pb-4">
87+
<UiAlertDialog>
88+
<UiDropdownMenu>
89+
<UiDropdownMenuTrigger as-child>
90+
<UiButton
91+
variant="ghost-default"
92+
size="2xl"
93+
class="mx-auto mt-auto xl:w-full"
94+
data-cy="logout-btn-trigger"
95+
>
96+
<div class="flex w-full items-center gap-3">
97+
<Avatar
98+
:img="userStore.user?.avatarUrl || ''"
99+
:alt="userStore.user?.displayName || 'User Avatar'"
100+
size="sm"
101+
/>
102+
<div class="hidden text-start xl:block">
103+
<p>{{ userStore.user?.displayName || 'User' }}</p>
104+
<p class="text-muted-foreground text-sm">
105+
{{ '@' + (userStore.user?.username || 'username') }}
106+
</p>
107+
</div>
108+
<div class="ms-auto hidden xl:flex">
109+
<Icon name="lucide:more-horizontal" class="pe-2" />
110+
</div>
111+
</div>
112+
</UiButton>
113+
</UiDropdownMenuTrigger>
114+
<UiDropdownMenuContent align="center" class="bg-background">
115+
<UiAlertDialogTrigger>
116+
<UiDropdownMenuItem data-cy="logout-button">
117+
{{ $t('ui.logout.label', { username: userStore.user?.username || 'username' }) }}
118+
</UiDropdownMenuItem>
119+
</UiAlertDialogTrigger>
120+
</UiDropdownMenuContent>
121+
</UiDropdownMenu>
122+
123+
<UiAlertDialogContent>
124+
<UiAlertDialogHeader>
125+
<UiAlertDialogTitle>
126+
{{ $t('ui.logout.title') }}
127+
</UiAlertDialogTitle>
128+
<UiAlertDialogDescription>
129+
{{ $t('ui.logout.description') }}
130+
</UiAlertDialogDescription>
131+
</UiAlertDialogHeader>
132+
<UiAlertDialogFooter>
133+
<UiAlertDialogAction data-cy="confirm-logout-button" @click="handleLogout">
134+
{{ $t('ui.logout.confirm') }}
135+
</UiAlertDialogAction>
136+
<UiAlertDialogCancel>
137+
{{ $t('ui.cancel') }}
138+
</UiAlertDialogCancel>
139+
</UiAlertDialogFooter>
140+
</UiAlertDialogContent>
141+
</UiAlertDialog>
79142
</div>
80143
</div>
81144
</template>

0 commit comments

Comments
 (0)