Cache system-tray-setting in ephemeral config
This commit is contained in:
parent
25325622ed
commit
50c9b1bf7f
4 changed files with 108 additions and 26 deletions
|
@ -8,6 +8,7 @@ import {
|
|||
} from '../ts/types/SystemTraySetting';
|
||||
import { isSystemTraySupported } from '../ts/types/Settings';
|
||||
import type { MainSQL } from '../ts/sql/main';
|
||||
import type { ConfigType } from './base_config';
|
||||
|
||||
/**
|
||||
* A small helper class to get and cache the `system-tray-setting` preference in the main
|
||||
|
@ -20,6 +21,7 @@ export class SystemTraySettingCache {
|
|||
|
||||
constructor(
|
||||
private readonly sql: Pick<MainSQL, 'sqlCall'>,
|
||||
private readonly ephemeralConfig: Pick<ConfigType, 'get' | 'set'>,
|
||||
private readonly argv: Array<string>,
|
||||
private readonly appVersion: string
|
||||
) {}
|
||||
|
@ -53,20 +55,25 @@ export class SystemTraySettingCache {
|
|||
`getSystemTraySetting saw --use-tray-icon flag. Returning ${result}`
|
||||
);
|
||||
} else if (isSystemTraySupported(this.appVersion)) {
|
||||
const { value } = (await this.sql.sqlCall('getItemById', [
|
||||
'system-tray-setting',
|
||||
])) || { value: undefined };
|
||||
const fastValue = this.ephemeralConfig.get('system-tray-setting');
|
||||
if (fastValue !== undefined) {
|
||||
log.info('getSystemTraySetting got fast value', fastValue);
|
||||
}
|
||||
|
||||
const value =
|
||||
fastValue ??
|
||||
(await this.sql.sqlCall('getItemById', ['system-tray-setting']))?.value;
|
||||
|
||||
if (value !== undefined) {
|
||||
result = parseSystemTraySetting(value);
|
||||
log.info(
|
||||
`getSystemTraySetting returning value from database, ${result}`
|
||||
);
|
||||
log.info(`getSystemTraySetting returning ${result}`);
|
||||
} else {
|
||||
result = SystemTraySetting.DoNotUseSystemTray;
|
||||
log.info(
|
||||
`getSystemTraySetting got no value from database, returning ${result}`
|
||||
);
|
||||
log.info(`getSystemTraySetting got no value, returning ${result}`);
|
||||
}
|
||||
|
||||
if (result !== fastValue) {
|
||||
this.ephemeralConfig.set('system-tray-setting', result);
|
||||
}
|
||||
} else {
|
||||
result = SystemTraySetting.DoNotUseSystemTray;
|
||||
|
@ -75,10 +82,14 @@ export class SystemTraySettingCache {
|
|||
);
|
||||
}
|
||||
|
||||
return this.updateCachedValue(result);
|
||||
}
|
||||
|
||||
private updateCachedValue(value: SystemTraySetting): SystemTraySetting {
|
||||
// If there's a value in the cache, someone has updated the value "out from under us",
|
||||
// so we should return that because it's newer.
|
||||
this.cachedValue =
|
||||
this.cachedValue === undefined ? result : this.cachedValue;
|
||||
this.cachedValue === undefined ? value : this.cachedValue;
|
||||
|
||||
return this.cachedValue;
|
||||
}
|
||||
|
|
17
app/main.ts
17
app/main.ts
|
@ -118,6 +118,7 @@ const heicConverter = getHeicConverter();
|
|||
let systemTrayService: SystemTrayService | undefined;
|
||||
const systemTraySettingCache = new SystemTraySettingCache(
|
||||
sql,
|
||||
ephemeralConfig,
|
||||
process.argv,
|
||||
app.getVersion()
|
||||
);
|
||||
|
@ -1230,11 +1231,9 @@ function showPermissionsPopupWindow(forCalling: boolean, forCamera: boolean) {
|
|||
});
|
||||
}
|
||||
|
||||
async function initializeSQL(): Promise<
|
||||
{ ok: true; error: undefined } | { ok: false; error: Error }
|
||||
> {
|
||||
const userDataPath = await getRealPath(app.getPath('userData'));
|
||||
|
||||
async function initializeSQL(
|
||||
userDataPath: string
|
||||
): Promise<{ ok: true; error: undefined } | { ok: false; error: Error }> {
|
||||
let key: string | undefined;
|
||||
const keyFromConfig = userConfig.get('key');
|
||||
if (typeof keyFromConfig === 'string') {
|
||||
|
@ -1255,6 +1254,9 @@ async function initializeSQL(): Promise<
|
|||
|
||||
sqlInitTimeStart = Date.now();
|
||||
try {
|
||||
// This should be the first awaited call in this function, otherwise
|
||||
// `sql.sqlCall` will throw an uninitialized error instead of waiting for
|
||||
// init to finish.
|
||||
await sql.initialize({
|
||||
configDir: userDataPath,
|
||||
key,
|
||||
|
@ -1339,9 +1341,11 @@ ipc.on('database-error', (_event: Electron.Event, error: string) => {
|
|||
// Some APIs can only be used after this event occurs.
|
||||
let ready = false;
|
||||
app.on('ready', async () => {
|
||||
const userDataPath = await getRealPath(app.getPath('userData'));
|
||||
|
||||
logger = await logging.initialize(getMainWindow);
|
||||
|
||||
sqlInitPromise = initializeSQL();
|
||||
sqlInitPromise = initializeSQL(userDataPath);
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
|
@ -1377,7 +1381,6 @@ app.on('ready', async () => {
|
|||
});
|
||||
});
|
||||
|
||||
const userDataPath = await getRealPath(app.getPath('userData'));
|
||||
const installPath = await getRealPath(app.getAppPath());
|
||||
|
||||
addSensitivePath(userDataPath);
|
||||
|
|
|
@ -12,6 +12,11 @@ import {
|
|||
IPCEventsCallbacksType,
|
||||
} from '../util/createIPCEvents';
|
||||
|
||||
const EPHEMERAL_NAME_MAP = new Map([
|
||||
['spellCheck', 'spell-check'],
|
||||
['systemTraySetting', 'system-tray-setting'],
|
||||
]);
|
||||
|
||||
export class SettingsChannel {
|
||||
private mainWindow?: BrowserWindow;
|
||||
|
||||
|
@ -50,7 +55,9 @@ export class SettingsChannel {
|
|||
|
||||
this.installSetting('themeSetting');
|
||||
this.installSetting('hideMenuBar');
|
||||
this.installSetting('systemTraySetting');
|
||||
this.installSetting('systemTraySetting', {
|
||||
isEphemeral: true,
|
||||
});
|
||||
|
||||
this.installSetting('notificationSetting');
|
||||
this.installSetting('notificationDrawAttention');
|
||||
|
@ -199,8 +206,12 @@ export class SettingsChannel {
|
|||
|
||||
ipc.on(`settings:set:${name}`, (event, value) => {
|
||||
if (isEphemeral) {
|
||||
strictAssert(name === 'spellCheck', 'Only spellCheck is ephemeral');
|
||||
ephemeralConfig.set('spell-check', value);
|
||||
const ephemeralName = EPHEMERAL_NAME_MAP.get(name);
|
||||
strictAssert(
|
||||
ephemeralName !== undefined,
|
||||
`${name} is not an ephemeral setting`
|
||||
);
|
||||
ephemeralConfig.set(ephemeralName, value);
|
||||
}
|
||||
|
||||
const { mainWindow } = this;
|
||||
|
|
|
@ -6,19 +6,27 @@ import * as sinon from 'sinon';
|
|||
import { MainSQL } from '../../sql/main';
|
||||
import { SystemTraySetting } from '../../types/SystemTraySetting';
|
||||
|
||||
import type { ConfigType } from '../../../app/base_config';
|
||||
import { SystemTraySettingCache } from '../../../app/SystemTraySettingCache';
|
||||
|
||||
describe('SystemTraySettingCache', () => {
|
||||
let sandbox: sinon.SinonSandbox;
|
||||
|
||||
let sqlCallStub: sinon.SinonStub;
|
||||
let configGetStub: sinon.SinonStub;
|
||||
let configSetStub: sinon.SinonStub;
|
||||
let sql: Pick<MainSQL, 'sqlCall'>;
|
||||
let config: Pick<ConfigType, 'get' | 'set'>;
|
||||
|
||||
beforeEach(() => {
|
||||
sandbox = sinon.createSandbox();
|
||||
|
||||
sqlCallStub = sandbox.stub().resolves();
|
||||
sql = { sqlCall: sqlCallStub };
|
||||
|
||||
configGetStub = sandbox.stub().returns(undefined);
|
||||
configSetStub = sandbox.stub().returns(undefined);
|
||||
config = { get: configGetStub, set: configSetStub };
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -28,6 +36,7 @@ describe('SystemTraySettingCache', () => {
|
|||
it('returns MinimizeToAndStartInSystemTray if passed the --start-in-tray argument', async () => {
|
||||
const justOneArg = new SystemTraySettingCache(
|
||||
sql,
|
||||
config,
|
||||
['--start-in-tray'],
|
||||
'1.2.3'
|
||||
);
|
||||
|
@ -38,6 +47,7 @@ describe('SystemTraySettingCache', () => {
|
|||
|
||||
const bothArgs = new SystemTraySettingCache(
|
||||
sql,
|
||||
config,
|
||||
['--start-in-tray', '--use-tray-icon'],
|
||||
'1.2.3'
|
||||
);
|
||||
|
@ -47,23 +57,39 @@ describe('SystemTraySettingCache', () => {
|
|||
);
|
||||
|
||||
sinon.assert.notCalled(sqlCallStub);
|
||||
sinon.assert.notCalled(configGetStub);
|
||||
sinon.assert.notCalled(configSetStub);
|
||||
});
|
||||
|
||||
it('returns MinimizeToSystemTray if passed the --use-tray-icon argument', async () => {
|
||||
const cache = new SystemTraySettingCache(sql, ['--use-tray-icon'], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(
|
||||
sql,
|
||||
config,
|
||||
['--use-tray-icon'],
|
||||
'1.2.3'
|
||||
);
|
||||
assert.strictEqual(
|
||||
await cache.get(),
|
||||
SystemTraySetting.MinimizeToSystemTray
|
||||
);
|
||||
|
||||
sinon.assert.notCalled(sqlCallStub);
|
||||
sinon.assert.notCalled(configGetStub);
|
||||
sinon.assert.notCalled(configSetStub);
|
||||
});
|
||||
|
||||
it('returns DoNotUseSystemTray if system tray is supported but no preference is stored', async () => {
|
||||
sandbox.stub(process, 'platform').value('win32');
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, [], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
assert.strictEqual(await cache.get(), SystemTraySetting.DoNotUseSystemTray);
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
assert(
|
||||
configSetStub.calledOnceWith(
|
||||
'system-tray-setting',
|
||||
SystemTraySetting.DoNotUseSystemTray
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('returns DoNotUseSystemTray if system tray is supported but the stored preference is invalid', async () => {
|
||||
|
@ -71,8 +97,15 @@ describe('SystemTraySettingCache', () => {
|
|||
|
||||
sqlCallStub.resolves({ value: 'garbage' });
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, [], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
assert.strictEqual(await cache.get(), SystemTraySetting.DoNotUseSystemTray);
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
assert(
|
||||
configSetStub.calledOnceWith(
|
||||
'system-tray-setting',
|
||||
SystemTraySetting.DoNotUseSystemTray
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the stored preference if system tray is supported and something is stored', async () => {
|
||||
|
@ -80,29 +113,53 @@ describe('SystemTraySettingCache', () => {
|
|||
|
||||
sqlCallStub.resolves({ value: 'MinimizeToSystemTray' });
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, [], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
assert.strictEqual(
|
||||
await cache.get(),
|
||||
SystemTraySetting.MinimizeToSystemTray
|
||||
);
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
assert(
|
||||
configSetStub.calledOnceWith(
|
||||
'system-tray-setting',
|
||||
SystemTraySetting.MinimizeToSystemTray
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the cached preference if system tray is supported and something is stored', async () => {
|
||||
sandbox.stub(process, 'platform').value('win32');
|
||||
|
||||
configGetStub.returns('MinimizeToSystemTray');
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
assert.strictEqual(
|
||||
await cache.get(),
|
||||
SystemTraySetting.MinimizeToSystemTray
|
||||
);
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
sinon.assert.notCalled(sqlCallStub);
|
||||
});
|
||||
|
||||
it('only kicks off one request to the database if multiple sources ask at once', async () => {
|
||||
sandbox.stub(process, 'platform').value('win32');
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, [], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
|
||||
await Promise.all([cache.get(), cache.get(), cache.get()]);
|
||||
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
sinon.assert.calledOnce(sqlCallStub);
|
||||
});
|
||||
|
||||
it('returns DoNotUseSystemTray if system tray is unsupported and there are no CLI flags', async () => {
|
||||
sandbox.stub(process, 'platform').value('darwin');
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, [], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
assert.strictEqual(await cache.get(), SystemTraySetting.DoNotUseSystemTray);
|
||||
|
||||
sinon.assert.notCalled(configGetStub);
|
||||
sinon.assert.notCalled(configSetStub);
|
||||
sinon.assert.notCalled(sqlCallStub);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue