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