Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions frontend/app/view/preview/preview-directory-utils.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// Copyright 2026, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { getSettingsKeyAtom, globalStore } from "@/app/store/global";
import { RpcApi } from "@/app/store/wshclientapi";
import { globalStore } from "@/app/store/jotaiStore";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { fireAndForget, isBlank } from "@/util/util";
import dayjs from "dayjs";
Expand Down Expand Up @@ -95,7 +94,7 @@ export function handleRename(
if (isDir) {
srcuri += "/";
}
await RpcApi.FileMoveCommand(TabRpcClient, {
await model.env.rpc.FileMoveCommand(TabRpcClient, {
srcuri,
desturi: await model.formatRemoteUri(newPath, globalStore.get),
});
Expand All @@ -121,7 +120,7 @@ export function handleFileDelete(
fireAndForget(async () => {
const formattedPath = await model.formatRemoteUri(path, globalStore.get);
try {
await RpcApi.FileDeleteCommand(TabRpcClient, {
await model.env.rpc.FileDeleteCommand(TabRpcClient, {
path: formattedPath,
recursive,
});
Expand Down Expand Up @@ -154,7 +153,7 @@ export function handleFileDelete(
}

export function makeDirectoryDefaultMenuItems(model: PreviewModel): ContextMenuItem[] {
const defaultSort = globalStore.get(getSettingsKeyAtom("preview:defaultsort")) ?? "name";
const defaultSort = globalStore.get(model.env.getSettingsKeyAtom("preview:defaultsort")) ?? "name";
const showHiddenFiles = globalStore.get(model.showHiddenFiles) ?? true;
return [
{
Expand All @@ -165,15 +164,17 @@ export function makeDirectoryDefaultMenuItems(model: PreviewModel): ContextMenuI
type: "checkbox",
checked: defaultSort === "name",
click: () =>
fireAndForget(() => RpcApi.SetConfigCommand(TabRpcClient, { "preview:defaultsort": "name" })),
fireAndForget(() =>
model.env.rpc.SetConfigCommand(TabRpcClient, { "preview:defaultsort": "name" })
),
},
{
label: "Last Modified",
type: "checkbox",
checked: defaultSort === "modtime",
click: () =>
fireAndForget(() =>
RpcApi.SetConfigCommand(TabRpcClient, { "preview:defaultsort": "modtime" })
model.env.rpc.SetConfigCommand(TabRpcClient, { "preview:defaultsort": "modtime" })
),
},
],
Expand All @@ -187,7 +188,9 @@ export function makeDirectoryDefaultMenuItems(model: PreviewModel): ContextMenuI
checked: showHiddenFiles,
click: () => {
globalStore.set(model.showHiddenFiles, true);
fireAndForget(() => RpcApi.SetConfigCommand(TabRpcClient, { "preview:showhiddenfiles": true }));
fireAndForget(() =>
model.env.rpc.SetConfigCommand(TabRpcClient, { "preview:showhiddenfiles": true })
);
},
},
{
Expand All @@ -197,7 +200,7 @@ export function makeDirectoryDefaultMenuItems(model: PreviewModel): ContextMenuI
click: () => {
globalStore.set(model.showHiddenFiles, false);
fireAndForget(() =>
RpcApi.SetConfigCommand(TabRpcClient, { "preview:showhiddenfiles": false })
model.env.rpc.SetConfigCommand(TabRpcClient, { "preview:showhiddenfiles": false })
);
},
},
Expand Down
23 changes: 13 additions & 10 deletions frontend/app/view/preview/preview-directory.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright 2025, Command Line Inc.
// Copyright 2026, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { ContextMenuModel } from "@/app/store/contextmenu";
import { atoms, getApi, getSettingsKeyAtom, globalStore } from "@/app/store/global";
import { RpcApi } from "@/app/store/wshclientapi";
import { useWaveEnv } from "@/app/waveenv/waveenv";
import { globalStore } from "@/app/store/jotaiStore";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { checkKeyPressed, isCharacterKeyEvent } from "@/util/keyutil";
import { PLATFORM, PlatformMacOS } from "@/util/platformutil";
Expand Down Expand Up @@ -44,6 +44,7 @@ import {
overwriteError,
} from "./preview-directory-utils";
import { type PreviewModel } from "./preview-model";
import type { PreviewEnv } from "./previewenv";

const PageJumpSize = 20;

Expand Down Expand Up @@ -110,9 +111,10 @@ function DirectoryTable({
newFile,
newDirectory,
}: DirectoryTableProps) {
const env = useWaveEnv<PreviewEnv>();
const searchActive = useAtomValue(model.directorySearchActive);
const fullConfig = useAtomValue(atoms.fullConfigAtom);
const defaultSort = useAtomValue(getSettingsKeyAtom("preview:defaultsort")) ?? "name";
const fullConfig = useAtomValue(env.atoms.fullConfigAtom);
const defaultSort = useAtomValue(env.getSettingsKeyAtom("preview:defaultsort")) ?? "name";
const setErrorMsg = useSetAtom(model.errorMsgAtom);
const getIconFromMimeType = useCallback(
(mimeType: string): string => {
Expand Down Expand Up @@ -560,6 +562,7 @@ interface DirectoryPreviewProps {
}

function DirectoryPreview({ model }: DirectoryPreviewProps) {
const env = useWaveEnv<PreviewEnv>();
const [searchText, setSearchText] = useState("");
const [focusIndex, setFocusIndex] = useState(0);
const [unfilteredData, setUnfilteredData] = useState<FileInfo[]>([]);
Expand All @@ -586,7 +589,7 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) {
fireAndForget(async () => {
let entries: FileInfo[];
try {
const file = await RpcApi.FileReadCommand(
const file = await env.rpc.FileReadCommand(
TabRpcClient,
{
info: {
Expand Down Expand Up @@ -680,7 +683,7 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) {
PLATFORM == PlatformMacOS &&
!blockData?.meta?.connection
) {
getApi().onQuicklook(selectedPath);
env.electron.onQuicklook(selectedPath);
return true;
}
if (isCharacterKeyEvent(waveEvent)) {
Expand Down Expand Up @@ -714,7 +717,7 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) {
const handleDropCopy = useCallback(
async (data: CommandFileCopyData, isDir: boolean) => {
try {
await RpcApi.FileCopyCommand(TabRpcClient, data, { timeout: data.opts.timeout });
await env.rpc.FileCopyCommand(TabRpcClient, data, { timeout: data.opts.timeout });
} catch (e) {
console.warn("Copy failed:", e);
const copyError = `${e}`;
Expand Down Expand Up @@ -801,7 +804,7 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) {
onSave: (newName: string) => {
console.log(`newFile: ${newName}`);
fireAndForget(async () => {
await RpcApi.FileCreateCommand(
await env.rpc.FileCreateCommand(
TabRpcClient,
{
info: {
Expand All @@ -822,7 +825,7 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) {
onSave: (newName: string) => {
console.log(`newDirectory: ${newName}`);
fireAndForget(async () => {
await RpcApi.FileMkdirCommand(TabRpcClient, {
await env.rpc.FileMkdirCommand(TabRpcClient, {
info: {
path: await model.formatRemoteUri(`${dirPath}/${newName}`, globalStore.get),
},
Expand Down
39 changes: 20 additions & 19 deletions frontend/app/view/preview/preview-model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
import { BlockNodeModel } from "@/app/block/blocktypes";
import { ContextMenuModel } from "@/app/store/contextmenu";
import type { TabModel } from "@/app/store/tab-model";
import { RpcApi } from "@/app/store/wshclientapi";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { getConnStatusAtom, getOverrideConfigAtom, getSettingsKeyAtom, globalStore, refocusNode } from "@/store/global";
import * as services from "@/store/services";
import { getOverrideConfigAtom, globalStore, refocusNode } from "@/store/global";
import * as WOS from "@/store/wos";
import { goHistory, goHistoryBack, goHistoryForward } from "@/util/historyutil";
import { checkKeyPressed } from "@/util/keyutil";
Expand All @@ -21,6 +19,7 @@ import type * as MonacoTypes from "monaco-editor";
import { createRef } from "react";
import { PreviewView } from "./preview";
import { makeDirectoryDefaultMenuItems } from "./preview-directory-utils";
import type { PreviewEnv } from "./previewenv";

// TODO drive this using config
const BOOKMARKS: { label: string; path: string }[] = [
Expand Down Expand Up @@ -168,13 +167,15 @@ export class PreviewModel implements ViewModel {
refreshCallback: () => void;
directoryKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean;
codeEditKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean;
env: PreviewEnv;

constructor({ blockId, nodeModel, tabModel }: ViewModelInitType) {
constructor({ blockId, nodeModel, tabModel, waveEnv }: ViewModelInitType) {
this.viewType = "preview";
this.blockId = blockId;
this.nodeModel = nodeModel;
this.tabModel = tabModel;
let showHiddenFiles = globalStore.get(getSettingsKeyAtom("preview:showhiddenfiles")) ?? true;
this.env = waveEnv;
let showHiddenFiles = globalStore.get(this.env.getSettingsKeyAtom("preview:showhiddenfiles")) ?? true;
this.showHiddenFiles = atom<boolean>(showHiddenFiles);
this.refreshVersion = atom(0);
this.directorySearchActive = atom(false);
Expand All @@ -184,7 +185,7 @@ export class PreviewModel implements ViewModel {
this.openFileError = atom(null) as PrimitiveAtom<string>;
this.openFileModalGiveFocusRef = createRef();
this.manageConnection = atom(true);
this.blockAtom = WOS.getWaveObjectAtom<Block>(`block:${blockId}`);
this.blockAtom = this.env.wos.getWaveObjectAtom<Block>(`block:${blockId}`);
this.markdownShowToc = atom(false);
this.filterOutNowsh = atom(true);
this.monacoRef = createRef();
Expand Down Expand Up @@ -389,7 +390,7 @@ export class PreviewModel implements ViewModel {
this.connection = atom<Promise<string>>(async (get) => {
const connName = get(this.blockAtom)?.meta?.connection;
try {
await RpcApi.ConnEnsureCommand(TabRpcClient, { connname: connName }, { timeout: 60000 });
await this.env.rpc.ConnEnsureCommand(TabRpcClient, { connname: connName }, { timeout: 60000 });
globalStore.set(this.connectionError, "");
} catch (e) {
globalStore.set(this.connectionError, e as string);
Expand All @@ -406,7 +407,7 @@ export class PreviewModel implements ViewModel {
return null;
}
try {
const statFile = await RpcApi.FileInfoCommand(TabRpcClient, {
const statFile = await this.env.rpc.FileInfoCommand(TabRpcClient, {
info: {
path,
},
Expand Down Expand Up @@ -436,7 +437,7 @@ export class PreviewModel implements ViewModel {
return null;
}
try {
const file = await RpcApi.FileReadCommand(TabRpcClient, {
const file = await this.env.rpc.FileReadCommand(TabRpcClient, {
info: {
path,
},
Expand Down Expand Up @@ -482,7 +483,7 @@ export class PreviewModel implements ViewModel {
this.connStatus = atom((get) => {
const blockData = get(this.blockAtom);
const connName = blockData?.meta?.connection;
const connAtom = getConnStatusAtom(connName);
const connAtom = this.env.getConnStatusAtom(connName);
return get(connAtom);
});

Expand Down Expand Up @@ -586,7 +587,7 @@ export class PreviewModel implements ViewModel {
return;
}
const blockOref = WOS.makeORef("block", this.blockId);
await services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);
await this.env.services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);

// Clear the saved file buffers
globalStore.set(this.fileContentSaved, null);
Expand Down Expand Up @@ -622,7 +623,7 @@ export class PreviewModel implements ViewModel {
}
updateMeta.edit = false;
const blockOref = WOS.makeORef("block", this.blockId);
await services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);
await this.env.services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);
}

async goHistoryForward() {
Expand All @@ -634,13 +635,13 @@ export class PreviewModel implements ViewModel {
}
updateMeta.edit = false;
const blockOref = WOS.makeORef("block", this.blockId);
await services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);
await this.env.services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);
}

async setEditMode(edit: boolean) {
const blockMeta = globalStore.get(this.blockAtom)?.meta;
const blockOref = WOS.makeORef("block", this.blockId);
await services.ObjectService.UpdateObjectMeta(blockOref, { ...blockMeta, edit });
await this.env.services.ObjectService.UpdateObjectMeta(blockOref, { ...blockMeta, edit });
}

async handleFileSave() {
Expand All @@ -654,7 +655,7 @@ export class PreviewModel implements ViewModel {
return;
}
try {
await RpcApi.FileWriteCommand(TabRpcClient, {
await this.env.rpc.FileWriteCommand(TabRpcClient, {
info: {
path: await this.formatRemoteUri(filePath, globalStore.get),
},
Expand Down Expand Up @@ -699,7 +700,7 @@ export class PreviewModel implements ViewModel {
}

getSettingsMenuItems(): ContextMenuItem[] {
const defaultFontSize = globalStore.get(getSettingsKeyAtom("editor:fontsize")) ?? 12;
const defaultFontSize = globalStore.get(this.env.getSettingsKeyAtom("editor:fontsize")) ?? 12;
const blockData = globalStore.get(this.blockAtom);
const overrideFontSize = blockData?.meta?.["editor:fontsize"];
const menuItems: ContextMenuItem[] = [];
Expand Down Expand Up @@ -747,7 +748,7 @@ export class PreviewModel implements ViewModel {
type: "checkbox",
checked: overrideFontSize == fontSize,
click: () => {
RpcApi.SetMetaCommand(TabRpcClient, {
this.env.rpc.SetMetaCommand(TabRpcClient, {
oref: WOS.makeORef("block", this.blockId),
meta: { "editor:fontsize": fontSize },
});
Expand All @@ -760,7 +761,7 @@ export class PreviewModel implements ViewModel {
type: "checkbox",
checked: overrideFontSize == null,
click: () => {
RpcApi.SetMetaCommand(TabRpcClient, {
this.env.rpc.SetMetaCommand(TabRpcClient, {
oref: WOS.makeORef("block", this.blockId),
meta: { "editor:fontsize": null },
});
Expand Down Expand Up @@ -789,7 +790,7 @@ export class PreviewModel implements ViewModel {
click: () =>
fireAndForget(async () => {
const blockOref = WOS.makeORef("block", this.blockId);
await services.ObjectService.UpdateObjectMeta(blockOref, {
await this.env.services.ObjectService.UpdateObjectMeta(blockOref, {
"editor:wordwrap": !wordWrap,
});
}),
Expand Down
13 changes: 8 additions & 5 deletions frontend/app/view/preview/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright 2025, Command Line Inc.
// Copyright 2026, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { CenteredDiv } from "@/app/element/quickelems";
import { RpcApi } from "@/app/store/wshclientapi";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { BlockHeaderSuggestionControl } from "@/app/suggestion/suggestion";
import { useWaveEnv } from "@/app/waveenv/waveenv";
import { globalStore } from "@/store/global";
import { isBlank, makeConnRoute } from "@/util/util";
import { useAtom, useAtomValue, useSetAtom } from "jotai";
Expand All @@ -16,6 +16,7 @@ import { ErrorOverlay } from "./preview-error-overlay";
import { MarkdownPreview } from "./preview-markdown";
import type { PreviewModel } from "./preview-model";
import { StreamingPreview } from "./preview-streaming";
import type { PreviewEnv } from "./previewenv";

export type SpecializedViewProps = {
model: PreviewModel;
Expand Down Expand Up @@ -64,6 +65,7 @@ const SpecializedView = memo(({ parentRef, model }: SpecializedViewProps) => {
});

const fetchSuggestions = async (
env: PreviewEnv,
model: PreviewModel,
query: string,
reqContext: SuggestionRequestContext
Expand All @@ -74,7 +76,7 @@ const fetchSuggestions = async (
route = null;
}
if (reqContext?.dispose) {
RpcApi.DisposeSuggestionsCommand(TabRpcClient, reqContext.widgetid, { noresponse: true, route: route });
env.rpc.DisposeSuggestionsCommand(TabRpcClient, reqContext.widgetid, { noresponse: true, route: route });
return null;
}
const fileInfo = await globalStore.get(model.statFile);
Expand All @@ -89,7 +91,7 @@ const fetchSuggestions = async (
reqnum: reqContext.reqnum,
"file:connection": conn,
};
return await RpcApi.FetchSuggestionsCommand(TabRpcClient, sdata, {
return await env.rpc.FetchSuggestionsCommand(TabRpcClient, sdata, {
route: route,
});
};
Expand All @@ -104,6 +106,7 @@ function PreviewView({
contentRef: React.RefObject<HTMLDivElement>;
model: PreviewModel;
}) {
const env = useWaveEnv<PreviewEnv>();
const connStatus = useAtomValue(model.connStatus);
const [errorMsg, setErrorMsg] = useAtom(model.errorMsgAtom);
const connection = useAtomValue(model.connectionImmediate);
Expand Down Expand Up @@ -140,7 +143,7 @@ function PreviewView({
}
};
const fetchSuggestionsFn = async (query, ctx) => {
return await fetchSuggestions(model, query, ctx);
return await fetchSuggestions(env, model, query, ctx);
};

return (
Expand Down
Loading
Loading