Skip to content
Closed
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
14 changes: 14 additions & 0 deletions src/components/terminal/lazyTerminalManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
let terminalManager;
let terminalManagerPromise;

export function getLoadedTerminalManager() {
return terminalManager;
}

export function loadTerminalManager() {
terminalManagerPromise ??= import("./terminalManager").then((module) => {
terminalManager = module.default;
return terminalManager;
});
return terminalManagerPromise;
}
1 change: 1 addition & 0 deletions src/components/terminal/terminalManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import "@xterm/xterm/css/xterm.css";
import "./terminalTouchSelection.css";
import quickTools from "components/quickTools";
import toast from "components/toast";
import alert from "dialogs/alert";
Expand Down
1 change: 0 additions & 1 deletion src/components/terminal/terminalTouchSelection.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import "./terminalTouchSelection.css";
import select from "dialogs/select";

const DEFAULT_MORE_OPTION_ID = "__acode_terminal_select_all__";
Expand Down
3 changes: 2 additions & 1 deletion src/handlers/intent.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import fsOperation from "fileSystem";
import auth from "lib/auth";
import config from "lib/config";
import { loadStartAdModule } from "lib/lazyAds";
import openFile from "lib/openFile";
import { hideAd } from "lib/startAd";
import helpers from "utils/helpers";

const handlers = [];
Expand Down Expand Up @@ -53,6 +53,7 @@ export default async function HandleIntent(intent = {}) {
try {
const user = await auth.getLoggedInUser(true);
if (user.acode_pro) {
const { hideAd } = await loadStartAdModule();
hideAd();
config.HAS_PRO = true;
const settings = document.querySelector(
Expand Down
3 changes: 2 additions & 1 deletion src/handlers/keyboard.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { bannerAd } from "lib/startAd";
import { getLoadedStartAdModule } from "lib/lazyAds";
import {
getSystemConfiguration,
HARDKEYBOARDHIDDEN_NO,
Expand Down Expand Up @@ -212,6 +212,7 @@ function focusBlurEditor(keyboardHidden) {
* @param {boolean} keyboardHidden
*/
function toggleBannerAd(keyboardHidden) {
const { bannerAd } = getLoadedStartAdModule() || {};
const bannerIsActive = !!bannerAd?.active;

if (
Expand Down
67 changes: 53 additions & 14 deletions src/lib/acode.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ import Page from "components/page";
import palette from "components/palette";
import settingsPage from "components/settingsPage";
import SideButton from "components/sideButton";
import { TerminalManager, TerminalThemeManager } from "components/terminal";
import {
getLoadedTerminalManager,
loadTerminalManager,
} from "components/terminal/lazyTerminalManager";
import TerminalThemeManager from "components/terminal/terminalThemeManager";
import toast from "components/toast";
import tutorial from "components/tutorial";
import alert from "dialogs/alert";
Expand Down Expand Up @@ -66,7 +70,6 @@ import openFolder, { addedFolder } from "lib/openFolder";
import projects from "lib/projects";
import selectionMenu from "lib/selectionMenu";
import appSettings from "lib/settings";
import FileBrowser from "pages/fileBrowser";
import formatterSettings from "settings/formatterSettings";
import ThemeBuilder from "theme/builder";
import themes from "theme/list";
Expand All @@ -77,6 +80,34 @@ import KeyboardEvent from "utils/keyboardEvent";
import Url from "utils/Url";
import config from "./config";

let fileBrowserPromise;

function loadFileBrowser() {
fileBrowserPromise ??= import("pages/fileBrowser").then(
(module) => module.default,
);
return fileBrowserPromise;
}

function createLazyFileBrowser() {
const FileBrowser = (...args) =>
loadFileBrowser().then((module) => module(...args));

for (const method of [
"openFile",
"openFileError",
"openFolder",
"openFolderError",
"open",
"openError",
]) {
FileBrowser[method] = (...args) =>
loadFileBrowser().then((module) => module[method](...args));
}

return FileBrowser;
}

class Acode {
#modules = {};
#pluginsInit = {};
Expand Down Expand Up @@ -281,20 +312,26 @@ class Acode {
};

const terminalTouchSelectionMoreOptions = {
add: (option) => TerminalManager.addTouchSelectionMoreOption(option),
remove: (id) => TerminalManager.removeTouchSelectionMoreOption(id),
list: () => TerminalManager.getTouchSelectionMoreOptions(),
add: async (option) =>
(await loadTerminalManager()).addTouchSelectionMoreOption(option),
remove: async (id) =>
(await loadTerminalManager()).removeTouchSelectionMoreOption(id),
list: () =>
getLoadedTerminalManager()?.getTouchSelectionMoreOptions() || [],
};
Comment on lines +319 to 321

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 terminalTouchSelectionMoreOptions.list() silently returns [] before terminal loads

The add and remove methods on this object are async and await the terminal manager, but list is synchronous and returns getLoadedTerminalManager()?.getTouchSelectionMoreOptions() || []. Any plugin that calls list() before the terminal manager has been lazy-loaded (e.g., to read existing options at startup) will receive an empty array instead of the real list. This is an API contract break relative to the previous always-synchronous TerminalManager.getTouchSelectionMoreOptions() call that always had the manager available.


const terminalModule = {
create: (options) => TerminalManager.createTerminal(options),
createLocal: (options) => TerminalManager.createLocalTerminal(options),
createServer: (options) => TerminalManager.createServerTerminal(options),
get: (id) => TerminalManager.getTerminal(id),
getAll: () => TerminalManager.getAllTerminals(),
create: async (options) =>
(await loadTerminalManager()).createTerminal(options),
createLocal: async (options) =>
(await loadTerminalManager()).createLocalTerminal(options),
createServer: async (options) =>
(await loadTerminalManager()).createServerTerminal(options),
get: (id) => getLoadedTerminalManager()?.getTerminal(id) || null,
getAll: () => getLoadedTerminalManager()?.getAllTerminals() || [],
write: (id, data) => this.#secureTerminalWrite(id, data),
clear: (id) => TerminalManager.clearTerminal(id),
close: (id) => TerminalManager.closeTerminal(id),
clear: async (id) => (await loadTerminalManager()).clearTerminal(id),
close: async (id) => (await loadTerminalManager()).closeTerminal(id),
moreOptions: terminalTouchSelectionMoreOptions,
touchSelection: {
moreOptions: terminalTouchSelectionMoreOptions,
Expand Down Expand Up @@ -389,7 +426,7 @@ class Acode {
this.define("multiPrompt", multiPrompt);
this.define("addedfolder", addedFolder);
this.define("contextMenu", Contextmenu);
this.define("fileBrowser", FileBrowser);
this.define("fileBrowser", createLazyFileBrowser());
this.define("fsOperation", fsOperation);
this.define("keyboard", keyboardHandler);
this.define("windowResize", windowResize);
Expand Down Expand Up @@ -508,7 +545,9 @@ class Acode {
}

// If all security checks pass, proceed with writing
return TerminalManager.writeToTerminal(id, data);
return loadTerminalManager().then((TerminalManager) =>
TerminalManager.writeToTerminal(id, data),
);
}

/**
Expand Down
9 changes: 9 additions & 0 deletions src/lib/canSaveFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function canSaveFile(file = editorManager.activeFile) {
return (
file?.type === "editor" &&
typeof file.save === "function" &&
typeof file.saveAs === "function"
);
}

export default canSaveFile;
Loading