183 lines
4.4 KiB
TypeScript
183 lines
4.4 KiB
TypeScript
import { get, writable } from 'svelte/store';
|
|
import { addNotification, notiStore } from '../stores/noti';
|
|
import {
|
|
materialFromServerQuery,
|
|
recipeData,
|
|
recipeDataError,
|
|
recipeLoading,
|
|
recipeOverviewData,
|
|
recipeStreamMeta,
|
|
toppingGroupFromServerQuery,
|
|
toppingListFromServerQuery
|
|
} from '../stores/recipeStore';
|
|
import { buildOverviewFromServer } from '$lib/data/recipeService';
|
|
import { auth } from '../client/firebase';
|
|
|
|
export const messages = writable<string[]>([]);
|
|
|
|
type WSMessage = { type: string; payload: any };
|
|
|
|
const handlers: Record<string, (payload: any) => void> = {
|
|
chat: (p) => messages.update((m) => [...m, p]),
|
|
ping: (p) => console.log('ping from server'),
|
|
recipeResponse: (p) => {
|
|
let recipe_result = p.result;
|
|
let recipe_request = p.request;
|
|
|
|
if (recipe_result) {
|
|
addNotification('INFO:Start fetch recipe!');
|
|
}
|
|
},
|
|
stream_data_start: (p) => {
|
|
let stream_id = p.stream_id;
|
|
let total_size = p.total_size;
|
|
let chunk_size = p.chunk_size;
|
|
|
|
if (stream_id) {
|
|
addNotification('INFO:Start streaming data');
|
|
// recipeLoading.set(true);
|
|
recipeStreamMeta.set({
|
|
id: stream_id,
|
|
total_size: total_size,
|
|
chunk_size: chunk_size,
|
|
progress: 0
|
|
});
|
|
recipeData.set([]);
|
|
recipeOverviewData.set([]);
|
|
}
|
|
},
|
|
stream_data_error: (p) => {
|
|
recipeLoading.set(false);
|
|
recipeDataError.set(p);
|
|
|
|
setTimeout(() => {
|
|
addNotification(`ERROR:${p.error}`);
|
|
}, 2000);
|
|
},
|
|
stream_data_chunk: (p) => {
|
|
let current_meta = get(recipeStreamMeta);
|
|
if (current_meta) {
|
|
let stream_id = current_meta.id;
|
|
|
|
let progress_response_id = p.stream_id;
|
|
if (stream_id === progress_response_id) {
|
|
let current_response_end = p.start_idx + current_meta.chunk_size;
|
|
let percent = (current_response_end / current_meta.total_size) * 100;
|
|
if (percent > 100) {
|
|
percent = 100;
|
|
}
|
|
let data = p.data;
|
|
let currentData = get(recipeData);
|
|
for (let rp of data) {
|
|
currentData.push(rp);
|
|
}
|
|
recipeData.set(currentData);
|
|
recipeStreamMeta.set({
|
|
...current_meta,
|
|
progress: percent
|
|
});
|
|
|
|
// build overview
|
|
|
|
if (percent == 100) {
|
|
addNotification(`INFO:Current progress ${percent}%`);
|
|
}
|
|
buildOverviewFromServer();
|
|
}
|
|
}
|
|
},
|
|
stream_data_end: (p) => {
|
|
recipeLoading.set(false);
|
|
|
|
// build overview for recipe from server
|
|
//
|
|
|
|
buildOverviewFromServer();
|
|
},
|
|
stream_data_extra: (p) => {
|
|
// extended data from server, may be extra infos
|
|
//
|
|
// expected last stream_id + count
|
|
let exid = p.exid;
|
|
let extp = p.extp;
|
|
let ex_payload = p.payload;
|
|
|
|
if (extp) {
|
|
// know type
|
|
switch (extp) {
|
|
case 'matset':
|
|
let curr_mat_query = get(materialFromServerQuery) ?? [];
|
|
|
|
if (!curr_mat_query) {
|
|
curr_mat_query = [];
|
|
}
|
|
|
|
// ex_payload has chunks of material setting
|
|
for (let m of ex_payload) {
|
|
let mid = m.id;
|
|
// curr_mat_query[mid] = m;
|
|
|
|
curr_mat_query.push(m);
|
|
}
|
|
|
|
// console.log('current materials: ', JSON.stringify(curr_mat_query));
|
|
materialFromServerQuery.set(curr_mat_query);
|
|
break;
|
|
case 'topplist':
|
|
let curr_topping_list_query = get(toppingListFromServerQuery) ?? [];
|
|
if (!curr_topping_list_query) {
|
|
curr_topping_list_query = [];
|
|
}
|
|
|
|
for (let t of ex_payload) {
|
|
curr_topping_list_query.push(t);
|
|
}
|
|
|
|
toppingListFromServerQuery.set(curr_topping_list_query);
|
|
|
|
break;
|
|
case 'toppgrp':
|
|
let curr_topping_group_query = get(toppingGroupFromServerQuery) ?? [];
|
|
if (!curr_topping_group_query) {
|
|
curr_topping_group_query = [];
|
|
}
|
|
|
|
for (let t of ex_payload) {
|
|
curr_topping_group_query.push(t);
|
|
}
|
|
|
|
toppingGroupFromServerQuery.set(curr_topping_group_query);
|
|
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
stream_patch_update: (p) => {},
|
|
notify: (p) => {
|
|
let noti_level = p.level ?? 'INFO';
|
|
let msg = p.msg ?? `Notify from ${p.from}`;
|
|
let target = p.to;
|
|
|
|
if (target) {
|
|
//
|
|
let currentUsername = auth.currentUser?.displayName;
|
|
if (currentUsername && currentUsername === target) {
|
|
addNotification(`${noti_level}:${msg}`);
|
|
}
|
|
} else {
|
|
// broadcast to all
|
|
addNotification(`${noti_level}:${msg}`);
|
|
}
|
|
}
|
|
};
|
|
|
|
export function handleIncomingMessages(raw: string) {
|
|
const msg: WSMessage = JSON.parse(raw);
|
|
console.log(`${new Date().toLocaleTimeString()}:ws msg`, msg);
|
|
if (msg == null) {
|
|
// error response
|
|
addNotification('ERR:No response from server');
|
|
return;
|
|
}
|
|
handlers[msg.type]?.(msg.payload);
|
|
}
|