mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
app is working again. new structure for blocks. new useWaveObjectValueWithSuspense hook
This commit is contained in:
@@ -3,8 +3,7 @@
|
||||
|
||||
import * as React from "react";
|
||||
import * as jotai from "jotai";
|
||||
import { atoms, blockDataMap } from "@/store/global";
|
||||
|
||||
import * as WOS from "@/store/wos";
|
||||
import { TerminalView } from "@/app/view/term";
|
||||
import { PreviewView } from "@/app/view/preview";
|
||||
import { PlotView } from "@/app/view/plotview";
|
||||
@@ -33,9 +32,10 @@ const Block = ({ tabId, blockId }: { tabId: string; blockId: string }) => {
|
||||
}, [blockRef.current]);
|
||||
|
||||
let blockElem: JSX.Element = null;
|
||||
const blockAtom = blockDataMap.get(blockId);
|
||||
const blockData = jotai.useAtomValue(blockAtom);
|
||||
if (blockData.view === "term") {
|
||||
const [blockData, blockDataLoading] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
|
||||
if (blockDataLoading) {
|
||||
blockElem = <CenteredDiv>Loading...</CenteredDiv>;
|
||||
} else if (blockData.view === "term") {
|
||||
blockElem = <TerminalView blockId={blockId} />;
|
||||
} else if (blockData.view === "preview") {
|
||||
blockElem = <PreviewView blockId={blockId} />;
|
||||
|
||||
@@ -4,13 +4,9 @@
|
||||
import * as jotai from "jotai";
|
||||
import * as rxjs from "rxjs";
|
||||
import { Events } from "@wailsio/runtime";
|
||||
import { produce } from "immer";
|
||||
import { BlockService } from "@/bindings/blockservice";
|
||||
import * as wstore from "@/gopkg/wstore";
|
||||
import * as WOS from "./wos";
|
||||
|
||||
const globalStore = jotai.createStore();
|
||||
const blockDataMap = new Map<string, jotai.Atom<wstore.Block>>();
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const globalWindowId = urlParams.get("windowid");
|
||||
const globalClientId = urlParams.get("clientid");
|
||||
@@ -19,8 +15,10 @@ const clientIdAtom = jotai.atom(null) as jotai.PrimitiveAtom<string>;
|
||||
globalStore.set(windowIdAtom, globalWindowId);
|
||||
globalStore.set(clientIdAtom, globalClientId);
|
||||
const uiContextAtom = jotai.atom((get) => {
|
||||
const windowData = get(windowDataAtom);
|
||||
const uiContext: UIContext = {
|
||||
windowid: get(atoms.windowId),
|
||||
activetabid: windowData.activetabid,
|
||||
};
|
||||
return uiContext;
|
||||
}) as jotai.Atom<UIContext>;
|
||||
@@ -54,7 +52,6 @@ const atoms = {
|
||||
client: clientAtom,
|
||||
waveWindow: windowDataAtom,
|
||||
workspace: workspaceAtom,
|
||||
blockDataMap: blockDataMap,
|
||||
};
|
||||
|
||||
type SubjectWithRef<T> = rxjs.Subject<T> & { refCount: number; release: () => void };
|
||||
@@ -93,6 +90,8 @@ Events.On("block:ptydata", (event: any) => {
|
||||
subject.next(data);
|
||||
});
|
||||
|
||||
const blockAtomCache = new Map<string, Map<string, jotai.Atom<any>>>();
|
||||
|
||||
function useBlockAtom<T>(blockId: string, name: string, makeFn: () => jotai.Atom<T>): jotai.Atom<T> {
|
||||
let blockCache = blockAtomCache.get(blockId);
|
||||
if (blockCache == null) {
|
||||
@@ -103,8 +102,9 @@ function useBlockAtom<T>(blockId: string, name: string, makeFn: () => jotai.Atom
|
||||
if (atom == null) {
|
||||
atom = makeFn();
|
||||
blockCache.set(name, atom);
|
||||
console.log("New BlockAtom", blockId, name);
|
||||
}
|
||||
return atom as jotai.Atom<T>;
|
||||
}
|
||||
|
||||
export { globalStore, atoms, getBlockSubject, blockDataMap, useBlockAtom, WOS };
|
||||
export { globalStore, atoms, getBlockSubject, useBlockAtom, WOS };
|
||||
|
||||
+34
-10
@@ -94,7 +94,7 @@ function createWaveValueObject<T extends WaveObj>(oref: string, shouldFetch: boo
|
||||
}
|
||||
wov.pendingPromise = null;
|
||||
globalStore.set(wov.dataAtom, { value: val, loading: false });
|
||||
console.log("GetObject resolved", oref, Date.now() - startTs + "ms");
|
||||
console.log("WaveObj resolved", oref, Date.now() - startTs + "ms");
|
||||
});
|
||||
return wov;
|
||||
}
|
||||
@@ -113,6 +113,25 @@ function loadAndPinWaveObject<T>(oref: string): Promise<T> {
|
||||
return wov.pendingPromise;
|
||||
}
|
||||
|
||||
function useWaveObjectValueWithSuspense<T>(oref: string): T {
|
||||
let wov = waveObjectValueCache.get(oref);
|
||||
if (wov == null) {
|
||||
wov = createWaveValueObject(oref, true);
|
||||
waveObjectValueCache.set(oref, wov);
|
||||
}
|
||||
React.useEffect(() => {
|
||||
wov.refCount++;
|
||||
return () => {
|
||||
wov.refCount--;
|
||||
};
|
||||
}, [oref]);
|
||||
const dataValue = jotai.useAtomValue(wov.dataAtom);
|
||||
if (dataValue.loading) {
|
||||
throw wov.pendingPromise;
|
||||
}
|
||||
return dataValue.value;
|
||||
}
|
||||
|
||||
function useWaveObjectValue<T>(oref: string): [T, boolean] {
|
||||
let wov = waveObjectValueCache.get(oref);
|
||||
if (wov == null) {
|
||||
@@ -214,7 +233,6 @@ function wrapObjectServiceCall<T>(fnName: string, ...args: any[]): Promise<T> {
|
||||
);
|
||||
prtn = prtn.then((val) => {
|
||||
if (val.updates) {
|
||||
console.log(val.updates);
|
||||
updateWaveObjects(val.updates);
|
||||
}
|
||||
return val;
|
||||
@@ -222,14 +240,6 @@ function wrapObjectServiceCall<T>(fnName: string, ...args: any[]): Promise<T> {
|
||||
return prtn;
|
||||
}
|
||||
|
||||
function AddTabToWorkspace(tabName: string, activateTab: boolean): Promise<{ tabId: string }> {
|
||||
return wrapObjectServiceCall("AddTabToWorkspace", tabName, activateTab);
|
||||
}
|
||||
|
||||
function SetActiveTab(tabId: string): Promise<void> {
|
||||
return wrapObjectServiceCall("SetActiveTab", tabId);
|
||||
}
|
||||
|
||||
function getStaticObjectValue<T>(oref: string, getFn: jotai.Getter): T {
|
||||
let wov = waveObjectValueCache.get(oref);
|
||||
if (wov == null) {
|
||||
@@ -239,10 +249,23 @@ function getStaticObjectValue<T>(oref: string, getFn: jotai.Getter): T {
|
||||
return atomVal.value;
|
||||
}
|
||||
|
||||
function AddTabToWorkspace(tabName: string, activateTab: boolean): Promise<{ tabId: string }> {
|
||||
return wrapObjectServiceCall("AddTabToWorkspace", tabName, activateTab);
|
||||
}
|
||||
|
||||
function SetActiveTab(tabId: string): Promise<void> {
|
||||
return wrapObjectServiceCall("SetActiveTab", tabId);
|
||||
}
|
||||
|
||||
function CreateBlock(blockDef: BlockDef, rtOpts: RuntimeOpts): Promise<{ blockId: string }> {
|
||||
return wrapObjectServiceCall("CreateBlock", blockDef, rtOpts);
|
||||
}
|
||||
|
||||
export {
|
||||
makeORef,
|
||||
useWaveObject,
|
||||
useWaveObjectValue,
|
||||
useWaveObjectValueWithSuspense,
|
||||
loadAndPinWaveObject,
|
||||
clearWaveObjectCache,
|
||||
updateWaveObject,
|
||||
@@ -251,4 +274,5 @@ export {
|
||||
getStaticObjectValue,
|
||||
AddTabToWorkspace,
|
||||
SetActiveTab,
|
||||
CreateBlock,
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ const TabContent = ({ tabId }: { tabId: string }) => {
|
||||
{tabData.blockids.map((blockId: string) => {
|
||||
return (
|
||||
<div key={blockId} className="block-container">
|
||||
<Block tabId={tabId} blockId={blockId} />
|
||||
<Block key={blockId} tabId={tabId} blockId={blockId} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
|
||||
import * as React from "react";
|
||||
import * as jotai from "jotai";
|
||||
import { atoms, blockDataMap, useBlockAtom } from "@/store/global";
|
||||
import { atoms, useBlockAtom } from "@/store/global";
|
||||
import { Markdown } from "@/element/markdown";
|
||||
import { FileService, FileInfo, FullFile } from "@/bindings/fileservice";
|
||||
import * as util from "@/util/util";
|
||||
import { CenteredDiv } from "../element/quickelems";
|
||||
import { DirectoryTable } from "@/element/directorytable";
|
||||
import * as wstore from "@/gopkg/wstore";
|
||||
import * as WOS from "@/store/wos";
|
||||
|
||||
import "./view.less";
|
||||
import { first } from "rxjs";
|
||||
|
||||
const MaxFileSize = 1024 * 1024 * 10; // 10MB
|
||||
|
||||
@@ -62,10 +63,17 @@ function DirectoryPreview({ contentAtom }: { contentAtom: jotai.Atom<Promise<str
|
||||
}
|
||||
|
||||
function PreviewView({ blockId }: { blockId: string }) {
|
||||
const blockDataAtom: jotai.Atom<wstore.Block> = blockDataMap.get(blockId);
|
||||
const blockData = WOS.useWaveObjectValueWithSuspense<Block>(WOS.makeORef("block", blockId));
|
||||
if (blockData == null) {
|
||||
return (
|
||||
<div className="view-preview">
|
||||
<CenteredDiv>Block Not Found</CenteredDiv>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const fileNameAtom = useBlockAtom(blockId, "preview:filename", () =>
|
||||
jotai.atom<string>((get) => {
|
||||
return get(blockDataAtom)?.meta?.file;
|
||||
return blockData?.meta?.file;
|
||||
})
|
||||
);
|
||||
const statFileAtom = useBlockAtom(blockId, "preview:statfile", () =>
|
||||
|
||||
@@ -5,13 +5,7 @@ import * as React from "react";
|
||||
import * as jotai from "jotai";
|
||||
import { TabContent } from "@/app/tab/tab";
|
||||
import { clsx } from "clsx";
|
||||
import { atoms, blockDataMap } from "@/store/global";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { BlockService } from "@/bindings/blockservice";
|
||||
import { ClientService } from "@/bindings/clientservice";
|
||||
import { Workspace } from "@/gopkg/wstore";
|
||||
import * as wstore from "@/gopkg/wstore";
|
||||
import * as jotaiUtil from "jotai/utils";
|
||||
import { atoms } from "@/store/global";
|
||||
import * as WOS from "@/store/wos";
|
||||
import { CenteredLoadingDiv, CenteredDiv } from "../element/quickelems";
|
||||
|
||||
@@ -36,7 +30,7 @@ function Tab({ tabId }: { tabId: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
function TabBar({ workspace, waveWindow }: { workspace: Workspace; waveWindow: WaveWindow }) {
|
||||
function TabBar({ workspace }: { workspace: Workspace }) {
|
||||
function handleAddTab() {
|
||||
const newTabName = `Tab-${workspace.tabids.length + 1}`;
|
||||
WOS.AddTabToWorkspace(newTabName, true);
|
||||
@@ -58,34 +52,31 @@ function Widgets() {
|
||||
const windowData = jotai.useAtomValue(atoms.waveWindow);
|
||||
const activeTabId = windowData.activetabid;
|
||||
|
||||
async function createBlock(blockDef: wstore.BlockDef) {
|
||||
const rtOpts: wstore.RuntimeOpts = new wstore.RuntimeOpts({ termsize: { rows: 25, cols: 80 } });
|
||||
const rtnBlock: wstore.Block = await BlockService.CreateBlock(blockDef, rtOpts);
|
||||
const newBlockAtom = jotai.atom(rtnBlock);
|
||||
blockDataMap.set(rtnBlock.blockid, newBlockAtom);
|
||||
addBlockIdToTab(activeTabId, rtnBlock.blockid);
|
||||
async function createBlock(blockDef: BlockDef) {
|
||||
const rtOpts: RuntimeOpts = { termsize: { rows: 25, cols: 80 } };
|
||||
await WOS.CreateBlock(blockDef, rtOpts);
|
||||
}
|
||||
|
||||
async function clickTerminal() {
|
||||
const termBlockDef = new wstore.BlockDef({
|
||||
const termBlockDef = {
|
||||
controller: "shell",
|
||||
view: "term",
|
||||
});
|
||||
};
|
||||
createBlock(termBlockDef);
|
||||
}
|
||||
|
||||
async function clickPreview(fileName: string) {
|
||||
const markdownDef = new wstore.BlockDef({
|
||||
const markdownDef = {
|
||||
view: "preview",
|
||||
meta: { file: fileName },
|
||||
});
|
||||
};
|
||||
createBlock(markdownDef);
|
||||
}
|
||||
|
||||
async function clickPlot() {
|
||||
const plotDef = new wstore.BlockDef({
|
||||
const plotDef: BlockDef = {
|
||||
view: "plot",
|
||||
});
|
||||
};
|
||||
createBlock(plotDef);
|
||||
}
|
||||
|
||||
@@ -122,7 +113,7 @@ function WorkspaceElem() {
|
||||
const ws = jotai.useAtomValue(atoms.workspace);
|
||||
return (
|
||||
<div className="workspace">
|
||||
<TabBar workspace={ws} waveWindow={windowData} />
|
||||
<TabBar workspace={ws} />
|
||||
<div className="workspace-tabcontent">
|
||||
<TabContent key={windowData.workspaceid} tabId={activeTabId} />
|
||||
<Widgets />
|
||||
|
||||
Vendored
+2
-1
@@ -4,6 +4,7 @@
|
||||
declare global {
|
||||
type UIContext = {
|
||||
windowid: string;
|
||||
activetabid: string;
|
||||
};
|
||||
|
||||
type ORef = {
|
||||
@@ -33,7 +34,7 @@ declare global {
|
||||
};
|
||||
|
||||
type BlockDef = {
|
||||
controller: string;
|
||||
controller?: string;
|
||||
view?: string;
|
||||
files?: { [key: string]: FileDef };
|
||||
meta?: { [key: string]: any };
|
||||
|
||||
+4
-11
@@ -18,20 +18,12 @@ const urlParams = new URLSearchParams(window.location.search);
|
||||
const windowId = urlParams.get("windowid");
|
||||
const clientId = urlParams.get("clientid");
|
||||
|
||||
wstore.Block.prototype[immerable] = true;
|
||||
wstore.Tab.prototype[immerable] = true;
|
||||
wstore.Client.prototype[immerable] = true;
|
||||
wstore.Window.prototype[immerable] = true;
|
||||
wstore.Workspace.prototype[immerable] = true;
|
||||
wstore.BlockDef.prototype[immerable] = true;
|
||||
wstore.RuntimeOpts.prototype[immerable] = true;
|
||||
wstore.FileDef.prototype[immerable] = true;
|
||||
wstore.Point.prototype[immerable] = true;
|
||||
wstore.WinSize.prototype[immerable] = true;
|
||||
|
||||
loadFonts();
|
||||
|
||||
console.log("Wave Starting");
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
console.log("DOMContentLoaded");
|
||||
// ensures client/window are loaded into the cache before rendering
|
||||
await WOS.loadAndPinWaveObject<Client>(WOS.makeORef("client", clientId));
|
||||
const waveWindow = await WOS.loadAndPinWaveObject<WaveWindow>(WOS.makeORef("window", windowId));
|
||||
@@ -40,6 +32,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
let elem = document.getElementById("main");
|
||||
let root = createRoot(elem);
|
||||
document.fonts.ready.then(() => {
|
||||
console.log("Wave First Render");
|
||||
root.render(reactElem);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user