feat: Global Account Controller implented with Context's
This commit is contained in:
parent
6d9f145ada
commit
dab365f048
11 changed files with 275 additions and 197 deletions
|
|
@ -10,6 +10,8 @@ fn main() {
|
|||
"get_users",
|
||||
"get_user",
|
||||
"remove_user",
|
||||
"get_default_user",
|
||||
"set_default_user",
|
||||
// Cluster
|
||||
"create_cluster",
|
||||
"remove_cluster",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ permissions = [
|
|||
"allow-get-users",
|
||||
"allow-get-user",
|
||||
"allow-remove-user",
|
||||
"allow-get-default-user",
|
||||
"allow-set-default-user",
|
||||
|
||||
# Cluster
|
||||
"allow-create-cluster",
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ macro_rules! collect_commands {
|
|||
auth_login,
|
||||
get_users,
|
||||
get_user,
|
||||
get_default_user,
|
||||
set_default_user,
|
||||
remove_user,
|
||||
// Cluster
|
||||
create_cluster,
|
||||
|
|
@ -212,6 +214,24 @@ pub async fn get_user(uuid: Uuid) -> Result<MinecraftCredentials, String> {
|
|||
Ok(minecraft::get_user(uuid).await?)
|
||||
}
|
||||
|
||||
#[specta::specta]
|
||||
#[tauri::command]
|
||||
pub async fn get_default_user() -> Result<Option<MinecraftCredentials>, String> {
|
||||
let uuid = minecraft::get_default_user().await?;
|
||||
|
||||
match uuid {
|
||||
Some(uuid) => Ok(Some(minecraft::get_user(uuid).await?)),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
#[specta::specta]
|
||||
#[tauri::command]
|
||||
pub async fn set_default_user(uuid: Uuid) -> Result<(), String> {
|
||||
minecraft::set_default_user(uuid).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[specta::specta]
|
||||
#[tauri::command]
|
||||
pub async fn auth_login(handle: AppHandle) -> Result<Option<MinecraftCredentials>, String> {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import NotificationOverlay from './components/overlay/notifications/Notification
|
|||
import { SettingsProvider } from './hooks/useSettings';
|
||||
import { ClusterModalController } from './components/overlay/cluster/ClusterCreationModal';
|
||||
import { MultiProvider } from './components/MultiProvider';
|
||||
import { AccountControllerProvider } from './components/overlay/account/AddAccountModal';
|
||||
import { AppInfo } from '~utils/program-info';
|
||||
|
||||
function App(props: ParentProps) {
|
||||
|
|
@ -50,6 +51,7 @@ function GlobalContexts(props: ParentProps) {
|
|||
values={[
|
||||
SettingsProvider,
|
||||
ClusterModalController,
|
||||
AccountControllerProvider,
|
||||
]}
|
||||
>
|
||||
{props.children}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import { createSignal } from 'solid-js';
|
|||
import { Bell01Icon, Cloud01Icon, Settings01Icon, TerminalBrowserIcon } from '@untitled-theme/icons-solid';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import { WEBSITE } from '@onelauncher/client';
|
||||
import useAccount from '../hooks/useAccount';
|
||||
import PolyfrostFull from './logos/PolyfrostFull';
|
||||
import AccountPopup from './overlay/AccountPopup';
|
||||
import AccountPopup from './overlay/account/AccountsPopup';
|
||||
import PlayerHead from './game/PlayerHead';
|
||||
import Button from './base/Button';
|
||||
import NotificationPopup from './overlay/notifications/NotificationPopup';
|
||||
import Popup from './overlay/Popup';
|
||||
import useAccountController from './overlay/account/AddAccountModal';
|
||||
|
||||
interface NavbarLinkProps {
|
||||
path: string;
|
||||
|
|
@ -33,9 +33,9 @@ function NavbarLink(props: NavbarLinkProps) {
|
|||
function Navbar() {
|
||||
const [profileMenuOpen, setProfileMenuOpen] = createSignal(false);
|
||||
const [notificationMenuOpen, setNotificationMenuOpen] = createSignal(false);
|
||||
const navigate = useNavigate();
|
||||
const controller = useAccountController();
|
||||
|
||||
const account = useAccount();
|
||||
const navigate = useNavigate();
|
||||
|
||||
let profileButton!: HTMLButtonElement;
|
||||
let notificationButton!: HTMLButtonElement;
|
||||
|
|
@ -81,7 +81,7 @@ function Navbar() {
|
|||
ref={profileButton}
|
||||
onClick={() => setProfileMenuOpen(!profileMenuOpen())}
|
||||
>
|
||||
<PlayerHead class="w-[30px] h-[30px] rounded-md hover:opacity-70" uuid={account.uuid} />
|
||||
<PlayerHead class="w-[30px] h-[30px] rounded-md hover:opacity-70" uuid={controller.defaultAccount()?.id} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { JSX } from 'solid-js';
|
|||
import steveSrc from '../../../assets/images/steve.png';
|
||||
|
||||
type PlayerHeadProps = JSX.IntrinsicElements['img'] & {
|
||||
uuid: string;
|
||||
uuid: string | null | undefined;
|
||||
onError?: () => any;
|
||||
};
|
||||
|
||||
|
|
@ -24,13 +24,15 @@ function PlayerHead(props: PlayerHeadProps) {
|
|||
{...rest}
|
||||
/>
|
||||
</Show>
|
||||
<img
|
||||
src={headSrc(split.uuid)}
|
||||
onLoad={() => setLoading(false)}
|
||||
onError={() => props.onError && props.onError()}
|
||||
class={`image-render-pixel ${isLoading() ? 'hidden' : ''} ${split.class}`}
|
||||
{...rest}
|
||||
/>
|
||||
<Show when={props.uuid !== null && props.uuid !== undefined}>
|
||||
<img
|
||||
src={headSrc(split.uuid!)}
|
||||
onLoad={() => setLoading(false)}
|
||||
onError={() => props.onError && props.onError()}
|
||||
class={`image-render-pixel ${isLoading() ? 'hidden' : ''} ${split.class}`}
|
||||
{...rest}
|
||||
/>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
import { LogOut01Icon, PlusIcon, Settings01Icon } from '@untitled-theme/icons-solid';
|
||||
import { useNavigate } from '@solidjs/router';
|
||||
import Button from '../base/Button';
|
||||
import PlayerHead from '../game/PlayerHead';
|
||||
import useAccount from '../../hooks/useAccount';
|
||||
import Popup from './Popup';
|
||||
|
||||
interface AccountComponentProps {
|
||||
username: string;
|
||||
uuid: string;
|
||||
loggedIn?: boolean;
|
||||
}
|
||||
|
||||
function AccountComponent(props: AccountComponentProps) {
|
||||
return (
|
||||
<div class={`flex flex-row justify-between p-2 rounded-lg ${!props.loggedIn && 'hover:bg-gray-05 active:bg-gray-10 hover:text-fg-primary-hover'}`}>
|
||||
<div class="flex flex-row justify-start flex-1 gap-x-3">
|
||||
<PlayerHead class="w-8 h-8 rounded-md" uuid={props.uuid} />
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
<div class="flex flex-col items-start justify-between">
|
||||
<p class="font-semibold h-[18px]">{props.username}</p>
|
||||
{props.loggedIn && <p class="text-xs">Logged in</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{props.loggedIn && (
|
||||
<Button buttonStyle="icon">
|
||||
<LogOut01Icon class=" stroke-danger" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AccountPopup(props: Popup.PopupProps) {
|
||||
const loggedInAccount = useAccount();
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Popup {...props}>
|
||||
<div class="bg-secondary rounded-xl border border-gray-10 w-72 p-2 shadow-md shadow-black/30">
|
||||
<div class="flex flex-col gap-y-2 text-fg-primary">
|
||||
<AccountComponent username={loggedInAccount.username} uuid={loggedInAccount.uuid} loggedIn />
|
||||
|
||||
<div class="w-full h-px bg-gray-05 rounded-md" />
|
||||
|
||||
<AccountComponent username="Wyvest" uuid="a5331404-0e77-440e-8bef-24c071dac1ae" />
|
||||
|
||||
<div class="w-full h-px bg-gray-05 rounded-md" />
|
||||
|
||||
<div class="flex flex-row justify-between">
|
||||
<div>
|
||||
<Button buttonStyle="ghost" iconLeft={<PlusIcon />}>Add Account</Button>
|
||||
</div>
|
||||
<div class="flex flex-row">
|
||||
<Button
|
||||
buttonStyle="icon"
|
||||
large
|
||||
onClick={() => {
|
||||
props.setVisible(false);
|
||||
navigate('/settings/accounts');
|
||||
}}
|
||||
>
|
||||
<Settings01Icon class="stroke-fg-primary" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</Popup>
|
||||
);
|
||||
}
|
||||
|
||||
export default AccountPopup;
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
import { For, Show } from 'solid-js';
|
||||
import { LogOut01Icon, PlusIcon, Settings01Icon } from '@untitled-theme/icons-solid';
|
||||
import { useNavigate } from '@solidjs/router';
|
||||
import Button from '../../base/Button';
|
||||
import PlayerHead from '../../game/PlayerHead';
|
||||
import Popup from '../Popup';
|
||||
import useAccountController from './AddAccountModal';
|
||||
import type { MinecraftCredentials } from '~bindings';
|
||||
|
||||
interface AccountComponentProps {
|
||||
account: MinecraftCredentials | null | undefined;
|
||||
loggedIn?: boolean;
|
||||
}
|
||||
|
||||
function AccountComponent(props: AccountComponentProps) {
|
||||
return (
|
||||
<Show when={props.account}>
|
||||
<div class={`flex flex-row justify-between p-2 rounded-lg ${!props.loggedIn && 'hover:bg-gray-05 active:bg-gray-10 hover:text-fg-primary-hover'}`}>
|
||||
<div class="flex flex-row justify-start flex-1 gap-x-3">
|
||||
<PlayerHead class="w-8 h-8 rounded-md" uuid={props.account!.id} />
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
<div class="flex flex-col items-start justify-between">
|
||||
<p class="font-semibold h-[18px]">{props.account!.username}</p>
|
||||
{props.loggedIn && <p class="text-xs">Logged in</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{props.loggedIn && (
|
||||
<Button buttonStyle="icon">
|
||||
<LogOut01Icon class=" stroke-danger" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</Show>
|
||||
);
|
||||
}
|
||||
|
||||
function AccountPopup(props: Popup.PopupProps) {
|
||||
const controller = useAccountController();
|
||||
|
||||
const filteredAccounts = () => controller.accounts()?.filter(account => account.id !== controller.defaultAccount()?.id) ?? [];
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Popup {...props}>
|
||||
<div class="bg-secondary rounded-xl border border-gray-10 w-72 p-2 shadow-md shadow-black/30">
|
||||
<div class="flex flex-col gap-y-2 text-fg-primary">
|
||||
<AccountComponent account={controller.defaultAccount()} loggedIn />
|
||||
|
||||
<Show when={filteredAccounts().length !== 0}>
|
||||
<div class="w-full h-px bg-gray-05 rounded-md" />
|
||||
<For each={filteredAccounts()}>
|
||||
{account => (
|
||||
<AccountComponent account={account} />
|
||||
)}
|
||||
</For>
|
||||
<div class="w-full h-px bg-gray-05 rounded-md" />
|
||||
</Show>
|
||||
|
||||
<div class="flex flex-row justify-between">
|
||||
<div>
|
||||
<Button
|
||||
buttonStyle="ghost"
|
||||
iconLeft={<PlusIcon />}
|
||||
onClick={() => {
|
||||
props.setVisible(false);
|
||||
controller.displayAddAccount();
|
||||
}}
|
||||
>
|
||||
Add Account
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex flex-row">
|
||||
<Button
|
||||
buttonStyle="icon"
|
||||
large
|
||||
onClick={() => {
|
||||
props.setVisible(false);
|
||||
navigate('/settings/accounts');
|
||||
}}
|
||||
>
|
||||
<Settings01Icon class="stroke-fg-primary" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</Popup>
|
||||
);
|
||||
}
|
||||
|
||||
export default AccountPopup;
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
import { type Accessor, type Context, Match, type ParentProps, type Resource, type Setter, Switch, createContext, createSignal, useContext } from 'solid-js';
|
||||
import { LinkExternal01Icon } from '@untitled-theme/icons-solid';
|
||||
import Modal from '../Modal';
|
||||
import type { MinecraftCredentials } from '~bindings';
|
||||
import { bridge } from '~imports';
|
||||
import useCommand, { tryResult } from '~ui/hooks/useCommand';
|
||||
import Button from '~ui/components/base/Button';
|
||||
|
||||
interface AccountControllerContextFunc {
|
||||
displayAddAccount: () => void;
|
||||
refetch: () => void;
|
||||
accounts: Resource<MinecraftCredentials[]>;
|
||||
defaultAccount: Resource<MinecraftCredentials | null>;
|
||||
setDefaultAccount: (uuid: string) => Promise<void>;
|
||||
removeAccount: (uuid: string) => Promise<void>;
|
||||
}
|
||||
|
||||
const AccountControllerContext = createContext<AccountControllerContextFunc>() as Context<AccountControllerContextFunc>;
|
||||
|
||||
export function AccountControllerProvider(props: ParentProps) {
|
||||
const [accounts, { refetch: refetchAccounts }] = useCommand(bridge.commands.getUsers);
|
||||
const [defaultAccount, { refetch: refetchDefaultAccount }] = useCommand(bridge.commands.getDefaultUser);
|
||||
const [visible, setVisible] = createSignal(false);
|
||||
|
||||
function refetch() {
|
||||
refetchAccounts();
|
||||
refetchDefaultAccount();
|
||||
}
|
||||
|
||||
async function setDefaultAccount(uuid: string) {
|
||||
await tryResult(bridge.commands.setDefaultUser, uuid);
|
||||
}
|
||||
|
||||
async function removeAccount(uuid: string) {
|
||||
await tryResult(bridge.commands.removeUser, uuid);
|
||||
refetch();
|
||||
}
|
||||
|
||||
const func: AccountControllerContextFunc = {
|
||||
displayAddAccount: () => setVisible(true),
|
||||
refetch,
|
||||
accounts,
|
||||
defaultAccount,
|
||||
setDefaultAccount,
|
||||
removeAccount,
|
||||
};
|
||||
|
||||
return (
|
||||
<AccountControllerContext.Provider value={func}>
|
||||
{props.children}
|
||||
<AddAccountModal visible={visible} setVisible={setVisible} refetch={refetch} />
|
||||
</AccountControllerContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useAccountController() {
|
||||
return useContext(AccountControllerContext);
|
||||
}
|
||||
|
||||
export default useAccountController;
|
||||
|
||||
enum ModalStage {
|
||||
Tasks,
|
||||
WaitingForCode,
|
||||
LoggingIn,
|
||||
}
|
||||
|
||||
interface AddAccountModalProps {
|
||||
visible: Accessor<boolean>;
|
||||
setVisible: Setter<boolean>;
|
||||
refetch: () => any;
|
||||
}
|
||||
|
||||
function AddAccountModal(props: AddAccountModalProps) {
|
||||
const [stage, setStage] = createSignal(ModalStage.Tasks);
|
||||
|
||||
function start() {
|
||||
setStage(ModalStage.WaitingForCode);
|
||||
|
||||
// tryResult(bridge.commands.beginMsa).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
}
|
||||
|
||||
// function finish() {
|
||||
// props.setVisible(false);
|
||||
// props.refetch();
|
||||
// }
|
||||
|
||||
return (
|
||||
<Modal.Simple
|
||||
title="Add Account"
|
||||
visible={props.visible}
|
||||
setVisible={props.setVisible}
|
||||
buttons={[
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
children="Cancel"
|
||||
onClick={() => props.setVisible(false)}
|
||||
/>,
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
children="Add"
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
onClick={start}
|
||||
disabled={stage() !== 0}
|
||||
/>,
|
||||
]}
|
||||
>
|
||||
<div class="flex flex-col gap-y-3 max-w-120 line-height-normal">
|
||||
<Switch>
|
||||
<Match when={stage() !== ModalStage.LoggingIn}>
|
||||
<p>
|
||||
Pressing the "Add" button will open your browser with a Microsoft login page.
|
||||
On this page, you login to your chosen Microsoft account and end up being asked whether you want to add the OneLauncher application.
|
||||
</p>
|
||||
</Match>
|
||||
|
||||
<Match when={stage() === ModalStage.LoggingIn}>
|
||||
<p>Proceeding with Microsoft auth steps...</p>
|
||||
</Match>
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
</Modal.Simple>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
function useAccount() {
|
||||
// TODO return the currently logged in account
|
||||
|
||||
return {
|
||||
username: 'Lynith',
|
||||
uuid: 'f247be7c-5b82-41c6-9148-793ded77e71f',
|
||||
skins: [],
|
||||
};
|
||||
}
|
||||
|
||||
export default useAccount;
|
||||
|
|
@ -1,36 +1,25 @@
|
|||
import { InfoCircleIcon, LinkExternal01Icon, Trash01Icon, UserPlus02Icon } from '@untitled-theme/icons-solid';
|
||||
import { type Accessor, For, Match, type Setter, Show, Switch, createEffect, createSignal, mergeProps } from 'solid-js';
|
||||
import { bridge } from '~imports';
|
||||
import { InfoCircleIcon, Trash01Icon, UserPlus02Icon } from '@untitled-theme/icons-solid';
|
||||
import { For, Match, Show, Switch, createSignal, mergeProps } from 'solid-js';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Tooltip from '~ui/components/base/Tooltip';
|
||||
import PlayerHead from '~ui/components/game/PlayerHead';
|
||||
import Modal from '~ui/components/overlay/Modal';
|
||||
import useAccountController from '~ui/components/overlay/account/AddAccountModal';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
|
||||
function SettingsAccounts() {
|
||||
const [current, setCurrent] = createSignal<string>();
|
||||
const [accounts, { refetch }] = useCommand(bridge.commands.getUsers);
|
||||
const [modalVisible, setModalVisible] = createSignal(false);
|
||||
const controller = useAccountController();
|
||||
|
||||
createEffect(() => {
|
||||
const users = accounts();
|
||||
if (users === undefined || users.length < 1 || current() !== undefined)
|
||||
return;
|
||||
|
||||
setCurrent(users[0]!.id);
|
||||
});
|
||||
function setCurrent(uuid: string) {
|
||||
controller.setDefaultAccount(uuid);
|
||||
}
|
||||
|
||||
function onDelete(uuid: string) {
|
||||
bridge.commands.removeUser(uuid)
|
||||
.finally(() => {
|
||||
refetch();
|
||||
});
|
||||
controller.removeAccount(uuid);
|
||||
}
|
||||
|
||||
function showModal() {
|
||||
setModalVisible(true);
|
||||
controller.displayAddAccount();
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -39,19 +28,19 @@ function SettingsAccounts() {
|
|||
|
||||
<ScrollableContainer>
|
||||
<Switch>
|
||||
<Match when={accounts()?.length === 0}>
|
||||
<Match when={controller.accounts()?.length === 0}>
|
||||
<div class="flex flex-col h-full gap-y-4 max-h-64 justify-center items-center">
|
||||
<span class="text-lg font-bold uppercase text-fg-secondary">No accounts added.</span>
|
||||
<span class="text-xl font-bold">Add one with the Add Account button.</span>
|
||||
</div>
|
||||
</Match>
|
||||
<Match when={accounts()?.length !== 0}>
|
||||
<For each={accounts()}>
|
||||
<Match when={controller.accounts()?.length !== 0}>
|
||||
<For each={controller.accounts()}>
|
||||
{account => (
|
||||
<AccountRow
|
||||
username={account.username}
|
||||
uuid={account.id}
|
||||
current={current() === account.id}
|
||||
current={controller.defaultAccount()?.id === account.id}
|
||||
onClick={setCurrent}
|
||||
onDelete={onDelete}
|
||||
/>
|
||||
|
|
@ -69,84 +58,10 @@ function SettingsAccounts() {
|
|||
onClick={showModal}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<AddAccountModal
|
||||
setVisible={setModalVisible}
|
||||
visible={modalVisible}
|
||||
refetch={refetch}
|
||||
/>
|
||||
|
||||
</Sidebar.Page>
|
||||
);
|
||||
}
|
||||
|
||||
enum ModalStage {
|
||||
Tasks,
|
||||
WaitingForCode,
|
||||
LoggingIn,
|
||||
}
|
||||
|
||||
interface AddAccountModalProps {
|
||||
visible: Accessor<boolean>;
|
||||
setVisible: Setter<boolean>;
|
||||
refetch: () => any;
|
||||
}
|
||||
|
||||
function AddAccountModal(props: AddAccountModalProps) {
|
||||
const [stage, setStage] = createSignal(ModalStage.Tasks);
|
||||
|
||||
function start() {
|
||||
setStage(ModalStage.WaitingForCode);
|
||||
|
||||
// tryResult(bridge.commands.beginMsa).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
}
|
||||
|
||||
function finish() {
|
||||
props.setVisible(false);
|
||||
props.refetch();
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal.Simple
|
||||
title="Add Account"
|
||||
visible={props.visible}
|
||||
setVisible={props.setVisible}
|
||||
buttons={[
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
children="Cancel"
|
||||
onClick={() => props.setVisible(false)}
|
||||
/>,
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
children="Add"
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
onClick={start}
|
||||
disabled={stage() !== 0}
|
||||
/>,
|
||||
]}
|
||||
>
|
||||
<div class="flex flex-col gap-y-3 max-w-120 line-height-normal">
|
||||
<Switch>
|
||||
<Match when={stage() !== ModalStage.LoggingIn}>
|
||||
<p>
|
||||
Pressing the "Add" button will open your browser with a Microsoft login page.
|
||||
On this page, you login to your chosen Microsoft account and end up being asked whether you want to add the OneLauncher application.
|
||||
</p>
|
||||
</Match>
|
||||
|
||||
<Match when={stage() === ModalStage.LoggingIn}>
|
||||
<p>Proceeding with Microsoft auth steps...</p>
|
||||
</Match>
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
</Modal.Simple>
|
||||
);
|
||||
}
|
||||
|
||||
interface AccountRowProps {
|
||||
username: string;
|
||||
uuid: string;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue