implement history functions for preview

This commit is contained in:
sawka 2024-08-19 22:07:35 -07:00
parent 9a06b43266
commit e70e08e531
5 changed files with 175 additions and 44 deletions

View File

@ -34,7 +34,6 @@ interface DirectoryTableProps {
search: string;
focusIndex: number;
setFocusIndex: (_: number) => void;
setFileName: (_: string) => void;
setSearch: (_: string) => void;
setSelectedPath: (_: string) => void;
setRefreshVersion: React.Dispatch<React.SetStateAction<number>>;
@ -130,7 +129,6 @@ function DirectoryTable({
search,
focusIndex,
setFocusIndex,
setFileName,
setSearch,
setSelectedPath,
setRefreshVersion,
@ -301,7 +299,6 @@ function DirectoryTable({
table={table}
search={search}
focusIndex={focusIndex}
setFileName={setFileName}
setFocusIndex={setFocusIndex}
setSearch={setSearch}
setSelectedPath={setSelectedPath}
@ -314,7 +311,6 @@ function DirectoryTable({
table={table}
search={search}
focusIndex={focusIndex}
setFileName={setFileName}
setFocusIndex={setFocusIndex}
setSearch={setSearch}
setSelectedPath={setSelectedPath}
@ -332,7 +328,6 @@ interface TableBodyProps {
search: string;
focusIndex: number;
setFocusIndex: (_: number) => void;
setFileName: (_: string) => void;
setSearch: (_: string) => void;
setSelectedPath: (_: string) => void;
setRefreshVersion: React.Dispatch<React.SetStateAction<number>>;
@ -345,7 +340,6 @@ function TableBody({
search,
focusIndex,
setFocusIndex,
setFileName,
setSearch,
setSelectedPath,
setRefreshVersion,
@ -478,7 +472,7 @@ function TableBody({
key={row.id}
onDoubleClick={() => {
const newFileName = row.getValue("path") as string;
setFileName(newFileName);
model.goHistory(newFileName);
setSearch("");
}}
onClick={() => setFocusIndex(idx)}
@ -495,7 +489,7 @@ function TableBody({
))}
</div>
),
[setSearch, setFileName, handleFileContextMenu, setFocusIndex, focusIndex]
[setSearch, handleFileContextMenu, setFocusIndex, focusIndex]
);
const handleScrollbarInitialized = (instance) => {
@ -535,7 +529,7 @@ const MemoizedTableBody = React.memo(
) as typeof TableBody;
interface DirectoryPreviewProps {
fileNameAtom: jotai.WritableAtom<string, [string], void>;
fileNameAtom: jotai.Atom<string>;
model: PreviewModel;
}
@ -544,7 +538,7 @@ function DirectoryPreview({ fileNameAtom, model }: DirectoryPreviewProps) {
const [focusIndex, setFocusIndex] = useState(0);
const [unfilteredData, setUnfilteredData] = useState<FileInfo[]>([]);
const [filteredData, setFilteredData] = useState<FileInfo[]>([]);
const [fileName, setFileName] = jotai.useAtom(fileNameAtom);
const fileName = jotai.useAtomValue(fileNameAtom);
const showHiddenFiles = jotai.useAtomValue(model.showHiddenFiles);
const [selectedPath, setSelectedPath] = useState("");
const [refreshVersion, setRefreshVersion] = jotai.useAtom(model.refreshVersion);
@ -597,7 +591,7 @@ function DirectoryPreview({ fileNameAtom, model }: DirectoryPreviewProps) {
if (filteredData.length == 0) {
return;
}
setFileName(selectedPath);
model.goHistory(selectedPath);
setSearchText("");
return true;
}
@ -645,7 +639,6 @@ function DirectoryPreview({ fileNameAtom, model }: DirectoryPreviewProps) {
data={filteredData}
search={searchText}
focusIndex={focusIndex}
setFileName={setFileName}
setFocusIndex={setFocusIndex}
setSearch={setSearchText}
setSelectedPath={setSelectedPath}

View File

@ -7,6 +7,8 @@ import { createBlock, globalStore, useBlockAtom } from "@/store/global";
import * as services from "@/store/services";
import * as WOS from "@/store/wos";
import { getWebServerEndpoint } from "@/util/endpoints";
import * as historyutil from "@/util/historyutil";
import * as keyutil from "@/util/keyutil";
import * as util from "@/util/util";
import clsx from "clsx";
import * as jotai from "jotai";
@ -43,7 +45,7 @@ export class PreviewModel implements ViewModel {
ceReadOnly: jotai.PrimitiveAtom<boolean>;
isCeView: jotai.PrimitiveAtom<boolean>;
fileName: jotai.WritableAtom<string, [string], void>;
fileName: jotai.Atom<string>;
connection: jotai.Atom<string>;
statFile: jotai.Atom<Promise<FileInfo>>;
fullFile: jotai.Atom<Promise<FullFile>>;
@ -80,20 +82,26 @@ export class PreviewModel implements ViewModel {
icon: "folder-open",
longClick: (e: React.MouseEvent<any>) => {
let menuItems: ContextMenuItem[] = [];
menuItems.push({ label: "Go to Home", click: () => globalStore.set(this.fileName, "~") });
menuItems.push({
label: "Go to Home",
click: () => this.goHistory("~"),
});
menuItems.push({
label: "Go to Desktop",
click: () => globalStore.set(this.fileName, "~/Desktop"),
click: () => this.goHistory("~/Desktop"),
});
menuItems.push({
label: "Go to Downloads",
click: () => globalStore.set(this.fileName, "~/Downloads"),
click: () => this.goHistory("~/Downloads"),
});
menuItems.push({
label: "Go to Documents",
click: () => globalStore.set(this.fileName, "~/Documents"),
click: () => this.goHistory("~/Documents"),
});
menuItems.push({
label: "Go to Root",
click: () => this.goHistory("/"),
});
menuItems.push({ label: "Go to Root", click: () => globalStore.set(this.fileName, "/") });
ContextMenuModel.showContextMenu(menuItems, e);
},
};
@ -164,7 +172,7 @@ export class PreviewModel implements ViewModel {
return {
elemtype: "iconbutton",
icon: "chevron-left",
click: this.handleBack.bind(this),
click: this.goParentDirectory.bind(this),
};
});
this.endIconButtons = jotai.atom((get) => {
@ -188,18 +196,13 @@ export class PreviewModel implements ViewModel {
}
return null;
});
this.fileName = jotai.atom<string, [string], void>(
(get) => {
const file = get(this.blockAtom)?.meta?.file;
if (util.isBlank(file)) {
return "~";
}
return file;
},
(get, set, update) => {
services.ObjectService.UpdateObjectMeta(`block:${blockId}`, { file: update });
this.fileName = jotai.atom<string>((get) => {
const file = get(this.blockAtom)?.meta?.file;
if (util.isBlank(file)) {
return "~";
}
);
return file;
});
this.connection = jotai.atom<string>((get) => {
return get(this.blockAtom)?.meta?.connection;
});
@ -232,20 +235,58 @@ export class PreviewModel implements ViewModel {
});
this.newFileContent = jotai.atom(null) as jotai.PrimitiveAtom<string | null>;
this.handleBack = this.handleBack.bind(this);
this.goParentDirectory = this.goParentDirectory.bind(this);
}
handleBack() {
goHistory(newPath: string) {
const blockMeta = globalStore.get(this.blockAtom)?.meta;
const fileName = globalStore.get(this.fileName);
if (fileName == null) {
return;
}
const splitPath = fileName.split("/");
console.log("splitPath-1", splitPath);
splitPath.pop();
console.log("splitPath-2", splitPath);
const newPath = splitPath.join("/");
globalStore.set(this.fileName, newPath);
const updateMeta = historyutil.goHistory("file", fileName, newPath, blockMeta);
if (updateMeta == null) {
return;
}
const blockOref = WOS.makeORef("block", this.blockId);
services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);
}
goParentDirectory() {
const blockMeta = globalStore.get(this.blockAtom)?.meta;
const fileName = globalStore.get(this.fileName);
if (fileName == null) {
return;
}
const newPath = historyutil.getParentDirectory(fileName);
const updateMeta = historyutil.goHistory("file", fileName, newPath, blockMeta);
if (updateMeta == null) {
return;
}
const blockOref = WOS.makeORef("block", this.blockId);
services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);
}
goHistoryBack() {
const blockMeta = globalStore.get(this.blockAtom)?.meta;
const curPath = globalStore.get(this.fileName);
const updateMeta = historyutil.goHistoryBack("file", curPath, blockMeta, true);
if (updateMeta == null) {
return;
}
const blockOref = WOS.makeORef("block", this.blockId);
services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);
}
goHistoryForward() {
const blockMeta = globalStore.get(this.blockAtom)?.meta;
const curPath = globalStore.get(this.fileName);
const updateMeta = historyutil.goHistoryForward("file", curPath, blockMeta);
if (updateMeta == null) {
return;
}
const blockOref = WOS.makeORef("block", this.blockId);
services.ObjectService.UpdateObjectMeta(blockOref, updateMeta);
}
toggleCodeEditorReadOnly(readOnly: boolean) {
@ -317,6 +358,23 @@ export class PreviewModel implements ViewModel {
}
return false;
}
keyDownHandler(e: WaveKeyboardEvent): boolean {
if (keyutil.checkKeyPressed(e, "Cmd:ArrowLeft")) {
this.goHistoryBack();
return true;
}
if (keyutil.checkKeyPressed(e, "Cmd:ArrowRight")) {
this.goHistoryForward();
return true;
}
if (keyutil.checkKeyPressed(e, "Cmd:ArrowUp")) {
// handle up directory
this.goParentDirectory();
return true;
}
return false;
}
}
function makePreviewModel(blockId: string): PreviewModel {

View File

@ -208,6 +208,8 @@ declare global {
file?: string;
url?: string;
connection?: string;
history?: string[];
"history:forward"?: string[];
icon?: string;
"icon:color"?: string;
frame?: boolean;

View File

@ -0,0 +1,75 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import * as util from "@/util/util";
const MaxHistory = 20;
// this needs to be fixed for windows
function getParentDirectory(path: string): string {
if (util.isBlank(path) == null) {
// this not great, ideally we'd never be passed a null path
return "/";
}
if (path == "/") {
return "/";
}
const splitPath = path.split("/");
splitPath.pop();
if (splitPath.length == 1 && splitPath[0] == "") {
return "/";
}
const newPath = splitPath.join("/");
return newPath;
}
function goHistoryBack(curValKey: "url" | "file", curVal: string, meta: MetaType, backToParent: boolean): MetaType {
const rtnMeta: MetaType = {};
const history = (meta?.history ?? []).slice();
const historyForward = (meta?.["history:forward"] ?? []).slice();
if (history == null || history.length == 0) {
if (backToParent) {
const parentDir = getParentDirectory(curVal);
if (parentDir == curVal) {
return null;
}
historyForward.unshift(curVal);
while (historyForward.length > MaxHistory) {
historyForward.pop();
}
return { [curValKey]: parentDir, "history:forward": historyForward };
} else {
return null;
}
}
const lastVal = history.pop();
historyForward.unshift(curVal);
return { [curValKey]: lastVal, history: history, "history:forward": historyForward };
}
function goHistoryForward(curValKey: "url" | "file", curVal: string, meta: MetaType): MetaType {
const rtnMeta: MetaType = {};
let history = (meta?.history ?? []).slice();
const historyForward = (meta?.["history:forward"] ?? []).slice();
if (historyForward == null || historyForward.length == 0) {
return null;
}
const lastVal = historyForward.shift();
history.push(curVal);
if (history.length > MaxHistory) {
history.shift();
}
return { [curValKey]: lastVal, history: history, "history:forward": historyForward };
}
function goHistory(curValKey: "url" | "file", curVal: string, newVal: string, meta: MetaType): MetaType {
const rtnMeta: MetaType = {};
const history = (meta?.history ?? []).slice();
history.push(curVal);
if (history.length > MaxHistory) {
history.shift();
}
return { [curValKey]: newVal, history: history, "history:forward": [] };
}
export { getParentDirectory, goHistory, goHistoryBack, goHistoryForward };

View File

@ -27,6 +27,7 @@ const (
MetaKey_File = "file"
MetaKey_Url = "url"
MetaKey_Connection = "connection"
MetaKey_History = "history" // stores an array of history items specific to the block
MetaKey_Icon = "icon"
MetaKey_IconColor = "icon:color"
@ -60,12 +61,14 @@ const (
// for typescript typing
type MetaTSType struct {
// shared
View string `json:"view,omitempty"`
Controller string `json:"controller,omitempty"`
Title string `json:"title,omitempty"`
File string `json:"file,omitempty"`
Url string `json:"url,omitempty"`
Connection string `json:"connection,omitempty"`
View string `json:"view,omitempty"`
Controller string `json:"controller,omitempty"`
Title string `json:"title,omitempty"`
File string `json:"file,omitempty"`
Url string `json:"url,omitempty"`
Connection string `json:"connection,omitempty"`
History []string `json:"history,omitempty"`
HistoryForward []string `json:"history:forward,omitempty"`
Icon string `json:"icon,omitempty"`
IconColor string `json:"icon:color,omitempty"`