refactor: ♻️ Replace megalodon with @lysand-org/client

This commit is contained in:
Jesse Wierzbinski 2024-06-07 13:09:15 -10:00
parent 5c528e8d03
commit 0bd3237965
No known key found for this signature in database
41 changed files with 147 additions and 170 deletions

View file

@ -19,7 +19,7 @@ provideHeadlessUseId(() => useId());
const code = useRequestURL().searchParams.get("code"); const code = useRequestURL().searchParams.get("code");
const appData = useAppData(); const appData = useAppData();
const tokenData = useTokenData(); const tokenData = useTokenData();
const client = useMegalodon(tokenData); const client = useClient(tokenData);
const instance = useInstance(); const instance = useInstance();
const description = useExtendedDescription(client); const description = useExtendedDescription(client);
@ -28,12 +28,12 @@ useSeoMeta({
return titleChunk ? `${titleChunk} · Lysand` : "Lysand"; return titleChunk ? `${titleChunk} · Lysand` : "Lysand";
}, },
title: computed(() => instance.value?.title ?? ""), title: computed(() => instance.value?.title ?? ""),
ogImage: computed(() => instance.value?.banner), ogImage: computed(() => instance.value?.banner.url),
twitterTitle: computed(() => instance.value?.title ?? ""), twitterTitle: computed(() => instance.value?.title ?? ""),
twitterDescription: computed(() => twitterDescription: computed(() =>
convert(description.value?.content ?? ""), convert(description.value?.content ?? ""),
), ),
twitterImage: computed(() => instance.value?.banner), twitterImage: computed(() => instance.value?.banner.url),
description: computed(() => convert(description.value?.content ?? "")), description: computed(() => convert(description.value?.content ?? "")),
ogDescription: computed(() => convert(description.value?.content ?? "")), ogDescription: computed(() => convert(description.value?.content ?? "")),
ogSiteName: "Lysand", ogSiteName: "Lysand",
@ -57,7 +57,7 @@ if (code) {
new URL("/", useRequestURL().origin).toString(), new URL("/", useRequestURL().origin).toString(),
) )
.then((res) => { .then((res) => {
tokenData.value = res; tokenData.value = res.data;
// Remove code from URL // Remove code from URL
window.history.replaceState( window.history.replaceState(

BIN
bun.lockb

Binary file not shown.

View file

@ -206,87 +206,64 @@ const canSubmit = computed(
content.value?.trim().length <= characterLimit.value, content.value?.trim().length <= characterLimit.value,
); );
const tokenData = useTokenData(); const tokenData = useTokenData();
const client = useMegalodon(tokenData); const client = useClient(tokenData);
const send = async () => { const send = async () => {
loading.value = true; loading.value = true;
if (!tokenData.value || !client.value) {
if (respondingType.value === "edit") { throw new Error("Not authenticated");
fetch(
new URL(
`/api/v1/statuses/${respondingTo.value?.id}`,
client.value?.baseUrl ?? "",
).toString(),
{
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${tokenData.value?.access_token}`,
},
body: JSON.stringify({
status: content.value?.trim() ?? "",
content_type: markdown.value
? "text/markdown"
: "text/plain",
spoiler_text: cw.value ? cwContent.value.trim() : undefined,
sensitive: cw.value,
media_ids: files.value
.filter((file) => !!file.api_id)
.map((file) => file.api_id),
}),
},
)
.then(async (res) => {
if (!res.ok) {
throw new Error("Failed to edit status");
}
content.value = "";
loading.value = false;
useEvent("composer:send-edit", await res.json());
})
.finally(() => {
useEvent("composer:close");
});
return;
} }
fetch(new URL("/api/v1/statuses", client.value?.baseUrl ?? "").toString(), { if (respondingType.value === "edit" && respondingTo.value) {
method: "POST", const response = await client.value.editStatus(respondingTo.value.id, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${tokenData.value?.access_token}`,
},
body: JSON.stringify({
status: content.value?.trim() ?? "", status: content.value?.trim() ?? "",
content_type: markdown.value ? "text/markdown" : "text/plain", content_type: markdown.value ? "text/markdown" : "text/plain",
in_reply_to_id:
respondingType.value === "reply"
? respondingTo.value?.id
: null,
quote_id:
respondingType.value === "quote"
? respondingTo.value?.id
: null,
spoiler_text: cw.value ? cwContent.value.trim() : undefined, spoiler_text: cw.value ? cwContent.value.trim() : undefined,
sensitive: cw.value, sensitive: cw.value,
media_ids: files.value media_ids: files.value
.filter((file) => !!file.api_id) .filter((file) => !!file.api_id)
.map((file) => file.api_id), .map((file) => file.api_id) as string[],
}),
})
.then(async (res) => {
if (!res.ok) {
throw new Error("Failed to send status");
}
content.value = "";
loading.value = false;
useEvent("composer:send", await res.json());
})
.finally(() => {
useEvent("composer:close");
}); });
if (!response.data) {
throw new Error("Failed to edit status");
}
content.value = "";
loading.value = false;
useEvent("composer:send-edit", response.data);
useEvent("composer:close");
return;
}
const response = await client.value.postStatus(
content.value?.trim() ?? "",
{
content_type: markdown.value ? "text/markdown" : "text/plain",
in_reply_to_id:
respondingType.value === "reply"
? respondingTo.value?.id
: undefined,
quote_id:
respondingType.value === "quote"
? respondingTo.value?.id
: undefined,
spoiler_text: cw.value ? cwContent.value.trim() : undefined,
sensitive: cw.value,
media_ids: files.value
.filter((file) => !!file.api_id)
.map((file) => file.api_id) as string[],
},
);
if (!response.data) {
throw new Error("Failed to send status");
}
content.value = "";
loading.value = false;
useEvent("composer:send", response.data as Status);
useEvent("composer:close");
}; };
const characterLimit = computed( const characterLimit = computed(

View file

@ -74,7 +74,7 @@ const files = defineModel<
}); });
const tokenData = useTokenData(); const tokenData = useTokenData();
const client = useMegalodon(tokenData); const client = useClient(tokenData);
const fileInput = ref<HTMLInputElement | null>(null); const fileInput = ref<HTMLInputElement | null>(null);
const openFilePicker = () => { const openFilePicker = () => {

View file

@ -175,7 +175,7 @@ const loadingAuth = ref(false);
const appData = useAppData(); const appData = useAppData();
const tokenData = useTokenData(); const tokenData = useTokenData();
const client = useMegalodon(); const client = useClient();
const me = useMe(); const me = useMe();
const compose = () => { const compose = () => {
@ -191,18 +191,18 @@ const signIn = async () => {
website: useBaseUrl().value, website: useBaseUrl().value,
}); });
if (!output) { if (!output?.data) {
alert("Failed to create app"); alert("Failed to create app");
return; return;
} }
appData.value = output; appData.value = output.data;
const url = await client.value?.generateAuthUrl( const url = await client.value?.generateAuthUrl(
output.client_id, output.data.client_id,
output.client_secret, output.data.client_secret,
{ {
scope: ["read", "write", "follow", "push"], scopes: ["read", "write", "follow", "push"],
redirect_uri: new URL("/", useRequestURL().origin).toString(), redirect_uri: new URL("/", useRequestURL().origin).toString(),
}, },
); );

View file

@ -2,8 +2,8 @@
<div class="flex flex-col p-10 gap-4 h-full"> <div class="flex flex-col p-10 gap-4 h-full">
<div <div
class="aspect-video shrink-0 w-full rounded ring-white/5 bg-dark-800 shadow overflow-hidden ring-1 hover:ring-2 duration-100"> class="aspect-video shrink-0 w-full rounded ring-white/5 bg-dark-800 shadow overflow-hidden ring-1 hover:ring-2 duration-100">
<img class="object-cover w-full h-full duration-150 hover:scale-[102%] ease-in-out" v-if="instance?.banner" <img class="object-cover w-full h-full duration-150 hover:scale-[102%] ease-in-out"
alt="Instance banner" :src="instance.banner" /> v-if="instance?.banner.url" alt="Instance banner" :src="instance.banner.url" />
</div> </div>
<div class="prose prose-invert prose-sm"> <div class="prose prose-invert prose-sm">
@ -11,15 +11,15 @@
<div v-html="description?.content"></div> <div v-html="description?.content"></div>
</div> </div>
<div v-if="instance?.contact_account" class="flex flex-col gap-2 mt-auto"> <div v-if="instance?.contact.account" class="flex flex-col gap-2 mt-auto">
<h2 class="text-gray-200 font-semibold uppercase text-xs">Administrator</h2> <h2 class="text-gray-200 font-semibold uppercase text-xs">Administrator</h2>
<SocialElementsUsersSmallCard :account="instance.contact_account" /> <SocialElementsUsersSmallCard :account="instance.contact.account" />
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
const client = useMegalodon(); const client = useClient();
const instance = useInstance(); const instance = useInstance();
const description = useExtendedDescription(client); const description = useExtendedDescription(client);
</script> </script>

View file

@ -112,7 +112,7 @@ useListen("composer:send-edit", (note) => {
const tokenData = useTokenData(); const tokenData = useTokenData();
const isSignedIn = useSignedIn(); const isSignedIn = useSignedIn();
const me = useMe(); const me = useMe();
const client = useMegalodon(tokenData); const client = useClient(tokenData);
const { const {
loaded, loaded,
note: outputtedNote, note: outputtedNote,

View file

@ -16,6 +16,6 @@ const props = defineProps<{
}>(); }>();
const tokenData = useTokenData(); const tokenData = useTokenData();
const client = useMegalodon(tokenData); const client = useClient(tokenData);
const account = useAccount(client, props.account_id); const account = useAccount(client, props.account_id);
</script> </script>

View file

@ -105,7 +105,7 @@ const props = defineProps<{
const skeleton = computed(() => !props.account); const skeleton = computed(() => !props.account);
const tokenData = useTokenData(); const tokenData = useTokenData();
const me = useMe(); const me = useMe();
const client = useMegalodon(tokenData); const client = useClient(tokenData);
const accountId = computed(() => props.account?.id ?? null); const accountId = computed(() => props.account?.id ?? null);
const { relationship, isLoading } = useRelationship(client, accountId); const { relationship, isLoading } = useRelationship(client, accountId);

View file

@ -7,7 +7,7 @@ const props = defineProps<{
id?: string; id?: string;
}>(); }>();
const client = useMegalodon(); const client = useClient();
const timelineParameters = ref({}); const timelineParameters = ref({});
const { timeline, loadNext, loadPrev } = useAccountTimeline( const { timeline, loadNext, loadPrev } = useAccountTimeline(
client.value, client.value,

View file

@ -4,7 +4,7 @@
<script lang="ts" setup> <script lang="ts" setup>
const tokenData = useTokenData(); const tokenData = useTokenData();
const client = useMegalodon(tokenData); const client = useClient(tokenData);
const timelineParameters = ref({}); const timelineParameters = ref({});
const { timeline, loadNext, loadPrev } = useHomeTimeline( const { timeline, loadNext, loadPrev } = useHomeTimeline(
client.value, client.value,

View file

@ -3,7 +3,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
const client = useMegalodon(); const client = useClient();
const timelineParameters = ref({}); const timelineParameters = ref({});
const { timeline, loadNext, loadPrev } = useLocalTimeline( const { timeline, loadNext, loadPrev } = useLocalTimeline(
client.value, client.value,

View file

@ -15,7 +15,7 @@
<script lang="ts" setup> <script lang="ts" setup>
const tokenData = useTokenData(); const tokenData = useTokenData();
const client = useMegalodon(tokenData); const client = useClient(tokenData);
const isLoading = ref(true); const isLoading = ref(true);

View file

@ -3,7 +3,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
const client = useMegalodon(); const client = useClient();
const timelineParameters = ref({}); const timelineParameters = ref({});
const { timeline, loadNext, loadPrev } = usePublicTimeline( const { timeline, loadNext, loadPrev } = usePublicTimeline(
client.value, client.value,

View file

@ -1,8 +1,8 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Account } from "~/types/mastodon/account"; import type { Account } from "~/types/mastodon/account";
export const useAccount = ( export const useAccount = (
client: MaybeRef<Mastodon | null>, client: MaybeRef<LysandClient | null>,
accountId: MaybeRef<string | null>, accountId: MaybeRef<string | null>,
) => { ) => {
if (!client) { if (!client) {

View file

@ -1,8 +1,8 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Account } from "~/types/mastodon/account"; import type { Account } from "~/types/mastodon/account";
export const useAccountSearch = ( export const useAccountSearch = (
client: MaybeRef<Mastodon | null>, client: MaybeRef<LysandClient | null>,
q: string, q: string,
): Ref<Account[] | null> => { ): Ref<Account[] | null> => {
const output = ref(null as Account[] | null); const output = ref(null as Account[] | null);

View file

@ -1,8 +1,8 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Status } from "~/types/mastodon/status"; import type { Status } from "~/types/mastodon/status";
export const useAccountTimeline = ( export const useAccountTimeline = (
client: Mastodon | null, client: LysandClient | null,
id: MaybeRef<string | null>, id: MaybeRef<string | null>,
options: MaybeRef<{ options: MaybeRef<{
limit?: number | undefined; limit?: number | undefined;

View file

@ -1,8 +1,12 @@
import type { LysandClient } from "@lysand-org/client";
import { StorageSerializers } from "@vueuse/core"; import { StorageSerializers } from "@vueuse/core";
import type { OAuth } from "megalodon";
export type ApplicationData = Awaited<
ReturnType<LysandClient["createApp"]>
>["data"];
export const useAppData = () => { export const useAppData = () => {
return useLocalStorage<OAuth.AppData | null>("lysand:app_data", null, { return useLocalStorage<ApplicationData | null>("lysand:app_data", null, {
serializer: StorageSerializers.object, serializer: StorageSerializers.object,
}); });
}; };

View file

@ -1,7 +1,6 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { InstanceWithExtra } from "./Instance";
export const useCacheRefresh = (client: MaybeRef<Mastodon | null>) => { export const useCacheRefresh = (client: MaybeRef<LysandClient | null>) => {
if (process.server) return; if (process.server) return;
const tokenData = useTokenData(); const tokenData = useTokenData();
@ -43,7 +42,7 @@ export const useCacheRefresh = (client: MaybeRef<Mastodon | null>) => {
toValue(client) toValue(client)
?.getInstance() ?.getInstance()
.then((res) => { .then((res) => {
instance.value = res.data as InstanceWithExtra; instance.value = res.data;
}); });
}); });
}; };

View file

@ -1,11 +1,13 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
type ExtendedDescription = { type ExtendedDescription = {
updated_at: string; updated_at: string;
content: string; content: string;
}; };
export const useExtendedDescription = (client: MaybeRef<Mastodon | null>) => { export const useExtendedDescription = (
client: MaybeRef<LysandClient | null>,
) => {
if (!ref(client).value) { if (!ref(client).value) {
return ref(null as ExtendedDescription | null); return ref(null as ExtendedDescription | null);
} }
@ -13,7 +15,7 @@ export const useExtendedDescription = (client: MaybeRef<Mastodon | null>) => {
const output = ref(null as ExtendedDescription | null); const output = ref(null as ExtendedDescription | null);
ref(client) ref(client)
.value?.client.get("/api/v1/instance/extended_description") .value?.getInstanceExtendedDescription()
.then((res) => { .then((res) => {
output.value = res.data; output.value = res.data;
}); });

View file

@ -1,8 +1,8 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Status } from "~/types/mastodon/status"; import type { Status } from "~/types/mastodon/status";
export const useHomeTimeline = ( export const useHomeTimeline = (
client: Mastodon | null, client: LysandClient | null,
options: MaybeRef<{ options: MaybeRef<{
local?: boolean; local?: boolean;
limit?: number; limit?: number;

View file

@ -1,26 +1,15 @@
import type { LysandClient } from "@lysand-org/client";
import { StorageSerializers } from "@vueuse/core"; import { StorageSerializers } from "@vueuse/core";
import type { Mastodon } from "megalodon";
import type { Instance } from "~/types/mastodon/instance";
export type InstanceWithExtra = Instance & { // Return type of LysandClient.getInstance
banner: string | null; export type Instance = Awaited<ReturnType<LysandClient["getInstance"]>>["data"];
lysand_version: string;
sso: {
forced: boolean;
providers: {
id: string;
name: string;
icon?: string;
}[];
};
};
export const useInstance = () => { export const useInstance = () => {
if (process.server) { if (process.server) {
return ref(null); return ref(null);
} }
return useLocalStorage<InstanceWithExtra | null>("lysand:instance", null, { return useLocalStorage<Instance | null>("lysand:instance", null, {
serializer: StorageSerializers.object, serializer: StorageSerializers.object,
}); });
}; };

View file

@ -1,8 +1,8 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Status } from "~/types/mastodon/status"; import type { Status } from "~/types/mastodon/status";
export const useLocalTimeline = ( export const useLocalTimeline = (
client: Mastodon | null, client: LysandClient | null,
options: MaybeRef< options: MaybeRef<
Partial<{ Partial<{
only_media: boolean; only_media: boolean;

View file

@ -1,15 +1,18 @@
import { Mastodon, type OAuth } from "megalodon"; import { LysandClient, type Token } from "@lysand-org/client";
export const useMegalodon = ( export const useClient = (
tokenData?: MaybeRef<OAuth.TokenData | null>, tokenData?: MaybeRef<Token | null>,
disableOnServer = false, disableOnServer = false,
): Ref<Mastodon | null> => { ): Ref<LysandClient | null> => {
if (disableOnServer && process.server) { if (disableOnServer && process.server) {
return ref(null); return ref(null);
} }
return computed( return computed(
() => () =>
new Mastodon(useBaseUrl().value, toValue(tokenData)?.access_token), new LysandClient(
new URL(useBaseUrl().value),
toValue(tokenData)?.access_token,
),
); );
}; };

View file

@ -1,7 +1,10 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Status } from "~/types/mastodon/status"; import type { Status } from "~/types/mastodon/status";
export const useNote = (client: MaybeRef<Mastodon | null>, noteId: string) => { export const useNote = (
client: MaybeRef<LysandClient | null>,
noteId: string,
) => {
if (!ref(client).value) { if (!ref(client).value) {
return ref(null as Status | null); return ref(null as Status | null);
} }

View file

@ -1,8 +1,8 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Context } from "~/types/mastodon/context"; import type { Context } from "~/types/mastodon/context";
export const useNoteContext = ( export const useNoteContext = (
client: MaybeRef<Mastodon | null>, client: MaybeRef<LysandClient | null>,
noteId: MaybeRef<string | null>, noteId: MaybeRef<string | null>,
) => { ) => {
if (!ref(client).value) { if (!ref(client).value) {

View file

@ -1,9 +1,9 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Status } from "~/types/mastodon/status"; import type { Status } from "~/types/mastodon/status";
export const useNoteData = ( export const useNoteData = (
noteProp: MaybeRef<Status | undefined>, noteProp: MaybeRef<Status | undefined>,
client: Ref<Mastodon | null>, client: Ref<LysandClient | null>,
) => { ) => {
const isReply = computed(() => !!toValue(noteProp)?.in_reply_to_id); const isReply = computed(() => !!toValue(noteProp)?.in_reply_to_id);
const isQuote = computed(() => !!toValue(noteProp)?.quote); const isQuote = computed(() => !!toValue(noteProp)?.quote);

View file

@ -1,8 +1,8 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Notification } from "~/types/mastodon/notification"; import type { Notification } from "~/types/mastodon/notification";
export const useNotificationTimeline = ( export const useNotificationTimeline = (
client: Mastodon | null, client: LysandClient | null,
options: MaybeRef<{ options: MaybeRef<{
limit?: number | undefined; limit?: number | undefined;
max_id?: string | undefined; max_id?: string | undefined;

View file

@ -1,8 +1,8 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Status } from "~/types/mastodon/status"; import type { Status } from "~/types/mastodon/status";
export const usePublicTimeline = ( export const usePublicTimeline = (
client: Mastodon | null, client: LysandClient | null,
options: MaybeRef<{ options: MaybeRef<{
only_media?: boolean; only_media?: boolean;
limit?: number; limit?: number;

View file

@ -1,8 +1,8 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Relationship } from "~/types/mastodon/relationship"; import type { Relationship } from "~/types/mastodon/relationship";
export const useRelationship = ( export const useRelationship = (
client: MaybeRef<Mastodon | null>, client: MaybeRef<LysandClient | null>,
accountId: MaybeRef<string | null>, accountId: MaybeRef<string | null>,
) => { ) => {
const relationship = ref(null as Relationship | null); const relationship = ref(null as Relationship | null);

View file

@ -1,10 +1,10 @@
import type { Mastodon } from "megalodon"; import type { LysandClient } from "@lysand-org/client";
import type { Account } from "~/types/mastodon/account"; import type { Account } from "~/types/mastodon/account";
import type { Mention } from "~/types/mastodon/mention"; import type { Mention } from "~/types/mastodon/mention";
export const useResolveMentions = ( export const useResolveMentions = (
mentions: Ref<Mention[]>, mentions: Ref<Mention[]>,
client: Mastodon | null, client: LysandClient | null,
): Ref<Account[]> => { ): Ref<Account[]> => {
if (!client) { if (!client) {
return ref([]); return ref([]);

View file

@ -1,6 +1,6 @@
import type { InstanceWithExtra } from "./Instance"; import type { Instance } from "./Instance";
export const useSSOConfig = (): Ref<InstanceWithExtra["sso"] | null> => { export const useSSOConfig = (): Ref<Instance["sso"] | null> => {
const instance = useInstance(); const instance = useInstance();
return computed(() => instance.value?.sso || null); return computed(() => instance.value?.sso || null);

View file

@ -1,4 +1,4 @@
import type { Mastodon, Response } from "megalodon"; import type { LysandClient, Output } from "@lysand-org/client";
interface BaseOptions { interface BaseOptions {
max_id?: string; max_id?: string;
@ -6,9 +6,9 @@ interface BaseOptions {
} }
type FetchTimelineFunction<Element, Options> = ( type FetchTimelineFunction<Element, Options> = (
client: Mastodon, client: LysandClient,
options: Options & BaseOptions, options: Options & BaseOptions,
) => Promise<Response<Element[]>>; ) => Promise<Output<Element[]>>;
export const useTimeline = < export const useTimeline = <
Element extends { Element extends {
@ -16,7 +16,7 @@ export const useTimeline = <
}, },
Options, Options,
>( >(
client: Mastodon | null, client: LysandClient | null,
fetchTimeline: FetchTimelineFunction<Element, Options> | null | undefined, fetchTimeline: FetchTimelineFunction<Element, Options> | null | undefined,
options: MaybeRef<Options & BaseOptions>, options: MaybeRef<Options & BaseOptions>,
): { ): {
@ -98,7 +98,7 @@ export const useIdTimeline = <
}, },
Options, Options,
>( >(
client: Mastodon | null, client: LysandClient | null,
id: MaybeRef<string | null>, id: MaybeRef<string | null>,
fetchTimeline: FetchTimelineFunction<Element, Options> | null | undefined, fetchTimeline: FetchTimelineFunction<Element, Options> | null | undefined,
options: MaybeRef<Options & BaseOptions>, options: MaybeRef<Options & BaseOptions>,

View file

@ -1,8 +1,8 @@
import type { Token } from "@lysand-org/client";
import { StorageSerializers } from "@vueuse/core"; import { StorageSerializers } from "@vueuse/core";
import type { OAuth } from "megalodon";
export const useTokenData = () => { export const useTokenData = () => {
return useLocalStorage<OAuth.TokenData | null>("lysand:token_data", null, { return useLocalStorage<Token | null>("lysand:token_data", null, {
serializer: StorageSerializers.object, serializer: StorageSerializers.object,
}); });
}; };

View file

@ -47,7 +47,7 @@ const { width } = useWindowSize();
const { n, o_i_d_c } = useMagicKeys(); const { n, o_i_d_c } = useMagicKeys();
const tokenData = useTokenData(); const tokenData = useTokenData();
const client = useMegalodon(tokenData); const client = useClient(tokenData);
const providers = useSSOConfig(); const providers = useSSOConfig();
watchEffect(async () => { watchEffect(async () => {
@ -71,7 +71,7 @@ watchEffect(async () => {
} }
const response = await fetch( const response = await fetch(
new URL("/api/v1/sso", client.value?.baseUrl), new URL("/api/v1/sso", client.value?.url),
{ {
method: "POST", method: "POST",
headers: { headers: {

View file

@ -25,10 +25,12 @@
"generate": "nuxt generate", "generate": "nuxt generate",
"preview": "nuxt preview", "preview": "nuxt preview",
"postinstall": "nuxt prepare", "postinstall": "nuxt prepare",
"lint": "bunx @biomejs/biome check ." "lint": "bunx @biomejs/biome check .",
"check": "bunx tsc -p ."
}, },
"dependencies": { "dependencies": {
"@ark-ui/vue": "^3.3.0", "@ark-ui/vue": "^3.3.1",
"@lysand-org": "github:lysand-org/api#main",
"@nuxt/fonts": "^0.7.0", "@nuxt/fonts": "^0.7.0",
"@tailwindcss/typography": "^0.5.13", "@tailwindcss/typography": "^0.5.13",
"@vee-validate/nuxt": "^4.13.1", "@vee-validate/nuxt": "^4.13.1",
@ -39,7 +41,6 @@
"html-to-text": "^9.0.5", "html-to-text": "^9.0.5",
"iconify-icon": "^2.1.0", "iconify-icon": "^2.1.0",
"magic-regexp": "^0.8.0", "magic-regexp": "^0.8.0",
"megalodon": "^10.0.1",
"mitt": "^3.0.1", "mitt": "^3.0.1",
"nanoid": "^5.0.7", "nanoid": "^5.0.7",
"nuxt": "^3.11.2", "nuxt": "^3.11.2",
@ -48,7 +49,7 @@
"nuxt-shiki": "^0.3.0", "nuxt-shiki": "^0.3.0",
"overlayscrollbars": "^2.8.3", "overlayscrollbars": "^2.8.3",
"overlayscrollbars-vue": "^0.5.9", "overlayscrollbars-vue": "^0.5.9",
"shiki": "^1.6.2", "shiki": "^1.6.3",
"vue": "^3.4.27", "vue": "^3.4.27",
"vue-router": "^4.3.2", "vue-router": "^4.3.2",
"zod": "^3.23.8" "zod": "^3.23.8"
@ -59,7 +60,8 @@
"@nuxtjs/tailwindcss": "^6.12.0", "@nuxtjs/tailwindcss": "^6.12.0",
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.7",
"@types/html-to-text": "^9.0.4", "@types/html-to-text": "^9.0.4",
"@vue-email/nuxt": "^0.8.19" "@vue-email/nuxt": "^0.8.19",
"typescript": "^5.4.5"
}, },
"trustedDependencies": [ "trustedDependencies": [
"@biomejs/biome", "@biomejs/biome",

View file

@ -20,7 +20,7 @@ definePageMeta({
const element = ref<HTMLElement | null>(null); const element = ref<HTMLElement | null>(null);
const route = useRoute(); const route = useRoute();
const client = useMegalodon(); const client = useClient();
const uuid = route.params.uuid as string; const uuid = route.params.uuid as string;
const note = useNote(client, uuid); const note = useNote(client, uuid);

View file

@ -15,7 +15,7 @@ definePageMeta({
}); });
const route = useRoute(); const route = useRoute();
const client = useMegalodon(undefined, true); const client = useClient(undefined, true);
const username = (route.params.username as string).replace("@", ""); const username = (route.params.username as string).replace("@", "");
const accounts = useAccountSearch(client, username); const accounts = useAccountSearch(client, username);

View file

@ -11,6 +11,4 @@
definePageMeta({ definePageMeta({
layout: "app", layout: "app",
}); });
const me = useMe();
</script> </script>

View file

@ -27,7 +27,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
const url = useRequestURL();
const query = useRoute().query; const query = useRoute().query;
const code = query.code; const code = query.code;

View file

@ -44,7 +44,7 @@
</VeeErrorMessage> </VeeErrorMessage>
</VeeField> </VeeField>
<VeeField name="reason" as="div" v-slot="{ errors, field }" validate-on-change> <VeeField name="reason" as="div" v-slot="{ errors }" validate-on-change>
<label for="reason" class="block text-sm font-medium leading-6 text-gray-50">Why do you want to <label for="reason" class="block text-sm font-medium leading-6 text-gray-50">Why do you want to
join?</label> join?</label>
<div class="mt-2"> <div class="mt-2">
@ -62,7 +62,7 @@
class="rounded disabled:hover:cursor-wait mr-1 align-middle mb-0.5 text-pink-700 !ring-0 !outline-none" class="rounded disabled:hover:cursor-wait mr-1 align-middle mb-0.5 text-pink-700 !ring-0 !outline-none"
required /> required />
<span class="text-sm text-gray-100">I agree to the terms and conditions of this server <a <span class="text-sm text-gray-100">I agree to the terms and conditions of this server <a
class="underline font-bold" target="_blank" :href="instance.uri">available here</a></span> class="underline font-bold" target="_blank" :href="'#'">available here</a></span>
<VeeErrorMessage name="tos" as="p" class="mt-2 text-sm text-red-600" v-slot="{ message }"> <VeeErrorMessage name="tos" as="p" class="mt-2 text-sm text-red-600" v-slot="{ message }">
{{ message }} {{ message }}
</VeeErrorMessage> </VeeErrorMessage>
@ -88,6 +88,7 @@ import { toTypedSchema } from "@vee-validate/zod";
import type { AxiosError } from "axios"; import type { AxiosError } from "axios";
import { z } from "zod"; import { z } from "zod";
import LoginInput from "../../components/LoginInput.vue"; import LoginInput from "../../components/LoginInput.vue";
// TODO: Add instance TOS link
const schema = toTypedSchema( const schema = toTypedSchema(
z z
@ -114,7 +115,7 @@ const schema = toTypedSchema(
}), }),
); );
const client = useMegalodon(); const client = useClient();
const instance = useInstance(); const instance = useInstance();
const errors = ref<{ const errors = ref<{