mirror of
https://github.com/versia-pub/frontend.git
synced 2025-12-06 08:28:20 +01:00
feat: ✨ Add Enum preference type support
This commit is contained in:
parent
ca824a2a1a
commit
dca7af4b0e
46
components/preferences/select.vue
Normal file
46
components/preferences/select.vue
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<template>
|
||||
<Card class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
|
||||
<CardHeader class="space-y-0.5 p-0">
|
||||
<CardTitle class="text-base">
|
||||
{{ setting.title }}
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
{{ setting.description }}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter class="p-0">
|
||||
<Select :model-value="setting.value" @update:model-value="v => { setting.value = v }">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select an option" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="option of setting.options" :value="option.value">
|
||||
{{ option.label }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
Card,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "~/components/ui/card";
|
||||
import type { EnumSetting } from "~/settings.ts";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "../ui/select";
|
||||
|
||||
defineModel<EnumSetting>("setting", {
|
||||
required: true,
|
||||
});
|
||||
</script>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<Card class="grid grid-cols-[1fr,auto] items-center p-6">
|
||||
<Card class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
|
||||
<CardHeader class="space-y-0.5 p-0">
|
||||
<CardTitle class="text-base">
|
||||
{{ setting.title }}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<Avatar shape="square">
|
||||
<Avatar :shape="(shape.value as 'circle' | 'square')">
|
||||
<AvatarFallback v-if="name">
|
||||
{{ getInitials(name) }}
|
||||
</AvatarFallback>
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { SettingIds } from "~/settings";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
|
||||
|
||||
const { name } = defineProps<{
|
||||
|
|
@ -28,4 +29,6 @@ const getInitials = (name: string): string => {
|
|||
|
||||
return `${firstLetter}${secondLetter}`.toUpperCase();
|
||||
};
|
||||
|
||||
const shape = useSetting(SettingIds.AvatarShape);
|
||||
</script>
|
||||
|
|
@ -13,8 +13,11 @@ import {
|
|||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "~/components/ui/sidebar";
|
||||
import { SettingIds } from "~/settings";
|
||||
import LeftSidebar from "./left-sidebar.vue";
|
||||
import RightSidebar from "./right-sidebar.vue";
|
||||
|
||||
const showRightSidebar = useSetting(SettingIds.NotificationsSidebar);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -45,6 +48,6 @@ import RightSidebar from "./right-sidebar.vue";
|
|||
<slot />
|
||||
</div>
|
||||
</SidebarInset>
|
||||
<RightSidebar v-if="identity" />
|
||||
<RightSidebar v-if="identity" v-show="showRightSidebar.value" />
|
||||
</SidebarProvider>
|
||||
</template>
|
||||
|
|
|
|||
34
components/timelines/global.vue
Normal file
34
components/timelines/global.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<template>
|
||||
<Timeline type="status" :items="(items as Status[])" :is-loading="isLoading" :has-reached-end="hasReachedEnd"
|
||||
:error="error" :load-next="loadNext" :load-prev="loadPrev" :remove-item="removeItem"
|
||||
:update-item="updateItem" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Status } from "@versia/client/types";
|
||||
import { useGlobalTimeline } from "~/composables/GlobalTimeline";
|
||||
import Timeline from "./timeline.vue";
|
||||
|
||||
const {
|
||||
error,
|
||||
hasReachedEnd,
|
||||
isLoading,
|
||||
items,
|
||||
loadNext,
|
||||
loadPrev,
|
||||
removeItem,
|
||||
updateItem,
|
||||
} = useGlobalTimeline(client.value);
|
||||
|
||||
useListen("note:delete", ({ id }) => {
|
||||
removeItem(id);
|
||||
});
|
||||
|
||||
useListen("note:edit", (updatedNote) => {
|
||||
updateItem(updatedNote);
|
||||
});
|
||||
|
||||
useListen("composer:send", () => {
|
||||
loadPrev();
|
||||
});
|
||||
</script>
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
<template>
|
||||
<div class="timeline rounded">
|
||||
<TransitionGroup name="timeline-item" tag="div"
|
||||
class="timeline-items *:rounded space-y-4 *:border *:border-border/50">
|
||||
class="timeline-items *:rounded space-y-4 *:border">
|
||||
<TimelineItem :type="type" v-for="item in items" :key="item.id" :item="item" @update="updateItem"
|
||||
@delete="removeItem" />
|
||||
</TransitionGroup>
|
||||
|
|
|
|||
14
composables/GlobalTimeline.ts
Normal file
14
composables/GlobalTimeline.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import type { Client } from "@versia/client";
|
||||
import type { Status } from "@versia/client/types";
|
||||
import { type TimelineOptions, useTimeline } from "./Timeline";
|
||||
|
||||
export function useGlobalTimeline(
|
||||
client: Client,
|
||||
options: Partial<TimelineOptions<Status>> = {},
|
||||
) {
|
||||
return useTimeline(client, {
|
||||
// TODO: Implement global timeline in client sdk
|
||||
fetchFunction: (client, opts) => client.getPublicTimeline(opts),
|
||||
...options,
|
||||
});
|
||||
}
|
||||
16
pages/global.vue
Normal file
16
pages/global.vue
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<div class="mx-auto max-w-2xl w-full">
|
||||
<TimelineScroller>
|
||||
<Global />
|
||||
</TimelineScroller>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Global from "~/components/timelines/global.vue";
|
||||
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
||||
|
||||
definePageMeta({
|
||||
layout: "app",
|
||||
});
|
||||
</script>
|
||||
|
|
@ -6,15 +6,18 @@
|
|||
<div class="grid grid-cols-1 2xl:grid-cols-2 gap-4 mt-6">
|
||||
<template v-for="[id, setting] of settingEntries">
|
||||
<SwitchPreference v-if="setting.type === SettingType.Boolean" :setting="(setting as BooleanSetting)" @update:setting="updateSetting(id, setting)" />
|
||||
<SelectPreference v-else-if="setting.type === SettingType.Enum" :setting="(setting as EnumSetting)" @update:setting="updateSetting(id, setting)" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import SelectPreference from "~/components/preferences/select.vue";
|
||||
import SwitchPreference from "~/components/preferences/switch.vue";
|
||||
import {
|
||||
type BooleanSetting,
|
||||
type EnumSetting,
|
||||
type Setting,
|
||||
type SettingIds,
|
||||
type SettingPages,
|
||||
|
|
|
|||
26
settings.ts
26
settings.ts
|
|
@ -80,6 +80,8 @@ export enum SettingIds {
|
|||
CtrlEnterToSend = "ctrl-enter-to-send",
|
||||
EmojiTheme = "emoji-theme",
|
||||
BackgroundURL = "background-url",
|
||||
NotificationsSidebar = "notifications-sidebar",
|
||||
AvatarShape = "avatar-shape",
|
||||
}
|
||||
|
||||
export const settings: Record<SettingIds, Setting> = {
|
||||
|
|
@ -91,6 +93,23 @@ export const settings: Record<SettingIds, Setting> = {
|
|||
page: SettingPages.Behaviour,
|
||||
notImplemented: true,
|
||||
} as BooleanSetting,
|
||||
[SettingIds.AvatarShape]: {
|
||||
title: "Avatar Shape",
|
||||
description: "Shape of all user avatars.",
|
||||
type: SettingType.Enum,
|
||||
value: "square",
|
||||
options: [
|
||||
{
|
||||
value: "circle",
|
||||
label: "Round",
|
||||
},
|
||||
{
|
||||
value: "square",
|
||||
label: "Square",
|
||||
},
|
||||
],
|
||||
page: SettingPages.Appearance,
|
||||
} as EnumSetting,
|
||||
[SettingIds.CustomCSS]: {
|
||||
title: "Custom CSS",
|
||||
description: "Custom CSS for the UI.",
|
||||
|
|
@ -222,6 +241,13 @@ export const settings: Record<SettingIds, Setting> = {
|
|||
value: "",
|
||||
page: SettingPages.Appearance,
|
||||
} as StringSetting,
|
||||
[SettingIds.NotificationsSidebar]: {
|
||||
title: "Notifications Sidebar",
|
||||
description: "Display a sidebar with notifications on desktop.",
|
||||
type: SettingType.Boolean,
|
||||
value: true,
|
||||
page: SettingPages.Appearance,
|
||||
} as BooleanSetting,
|
||||
};
|
||||
|
||||
export const getSettingsForPage = (page: SettingPages): Partial<Settings> => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue