diff options
Diffstat (limited to 'gui/src/main')
| -rw-r--r-- | gui/src/main/index.ts | 32 | ||||
| -rw-r--r-- | gui/src/main/notification-controller.ts | 18 |
2 files changed, 50 insertions, 0 deletions
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index 4df3b4c7a2..32620c3574 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -2,8 +2,10 @@ import { execFile } from 'child_process'; import { app, BrowserWindow, ipcMain, Menu, nativeImage, screen, Tray } from 'electron'; import log from 'electron-log'; import mkdirp from 'mkdirp'; +import moment from 'moment'; import * as path from 'path'; import * as uuid from 'uuid'; +import AccountExpiry from '../shared/account-expiry'; import BridgeSettingsBuilder from '../shared/bridge-settings-builder'; import { AccountToken, @@ -145,6 +147,8 @@ class ApplicationMain { private wireguardPublicKey?: IWireguardPublicKey; + private accountExpiryNotificationTimeout?: NodeJS.Timeout; + private accountDataCache = new AccountDataCache( (accountToken) => { return this.daemonRpc.getAccountData(accountToken); @@ -155,6 +159,8 @@ class ApplicationMain { if (this.windowController) { IpcMainEventChannel.account.notify(this.windowController.webContents, accountData); } + + this.notifyOfAccountExpiry(); }, ); @@ -1081,6 +1087,11 @@ class ApplicationMain { private async logout(): Promise<void> { try { await this.daemonRpc.setAccount(); + + if (this.accountExpiryNotificationTimeout) { + global.clearTimeout(this.accountExpiryNotificationTimeout); + this.accountExpiryNotificationTimeout = undefined; + } } catch (error) { log.info(`Failed to logout: ${error.message}`); @@ -1132,6 +1143,27 @@ class ApplicationMain { } } + private notifyOfAccountExpiry() { + if (this.accountData) { + const accountExpiry = new AccountExpiry(this.accountData.expiry, this.locale); + if ( + accountExpiry && + !this.accountExpiryNotificationTimeout && + accountExpiry.willHaveExpiredAt( + moment() + .add(3, 'days') + .toDate(), + ) + ) { + this.notificationController.closeToExpiryNotification(accountExpiry); + this.accountExpiryNotificationTimeout = global.setTimeout(() => { + this.accountExpiryNotificationTimeout = undefined; + this.notifyOfAccountExpiry(); + }, 12 * 60 * 60 * 1000); // Every 12 hours + } + } + } + private async updateAccountHistory(): Promise<void> { try { this.setAccountHistory(await this.daemonRpc.getAccountHistory()); diff --git a/gui/src/main/notification-controller.ts b/gui/src/main/notification-controller.ts index 98852029f3..69c0f9ec30 100644 --- a/gui/src/main/notification-controller.ts +++ b/gui/src/main/notification-controller.ts @@ -3,6 +3,7 @@ import os from 'os'; import path from 'path'; import { sprintf } from 'sprintf-js'; import config from '../config.json'; +import AccountExpiry from '../shared/account-expiry'; import { TunnelState } from '../shared/daemon-rpc-types'; import { messages } from '../shared/gettext'; @@ -156,6 +157,23 @@ export default class NotificationController { this.scheduleNotification(notification); } + public closeToExpiryNotification(accountExpiry: AccountExpiry) { + const duration = accountExpiry.durationUntilExpiry(); + const notification = new Notification({ + title: this.notificationTitle, + body: sprintf( + // TRANSLATORS: The system notification displayed to the user when the account credit is close to expiry. + // TRANSLATORS: Available placeholder: + // TRANSLATORS: %(duration)s - remaining time, e.g. "2 days" + messages.pgettext('notifications', 'Account credit expires in %(duration)s'), + { duration }, + ), + silent: true, + icon: this.notificationIcon, + }); + this.scheduleNotification(notification); + } + public cancelPendingNotifications() { for (const notification of this.pendingNotifications) { notification.close(); |
