diff --git a/.gitignore b/.gitignore index 3ae717f..ff263f9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,11 +5,6 @@ out *.log* packages ./ui -./main +main .idea scripts/*.js -/main/index.js -/main/index.js.map -/main/preload/chromealive.js -/main/preload/desktop.js -/main/preload/menubar.js diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz index 1fdcb29..2517853 100644 Binary files a/.yarn/install-state.gz and b/.yarn/install-state.gz differ diff --git a/electron-builder.js b/electron-builder.js index 95ff5bf..028a85e 100644 --- a/electron-builder.js +++ b/electron-builder.js @@ -38,9 +38,6 @@ module.exports = { }, hardenedRuntime: true, gatekeeperAssess: false, - extendInfo: { - LSUIElement: 1, - }, entitlements: 'build-resources/entitlements.mac.plist', entitlementsInherit: 'build-resources/entitlements.mac.plist', notarize: false, // do this manually diff --git a/package.json b/package.json index 0bbabb0..9763889 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ulixee/desktop", - "version": "2.0.0-alpha.30", + "version": "2.0.0-alpha.31", "description": "This is a builder project that uses the dual package.json approach (./app contains the app package.json).", "private": true, "author": "Ulixee Foundation", @@ -29,24 +29,24 @@ "unpack:asar": "npx @electron/asar extract dist/mac/Ulixee.app/Contents/Resources/app.asar dist/mac/app_unpacked" }, "dependencies": { - "@argonprotocol/localchain": "0.0.14", + "@argonprotocol/localchain": "0.0.20", "@electron-toolkit/preload": "^3.0.0", - "@ulixee/cloud": "2.0.0-alpha.30", - "@ulixee/commons": "2.0.0-alpha.30", - "@ulixee/datastore": "2.0.0-alpha.30", - "@ulixee/datastore-core": "2.0.0-alpha.30", - "@ulixee/datastore-plugins-hero": "2.0.0-alpha.30", - "@ulixee/default-browser-emulator": "2.0.0-alpha.30", - "@ulixee/desktop-core": "2.0.0-alpha.30", - "@ulixee/desktop-interfaces": "2.0.0-alpha.30", - "@ulixee/hero-core": "2.0.0-alpha.30", - "@ulixee/hero-interfaces": "2.0.0-alpha.30", - "@ulixee/js-path": "2.0.0-alpha.30", - "@ulixee/net": "2.0.0-alpha.30", - "@ulixee/platform-specification": "2.0.0-alpha.30", - "@ulixee/platform-utils": "2.0.0-alpha.30", - "@ulixee/unblocked-agent-mitm-socket": "^2.0.0-alpha.30", - "@ulixee/unblocked-specification": "2.0.0-alpha.30", + "@ulixee/cloud": "2.0.0-alpha.31", + "@ulixee/commons": "2.0.0-alpha.31", + "@ulixee/datastore": "2.0.0-alpha.31", + "@ulixee/datastore-core": "2.0.0-alpha.31", + "@ulixee/datastore-plugins-hero": "2.0.0-alpha.31", + "@ulixee/default-browser-emulator": "2.0.0-alpha.31", + "@ulixee/desktop-core": "2.0.0-alpha.31", + "@ulixee/desktop-interfaces": "2.0.0-alpha.31", + "@ulixee/hero-core": "2.0.0-alpha.31", + "@ulixee/hero-interfaces": "2.0.0-alpha.31", + "@ulixee/js-path": "2.0.0-alpha.31", + "@ulixee/net": "2.0.0-alpha.31", + "@ulixee/platform-specification": "2.0.0-alpha.31", + "@ulixee/platform-utils": "2.0.0-alpha.31", + "@ulixee/unblocked-agent-mitm-socket": "^2.0.0-alpha.31", + "@ulixee/unblocked-specification": "2.0.0-alpha.31", "better-sqlite3": "^11.1.2", "electron-log": "^5.1.7", "electron-updater": "^6.3.4", @@ -98,7 +98,7 @@ "tailwindcss": "^3.4.1", "ts-node": "^10.9.2", "tslib": "^2.7.0", - "typescript": "^5.6.2", + "typescript": "~5.6.2", "vite": "^5.3.1", "vite-plugin-checker": "^0.8.0", "vite-plugin-multiple": "^0.2.0", diff --git a/src/main/lib/AccountManager.ts b/src/main/lib/AccountManager.ts index 4a633ee..9f77ed9 100644 --- a/src/main/lib/AccountManager.ts +++ b/src/main/lib/AccountManager.ts @@ -234,7 +234,7 @@ export default class AccountManager extends TypedEventEmitter<{ balance += account.balance; } - const formattedBalance = ArgonUtils.format(balance, 'milligons', 'argons'); + const formattedBalance = ArgonUtils.format(balance, 'microgons', 'argons'); return { credits: [], @@ -275,7 +275,7 @@ export default class AccountManager extends TypedEventEmitter<{ } public async createArgonsToSendFile(request: { - milligons: bigint; + microgons: bigint; fromAddress?: string; toAddress?: string; }): Promise { @@ -283,7 +283,7 @@ export default class AccountManager extends TypedEventEmitter<{ (await this.getLocalchain(request.fromAddress)) ?? this.getDefaultLocalchain(); const file = await localchain.transactions.send( - request.milligons, + request.microgons, request.toAddress ? [request.toAddress] : null, ); const argonFile = JSON.parse(file); @@ -292,17 +292,17 @@ export default class AccountManager extends TypedEventEmitter<{ return { rawJson: file, file: ArgonFileSchema.parse(argonFile), - name: `${ArgonUtils.format(request.milligons, 'milligons', 'argons')} ${recipient}.${ARGON_FILE_EXTENSION}`, + name: `${ArgonUtils.format(request.microgons, 'microgons', 'argons')} ${recipient}.${ARGON_FILE_EXTENSION}`, }; } public async createArgonsToRequestFile(request: { - milligons: bigint; + microgons: bigint; sendToMyAddress?: string; }): Promise { const localchain = (await this.getLocalchain(request.sendToMyAddress)) ?? this.getDefaultLocalchain(); - const file = await localchain.transactions.request(request.milligons); + const file = await localchain.transactions.request(request.microgons); const argonFile = JSON.parse(file); return { @@ -324,7 +324,7 @@ export default class AccountManager extends TypedEventEmitter<{ const funding = argonFile.request.reduce((sum, x) => { if (x.accountType === 'deposit') { for (const note of x.notes) { - if (note.noteType.action === 'claim') sum += note.milligons; + if (note.noteType.action === 'claim') sum += note.microgons; } } return sum; diff --git a/src/main/lib/ApiClient.ts b/src/main/lib/ApiClient.ts index be3b6a5..b559fba 100644 --- a/src/main/lib/ApiClient.ts +++ b/src/main/lib/ApiClient.ts @@ -39,7 +39,7 @@ export default class ApiClient< } public async connect(): Promise { - await this.connection.connect(false, 15e3); + await this.connection.connect({ timeoutMs: 15e3, isAutoConnect: false }); this.isConnected = true; } diff --git a/src/main/lib/ApiManager.ts b/src/main/lib/ApiManager.ts index 3c72d28..98e7724 100644 --- a/src/main/lib/ApiManager.ts +++ b/src/main/lib/ApiManager.ts @@ -168,8 +168,7 @@ export default class ApiManager< if (!this.paymentService) throw new Error("Payment service isn't initialized"); const localchainWallet = await this.accountManager.getWallet(); const credits = await this.paymentService.credits(); - const creditBalance = credits.reduce((sum, x) => sum + x.remaining, 0); - const creditMilligons = ArgonUtils.microgonsToMilligons(creditBalance); + const creditBalance = credits.reduce((sum, x) => sum + x.remaining, 0n); const localchainBalance = localchainWallet.accounts.reduce( (sum, x) => sum + x.balance + x.mainchainBalance, @@ -179,8 +178,8 @@ export default class ApiManager< const brokerBalance = localchainWallet.brokerAccounts.reduce((sum, x) => sum + x.balance, 0n); const formattedBalance = ArgonUtils.format( - localchainBalance + creditMilligons + brokerBalance, - 'milligons', + localchainBalance + creditBalance + brokerBalance, + 'microgons', 'argons', ); @@ -254,6 +253,10 @@ export default class ApiManager< } } + public async getCloudConnectionIdByAddress(address: string): Promise { + return (await this.apiByCloudAddress.get(address)?.resolvable)?.id; + } + public async connectToCloud(cloud: ICloudSetup): Promise { const { adminIdentity, oldAddress, type } = cloud; let { address, name } = cloud; diff --git a/src/main/lib/ChromeAliveWindow.ts b/src/main/lib/ChromeAliveWindow.ts index ccb43c8..b264c1f 100644 --- a/src/main/lib/ChromeAliveWindow.ts +++ b/src/main/lib/ChromeAliveWindow.ts @@ -5,16 +5,14 @@ import { IChromeAliveSessionApis } from '@ulixee/desktop-interfaces/apis'; import IChromeAliveSessionEvents from '@ulixee/desktop-interfaces/events/IChromeAliveSessionEvents'; import ISessionAppModeEvent from '@ulixee/desktop-interfaces/events/ISessionAppModeEvent'; import HeroCore from '@ulixee/hero-core'; -import { data } from 'autoprefixer'; import { app, BrowserWindow, MenuItem, screen, shell } from 'electron'; -import { nanoid } from 'nanoid'; import * as Path from 'path'; import moment from 'moment'; import generateContextMenu from '../menus/generateContextMenu'; import ApiClient from './ApiClient'; import View from './View'; +import loadUrl from './util/loadUrl'; import BrowserView = Electron.BrowserView; -import loadUrl, { getUrl } from './util/loadUrl'; // make electron packaging friendly const extensionPath = Path.resolve(__dirname, '../ui').replace('app.asar', 'app.asar.unpacked'); @@ -58,7 +56,8 @@ export default class ChromeAliveWindow { heroSessionId: string; dbPath: string; }, - cloudAddress: string, + public cloudAddress: string, + public apiConnectionId: string, ) { bindFunctions(this); this.createApi(cloudAddress); @@ -271,10 +270,9 @@ export default class ChromeAliveWindow { return; } - await devtoolsWc.executeJavaScript( + void devtoolsWc.executeJavaScript( `(async () => { - while (typeof UI === 'undefined') { - console.log('waiting') + while (typeof UI?.panels?.elements?.parentWidgetInternal === 'undefined') { await new Promise(resolve => setTimeout(resolve, 100)); } @@ -293,6 +291,8 @@ export default class ChromeAliveWindow { } })()`, ); + // give the devtools a chance to load + await new Promise(setImmediate); const target = await View.getTargetInfo(devtoolsWc); await this.api?.send('Session.devtoolsTargetOpened', target); }); @@ -335,6 +335,7 @@ export default class ChromeAliveWindow { if (!this.session.dbPath.includes(HeroCore.dataDir)) { address.searchParams.set('path', this.session.dbPath); } + address.searchParams.set('id', this.apiConnectionId); this.api = new ApiClient(address.href, this.onChromeAliveEvent); // eslint-disable-next-line no-console console.log('Window connected to %s', this.api.address); diff --git a/src/main/lib/DesktopWindow.ts b/src/main/lib/DesktopWindow.ts index aee5476..effd443 100644 --- a/src/main/lib/DesktopWindow.ts +++ b/src/main/lib/DesktopWindow.ts @@ -30,7 +30,7 @@ export default class DesktopWindow extends TypedEventEmitter<{ constructor(private apiManager: ApiManager) { super(); - void this.open(false); + void this.open(true); } public focus(): void { diff --git a/src/main/lib/Menubar.ts b/src/main/lib/Menubar.ts index 00c36ab..0b76641 100644 --- a/src/main/lib/Menubar.ts +++ b/src/main/lib/Menubar.ts @@ -39,11 +39,14 @@ export class Menubar extends EventEmitter { } // hide the dock icon if it shows - if (process.platform === 'darwin') { - app.setActivationPolicy('accessory'); - } app.on('second-instance', this.onSecondInstance.bind(this)); app.on('open-file', this.onFileOpened.bind(this)); + app.on('window-all-closed', () => { + console.log('window-all-closed'); + if (process.platform !== 'darwin') { // On macOS, apps generally stay open until explicitly quit + app.quit(); + } + }); app.setAppLogsPath(); (process.env as any).ELECTRON_DISABLE_SECURITY_WARNINGS = true; void this.appReady(); @@ -55,6 +58,11 @@ export class Menubar extends EventEmitter { return this.#tray; } + public async appExit(): Promise { + await this.beforeQuit(); + app.exit(); + } + private bindSignals(): void { let didRun = false; const exit = (): Promise => { @@ -141,11 +149,6 @@ export class Menubar extends EventEmitter { } } - private async appExit(): Promise { - await this.beforeQuit(); - app.exit(); - } - private async appReady(): Promise { try { await app.whenReady(); diff --git a/src/main/lib/PrivateDesktopApiHandler.ts b/src/main/lib/PrivateDesktopApiHandler.ts index 3881cfb..2a7029b 100644 --- a/src/main/lib/PrivateDesktopApiHandler.ts +++ b/src/main/lib/PrivateDesktopApiHandler.ts @@ -160,7 +160,7 @@ export default class PrivateDesktopApiHandler extends TypedEventEmitter<{ } public async createArgonsToSendFile(request: { - milligons: bigint; + microgons: bigint; fromAddress?: string; toAddress?: string; }): Promise { @@ -168,27 +168,27 @@ export default class PrivateDesktopApiHandler extends TypedEventEmitter<{ } public async transferArgonsFromMainchain(request: { - milligons: bigint; + microgons: bigint; address: string; }): Promise { await this.apiManager.accountManager.transferMainchainToLocal( request.address, - request.milligons, + request.microgons, ); } public async transferArgonsToMainchain(request: { - milligons: bigint; + microgons: bigint; address: string; }): Promise { return this.apiManager.accountManager.transferLocalToMainchain( request.address, - request.milligons, + request.microgons, ); } public async createArgonsToRequestFile(request: { - milligons: bigint; + microgons: bigint; sendToMyAddress?: string; }): Promise { return this.apiManager.accountManager.createArgonsToRequestFile(request); diff --git a/src/main/lib/WindowManager.ts b/src/main/lib/WindowManager.ts index 807d1fc..9c515f2 100644 --- a/src/main/lib/WindowManager.ts +++ b/src/main/lib/WindowManager.ts @@ -33,7 +33,7 @@ export class WindowManager { this.bindIpcEvents(); this.desktopWindow = new DesktopWindow(apiManager); - this.events.on(this.desktopWindow, 'close', this.checkOpenWindows.bind(this)); + this.events.on(this.desktopWindow, 'close', this.close.bind(this)); this.events.on(this.desktopWindow, 'focus', this.setMenu.bind(this)); this.events.on( apiManager.privateDesktopApiHandler, @@ -43,13 +43,14 @@ export class WindowManager { } public async openDesktop(): Promise { - await app.dock?.show(); this.setMenu(); - await this.desktopWindow.open(); + await this.desktopWindow.open(true); } public close(): void { + console.log('Closing Desktop'); this.events.close(); + void this.menuBar.appExit(); } public async loadChromeAliveWindow(data: { @@ -61,8 +62,11 @@ export class WindowManager { this.#chromeAliveWindowsBySessionId.get(data.heroSessionId)?.window.focus(); return; } - await app.dock?.show(); - const chromeAliveWindow = new ChromeAliveWindow(data, data.cloudAddress); + const connectionId = await this.apiManager.getCloudConnectionIdByAddress(data.cloudAddress); + if (!connectionId) { + throw new Error(`No connection found for cloud address ${data.cloudAddress}`); + } + const chromeAliveWindow = new ChromeAliveWindow(data, data.cloudAddress, connectionId); const { heroSessionId } = data; this.chromeAliveWindows.push(chromeAliveWindow); @@ -167,7 +171,7 @@ export class WindowManager { private checkOpenWindows(): void { if (this.chromeAliveWindows.length === 0 && !this.desktopWindow.isOpen) { - app.dock?.hide(); + app.quit(); } } diff --git a/src/main/lib/util/defaultEnvVars.ts b/src/main/lib/util/defaultEnvVars.ts index 8fcb19a..a3aacee 100644 --- a/src/main/lib/util/defaultEnvVars.ts +++ b/src/main/lib/util/defaultEnvVars.ts @@ -5,5 +5,5 @@ if (app.isPackaged) { process.env.DEBUG = [process.env.DEBUG ?? '', 'ulx:*'].filter(Boolean).join(','); process.env.NODE_DISABLE_COLORS = 'true'; } else { - process.env.DEBUG = [process.env.DEBUG ?? '', 'ulx:*'].filter(Boolean).join(','); + process.env.DEBUG = [process.env.DEBUG ?? '', 'ulx'].filter(Boolean).join(','); } diff --git a/src/ui/src/pages/desktop/components/DatastoreCard.vue b/src/ui/src/pages/desktop/components/DatastoreCard.vue index 4a0f404..870c6ca 100644 --- a/src/ui/src/pages/desktop/components/DatastoreCard.vue +++ b/src/ui/src/pages/desktop/components/DatastoreCard.vue @@ -27,7 +27,8 @@ Stopped + >Stopped
@@ -48,17 +49,13 @@
-
- Total Earned -
+
Total Earned
{{ earned }}
-
- Total Spent -
+
Total Spent
{{ spent() }}
@@ -106,7 +103,7 @@ export default Vue.defineComponent({ runs, errors, reliability, - earned: toArgons(microgons, true), + earned: toArgons(microgons), }; }, methods: { @@ -127,11 +124,11 @@ export default Vue.defineComponent({ const credits = this.wallet.credits.filter( x => x.datastoreId === this.datastore.id && x.datastoreVersion === this.datastore.version, ); - let spentCredits = 0; + let spentCredits = 0n; for (const credit of credits) { spentCredits += credit.allocated - credit.remaining; } - return toArgons(spentCredits, true); + return toArgons(spentCredits); }, }, }); diff --git a/src/ui/src/pages/desktop/lib/utils.ts b/src/ui/src/pages/desktop/lib/utils.ts index 153ba0c..1e87411 100644 --- a/src/ui/src/pages/desktop/lib/utils.ts +++ b/src/ui/src/pages/desktop/lib/utils.ts @@ -1,9 +1,9 @@ import ArgonUtils from '@ulixee/platform-utils/lib/ArgonUtils'; import { isRef, unref } from 'vue'; -export function toArgons(amount: number | bigint, isMicrogons = false): string { +export function toArgons(amount: number | bigint): string { if (amount === null || amount === undefined) return `${ArgonUtils.ArgonSymbol}0`; - return ArgonUtils.format(amount, isMicrogons ? 'microgons' : 'milligons', 'argons'); + return ArgonUtils.format(amount, 'microgons', 'argons'); } export function titleCase(text: string): string { diff --git a/src/ui/src/pages/desktop/stores/WalletStore.ts b/src/ui/src/pages/desktop/stores/WalletStore.ts index 2dd7e70..0115770 100644 --- a/src/ui/src/pages/desktop/stores/WalletStore.ts +++ b/src/ui/src/pages/desktop/stores/WalletStore.ts @@ -47,13 +47,13 @@ export const useWalletStore = defineStore('walletStore', () => { return account; } - async function transferFromMainchain(milligons: bigint, address: string) { - await window.desktopApi.send('Argon.transferFromMainchain', { milligons, address }); + async function transferFromMainchain(microgons: bigint, address: string) { + await window.desktopApi.send('Argon.transferFromMainchain', { microgons, address }); await load(); } - async function transferToMainchain(milligons: bigint, address: string) { - await window.desktopApi.send('Argon.transferToMainchain', { milligons, address }); + async function transferToMainchain(microgons: bigint, address: string) { + await window.desktopApi.send('Argon.transferToMainchain', { microgons, address }); await load(); } @@ -75,9 +75,9 @@ export const useWalletStore = defineStore('walletStore', () => { await load(); } - async function createSendArgonsFile(milligons: bigint, toAddress?: string, fromAddress?: string) { + async function createSendArgonsFile(microgons: bigint, toAddress?: string, fromAddress?: string) { const argons = await window.desktopApi.send('Argon.send', { - milligons, + microgons, toAddress, fromAddress, }); @@ -85,9 +85,9 @@ export const useWalletStore = defineStore('walletStore', () => { return argons; } - async function createRequestArgonsFile(milligons: bigint, sendToMyAddress?: string) { + async function createRequestArgonsFile(microgons: bigint, sendToMyAddress?: string) { const argons = await window.desktopApi.send('Argon.request', { - milligons, + microgons, sendToMyAddress, }); await load(); diff --git a/src/ui/src/pages/desktop/views/Overview.vue b/src/ui/src/pages/desktop/views/Overview.vue index 617ec97..9ea2c23 100644 --- a/src/ui/src/pages/desktop/views/Overview.vue +++ b/src/ui/src/pages/desktop/views/Overview.vue @@ -1,31 +1,19 @@