farjs-app
Version:
FAR.js - Cross-platform File and Archive Manager app in your terminal
104 lines (94 loc) • 3.66 kB
JavaScript
/**
* @typedef {import("@farjs/blessed").Widgets.Events.IKeyEventArg & {
* data?: any
* }} IKeyEventArg
* @typedef {import("@farjs/filelist/FileListState.mjs").FileListState} FileListState
* @import { FileListItem } from "@farjs/filelist/api/FileListItem.mjs"
* @import PanelStack from "@farjs/filelist/stack/PanelStack.mjs"
* @import PanelStackItem from "@farjs/filelist/stack/PanelStackItem.mjs"
* @import { WithStacksProps } from "@farjs/filelist/stack/WithStacksProps.mjs"
* @import { Dispatch, ReactComponent } from "@farjs/filelist/FileListData.mjs"
* @import { FileListPluginLoader } from "@farjs/filelist/FileListPluginLoader.mjs"
*/
import path from "path";
import Task from "@farjs/ui/task/Task.mjs";
import TaskAction from "@farjs/ui/task/TaskAction.mjs";
import FileListState from "@farjs/filelist/FileListState.mjs";
import FileListStateReducer from "@farjs/filelist/FileListStateReducer.mjs";
import FSPlugin from "../../fs/FSPlugin.mjs";
/**
* @typedef {{
* openCurrItem(dispatch: Dispatch, stack: PanelStack): void;
* openPluginUi(dispatch: Dispatch, key: IKeyEventArg, stacks: WithStacksProps): Promise<ReactComponent | undefined>;
* }} FileListPluginHandler
*/
/**
* @param {readonly FileListPluginLoader[]} plugins
* @returns {FileListPluginHandler}
*/
function FileListPluginHandler(plugins) {
return {
openCurrItem: (dispatch, stack) => {
const stackItem = stack.peek();
const data = stackItem.getData();
if (
data &&
data.actions.api.isLocal &&
FileListState.currentItem(data.state, (_) => !_.isDir)
) {
const { actions, state } = data;
const item = FileListState.currentItem(state);
if (item !== undefined) {
const filePath = path.join(state.currDir.path, item.name);
/** @type {(item: FileListItem) => Promise<void>} */
async function doOpen(item) {
const source = await actions.api.readFile(
state.currDir.path,
item,
0,
);
const buff = new Uint8Array(64 * 1024);
const bytesRead = await source.readNextBytes(buff);
await source.close();
const fileHeader = buff.subarray(0, bytesRead);
/** @type {Promise<PanelStackItem<FileListState> | undefined>} */
const zero = Promise.resolve(undefined);
const pluginRes = plugins.reduce(async (resP, plugin) => {
const res = await resP;
return res === undefined
? plugin.onFileTrigger(filePath, fileHeader, () => stack.pop())
: resP;
}, zero);
const pluginItem = await pluginRes;
if (pluginItem !== undefined) {
stack.push(
FSPlugin.instance.initDispatch(
dispatch,
FileListStateReducer,
stack,
pluginItem,
),
);
}
}
const openP = doOpen(item);
openP.catch(() => {
dispatch(TaskAction(Task("Opening File Plugin", openP)));
});
}
}
},
openPluginUi: (dispatch, key, stacks) => {
const plugin = plugins.find((_) => _.triggerKeys.includes(key.full));
if (!plugin) {
return Promise.resolve(undefined);
}
const pluginRes = plugin.onKeyTrigger(key.full, stacks, key.data);
return pluginRes.catch(() => {
dispatch(TaskAction(Task("Opening Plugin Ui", pluginRes)));
return undefined;
});
},
};
}
export default FileListPluginHandler;