mirror of
https://github.com/versia-pub/frontend.git
synced 2025-12-06 08:28:20 +01:00
refactor: 🌐 Internationalize every string
This commit is contained in:
parent
8c3ddc2a28
commit
2ceee4827f
4
app.vue
4
app.vue
|
|
@ -19,10 +19,14 @@ import "~/styles/index.css";
|
||||||
import { convert } from "html-to-text";
|
import { convert } from "html-to-text";
|
||||||
import ConfirmationModal from "./components/modals/confirm.vue";
|
import ConfirmationModal from "./components/modals/confirm.vue";
|
||||||
import { Toaster } from "./components/ui/sonner";
|
import { Toaster } from "./components/ui/sonner";
|
||||||
|
import { setLanguageTag } from "./paraglide/runtime";
|
||||||
import { type EnumSetting, SettingIds } from "./settings";
|
import { type EnumSetting, SettingIds } from "./settings";
|
||||||
// Sin
|
// Sin
|
||||||
//import "~/styles/mcdonalds.css";
|
//import "~/styles/mcdonalds.css";
|
||||||
|
|
||||||
|
const lang = useLanguage();
|
||||||
|
setLanguageTag(lang.value);
|
||||||
|
|
||||||
const code = useRequestURL().searchParams.get("code");
|
const code = useRequestURL().searchParams.get("code");
|
||||||
const appData = useAppData();
|
const appData = useAppData();
|
||||||
const instance = useInstance();
|
const instance = useInstance();
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>Mention someone</p>
|
<p>{{ m.game_tough_seal_adore() }}</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
</Toggle>
|
</Toggle>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>Enable Markdown</p>
|
<p>{{ m.plane_born_koala_hope() }}</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Select v-model:model-value="state.visibility">
|
<Select v-model:model-value="state.visibility">
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>Insert emoji</p>
|
<p>{{ m.blue_ornate_coyote_tickle() }}</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>Attach a file</p>
|
<p>{{ m.top_patchy_earthworm_vent() }}</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
|
|
@ -82,12 +82,12 @@
|
||||||
</Toggle>
|
</Toggle>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>Mark as sensitive</p>
|
<p>{{ m.frail_broad_mallard_dart() }}</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Button type="submit" size="lg" class="ml-auto" :disabled="sending" @click="submit">
|
<Button type="submit" size="lg" class="ml-auto" :disabled="sending" @click="submit">
|
||||||
<Loader v-if="sending" class="!size-5 animate-spin" />
|
<Loader v-if="sending" class="!size-5 animate-spin" />
|
||||||
{{ relation?.type === "edit" ? "Save" : "Send" }}
|
{{ relation?.type === "edit" ? m.gaudy_strong_puma_slide() : m.free_teal_bulldog_learn() }}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -110,6 +110,7 @@ import { SelectTrigger } from "radix-vue";
|
||||||
import { toast } from "vue-sonner";
|
import { toast } from "vue-sonner";
|
||||||
import Note from "~/components/notes/note.vue";
|
import Note from "~/components/notes/note.vue";
|
||||||
import { Select, SelectContent, SelectItem } from "~/components/ui/select";
|
import { Select, SelectContent, SelectItem } from "~/components/ui/select";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { SettingIds } from "~/settings";
|
import { SettingIds } from "~/settings";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { Input } from "../ui/input";
|
import { Input } from "../ui/input";
|
||||||
|
|
@ -145,11 +146,11 @@ const getMentions = () => {
|
||||||
const peopleToMention = relation.note.mentions
|
const peopleToMention = relation.note.mentions
|
||||||
.concat(relation.note.account)
|
.concat(relation.note.account)
|
||||||
// Deduplicate mentions
|
// Deduplicate mentions
|
||||||
.filter((m, i, a) => a.indexOf(m) === i)
|
.filter((men, i, a) => a.indexOf(men) === i)
|
||||||
// Remove self
|
// Remove self
|
||||||
.filter((m) => m.id !== identity.value?.account.id);
|
.filter((men) => men.id !== identity.value?.account.id);
|
||||||
|
|
||||||
const mentions = peopleToMention.map((m) => `@${m.acct}`).join(" ");
|
const mentions = peopleToMention.map((me) => `@${me.acct}`).join(" ");
|
||||||
|
|
||||||
return `${mentions} `;
|
return `${mentions} `;
|
||||||
};
|
};
|
||||||
|
|
@ -165,10 +166,10 @@ const state = reactive({
|
||||||
? relation.note.visibility
|
? relation.note.visibility
|
||||||
: "public") as Status["visibility"],
|
: "public") as Status["visibility"],
|
||||||
files: (relation?.type === "edit"
|
files: (relation?.type === "edit"
|
||||||
? relation.note.media_attachments.map((m) => ({
|
? relation.note.media_attachments.map((a) => ({
|
||||||
apiId: m.id,
|
apiId: a.id,
|
||||||
file: new File([], m.url),
|
file: new File([], a.url),
|
||||||
alt: m.description,
|
alt: a.description,
|
||||||
uploading: false,
|
uploading: false,
|
||||||
updating: false,
|
updating: false,
|
||||||
}))
|
}))
|
||||||
|
|
@ -276,23 +277,23 @@ const uploadFiles = (files: File[]) => {
|
||||||
const visibilities = {
|
const visibilities = {
|
||||||
public: {
|
public: {
|
||||||
icon: Globe,
|
icon: Globe,
|
||||||
name: "Public",
|
name: m.lost_trick_dog_grace(),
|
||||||
text: "Can be seen by anyone.",
|
text: m.last_mean_peacock_zip(),
|
||||||
},
|
},
|
||||||
unlisted: {
|
unlisted: {
|
||||||
icon: LockOpen,
|
icon: LockOpen,
|
||||||
name: "Unlisted",
|
name: m.funny_slow_jannes_walk(),
|
||||||
text: "Can be seen by anyone with the link.",
|
text: m.grand_strong_gibbon_race(),
|
||||||
},
|
},
|
||||||
private: {
|
private: {
|
||||||
icon: Lock,
|
icon: Lock,
|
||||||
name: "Private",
|
name: m.grassy_empty_raven_startle(),
|
||||||
text: "Can only be seen by your followers.",
|
text: m.white_teal_ostrich_yell(),
|
||||||
},
|
},
|
||||||
direct: {
|
direct: {
|
||||||
icon: AtSign,
|
icon: AtSign,
|
||||||
name: "Direct",
|
name: m.pretty_bold_baboon_wave(),
|
||||||
text: "Can only be seen by mentioned users.",
|
text: m.lucky_mean_robin_link(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||||
import type { Status, StatusSource } from "@versia/client/types";
|
import type { Status, StatusSource } from "@versia/client/types";
|
||||||
import { toast } from "vue-sonner";
|
import { toast } from "vue-sonner";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import Composer from "./composer.vue";
|
import Composer from "./composer.vue";
|
||||||
|
|
||||||
useListen("composer:open", () => {
|
useListen("composer:open", () => {
|
||||||
|
|
@ -11,7 +12,7 @@ useListen("composer:open", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
useListen("composer:edit", async (note) => {
|
useListen("composer:edit", async (note) => {
|
||||||
const id = toast.loading("Loading note data...", {
|
const id = toast.loading(m.wise_late_fireant_walk(), {
|
||||||
duration: 0,
|
duration: 0,
|
||||||
});
|
});
|
||||||
const { data: source } = await client.value.getStatusSource(note.id);
|
const { data: source } = await client.value.getStatusSource(note.id);
|
||||||
|
|
@ -56,13 +57,16 @@ const relation = ref(
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Dialog v-model:open="open" @update:open="o => {if (!o) { relation = null}}">
|
<Dialog v-model:open="open" @update:open="o => { if (!o) { relation = null } }">
|
||||||
<DialogContent :hide-close="true" class="sm:max-w-xl max-w-full w-full grid-rows-[minmax(0,1fr)_auto] max-h-[90dvh] p-5 pt-6 top-0 sm:top-1/2 translate-y-0 sm:-translate-y-1/2">
|
<DialogContent :hide-close="true"
|
||||||
|
class="sm:max-w-xl max-w-full w-full grid-rows-[minmax(0,1fr)_auto] max-h-[90dvh] p-5 pt-6 top-0 sm:top-1/2 translate-y-0 sm:-translate-y-1/2">
|
||||||
<DialogTitle class="sr-only">
|
<DialogTitle class="sr-only">
|
||||||
{{ relation?.type === "reply" ? "Reply" : relation?.type === "quote" ? "Quote" : "Compose" }}
|
{{ relation?.type === "reply" ? m.loved_busy_mantis_slide() : relation?.type === "quote" ? "Quote" :
|
||||||
|
m.chunky_dull_marlin_trip() }}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogDescription class="sr-only">
|
<DialogDescription class="sr-only">
|
||||||
{{ relation?.type === "reply" ? "Reply to this status" : relation?.type === "quote" ? "Quote this status" : "Compose a new status" }}
|
{{ relation?.type === "reply" ? m.tired_grassy_vulture_forgive() : relation?.type === "quote" ?
|
||||||
|
m.livid_livid_nils_snip() : m.brief_cool_capybara_fear() }}
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
<Composer :relation="relation ?? undefined" />
|
<Composer :relation="relation ?? undefined" />
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import {
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import type { ConfirmModalOptions, ConfirmModalResult } from "./composable.ts";
|
import type { ConfirmModalOptions, ConfirmModalResult } from "./composable.ts";
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
|
@ -41,14 +42,14 @@ const inputValue = ref<string>("");
|
||||||
|
|
||||||
<div v-if="modalOptions.inputType === 'text'" class="grid gap-4 py-4">
|
<div v-if="modalOptions.inputType === 'text'" class="grid gap-4 py-4">
|
||||||
<div class="grid grid-cols-4 items-center gap-4">
|
<div class="grid grid-cols-4 items-center gap-4">
|
||||||
<Label for="confirmInput" class="text-right">Value</Label>
|
<Label for="confirmInput" class="text-right">{{ m.mean_mean_badger_inspire() }}</Label>
|
||||||
<Input id="confirmInput" v-model="inputValue" class="col-span-3" />
|
<Input id="confirmInput" v-model="inputValue" class="col-span-3" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="modalOptions.inputType === 'textarea'" class="grid gap-4 py-4">
|
<div v-else-if="modalOptions.inputType === 'textarea'" class="grid gap-4 py-4">
|
||||||
<div class="grid grid-cols-4 items-center gap-4">
|
<div class="grid grid-cols-4 items-center gap-4">
|
||||||
<Label for="confirmTextarea" class="text-right">Value</Label>
|
<Label for="confirmTextarea" class="text-right">{{ m.mean_mean_badger_inspire() }}</Label>
|
||||||
<Textarea id="confirmTextarea" v-model="inputValue" class="col-span-3" />
|
<Textarea id="confirmTextarea" v-model="inputValue" class="col-span-3" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import {
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import {
|
import {
|
||||||
type ConfirmModalOptions,
|
type ConfirmModalOptions,
|
||||||
type ConfirmModalResult,
|
type ConfirmModalResult,
|
||||||
|
|
@ -20,11 +21,11 @@ import {
|
||||||
|
|
||||||
const isOpen = ref(false);
|
const isOpen = ref(false);
|
||||||
const modalOptions = ref<ConfirmModalOptions>({
|
const modalOptions = ref<ConfirmModalOptions>({
|
||||||
title: "Confirm",
|
title: m.antsy_whole_alligator_blink(),
|
||||||
message: "",
|
message: "",
|
||||||
inputType: "none",
|
inputType: "none",
|
||||||
confirmText: "Confirm",
|
confirmText: m.antsy_whole_alligator_blink(),
|
||||||
cancelText: "Cancel",
|
cancelText: m.soft_bold_ant_attend(),
|
||||||
});
|
});
|
||||||
const inputValue = ref("");
|
const inputValue = ref("");
|
||||||
const resolvePromise = ref<((result: ConfirmModalResult) => void) | null>(null);
|
const resolvePromise = ref<((result: ConfirmModalResult) => void) | null>(null);
|
||||||
|
|
@ -32,11 +33,11 @@ const resolvePromise = ref<((result: ConfirmModalResult) => void) | null>(null);
|
||||||
function open(options: ConfirmModalOptions): Promise<ConfirmModalResult> {
|
function open(options: ConfirmModalOptions): Promise<ConfirmModalResult> {
|
||||||
isOpen.value = true;
|
isOpen.value = true;
|
||||||
modalOptions.value = {
|
modalOptions.value = {
|
||||||
title: options.title || "Confirm",
|
title: options.title || m.antsy_whole_alligator_blink(),
|
||||||
message: options.message,
|
message: options.message,
|
||||||
inputType: options.inputType || "none",
|
inputType: options.inputType || "none",
|
||||||
confirmText: options.confirmText || "Confirm",
|
confirmText: options.confirmText || m.antsy_whole_alligator_blink(),
|
||||||
cancelText: options.cancelText || "Cancel",
|
cancelText: options.cancelText || m.soft_bold_ant_attend(),
|
||||||
};
|
};
|
||||||
inputValue.value = options.defaultValue || "";
|
inputValue.value = options.defaultValue || "";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-row w-full items-stretch justify-around text-sm *:max-w-28 *:w-full *:text-muted-foreground">
|
<div class="flex flex-row w-full items-stretch justify-around text-sm *:max-w-28 *:w-full *:text-muted-foreground">
|
||||||
<Button variant="ghost" @click="emit('reply')" title="Reply" :disabled="!identity">
|
<Button variant="ghost" @click="emit('reply')" :title="m.drab_tense_turtle_comfort()" :disabled="!identity">
|
||||||
<Reply class="size-5 text-primary" />
|
<Reply class="size-5 text-primary" />
|
||||||
{{ numberFormat(replyCount) }}
|
{{ numberFormat(replyCount) }}
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="ghost" @click="liked ? unlike() : like()" :title="liked ? 'Unlike' : 'Like'" :disabled="!identity">
|
<Button variant="ghost" @click="liked ? unlike() : like()" :title="liked ? m.vexed_fluffy_clownfish_dance() : m.royal_close_samuel_scold()" :disabled="!identity">
|
||||||
<Heart class="size-5 text-primary" />
|
<Heart class="size-5 text-primary" />
|
||||||
{{ numberFormat(likeCount) }}
|
{{ numberFormat(likeCount) }}
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="ghost" @click="reblogged ? unreblog() : reblog()" :title="reblogged ? 'Unreblog' : 'Reblog'" :disabled="!identity">
|
<Button variant="ghost" @click="reblogged ? unreblog() : reblog()" :title="reblogged ? m.lime_neat_ox_stab() : m.aware_helpful_marlin_drop()" :disabled="!identity">
|
||||||
<Repeat class="size-5 text-primary" />
|
<Repeat class="size-5 text-primary" />
|
||||||
{{ numberFormat(reblogCount) }}
|
{{ numberFormat(reblogCount) }}
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="ghost" @click="emit('quote')" title="Quote" :disabled="!identity">
|
<Button variant="ghost" @click="emit('quote')" :title="m.true_shy_jackal_drip()" :disabled="!identity">
|
||||||
<Quote class="size-5 text-primary" />
|
<Quote class="size-5 text-primary" />
|
||||||
</Button>
|
</Button>
|
||||||
<Menu :api-note-string="apiNoteString" :url="url" :remote-url="remoteUrl" :is-remote="isRemote" :author-id="authorId" @edit="emit('edit')" :note-id="noteId" @delete="emit('delete')">
|
<Menu :api-note-string="apiNoteString" :url="url" :remote-url="remoteUrl" :is-remote="isRemote" :author-id="authorId" @edit="emit('edit')" :note-id="noteId" @delete="emit('delete')">
|
||||||
<Button variant="ghost" title="Actions">
|
<Button variant="ghost" :title="m.busy_merry_cowfish_absorb()">
|
||||||
<Ellipsis class="size-5 text-primary" />
|
<Ellipsis class="size-5 text-primary" />
|
||||||
</Button>
|
</Button>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
@ -27,6 +27,8 @@
|
||||||
import { Ellipsis, Heart, Quote, Repeat, Reply } from "lucide-vue-next";
|
import { Ellipsis, Heart, Quote, Repeat, Reply } from "lucide-vue-next";
|
||||||
import { toast } from "vue-sonner";
|
import { toast } from "vue-sonner";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
import { languageTag } from "~/paraglide/runtime";
|
||||||
import { SettingIds } from "~/settings";
|
import { SettingIds } from "~/settings";
|
||||||
import { confirmModalService } from "../modals/composable";
|
import { confirmModalService } from "../modals/composable";
|
||||||
import Menu from "./menu.vue";
|
import Menu from "./menu.vue";
|
||||||
|
|
@ -58,9 +60,9 @@ const confirmReblogs = useSetting(SettingIds.ConfirmReblog);
|
||||||
const like = async () => {
|
const like = async () => {
|
||||||
if (confirmLikes.value.value) {
|
if (confirmLikes.value.value) {
|
||||||
const confirmation = await confirmModalService.confirm({
|
const confirmation = await confirmModalService.confirm({
|
||||||
title: "Like status",
|
title: m.slimy_least_ray_aid(),
|
||||||
message: "Are you sure you want to like this status?",
|
message: m.stale_new_ray_jolt(),
|
||||||
confirmText: "Like",
|
confirmText: m.royal_close_samuel_scold(),
|
||||||
inputType: "none",
|
inputType: "none",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -69,19 +71,19 @@ const like = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = toast.loading("Liking status...");
|
const id = toast.loading(m.slimy_candid_tiger_read());
|
||||||
const { data } = await client.value.favouriteStatus(noteId);
|
const { data } = await client.value.favouriteStatus(noteId);
|
||||||
toast.dismiss(id);
|
toast.dismiss(id);
|
||||||
toast.success("Status liked");
|
toast.success(m.mealy_slow_buzzard_commend());
|
||||||
useEvent("note:edit", data);
|
useEvent("note:edit", data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const unlike = async () => {
|
const unlike = async () => {
|
||||||
if (confirmLikes.value.value) {
|
if (confirmLikes.value.value) {
|
||||||
const confirmation = await confirmModalService.confirm({
|
const confirmation = await confirmModalService.confirm({
|
||||||
title: "Unlike status",
|
title: m.odd_strong_halibut_prosper(),
|
||||||
message: "Are you sure you want to unlike this status?",
|
message: m.slow_blue_parrot_savor(),
|
||||||
confirmText: "Unlike",
|
confirmText: m.vexed_fluffy_clownfish_dance(),
|
||||||
inputType: "none",
|
inputType: "none",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -90,19 +92,19 @@ const unlike = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = toast.loading("Unliking status...");
|
const id = toast.loading(m.busy_active_leopard_strive());
|
||||||
const { data } = await client.value.unfavouriteStatus(noteId);
|
const { data } = await client.value.unfavouriteStatus(noteId);
|
||||||
toast.dismiss(id);
|
toast.dismiss(id);
|
||||||
toast.success("Status unliked");
|
toast.success(m.fresh_direct_bear_affirm());
|
||||||
useEvent("note:edit", data);
|
useEvent("note:edit", data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const reblog = async () => {
|
const reblog = async () => {
|
||||||
if (confirmReblogs.value.value) {
|
if (confirmReblogs.value.value) {
|
||||||
const confirmation = await confirmModalService.confirm({
|
const confirmation = await confirmModalService.confirm({
|
||||||
title: "Reblog status",
|
title: m.best_mellow_llama_surge(),
|
||||||
message: "Are you sure you want to reblog this status?",
|
message: m.salty_plain_mallard_gaze(),
|
||||||
confirmText: "Reblog",
|
confirmText: m.aware_helpful_marlin_drop(),
|
||||||
inputType: "none",
|
inputType: "none",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -111,19 +113,19 @@ const reblog = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = toast.loading("Reblogging status...");
|
const id = toast.loading(m.late_sunny_cobra_scold());
|
||||||
const { data } = await client.value.reblogStatus(noteId);
|
const { data } = await client.value.reblogStatus(noteId);
|
||||||
toast.dismiss(id);
|
toast.dismiss(id);
|
||||||
toast.success("Status reblogged");
|
toast.success(m.weird_moving_hawk_lift());
|
||||||
useEvent("note:edit", data.reblog || data);
|
useEvent("note:edit", data.reblog || data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const unreblog = async () => {
|
const unreblog = async () => {
|
||||||
if (confirmReblogs.value.value) {
|
if (confirmReblogs.value.value) {
|
||||||
const confirmation = await confirmModalService.confirm({
|
const confirmation = await confirmModalService.confirm({
|
||||||
title: "Unreblog status",
|
title: m.main_fancy_octopus_loop(),
|
||||||
message: "Are you sure you want to unreblog this status?",
|
message: m.odd_alive_swan_express(),
|
||||||
confirmText: "Unreblog",
|
confirmText: m.lime_neat_ox_stab(),
|
||||||
inputType: "none",
|
inputType: "none",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -132,16 +134,16 @@ const unreblog = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = toast.loading("Unreblogging status...");
|
const id = toast.loading(m.white_sharp_gorilla_embrace());
|
||||||
const { data } = await client.value.unreblogStatus(noteId);
|
const { data } = await client.value.unreblogStatus(noteId);
|
||||||
toast.dismiss(id);
|
toast.dismiss(id);
|
||||||
toast.success("Status unreblogged");
|
toast.success(m.royal_polite_moose_catch());
|
||||||
useEvent("note:edit", data);
|
useEvent("note:edit", data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const numberFormat = (number = 0) =>
|
const numberFormat = (number = 0) =>
|
||||||
number !== 0
|
number !== 0
|
||||||
? new Intl.NumberFormat(undefined, {
|
? new Intl.NumberFormat(languageTag(), {
|
||||||
notation: "compact",
|
notation: "compact",
|
||||||
compactDisplay: "short",
|
compactDisplay: "short",
|
||||||
maximumFractionDigits: 1,
|
maximumFractionDigits: 1,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<Alert variant="warning" v-if="(sensitive || contentWarning) && showCw.value"
|
<Alert variant="warning" v-if="(sensitive || contentWarning) && showCw.value"
|
||||||
class="mb-4 py-2 px-4 grid grid-cols-[auto,1fr,auto] gap-2 items-center [&>svg~*]:pl-0 [&>svg+div]:translate-y-0 [&>svg]:static">
|
class="mb-4 py-2 px-4 grid grid-cols-[auto,1fr,auto] gap-2 items-center [&>svg~*]:pl-0 [&>svg+div]:translate-y-0 [&>svg]:static">
|
||||||
<AlertTitle class="sr-only">Sensitive content</AlertTitle>
|
<AlertTitle class="sr-only">{{ m.livid_tangy_lionfish_clasp() }}</AlertTitle>
|
||||||
<div>
|
<div>
|
||||||
<TriangleAlert class="size-4" />
|
<TriangleAlert class="size-4" />
|
||||||
</div>
|
</div>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
{{ contentWarning || "This content is sensitive" }}
|
{{ contentWarning || m.sour_seemly_bird_hike() }}
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
<Button @click="blurred = !blurred" variant="outline" size="sm">{{ blurred ? "Show" : "Hide" }}</Button>
|
<Button @click="blurred = !blurred" variant="outline" size="sm">{{ blurred ? m.bald_direct_turtle_win() : m.known_flaky_cockroach_dash() }}</Button>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
<div ref="container" :class="cn('overflow-y-hidden relative duration-200', (blurred && showCw.value) && 'blur-md')" :style="{
|
<div ref="container" :class="cn('overflow-y-hidden relative duration-200', (blurred && showCw.value) && 'blur-md')" :style="{
|
||||||
|
|
@ -23,9 +23,10 @@
|
||||||
<Button v-if="isOverflowing" @click="collapsed = !collapsed"
|
<Button v-if="isOverflowing" @click="collapsed = !collapsed"
|
||||||
class="absolute bottom-2 right-1/2 translate-x-1/2">{{
|
class="absolute bottom-2 right-1/2 translate-x-1/2">{{
|
||||||
collapsed
|
collapsed
|
||||||
? `Show more${plainContent ? ` • ${formattedCharacterCount} characters` : ""
|
? `${m.lazy_honest_mammoth_bump()}${plainContent ? ` • ${m.dark_spare_goldfish_charm({
|
||||||
}`
|
count: formattedCharacterCount ?? '0',
|
||||||
: "Show less"
|
})}` : "" }`
|
||||||
|
: m.that_misty_mule_arrive()
|
||||||
}}</Button>
|
}}</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -41,6 +42,7 @@ import { cn } from "@/lib/utils";
|
||||||
import type { Attachment, Emoji, Status } from "@versia/client/types";
|
import type { Attachment, Emoji, Status } from "@versia/client/types";
|
||||||
import { TriangleAlert } from "lucide-vue-next";
|
import { TriangleAlert } from "lucide-vue-next";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { languageTag } from "~/paraglide/runtime";
|
import { languageTag } from "~/paraglide/runtime";
|
||||||
import { type BooleanSetting, SettingIds } from "~/settings";
|
import { type BooleanSetting, SettingIds } from "~/settings";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<span @click="copyText"
|
<span @click="copyText"
|
||||||
class="select-none cursor-pointer space-x-1">
|
class="select-none cursor-pointer space-x-1">
|
||||||
<Clipboard class="size-4 -translate-y-0.5 inline" />
|
<Clipboard class="size-4 -translate-y-0.5 inline" />
|
||||||
Click to copy
|
{{ m.clean_yummy_owl_reside() }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -18,6 +18,7 @@ import { cn } from "@/lib/utils";
|
||||||
import { Check, Clipboard } from "lucide-vue-next";
|
import { Check, Clipboard } from "lucide-vue-next";
|
||||||
import type { HTMLAttributes } from "vue";
|
import type { HTMLAttributes } from "vue";
|
||||||
import { toast } from "vue-sonner";
|
import { toast } from "vue-sonner";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
const { text } = defineProps<{
|
const { text } = defineProps<{
|
||||||
text: string;
|
text: string;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import {
|
||||||
} from "lucide-vue-next";
|
} from "lucide-vue-next";
|
||||||
import { toast } from "vue-sonner";
|
import { toast } from "vue-sonner";
|
||||||
import { confirmModalService } from "~/components/modals/composable.ts";
|
import { confirmModalService } from "~/components/modals/composable.ts";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { SettingIds } from "~/settings";
|
import { SettingIds } from "~/settings";
|
||||||
|
|
||||||
const { authorId, noteId } = defineProps<{
|
const { authorId, noteId } = defineProps<{
|
||||||
|
|
@ -45,23 +46,23 @@ const confirmDeletes = useSetting(SettingIds.ConfirmDelete);
|
||||||
|
|
||||||
const copyText = (text: string) => {
|
const copyText = (text: string) => {
|
||||||
copy(text);
|
copy(text);
|
||||||
toast.success("Copied to clipboard");
|
toast.success(m.flat_nice_worm_dream());
|
||||||
};
|
};
|
||||||
|
|
||||||
const blockUser = async (userId: string) => {
|
const blockUser = async (userId: string) => {
|
||||||
const id = toast.loading("Blocking user...");
|
const id = toast.loading(m.top_cute_bison_nudge());
|
||||||
await client.value.blockAccount(userId);
|
await client.value.blockAccount(userId);
|
||||||
toast.dismiss(id);
|
toast.dismiss(id);
|
||||||
|
|
||||||
toast.success("User blocked");
|
toast.success(m.main_weary_racoon_peek());
|
||||||
};
|
};
|
||||||
|
|
||||||
const _delete = async () => {
|
const _delete = async () => {
|
||||||
if (confirmDeletes.value.value) {
|
if (confirmDeletes.value.value) {
|
||||||
const confirmation = await confirmModalService.confirm({
|
const confirmation = await confirmModalService.confirm({
|
||||||
title: "Delete status",
|
title: m.calm_icy_weasel_twirl(),
|
||||||
message: "Are you sure you want to delete this status?",
|
message: m.gray_fun_toucan_slide(),
|
||||||
confirmText: "Delete",
|
confirmText: m.royal_best_tern_transform(),
|
||||||
inputType: "none",
|
inputType: "none",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -70,11 +71,11 @@ const _delete = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = toast.loading("Deleting status...");
|
const id = toast.loading(m.new_funny_fox_boil());
|
||||||
await client.value.deleteStatus(noteId);
|
await client.value.deleteStatus(noteId);
|
||||||
toast.dismiss(id);
|
toast.dismiss(id);
|
||||||
|
|
||||||
toast.success("Status deleted");
|
toast.success(m.green_tasty_bumblebee_beam());
|
||||||
emit("delete");
|
emit("delete");
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -85,57 +86,57 @@ const _delete = async () => {
|
||||||
<slot />
|
<slot />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent class="min-w-56">
|
<DropdownMenuContent class="min-w-56">
|
||||||
<DropdownMenuLabel>Note Actions</DropdownMenuLabel>
|
<DropdownMenuLabel>{{ m.many_misty_parakeet_fall() }}</DropdownMenuLabel>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuGroup>
|
<DropdownMenuGroup>
|
||||||
<DropdownMenuItem v-if="authorIsMe" as="button" @click="emit('edit')">
|
<DropdownMenuItem v-if="authorIsMe" as="button" @click="emit('edit')">
|
||||||
<Pencil class="mr-2 size-4" />
|
<Pencil class="mr-2 size-4" />
|
||||||
<span>Edit</span>
|
{{ m.front_lime_grizzly_persist() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem as="button" @click="copyText(apiNoteString)">
|
<DropdownMenuItem as="button" @click="copyText(apiNoteString)">
|
||||||
<Code class="mr-2 size-4" />
|
<Code class="mr-2 size-4" />
|
||||||
<span>Copy API data</span>
|
{{ m.yummy_moving_scallop_sail() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem as="button" @click="copyText(noteId)">
|
<DropdownMenuItem as="button" @click="copyText(noteId)">
|
||||||
<Hash class="mr-2 size-4" />
|
<Hash class="mr-2 size-4" />
|
||||||
<span>Copy ID</span>
|
{{ m.sunny_zany_jellyfish_pop() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuGroup>
|
</DropdownMenuGroup>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuGroup>
|
<DropdownMenuGroup>
|
||||||
<DropdownMenuItem as="button" @click="copyText(url)">
|
<DropdownMenuItem as="button" @click="copyText(url)">
|
||||||
<Link class="mr-2 size-4" />
|
<Link class="mr-2 size-4" />
|
||||||
<span>Copy link</span>
|
{{ m.ago_new_pelican_drip() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem as="button" v-if="isRemote" @click="copyText(remoteUrl)">
|
<DropdownMenuItem as="button" v-if="isRemote" @click="copyText(remoteUrl)">
|
||||||
<Link class="mr-2 size-4" />
|
<Link class="mr-2 size-4" />
|
||||||
<span>Copy link (origin)</span>
|
{{ m.solid_witty_zebra_walk() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem as="a" v-if="isRemote" target="_blank" rel="noopener noreferrer" :href="remoteUrl">
|
<DropdownMenuItem as="a" v-if="isRemote" target="_blank" rel="noopener noreferrer" :href="remoteUrl">
|
||||||
<ExternalLink class="mr-2 size-4" />
|
<ExternalLink class="mr-2 size-4" />
|
||||||
<span>Open on remote</span>
|
{{ m.active_trite_lark_inspire() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuGroup>
|
</DropdownMenuGroup>
|
||||||
<DropdownMenuSeparator v-if="authorIsMe" />
|
<DropdownMenuSeparator v-if="authorIsMe" />
|
||||||
<DropdownMenuGroup v-if="authorIsMe">
|
<DropdownMenuGroup v-if="authorIsMe">
|
||||||
<DropdownMenuItem as="button" :disabled="true">
|
<DropdownMenuItem as="button" :disabled="true">
|
||||||
<Delete class="mr-2 size-4" />
|
<Delete class="mr-2 size-4" />
|
||||||
<span>Delete and redraft</span>
|
{{ m.real_green_clownfish_pet() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem as="button" @click="_delete">
|
<DropdownMenuItem as="button" @click="_delete">
|
||||||
<Trash class="mr-2 size-4" />
|
<Trash class="mr-2 size-4" />
|
||||||
<span>Delete</span>
|
{{ m.tense_quick_cod_favor() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuGroup>
|
</DropdownMenuGroup>
|
||||||
<DropdownMenuSeparator v-if="loggedIn && !authorIsMe" />
|
<DropdownMenuSeparator v-if="loggedIn && !authorIsMe" />
|
||||||
<DropdownMenuGroup v-if="loggedIn && !authorIsMe">
|
<DropdownMenuGroup v-if="loggedIn && !authorIsMe">
|
||||||
<DropdownMenuItem as="button" :disabled="true">
|
<DropdownMenuItem as="button" :disabled="true">
|
||||||
<Flag class="mr-2 size-4" />
|
<Flag class="mr-2 size-4" />
|
||||||
<span>Report</span>
|
{{ m.great_few_jaguar_rise() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem as="button" @click="blockUser(authorId)">
|
<DropdownMenuItem as="button" @click="blockUser(authorId)">
|
||||||
<Ban class="mr-2 size-4" />
|
<Ban class="mr-2 size-4" />
|
||||||
<span>Block user</span>
|
{{ m.misty_soft_sparrow_vent() }}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuGroup>
|
</DropdownMenuGroup>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ import {
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "~/components/ui/tooltip";
|
} from "~/components/ui/tooltip";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import Note from "../notes/note.vue";
|
import Note from "../notes/note.vue";
|
||||||
import Avatar from "../profiles/avatar.vue";
|
import Avatar from "../profiles/avatar.vue";
|
||||||
import FollowRequest from "./follow-request.vue";
|
import FollowRequest from "./follow-request.vue";
|
||||||
|
|
@ -85,17 +86,17 @@ const icon = computed(() => {
|
||||||
const text = computed(() => {
|
const text = computed(() => {
|
||||||
switch (notification.type) {
|
switch (notification.type) {
|
||||||
case "mention":
|
case "mention":
|
||||||
return "Mentioned you";
|
return m.fuzzy_orange_tuna_succeed();
|
||||||
case "reblog":
|
case "reblog":
|
||||||
return "Reblogged your note";
|
return m.grand_proof_quail_read();
|
||||||
case "follow":
|
case "follow":
|
||||||
return "Followed you";
|
return m.top_steep_scallop_care();
|
||||||
case "favourite":
|
case "favourite":
|
||||||
return "Liked your note";
|
return m.swift_just_beetle_devour();
|
||||||
case "follow_request":
|
case "follow_request":
|
||||||
return "Requested to follow you";
|
return m.seemly_short_thrush_bloom();
|
||||||
case "follow_accept":
|
case "follow_accept":
|
||||||
return "Accepted your follow request";
|
return m.weird_seemly_termite_scold();
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
{{ emoji.shortcode }}
|
{{ emoji.shortcode }}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
{{ emoji.global ? m.lime_day_squid_pout() : m.witty_heroic_trout_cry() }}
|
{{ emoji.global ? m.real_tame_moose_greet() : m.witty_heroic_trout_cry() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardFooter class="p-0" v-if="canEdit">
|
<CardFooter class="p-0" v-if="canEdit">
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
<Card class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
|
<Card class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
|
||||||
<CardHeader class="space-y-0.5 p-0">
|
<CardHeader class="space-y-0.5 p-0">
|
||||||
<CardTitle class="text-base">
|
<CardTitle class="text-base">
|
||||||
{{ setting.title }}
|
{{ setting.title() }}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
{{ setting.description }}
|
{{ setting.description() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardFooter class="p-0">
|
<CardFooter class="p-0">
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem v-for="option of setting.options" :value="option.value">
|
<SelectItem v-for="option of setting.options" :value="option.value">
|
||||||
{{ option.label }}
|
{{ option.label() }}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
<Card class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
|
<Card class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
|
||||||
<CardHeader class="space-y-0.5 p-0">
|
<CardHeader class="space-y-0.5 p-0">
|
||||||
<CardTitle class="text-base">
|
<CardTitle class="text-base">
|
||||||
{{ setting.title }}
|
{{ setting.title() }}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
{{ setting.description }}
|
{{ setting.description() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardFooter class="p-0">
|
<CardFooter class="p-0">
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,6 @@ import {
|
||||||
SidebarRail,
|
SidebarRail,
|
||||||
} from "~/components/ui/sidebar";
|
} from "~/components/ui/sidebar";
|
||||||
import * as m from "~/paraglide/messages.js";
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { setLanguageTag } from "~/paraglide/runtime";
|
|
||||||
import { type EnumSetting, SettingIds } from "~/settings";
|
import { type EnumSetting, SettingIds } from "~/settings";
|
||||||
import Avatar from "../profiles/avatar.vue";
|
import Avatar from "../profiles/avatar.vue";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
|
@ -128,8 +127,6 @@ import AccountSwitcher from "./account-switcher.vue";
|
||||||
|
|
||||||
const sidebarStyle = useSetting(SettingIds.SidebarStyle) as Ref<EnumSetting>;
|
const sidebarStyle = useSetting(SettingIds.SidebarStyle) as Ref<EnumSetting>;
|
||||||
|
|
||||||
setLanguageTag("fr");
|
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
navMain: [
|
navMain: [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@
|
||||||
<!-- If there are some posts, but the user scrolled to the end -->
|
<!-- If there are some posts, but the user scrolled to the end -->
|
||||||
<Card v-if="hasReachedEnd && items.length > 0" class="shadow-none bg-transparent border-none p-4">
|
<Card v-if="hasReachedEnd && items.length > 0" class="shadow-none bg-transparent border-none p-4">
|
||||||
<CardHeader class="text-center gap-y-4">
|
<CardHeader class="text-center gap-y-4">
|
||||||
<CardTitle class="text-">No more data.</CardTitle>
|
<CardTitle>{{ m.steep_suave_fish_snap() }}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
You've scrolled so far, there's nothing left to show.
|
{{ m.muddy_bland_shark_accept() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -28,16 +28,16 @@
|
||||||
<!-- If there are no posts at all -->
|
<!-- If there are no posts at all -->
|
||||||
<Card v-else-if="hasReachedEnd && items.length === 0" class="shadow-none bg-transparent border-none p-4">
|
<Card v-else-if="hasReachedEnd && items.length === 0" class="shadow-none bg-transparent border-none p-4">
|
||||||
<CardHeader class="text-center gap-y-4">
|
<CardHeader class="text-center gap-y-4">
|
||||||
<CardTitle class="text-">There's nothing to show here.</CardTitle>
|
<CardTitle>{{ m.fine_arable_lemming_fold() }}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Either you're all caught up or there's nothing to show.
|
{{ m.petty_honest_fish_stir() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<div v-else-if="!infiniteScroll.value" class="py-10 px-4">
|
<div v-else-if="!infiniteScroll.value" class="py-10 px-4">
|
||||||
<Button variant="secondary" @click="loadNext" :disabled="isLoading" class="w-full">
|
<Button variant="secondary" @click="loadNext" :disabled="isLoading" class="w-full">
|
||||||
Load More
|
{{ m.gaudy_bland_gorilla_talk() }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -55,6 +55,7 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "~/components/ui/card";
|
} from "~/components/ui/card";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { SettingIds } from "~/settings";
|
import { SettingIds } from "~/settings";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import TimelineItem from "./timeline-item.vue";
|
import TimelineItem from "./timeline-item.vue";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import type { Client } from "@versia/client";
|
import type { Client } from "@versia/client";
|
||||||
import type { RolePermission } from "@versia/client/types";
|
import type { RolePermission } from "@versia/client/types";
|
||||||
|
import { toast } from "vue-sonner";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
export const useCacheRefresh = (client: MaybeRef<Client | null>) => {
|
export const useCacheRefresh = (client: MaybeRef<Client | null>) => {
|
||||||
// Refresh custom emojis and instance data and me on every reload
|
// Refresh custom emojis and instance data and me on every reload
|
||||||
|
|
@ -21,11 +23,8 @@ export const useCacheRefresh = (client: MaybeRef<Client | null>) => {
|
||||||
if (code === 401) {
|
if (code === 401) {
|
||||||
// Reset tokenData
|
// Reset tokenData
|
||||||
identity.value = null;
|
identity.value = null;
|
||||||
useEvent("notification:new", {
|
toast.error(m.fancy_this_wasp_renew(), {
|
||||||
type: "error",
|
description: m.real_weird_deer_stop(),
|
||||||
title: "Your session has expired",
|
|
||||||
description:
|
|
||||||
"You have been logged out. Please log in again.",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
7
composables/Language.ts
Normal file
7
composables/Language.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { SettingIds } from "~/settings";
|
||||||
|
|
||||||
|
export const useLanguage = () => {
|
||||||
|
const lang = useSetting(SettingIds.Language);
|
||||||
|
|
||||||
|
return computed(() => lang.value.value as "en" | "fr");
|
||||||
|
};
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
} from "~/settings";
|
} from "~/settings";
|
||||||
|
|
||||||
const useSettings = () => {
|
const useSettings = () => {
|
||||||
return useLocalStorage<Settings>("versia:settings", settingsJson, {
|
return useLocalStorage<Settings>("versia:settings", settingsJson(), {
|
||||||
serializer: {
|
serializer: {
|
||||||
read(raw) {
|
read(raw) {
|
||||||
const json = StorageSerializers.object.read(raw);
|
const json = StorageSerializers.object.read(raw);
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
<slot v-if="!route.meta.requiresAuth || identity" />
|
<slot v-if="!route.meta.requiresAuth || identity" />
|
||||||
<Card v-else class="shadow-none bg-transparent border-none p-4 max-w-md mx-auto">
|
<Card v-else class="shadow-none bg-transparent border-none p-4 max-w-md mx-auto">
|
||||||
<CardHeader class="text-center gap-y-4">
|
<CardHeader class="text-center gap-y-4">
|
||||||
<CardTitle class="text-">Not signed in</CardTitle>
|
<CardTitle>{{ m.sunny_quick_lionfish_flip() }}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
This page requires you to be authenticated. Please sign in to continue.
|
{{ m.brave_known_pelican_drip() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardFooter>
|
<CardFooter>
|
||||||
<Button variant="secondary" class="w-full" @click="signInAction">
|
<Button variant="secondary" class="w-full" @click="signInAction">
|
||||||
Sign in
|
{{ m.fuzzy_sea_moth_absorb() }}
|
||||||
</Button>
|
</Button>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -31,6 +31,7 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "~/components/ui/card";
|
} from "~/components/ui/card";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
const appData = useAppData();
|
const appData = useAppData();
|
||||||
const signInAction = () => signIn(appData);
|
const signInAction = () => signIn(appData);
|
||||||
|
|
|
||||||
222
messages/en.json
222
messages/en.json
|
|
@ -56,10 +56,8 @@
|
||||||
"awake_quick_cuckoo_smile": "User followed",
|
"awake_quick_cuckoo_smile": "User followed",
|
||||||
"funny_aloof_swan_loop": "Unfollow user",
|
"funny_aloof_swan_loop": "Unfollow user",
|
||||||
"cute_polite_oryx_blend": "Unfollow",
|
"cute_polite_oryx_blend": "Unfollow",
|
||||||
"dirty_inclusive_meerkat_nudge": "Cancel",
|
|
||||||
"big_safe_guppy_mix": "Unfollowing user...",
|
"big_safe_guppy_mix": "Unfollowing user...",
|
||||||
"misty_level_stingray_expand": "User unfollowed",
|
"misty_level_stingray_expand": "User unfollowed",
|
||||||
"lime_day_squid_pout": "Global",
|
|
||||||
"witty_heroic_trout_cry": "Uploaded by you",
|
"witty_heroic_trout_cry": "Uploaded by you",
|
||||||
"cuddly_such_swallow_hush": "Rename",
|
"cuddly_such_swallow_hush": "Rename",
|
||||||
"tense_quick_cod_favor": "Delete",
|
"tense_quick_cod_favor": "Delete",
|
||||||
|
|
@ -100,7 +98,7 @@
|
||||||
"sunny_novel_otter_glow": "Must be at least 3 characters long",
|
"sunny_novel_otter_glow": "Must be at least 3 characters long",
|
||||||
"fluffy_soft_wolf_cook": "Email (or username)",
|
"fluffy_soft_wolf_cook": "Email (or username)",
|
||||||
"livid_bright_wallaby_quiz": "Password",
|
"livid_bright_wallaby_quiz": "Password",
|
||||||
"fuzzy_sea_moth_absorb": "Sign In",
|
"fuzzy_sea_moth_absorb": "Sign in",
|
||||||
"tidy_tidy_cow_cut": "Or continue with",
|
"tidy_tidy_cow_cut": "Or continue with",
|
||||||
"slow_these_kestrel_sail": "Accept",
|
"slow_these_kestrel_sail": "Accept",
|
||||||
"weary_steep_yak_embrace": "Reject",
|
"weary_steep_yak_embrace": "Reject",
|
||||||
|
|
@ -108,5 +106,221 @@
|
||||||
"busy_awful_mouse_jump": "Follow request accepted.",
|
"busy_awful_mouse_jump": "Follow request accepted.",
|
||||||
"front_sunny_penguin_flip": "Rejecting follow request...",
|
"front_sunny_penguin_flip": "Rejecting follow request...",
|
||||||
"green_flat_mayfly_trust": "Follow request rejected.",
|
"green_flat_mayfly_trust": "Follow request rejected.",
|
||||||
"large_vivid_horse_catch": "reblogged"
|
"large_vivid_horse_catch": "reblogged",
|
||||||
|
"sour_major_baboon_wish": "Copied to clipboard",
|
||||||
|
"top_cute_bison_nudge": "Blocking user...",
|
||||||
|
"main_weary_racoon_peek": "User blocked",
|
||||||
|
"calm_icy_weasel_twirl": "Delete note",
|
||||||
|
"gray_fun_toucan_slide": "Are you sure you want to delete this note?",
|
||||||
|
"royal_best_tern_transform": "Delete",
|
||||||
|
"new_funny_fox_boil": "Deleting note...",
|
||||||
|
"green_tasty_bumblebee_beam": "Note deleted",
|
||||||
|
"many_misty_parakeet_fall": "Note Actions",
|
||||||
|
"front_lime_grizzly_persist": "Edit",
|
||||||
|
"wise_crazy_eel_honor": "Copy API data",
|
||||||
|
"dizzy_alive_wombat_bump": "Copy ID",
|
||||||
|
"slimy_livid_rabbit_belong": "Copy link",
|
||||||
|
"inner_pink_mare_renew": "Copy link (origin)",
|
||||||
|
"calm_fuzzy_thrush_soar": "Open on remote",
|
||||||
|
"real_green_clownfish_pet": " Delete and redraft",
|
||||||
|
"zippy_key_antelope_drop": "Delete",
|
||||||
|
"chunky_dry_gull_sing": "Report",
|
||||||
|
"bald_vexed_firefox_startle": "Block user",
|
||||||
|
"clean_yummy_owl_reside": "Click to copy",
|
||||||
|
"livid_tangy_lionfish_clasp": "Sensitive content",
|
||||||
|
"sour_seemly_bird_hike": "This content is sensitive",
|
||||||
|
"bald_direct_turtle_win": "Show",
|
||||||
|
"known_flaky_cockroach_dash": "Hide",
|
||||||
|
"dirty_sound_skunk_dust": "Show more${plainContent ? ` • ${formattedCharacterCount} characters",
|
||||||
|
"mad_direct_opossum_gleam": "`Show more${plainContent ? ` • ${formattedCharacterCount} characters` : \"\"\n }`",
|
||||||
|
"that_misty_mule_arrive": "Show less",
|
||||||
|
"lazy_honest_mammoth_bump": "Show more",
|
||||||
|
"dark_spare_goldfish_charm": "{count} characters",
|
||||||
|
"drab_tense_turtle_comfort": "Reply",
|
||||||
|
"vexed_fluffy_clownfish_dance": "Unlike",
|
||||||
|
"royal_close_samuel_scold": "Like",
|
||||||
|
"lime_neat_ox_stab": "Unreblog",
|
||||||
|
"aware_helpful_marlin_drop": "Reblog",
|
||||||
|
"true_shy_jackal_drip": "Quote",
|
||||||
|
"busy_merry_cowfish_absorb": "Actions",
|
||||||
|
"slimy_least_ray_aid": "Like note",
|
||||||
|
"stale_new_ray_jolt": "Are you sure you want to like this note?",
|
||||||
|
"slimy_candid_tiger_read": "Liking note...",
|
||||||
|
"mealy_slow_buzzard_commend": "Note liked",
|
||||||
|
"odd_strong_halibut_prosper": "Unlike note",
|
||||||
|
"slow_blue_parrot_savor": "Are you sure you want to unlike this note?",
|
||||||
|
"busy_active_leopard_strive": "Unliking note...",
|
||||||
|
"fresh_direct_bear_affirm": "Note unliked",
|
||||||
|
"best_mellow_llama_surge": "Reblog note",
|
||||||
|
"salty_plain_mallard_gaze": "Are you sure you want to reblog this note?",
|
||||||
|
"late_sunny_cobra_scold": "Reblogging note...",
|
||||||
|
"weird_moving_hawk_lift": "Note reblogged",
|
||||||
|
"main_fancy_octopus_loop": "Unreblog note",
|
||||||
|
"odd_alive_swan_express": "Are you sure you want to unreblog this note?",
|
||||||
|
"white_sharp_gorilla_embrace": "Unreblogging note...",
|
||||||
|
"royal_polite_moose_catch": "Note unreblogged",
|
||||||
|
"mean_mean_badger_inspire": "Value",
|
||||||
|
"antsy_whole_alligator_blink": "Confirm",
|
||||||
|
"game_tough_seal_adore": "Mention someone",
|
||||||
|
"plane_born_koala_hope": "Enable Markdown",
|
||||||
|
"blue_ornate_coyote_tickle": "Insert emoji",
|
||||||
|
"top_patchy_earthworm_vent": "Attach a file",
|
||||||
|
"frail_broad_mallard_dart": "Mark as sensitive",
|
||||||
|
"gaudy_strong_puma_slide": "Save",
|
||||||
|
"free_teal_bulldog_learn": "Send",
|
||||||
|
"last_mean_peacock_zip": "Can be seen by anyone.",
|
||||||
|
"funny_slow_jannes_walk": "Unlisted",
|
||||||
|
"grassy_empty_raven_startle": "Private",
|
||||||
|
"pretty_bold_baboon_wave": "Direct",
|
||||||
|
"grand_strong_gibbon_race": "Can be seen by anyone with the link.",
|
||||||
|
"white_teal_ostrich_yell": "Can only be seen by your followers.",
|
||||||
|
"lucky_mean_robin_link": "Can only be seen by mentioned users.",
|
||||||
|
"wise_late_fireant_walk": "Loading note data...",
|
||||||
|
"loved_busy_mantis_slide": "Reply",
|
||||||
|
"tired_grassy_vulture_forgive": "Reply to this note",
|
||||||
|
"solid_slow_angelfish_pave": "Compose",
|
||||||
|
"livid_livid_nils_snip": "Quote this note",
|
||||||
|
"brief_cool_capybara_fear": "Compose a new note",
|
||||||
|
"chunky_dull_marlin_trip": "Compose",
|
||||||
|
"steep_suave_fish_snap": "No more data.",
|
||||||
|
"muddy_bland_shark_accept": "You've scrolled so far, there's nothing left to show.",
|
||||||
|
"petty_honest_fish_stir": "Either you're all caught up or there's nothing to show.",
|
||||||
|
"fine_arable_lemming_fold": "There's nothing to show here.",
|
||||||
|
"gaudy_bland_gorilla_talk": "Load More",
|
||||||
|
"fancy_this_wasp_renew": "Your session has expired",
|
||||||
|
"real_weird_deer_stop": "You have been logged out. Please log in again.",
|
||||||
|
"sunny_quick_lionfish_flip": "Not signed in",
|
||||||
|
"brave_known_pelican_drip": "This page requires you to be authenticated. Please sign in to continue.",
|
||||||
|
"chunky_awake_mallard_grow": "Note",
|
||||||
|
"steep_sour_warthog_aim": "Loading",
|
||||||
|
"tough_nice_ox_drum": "Profile",
|
||||||
|
"noble_cute_ocelot_aim": "Register",
|
||||||
|
"novel_fine_stork_snap": "Log in to your account.",
|
||||||
|
"smug_main_whale_snip": "Enter your credentials for <code>{host}</code>.",
|
||||||
|
"aware_awful_crow_spur": "Here's your code",
|
||||||
|
"mushy_soft_lizard_propel": "You have signed in successfully.",
|
||||||
|
"short_arable_leopard_zap": "Paste the following code into your app:",
|
||||||
|
"spare_aqua_warthog_mend": "Authorization Code",
|
||||||
|
"fresh_broad_cockroach_radiate": "Authorize “{application}”?",
|
||||||
|
"gross_antsy_kangaroo_succeed": "You are signing in to <b>{application}</b> with your account.",
|
||||||
|
"hour_close_giraffe_mop": "This allows <b>{application}</b> to perform the above actions.",
|
||||||
|
"last_spare_polecat_reside": "Authorize",
|
||||||
|
"lower_factual_frog_evoke": "Authorization",
|
||||||
|
"awake_ago_capybara_kick": "$VERB your account information",
|
||||||
|
"teary_zesty_racoon_transform": "$VERB your block list",
|
||||||
|
"whole_flaky_nuthatch_rush": "$VERB your bookmarks",
|
||||||
|
"still_spicy_lionfish_quell": "$VERB your favourites",
|
||||||
|
"away_mean_dolphin_empower": "$VERB your filters",
|
||||||
|
"sleek_empty_penguin_radiate": "$VERB your follows",
|
||||||
|
"every_silly_racoon_lift": "$VERB your lists",
|
||||||
|
"top_careful_scallop_clip": "$VERB your mutes",
|
||||||
|
"this_short_bulldog_walk": "$VERB your notifications",
|
||||||
|
"fresh_odd_rook_forgive": "Perform searches",
|
||||||
|
"witty_whole_capybara_pull": "$VERB your notes",
|
||||||
|
"agent_warm_javelina_blink": "Edit your conversations",
|
||||||
|
"dirty_red_jellyfish_ascend": "Upload media",
|
||||||
|
"crisp_vivid_seahorse_tend": "Report users",
|
||||||
|
"teary_such_jay_fade": "Read and write",
|
||||||
|
"smug_safe_warthog_dare": "Read",
|
||||||
|
"loose_large_blackbird_peek": "Write",
|
||||||
|
"late_mean_capybara_fade": "Success",
|
||||||
|
"brave_acidic_lobster_fetch": "Your password has been reset. You can now log in with your new password.",
|
||||||
|
"every_tangy_koala_persist": "Back to front page",
|
||||||
|
"good_plane_gazelle_glow": "Your password has been reset by an administrator. Please change it here.",
|
||||||
|
"east_loud_lobster_explore": "Info",
|
||||||
|
"solid_slow_platypus_talk": "Enter your new password below. Make sure to put it in a password manager.",
|
||||||
|
"tired_green_sloth_evoke": "Reset your password",
|
||||||
|
"true_male_gadfly_stab": "New password",
|
||||||
|
"awful_cozy_jannes_rise": "Confirm password",
|
||||||
|
"noisy_round_skate_yell": "Reset",
|
||||||
|
"smart_bold_macaw_aid": "Must be at least {count} characters long",
|
||||||
|
"dry_smug_goldfish_promise": "Must be at most {count} characters long",
|
||||||
|
"candid_fancy_leopard_prosper": "Passwords do not match",
|
||||||
|
"arable_arable_herring_lead": "Reset Password",
|
||||||
|
"broad_whole_herring_reside": "Preferences",
|
||||||
|
"tasty_late_termite_sew": "Account",
|
||||||
|
"actual_mean_cow_dare": "Account Preferences",
|
||||||
|
"suave_smart_mantis_climb": "Emojis",
|
||||||
|
"lucky_suave_myna_adore": "Ask your administrator to add some emojis.",
|
||||||
|
"actual_steep_llama_rest": "No emojis found.",
|
||||||
|
"mild_many_dolphin_mend": "Emoji Preferences",
|
||||||
|
"lucky_ago_rat_pinch": "Uncategorized",
|
||||||
|
"empty_awful_lark_dart": "Account not found.",
|
||||||
|
"clean_even_mayfly_tap": "Check for typos or try again later.",
|
||||||
|
"vexed_each_falcon_enjoy": "Error",
|
||||||
|
"wide_topical_vole_walk": "Create an account",
|
||||||
|
"keen_clean_nils_slurp": "Username",
|
||||||
|
"top_inclusive_wallaby_hack": "Email address",
|
||||||
|
"mad_this_bumblebee_burn": "Password",
|
||||||
|
"happy_house_dragonfly_clap": "Passwords are never stored in plain text.",
|
||||||
|
"early_last_ocelot_praise": "Register",
|
||||||
|
"safe_candid_horse_jump": "Registrations are disabled on this instance.",
|
||||||
|
"wide_away_cat_taste": "Sorry :c",
|
||||||
|
"sea_maroon_peacock_yell": "Must be lowercase letters, numbers, underscores or hyphens",
|
||||||
|
"civil_loose_coyote_jump": "You must agree to the Terms of Service",
|
||||||
|
"plane_quick_chipmunk_rush": "I agree to the",
|
||||||
|
"glad_last_crow_dine": "Terms of Service",
|
||||||
|
"left_maroon_myna_drip": "You've successfully registered. You can now log in with your new account.",
|
||||||
|
"steep_aqua_fox_harbor": "Timelines",
|
||||||
|
"silly_sour_fireant_fear": "Failed to create app",
|
||||||
|
"level_due_ox_greet": "Signing in...",
|
||||||
|
"candid_frail_lion_value": "Failed to generate auth URL",
|
||||||
|
"wide_least_samuel_conquer": "Style of the left sidebar.",
|
||||||
|
"fluffy_north_crow_blink": "Inset",
|
||||||
|
"day_polite_newt_loop": "Sidebar",
|
||||||
|
"jolly_mad_jackdaw_assure": "Floating",
|
||||||
|
"agent_misty_firefox_arise": "Shape of all user avatars.",
|
||||||
|
"polite_awful_ladybug_greet": "Round",
|
||||||
|
"sad_each_cowfish_lock": "Square",
|
||||||
|
"fit_cool_bulldog_dine": "Avatar Shape",
|
||||||
|
"deft_seemly_donkey_slide": "Sidebar Style",
|
||||||
|
"quaint_clear_boar_attend": "Render MFM",
|
||||||
|
"aloof_helpful_larva_spur": "Render Misskey-Flavoured Markdown.",
|
||||||
|
"smart_awake_dachshund_view": "Custom CSS",
|
||||||
|
"loved_topical_rat_coax": "Custom CSS for the UI.",
|
||||||
|
"wise_neat_ox_buzz": "Dark",
|
||||||
|
"each_strong_snail_aid": "Light",
|
||||||
|
"helpful_raw_seal_nurture": "System",
|
||||||
|
"male_stout_florian_feast": "UI theme.",
|
||||||
|
"hour_elegant_mink_grip": "Theme",
|
||||||
|
"loud_raw_sheep_imagine": "Render Custom Emojis",
|
||||||
|
"inclusive_pink_tuna_enjoy": "Render custom emojis. Requires a page reload to apply.",
|
||||||
|
"fair_swift_elephant_hunt": "Blur Sensitive Content",
|
||||||
|
"gray_minor_bee_endure": "Blur notes marked sensitive/spoiler.",
|
||||||
|
"stock_large_marten_comfort": "Background URL",
|
||||||
|
"mean_weird_donkey_stab": "Change the background image of the site.",
|
||||||
|
"tired_jumpy_rook_slurp": "Notifications Sidebar",
|
||||||
|
"wide_new_robin_empower": "Display a sidebar with notifications on desktop.",
|
||||||
|
"less_early_lionfish_honor": "Fluent Emojis (flat version)",
|
||||||
|
"many_tasty_midge_zoom": "Fluent Emojis",
|
||||||
|
"shy_clear_spider_cook": "Noto Emoji",
|
||||||
|
"new_brave_maggot_relish": "Twitter Emojis",
|
||||||
|
"slimy_sound_termite_hug": "Operating System",
|
||||||
|
"warm_round_dove_skip": "Theme used for rendering emojis. Requires a page reload to apply.",
|
||||||
|
"weak_bad_martin_glow": "Emoji Theme",
|
||||||
|
"equal_blue_zebra_launch": "Ctrl+Enter to Send",
|
||||||
|
"heavy_pink_meerkat_affirm": "Send a note by pressing ⌘+Enter or Ctrl+Enter.",
|
||||||
|
"north_nimble_turkey_transform": "Popup Profile Hover",
|
||||||
|
"bold_moving_fly_savor": "Show profile popup when hovering over a user's avatar.",
|
||||||
|
"plane_dark_salmon_pout": "Automatically load more notes when reaching the bottom of the page.",
|
||||||
|
"helpful_early_worm_laugh": "Confirm before deleting a note.",
|
||||||
|
"trite_salty_eel_race": "Confirm Delete",
|
||||||
|
"sleek_this_earthworm_hug": "Infinite Scroll",
|
||||||
|
"jolly_empty_bullock_mend": "Confirm Follow",
|
||||||
|
"cool_tasty_mule_soar": "Confirm before following/unfollowing a user.",
|
||||||
|
"calm_male_wombat_relish": "Confirm before following/unfollowing a user.",
|
||||||
|
"wacky_inner_osprey_intend": "Confirm before reblogging a note.",
|
||||||
|
"honest_great_rooster_taste": "Confirm Reblog",
|
||||||
|
"patchy_basic_alligator_inspire": "Confirm Like",
|
||||||
|
"antsy_weak_raven_treat": "Confirm before liking a note.",
|
||||||
|
"fuzzy_orange_tuna_succeed": "Mentioned you",
|
||||||
|
"grand_proof_quail_read": "Reblogged your note",
|
||||||
|
"top_steep_scallop_care": "Followed you",
|
||||||
|
"swift_just_beetle_devour": "Liked your note",
|
||||||
|
"seemly_short_thrush_bloom": "Requested to follow you",
|
||||||
|
"weird_seemly_termite_scold": "Accepted your follow request",
|
||||||
|
"pretty_born_jackal_dial": "Language",
|
||||||
|
"tired_happy_lobster_pet": "Change the language of the interface. Requires a reload to apply.",
|
||||||
|
"keen_aware_goldfish_thrive": "English",
|
||||||
|
"vivid_mellow_sawfish_approve": "French"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
200
messages/fr.json
200
messages/fr.json
|
|
@ -55,10 +55,8 @@
|
||||||
"awake_quick_cuckoo_smile": "Utilisateur suivi",
|
"awake_quick_cuckoo_smile": "Utilisateur suivi",
|
||||||
"funny_aloof_swan_loop": "Se désabonner",
|
"funny_aloof_swan_loop": "Se désabonner",
|
||||||
"cute_polite_oryx_blend": "Se désabonner",
|
"cute_polite_oryx_blend": "Se désabonner",
|
||||||
"dirty_inclusive_meerkat_nudge": "Annuler",
|
|
||||||
"big_safe_guppy_mix": "Désabonnement...",
|
"big_safe_guppy_mix": "Désabonnement...",
|
||||||
"misty_level_stingray_expand": "Utilisateur désabonné",
|
"misty_level_stingray_expand": "Utilisateur désabonné",
|
||||||
"lime_day_squid_pout": "Global",
|
|
||||||
"witty_heroic_trout_cry": "Ajouté par vous",
|
"witty_heroic_trout_cry": "Ajouté par vous",
|
||||||
"cuddly_such_swallow_hush": "Renommer",
|
"cuddly_such_swallow_hush": "Renommer",
|
||||||
"tense_quick_cod_favor": "Supprimer",
|
"tense_quick_cod_favor": "Supprimer",
|
||||||
|
|
@ -105,5 +103,201 @@
|
||||||
"busy_awful_mouse_jump": "Demande de suivi acceptée.",
|
"busy_awful_mouse_jump": "Demande de suivi acceptée.",
|
||||||
"front_sunny_penguin_flip": "Rejet de la demande de suivi...",
|
"front_sunny_penguin_flip": "Rejet de la demande de suivi...",
|
||||||
"green_flat_mayfly_trust": "Demande de suivi rejetée.",
|
"green_flat_mayfly_trust": "Demande de suivi rejetée.",
|
||||||
"large_vivid_horse_catch": "a reblogué•e"
|
"large_vivid_horse_catch": "a reblogué•e",
|
||||||
|
"top_cute_bison_nudge": "Blocage de l'utilisateur...",
|
||||||
|
"main_weary_racoon_peek": "Utilisateur bloqué",
|
||||||
|
"calm_icy_weasel_twirl": "Supprimer la note",
|
||||||
|
"gray_fun_toucan_slide": "Etes-vous sûr de vouloir supprimer cette note ?",
|
||||||
|
"royal_best_tern_transform": "Supprimer",
|
||||||
|
"new_funny_fox_boil": "Suppression de la note...",
|
||||||
|
"green_tasty_bumblebee_beam": "Note supprimée",
|
||||||
|
"many_misty_parakeet_fall": "Actions sur la note",
|
||||||
|
"front_lime_grizzly_persist": "Modifier",
|
||||||
|
"real_green_clownfish_pet": " Supprimer et reformuler",
|
||||||
|
"clean_yummy_owl_reside": "Cliquez pour copier",
|
||||||
|
"livid_tangy_lionfish_clasp": "Contenu sensible",
|
||||||
|
"sour_seemly_bird_hike": "Ce contenu est sensible",
|
||||||
|
"bald_direct_turtle_win": "Montrer",
|
||||||
|
"known_flaky_cockroach_dash": "Cacher",
|
||||||
|
"that_misty_mule_arrive": "Afficher moins",
|
||||||
|
"lazy_honest_mammoth_bump": "Afficher plus",
|
||||||
|
"dark_spare_goldfish_charm": "{count} caractères",
|
||||||
|
"drab_tense_turtle_comfort": "Répondre",
|
||||||
|
"vexed_fluffy_clownfish_dance": "Dé-aimer",
|
||||||
|
"royal_close_samuel_scold": "Aimer",
|
||||||
|
"lime_neat_ox_stab": "Dé-rebloguer",
|
||||||
|
"aware_helpful_marlin_drop": "Rebloguer",
|
||||||
|
"true_shy_jackal_drip": "Citer",
|
||||||
|
"busy_merry_cowfish_absorb": "Actions",
|
||||||
|
"slimy_least_ray_aid": "Aimer note",
|
||||||
|
"stale_new_ray_jolt": "Etes-vous sûr de vouloir aimer cette note ?",
|
||||||
|
"slimy_candid_tiger_read": "En cours...",
|
||||||
|
"mealy_slow_buzzard_commend": "Note aimé",
|
||||||
|
"odd_strong_halibut_prosper": "Dé-aimer note",
|
||||||
|
"slow_blue_parrot_savor": "Etes-vous sûr de vouloir dé-aimer cette note ?",
|
||||||
|
"busy_active_leopard_strive": "En cours...",
|
||||||
|
"fresh_direct_bear_affirm": "Note dé-aimée",
|
||||||
|
"best_mellow_llama_surge": "Rebloguer note",
|
||||||
|
"salty_plain_mallard_gaze": "Etes-vous sûr de vouloir rebloguer cette note ?",
|
||||||
|
"late_sunny_cobra_scold": "Rebloguage de la note...",
|
||||||
|
"weird_moving_hawk_lift": "Note rebloguée",
|
||||||
|
"main_fancy_octopus_loop": "Dé-rebloguer la note",
|
||||||
|
"odd_alive_swan_express": "Etes-vous sûr de vouloir dé-rebloguer cette note ?",
|
||||||
|
"white_sharp_gorilla_embrace": "Dé-rebloguage de la note...",
|
||||||
|
"royal_polite_moose_catch": "Note dé-rebloguée",
|
||||||
|
"mean_mean_badger_inspire": "Valeur",
|
||||||
|
"antsy_whole_alligator_blink": "Confirmer",
|
||||||
|
"game_tough_seal_adore": "Mentionner quelqu'un",
|
||||||
|
"plane_born_koala_hope": "Activer le Markdown",
|
||||||
|
"blue_ornate_coyote_tickle": "Insérer un emoji",
|
||||||
|
"top_patchy_earthworm_vent": "Joindre un fichier",
|
||||||
|
"frail_broad_mallard_dart": "Marquer comme sensible",
|
||||||
|
"gaudy_strong_puma_slide": "Sauvegarder",
|
||||||
|
"free_teal_bulldog_learn": "Envoyer",
|
||||||
|
"last_mean_peacock_zip": "Peut être vu par tout le monde.",
|
||||||
|
"funny_slow_jannes_walk": "Non répertorié",
|
||||||
|
"grassy_empty_raven_startle": "Privé",
|
||||||
|
"pretty_bold_baboon_wave": "Direct",
|
||||||
|
"grand_strong_gibbon_race": "Peut être vu par toute personne avec le lien.",
|
||||||
|
"white_teal_ostrich_yell": "Ne peut être vu que par vos abonnés.",
|
||||||
|
"lucky_mean_robin_link": "Ne peut être vu que par les utilisateurs mentionnés.",
|
||||||
|
"wise_late_fireant_walk": "Chargement des données de la note...",
|
||||||
|
"loved_busy_mantis_slide": "Répondre",
|
||||||
|
"tired_grassy_vulture_forgive": "Répondre à cette note",
|
||||||
|
"livid_livid_nils_snip": "Citer cette note",
|
||||||
|
"brief_cool_capybara_fear": "Composer une nouvelle note",
|
||||||
|
"chunky_dull_marlin_trip": "Composer",
|
||||||
|
"steep_suave_fish_snap": "Plus de données.",
|
||||||
|
"muddy_bland_shark_accept": "Vous avez tellement défilé•e, qu'il il n'y a plus rien à afficher.",
|
||||||
|
"petty_honest_fish_stir": "Soit vous avez tout rattrapé, soit il n'y a rien à montrer.",
|
||||||
|
"fine_arable_lemming_fold": "Il n'y a rien ici.",
|
||||||
|
"gaudy_bland_gorilla_talk": "Charger plus",
|
||||||
|
"fancy_this_wasp_renew": "Votre session a expirée",
|
||||||
|
"real_weird_deer_stop": "Vous avez été déconnecté•e. Veuillez vous reconnecter.",
|
||||||
|
"sunny_quick_lionfish_flip": "Non connecté•e",
|
||||||
|
"brave_known_pelican_drip": "Cette page nécessite une authentification. Veuillez vous connecter pour continuer.",
|
||||||
|
"chunky_awake_mallard_grow": "Note",
|
||||||
|
"steep_sour_warthog_aim": "Chargement",
|
||||||
|
"tough_nice_ox_drum": "Profil",
|
||||||
|
"noble_cute_ocelot_aim": "Créer un compte",
|
||||||
|
"novel_fine_stork_snap": "Connectez-vous à votre compte.",
|
||||||
|
"smug_main_whale_snip": "Saisissez vos informations d'identification pour <code>{host}</code> .",
|
||||||
|
"aware_awful_crow_spur": "Voici votre code",
|
||||||
|
"mushy_soft_lizard_propel": "Vous vous êtes connecté avec succès.",
|
||||||
|
"short_arable_leopard_zap": "Collez le code suivant dans votre application :",
|
||||||
|
"spare_aqua_warthog_mend": "Code d'autorisation",
|
||||||
|
"fresh_broad_cockroach_radiate": "Autoriser « {application} » ?",
|
||||||
|
"gross_antsy_kangaroo_succeed": "Vous vous connectez à <b>{application}</b> avec votre compte.",
|
||||||
|
"hour_close_giraffe_mop": "Cela permet à <b>{application}</b> d'effectuer les actions listées.",
|
||||||
|
"last_spare_polecat_reside": "Autoriser",
|
||||||
|
"lower_factual_frog_evoke": "Autorisation",
|
||||||
|
"awake_ago_capybara_kick": "$VERB vos informations de compte",
|
||||||
|
"teary_zesty_racoon_transform": "$VERB votre liste de blocage",
|
||||||
|
"whole_flaky_nuthatch_rush": "$VERB vos signets",
|
||||||
|
"still_spicy_lionfish_quell": "$VERB vos favoris",
|
||||||
|
"away_mean_dolphin_empower": "$VERB vos filtres",
|
||||||
|
"sleek_empty_penguin_radiate": "$VERB vos suivis",
|
||||||
|
"every_silly_racoon_lift": "$VERB vos listes",
|
||||||
|
"top_careful_scallop_clip": "$VERB votre liste de mutage",
|
||||||
|
"this_short_bulldog_walk": "$VERB vos notifications",
|
||||||
|
"fresh_odd_rook_forgive": "Effectuer des recherches",
|
||||||
|
"witty_whole_capybara_pull": "$VERB vos notes",
|
||||||
|
"agent_warm_javelina_blink": "Modifier vos conversations",
|
||||||
|
"dirty_red_jellyfish_ascend": "Ajouter des médias",
|
||||||
|
"crisp_vivid_seahorse_tend": "Signaler des utilisateurs",
|
||||||
|
"teary_such_jay_fade": "Lire et modifier",
|
||||||
|
"smug_safe_warthog_dare": "Lire",
|
||||||
|
"loose_large_blackbird_peek": "Modifier",
|
||||||
|
"late_mean_capybara_fade": "Succès",
|
||||||
|
"brave_acidic_lobster_fetch": "Votre mot de passe a été réinitialisé. Vous pouvez désormais vous connecter avec votre nouveau mot de passe.",
|
||||||
|
"every_tangy_koala_persist": "Retour à la page d'accueil",
|
||||||
|
"good_plane_gazelle_glow": "Votre mot de passe a été réinitialisé par un administrateur. Veuillez le modifier ici.",
|
||||||
|
"east_loud_lobster_explore": "Info",
|
||||||
|
"solid_slow_platypus_talk": "Saisissez votre nouveau mot de passe ci-dessous. Assurez-vous de l'enregistrer dans un gestionnaire de mots de passe.",
|
||||||
|
"tired_green_sloth_evoke": "Réinitialisez votre mot de passe",
|
||||||
|
"true_male_gadfly_stab": "Nouveau mot de passe",
|
||||||
|
"awful_cozy_jannes_rise": "Confirmez le mot de passe",
|
||||||
|
"noisy_round_skate_yell": "Réinitialiser",
|
||||||
|
"smart_bold_macaw_aid": "Doit comporter au moins {count} caractères",
|
||||||
|
"dry_smug_goldfish_promise": "Doit comporter au maximum {count} caractères",
|
||||||
|
"candid_fancy_leopard_prosper": "Les mots de passe ne correspondent pas",
|
||||||
|
"arable_arable_herring_lead": "Réinitialiser le mot de passe",
|
||||||
|
"broad_whole_herring_reside": "Préférences",
|
||||||
|
"tasty_late_termite_sew": "Compte",
|
||||||
|
"actual_mean_cow_dare": "Préférences du compte",
|
||||||
|
"suave_smart_mantis_climb": "Émojis",
|
||||||
|
"lucky_suave_myna_adore": "Demandez à votre administrateur d’ajouter des émojis.",
|
||||||
|
"actual_steep_llama_rest": "Aucun emoji trouvé.",
|
||||||
|
"mild_many_dolphin_mend": "Préférences d'emoji",
|
||||||
|
"lucky_ago_rat_pinch": "Non classé",
|
||||||
|
"empty_awful_lark_dart": "Compte non trouvé.",
|
||||||
|
"clean_even_mayfly_tap": "Changez d'utilisateur ou réessayez plus tard.",
|
||||||
|
"early_last_ocelot_praise": "Créer un compte",
|
||||||
|
"dirty_inclusive_meerkat_nudge": "Annuler",
|
||||||
|
"sea_maroon_peacock_yell": "Ne peut contenir que des lettres minuscules, des chiffres, des tirets ou des traits de soulignement",
|
||||||
|
"civil_loose_coyote_jump": "Vous devez accepter les conditions d'utilisation",
|
||||||
|
"plane_quick_chipmunk_rush": "J'accepte les",
|
||||||
|
"glad_last_crow_dine": "Conditions d'Utilisation",
|
||||||
|
"left_maroon_myna_drip": "Vous vous êtes inscrit. Vous pouvez désormais vous connecter avec votre nouveau compte.",
|
||||||
|
"steep_aqua_fox_harbor": "Fils",
|
||||||
|
"silly_sour_fireant_fear": "Échec de la création de l'application",
|
||||||
|
"level_due_ox_greet": "Connexion...",
|
||||||
|
"candid_frail_lion_value": "Échec de la génération de l'URL d'authentification",
|
||||||
|
"wide_least_samuel_conquer": "Style de la barre latérale gauche.",
|
||||||
|
"fluffy_north_crow_blink": "Encart",
|
||||||
|
"day_polite_newt_loop": "Barre latérale",
|
||||||
|
"jolly_mad_jackdaw_assure": "Flottant",
|
||||||
|
"agent_misty_firefox_arise": "Forme de tous les avatars utilisateurs.",
|
||||||
|
"polite_awful_ladybug_greet": "Rond",
|
||||||
|
"sad_each_cowfish_lock": "Carré",
|
||||||
|
"fit_cool_bulldog_dine": "Forme d'avatar",
|
||||||
|
"deft_seemly_donkey_slide": "Style de la barre latérale",
|
||||||
|
"quaint_clear_boar_attend": "Rendu MFM",
|
||||||
|
"aloof_helpful_larva_spur": "Afficher le Misskey-Flavoured Markdown",
|
||||||
|
"smart_awake_dachshund_view": "CSS personnalisé",
|
||||||
|
"loved_topical_rat_coax": "CSS personnalisé, appliqué à l'interface utilisateur.",
|
||||||
|
"wise_neat_ox_buzz": "Sombre",
|
||||||
|
"each_strong_snail_aid": "Clair",
|
||||||
|
"helpful_raw_seal_nurture": "Système",
|
||||||
|
"male_stout_florian_feast": "Thème de l'interface.",
|
||||||
|
"hour_elegant_mink_grip": "Thème",
|
||||||
|
"loud_raw_sheep_imagine": "Afficher les émojis personnalisés",
|
||||||
|
"inclusive_pink_tuna_enjoy": "Afficher les émojis personnalisés. Nécessite un rechargement de la page.",
|
||||||
|
"fair_swift_elephant_hunt": "Flouter les contenus sensibles",
|
||||||
|
"gray_minor_bee_endure": "Floute les notes marquées comme sensibles/spoiler.",
|
||||||
|
"stock_large_marten_comfort": "URL d'arrière-plan",
|
||||||
|
"mean_weird_donkey_stab": "Change l'image d'arrière-plan du site.",
|
||||||
|
"tired_jumpy_rook_slurp": "Barre de notifications",
|
||||||
|
"wide_new_robin_empower": "Affiche une barre latérale avec des notifications.",
|
||||||
|
"less_early_lionfish_honor": "Emojis Fluents (version plate)",
|
||||||
|
"many_tasty_midge_zoom": "Émojis Fluent",
|
||||||
|
"shy_clear_spider_cook": "Émojis Noto",
|
||||||
|
"new_brave_maggot_relish": "Émojis Twitter",
|
||||||
|
"slimy_sound_termite_hug": "Système",
|
||||||
|
"warm_round_dove_skip": "Thème utilisé pour le rendu des émojis. Nécessite un rechargement de la page.",
|
||||||
|
"weak_bad_martin_glow": "Thème Emoji",
|
||||||
|
"equal_blue_zebra_launch": "Ctrl+Entrée pour envoyer",
|
||||||
|
"heavy_pink_meerkat_affirm": "Envoyez une note en appuyant sur ⌘+Entrée ou Ctrl+Entrée.",
|
||||||
|
"north_nimble_turkey_transform": "Popup sur les profils",
|
||||||
|
"bold_moving_fly_savor": "Afficher un popup d'iinformations lorsque vous survolez l'avatar d'un utilisateur.",
|
||||||
|
"plane_dark_salmon_pout": "Charger automatiquement plus de notes lorsque vous atteignez le bas de la page.",
|
||||||
|
"helpful_early_worm_laugh": "Confirmer avant de supprimer une note.",
|
||||||
|
"trite_salty_eel_race": "Confirmer les suppressions",
|
||||||
|
"sleek_this_earthworm_hug": "Défilement infini",
|
||||||
|
"jolly_empty_bullock_mend": "Confirmer suivre",
|
||||||
|
"calm_male_wombat_relish": "Confirmez avant de suivre/ne plus suivre un utilisateur.",
|
||||||
|
"wacky_inner_osprey_intend": "Confirmer avant de rebloguer une note.",
|
||||||
|
"honest_great_rooster_taste": "Confirmer les reblogs",
|
||||||
|
"patchy_basic_alligator_inspire": "Confirmer J'aime",
|
||||||
|
"antsy_weak_raven_treat": "Confirmer avant d'aimer une note.",
|
||||||
|
"fuzzy_orange_tuna_succeed": "Vous a mentionné•e",
|
||||||
|
"grand_proof_quail_read": "A reblogué•e votre note",
|
||||||
|
"top_steep_scallop_care": "Vous a suivi•e",
|
||||||
|
"swift_just_beetle_devour": "A aimé•e votre note",
|
||||||
|
"seemly_short_thrush_bloom": "Fait une demande de suivi",
|
||||||
|
"weird_seemly_termite_scold": "A accepté•e votre demande de suivi",
|
||||||
|
"pretty_born_jackal_dial": "Langue",
|
||||||
|
"tired_happy_lobster_pet": "Changer la langue de l'interface. Nécessite un rechargement.",
|
||||||
|
"keen_aware_goldfish_thrive": "Anglais",
|
||||||
|
"vivid_mellow_sawfish_approve": "Français"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,15 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useTitle } from "@vueuse/core";
|
|
||||||
import { Loader } from "lucide-vue-next";
|
import { Loader } from "lucide-vue-next";
|
||||||
import Note from "~/components/notes/note.vue";
|
import Note from "~/components/notes/note.vue";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Note",
|
text: m.chunky_awake_mallard_grow(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
@ -57,7 +57,9 @@ watch(
|
||||||
|
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title: computed(() =>
|
title: computed(() =>
|
||||||
note.value ? note.value.account.display_name : "Loading",
|
note.value
|
||||||
|
? note.value.account.display_name
|
||||||
|
: m.steep_sour_warthog_aim(),
|
||||||
),
|
),
|
||||||
description: computed(() => (note.value ? note.value.content : undefined)),
|
description: computed(() => (note.value ? note.value.content : undefined)),
|
||||||
ogImage: computed(() =>
|
ogImage: computed(() =>
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@
|
||||||
</TimelineScroller>
|
</TimelineScroller>
|
||||||
<Card v-else class="shadow-none bg-transparent border-none p-4">
|
<Card v-else class="shadow-none bg-transparent border-none p-4">
|
||||||
<CardHeader class="text-center gap-y-4">
|
<CardHeader class="text-center gap-y-4">
|
||||||
<CardTitle class="text-">Account not found.</CardTitle>
|
<CardTitle>{{ m.empty_awful_lark_dart() }}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Check for typos or try again later.
|
{{ m.clean_even_mayfly_tap() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -23,6 +23,7 @@ import { Loader } from "lucide-vue-next";
|
||||||
import AccountProfile from "~/components/profiles/profile.vue";
|
import AccountProfile from "~/components/profiles/profile.vue";
|
||||||
import AccountTimeline from "~/components/timelines/account.vue";
|
import AccountTimeline from "~/components/timelines/account.vue";
|
||||||
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const username = (route.params.username as string).startsWith("@")
|
const username = (route.params.username as string).startsWith("@")
|
||||||
|
|
@ -33,7 +34,7 @@ definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Profile",
|
text: m.tough_nice_ox_drum(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
@ -43,10 +44,10 @@ const accountId = computed(() => account.value?.id ?? undefined);
|
||||||
|
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title: computed(() =>
|
title: computed(() =>
|
||||||
account.value ? account.value.display_name : "Loading",
|
account.value ? account.value.display_name : m.steep_sour_warthog_aim(),
|
||||||
),
|
),
|
||||||
ogTitle: computed(() =>
|
ogTitle: computed(() =>
|
||||||
account.value ? account.value.display_name : "Loading",
|
account.value ? account.value.display_name : m.steep_sour_warthog_aim(),
|
||||||
),
|
),
|
||||||
ogImage: computed(() => (account.value ? account.value.avatar : undefined)),
|
ogImage: computed(() => (account.value ? account.value.avatar : undefined)),
|
||||||
ogType: "profile",
|
ogType: "profile",
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,20 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Global from "~/components/timelines/global.vue";
|
import Global from "~/components/timelines/global.vue";
|
||||||
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Global",
|
title: m.real_tame_moose_greet(),
|
||||||
});
|
});
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Timelines",
|
text: m.steep_aqua_fox_harbor(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Global",
|
text: m.real_tame_moose_greet(),
|
||||||
href: "/global",
|
href: "/global",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Home from "~/components/timelines/home.vue";
|
import Home from "~/components/timelines/home.vue";
|
||||||
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Home",
|
title: "Home",
|
||||||
|
|
@ -18,10 +19,10 @@ definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Timelines",
|
text: m.steep_aqua_fox_harbor(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Home",
|
text: m.bland_chunky_sparrow_propel(),
|
||||||
href: "/home",
|
href: "/home",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -12,24 +12,27 @@
|
||||||
import Home from "~/components/timelines/home.vue";
|
import Home from "~/components/timelines/home.vue";
|
||||||
import Public from "~/components/timelines/public.vue";
|
import Public from "~/components/timelines/public.vue";
|
||||||
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: identity.value ? "Home" : "Public",
|
title: identity.value
|
||||||
|
? m.bland_chunky_sparrow_propel()
|
||||||
|
: m.lost_trick_dog_grace(),
|
||||||
});
|
});
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Timelines",
|
text: m.steep_aqua_fox_harbor(),
|
||||||
},
|
},
|
||||||
identity.value
|
identity.value
|
||||||
? {
|
? {
|
||||||
text: "Home",
|
text: m.bland_chunky_sparrow_propel(),
|
||||||
href: "/home",
|
href: "/home",
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
text: "Public",
|
text: m.lost_trick_dog_grace(),
|
||||||
href: "/public",
|
href: "/public",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,20 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import Local from "~/components/timelines/local.vue";
|
import Local from "~/components/timelines/local.vue";
|
||||||
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Local",
|
title: m.crazy_game_parrot_pave(),
|
||||||
});
|
});
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Timelines",
|
text: m.steep_aqua_fox_harbor(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Local",
|
text: m.crazy_game_parrot_pave(),
|
||||||
href: "/local",
|
href: "/local",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,17 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import Notifications from "~/components/timelines/notifications.vue";
|
import Notifications from "~/components/timelines/notifications.vue";
|
||||||
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Notifications",
|
title: m.that_patchy_mare_snip(),
|
||||||
});
|
});
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Notifications",
|
text: m.that_patchy_mare_snip(),
|
||||||
href: "/notifications",
|
href: "/notifications",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@ import { AlertCircle, Loader } from "lucide-vue-next";
|
||||||
import UserAuthForm from "~/components/oauth/login.vue";
|
import UserAuthForm from "~/components/oauth/login.vue";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "~/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "~/components/ui/alert";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { NuxtLink } from "#components";
|
import { NuxtLink } from "#components";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Sign In",
|
title: m.fuzzy_sea_moth_absorb(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const host = new URL(useBaseUrl().value).host;
|
const host = new URL(useBaseUrl().value).host;
|
||||||
|
|
@ -18,7 +19,7 @@ const { error, error_description } = useUrlSearchParams();
|
||||||
<template>
|
<template>
|
||||||
<div class="container relative flex h-svh flex-col items-center justify-center md:flex-row lg:max-w-none lg:px-0">
|
<div class="container relative flex h-svh flex-col items-center justify-center md:flex-row lg:max-w-none lg:px-0">
|
||||||
<Button :as="NuxtLink" href="/register" variant="link" class="absolute right-4 top-4 md:right-8 md:top-8">
|
<Button :as="NuxtLink" href="/register" variant="link" class="absolute right-4 top-4 md:right-8 md:top-8">
|
||||||
Register
|
{{ m.noble_cute_ocelot_aim() }}
|
||||||
</Button>
|
</Button>
|
||||||
<div class="relative hidden h-full flex-col bg-muted p-10 text-white dark:border-r lg:flex grow bg-center bg-no-repeat bg-cover"
|
<div class="relative hidden h-full flex-col bg-muted p-10 text-white dark:border-r lg:flex grow bg-center bg-no-repeat bg-cover"
|
||||||
:style="{
|
:style="{
|
||||||
|
|
@ -55,10 +56,11 @@ const { error, error_description } = useUrlSearchParams();
|
||||||
</Alert>
|
</Alert>
|
||||||
<div class="flex flex-col space-y-2 text-center">
|
<div class="flex flex-col space-y-2 text-center">
|
||||||
<h1 class="text-2xl font-semibold tracking-tight">
|
<h1 class="text-2xl font-semibold tracking-tight">
|
||||||
Log in to your account.
|
{{ m.novel_fine_stork_snap() }}
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-sm text-muted-foreground">
|
<p class="text-sm text-muted-foreground" v-html="m.smug_main_whale_snip({
|
||||||
Enter your credentials for <code>{{ host }}</code>.
|
host,
|
||||||
|
})">
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<UserAuthForm v-if="instance" :instance="instance" />
|
<UserAuthForm v-if="instance" :instance="instance" />
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
}">
|
}">
|
||||||
<Card class="w-full max-w-md">
|
<Card class="w-full max-w-md">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Here's your code</CardTitle>
|
<CardTitle>{{ m.aware_awful_crow_spur() }}</CardTitle>
|
||||||
<CardDescription>You have signed in successfully.<br />Paste the following code into your app:
|
<CardDescription>{{ m.mushy_soft_lizard_propel() }}<br />{{ m.short_arable_leopard_zap() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent class="grid">
|
<CardContent class="grid">
|
||||||
|
|
@ -23,9 +23,10 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "~/components/ui/card";
|
} from "~/components/ui/card";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Authorization Code",
|
title: m.spare_aqua_warthog_mend(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { code } = useUrlSearchParams();
|
const { code } = useUrlSearchParams();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@
|
||||||
<Card class="w-full max-w-md" as="form" method="POST" :action="url.pathname.replace('/oauth/consent', '/oauth/authorize')">
|
<Card class="w-full max-w-md" as="form" method="POST" :action="url.pathname.replace('/oauth/consent', '/oauth/authorize')">
|
||||||
<input type="hidden" v-for="([key, value]) in url.searchParams" :key="key" :name="key" :value="value" />
|
<input type="hidden" v-for="([key, value]) in url.searchParams" :key="key" :name="key" :value="value" />
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle as="h1" class="text-2xl break-words">Authorize “{{ application }}”?</CardTitle>
|
<CardTitle as="h1" class="text-2xl break-words">{{ m.fresh_broad_cockroach_radiate({
|
||||||
|
application: application ?? "",
|
||||||
|
}) }}</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Card>
|
<Card>
|
||||||
|
|
@ -23,16 +25,17 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="flex-col flex gap-y-1 text-sm">
|
<div class="flex-col flex gap-y-1 text-sm">
|
||||||
<p>You are signing in to <b>{{ application }}</b> with your
|
<p v-html="m.gross_antsy_kangaroo_succeed({
|
||||||
account.</p>
|
application: application ?? '',
|
||||||
<p>This allows <b>{{ application }}</b> to perform the above
|
})"></p>
|
||||||
account
|
<p v-html="m.hour_close_giraffe_mop({
|
||||||
actions.</p>
|
application: application ?? '',
|
||||||
|
})"></p>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardFooter class="grid gap-2">
|
<CardFooter class="grid gap-2">
|
||||||
<Button variant="default" type="submit">Authorize</Button>
|
<Button variant="default" type="submit">{{ m.last_spare_polecat_reside() }}</Button>
|
||||||
<Button :as="NuxtLink" href="/" variant="secondary">Cancel</Button>
|
<Button :as="NuxtLink" href="/" variant="secondary">{{ m.soft_bold_ant_attend() }}</Button>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -42,10 +45,11 @@
|
||||||
import { Check } from "lucide-vue-next";
|
import { Check } from "lucide-vue-next";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { NuxtLink } from "#components";
|
import { NuxtLink } from "#components";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Authorization",
|
title: m.lower_factual_frog_evoke(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const url = useRequestURL();
|
const url = useRequestURL();
|
||||||
|
|
@ -62,20 +66,20 @@ const scope = params.scope ? decodeURIComponent(params.scope as string) : "";
|
||||||
const validUrlParameters = application && redirectUri && clientId && scope;
|
const validUrlParameters = application && redirectUri && clientId && scope;
|
||||||
|
|
||||||
const oauthScopeText: Record<string, string> = {
|
const oauthScopeText: Record<string, string> = {
|
||||||
"rw:accounts": "$VERB your account information",
|
"rw:accounts": m.awake_ago_capybara_kick(),
|
||||||
"rw:blocks": "$VERB your block list",
|
"rw:blocks": m.teary_zesty_racoon_transform(),
|
||||||
"rw:bookmarks": "$VERB your bookmarks",
|
"rw:bookmarks": m.whole_flaky_nuthatch_rush(),
|
||||||
"rw:favourites": "$VERB your favourites",
|
"rw:favourites": m.still_spicy_lionfish_quell(),
|
||||||
"rw:filters": "$VERB your filters",
|
"rw:filters": m.away_mean_dolphin_empower(),
|
||||||
"rw:follows": "$VERB your follows",
|
"rw:follows": m.sleek_empty_penguin_radiate(),
|
||||||
"rw:lists": "$VERB your lists",
|
"rw:lists": m.every_silly_racoon_lift(),
|
||||||
"rw:mutes": "$VERB your mutes",
|
"rw:mutes": m.top_careful_scallop_clip(),
|
||||||
"rw:notifications": "$VERB your notifications",
|
"rw:notifications": m.this_short_bulldog_walk(),
|
||||||
"r:search": "Perform searches",
|
"r:search": m.fresh_odd_rook_forgive(),
|
||||||
"rw:statuses": "$VERB your statuses",
|
"rw:statuses": m.witty_whole_capybara_pull(),
|
||||||
"w:conversations": "Edit your conversations",
|
"w:conversations": m.agent_warm_javelina_blink(),
|
||||||
"w:media": "Upload media",
|
"w:media": m.dirty_red_jellyfish_ascend(),
|
||||||
"w:reports": "Report users",
|
"w:reports": m.crisp_vivid_seahorse_tend(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const scopes = scope.split(" ");
|
const scopes = scope.split(" ");
|
||||||
|
|
@ -103,7 +107,7 @@ const getScopeText = (fullScopes: string[]) => {
|
||||||
) {
|
) {
|
||||||
if (oauthScopeText[possibleScope]?.includes("$VERB")) {
|
if (oauthScopeText[possibleScope]?.includes("$VERB")) {
|
||||||
scopeTexts.push([
|
scopeTexts.push([
|
||||||
"Read and write",
|
m.teary_such_jay_fade(),
|
||||||
oauthScopeText[possibleScope]?.replace("$VERB", "") ?? "",
|
oauthScopeText[possibleScope]?.replace("$VERB", "") ?? "",
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -119,7 +123,7 @@ const getScopeText = (fullScopes: string[]) => {
|
||||||
) {
|
) {
|
||||||
if (oauthScopeText[possibleScope]?.includes("$VERB")) {
|
if (oauthScopeText[possibleScope]?.includes("$VERB")) {
|
||||||
scopeTexts.push([
|
scopeTexts.push([
|
||||||
"Read",
|
m.smug_safe_warthog_dare(),
|
||||||
oauthScopeText[possibleScope]?.replace("$VERB", "") ?? "",
|
oauthScopeText[possibleScope]?.replace("$VERB", "") ?? "",
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -134,7 +138,7 @@ const getScopeText = (fullScopes: string[]) => {
|
||||||
) {
|
) {
|
||||||
if (oauthScopeText[possibleScope]?.includes("$VERB")) {
|
if (oauthScopeText[possibleScope]?.includes("$VERB")) {
|
||||||
scopeTexts.push([
|
scopeTexts.push([
|
||||||
"Write",
|
m.loose_large_blackbird_peek(),
|
||||||
oauthScopeText[possibleScope]?.replace("$VERB", "") ?? "",
|
oauthScopeText[possibleScope]?.replace("$VERB", "") ?? "",
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
}">
|
}">
|
||||||
<Card v-if="params.success" class="w-full max-w-md">
|
<Card v-if="params.success" class="w-full max-w-md">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Success</CardTitle>
|
<CardTitle>{{ m.late_mean_capybara_fade() }}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Your password has been reset. You can now log in with your new password.
|
{{ m.brave_acidic_lobster_fetch() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardFooter class="grid">
|
<CardFooter class="grid">
|
||||||
<Button :as="NuxtLink" href="/" variant="default">
|
<Button :as="NuxtLink" href="/" variant="default">
|
||||||
Back to front page
|
{{ m.every_tangy_koala_persist() }}
|
||||||
</Button>
|
</Button>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -20,9 +20,9 @@
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<Alert v-if="params.login_reset" variant="default" class="mb-4">
|
<Alert v-if="params.login_reset" variant="default" class="mb-4">
|
||||||
<AlertCircle class="size-4" />
|
<AlertCircle class="size-4" />
|
||||||
<AlertTitle>Info</AlertTitle>
|
<AlertTitle>{{ m.east_loud_lobster_explore() }}</AlertTitle>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
Your password has been reset by an administrator. Please change it here.
|
{{ m.good_plane_gazelle_glow() }}
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
<Alert v-if="params.error" variant="destructive" class="mb-4">
|
<Alert v-if="params.error" variant="destructive" class="mb-4">
|
||||||
|
|
@ -32,9 +32,9 @@
|
||||||
{{ params.error_description }}
|
{{ params.error_description }}
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
<CardTitle as="h1">Reset your password</CardTitle>
|
<CardTitle as="h1">{{ m.tired_green_sloth_evoke() }}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Enter your new password below. Make sure to put it in a password manager.
|
{{ m.solid_slow_platypus_talk() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent class="grid gap-6">
|
<CardContent class="grid gap-6">
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
<FormField v-slot="{ componentField }" name="password">
|
<FormField v-slot="{ componentField }" name="password">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
New password
|
{{ m.true_male_gadfly_stab() }}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-correct="off"
|
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-correct="off"
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
<FormField v-slot="{ componentField }" name="password-confirm">
|
<FormField v-slot="{ componentField }" name="password-confirm">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Confirm password
|
{{ m.awful_cozy_jannes_rise() }}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-correct="off"
|
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-correct="off"
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
</FormField>
|
</FormField>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardFooter class="grid gap-2">
|
<CardFooter class="grid gap-2">
|
||||||
<Button variant="default" type="submit">Reset</Button>
|
<Button variant="default" type="submit">{{ m.noisy_round_skate_yell() }}</Button>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</form>
|
</form>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -100,10 +100,11 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/ui/form";
|
} from "~/components/ui/form";
|
||||||
import { Input } from "~/components/ui/input";
|
import { Input } from "~/components/ui/input";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { NuxtLink } from "#components";
|
import { NuxtLink } from "#components";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Reset Password",
|
title: m.arable_arable_herring_lead(),
|
||||||
});
|
});
|
||||||
|
|
||||||
identity.value = null;
|
identity.value = null;
|
||||||
|
|
@ -115,18 +116,26 @@ const formSchema = toTypedSchema(
|
||||||
password: z
|
password: z
|
||||||
.string()
|
.string()
|
||||||
.min(3, {
|
.min(3, {
|
||||||
message: "Must be at least 3 characters long",
|
message: m.smart_bold_macaw_aid({
|
||||||
|
count: 3,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
.max(100, {
|
.max(100, {
|
||||||
message: "Must be at most 100 characters long",
|
message: m.dry_smug_goldfish_promise({
|
||||||
|
count: 100,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
"password-confirm": z
|
"password-confirm": z
|
||||||
.string()
|
.string()
|
||||||
.min(3, {
|
.min(3, {
|
||||||
message: "Must be at least 3 characters long",
|
message: m.smart_bold_macaw_aid({
|
||||||
|
count: 3,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
.max(100, {
|
.max(100, {
|
||||||
message: "Must be at most 100 characters long",
|
message: m.dry_smug_goldfish_promise({
|
||||||
|
count: 100,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.superRefine((data, ctx) => {
|
.superRefine((data, ctx) => {
|
||||||
|
|
@ -134,7 +143,7 @@ const formSchema = toTypedSchema(
|
||||||
ctx.addIssue({
|
ctx.addIssue({
|
||||||
path: [...ctx.path, "password-confirm"],
|
path: [...ctx.path, "password-confirm"],
|
||||||
code: "custom",
|
code: "custom",
|
||||||
message: "Passwords do not match",
|
message: m.candid_fancy_leopard_prosper(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import SelectPreference from "~/components/preferences/select.vue";
|
import SelectPreference from "~/components/preferences/select.vue";
|
||||||
import SwitchPreference from "~/components/preferences/switch.vue";
|
import SwitchPreference from "~/components/preferences/switch.vue";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import {
|
import {
|
||||||
type BooleanSetting,
|
type BooleanSetting,
|
||||||
type EnumSetting,
|
type EnumSetting,
|
||||||
|
|
@ -25,14 +26,14 @@ import {
|
||||||
} from "~/settings.ts";
|
} from "~/settings.ts";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Preferences",
|
title: m.broad_whole_herring_reside(),
|
||||||
});
|
});
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Preferences",
|
text: m.broad_whole_herring_reside(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="md:px-8 px-4 py-2 max-w-7xl mx-auto w-full space-y-6">
|
<div class="md:px-8 px-4 py-2 max-w-7xl mx-auto w-full space-y-6">
|
||||||
<div :class="cn('grid gap-2', profileEditor?.dirty && 'grid-cols-[1fr,auto]')">
|
<div :class="cn('grid gap-2', profileEditor?.dirty && 'grid-cols-[1fr,auto]')">
|
||||||
<h1 class="scroll-m-20 text-3xl font-extrabold tracking-tight lg:text-4xl capitalize">
|
<h1 class="scroll-m-20 text-3xl font-extrabold tracking-tight lg:text-4xl capitalize">
|
||||||
Account
|
{{ m.tasty_late_termite_sew() }}
|
||||||
</h1>
|
</h1>
|
||||||
<Button class="ml-auto" v-if="profileEditor?.dirty" @click="profileEditor.submitForm">Save</Button>
|
<Button class="ml-auto" v-if="profileEditor?.dirty" @click="profileEditor.submitForm">Save</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -17,16 +17,17 @@ import { cn } from "@/lib/utils";
|
||||||
// biome-ignore lint/style/useImportType: <explanation>
|
// biome-ignore lint/style/useImportType: <explanation>
|
||||||
import ProfileEditor from "~/components/preferences/profile/editor.vue";
|
import ProfileEditor from "~/components/preferences/profile/editor.vue";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Account Preferences",
|
title: m.actual_mean_cow_dare(),
|
||||||
});
|
});
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Preferences",
|
text: m.broad_whole_herring_reside(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="md:px-8 px-4 py-2 max-w-7xl mx-auto w-full space-y-6">
|
<div class="md:px-8 px-4 py-2 max-w-7xl mx-auto w-full space-y-6">
|
||||||
<h1 class="scroll-m-20 text-3xl font-extrabold tracking-tight lg:text-4xl capitalize">
|
<h1 class="scroll-m-20 text-3xl font-extrabold tracking-tight lg:text-4xl capitalize">
|
||||||
Emojis
|
{{ m.suave_smart_mantis_climb() }}
|
||||||
</h1>
|
</h1>
|
||||||
<div v-if="emojis.length > 0" class="max-w-sm w-full relative">
|
<div v-if="emojis.length > 0" class="max-w-sm w-full relative">
|
||||||
<Input v-model="search" placeholder="Search" class="pl-8" />
|
<Input v-model="search" placeholder="Search" class="pl-8" />
|
||||||
|
|
@ -11,9 +11,9 @@
|
||||||
:name="name" />
|
:name="name" />
|
||||||
<Card v-else class="shadow-none bg-transparent border-none p-4">
|
<Card v-else class="shadow-none bg-transparent border-none p-4">
|
||||||
<CardHeader class="text-center gap-y-4">
|
<CardHeader class="text-center gap-y-4">
|
||||||
<CardTitle class="text-">No emojis found.</CardTitle>
|
<CardTitle>{{ m.actual_steep_llama_rest() }}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Ask your administrator to add some emojis.
|
{{ m.lucky_suave_myna_adore() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -24,17 +24,24 @@
|
||||||
import type { Emoji } from "@versia/client/types";
|
import type { Emoji } from "@versia/client/types";
|
||||||
import { Search } from "lucide-vue-next";
|
import { Search } from "lucide-vue-next";
|
||||||
import Category from "~/components/preferences/emojis/category.vue";
|
import Category from "~/components/preferences/emojis/category.vue";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "~/components/ui/card";
|
||||||
import { Input } from "~/components/ui/input";
|
import { Input } from "~/components/ui/input";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Emoji Preferences",
|
title: m.mild_many_dolphin_mend(),
|
||||||
});
|
});
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Preferences",
|
text: m.broad_whole_herring_reside(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
|
|
@ -56,11 +63,11 @@ const categories = computed(() => {
|
||||||
const categories = new Map<string, Emoji[]>();
|
const categories = new Map<string, Emoji[]>();
|
||||||
for (const emoji of emojis.value) {
|
for (const emoji of emojis.value) {
|
||||||
if (!emoji.category) {
|
if (!emoji.category) {
|
||||||
if (!categories.has("Uncategorized")) {
|
if (!categories.has(m.lucky_ago_rat_pinch())) {
|
||||||
categories.set("Uncategorized", []);
|
categories.set(m.lucky_ago_rat_pinch(), []);
|
||||||
}
|
}
|
||||||
|
|
||||||
categories.get("Uncategorized")?.push(emoji);
|
categories.get(m.lucky_ago_rat_pinch())?.push(emoji);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Preferences",
|
text: m.broad_whole_herring_reside(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Public from "~/components/timelines/public.vue";
|
import Public from "~/components/timelines/public.vue";
|
||||||
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Public",
|
title: "Public",
|
||||||
|
|
@ -18,10 +19,10 @@ definePageMeta({
|
||||||
layout: "app",
|
layout: "app",
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
text: "Timelines",
|
text: m.steep_aqua_fox_harbor(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Public",
|
text: m.lost_trick_dog_grace(),
|
||||||
href: "/public",
|
href: "/public",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,18 @@
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<Alert v-if="errors.error" variant="destructive" class="mb-4">
|
<Alert v-if="errors.error" variant="destructive" class="mb-4">
|
||||||
<AlertCircle class="size-4" />
|
<AlertCircle class="size-4" />
|
||||||
<AlertTitle>Error</AlertTitle>
|
<AlertTitle>{{ m.vexed_each_falcon_enjoy() }}</AlertTitle>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
{{ errors.error }}
|
{{ errors.error }}
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
<CardTitle as="h1" class="text-2xl break-words">Create an account</CardTitle>
|
<CardTitle as="h1" class="text-2xl break-words">{{ m.wide_topical_vole_walk() }}</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent v-if="instance && tos" class="grid gap-6">
|
<CardContent v-if="instance && tos" class="grid gap-6">
|
||||||
<FormField v-slot="{ componentField }" name="username">
|
<FormField v-slot="{ componentField }" name="username">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Username
|
{{ m.keen_clean_nils_slurp() }}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="petergriffin" type="text" auto-capitalize="none"
|
<Input placeholder="petergriffin" type="text" auto-capitalize="none"
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
<FormField v-slot="{ componentField }" name="email">
|
<FormField v-slot="{ componentField }" name="email">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Email address
|
{{ m.top_inclusive_wallaby_hack() }}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="peter.griffin@fox.com" type="email" auto-capitalize="none"
|
<Input placeholder="peter.griffin@fox.com" type="email" auto-capitalize="none"
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
<FormField v-slot="{ componentField }" name="password">
|
<FormField v-slot="{ componentField }" name="password">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Password
|
{{ m.livid_bright_wallaby_quiz() }}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-complete="password"
|
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-complete="password"
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
<FormField v-slot="{ componentField }" name="password-confirm">
|
<FormField v-slot="{ componentField }" name="password-confirm">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Confirm password
|
{{ m.awful_cozy_jannes_rise() }}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-complete="password"
|
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-complete="password"
|
||||||
|
|
@ -72,8 +72,8 @@
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
<Dialog>
|
<Dialog>
|
||||||
I agree to the <DialogTrigger :as-child="true"><Button variant="link"
|
{{ m.plane_quick_chipmunk_rush() }} <DialogTrigger :as-child="true"><Button variant="link"
|
||||||
class="px-0 underline">Terms of Service</Button>.</DialogTrigger>
|
class="px-0 underline">{{ m.glad_last_crow_dine() }}</Button>.</DialogTrigger>
|
||||||
<DialogContent class="!max-h-[90vh] overflow-auto">
|
<DialogContent class="!max-h-[90vh] overflow-auto">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>{{ instance.title }}
|
<DialogTitle>{{ instance.title }}
|
||||||
|
|
@ -88,11 +88,11 @@
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</FormField>
|
</FormField>
|
||||||
<div class="flex-col flex gap-y-1 text-sm text-muted-foreground">
|
<div class="flex-col flex gap-y-1 text-sm text-muted-foreground">
|
||||||
<p>Passwords are never stored in plain text.</p>
|
<p>{{ m.happy_house_dragonfly_clap() }}</p>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardFooter v-if="instance && tos" class="grid gap-2">
|
<CardFooter v-if="instance && tos" class="grid gap-2">
|
||||||
<Button variant="default" type="submit">Register</Button>
|
<Button variant="default" type="submit">{{ m.early_last_ocelot_praise() }}</Button>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
<div v-else class="p-4 flex items-center justify-center h-48">
|
<div v-else class="p-4 flex items-center justify-center h-48">
|
||||||
<Loader class="size-8 animate-spin" />
|
<Loader class="size-8 animate-spin" />
|
||||||
|
|
@ -100,14 +100,14 @@
|
||||||
</Card>
|
</Card>
|
||||||
<Card v-else class="w-full max-w-md">
|
<Card v-else class="w-full max-w-md">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Sorry :c</CardTitle>
|
<CardTitle>{{ m.wide_away_cat_taste() }}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Registrations are disabled on this instance.
|
{{ m.safe_candid_horse_jump() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardFooter class="grid">
|
<CardFooter class="grid">
|
||||||
<Button :as="NuxtLink" href="/" variant="default">
|
<Button :as="NuxtLink" href="/" variant="default">
|
||||||
Back to front page
|
{{ m.every_tangy_koala_persist() }}}
|
||||||
</Button>
|
</Button>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -117,7 +117,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { toTypedSchema } from "@vee-validate/zod";
|
import { toTypedSchema } from "@vee-validate/zod";
|
||||||
import { Client, type ResponseError } from "@versia/client";
|
import { Client, type ResponseError } from "@versia/client";
|
||||||
import { AlertCircle, Check, Loader } from "lucide-vue-next";
|
import { AlertCircle, Loader } from "lucide-vue-next";
|
||||||
import { useForm } from "vee-validate";
|
import { useForm } from "vee-validate";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -126,10 +126,11 @@ import { Checkbox } from "~/components/ui/checkbox";
|
||||||
import { Dialog, DialogContent, DialogHeader } from "~/components/ui/dialog";
|
import { Dialog, DialogContent, DialogHeader } from "~/components/ui/dialog";
|
||||||
import { FormItem } from "~/components/ui/form";
|
import { FormItem } from "~/components/ui/form";
|
||||||
import { Input } from "~/components/ui/input";
|
import { Input } from "~/components/ui/input";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { NuxtLink } from "#components";
|
import { NuxtLink } from "#components";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Register",
|
title: m.early_last_ocelot_praise(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const schema = toTypedSchema(
|
const schema = toTypedSchema(
|
||||||
|
|
@ -141,13 +142,10 @@ const schema = toTypedSchema(
|
||||||
username: z
|
username: z
|
||||||
.string()
|
.string()
|
||||||
.min(3)
|
.min(3)
|
||||||
.regex(
|
.regex(/^[a-z0-9_-]+$/, m.sea_maroon_peacock_yell()),
|
||||||
/^[a-z0-9_]+$/,
|
|
||||||
"Must be lowercase letters, numbers, or underscores",
|
|
||||||
),
|
|
||||||
reason: z.string().optional(),
|
reason: z.string().optional(),
|
||||||
tos: z.boolean().refine((value) => value, {
|
tos: z.boolean().refine((value) => value, {
|
||||||
message: "You must agree to the Terms of Service",
|
message: m.civil_loose_coyote_jump(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.superRefine((data, ctx) => {
|
.superRefine((data, ctx) => {
|
||||||
|
|
@ -155,7 +153,7 @@ const schema = toTypedSchema(
|
||||||
ctx.addIssue({
|
ctx.addIssue({
|
||||||
path: [...ctx.path, "password-confirm"],
|
path: [...ctx.path, "password-confirm"],
|
||||||
code: "custom",
|
code: "custom",
|
||||||
message: "Passwords do not match",
|
message: m.candid_fancy_leopard_prosper(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
}">
|
}">
|
||||||
<Card class="w-full max-w-md">
|
<Card class="w-full max-w-md">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Success</CardTitle>
|
<CardTitle>{{ m.late_mean_capybara_fade() }}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
You've successfully registered. You can now log in with your new account.
|
{{ m.left_maroon_myna_drip() }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardFooter class="grid">
|
<CardFooter class="grid">
|
||||||
<Button :as="NuxtLink" href="/" variant="default">
|
<Button :as="NuxtLink" href="/" variant="default">
|
||||||
Back to front page
|
{{ m.every_tangy_koala_persist() }}
|
||||||
</Button>
|
</Button>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Card, CardFooter, CardHeader, CardTitle } from "~/components/ui/card";
|
import { Card, CardFooter, CardHeader, CardTitle } from "~/components/ui/card";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
import { NuxtLink } from "#components";
|
import { NuxtLink } from "#components";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
|
|
|
||||||
417
settings.ts
417
settings.ts
|
|
@ -1,3 +1,6 @@
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
import { setLanguageTag } from "./paraglide/runtime";
|
||||||
|
|
||||||
export enum SettingType {
|
export enum SettingType {
|
||||||
String = "string",
|
String = "string",
|
||||||
Boolean = "boolean",
|
Boolean = "boolean",
|
||||||
|
|
@ -8,8 +11,8 @@ export enum SettingType {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Setting = {
|
export type Setting = {
|
||||||
title: string;
|
title: () => string;
|
||||||
description: string;
|
description: () => string;
|
||||||
notImplemented?: boolean;
|
notImplemented?: boolean;
|
||||||
type: SettingType;
|
type: SettingType;
|
||||||
value: unknown;
|
value: unknown;
|
||||||
|
|
@ -31,7 +34,7 @@ export type EnumSetting = Setting & {
|
||||||
value: string;
|
value: string;
|
||||||
options: {
|
options: {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: () => string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
|
@ -66,6 +69,7 @@ export enum SettingPages {
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SettingIds {
|
export enum SettingIds {
|
||||||
|
Language = "language",
|
||||||
Mfm = "mfm",
|
Mfm = "mfm",
|
||||||
CustomCSS = "custom-css",
|
CustomCSS = "custom-css",
|
||||||
Theme = "theme",
|
Theme = "theme",
|
||||||
|
|
@ -85,195 +89,226 @@ export enum SettingIds {
|
||||||
SidebarStyle = "sidebar-style",
|
SidebarStyle = "sidebar-style",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const settings: Record<SettingIds, Setting> = {
|
export const settings = (): Record<SettingIds, Setting> => {
|
||||||
[SettingIds.Mfm]: {
|
return {
|
||||||
title: "Render MFM",
|
[SettingIds.Mfm]: {
|
||||||
description: "Render Misskey-Flavoured Markdown.",
|
title: m.quaint_clear_boar_attend,
|
||||||
type: SettingType.Boolean,
|
description: m.aloof_helpful_larva_spur,
|
||||||
value: false,
|
type: SettingType.Boolean,
|
||||||
page: SettingPages.Behaviour,
|
value: false,
|
||||||
notImplemented: true,
|
page: SettingPages.Behaviour,
|
||||||
} as BooleanSetting,
|
notImplemented: true,
|
||||||
[SettingIds.SidebarStyle]: {
|
} as BooleanSetting,
|
||||||
title: "Sidebar Style",
|
[SettingIds.Language]: {
|
||||||
description: "Style of the left sidebar.",
|
title: m.pretty_born_jackal_dial,
|
||||||
type: SettingType.Enum,
|
description: m.tired_happy_lobster_pet,
|
||||||
value: "inset",
|
type: SettingType.Enum,
|
||||||
options: [
|
value: "en",
|
||||||
{
|
options: [
|
||||||
value: "inset",
|
{
|
||||||
label: "Inset",
|
value: "en",
|
||||||
},
|
label: () =>
|
||||||
{
|
m.keen_aware_goldfish_thrive(
|
||||||
value: "sidebar",
|
{},
|
||||||
label: "Sidebar",
|
{
|
||||||
},
|
languageTag: "en",
|
||||||
{
|
},
|
||||||
value: "floating",
|
),
|
||||||
label: "Floating",
|
},
|
||||||
},
|
{
|
||||||
],
|
value: "fr",
|
||||||
page: SettingPages.Appearance,
|
label: () =>
|
||||||
} as EnumSetting,
|
m.vivid_mellow_sawfish_approve(
|
||||||
[SettingIds.AvatarShape]: {
|
{},
|
||||||
title: "Avatar Shape",
|
{
|
||||||
description: "Shape of all user avatars.",
|
languageTag: "fr",
|
||||||
type: SettingType.Enum,
|
},
|
||||||
value: "square",
|
),
|
||||||
options: [
|
},
|
||||||
{
|
],
|
||||||
value: "circle",
|
page: SettingPages.Behaviour,
|
||||||
label: "Round",
|
} as EnumSetting,
|
||||||
},
|
[SettingIds.SidebarStyle]: {
|
||||||
{
|
title: m.deft_seemly_donkey_slide,
|
||||||
value: "square",
|
description: m.wide_least_samuel_conquer,
|
||||||
label: "Square",
|
type: SettingType.Enum,
|
||||||
},
|
value: "inset",
|
||||||
],
|
options: [
|
||||||
page: SettingPages.Appearance,
|
{
|
||||||
} as EnumSetting,
|
value: "inset",
|
||||||
[SettingIds.CustomCSS]: {
|
label: m.fluffy_north_crow_blink,
|
||||||
title: "Custom CSS",
|
},
|
||||||
description: "Custom CSS for the UI.",
|
{
|
||||||
type: SettingType.Code,
|
value: "sidebar",
|
||||||
value: "",
|
label: m.day_polite_newt_loop,
|
||||||
language: "css",
|
},
|
||||||
page: SettingPages.Appearance,
|
{
|
||||||
} as CodeSetting,
|
value: "floating",
|
||||||
[SettingIds.Theme]: {
|
label: m.jolly_mad_jackdaw_assure,
|
||||||
title: "Theme",
|
},
|
||||||
description: "UI theme.",
|
],
|
||||||
type: SettingType.Enum,
|
page: SettingPages.Appearance,
|
||||||
value: "dark",
|
} as EnumSetting,
|
||||||
options: [
|
[SettingIds.AvatarShape]: {
|
||||||
{
|
title: m.fit_cool_bulldog_dine,
|
||||||
value: "dark",
|
description: m.agent_misty_firefox_arise,
|
||||||
label: "Dark",
|
type: SettingType.Enum,
|
||||||
},
|
value: "square",
|
||||||
{
|
options: [
|
||||||
value: "light",
|
{
|
||||||
label: "Light",
|
value: "circle",
|
||||||
},
|
label: m.polite_awful_ladybug_greet,
|
||||||
{
|
},
|
||||||
value: "system",
|
{
|
||||||
label: "System",
|
value: "square",
|
||||||
},
|
label: m.sad_each_cowfish_lock,
|
||||||
],
|
},
|
||||||
page: SettingPages.Appearance,
|
],
|
||||||
} as EnumSetting,
|
page: SettingPages.Appearance,
|
||||||
[SettingIds.CustomEmojis]: {
|
} as EnumSetting,
|
||||||
title: "Render Custom Emojis",
|
[SettingIds.CustomCSS]: {
|
||||||
description: "Render custom emojis. Requires a page reload to apply.",
|
title: m.smart_awake_dachshund_view,
|
||||||
type: SettingType.Boolean,
|
description: m.loved_topical_rat_coax,
|
||||||
value: true,
|
type: SettingType.Code,
|
||||||
page: SettingPages.Behaviour,
|
value: "",
|
||||||
} as BooleanSetting,
|
language: "css",
|
||||||
[SettingIds.ShowContentWarning]: {
|
page: SettingPages.Appearance,
|
||||||
title: "Blur Sensitive Content",
|
} as CodeSetting,
|
||||||
description: "Blur notes marked sensitive/spoiler.",
|
[SettingIds.Theme]: {
|
||||||
type: SettingType.Boolean,
|
title: m.hour_elegant_mink_grip,
|
||||||
value: true,
|
description: m.male_stout_florian_feast,
|
||||||
page: SettingPages.Behaviour,
|
type: SettingType.Enum,
|
||||||
} as BooleanSetting,
|
value: "dark",
|
||||||
[SettingIds.PopupAvatarHover]: {
|
options: [
|
||||||
title: "Popup Profile Hover",
|
{
|
||||||
description: "Show profile popup when hovering over a user's avatar.",
|
value: "dark",
|
||||||
type: SettingType.Boolean,
|
label: m.wise_neat_ox_buzz,
|
||||||
value: true,
|
},
|
||||||
page: SettingPages.Behaviour,
|
{
|
||||||
} as BooleanSetting,
|
value: "light",
|
||||||
[SettingIds.InfiniteScroll]: {
|
label: m.each_strong_snail_aid,
|
||||||
title: "Infinite Scroll",
|
},
|
||||||
description:
|
{
|
||||||
"Automatically load more notes when reaching the bottom of the page.",
|
value: "system",
|
||||||
type: SettingType.Boolean,
|
label: m.helpful_raw_seal_nurture,
|
||||||
value: true,
|
},
|
||||||
page: SettingPages.Behaviour,
|
],
|
||||||
} as BooleanSetting,
|
page: SettingPages.Appearance,
|
||||||
[SettingIds.ConfirmDelete]: {
|
} as EnumSetting,
|
||||||
title: "Confirm Delete",
|
[SettingIds.CustomEmojis]: {
|
||||||
description: "Confirm before deleting a note.",
|
title: m.loud_raw_sheep_imagine,
|
||||||
type: SettingType.Boolean,
|
description: m.inclusive_pink_tuna_enjoy,
|
||||||
value: true,
|
type: SettingType.Boolean,
|
||||||
page: SettingPages.Behaviour,
|
value: true,
|
||||||
} as BooleanSetting,
|
page: SettingPages.Behaviour,
|
||||||
[SettingIds.ConfirmFollow]: {
|
} as BooleanSetting,
|
||||||
title: "Confirm Follow",
|
[SettingIds.ShowContentWarning]: {
|
||||||
description: "Confirm before following/unfollowing a user.",
|
title: m.fair_swift_elephant_hunt,
|
||||||
type: SettingType.Boolean,
|
description: m.gray_minor_bee_endure,
|
||||||
value: false,
|
type: SettingType.Boolean,
|
||||||
page: SettingPages.Behaviour,
|
value: true,
|
||||||
} as BooleanSetting,
|
page: SettingPages.Behaviour,
|
||||||
[SettingIds.ConfirmReblog]: {
|
} as BooleanSetting,
|
||||||
title: "Confirm Reblog",
|
[SettingIds.PopupAvatarHover]: {
|
||||||
description: "Confirm before reblogging a note.",
|
title: m.north_nimble_turkey_transform,
|
||||||
type: SettingType.Boolean,
|
description: m.bold_moving_fly_savor,
|
||||||
value: false,
|
type: SettingType.Boolean,
|
||||||
page: SettingPages.Behaviour,
|
value: true,
|
||||||
} as BooleanSetting,
|
page: SettingPages.Behaviour,
|
||||||
[SettingIds.ConfirmLike]: {
|
} as BooleanSetting,
|
||||||
title: "Confirm Like",
|
[SettingIds.InfiniteScroll]: {
|
||||||
description: "Confirm before liking a note.",
|
title: m.sleek_this_earthworm_hug,
|
||||||
type: SettingType.Boolean,
|
description: m.plane_dark_salmon_pout,
|
||||||
value: false,
|
type: SettingType.Boolean,
|
||||||
page: SettingPages.Behaviour,
|
value: true,
|
||||||
} as BooleanSetting,
|
page: SettingPages.Behaviour,
|
||||||
[SettingIds.CtrlEnterToSend]: {
|
} as BooleanSetting,
|
||||||
title: "Ctrl+Enter to Send",
|
[SettingIds.ConfirmDelete]: {
|
||||||
description: "Send a note by pressing ⌘+Enter or Ctrl+Enter.",
|
title: m.trite_salty_eel_race,
|
||||||
type: SettingType.Boolean,
|
description: m.helpful_early_worm_laugh,
|
||||||
value: true,
|
type: SettingType.Boolean,
|
||||||
page: SettingPages.Behaviour,
|
value: true,
|
||||||
} as BooleanSetting,
|
page: SettingPages.Behaviour,
|
||||||
[SettingIds.EmojiTheme]: {
|
} as BooleanSetting,
|
||||||
title: "Emoji Theme",
|
[SettingIds.ConfirmFollow]: {
|
||||||
description:
|
title: m.jolly_empty_bullock_mend,
|
||||||
"Theme used for rendering emojis. Requires a page reload to apply.",
|
description: m.calm_male_wombat_relish,
|
||||||
type: SettingType.Enum,
|
type: SettingType.Boolean,
|
||||||
value: "native",
|
value: false,
|
||||||
options: [
|
page: SettingPages.Behaviour,
|
||||||
{
|
} as BooleanSetting,
|
||||||
value: "native",
|
[SettingIds.ConfirmReblog]: {
|
||||||
label: "Operating System",
|
title: m.honest_great_rooster_taste,
|
||||||
},
|
description: m.wacky_inner_osprey_intend,
|
||||||
{
|
type: SettingType.Boolean,
|
||||||
value: "twemoji",
|
value: false,
|
||||||
label: "Twitter Emojis",
|
page: SettingPages.Behaviour,
|
||||||
},
|
} as BooleanSetting,
|
||||||
{
|
[SettingIds.ConfirmLike]: {
|
||||||
value: "noto",
|
title: m.patchy_basic_alligator_inspire,
|
||||||
label: "Noto Emoji",
|
description: m.antsy_weak_raven_treat,
|
||||||
},
|
type: SettingType.Boolean,
|
||||||
{
|
value: false,
|
||||||
value: "fluent",
|
page: SettingPages.Behaviour,
|
||||||
label: "Fluent Emojis",
|
} as BooleanSetting,
|
||||||
},
|
[SettingIds.CtrlEnterToSend]: {
|
||||||
{
|
title: m.equal_blue_zebra_launch,
|
||||||
value: "fluent-flat",
|
description: m.heavy_pink_meerkat_affirm,
|
||||||
label: "Fluent Emojis (flat version)",
|
type: SettingType.Boolean,
|
||||||
},
|
value: true,
|
||||||
],
|
page: SettingPages.Behaviour,
|
||||||
page: SettingPages.Appearance,
|
} as BooleanSetting,
|
||||||
} as EnumSetting,
|
[SettingIds.EmojiTheme]: {
|
||||||
[SettingIds.BackgroundURL]: {
|
title: m.weak_bad_martin_glow,
|
||||||
title: "Background URL",
|
description: m.warm_round_dove_skip,
|
||||||
description: "Change the background image of the site.",
|
type: SettingType.Enum,
|
||||||
type: SettingType.String,
|
value: "native",
|
||||||
value: "",
|
options: [
|
||||||
page: SettingPages.Appearance,
|
{
|
||||||
} as StringSetting,
|
value: "native",
|
||||||
[SettingIds.NotificationsSidebar]: {
|
label: m.slimy_sound_termite_hug,
|
||||||
title: "Notifications Sidebar",
|
},
|
||||||
description: "Display a sidebar with notifications on desktop.",
|
{
|
||||||
type: SettingType.Boolean,
|
value: "twemoji",
|
||||||
value: true,
|
label: m.new_brave_maggot_relish,
|
||||||
page: SettingPages.Appearance,
|
},
|
||||||
} as BooleanSetting,
|
{
|
||||||
|
value: "noto",
|
||||||
|
label: m.shy_clear_spider_cook,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "fluent",
|
||||||
|
label: m.many_tasty_midge_zoom,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "fluent-flat",
|
||||||
|
label: m.less_early_lionfish_honor,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
page: SettingPages.Appearance,
|
||||||
|
} as EnumSetting,
|
||||||
|
[SettingIds.BackgroundURL]: {
|
||||||
|
title: m.stock_large_marten_comfort,
|
||||||
|
description: m.mean_weird_donkey_stab,
|
||||||
|
type: SettingType.String,
|
||||||
|
value: "",
|
||||||
|
page: SettingPages.Appearance,
|
||||||
|
} as StringSetting,
|
||||||
|
[SettingIds.NotificationsSidebar]: {
|
||||||
|
title: m.tired_jumpy_rook_slurp,
|
||||||
|
description: m.wide_new_robin_empower,
|
||||||
|
type: SettingType.Boolean,
|
||||||
|
value: true,
|
||||||
|
page: SettingPages.Appearance,
|
||||||
|
} as BooleanSetting,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSettingsForPage = (page: SettingPages): Partial<Settings> => {
|
export const getSettingsForPage = (page: SettingPages): Partial<Settings> => {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(settings).filter(([, setting]) => setting.page === page),
|
Object.entries(settings()).filter(
|
||||||
|
([, setting]) => setting.page === page,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -284,14 +319,14 @@ export const getSettingsForPage = (page: SettingPages): Partial<Settings> => {
|
||||||
export const mergeSettings = (
|
export const mergeSettings = (
|
||||||
settingsToMerge: Record<SettingIds, Setting["value"]>,
|
settingsToMerge: Record<SettingIds, Setting["value"]>,
|
||||||
): Settings => {
|
): Settings => {
|
||||||
const finalSettings = structuredClone(settings);
|
const finalSettings = settings();
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(settingsToMerge)) {
|
for (const [key, value] of Object.entries(settingsToMerge)) {
|
||||||
if (key in settings) {
|
if (key in settings()) {
|
||||||
finalSettings[key as SettingIds].value = value;
|
finalSettings[key as SettingIds].value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return finalSettings;
|
return finalSettings;
|
||||||
};
|
};
|
||||||
export type Settings = typeof settings;
|
export type Settings = ReturnType<typeof settings>;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import type { ApplicationData } from "@versia/client/types";
|
import type { ApplicationData } from "@versia/client/types";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { toast } from "vue-sonner";
|
import { toast } from "vue-sonner";
|
||||||
|
import * as m from "~/paraglide/messages.js";
|
||||||
|
|
||||||
export const signIn = async (appData: Ref<ApplicationData | null>) => {
|
export const signIn = async (appData: Ref<ApplicationData | null>) => {
|
||||||
const id = toast.loading("Signing in...");
|
const id = toast.loading(m.level_due_ox_greet());
|
||||||
|
|
||||||
const output = await client.value.createApp("Versia", {
|
const output = await client.value.createApp("Versia", {
|
||||||
scopes: ["read", "write", "follow", "push"],
|
scopes: ["read", "write", "follow", "push"],
|
||||||
|
|
@ -13,7 +14,7 @@ export const signIn = async (appData: Ref<ApplicationData | null>) => {
|
||||||
|
|
||||||
if (!output?.data) {
|
if (!output?.data) {
|
||||||
toast.dismiss(id);
|
toast.dismiss(id);
|
||||||
toast.error("Failed to create app");
|
toast.error(m.silly_sour_fireant_fear());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,7 +31,7 @@ export const signIn = async (appData: Ref<ApplicationData | null>) => {
|
||||||
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
toast.dismiss(id);
|
toast.dismiss(id);
|
||||||
toast.error("Failed to generate auth URL");
|
toast.error(m.candid_frail_lion_value());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue