mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
checkpoint on integratng wstore. moved to wails data structures, got immer working again, Window object, transitioned to generic DB ops, lots more
This commit is contained in:
@@ -19,6 +19,16 @@ const App = () => {
|
||||
};
|
||||
|
||||
const AppInner = () => {
|
||||
const client = jotai.useAtomValue(atoms.clientAtom);
|
||||
const windowData = jotai.useAtomValue(atoms.windowData);
|
||||
if (client == null || windowData == null) {
|
||||
return (
|
||||
<div className="mainapp">
|
||||
<div>invalid configuration, client or window was not loaded</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mainapp">
|
||||
<div className="titlebar"></div>
|
||||
|
||||
@@ -31,6 +31,7 @@ const Block = ({ tabId, blockId }: { tabId: string; blockId: string }) => {
|
||||
setDims({ width: newWidth, height: newHeight });
|
||||
}
|
||||
}, [blockRef.current]);
|
||||
|
||||
let blockElem: JSX.Element = null;
|
||||
const blockAtom = blockDataMap.get(blockId);
|
||||
const blockData = jotai.useAtomValue(blockAtom);
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
import "./quickelems.less";
|
||||
|
||||
function CenteredLoadingDiv() {
|
||||
return <CenteredDiv>loading...</CenteredDiv>;
|
||||
}
|
||||
|
||||
function CenteredDiv({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="centered-div">
|
||||
@@ -11,4 +15,4 @@ function CenteredDiv({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
export { CenteredDiv as CenteredDiv };
|
||||
export { CenteredDiv, CenteredLoadingDiv };
|
||||
|
||||
@@ -15,14 +15,19 @@ const globalStore = jotai.createStore();
|
||||
|
||||
const tabId1 = uuidv4();
|
||||
|
||||
const tabArr: TabData[] = [{ name: "Tab 1", tabid: tabId1, blockIds: [] }];
|
||||
const tabArr: wstore.Tab[] = [new wstore.Tab({ name: "Tab 1", tabid: tabId1, blockids: [] })];
|
||||
const blockDataMap = new Map<string, jotai.Atom<wstore.Block>>();
|
||||
const blockAtomCache = new Map<string, Map<string, jotai.Atom<any>>>();
|
||||
|
||||
const atoms = {
|
||||
activeTabId: jotai.atom<string>(tabId1),
|
||||
tabsAtom: jotai.atom<TabData[]>(tabArr),
|
||||
tabsAtom: jotai.atom<wstore.Tab[]>(tabArr),
|
||||
blockDataMap: blockDataMap,
|
||||
clientAtom: jotai.atom(null) as jotai.PrimitiveAtom<wstore.Client>,
|
||||
|
||||
// initialized in wave.ts (will not be null inside of application)
|
||||
windowId: jotai.atom<string>(null) as jotai.PrimitiveAtom<string>,
|
||||
windowData: jotai.atom<wstore.Window>(null) as jotai.PrimitiveAtom<wstore.Window>,
|
||||
};
|
||||
|
||||
type SubjectWithRef<T> = rxjs.Subject<T> & { refCount: number; release: () => void };
|
||||
@@ -65,7 +70,7 @@ function addBlockIdToTab(tabId: string, blockId: string) {
|
||||
let tabArr = globalStore.get(atoms.tabsAtom);
|
||||
const newTabArr = produce(tabArr, (draft) => {
|
||||
const tab = draft.find((tab) => tab.tabid == tabId);
|
||||
tab.blockIds.push(blockId);
|
||||
tab.blockids.push(blockId);
|
||||
});
|
||||
globalStore.set(atoms.tabsAtom, newTabArr);
|
||||
}
|
||||
@@ -93,7 +98,7 @@ function removeBlockFromTab(tabId: string, blockId: string) {
|
||||
let tabArr = globalStore.get(atoms.tabsAtom);
|
||||
const newTabArr = produce(tabArr, (draft) => {
|
||||
const tab = draft.find((tab) => tab.tabid == tabId);
|
||||
tab.blockIds = tab.blockIds.filter((id) => id !== blockId);
|
||||
tab.blockids = tab.blockids.filter((id) => id !== blockId);
|
||||
});
|
||||
globalStore.set(atoms.tabsAtom, newTabArr);
|
||||
removeBlock(blockId);
|
||||
|
||||
@@ -16,7 +16,7 @@ const TabContent = ({ tabId }: { tabId: string }) => {
|
||||
}
|
||||
return (
|
||||
<div className="tabcontent">
|
||||
{tabData.blockIds.map((blockId: string) => {
|
||||
{tabData.blockids.map((blockId: string) => {
|
||||
return (
|
||||
<div key={blockId} className="block-container">
|
||||
<Block tabId={tabId} blockId={blockId} />
|
||||
|
||||
@@ -9,6 +9,7 @@ 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 "./view.less";
|
||||
|
||||
@@ -61,7 +62,7 @@ function DirectoryPreview({ contentAtom }: { contentAtom: jotai.Atom<Promise<str
|
||||
}
|
||||
|
||||
function PreviewView({ blockId }: { blockId: string }) {
|
||||
const blockDataAtom: jotai.Atom<BlockData> = blockDataMap.get(blockId);
|
||||
const blockDataAtom: jotai.Atom<wstore.Block> = blockDataMap.get(blockId);
|
||||
const fileNameAtom = useBlockAtom(blockId, "preview:filename", () =>
|
||||
jotai.atom<string>((get) => {
|
||||
return get(blockDataAtom)?.meta?.file;
|
||||
|
||||
@@ -8,11 +8,15 @@ import { clsx } from "clsx";
|
||||
import { atoms, addBlockIdToTab, 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 "./workspace.less";
|
||||
import { CenteredLoadingDiv, CenteredDiv } from "../element/quickelems";
|
||||
|
||||
function Tab({ tab }: { tab: TabData }) {
|
||||
function Tab({ tab }: { tab: wstore.Tab }) {
|
||||
const [activeTab, setActiveTab] = jotai.useAtom(atoms.activeTabId);
|
||||
return (
|
||||
<div className={clsx("tab", { active: activeTab === tab.tabid })} onClick={() => setActiveTab(tab.tabid)}>
|
||||
@@ -25,11 +29,12 @@ function TabBar() {
|
||||
const [tabData, setTabData] = jotai.useAtom(atoms.tabsAtom);
|
||||
const [activeTab, setActiveTab] = jotai.useAtom(atoms.activeTabId);
|
||||
const tabs = jotai.useAtomValue(atoms.tabsAtom);
|
||||
const client = jotai.useAtomValue(atoms.clientAtom);
|
||||
|
||||
function handleAddTab() {
|
||||
const newTabId = uuidv4();
|
||||
const newTabName = "Tab " + (tabData.length + 1);
|
||||
setTabData([...tabData, { name: newTabName, tabid: newTabId, blockIds: [] }]);
|
||||
setTabData([...tabData, { name: newTabName, tabid: newTabId, blockids: [] }]);
|
||||
setActiveTab(newTabId);
|
||||
}
|
||||
|
||||
@@ -48,8 +53,8 @@ function TabBar() {
|
||||
function Widgets() {
|
||||
const activeTabId = jotai.useAtomValue(atoms.activeTabId);
|
||||
|
||||
async function createBlock(blockDef: BlockDef) {
|
||||
const rtOpts = { termsize: { rows: 25, cols: 80 } };
|
||||
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);
|
||||
@@ -57,25 +62,25 @@ function Widgets() {
|
||||
}
|
||||
|
||||
async function clickTerminal() {
|
||||
const termBlockDef = {
|
||||
const termBlockDef = new wstore.BlockDef({
|
||||
controller: "shell",
|
||||
view: "term",
|
||||
};
|
||||
});
|
||||
createBlock(termBlockDef);
|
||||
}
|
||||
|
||||
async function clickPreview(fileName: string) {
|
||||
const markdownDef = {
|
||||
const markdownDef = new wstore.BlockDef({
|
||||
view: "preview",
|
||||
meta: { file: fileName },
|
||||
};
|
||||
});
|
||||
createBlock(markdownDef);
|
||||
}
|
||||
|
||||
async function clickPlot() {
|
||||
const plotDef = {
|
||||
const plotDef = new wstore.BlockDef({
|
||||
view: "plot",
|
||||
};
|
||||
});
|
||||
createBlock(plotDef);
|
||||
}
|
||||
|
||||
@@ -106,17 +111,35 @@ function Widgets() {
|
||||
);
|
||||
}
|
||||
|
||||
function Workspace() {
|
||||
function WorkspaceElem() {
|
||||
const windowData = jotai.useAtomValue(atoms.windowData);
|
||||
const activeTabId = jotai.useAtomValue(atoms.activeTabId);
|
||||
const workspaceId = windowData.workspaceid;
|
||||
const wsAtom = React.useMemo(() => {
|
||||
return jotaiUtil.loadable(
|
||||
jotai.atom(async (get) => {
|
||||
const ws = await ClientService.GetWorkspace(workspaceId);
|
||||
return ws;
|
||||
})
|
||||
);
|
||||
}, [workspaceId]);
|
||||
const wsLoadable = jotai.useAtomValue(wsAtom);
|
||||
if (wsLoadable.state === "loading") {
|
||||
return <CenteredLoadingDiv />;
|
||||
}
|
||||
if (wsLoadable.state === "hasError") {
|
||||
return <CenteredDiv>Error: {wsLoadable.error?.toString()}</CenteredDiv>;
|
||||
}
|
||||
const ws: Workspace = wsLoadable.data;
|
||||
return (
|
||||
<div className="workspace">
|
||||
<TabBar />
|
||||
<div className="workspace-tabcontent">
|
||||
<TabContent key={activeTabId} tabId={activeTabId} />
|
||||
<TabContent key={workspaceId} tabId={activeTabId} />
|
||||
<Widgets />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { Workspace };
|
||||
export { WorkspaceElem as Workspace };
|
||||
|
||||
Vendored
+1
-33
@@ -1,38 +1,6 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
declare global {
|
||||
type MetaDataType = Record<string, any>;
|
||||
|
||||
type TabData = {
|
||||
name: string;
|
||||
tabid: string;
|
||||
blockIds: string[];
|
||||
};
|
||||
|
||||
type BlockData = {
|
||||
blockid: string;
|
||||
blockdef: BlockDef;
|
||||
controller: string;
|
||||
controllerstatus: string;
|
||||
view: string;
|
||||
meta?: MetaDataType;
|
||||
};
|
||||
|
||||
type FileDef = {
|
||||
filetype?: string;
|
||||
path?: string;
|
||||
url?: string;
|
||||
content?: string;
|
||||
meta?: MetaDataType;
|
||||
};
|
||||
|
||||
type BlockDef = {
|
||||
controller?: string;
|
||||
view: string;
|
||||
files?: FileDef[];
|
||||
meta?: MetaDataType;
|
||||
};
|
||||
}
|
||||
declare global {}
|
||||
|
||||
export {};
|
||||
|
||||
+26
-1
@@ -5,10 +5,35 @@ import * as React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { App } from "./app/app";
|
||||
import { loadFonts } from "./util/fontutil";
|
||||
import { ClientService } from "@/bindings/clientservice";
|
||||
import { Client } from "@/gopkg/wstore";
|
||||
import { globalStore, atoms } from "@/store/global";
|
||||
import * as wailsRuntime from "@wailsio/runtime";
|
||||
import * as wstore from "@/gopkg/wstore";
|
||||
import { immerable } from "immer";
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const windowId = urlParams.get("windowid");
|
||||
globalStore.set(atoms.windowId, windowId);
|
||||
|
||||
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();
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
const client = await ClientService.GetClientData();
|
||||
globalStore.set(atoms.clientAtom, client);
|
||||
const window = await ClientService.GetWindow(windowId);
|
||||
globalStore.set(atoms.windowData, window);
|
||||
let reactElem = React.createElement(App, null, null);
|
||||
let elem = document.getElementById("main");
|
||||
let root = createRoot(elem);
|
||||
|
||||
Reference in New Issue
Block a user