Skip to content

Commit c509d23

Browse files
committed
Add multi-device MFA support
1 parent 1fc0398 commit c509d23

File tree

4 files changed

+385
-53
lines changed

4 files changed

+385
-53
lines changed

app/components/Settings/ConnectTeamSpeak.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ const serverSelectModel = computed<SelectOption[] | undefined>({
106106
const identities = computed(() => localIdentities.value)
107107
const hasLinkedIdentities = computed(() => identities.value.length > 0)
108108
const buttonLabel = computed(() => hasLinkedIdentities.value ? 'Manage TeamSpeak' : 'Connect TeamSpeak')
109+
const isProfileLoading = computed(() => props.profile === null)
109110
const stepBadge = computed(() => {
110111
switch (step.value) {
111112
case 'manage':
@@ -410,7 +411,8 @@ function safeParseJson(input: string): unknown {
410411
variant="fill"
411412
class="teamspeak-manage"
412413
:expand="isBelowMedium"
413-
:disabled="!hasServers"
414+
:loading="isProfileLoading"
415+
:disabled="isProfileLoading || !hasServers"
414416
@click="openModal"
415417
>
416418
<template #start>

app/components/Settings/ConnectionsCard.vue

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { reactive, ref, watch } from 'vue'
55
import SharedErrorToast from '@/components/Shared/ErrorToast.vue'
66
import TinyBadge from '@/components/Shared/TinyBadge.vue'
77
import { useBreakpoint } from '@/lib/mediaQuery'
8+
import { normalizeTeamSpeakIdentities } from '@/lib/teamspeak'
89
910
const props = defineProps<{ profile: Tables<'profiles'> | null }>()
1011
const emit = defineEmits<{ (e: 'updated'): void }>()
@@ -26,6 +27,9 @@ const ConnectTeamspeak = defineAsyncComponent(() => import('@/components/Setting
2627
const richPresenceEnabled = ref(!(props.profile?.rich_presence_disabled ?? false))
2728
const richPresenceLoading = ref(false)
2829
30+
const hasTeamSpeakConnected = computed(() => normalizeTeamSpeakIdentities(props.profile?.teamspeak_identities).length > 0)
31+
const isProfileLoading = computed(() => props.profile === null)
32+
2933
watch(
3034
() => props.profile?.rich_presence_disabled,
3135
(disabled) => {
@@ -202,7 +206,17 @@ function toggleRichPresence() {
202206

203207
<div class="account-status" :style="{ width: isBelowSmall ? '100%' : undefined }">
204208
<Button
205-
v-if="props.profile?.patreon_id"
209+
v-if="isProfileLoading"
210+
:expand="isBelowSmall"
211+
variant="fill"
212+
:loading="true"
213+
disabled
214+
aria-disabled="true"
215+
>
216+
Loading
217+
</Button>
218+
<Button
219+
v-else-if="props.profile?.patreon_id"
206220
:expand="isBelowSmall"
207221
variant="danger"
208222
:loading="disconnectLoading.patreon"
@@ -246,7 +260,17 @@ function toggleRichPresence() {
246260
</Flex>
247261

248262
<div class="account-status" :style="{ width: isBelowSmall ? '100%' : undefined }">
249-
<ClientOnly v-if="!props.profile?.steam_id">
263+
<Button
264+
v-if="isProfileLoading"
265+
:expand="isBelowSmall"
266+
variant="fill"
267+
:loading="true"
268+
disabled
269+
aria-disabled="true"
270+
>
271+
Loading
272+
</Button>
273+
<ClientOnly v-else-if="!props.profile?.steam_id">
250274
<ConnectSteam :expand="isBelowSmall" @linked="emit('updated')" />
251275
</ClientOnly>
252276
</div>
@@ -283,7 +307,17 @@ function toggleRichPresence() {
283307

284308
<div class="account-status" :style="{ width: isBelowSmall ? '100%' : undefined }">
285309
<Button
286-
v-if="props.profile?.discord_id"
310+
v-if="isProfileLoading"
311+
:expand="isBelowSmall"
312+
variant="fill"
313+
:loading="true"
314+
disabled
315+
aria-disabled="true"
316+
>
317+
Loading
318+
</Button>
319+
<Button
320+
v-else-if="props.profile?.discord_id"
287321
:expand="isBelowSmall"
288322
variant="danger"
289323
:loading="disconnectLoading.discord"
@@ -313,15 +347,31 @@ function toggleRichPresence() {
313347
<Icon name="mdi:teamspeak" size="20" />
314348
</div>
315349
<Flex column expand class="account-row">
316-
<strong>TeamSpeak</strong>
350+
<Flex expand gap="s" y-center wrap :x-between="isBelowSmall">
351+
<strong>TeamSpeak</strong>
352+
<TinyBadge v-if="hasTeamSpeakConnected" variant="success">
353+
<Icon class="text-color-accent" name="ph:check" />
354+
Connected
355+
</TinyBadge>
356+
</Flex>
317357
<p class="text-xs text-color-lighter">
318358
Link your TeamSpeak identities to receive server access and roles
319359
</p>
320360
</Flex>
321361
</Flex>
322362

323363
<div class="account-status teamspeak-actions" :style="{ width: isBelowSmall ? '100%' : undefined }">
324-
<ClientOnly>
364+
<Button
365+
v-if="isProfileLoading"
366+
:expand="isBelowSmall"
367+
variant="fill"
368+
:loading="true"
369+
disabled
370+
aria-disabled="true"
371+
>
372+
Loading
373+
</Button>
374+
<ClientOnly v-else>
325375
<ConnectTeamspeak :profile="props.profile" @linked="emit('updated')" />
326376
</ClientOnly>
327377
</div>

0 commit comments

Comments
 (0)