Sync Mode6Test frontend improvements: pinch zoom 500% max, no flicker/flip, deferred rendering

This commit is contained in:
2026-01-20 19:33:12 +00:00
parent cbb14e69fb
commit 7de75b0596
44 changed files with 168752 additions and 13 deletions
+1
View File
@@ -0,0 +1 @@
Mode6Test
+150
View File
@@ -0,0 +1,150 @@
import { Hono } from 'hono';
import { serveStatic } from 'hono/bun';
import { spawn } from 'bun';
import fs from 'fs';
// Configuration
const MODES_DIR = '/home/admin/Job-Info-Prod';
const MODE_CONFIG_FILE = `${MODES_DIR}/ModeSwitch/activeMode.txt`;
const SHARED_PORT = 3000;
const ORCHESTRATOR_PORT = 3001;
// Mode folder mappings
const MODE_FOLDERS: Record<string, string> = {
'Mode1Test': 'Mode1Test',
'Mode2Test': 'Mode2Test',
'Mode3Test': 'Mode3Test',
'Mode6Test': 'Mode6Test',
};
let currentMode: string = 'Mode1Test';
let currentProcess: any = null;
// Helper: Read active mode from config file
function readActiveMode(): string {
try {
if (fs.existsSync(MODE_CONFIG_FILE)) {
const content = fs.readFileSync(MODE_CONFIG_FILE, 'utf-8').trim();
return content || 'Test1Mode';
}
} catch (err) {
console.error('Failed to read mode config:', err);
}
return 'Mode1Test';
}
// Helper: Write active mode to config file
function writeActiveMode(mode: string): void {
try {
fs.writeFileSync(MODE_CONFIG_FILE, mode, 'utf-8');
} catch (err) {
console.error('Failed to write mode config:', err);
}
}
// Helper: Kill process on shared port
async function killProcessOnPort(port: number): Promise<void> {
try {
await Bun.spawn({
cmd: ['pkill', '-f', `bun.*:${port}`],
stdout: 'ignore',
stderr: 'ignore',
});
// Fallback: Try to kill any Bun process we spawned
if (currentProcess) {
currentProcess.kill();
currentProcess = null;
}
// Give OS time to release the port
await new Promise(resolve => setTimeout(resolve, 500));
} catch (err) {
console.error(`Failed to kill process on port ${port}:`, err);
}
}
// Helper: Start a mode
async function startMode(mode: string): Promise<boolean> {
try {
// Kill any existing process
await killProcessOnPort(SHARED_PORT);
const folderName = MODE_FOLDERS[mode];
if (!folderName) {
console.error(`Unknown mode: ${mode}`);
return false;
}
const modePath = `${MODES_DIR}/${folderName}`;
if (!fs.existsSync(modePath)) {
console.error(`Mode folder not found: ${modePath}`);
return false;
}
console.log(`[ModeSwitch] Starting ${mode} (${folderName}/) on port ${SHARED_PORT}...`);
// Determine server path based on mode
// Mode2Test uses AuthAndToken/backend/server.ts
// Mode1Test and Mode3Test use backend/server.ts
let serverPath = 'backend/server.ts';
if (mode === 'Mode2Test') {
serverPath = 'AuthAndToken/backend/server.ts';
}
// Start the mode's backend server
currentProcess = Bun.spawn({
cmd: [process.execPath, 'run', serverPath],
cwd: modePath,
env: {
// Force mode service to bind to shared port
PORT: String(SHARED_PORT),
},
stdout: 'pipe',
stderr: 'pipe',
});
currentMode = mode;
writeActiveMode(mode);
// Read and log output from the spawned process
if (currentProcess.stdout) {
(async () => {
const reader = currentProcess.stdout.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log(`[${mode}]`, new TextDecoder().decode(value));
}
})();
}
console.log(`${mode} started successfully on port ${SHARED_PORT}`);
return true;
} catch (err) {
console.error(`Failed to start ${mode}:`, err);
return false;
}
}
// Initialize app
const app = new Hono();
// Startup message
console.log(`
================================================================================
[ModeSwitch Orchestrator]
================================================================================
Listening on port: ${ORCHESTRATOR_PORT}
Shared mode port: ${SHARED_PORT}
Config file: ${MODE_CONFIG_FILE}
================================================================================
`);
// Start initial mode
const initialMode = readActiveMode();
await startMode(initialMode);
// Export for Bun
export default {
port: ORCHESTRATOR_PORT,
fetch: app.fetch,
};
+32
View File
@@ -0,0 +1,32 @@
{
"lockfileVersion": 1,
"configVersion": 1,
"workspaces": {
"": {
"name": "mode-switch",
"dependencies": {
"dotenv": "^17.2.3",
"hono": "^4.10.8",
},
"devDependencies": {
"@types/bun": "latest",
"typescript": "^5",
},
},
},
"packages": {
"@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="],
"@types/node": ["@types/node@25.0.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw=="],
"bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="],
"dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
"hono": ["hono@4.11.4", "", {}, "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA=="],
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
}
}
+47
View File
@@ -0,0 +1,47 @@
[2026-01-17 14:30] Mode-Based Architecture Implementation Complete
=== ARCHITECTURE ===
✓ Created three-folder structure:
- Mode1Test/: Original application (standalone project)
- Mode2Test/: Placeholder for alternative configuration
- ModeSwitch/: Orchestrator hub (controls mode switching)
✓ ModeSwitch Orchestrator (Bun + Hono):
- Listens on port 3006 (control/monitoring)
- Manages port 3005 (shared public port)
- Reads activeMode.txt to determine startup mode
- Kills existing process and starts new mode on demand
- Hot-swap: Switch modes via API without manual restart
✓ Mode Folders:
- Each mode is a standalone, complete project
- Has own package.json, backend/, frontend/, logs/
- Runs on shared port 3005 when active
- Can be locked read-only once stable
=== ENDPOINTS ===
Orchestrator (port 3006):
GET /health - Health check
GET /api/mode - Get current mode and available modes
POST /api/mode/switch/:mode - Switch to different mode
App (port 3005):
Available when active mode is running
=== NAMING CONSISTENCY ===
Resolved: oldTest → Mode1Test
Updated:
- Folder renamed
- orchestrator.ts MODE_FOLDERS mapping
- activeMode.txt
- README.md references
- API response lists
=== CURRENT STATUS ===
✓ Mode1Test running on port 3005
✓ Orchestrator running on port 3006
✓ Ready for Mode2Test implementation
✓ Root directory clean (only 3 mode folders + Monica.txt + README.md + .git)
=== NEXT PHASE ===
Ready to begin Mode2Test development
+26
View File
@@ -0,0 +1,26 @@
================================================================================
[ModeSwitch Orchestrator]
================================================================================
Listening on port: 3006
Shared mode port: 3005
Config file: /home/admin/Job-Info-Test/ModeSwitch/activeMode.txt
================================================================================
[ModeSwitch] Starting Mode5Test (Mode5Test/) on port 3005...
✓ Mode5Test started successfully on port 3005
7 | if (typeof entryNamespace?.default?.fetch === 'function') {
8 | const server = Bun.serve(entryNamespace.default);
9 | console.debug(`Started ${server.development ? 'development ' : ''}server: ${server.protocol}://${server.hostname}:${server.port}`);
10 | }
11 | }, reportError);
12 | const server = Bun.serve(entryNamespace.default);
^
error: Failed to start server. Is port 3006 in use?
syscall: "listen",
errno: 0,
code: "EADDRINUSE"
at bun:main:12:28
Bun v1.3.2 (Linux x64 baseline)
+1
View File
@@ -0,0 +1 @@
47889
+19
View File
@@ -0,0 +1,19 @@
{
"name": "mode-switch",
"version": "1.0.0",
"description": "Mode switching orchestrator - controls which mode (Test1Mode, Mode2Test) runs on port 3005",
"type": "module",
"private": true,
"scripts": {
"start": "bun run backend/orchestrator.ts",
"dev": "bun --watch backend/orchestrator.ts"
},
"dependencies": {
"hono": "^4.10.8",
"dotenv": "^17.2.3"
},
"devDependencies": {
"@types/bun": "latest",
"typescript": "^5"
}
}