Skip to content

Commit e7c5efa

Browse files
authored
fix: installing of plugin and check app update from native (#1229)
1 parent 2358a53 commit e7c5efa

File tree

4 files changed

+278
-214
lines changed

4 files changed

+278
-214
lines changed

biome.json

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,10 @@
11
{
22
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
3-
"organizeImports": {
4-
"enabled": true
5-
},
3+
"formatter": { "enabled": true, "indentStyle": "tab" },
4+
"organizeImports": { "enabled": true },
65
"linter": {
76
"enabled": true,
8-
"rules": {
9-
"recommended": false,
10-
"complexity": {
11-
"noStaticOnlyClass": "error",
12-
"noUselessSwitchCase": "error",
13-
"useFlatMap": "error"
14-
},
15-
"style": {
16-
"noNegationElse": "off",
17-
"useForOf": "error",
18-
"useNodejsImportProtocol": "error",
19-
"useNumberNamespace": "error"
20-
},
21-
"suspicious": {
22-
"noDoubleEquals": "error",
23-
"noThenProperty": "error",
24-
"useIsArray": "error"
25-
}
26-
}
7+
"rules": { "recommended": false }
278
},
289
"files": {
2910
"include": ["src/**/*", "utils/**/*.js", "www/**/*.js", "www/res/**/*.css"],

src/lib/acode.js

Lines changed: 121 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import ajax from "@deadlyjack/ajax";
12
import Contextmenu from "components/contextmenu";
23
import inputhints from "components/inputhints";
34
import Page from "components/page";
@@ -16,6 +17,7 @@ import prompt from "dialogs/prompt";
1617
import select from "dialogs/select";
1718
import fsOperation from "fileSystem";
1819
import keyboardHandler from "handlers/keyboard";
20+
import purchaseListener from "handlers/purchase";
1921
import windowResize from "handlers/windowResize";
2022
import actionStack from "lib/actionStack";
2123
import commands from "lib/commands";
@@ -154,9 +156,8 @@ export default class Acode {
154156
exec(key, val) {
155157
if (key in commands) {
156158
return commands[key](val);
157-
} else {
158-
return false;
159159
}
160+
return false;
160161
}
161162

162163
/**
@@ -166,67 +167,117 @@ export default class Acode {
166167
* @returns {Promise<void>}
167168
*/
168169
installPlugin(pluginId, installerPluginName) {
169-
return new Promise(async (resolve, reject) => {
170-
try {
171-
const confirmation = await confirm(
172-
strings["install"],
173-
`Do you want to install plugin '${pluginId}'${installerPluginName ? ` requested by ${installerPluginName}` : ""}?`,
174-
);
175-
176-
if (!confirmation) {
177-
reject(new Error("User cancelled installation"));
178-
return;
179-
}
180-
181-
const isPluginExists = await fsOperation(
182-
Url.join(PLUGIN_DIR, pluginId),
183-
).exists();
184-
if (isPluginExists) {
185-
reject(new Error("PLugin already installed"));
186-
return;
187-
}
188-
189-
let purchaseToken = null;
190-
191-
const pluginUrl = Url.join(constants.API_BASE, `plugin/${pluginId}`);
192-
const remotePlugin = await fsOperation(pluginUrl)
193-
.readFile("json")
194-
.catch(() => {
195-
reject(new Error("Failed to fetch plugin details"));
196-
return null;
197-
});
198-
199-
if (remotePlugin) {
200-
if (Number.parseFloat(remotePlugin.price) > 0) {
201-
try {
202-
const [product] = await helpers.promisify(iap.getProducts, [
203-
remotePlugin.sku,
204-
]);
205-
if (product) {
206-
async function getPurchase(sku) {
207-
const purchases = await helpers.promisify(iap.getPurchases);
208-
const purchase = purchases.find((p) =>
209-
p.productIds.includes(sku),
210-
);
211-
return purchase;
212-
}
213-
const purchase = await getPurchase(product.productId);
214-
purchaseToken = purchase?.purchaseToken;
215-
}
216-
} catch (error) {
217-
helpers.error(error);
218-
reject(new Error("Failed to validate purchase"));
219-
return;
220-
}
170+
return new Promise((resolve, reject) => {
171+
confirm(
172+
strings.install,
173+
`Do you want to install plugin '${pluginId}'${installerPluginName ? ` requested by ${installerPluginName}` : ""}?`,
174+
)
175+
.then((confirmation) => {
176+
if (!confirmation) {
177+
reject(new Error("User cancelled installation"));
178+
return;
221179
}
222-
}
223180

224-
const { default: installPlugin } = await import("lib/installPlugin");
225-
await installPlugin(pluginId, remotePlugin.name, purchaseToken);
226-
resolve();
227-
} catch (error) {
228-
reject(error);
229-
}
181+
fsOperation(Url.join(PLUGIN_DIR, pluginId))
182+
.exists()
183+
.then((isPluginExists) => {
184+
if (isPluginExists) {
185+
reject(new Error("Plugin already installed"));
186+
return;
187+
}
188+
189+
let purchaseToken;
190+
let product;
191+
const pluginUrl = Url.join(
192+
constants.API_BASE,
193+
`plugin/${pluginId}`,
194+
);
195+
fsOperation(pluginUrl)
196+
.readFile("json")
197+
.catch(() => {
198+
reject(new Error("Failed to fetch plugin details"));
199+
return null;
200+
})
201+
.then((remotePlugin) => {
202+
if (remotePlugin) {
203+
const isPaid = remotePlugin.price > 0;
204+
helpers
205+
.promisify(iap.getProducts, [remotePlugin.sku])
206+
.then((products) => {
207+
[product] = products;
208+
if (product) {
209+
return getPurchase(product.productId);
210+
}
211+
return null;
212+
})
213+
.then((purchase) => {
214+
purchaseToken = purchase?.purchaseToken;
215+
216+
if (isPaid && !purchaseToken) {
217+
if (!product) throw new Error("Product not found");
218+
return helpers.checkAPIStatus().then((apiStatus) => {
219+
if (!apiStatus) {
220+
alert(strings.error, strings.api_error);
221+
return;
222+
}
223+
224+
iap.setPurchaseUpdatedListener(
225+
...purchaseListener(onpurchase, onerror),
226+
);
227+
return helpers.promisify(
228+
iap.purchase,
229+
product.json,
230+
);
231+
});
232+
}
233+
})
234+
.then(() => {
235+
import("lib/installPlugin").then(
236+
({ default: installPlugin }) => {
237+
installPlugin(
238+
pluginId,
239+
remotePlugin.name,
240+
purchaseToken,
241+
).then(() => {
242+
resolve();
243+
});
244+
},
245+
);
246+
});
247+
248+
async function onpurchase(e) {
249+
const purchase = await getPurchase(product.productId);
250+
await ajax.post(
251+
Url.join(constants.API_BASE, "plugin/order"),
252+
{
253+
data: {
254+
id: remotePlugin.id,
255+
token: purchase?.purchaseToken,
256+
package: BuildInfo.packageName,
257+
},
258+
},
259+
);
260+
purchaseToken = purchase?.purchaseToken;
261+
}
262+
263+
async function onerror(error) {
264+
throw error;
265+
}
266+
}
267+
});
268+
269+
async function getPurchase(sku) {
270+
const purchases = await helpers.promisify(iap.getPurchases);
271+
const purchase = purchases.find((p) =>
272+
p.productIds.includes(sku),
273+
);
274+
return purchase;
275+
}
276+
});
277+
})
278+
.catch((error) => {
279+
reject(error);
280+
});
230281
});
231282
}
232283

@@ -235,6 +286,7 @@ export default class Acode {
235286
if (numFiles) {
236287
return strings["unsaved files close app"];
237288
}
289+
return null;
238290
}
239291

240292
setLoadingMessage(message) {
@@ -296,11 +348,11 @@ export default class Acode {
296348
(formatter) => formatter.id !== id,
297349
);
298350
const { formatter } = appSettings.value;
299-
Object.keys(formatter).forEach((mode) => {
351+
for (const mode of Object.keys(formatter)) {
300352
if (formatter[mode] === id) {
301353
delete formatter[mode];
302354
}
303-
});
355+
}
304356
appSettings.update(false);
305357
}
306358

@@ -316,7 +368,8 @@ export default class Acode {
316368
formatterSettings(name);
317369
this.#afterSelectFormatter(name);
318370
return;
319-
} else if (!formatter && !selectIfNull) {
371+
}
372+
if (!formatter && !selectIfNull) {
320373
toast(strings["please select a formatter"]);
321374
}
322375
}
@@ -355,12 +408,12 @@ export default class Acode {
355408
*/
356409
getFormatterFor(extensions) {
357410
const options = [[null, strings.none]];
358-
this.formatters.forEach(({ id, name, exts }) => {
411+
for (const { id, name, exts } of this.formatters) {
359412
const supports = exts.some((ext) => extensions.includes(ext));
360413
if (supports || exts.includes("*")) {
361414
options.push([id, name]);
362415
}
363-
});
416+
}
364417
return options;
365418
}
366419

@@ -414,8 +467,8 @@ export default class Acode {
414467
}
415468

416469
async toInternalUrl(url) {
417-
url = await helpers.toInternalUri(url);
418-
return url;
470+
const internalUrl = await helpers.toInternalUri(url);
471+
return internalUrl;
419472
}
420473
/**
421474
* Push a notification

0 commit comments

Comments
 (0)