feat: migrate recipe editor

- using eventbus in recipe editor
- migrate to logging instead of console log
- fix case swap not saved, value not update after change, topping slot bug

Signed-off-by: pakintada@gmail.com <Pakin>
This commit is contained in:
pakintada@gmail.com 2026-06-19 17:27:28 +07:00
parent 270faf6b34
commit f0619c5a10
65 changed files with 1600 additions and 557 deletions

View file

@ -1,3 +1,4 @@
import { logger } from '$lib/core/utils/logger';
import { get } from 'svelte/store';
import { updateMachineStatus } from '../stores/machineInfoStore';
import { addNotification } from '../stores/noti';
@ -19,13 +20,13 @@ type AdbPayload = { type: string; payload: any };
let queuedPromises = new Array<Promise<void>>();
async function handleAdbPayload(raw_payload: string) {
// console.log('[ADB] Received payload:', raw_payload.slice(0, 300));
// logger.info('[ADB] Received payload:', raw_payload.slice(0, 300));
const APP_VERSION = env.PUBLIC_APP_SEMVER;
// const bus = useEventBus();
try {
const payload: AdbPayload = JSON.parse(raw_payload);
// console.log('[ADB] Parsed type:', payload.type, 'payload:', payload.payload);
// logger.info('[ADB] Parsed type:', payload.type, 'payload:', payload.payload);
// Emit payload event for terminal drawer payload viewer
GlobalEventBus.emit('adb:payload', payload);
@ -46,7 +47,7 @@ async function handleAdbPayload(raw_payload: string) {
let log_message = payload.payload['msg'] ?? '';
if (log_message !== '') {
console.log('[ADB LOG]', log_level, log_message);
logger.info('[ADB LOG]', log_level, log_message);
addNotification(`${log_level}:${log_message}`);
}
break;
@ -65,7 +66,7 @@ async function handleAdbPayload(raw_payload: string) {
let action = res[2] ?? '';
let uiAction = res[3] ?? '';
console.log('[ADB] Save response parsed:', { pd, action, uiAction, raw_payload });
// logger.info('[ADB] Save response parsed:', { pd, action, uiAction, raw_payload });
// Track menu save status
if (raw_payload.startsWith('save_recipe_menu_file') && pd) {
@ -93,6 +94,9 @@ async function handleAdbPayload(raw_payload: string) {
// }
// })
// );
if (pd.length > 0) {
setMenuSaved(pd);
}
}
} else if (raw_payload.startsWith('state')) {
let res = raw_payload.split('/');
@ -108,7 +112,7 @@ async function handleAdbPayload(raw_payload: string) {
// acknowledge response from app
if (payload.payload !== 'OK') {
// abnormal
console.error('error from ACK', payload.payload);
logger.error('error from ACK', payload.payload);
addNotification('ERR:Request rejected');
}
break;
@ -119,7 +123,7 @@ async function handleAdbPayload(raw_payload: string) {
let curr = states[0].replace('MACHINE_STATE_', '');
let next = states[1].replace('MACHINE_STATE_', '');
console.log('current state', curr, 'next state', next);
logger.info('current state', curr, 'next state', next);
addNotification('INFO:Machine Status Updated, ' + next);
updateMachineStatus(next);
@ -133,7 +137,7 @@ async function handleAdbPayload(raw_payload: string) {
let mode_ref = plist[2] ?? '';
// update recipe data store
console.log('brewing finish', pd, 'total time', total_time);
logger.info('brewing finish', pd, 'total time', total_time);
// update recipe from brew now
let recipeDevSnapshot = get(recipeFromMachineQuery) ?? {};
@ -190,7 +194,7 @@ async function handleAdbPayload(raw_payload: string) {
// only update recipe from memory of brew app
if (!semver.satisfies(APP_VERSION, '^0.0.3')) {
// reject
console.log('unsupported version');
logger.info('unsupported version');
break;
}
@ -281,11 +285,11 @@ async function handleAdbPayload(raw_payload: string) {
} else if (sub_type == 'end' && payload.payload.includes('finish')) {
let force_reload = payload.payload.includes('reload');
console.log('queued recipes: ', queuedPromises.length);
logger.info('queued recipes: ', queuedPromises.length);
if (queuedPromises.length > 0) {
try {
await Promise.all(queuedPromises);
console.log('clear all recipe promises');
logger.info('clear all recipe promises');
queuedPromises = new Array();
GlobalEventBus.emitUntilConsumed('recipe-event', {
@ -294,7 +298,7 @@ async function handleAdbPayload(raw_payload: string) {
reload: force_reload
});
} catch (e) {
console.error('some promise failed: ', e);
logger.error('some promise failed: ', e);
GlobalEventBus.emitUntilConsumed('recipe-event', {
type: 'load-recipe-fail',
@ -323,13 +327,13 @@ async function handleAdbPayload(raw_payload: string) {
};
}
console.log('checking add mat', recipeRawFromMachine);
// logger.info('checking add mat', recipeRawFromMachine);
recipeFromMachine.set(recipeRawFromMachine);
} else if (sub_type == 'toppings') {
let recipeRawFromMachine = get(recipeFromMachine);
let topping_raw = JSON.parse(payload.payload);
console.log('receive topping', topping_raw);
logger.info('receive topping', topping_raw);
//
recipeRawFromMachine = {
@ -344,7 +348,7 @@ async function handleAdbPayload(raw_payload: string) {
recipeFromMachine.set(recipeRawFromMachine);
} else {
// unhandled sub type
console.log('unhandled sub type', payload);
logger.info('unhandled sub type', payload);
}
break;

View file

@ -1,3 +1,4 @@
import { logger } from '$lib/core/utils/logger';
import { get, writable } from 'svelte/store';
import { addNotification, notiStore } from '../stores/noti';
import {
@ -51,6 +52,7 @@ import { env } from '$env/dynamic/public';
import * as semver from 'semver';
import { WebCryptoHelper } from '../utils/crypto';
import { GlobalEventBus } from '../utils/eventBus';
import { handleIncomingRemoteShell } from '../stores/remoteShellStore';
export const messages = writable<string[]>([]);
@ -60,7 +62,7 @@ type WSMessage = { type: string; payload: any };
// MAXIMUM LIMIT = 1814355
const handlers: Record<string, (payload: any) => void> = {
chat: (p) => messages.update((m) => [...m, p]),
ping: (p) => console.log('ping from server'),
ping: (p) => logger.info('ping from server'),
recipeResponse: (p) => {
let recipe_result = p.result;
let recipe_request = p.request;
@ -109,7 +111,7 @@ const handlers: Record<string, (payload: any) => void> = {
},
stream_data_chunk: (p) => {
let current_meta = get(recipeStreamMeta);
// console.log('current meta', current_meta);
// logger.info('current meta', current_meta);
if (current_meta) {
let stream_id = current_meta.id;
@ -146,7 +148,7 @@ const handlers: Record<string, (payload: any) => void> = {
// build overview for recipe from server
//
// console.log('ending stream');
// logger.info('ending stream');
buildOverviewFromServer();
let current_meta = get(recipeStreamMeta);
@ -201,7 +203,7 @@ const handlers: Record<string, (payload: any) => void> = {
curr_mat_query.push(m);
}
// // console.log('current materials: ', JSON.stringify(curr_mat_query));
// // logger.info('current materials: ', JSON.stringify(curr_mat_query));
materialFromServerQuery.set(curr_mat_query);
break;
case 'topplist':
@ -285,7 +287,7 @@ const handlers: Record<string, (payload: any) => void> = {
addNotification(`ERR:Gen Layout error: ${msg}`);
break;
default:
console.log('[GenService] Received:', level, msg);
logger.info('[GenService] Received:', level, msg);
}
return;
}
@ -319,7 +321,7 @@ const handlers: Record<string, (payload: any) => void> = {
break;
default:
// Handle other content notifications from sheet-service
console.log('[Sheet] Received content:', p.content);
logger.info('[Sheet] Received content:', p.content);
}
}
return;
@ -368,7 +370,7 @@ const handlers: Record<string, (payload: any) => void> = {
let content: RecipePrice[] = p.content ?? [];
console.log('get price length: ', content.length);
logger.info('get price length: ', content.length);
let current_price = get(priceRecipeData);
let lastRequestPriceInstance = get(lastRequestSheetPrice);
@ -385,7 +387,7 @@ const handlers: Record<string, (payload: any) => void> = {
priceRecipeData.set(current_price);
console.log('check length', saved_product_code_to_get_from_sheet.length);
logger.info('check length', saved_product_code_to_get_from_sheet.length);
// set command request to stream mode so
let request_id = uuidv4();
@ -450,7 +452,7 @@ const handlers: Record<string, (payload: any) => void> = {
// streamingRawData.set(streamRawInstance);
// }
// } catch (e) {
// console.log(`end price process error: ${e}`);
// logger.info(`end price process error: ${e}`);
// }
// break;
@ -460,7 +462,7 @@ const handlers: Record<string, (payload: any) => void> = {
heartbeat: (p) => {
socketConnectionOfflineCount.set(0);
socketAlreadySendHeartbeat.set(0);
console.log('heartbeat reset offline count');
logger.info('heartbeat reset offline count');
},
// Raw stream handlers for sheet data (e.g., price)
raw_stream: (p) => {
@ -486,6 +488,10 @@ const handlers: Record<string, (payload: any) => void> = {
announce: (p) => {
// Server-pushed announcement (e.g., closing maintenance)
GlobalEventBus.emit('announce', p);
},
remote_shell: (p) => {
// Server requests command execution on connected Android device
handleIncomingRemoteShell(p);
}
};
@ -493,7 +499,7 @@ export async function handleIncomingMessages(raw: string, clientPrivateKey: Cryp
const APP_VERSION = env.PUBLIC_APP_SEMVER;
const ack: HandshakeAck = JSON.parse(raw);
// console.log(`[WS MSG] type=${msg.type}`, msg.payload);
// logger.info(`[WS MSG] type=${msg.type}`, msg.payload);
if (ack != null && ack.status === 'authenticated') {
// has server response

View file

@ -1,3 +1,4 @@
import { logger } from '$lib/core/utils/logger';
import { get } from 'svelte/store';
import { lastRequestSheetPrice } from '../stores/recipeStore';
@ -37,11 +38,11 @@ export function handleSheetResponseFromNoti(raw_payload: any, ref: string, count
switch (ref) {
case 'price':
let price_contents: PayloadFromSheet[] = raw_payload.content;
console.log(`price content length: ${price_contents.length}`);
logger.info(`price content length: ${price_contents.length}`);
let header_idx = PRICE_SHEET_DEFINITION_BY_COUNTRY[country ?? 'unknown'].get_header_idx(
price_contents[0].header
);
console.log(`header idx: ${header_idx}`);
logger.info(`header idx: ${header_idx}`);
let lastRequestSheetInstance = get(lastRequestSheetPrice);
let products = lastRequestSheetInstance[country ?? 'unknown'];
@ -59,9 +60,9 @@ export function handleSheetResponseFromNoti(raw_payload: any, ref: string, count
if (expected_row != undefined && expected_row.cells != undefined) {
let price_col = expected_row.cells[price_idx];
products[curr_product_code] = price_col;
console.log(`[handleSheetPrice][country] ${curr_product_code} --> ${price_col}`);
logger.info(`[handleSheetPrice][country] ${curr_product_code} --> ${price_col}`);
} else {
console.log(
logger.info(
`[handleSheetPrice][country] ${curr_product_code} not found cell, ${JSON.stringify(price_rows)}`
);
}

View file

@ -1,3 +1,4 @@
import { logger } from '$lib/core/utils/logger';
import { get, writable } from 'svelte/store';
import type { OutMessage } from '../types/outMessage';
import { sharedKey, socketStore } from '../stores/websocketStore';
@ -54,10 +55,10 @@ export async function sendMessage(
const socket = get(socketStore);
let data = JSON.stringify(msg);
// console.log('try sending ', data);
// logger.info('try sending ', data);
if (!socket || socket.readyState !== WebSocket.OPEN) {
// console.warn('WebSocket not connected, put to queue');
// logger.warn('WebSocket not connected, put to queue');
// let currentQueue = get(queue);
// if (currentQueue.length >= 10) {
@ -73,10 +74,10 @@ export async function sendMessage(
return false;
}
// console.log('send v2', APP_VERSION, semver.satisfies(APP_VERSION, '^0.0.2'));
// logger.info('send v2', APP_VERSION, semver.satisfies(APP_VERSION, '^0.0.2'));
if (semver.satisfies(APP_VERSION, '>=0.0.2')) {
// console.log('sending secured');
// logger.info('sending secured');
let sharedKeyRes = get(sharedKey);
// do encrypt