elk/composables/masto/masto.ts
2024-02-24 16:46:14 +00:00

112 lines
3.4 KiB
TypeScript

import type { Pausable } from '@vueuse/core'
import type { mastodon } from 'masto'
import { createRestAPIClient, createStreamingAPIClient } from 'masto'
import type { Ref } from 'vue'
import type { ElkInstance } from '../users'
import type { UserLogin } from '~/types'
export function createMasto() {
return {
client: shallowRef<mastodon.rest.Client>(undefined as never),
streamingClient: shallowRef<mastodon.streaming.Client | undefined>(),
}
}
export type ElkMasto = ReturnType<typeof createMasto>
export function useMasto() {
return useNuxtApp().$masto as ElkMasto
}
export function useMastoClient() {
return useMasto().client.value
}
export function mastoLogin(masto: ElkMasto, user: Pick<UserLogin, 'server' | 'token'>) {
const server = user.server
const url = `https://${server}`
const instance: ElkInstance = reactive(getInstanceCache(server) || { uri: server, accountDomain: server })
const accessToken = user.token
const createStreamingClient = (streamingApiUrl: string | undefined) => {
return streamingApiUrl ? createStreamingAPIClient({ streamingApiUrl, accessToken, implementation: globalThis.WebSocket }) : undefined
}
const streamingApiUrl = instance?.urls?.streamingApi
masto.client.value = createRestAPIClient({ url, accessToken })
masto.streamingClient.value = createStreamingClient(streamingApiUrl)
// Refetch instance info in the background on login
masto.client.value.v1.instance.fetch().then((newInstance) => {
Object.assign(instance, newInstance)
if (newInstance.urls.streamingApi !== streamingApiUrl)
masto.streamingClient.value = createStreamingClient(newInstance.urls.streamingApi)
instanceStorage.value[server] = newInstance
})
return instance
}
interface UseStreamingOptions<Controls extends boolean> {
/**
* Expose more controls
*
* @default false
*/
controls?: Controls
/**
* Connect on calling
*
* @default true
*/
immediate?: boolean
}
export function useStreaming(
cb: (client: mastodon.streaming.Client) => mastodon.streaming.Subscription,
options: UseStreamingOptions<true>,
): { stream: Ref<mastodon.streaming.Subscription | undefined> } & Pausable
export function useStreaming(
cb: (client: mastodon.streaming.Client) => mastodon.streaming.Subscription,
options?: UseStreamingOptions<false>,
): Ref<mastodon.streaming.Subscription | undefined>
export function useStreaming(
cb: (client: mastodon.streaming.Client) => mastodon.streaming.Subscription,
{ immediate = true, controls }: UseStreamingOptions<boolean> = {},
): ({ stream: Ref<mastodon.streaming.Subscription | undefined> } & Pausable) | Ref<mastodon.streaming.Subscription | undefined> {
const { streamingClient } = useMasto()
const isActive = ref(immediate)
const stream = ref<mastodon.streaming.Subscription>()
function pause() {
isActive.value = false
}
function resume() {
isActive.value = true
}
function cleanup() {
if (stream.value) {
stream.value.unsubscribe()
stream.value = undefined
}
}
watchEffect(() => {
cleanup()
if (streamingClient.value && isActive.value)
stream.value = cb(streamingClient.value)
})
if (import.meta.client && !process.test)
useNuxtApp().$pageLifecycle.addFrozenListener(cleanup)
tryOnBeforeUnmount(() => isActive.value = false)
if (controls)
return { stream, isActive, pause, resume }
else
return stream
}