mirror of
https://github.com/versia-pub/frontend.git
synced 2026-03-13 03:29:16 +01:00
feat: ✨ Add support for accounts on other instances
This commit is contained in:
parent
18eee4d481
commit
29b4cb43ca
13 changed files with 179 additions and 40 deletions
|
|
@ -3,7 +3,7 @@ export type ConfirmModalOptions = {
|
|||
message?: string;
|
||||
confirmText?: string;
|
||||
cancelText?: string;
|
||||
inputType?: "none" | "text" | "textarea";
|
||||
inputType?: "none" | "text" | "textarea" | "url";
|
||||
defaultValue?: string;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
AlertDialogTitle,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Input, UrlInput } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import {
|
||||
|
|
@ -32,6 +32,8 @@ const resolvePromise = ref<((result: ConfirmModalResult) => void) | null>(null);
|
|||
|
||||
function open(options: ConfirmModalOptions): Promise<ConfirmModalResult> {
|
||||
isOpen.value = true;
|
||||
isValid.value = false;
|
||||
|
||||
modalOptions.value = {
|
||||
title: options.title || m.antsy_whole_alligator_blink(),
|
||||
message: options.message,
|
||||
|
|
@ -68,6 +70,8 @@ function handleCancel() {
|
|||
confirmModalService.register({
|
||||
open,
|
||||
});
|
||||
|
||||
const isValid = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -82,6 +86,8 @@ confirmModalService.register({
|
|||
|
||||
<Input v-if="modalOptions.inputType === 'text'" v-model="inputValue" />
|
||||
|
||||
<UrlInput v-if="modalOptions.inputType === 'url'" v-model="inputValue" placeholder="google.com" v-model:is-valid="isValid" />
|
||||
|
||||
<Textarea v-else-if="modalOptions.inputType === 'textarea'" v-model="inputValue" rows="6" />
|
||||
|
||||
<AlertDialogFooter class="w-full">
|
||||
|
|
@ -91,11 +97,11 @@ confirmModalService.register({
|
|||
</Button>
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction :as-child="true">
|
||||
<Button @click="handleConfirm">
|
||||
<Button @click="handleConfirm" :disabled="!isValid && modalOptions.inputType === 'url'">
|
||||
{{ modalOptions.confirmText }}
|
||||
</Button>
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</template>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ import {
|
|||
const appData = useAppData();
|
||||
const isMobile = useMediaQuery("(max-width: 768px)");
|
||||
|
||||
const signInAction = () => signIn(appData);
|
||||
const signInAction = () => signIn(appData, new URL(useBaseUrl().value));
|
||||
|
||||
const signOut = async (userId?: string) => {
|
||||
const id = toast.loading("Signing out...");
|
||||
|
|
@ -164,4 +164,4 @@ const switchAccount = async (userId: string) => {
|
|||
|
||||
window.location.href = "/";
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
export { default as Input } from "./Input.vue";
|
||||
export { default as UrlInput } from "./url.vue";
|
||||
|
|
|
|||
53
components/ui/input/url.vue
Normal file
53
components/ui/input/url.vue
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<script setup lang="ts">
|
||||
import { useVModel } from "@vueuse/core";
|
||||
import { Check, X } from "lucide-vue-next";
|
||||
import type { HTMLAttributes } from "vue";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import Input from "./Input.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
defaultValue?: string | number;
|
||||
modelValue?: string | number;
|
||||
class?: HTMLAttributes["class"];
|
||||
}>();
|
||||
|
||||
const emits =
|
||||
defineEmits<(e: "update:modelValue", payload: string | number) => void>();
|
||||
|
||||
const modelValue = useVModel(props, "modelValue", emits, {
|
||||
passive: true,
|
||||
defaultValue: props.defaultValue,
|
||||
});
|
||||
|
||||
const isValid = defineModel<boolean>("isValid");
|
||||
|
||||
const tryGuessUrl = (string: string) =>
|
||||
URL.canParse(`https://${string}`) &&
|
||||
string.includes(".") &&
|
||||
string.length > 3 &&
|
||||
string.charAt(string.length - 1) !== ".";
|
||||
|
||||
const isValidUrl = computed(
|
||||
() =>
|
||||
URL.canParse(modelValue.value as string) ||
|
||||
tryGuessUrl(modelValue.value as string),
|
||||
);
|
||||
|
||||
watch(modelValue, (value) => {
|
||||
if (!URL.canParse(value as string) && tryGuessUrl(value as string)) {
|
||||
modelValue.value = `https://${value}`;
|
||||
}
|
||||
});
|
||||
|
||||
watch(isValidUrl, (value) => {
|
||||
isValid.value = value;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-3">
|
||||
<Input v-model="modelValue" v-bind="$attrs" />
|
||||
<p v-if="isValidUrl" class="text-green-600 text-sm"><Check class="inline size-4" /> {{ m.sunny_small_warbler_express() }}</p>
|
||||
<p v-else-if="(modelValue?.toString().length ?? 0) > 0" class="text-destructive text-sm"><X class="inline size-4" /> {{ m.teal_late_grebe_blend() }}</p>
|
||||
</div>
|
||||
</template>
|
||||
Loading…
Add table
Add a link
Reference in a new issue