Improved native options.

This commit is contained in:
Paul 2021-08-01 14:22:08 +01:00
parent 63d2d1b760
commit 31636d569c
6 changed files with 292 additions and 75 deletions

View file

@ -0,0 +1,72 @@
import { X, Minus, Square } from "@styled-icons/boxicons-regular";
import styled from "styled-components";
import wideSVG from "../../assets/wide.svg";
export const TITLEBAR_HEIGHT = "24px";
export const USE_TITLEBAR = window.isNative && !window.native.getConfig().frame;
const TitlebarBase = styled.div`
height: ${TITLEBAR_HEIGHT};
display: flex;
user-select: none;
align-items: center;
.title {
flex-grow: 1;
-webkit-app-region: drag;
font-size: 16px;
font-weight: 600;
margin-left: 4px;
img {
width: 60px;
}
}
.actions {
z-index: 100;
display: flex;
align-items: center;
div {
width: 24px;
height: 24px;
display: grid;
place-items: center;
transition: 0.2s ease background-color;
&:hover {
background: var(--primary-background);
}
&.error:hover {
background: var(--error);
}
}
}
`;
export function Titlebar() {
return (
<TitlebarBase>
<span class="title">
<img src={wideSVG} />
</span>
<div class="actions">
<div onClick={window.native.min}>
<Minus size={20} />
</div>
<div onClick={window.native.max}>
<Square size={14} />
</div>
<div onClick={window.native.close} class="error">
<X size={20} />
</div>
</div>
</TitlebarBase>
);
}

8
src/globals.d.ts vendored
View file

@ -7,12 +7,20 @@ type NativeConfig = {
declare interface Window {
isNative?: boolean;
nativeVersion: string;
native: {
min();
max();
close();
reload();
relaunch();
getConfig(): NativeConfig;
setFrame(frame: boolean);
setBuild(build: Build);
getAutoStart(): Promise<boolean>;
enableAutoStart(): Promise<void>;
disableAutoStart(): Promise<void>;
};
}

View file

@ -10,6 +10,7 @@ import Notifications from "../context/revoltjs/Notifications";
import StateMonitor from "../context/revoltjs/StateMonitor";
import SyncManager from "../context/revoltjs/SyncManager";
import { TITLEBAR_HEIGHT, USE_TITLEBAR } from "../components/native/Titlebar";
import BottomNavigation from "../components/navigation/BottomNavigation";
import LeftSidebar from "../components/navigation/LeftSidebar";
import RightSidebar from "../components/navigation/RightSidebar";
@ -42,83 +43,89 @@ export default function App() {
path.includes("/settings");
return (
<OverlappingPanels
width="100vw"
height="var(--app-height)"
leftPanel={
inSpecial
? undefined
: { width: 292, component: <LeftSidebar /> }
}
rightPanel={
!inSpecial && inChannel
? { width: 240, component: <RightSidebar /> }
: undefined
}
bottomNav={{
component: <BottomNavigation />,
showIf: fixedBottomNav ? ShowIf.Always : ShowIf.Left,
height: 50,
}}
docked={isTouchscreenDevice ? Docked.None : Docked.Left}>
<Routes>
<Switch>
<Route
path="/server/:server/channel/:channel/settings/:page"
component={ChannelSettings}
/>
<Route
path="/server/:server/channel/:channel/settings"
component={ChannelSettings}
/>
<Route
path="/server/:server/settings/:page"
component={ServerSettings}
/>
<Route
path="/server/:server/settings"
component={ServerSettings}
/>
<Route
path="/channel/:channel/settings/:page"
component={ChannelSettings}
/>
<Route
path="/channel/:channel/settings"
component={ChannelSettings}
/>
<>
<OverlappingPanels
width="100vw"
height={
USE_TITLEBAR
? `calc(var(--app-height) - ${TITLEBAR_HEIGHT})`
: "var(--app-height)"
}
leftPanel={
inSpecial
? undefined
: { width: 292, component: <LeftSidebar /> }
}
rightPanel={
!inSpecial && inChannel
? { width: 240, component: <RightSidebar /> }
: undefined
}
bottomNav={{
component: <BottomNavigation />,
showIf: fixedBottomNav ? ShowIf.Always : ShowIf.Left,
height: 50,
}}
docked={isTouchscreenDevice ? Docked.None : Docked.Left}>
<Routes>
<Switch>
<Route
path="/server/:server/channel/:channel/settings/:page"
component={ChannelSettings}
/>
<Route
path="/server/:server/channel/:channel/settings"
component={ChannelSettings}
/>
<Route
path="/server/:server/settings/:page"
component={ServerSettings}
/>
<Route
path="/server/:server/settings"
component={ServerSettings}
/>
<Route
path="/channel/:channel/settings/:page"
component={ChannelSettings}
/>
<Route
path="/channel/:channel/settings"
component={ChannelSettings}
/>
<Route
path="/channel/:channel/:message"
component={Channel}
/>
<Route
path="/server/:server/channel/:channel/:message"
component={Channel}
/>
<Route
path="/channel/:channel/:message"
component={Channel}
/>
<Route
path="/server/:server/channel/:channel/:message"
component={Channel}
/>
<Route
path="/server/:server/channel/:channel"
component={Channel}
/>
<Route path="/server/:server" />
<Route path="/channel/:channel" component={Channel} />
<Route
path="/server/:server/channel/:channel"
component={Channel}
/>
<Route path="/server/:server" />
<Route path="/channel/:channel" component={Channel} />
<Route path="/settings/:page" component={Settings} />
<Route path="/settings" component={Settings} />
<Route path="/settings/:page" component={Settings} />
<Route path="/settings" component={Settings} />
<Route path="/dev" component={Developer} />
<Route path="/friends" component={Friends} />
<Route path="/open/:id" component={Open} />
<Route path="/invite/:code" component={Invite} />
<Route path="/" component={Home} />
</Switch>
</Routes>
<ContextMenus />
<Popovers />
<Notifications />
<StateMonitor />
<SyncManager />
</OverlappingPanels>
<Route path="/dev" component={Developer} />
<Route path="/friends" component={Friends} />
<Route path="/open/:id" component={Open} />
<Route path="/invite/:code" component={Invite} />
<Route path="/" component={Home} />
</Switch>
</Routes>
<ContextMenus />
<Popovers />
<Notifications />
<StateMonitor />
<SyncManager />
</OverlappingPanels>
</>
);
}

View file

@ -8,6 +8,8 @@ import { CheckAuth } from "../context/revoltjs/CheckAuth";
import Masks from "../components/ui/Masks";
import Preloader from "../components/ui/Preloader";
import { Titlebar, USE_TITLEBAR } from "../components/native/Titlebar";
const Login = lazy(() => import("./login/Login"));
const RevoltApp = lazy(() => import("./RevoltApp"));
@ -15,6 +17,7 @@ export function App() {
return (
<Context>
<Masks />
{USE_TITLEBAR && <Titlebar />}
{/*
// @ts-expect-error */}
<Suspense fallback={<Preloader type="spinner" />}>

View file

@ -210,6 +210,9 @@ export default function Settings() {
{GIT_BRANCH === "production" ? "Stable" : "Nightly"}{" "}
{APP_VERSION}
</span>
{window.isNative && (
<span>Native: {window.nativeVersion}</span>
)}
<span>
API: {client.configuration?.revolt ?? "N/A"}
</span>

View file

@ -1,5 +1,8 @@
import { useEffect, useState } from "preact/hooks";
import { SyncOptions } from "../../../redux/reducers/sync";
import Button from "../../../components/ui/Button";
import Checkbox from "../../../components/ui/Checkbox";
interface Props {
@ -7,5 +10,126 @@ interface Props {
}
export function Native(props: Props) {
return <div></div>;
const [config, setConfig] = useState(window.native.getConfig());
const [autoStart, setAutoStart] = useState<boolean | undefined>();
const fetchValue = () => window.native.getAutoStart().then(setAutoStart);
const [hintReload, setHintReload] = useState(false);
const [hintRelaunch, setHintRelaunch] = useState(false);
const [confirmDev, setConfirmDev] = useState(false);
useEffect(() => {
fetchValue();
}, []);
return (
<div>
<Checkbox
checked={autoStart ?? false}
disabled={typeof autoStart === "undefined"}
onChange={async (v) => {
if (v) {
await window.native.enableAutoStart();
} else {
await window.native.disableAutoStart();
}
setAutoStart(v);
}}
description="Launch Revolt when you log into your computer.">
Start with computer
</Checkbox>
<Checkbox
checked={!config.frame}
onChange={(frame) => {
window.native.setFrame(!frame);
setHintRelaunch(true);
setConfig({
...config,
frame: !frame,
});
}}
description={<>Let Revolt use its own window frame.</>}>
Custom window frame
</Checkbox>
<Checkbox
checked={config.build === "nightly"}
onChange={(nightly) => {
const build = nightly ? "nightly" : "stable";
window.native.setBuild(build);
setHintReload(true);
setConfig({
...config,
build,
});
}}
description={<>Use the beta branch of Revolt.</>}>
Revolt Nightly
</Checkbox>
<p style={{ display: "flex", gap: "8px" }}>
<Button
contrast
compact
disabled={!hintReload}
onClick={window.native.reload}>
Reload Page
</Button>
<Button
contrast
compact
disabled={!hintRelaunch}
onClick={window.native.relaunch}>
Reload App
</Button>
</p>
<h3 style={{ marginTop: "4em" }}>Local Development Mode</h3>
{config.build === "dev" ? (
<p>
<Button
contrast
compact
onClick={() => {
window.native.setBuild("stable");
window.native.reload();
}}>
Exit Development Mode
</Button>
</p>
) : (
<>
<Checkbox
checked={confirmDev}
onChange={setConfirmDev}
description={
<>
This will change the app to the 'dev' branch,
instead loading the app from a local server on
your machine.
<br />
<b>
Without a server running,{" "}
<span style={{ color: "var(--error)" }}>
the app will not load!
</span>
</b>
</>
}>
I understand there's no going back.
</Checkbox>
<p>
<Button
error
compact
disabled={!confirmDev}
onClick={() => {
window.native.setBuild("dev");
window.native.reload();
}}>
Enter Development Mode
</Button>
</p>
</>
)}
</div>
);
}