From 8afcd80f5ab3e092d6b1b4a9de283469441690fb Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Wed, 7 Sep 2022 15:54:38 +0100 Subject: [PATCH] Add preferences window --- src/app/browser/index.ts | 2 + src/app/browser/main/discord.tsx | 2 +- src/app/browser/preferences/index.tsx | 353 ++++++++++++++++++++++ src/app/browser/util.tsx | 2 +- src/app/common/types.ts | 4 +- src/app/main/app-menu.ts | 31 +- src/app/main/electron.ts | 3 + src/app/main/index.ts | 54 +++- src/app/main/ipc.ts | 20 +- src/app/main/menu.ts | 1 + src/app/main/monitor.ts | 35 ++- src/app/preload/index.ts | 12 +- src/cli/nso/presence.ts | 2 +- src/cli/util/discord-activity.ts | 3 +- src/cli/util/export-discord-titles.ts | 2 +- src/common/presence.ts | 3 +- src/discord/titles.ts | 2 +- src/discord/titles/capcom.ts | 2 +- src/discord/titles/mojang.ts | 2 +- src/discord/titles/nintendo.ts | 2 +- src/discord/titles/the-pokémon-company.ts | 2 +- src/discord/types.ts | 112 +++++++ src/discord/util.ts | 113 +------ 23 files changed, 622 insertions(+), 142 deletions(-) create mode 100644 src/app/browser/preferences/index.tsx create mode 100644 src/discord/types.ts diff --git a/src/app/browser/index.ts b/src/app/browser/index.ts index 34bfc2e..189cec4 100644 --- a/src/app/browser/index.ts +++ b/src/app/browser/index.ts @@ -4,11 +4,13 @@ import App from './main/index.js'; import Friend from './friend/index.js'; import DiscordSetup from './discord/index.js'; import AddFriend from './add-friend/index.js'; +import Preferences from './preferences/index.js'; AppRegistry.registerComponent('App', () => App); AppRegistry.registerComponent('Friend', () => Friend); AppRegistry.registerComponent('DiscordPresence', () => DiscordSetup); AppRegistry.registerComponent('AddFriend', () => AddFriend); +AppRegistry.registerComponent('Preferences', () => Preferences); const style = window.document.createElement('style'); diff --git a/src/app/browser/main/discord.tsx b/src/app/browser/main/discord.tsx index a71c87a..342e445 100644 --- a/src/app/browser/main/discord.tsx +++ b/src/app/browser/main/discord.tsx @@ -4,7 +4,7 @@ import { User } from 'discord-rpc'; import ipc, { events } from '../ipc.js'; import { RequestState, useAsync, useEventListener } from '../util.js'; import { DiscordPresenceSource, DiscordPresenceSourceUrl, DiscordPresenceSourceCoral } from '../../common/types.js'; -import { DiscordPresence } from '../../../discord/util.js'; +import { DiscordPresence } from '../../../discord/types.js'; import { DISCORD_COLOUR, TEXT_COLOUR_DARK } from '../constants.js'; export default function DiscordPresenceSource(props: { diff --git a/src/app/browser/preferences/index.tsx b/src/app/browser/preferences/index.tsx new file mode 100644 index 0000000..72ae840 --- /dev/null +++ b/src/app/browser/preferences/index.tsx @@ -0,0 +1,353 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { StyleSheet, Text, TextInput, TouchableHighlight, TouchableOpacity, useColorScheme, View } from 'react-native'; +import { CheckBox, Picker } from 'react-native-web'; +import { DiscordPresencePlayTime } from '../../../discord/types.js'; +import { Button } from '../components/index.js'; +import { DEFAULT_ACCENT_COLOUR, HIGHLIGHT_COLOUR_DARK, HIGHLIGHT_COLOUR_LIGHT, TEXT_COLOUR_DARK, TEXT_COLOUR_LIGHT } from '../constants.js'; +import ipc, { events } from '../ipc.js'; +import { getAccounts, RequestState, Root, useAsync, useDiscordPresenceSource, useEventListener } from '../util.js'; + +export interface PreferencesProps {} + +export default function Preferences(props: PreferencesProps) { + const colour_scheme = useColorScheme(); + const theme = colour_scheme === 'light' ? light : dark; + + const [accent_colour, setAccentColour] = React.useState(() => ipc.getAccentColour()); + useEventListener(events, 'systemPreferences:accent-colour', setAccentColour, []); + + const [users, ,, forceRefreshAccounts] = useAsync(useCallback(() => getAccounts(), [ipc])); + useEventListener(events, 'update-nintendo-accounts', forceRefreshAccounts, []); + + 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}); + forceRefreshLoginItem(); + }, [ipc, login_item]); + const setOpenAsHidden = useCallback(async (open_as_hidden: boolean | 'mixed') => { + await ipc.setLoginItemSettings({...login_item, openAsHidden: !!open_as_hidden}); + forceRefreshLoginItem(); + }, [ipc, login_item]); + + const [discord_users, discord_users_error, discord_users_state, forceRefreshDiscordUsers] = + useAsync(useCallback(() => ipc.getDiscordUsers(), [ipc])); + + const [discord_options, , discord_options_state, forceRefreshDiscordOptions] = + useAsync(useCallback(() => ipc.getSavedDiscordPresenceOptions(), [ipc])); + + const [discord_friend_code, setDiscordFriendCodeValue] = useState(discord_options?.friend_code ?? ''); + const discord_friend_code_valid = !discord_friend_code || discord_friend_code.match(/^\d{4}-\d{4}-\d{4}$/); + + useEffect(() => { + setDiscordFriendCodeValue(discord_options?.friend_code ?? ''); + }, [discord_options]); + + const setDiscordUser = useCallback(async (user: string | undefined) => { + if (user === '*') user = undefined; + await ipc.setDiscordPresenceOptions({...discord_options, user}); + forceRefreshDiscordOptions(); + }, [ipc, discord_options]); + const setDiscordFriendCode = useCallback(async (friend_code: string | undefined) => { + setDiscordFriendCodeValue(friend_code ?? ''); + if (friend_code && !friend_code.match(/^\d{4}-\d{4}-\d{4}$/)) return; + if (!friend_code) friend_code = undefined; + await ipc.setDiscordPresenceOptions({...discord_options, friend_code}); + forceRefreshDiscordOptions(); + }, [ipc, discord_options]); + const setDiscordShowConsoleOnline = useCallback(async (show_console_online: boolean | 'mixed') => { + await ipc.setDiscordPresenceOptions({...discord_options, show_console_online: !!show_console_online}); + forceRefreshDiscordOptions(); + }, [ipc, discord_options]); + const setDiscordShowPlayTime = useCallback(async (show_play_time: DiscordPresencePlayTime) => { + await ipc.setDiscordPresenceOptions({...discord_options, show_play_time}); + forceRefreshDiscordOptions(); + }, [ipc, discord_options]); + + const [discord_presence_source, discord_presence_source_state] = useDiscordPresenceSource(); + + const discord_presence_source_user = discord_presence_source && 'na_id' in discord_presence_source ? + discord_presence_source.friend_nsa_id ? + users?.find(u => u.nso?.nsoAccount.user.nsaId === discord_presence_source.friend_nsa_id)?.nso : + users?.find(u => u.nso?.user.id === discord_presence_source.na_id)?.nso : + null; + + const discord_friend_code_self = discord_presence_source_user?.nsoAccount.user.links.friendCode.id; + const [is_discord_friend_code_self, setIsDiscordFriendCodeSelf] = useState(false); + useEffect(() => { + setIsDiscordFriendCodeSelf(!!discord_presence_source && (!discord_friend_code || discord_friend_code === discord_friend_code_self)); + }, [discord_presence_source, discord_friend_code_self]); + + useEventListener(events, 'window:refresh', () => ( + forceRefreshAccounts(), forceRefreshLoginItem(), + forceRefreshDiscordUsers(), forceRefreshDiscordOptions() + ), []); + + if (!users || + !login_item || + !discord_options || + discord_presence_source_state !== RequestState.LOADED + ) { + return null; + } + + const discord_user_picker = []; + + if (discord_options?.user && !discord_users?.find(u => u.id === discord_options.user)) { + discord_user_picker.push(); + } + for (const user of discord_users ?? []) { + discord_user_picker.push(); + } + + return + + {/* Preferences */} + + {ipc.platform === 'darwin' || ipc.platform === 'win32' ? + + Startup + + + {/* Launch at startup menu here + {JSON.stringify(login_item, null, 4)} */} + + + + setOpenAtLogin(!login_item.openAtLogin)}> + Open at login + + + + {ipc.platform === 'darwin' ? + + setOpenAsHidden(!login_item.openAsHidden)}> + Open in background + + : null} + + : null} + + + + Sleep + + + Prevent sleep menu here + + + + + + Discord Rich Presence + + + Discord Rich Presence is {discord_presence_source ? 'en' : 'dis'}abled. + + +