fileserver/frontend/src/store.ts

114 lines
3.4 KiB
TypeScript
Raw Normal View History

import {MRPCConnector, type Session, type Response} from './api';
import {get, type Writable, writable} from 'svelte/store';
import {filesize} from 'filesize';
export * as api from './api';
export enum StateE { LOGIN, SIGNUP, RESET_PASSWORD, PROFILE, TFA_SETUP, ADMIN, VIEW }
export interface State {
s: StateE,
view_node: number
}
export interface UploadFile {
id: number,
name: string,
full_name: string,
file: File,
overwrite: boolean
}
export const show_working = writable<boolean>(false);
export const info_banner = writable<string>('');
export const error_banner = writable<string>('');
export const state = writable<State>({s: StateE.LOGIN, view_node: 0});
export const rpc = new MRPCConnector('/mrpc');
export const token = writable<string|null>(localStorage.getItem('token'));
export const session: { s: Writable<Session|null>, update: (token: string|null) => Promise<void> } = {
s: writable(null),
update: async (t: string|null) => {
console.log('S');
if (t == null) {
session.s.set(null);
return;
}
const s = await rpc.Auth_session_info(t)
if (s.e)
token.set(null);
else
session.s.set(s.o);
}
};
token.subscribe((t) => session.update(t));
token.subscribe(v => {
if (v == null)
localStorage.removeItem('token');
else
localStorage.setItem('token', v);
})
export function changeStateFunction(target: StateE, node?: number): () => void {
return () => {
const new_node = node ?? get(state).view_node;
state.set({s: target, view_node: new_node});
}
}
export async function workingWrapper<T>(fn: () => Promise<T>): Promise<T|null> {
let r = null;
error_banner.set('');
show_working.set(true);
try {
r = await fn();
} catch (e) {
error_banner.set(`Error while making request: ${e}`);
}
show_working.set(false);
return r;
}
export async function workingWrapperO(fn: () => Promise<string|null>): Promise<boolean> {
const resp = await workingWrapper(fn);
if (resp)
error_banner.set(resp);
if (resp === 'Unauthorized')
token.set(null);
return resp == null;
}
export async function workingWrapperR<T>(fn: () => Promise<Response<T>>): Promise<T|null> {
const resp = await workingWrapper(fn);
if (!resp)
return null;
if (resp.e === 'Unauthorized')
token.set(null);
else if (resp.e != null)
error_banner.set(resp.e);
return resp.o;
}
export async function download<T extends {id:number, file:boolean}>(token: string, nodes: T[]) {
const form = document.createElement('form');
form.method = 'POST';
form.target = '_blank';
form.innerHTML = `<input type="hidden" name="token" value="${token}">`;
if (nodes.length == 1 && nodes[0].file) {
form.action = '/download';
form.innerHTML += `<input type="hidden" name="node" value="${nodes[0].id}}">`;
} else {
form.action = '/download_multi';
form.innerHTML += `<input type="hidden" name="nodes" value="${nodes.map(n => n.id).join('.')}">`;
const resp = await workingWrapperR<number>(() => rpc.FS_get_nodes_size(token, nodes.map(v => v.id)));
if (!resp)
return;
info_banner.set(`Estimated size: ${filesize(resp, {base: 2, standard: 'jedec'})}`);
}
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}