feat: Build Manager, Crucible ops deck, branding, and portable Cloudflare tunnel
Add Build Manager with pin-to-dropper, Crucible multi-node terminal with SSH probe/wake, Command Deck chart balance and pretty stats, AetherForge logo and sacred geometry UI, Field Guide refresh, and LAUNCH.bat Cloudflare MSI + token service install flow.
This commit is contained in:
45
server/web/src/context/ForgeContext.tsx
Normal file
45
server/web/src/context/ForgeContext.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import { createContext, useContext, useState, useCallback, ReactNode } from 'react';
|
||||
|
||||
export interface ForgeState {
|
||||
forging: boolean;
|
||||
stage: string;
|
||||
progress: number; // 0–100
|
||||
}
|
||||
|
||||
interface ForgeContextValue extends ForgeState {
|
||||
startForge: () => void;
|
||||
endForge: () => void;
|
||||
setStage: (stage: string, progress: number) => void;
|
||||
}
|
||||
|
||||
const ForgeContext = createContext<ForgeContextValue>({
|
||||
forging: false,
|
||||
stage: '',
|
||||
progress: 0,
|
||||
startForge: () => {},
|
||||
endForge: () => {},
|
||||
setStage: () => {},
|
||||
});
|
||||
|
||||
export function ForgeProvider({ children }: { children: ReactNode }) {
|
||||
const [state, setState] = useState<ForgeState>({ forging: false, stage: '', progress: 0 });
|
||||
|
||||
const startForge = useCallback(() =>
|
||||
setState({ forging: true, stage: 'Initializing forge...', progress: 0 }), []);
|
||||
|
||||
const endForge = useCallback(() =>
|
||||
setState({ forging: false, stage: '', progress: 0 }), []);
|
||||
|
||||
const setStage = useCallback((stage: string, progress: number) =>
|
||||
setState((s) => ({ ...s, stage, progress })), []);
|
||||
|
||||
return (
|
||||
<ForgeContext.Provider value={{ ...state, startForge, endForge, setStage }}>
|
||||
{children}
|
||||
</ForgeContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useForge() {
|
||||
return useContext(ForgeContext);
|
||||
}
|
||||
@@ -114,6 +114,7 @@ export function WebSocketProvider({ children }: { children: React.ReactNode }) {
|
||||
(update.shares_accepted ?? a.shares_good)
|
||||
),
|
||||
status: 'online' as const,
|
||||
...(update.ssh_available !== undefined ? { ssh_available: update.ssh_available } : {}),
|
||||
}
|
||||
: a
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user