Add open hidden at login option for Windows and Linux

https://github.com/samuelthomas2774/nxapi/issues/19
This commit is contained in:
Samuel Elliott 2022-11-12 17:22:48 +00:00
parent 0192529020
commit e6e1e73bdc
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
5 changed files with 115 additions and 24 deletions

View File

@ -22,11 +22,11 @@ export default function Preferences(props: PreferencesProps) {
const [login_item, ,, forceRefreshLoginItem] = useAsync(useCallback(() => ipc.getLoginItemSettings(), [ipc]));
const setOpenAtLogin = useCallback(async (open_at_login: boolean | 'mixed') => {
await ipc.setLoginItemSettings({...login_item, openAtLogin: !!open_at_login});
await ipc.setLoginItemSettings({...login_item!, startup_enabled: !!open_at_login});
forceRefreshLoginItem();
}, [ipc, login_item]);
const setOpenAsHidden = useCallback(async (open_as_hidden: boolean | 'mixed') => {
await ipc.setLoginItemSettings({...login_item, openAsHidden: !!open_as_hidden});
await ipc.setLoginItemSettings({...login_item!, startup_hidden: !!open_as_hidden});
forceRefreshLoginItem();
}, [ipc, login_item]);
@ -114,7 +114,7 @@ export default function Preferences(props: PreferencesProps) {
<View style={styles.main}>
{/* <Text style={theme.text}>Preferences</Text> */}
{ipc.platform === 'darwin' || ipc.platform === 'win32' ? <View style={styles.section}>
{login_item.supported || login_item.startup_enabled ? <View style={styles.section}>
<View style={styles.sectionLeft}>
<Text style={[styles.label, theme.text]}>Startup</Text>
</View>
@ -124,32 +124,33 @@ export default function Preferences(props: PreferencesProps) {
<View style={styles.checkboxContainer}>
<CheckBox
value={login_item.openAtLogin}
value={login_item.startup_enabled}
onValueChange={setOpenAtLogin}
disabled={!login_item.supported}
color={'#' + (accent_colour ?? DEFAULT_ACCENT_COLOUR)}
style={styles.checkbox}
/>
<TouchableOpacity style={styles.checkboxLabel} onPress={() => setOpenAtLogin(!login_item.openAtLogin)}>
<TouchableOpacity disabled={!login_item.supported} style={styles.checkboxLabel} onPress={() => setOpenAtLogin(!login_item.startup_enabled)}>
<Text style={[styles.checkboxLabelText, theme.text]}>Open at login</Text>
</TouchableOpacity>
</View>
{ipc.platform === 'darwin' ? <View
style={[styles.checkboxContainer, !login_item.openAtLogin ? styles.disabled : null]}
<View
style={[styles.checkboxContainer, !login_item.startup_enabled ? styles.disabled : null]}
>
<CheckBox
value={login_item.openAsHidden}
value={login_item.startup_hidden}
onValueChange={setOpenAsHidden}
disabled={!login_item.openAtLogin}
disabled={!login_item.startup_enabled}
color={'#' + (accent_colour ?? DEFAULT_ACCENT_COLOUR)}
style={styles.checkbox}
/>
<TouchableOpacity disabled={!login_item.openAtLogin} style={styles.checkboxLabel}
onPress={() => setOpenAsHidden(!login_item.openAsHidden)}
<TouchableOpacity disabled={!login_item.startup_enabled} style={styles.checkboxLabel}
onPress={() => setOpenAsHidden(!login_item.startup_hidden)}
>
<Text style={[styles.checkboxLabelText, theme.text]}>Open in background</Text>
</TouchableOpacity>
</View> : null}
</View>
</View>
</View> : null}

View File

@ -47,3 +47,10 @@ export interface DiscordPresenceSourceUrl {
export interface DiscordPresenceExternalMonitorsConfiguration {
enable_splatnet3_monitoring?: boolean;
}
export interface LoginItem {
supported: boolean;
startup_enabled: boolean;
startup_hidden: boolean;
}
export type LoginItemOptions = Omit<LoginItem, 'supported'>;

View File

@ -9,7 +9,7 @@ import MenuApp from './menu.js';
import { handleOpenWebServiceUri } from './webservices.js';
import { EmbeddedPresenceMonitor, PresenceMonitorManager } from './monitor.js';
import { createWindow } from './windows.js';
import { DiscordPresenceConfiguration, WindowType } from '../common/types.js';
import { DiscordPresenceConfiguration, LoginItem, LoginItemOptions, WindowType } from '../common/types.js';
import { initStorage, paths } from '../../util/storage.js';
import { checkUpdates, UpdateCacheData } from '../../common/update.js';
import Users, { CoralUser } from '../../common/users.js';
@ -29,10 +29,28 @@ export const protocol_registration_options = dev && process.platform === 'win32'
path.join(dir, 'dist', 'app', 'app-entry.cjs'),
],
} : null;
export const login_item_options: LoginItemSettingsOptions = {};
export const login_item_options: LoginItemSettingsOptions = {
path: process.execPath,
args: dev ? [
path.join(dir, 'dist', 'app', 'app-entry.cjs'),
'--app-open-at-login=1',
] : [
'--app-open-at-login=1',
],
};
enum LoginItemType {
NATIVE,
NATIVE_PARTIAL,
NOT_SUPPORTED,
}
const login_item_type: LoginItemType =
process.platform === 'darwin' ? LoginItemType.NATIVE :
process.platform === 'win32' ? LoginItemType.NATIVE_PARTIAL :
LoginItemType.NOT_SUPPORTED;
debug('Protocol registration options', protocol_registration_options);
debug('Login item registration options', login_item_options);
debug('Login item registration options', LoginItemType[login_item_type], login_item_options);
export class App {
readonly store: Store;
@ -184,7 +202,11 @@ export async function init() {
debug('App started');
if (!app.getLoginItemSettings(login_item_options).wasOpenedAsHidden) {
const should_hide =
login_item_type === LoginItemType.NATIVE ? app.getLoginItemSettings(login_item_options).wasOpenedAsHidden :
process.argv.includes('--app-open-at-login=1') && (await appinstance.store.getLoginItem()).startup_hidden;
if (!should_hide) {
appinstance.showMainWindow();
}
}
@ -254,6 +276,10 @@ class Updater {
}
}
interface SavedStartupOptions {
hide: boolean;
}
interface SavedMonitorState {
users: {
/** Nintendo Account ID */
@ -277,6 +303,63 @@ export class Store extends EventEmitter {
this.users = Users.coral(this, process.env.ZNC_PROXY_URL, false);
}
async getLoginItem(): Promise<LoginItem> {
const settings = app.getLoginItemSettings(login_item_options);
if (login_item_type === LoginItemType.NATIVE) {
// Fully supported
return {
supported: true,
startup_enabled: settings.openAtLogin,
startup_hidden: settings.openAsHidden,
};
}
const startup_options: SavedStartupOptions | undefined = await this.storage.getItem('StartupOptions');
const was_opened_at_login = process.argv.includes('--app-open-at-login=1');
if (login_item_type === LoginItemType.NATIVE_PARTIAL) {
// Partial native support
return {
supported: true,
startup_enabled: settings.openAtLogin,
startup_hidden: startup_options?.hide ?? false,
};
}
return {
supported: false,
startup_enabled: was_opened_at_login,
startup_hidden: startup_options?.hide ?? false,
};
}
async setLoginItem(settings: LoginItemOptions) {
if (login_item_type === LoginItemType.NATIVE) {
// Fully supported
app.setLoginItemSettings({
...login_item_options,
openAtLogin: settings.startup_enabled,
openAsHidden: settings.startup_hidden,
});
return;
}
if (login_item_type === LoginItemType.NATIVE_PARTIAL) {
// Partial native support
app.setLoginItemSettings({
...login_item_options,
openAtLogin: settings.startup_enabled,
});
}
const startup_options: SavedStartupOptions = {
hide: settings.startup_hidden,
};
await this.storage.setItem('StartupOptions', startup_options);
}
async saveMonitorState(monitors: PresenceMonitorManager) {
const users = new Set();
const state: SavedMonitorState = {

View File

@ -1,10 +1,10 @@
import { app, BrowserWindow, clipboard, dialog, IpcMain, KeyboardEvent, LoginItemSettings, Menu, MenuItem, Settings, ShareMenu, SharingItem, shell, systemPreferences } from './electron.js';
import { app, BrowserWindow, clipboard, dialog, IpcMain, KeyboardEvent, Menu, MenuItem, Settings, ShareMenu, SharingItem, shell, systemPreferences } from './electron.js';
import * as util from 'node:util';
import createDebug from 'debug';
import { User } from 'discord-rpc';
import openWebService, { QrCodeReaderOptions, WebServiceIpc, WebServiceValidationError } from './webservices.js';
import { createWindow, getWindowConfiguration } from './windows.js';
import { DiscordPresenceConfiguration, DiscordPresenceSource, WindowType } from '../common/types.js';
import { DiscordPresenceConfiguration, DiscordPresenceSource, LoginItemOptions, WindowType } from '../common/types.js';
import { CurrentUser, Friend, Game, PresenceState, WebService } from '../../api/coral-types.js';
import { askAddNsoAccount, askAddPctlAccount } from './na-auth.js';
import { App, login_item_options } from './index.js';
@ -40,8 +40,8 @@ export function setupIpc(appinstance: App, ipcMain: IpcMain) {
sendToAllWindows('nxapi:systemPreferences:accent-colour', accent_colour);
});
ipcMain.handle('nxapi:systemPreferences:getloginitem', () => app.getLoginItemSettings(login_item_options));
ipcMain.handle('nxapi:systemPreferences:setloginitem', (e, settings: Settings) => app.setLoginItemSettings({...login_item_options, ...settings}));
ipcMain.handle('nxapi:systemPreferences:getloginitem', () => appinstance.store.getLoginItem());
ipcMain.handle('nxapi:systemPreferences:setloginitem', (e, settings: LoginItemOptions) => appinstance.store.setLoginItem(settings));
ipcMain.handle('nxapi:update:get', () => appinstance.updater.cache ?? appinstance.updater.check());
ipcMain.handle('nxapi:update:check', () => appinstance.updater.check());

View File

@ -2,8 +2,8 @@ import { contextBridge, ipcRenderer } from 'electron';
import { EventEmitter } from 'events';
import createDebug from 'debug';
import type { User } from 'discord-rpc';
import type { LoginItemSettings, Settings, SharingItem } from '../main/electron.js';
import type { DiscordPresenceConfiguration, DiscordPresenceSource, WindowConfiguration } from '../common/types.js';
import type { SharingItem } from '../main/electron.js';
import type { DiscordPresenceConfiguration, DiscordPresenceSource, LoginItem, LoginItemOptions, WindowConfiguration } from '../common/types.js';
import type { SavedToken } from '../../common/auth/coral.js';
import type { SavedMoonToken } from '../../common/auth/moon.js';
import type { UpdateCacheData } from '../../common/update.js';
@ -30,8 +30,8 @@ events.setMaxListeners(0);
const ipc = {
getWindowData: () => invSync<WindowConfiguration>('browser:getwindowdata'),
getLoginItemSettings: () => inv<LoginItemSettings>('systemPreferences:getloginitem'),
setLoginItemSettings: (settings: Settings) => inv('systemPreferences:setloginitem', settings),
getLoginItemSettings: () => inv<LoginItem>('systemPreferences:getloginitem'),
setLoginItemSettings: (settings: LoginItemOptions) => inv('systemPreferences:setloginitem', settings),
getUpdateData: () => inv<UpdateCacheData | null>('update:get'),
checkUpdates: () => inv<UpdateCacheData | null>('update:check'),