mirror of
https://github.com/elk-zone/elk.git
synced 2024-12-13 14:49:47 +03:00
wip
This commit is contained in:
parent
3468c13e75
commit
1816530f84
10 changed files with 70 additions and 44 deletions
|
@ -6,7 +6,7 @@ const all = useUsers()
|
|||
const router = useRouter()
|
||||
const masto = useMasto()
|
||||
const switchUser = (user: UserLogin) => {
|
||||
if (user.account.id === currentUser.value?.account.id)
|
||||
if (!user.guest && !currentUser.value?.guest && user.account.id === currentUser.value?.account.id)
|
||||
router.push(getAccountRoute(user.account))
|
||||
else
|
||||
masto.loginTo(user)
|
||||
|
@ -21,7 +21,7 @@ const switchUser = (user: UserLogin) => {
|
|||
flex rounded
|
||||
cursor-pointer
|
||||
aria-label="Switch user"
|
||||
:class="user.account.id === currentUser?.account.id ? '' : 'op25 grayscale'"
|
||||
:class="user.account?.id === currentUser?.account?.id ? '' : 'op25 grayscale'"
|
||||
hover="filter-none op100"
|
||||
@click="switchUser(user)"
|
||||
>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import Fuse from 'fuse.js'
|
||||
import { $fetch } from 'ofetch'
|
||||
import { DEFAULT_SERVER } from '~/constants'
|
||||
|
||||
const masto = useMasto()
|
||||
|
||||
const input = $ref<HTMLInputElement>()
|
||||
let server = $ref<string>('')
|
||||
|
@ -26,7 +27,7 @@ async function oauth() {
|
|||
server = server.split('/')[0]
|
||||
|
||||
try {
|
||||
location.href = await $fetch<string>(`/api/${server || DEFAULT_SERVER}/login`, {
|
||||
location.href = await $fetch<string>(`/api/${server}/login`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
origin: location.origin,
|
||||
|
@ -46,6 +47,10 @@ async function oauth() {
|
|||
}
|
||||
}
|
||||
|
||||
function explore() {
|
||||
masto.loginTo({ server, guest: true })
|
||||
}
|
||||
|
||||
async function handleInput() {
|
||||
if (server.startsWith('https://'))
|
||||
server = server.replace('https://', '')
|
||||
|
@ -180,9 +185,19 @@ onClickOutside($$(input), () => {
|
|||
</i18n-t>
|
||||
</span>
|
||||
</div>
|
||||
<button flex="~ row" gap-x-2 items-center btn-solid mt2 :disabled="!server || busy">
|
||||
<span aria-hidden="true" inline-block :class="busy ? 'i-ri:loader-2-fill animate animate-spin' : 'i-ri:login-circle-line'" class="rtl-flip" />
|
||||
{{ $t('action.sign_in') }}
|
||||
</button>
|
||||
<div flex="~ gap2" mt2 items-center>
|
||||
<button
|
||||
type="button"
|
||||
flex="~ row" gap-x-2 items-center btn-outline text-sm px2 py1 h-fit :disabled="!server || busy"
|
||||
@click="explore"
|
||||
>
|
||||
<span aria-hidden="true" inline-block :class="busy ? 'i-ri:loader-2-fill animate animate-spin' : 'i-ri:user-4-line'" />
|
||||
{{ $t('action.explore_as_a_guest') }}
|
||||
</button>
|
||||
<button flex="~ row" gap-x-2 items-center btn-solid :disabled="!server || busy">
|
||||
<span aria-hidden="true" inline-block :class="busy ? 'i-ri:loader-2-fill animate animate-spin' : 'i-ri:login-circle-line'" class="rtl-flip" />
|
||||
{{ $t('action.sign_in') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
|
|
@ -344,9 +344,9 @@ export const provideGlobalCommands = () => {
|
|||
parent: 'account-switch',
|
||||
scope: 'Switch account',
|
||||
|
||||
visible: () => user.account.id !== currentUser.value?.account.id,
|
||||
visible: () => !user.guest && user.account.id !== currentUser.value?.account?.id,
|
||||
|
||||
name: () => t('command.switch_account', [getFullHandle(user.account)]),
|
||||
name: () => t('command.switch_account', [getFullHandle(user)]),
|
||||
icon: 'i-ri:user-shared-line',
|
||||
|
||||
onActivate() {
|
||||
|
@ -357,8 +357,7 @@ export const provideGlobalCommands = () => {
|
|||
scope: 'Account',
|
||||
|
||||
visible: () => currentUser.value,
|
||||
|
||||
name: () => t('user.sign_out_account', [getFullHandle(currentUser.value!.account)]),
|
||||
name: () => currentUser.value ? t('user.sign_out_account', [getFullHandle(currentUser.value)]) : '',
|
||||
icon: 'i-ri:logout-box-line',
|
||||
|
||||
onActivate() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Ref } from 'vue'
|
||||
import type { Account, Relationship, Status } from 'masto'
|
||||
import { withoutProtocol } from 'ufo'
|
||||
import type { ElkMasto } from '~/types'
|
||||
import type { ElkMasto, UserLogin } from '~/types'
|
||||
|
||||
export const useMasto = () => useNuxtApp().$masto as ElkMasto
|
||||
|
||||
|
@ -33,7 +33,11 @@ export function getServerName(account: Account) {
|
|||
return currentInstance.value?.uri || ''
|
||||
}
|
||||
|
||||
export function getFullHandle(account: Account) {
|
||||
export function getFullHandle(_account: Account | UserLogin) {
|
||||
if ('guest' in _account && _account.guest)
|
||||
return `[anonymous]@${_account.server}`
|
||||
|
||||
const account = 'server' in _account ? _account.account : _account
|
||||
const handle = `@${account.acct}`
|
||||
if (!currentUser.value || account.acct.includes('@'))
|
||||
return handle
|
||||
|
|
|
@ -45,34 +45,37 @@ const instances = useLocalStorage<Record<string, Instance>>(STORAGE_KEY_SERVERS,
|
|||
const currentUserId = useLocalStorage<string>(STORAGE_KEY_CURRENT_USER, mock ? mock.user.account.id : '')
|
||||
|
||||
export const currentUser = computed<UserLogin | undefined>(() => {
|
||||
if (currentUserId.value) {
|
||||
const user = users.value.find(user => user.account?.id === currentUserId.value)
|
||||
if (user)
|
||||
return user
|
||||
}
|
||||
// Fallback to the first account
|
||||
return users.value[0]
|
||||
if (!currentUserId.value)
|
||||
// Fallback to the first account
|
||||
return users.value[0]
|
||||
|
||||
const user = users.value.find(user => user.account?.id === currentUserId.value)
|
||||
if (user)
|
||||
return user
|
||||
})
|
||||
|
||||
const publicInstance = ref<Instance | null>(null)
|
||||
export const currentInstance = computed<null | Instance>(() => currentUser.value ? instances.value[currentUser.value.server] ?? null : publicInstance.value)
|
||||
export const isGuest = computed(
|
||||
() => currentUserId.value.startsWith('[anonymous]@') || !currentUser.value?.account?.acct,
|
||||
)
|
||||
|
||||
export const publicServer = ref(DEFAULT_SERVER)
|
||||
export const currentServer = computed<string>(() => currentUser.value?.server || publicServer.value)
|
||||
export const currentServer = computed<string>(() => currentUser.value?.server || DEFAULT_SERVER)
|
||||
export const currentInstance = computed<null | Instance>(() => {
|
||||
return instances.value[currentServer.value] ?? null
|
||||
})
|
||||
|
||||
export const currentUserHandle = computed(() => currentUser.value?.account.id
|
||||
? `${currentUser.value.account.acct}@${currentInstance.value?.uri || currentServer.value}`
|
||||
: '[anonymous]',
|
||||
export const currentUserHandle = computed(() =>
|
||||
isGuest.value ? '[anonymous]' : currentUser.value!.account!.acct
|
||||
,
|
||||
)
|
||||
|
||||
export const useUsers = () => users
|
||||
|
||||
export const characterLimit = computed(() => currentInstance.value?.configuration.statuses.maxCharacters ?? DEFAULT_POST_CHARS_LIMIT)
|
||||
|
||||
async function loginTo(user?: Omit<UserLogin, 'account'> & { account?: AccountCredentials }) {
|
||||
async function loginTo(user?: UserLogin) {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const server = user?.server || route.params.server as string || publicServer.value
|
||||
const server = user?.server || (route.params.server as string)
|
||||
const masto = await loginMasto({
|
||||
url: `https://${server}`,
|
||||
accessToken: user?.token,
|
||||
|
@ -82,8 +85,11 @@ async function loginTo(user?: Omit<UserLogin, 'account'> & { account?: AccountCr
|
|||
})
|
||||
|
||||
if (!user?.token) {
|
||||
publicServer.value = server
|
||||
publicInstance.value = await masto.instances.fetch()
|
||||
const instance = await masto.instances.fetch()
|
||||
|
||||
currentUserId.value = `[anonymous]@${server}`
|
||||
instances.value[server] = instance
|
||||
users.value.push({ server, guest: true })
|
||||
}
|
||||
|
||||
else {
|
||||
|
@ -107,7 +113,7 @@ async function loginTo(user?: Omit<UserLogin, 'account'> & { account?: AccountCr
|
|||
instances.value[server] = instance
|
||||
|
||||
if (!users.value.some(u => u.server === user.server && u.token === user.token))
|
||||
users.value.push(user as UserLogin)
|
||||
users.value.push(user)
|
||||
}
|
||||
catch {
|
||||
await signout()
|
||||
|
@ -154,7 +160,7 @@ export function getUsersIndexByUserId(userId: string) {
|
|||
export async function removePushNotificationData(user: UserLogin, fromSWPushManager = true) {
|
||||
// clear push subscription
|
||||
user.pushSubscription = undefined
|
||||
const { acct } = user.account
|
||||
const { acct } = user.account!
|
||||
// clear request notification permission
|
||||
delete useLocalStorage<PushNotificationRequest>(STORAGE_KEY_NOTIFICATION, {}).value[acct]
|
||||
// clear push notification policy
|
||||
|
@ -197,7 +203,7 @@ export async function signout() {
|
|||
|
||||
const masto = useMasto()
|
||||
|
||||
const _currentUserId = currentUser.value.account.id
|
||||
const _currentUserId = currentUser.value.account!.id
|
||||
|
||||
const index = users.value.findIndex(u => u.account?.id === _currentUserId)
|
||||
|
||||
|
@ -228,7 +234,7 @@ export async function signout() {
|
|||
const notifications = reactive<Record<string, undefined | [Promise<WsEvents>, number]>>({})
|
||||
|
||||
export const useNotifications = () => {
|
||||
const id = currentUser.value?.account.id
|
||||
const id = currentUser.value?.account!.id
|
||||
const masto = useMasto()
|
||||
|
||||
const clearNotifications = () => {
|
||||
|
@ -286,9 +292,9 @@ export function useUserLocalStorage<T extends object>(key: string, initial: () =
|
|||
const all = storages.get(key) as Ref<Record<string, T>>
|
||||
|
||||
return computed(() => {
|
||||
const id = currentUser.value?.account.id
|
||||
? currentUser.value.account.acct
|
||||
: '[anonymous]'
|
||||
const id = isGuest.value
|
||||
? '[anonymous]'
|
||||
: currentUser.value!.account!.acct
|
||||
all.value[id] = Object.assign(initial(), all.value[id] || {})
|
||||
return all.value[id]
|
||||
})
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
"confirm": "Confirm",
|
||||
"edit": "Edit",
|
||||
"enter_app": "Enter App",
|
||||
"explore_as_a_guest": "Explore as a guest",
|
||||
"favourite": "Favourite",
|
||||
"favourited": "Favourited",
|
||||
"more": "More",
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
"confirm": "Confirm",
|
||||
"edit": "Edit",
|
||||
"enter_app": "Enter App",
|
||||
"explore_as_a_guest": "Explore as a guest",
|
||||
"favourite": "Favorite",
|
||||
"favourite_count": "{0}",
|
||||
"favourited": "Favorited",
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
"confirm": "确认",
|
||||
"edit": "编辑",
|
||||
"enter_app": "进入应用",
|
||||
"explore_as_a_guest": "游客浏览",
|
||||
"favourite": "喜欢",
|
||||
"favourited": "已喜欢",
|
||||
"more": "更多",
|
||||
|
|
|
@ -12,16 +12,15 @@ export interface AppInfo {
|
|||
vapid_key: string
|
||||
}
|
||||
|
||||
export interface UserLogin {
|
||||
export type UserLogin = {
|
||||
server: string
|
||||
token?: string
|
||||
account: AccountCredentials
|
||||
vapidKey?: string
|
||||
pushSubscription?: PushSubscription
|
||||
}
|
||||
} & ({ account: AccountCredentials; guest: false } | { account?: undefined; guest: true })
|
||||
|
||||
export interface ElkMasto extends MastoClient {
|
||||
loginTo (user?: Omit<UserLogin, 'account'> & { account?: AccountCredentials }): Promise<MastoClient>
|
||||
loginTo(user?: UserLogin): Promise<MastoClient>
|
||||
loggedIn: Ref<boolean>
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ export default defineConfig({
|
|||
// buttons
|
||||
'btn-base': 'cursor-pointer disabled:pointer-events-none disabled:bg-$c-bg-btn-disabled disabled:text-$c-text-btn-disabled',
|
||||
'btn-solid': 'btn-base px-4 py-2 rounded text-$c-text-btn bg-$c-primary hover:bg-$c-primary-active',
|
||||
'btn-outline': 'btn-base px-4 py-2 rounded text-$c-primary border border-$c-primary hover:bg-$c-primary hover:text-inverted',
|
||||
'btn-outline': 'btn-base px-4 py-2 rounded text-$c-primary border border-$c-primary hover:bg-$c-primary hover:text-inverted disabled:border-$c-bg-btn-disabled',
|
||||
'btn-text': 'btn-base px-4 py-2 text-$c-primary hover:text-$c-primary-active',
|
||||
'btn-action-icon': 'btn-base hover:bg-active rounded-full h9 w9 flex items-center justify-center disabled:bg-transparent disabled:text-$c-text-secondary',
|
||||
|
||||
|
|
Loading…
Reference in a new issue