Files
native/src/lib/capabilities.ts
T

63 lines
2.5 KiB
TypeScript

import { CAPABILITIES } from '../api/types';
import type { JMAPSession } from '../api/types';
import { useAuthStore } from '../stores/auth-store';
import { accountSupportsFiles } from '../api/files';
// When the session is null (cold start, offline restore) we assume features
// are available so they don't flicker off mid-restore. Once the live session
// arrives, the real capability set takes over.
function sessionHasCapability(capability: string): boolean {
const session = useAuthStore.getState().session;
if (!session) return true;
return capability in session.capabilities;
}
export function hasCalendarCapability(): boolean {
return sessionHasCapability(CAPABILITIES.CALENDARS);
}
export function hasContactsCapability(): boolean {
return sessionHasCapability(CAPABILITIES.CONTACTS);
}
// Files is gated on the ACCOUNT capability (or a non-personal account), not
// just the server-wide session capability: an account whose filenode
// permissions were revoked still sees the capability in the session but
// every FileNode call fails (#563).
function sessionSupportsFiles(session: JMAPSession | null): boolean {
if (!session) return true;
const filesAccountId = session.primaryAccounts?.[CAPABILITIES.FILES];
const accountId = filesAccountId ?? useAuthStore.getState().activeAccountId ?? '';
const account = session.accounts?.[accountId]
?? (filesAccountId ? undefined : Object.values(session.accounts ?? {}).find((a) => a.isPersonal));
return accountSupportsFiles(account, session.capabilities);
}
export function hasFilesCapability(): boolean {
return sessionSupportsFiles(useAuthStore.getState().session);
}
export function useHasCalendar(): boolean {
return useAuthStore((s) => (s.session ? CAPABILITIES.CALENDARS in s.session.capabilities : true));
}
export function useHasContacts(): boolean {
return useAuthStore((s) => (s.session ? CAPABILITIES.CONTACTS in s.session.capabilities : true));
}
export function useHasFiles(): boolean {
return useAuthStore((s) => sessionSupportsFiles(s.session));
}
// Settings tabs for Sieve filters and the vacation responder are gated on the
// same session capabilities api/sieve.ts and api/vacation.ts check, so the
// tab is disabled up front instead of opening onto a "not supported" screen.
export function useHasSieve(): boolean {
return useAuthStore((s) => (s.session ? CAPABILITIES.SIEVE in s.session.capabilities : true));
}
export function useHasVacation(): boolean {
return useAuthStore((s) => (s.session ? CAPABILITIES.VACATION in s.session.capabilities : true));
}