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
25 changes: 3 additions & 22 deletions biome.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,10 @@
{
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
"organizeImports": {
"enabled": true
},
"formatter": { "enabled": true, "indentStyle": "tab" },
"organizeImports": { "enabled": true },
"linter": {
"enabled": true,
"rules": {
"recommended": false,
"complexity": {
"noStaticOnlyClass": "error",
"noUselessSwitchCase": "error",
"useFlatMap": "error"
},
"style": {
"noNegationElse": "off",
"useForOf": "error",
"useNodejsImportProtocol": "error",
"useNumberNamespace": "error"
},
"suspicious": {
"noDoubleEquals": "error",
"noThenProperty": "error",
"useIsArray": "error"
}
}
"rules": { "recommended": false }
},
"files": {
"include": ["src/**/*", "utils/**/*.js", "www/**/*.js", "www/res/**/*.css"],
Expand Down
189 changes: 121 additions & 68 deletions src/lib/acode.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ajax from "@deadlyjack/ajax";
import Contextmenu from "components/contextmenu";
import inputhints from "components/inputhints";
import Page from "components/page";
Expand All @@ -16,6 +17,7 @@ import prompt from "dialogs/prompt";
import select from "dialogs/select";
import fsOperation from "fileSystem";
import keyboardHandler from "handlers/keyboard";
import purchaseListener from "handlers/purchase";
import windowResize from "handlers/windowResize";
import actionStack from "lib/actionStack";
import commands from "lib/commands";
Expand Down Expand Up @@ -154,9 +156,8 @@ export default class Acode {
exec(key, val) {
if (key in commands) {
return commands[key](val);
} else {
return false;
}
return false;
}

/**
Expand All @@ -166,67 +167,117 @@ export default class Acode {
* @returns {Promise<void>}
*/
installPlugin(pluginId, installerPluginName) {
return new Promise(async (resolve, reject) => {
try {
const confirmation = await confirm(
strings["install"],
`Do you want to install plugin '${pluginId}'${installerPluginName ? ` requested by ${installerPluginName}` : ""}?`,
);

if (!confirmation) {
reject(new Error("User cancelled installation"));
return;
}

const isPluginExists = await fsOperation(
Url.join(PLUGIN_DIR, pluginId),
).exists();
if (isPluginExists) {
reject(new Error("PLugin already installed"));
return;
}

let purchaseToken = null;

const pluginUrl = Url.join(constants.API_BASE, `plugin/${pluginId}`);
const remotePlugin = await fsOperation(pluginUrl)
.readFile("json")
.catch(() => {
reject(new Error("Failed to fetch plugin details"));
return null;
});

if (remotePlugin) {
if (Number.parseFloat(remotePlugin.price) > 0) {
try {
const [product] = await helpers.promisify(iap.getProducts, [
remotePlugin.sku,
]);
if (product) {
async function getPurchase(sku) {
const purchases = await helpers.promisify(iap.getPurchases);
const purchase = purchases.find((p) =>
p.productIds.includes(sku),
);
return purchase;
}
const purchase = await getPurchase(product.productId);
purchaseToken = purchase?.purchaseToken;
}
} catch (error) {
helpers.error(error);
reject(new Error("Failed to validate purchase"));
return;
}
return new Promise((resolve, reject) => {
confirm(
strings.install,
`Do you want to install plugin '${pluginId}'${installerPluginName ? ` requested by ${installerPluginName}` : ""}?`,
)
.then((confirmation) => {
if (!confirmation) {
reject(new Error("User cancelled installation"));
return;
}
}

const { default: installPlugin } = await import("lib/installPlugin");
await installPlugin(pluginId, remotePlugin.name, purchaseToken);
resolve();
} catch (error) {
reject(error);
}
fsOperation(Url.join(PLUGIN_DIR, pluginId))
.exists()
.then((isPluginExists) => {
if (isPluginExists) {
reject(new Error("Plugin already installed"));
return;
}

let purchaseToken;
let product;
const pluginUrl = Url.join(
constants.API_BASE,
`plugin/${pluginId}`,
);
fsOperation(pluginUrl)
.readFile("json")
.catch(() => {
reject(new Error("Failed to fetch plugin details"));
return null;
})
.then((remotePlugin) => {
if (remotePlugin) {
const isPaid = remotePlugin.price > 0;
helpers
.promisify(iap.getProducts, [remotePlugin.sku])
.then((products) => {
[product] = products;
if (product) {
return getPurchase(product.productId);
}
return null;
})
.then((purchase) => {
purchaseToken = purchase?.purchaseToken;

if (isPaid && !purchaseToken) {
if (!product) throw new Error("Product not found");
return helpers.checkAPIStatus().then((apiStatus) => {
if (!apiStatus) {
alert(strings.error, strings.api_error);
return;
}

iap.setPurchaseUpdatedListener(
...purchaseListener(onpurchase, onerror),
);
return helpers.promisify(
iap.purchase,
product.json,
);
});
}
})
.then(() => {
import("lib/installPlugin").then(
({ default: installPlugin }) => {
installPlugin(
pluginId,
remotePlugin.name,
purchaseToken,
).then(() => {
resolve();
});
},
);
});

async function onpurchase(e) {
const purchase = await getPurchase(product.productId);
await ajax.post(
Url.join(constants.API_BASE, "plugin/order"),
{
data: {
id: remotePlugin.id,
token: purchase?.purchaseToken,
package: BuildInfo.packageName,
},
},
);
purchaseToken = purchase?.purchaseToken;
}

async function onerror(error) {
throw error;
}
}
});

async function getPurchase(sku) {
const purchases = await helpers.promisify(iap.getPurchases);
const purchase = purchases.find((p) =>
p.productIds.includes(sku),
);
return purchase;
}
});
})
.catch((error) => {
reject(error);
});
});
}

Expand All @@ -235,6 +286,7 @@ export default class Acode {
if (numFiles) {
return strings["unsaved files close app"];
}
return null;
}

setLoadingMessage(message) {
Expand Down Expand Up @@ -296,11 +348,11 @@ export default class Acode {
(formatter) => formatter.id !== id,
);
const { formatter } = appSettings.value;
Object.keys(formatter).forEach((mode) => {
for (const mode of Object.keys(formatter)) {
if (formatter[mode] === id) {
delete formatter[mode];
}
});
}
appSettings.update(false);
}

Expand All @@ -316,7 +368,8 @@ export default class Acode {
formatterSettings(name);
this.#afterSelectFormatter(name);
return;
} else if (!formatter && !selectIfNull) {
}
if (!formatter && !selectIfNull) {
toast(strings["please select a formatter"]);
}
}
Expand Down Expand Up @@ -355,12 +408,12 @@ export default class Acode {
*/
getFormatterFor(extensions) {
const options = [[null, strings.none]];
this.formatters.forEach(({ id, name, exts }) => {
for (const { id, name, exts } of this.formatters) {
const supports = exts.some((ext) => extensions.includes(ext));
if (supports || exts.includes("*")) {
options.push([id, name]);
}
});
}
return options;
}

Expand Down Expand Up @@ -414,8 +467,8 @@ export default class Acode {
}

async toInternalUrl(url) {
url = await helpers.toInternalUri(url);
return url;
const internalUrl = await helpers.toInternalUri(url);
return internalUrl;
}
/**
* Push a notification
Expand Down
Loading