mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-10 01:03:36 -05:00
Improved native options.
This commit is contained in:
parent
63d2d1b760
commit
31636d569c
6 changed files with 292 additions and 75 deletions
72
src/components/native/Titlebar.tsx
Normal file
72
src/components/native/Titlebar.tsx
Normal 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
8
src/globals.d.ts
vendored
|
@ -7,12 +7,20 @@ type NativeConfig = {
|
||||||
|
|
||||||
declare interface Window {
|
declare interface Window {
|
||||||
isNative?: boolean;
|
isNative?: boolean;
|
||||||
|
nativeVersion: string;
|
||||||
native: {
|
native: {
|
||||||
|
min();
|
||||||
|
max();
|
||||||
close();
|
close();
|
||||||
reload();
|
reload();
|
||||||
|
relaunch();
|
||||||
|
|
||||||
getConfig(): NativeConfig;
|
getConfig(): NativeConfig;
|
||||||
setFrame(frame: boolean);
|
setFrame(frame: boolean);
|
||||||
setBuild(build: Build);
|
setBuild(build: Build);
|
||||||
|
|
||||||
|
getAutoStart(): Promise<boolean>;
|
||||||
|
enableAutoStart(): Promise<void>;
|
||||||
|
disableAutoStart(): Promise<void>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Notifications from "../context/revoltjs/Notifications";
|
||||||
import StateMonitor from "../context/revoltjs/StateMonitor";
|
import StateMonitor from "../context/revoltjs/StateMonitor";
|
||||||
import SyncManager from "../context/revoltjs/SyncManager";
|
import SyncManager from "../context/revoltjs/SyncManager";
|
||||||
|
|
||||||
|
import { TITLEBAR_HEIGHT, USE_TITLEBAR } from "../components/native/Titlebar";
|
||||||
import BottomNavigation from "../components/navigation/BottomNavigation";
|
import BottomNavigation from "../components/navigation/BottomNavigation";
|
||||||
import LeftSidebar from "../components/navigation/LeftSidebar";
|
import LeftSidebar from "../components/navigation/LeftSidebar";
|
||||||
import RightSidebar from "../components/navigation/RightSidebar";
|
import RightSidebar from "../components/navigation/RightSidebar";
|
||||||
|
@ -42,83 +43,89 @@ export default function App() {
|
||||||
path.includes("/settings");
|
path.includes("/settings");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OverlappingPanels
|
<>
|
||||||
width="100vw"
|
<OverlappingPanels
|
||||||
height="var(--app-height)"
|
width="100vw"
|
||||||
leftPanel={
|
height={
|
||||||
inSpecial
|
USE_TITLEBAR
|
||||||
? undefined
|
? `calc(var(--app-height) - ${TITLEBAR_HEIGHT})`
|
||||||
: { width: 292, component: <LeftSidebar /> }
|
: "var(--app-height)"
|
||||||
}
|
}
|
||||||
rightPanel={
|
leftPanel={
|
||||||
!inSpecial && inChannel
|
inSpecial
|
||||||
? { width: 240, component: <RightSidebar /> }
|
? undefined
|
||||||
: undefined
|
: { width: 292, component: <LeftSidebar /> }
|
||||||
}
|
}
|
||||||
bottomNav={{
|
rightPanel={
|
||||||
component: <BottomNavigation />,
|
!inSpecial && inChannel
|
||||||
showIf: fixedBottomNav ? ShowIf.Always : ShowIf.Left,
|
? { width: 240, component: <RightSidebar /> }
|
||||||
height: 50,
|
: undefined
|
||||||
}}
|
}
|
||||||
docked={isTouchscreenDevice ? Docked.None : Docked.Left}>
|
bottomNav={{
|
||||||
<Routes>
|
component: <BottomNavigation />,
|
||||||
<Switch>
|
showIf: fixedBottomNav ? ShowIf.Always : ShowIf.Left,
|
||||||
<Route
|
height: 50,
|
||||||
path="/server/:server/channel/:channel/settings/:page"
|
}}
|
||||||
component={ChannelSettings}
|
docked={isTouchscreenDevice ? Docked.None : Docked.Left}>
|
||||||
/>
|
<Routes>
|
||||||
<Route
|
<Switch>
|
||||||
path="/server/:server/channel/:channel/settings"
|
<Route
|
||||||
component={ChannelSettings}
|
path="/server/:server/channel/:channel/settings/:page"
|
||||||
/>
|
component={ChannelSettings}
|
||||||
<Route
|
/>
|
||||||
path="/server/:server/settings/:page"
|
<Route
|
||||||
component={ServerSettings}
|
path="/server/:server/channel/:channel/settings"
|
||||||
/>
|
component={ChannelSettings}
|
||||||
<Route
|
/>
|
||||||
path="/server/:server/settings"
|
<Route
|
||||||
component={ServerSettings}
|
path="/server/:server/settings/:page"
|
||||||
/>
|
component={ServerSettings}
|
||||||
<Route
|
/>
|
||||||
path="/channel/:channel/settings/:page"
|
<Route
|
||||||
component={ChannelSettings}
|
path="/server/:server/settings"
|
||||||
/>
|
component={ServerSettings}
|
||||||
<Route
|
/>
|
||||||
path="/channel/:channel/settings"
|
<Route
|
||||||
component={ChannelSettings}
|
path="/channel/:channel/settings/:page"
|
||||||
/>
|
component={ChannelSettings}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/channel/:channel/settings"
|
||||||
|
component={ChannelSettings}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/channel/:channel/:message"
|
path="/channel/:channel/:message"
|
||||||
component={Channel}
|
component={Channel}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/server/:server/channel/:channel/:message"
|
path="/server/:server/channel/:channel/:message"
|
||||||
component={Channel}
|
component={Channel}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/server/:server/channel/:channel"
|
path="/server/:server/channel/:channel"
|
||||||
component={Channel}
|
component={Channel}
|
||||||
/>
|
/>
|
||||||
<Route path="/server/:server" />
|
<Route path="/server/:server" />
|
||||||
<Route path="/channel/:channel" component={Channel} />
|
<Route path="/channel/:channel" component={Channel} />
|
||||||
|
|
||||||
<Route path="/settings/:page" component={Settings} />
|
<Route path="/settings/:page" component={Settings} />
|
||||||
<Route path="/settings" component={Settings} />
|
<Route path="/settings" component={Settings} />
|
||||||
|
|
||||||
<Route path="/dev" component={Developer} />
|
<Route path="/dev" component={Developer} />
|
||||||
<Route path="/friends" component={Friends} />
|
<Route path="/friends" component={Friends} />
|
||||||
<Route path="/open/:id" component={Open} />
|
<Route path="/open/:id" component={Open} />
|
||||||
<Route path="/invite/:code" component={Invite} />
|
<Route path="/invite/:code" component={Invite} />
|
||||||
<Route path="/" component={Home} />
|
<Route path="/" component={Home} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</Routes>
|
</Routes>
|
||||||
<ContextMenus />
|
<ContextMenus />
|
||||||
<Popovers />
|
<Popovers />
|
||||||
<Notifications />
|
<Notifications />
|
||||||
<StateMonitor />
|
<StateMonitor />
|
||||||
<SyncManager />
|
<SyncManager />
|
||||||
</OverlappingPanels>
|
</OverlappingPanels>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import { CheckAuth } from "../context/revoltjs/CheckAuth";
|
||||||
import Masks from "../components/ui/Masks";
|
import Masks from "../components/ui/Masks";
|
||||||
import Preloader from "../components/ui/Preloader";
|
import Preloader from "../components/ui/Preloader";
|
||||||
|
|
||||||
|
import { Titlebar, USE_TITLEBAR } from "../components/native/Titlebar";
|
||||||
|
|
||||||
const Login = lazy(() => import("./login/Login"));
|
const Login = lazy(() => import("./login/Login"));
|
||||||
const RevoltApp = lazy(() => import("./RevoltApp"));
|
const RevoltApp = lazy(() => import("./RevoltApp"));
|
||||||
|
|
||||||
|
@ -15,6 +17,7 @@ export function App() {
|
||||||
return (
|
return (
|
||||||
<Context>
|
<Context>
|
||||||
<Masks />
|
<Masks />
|
||||||
|
{USE_TITLEBAR && <Titlebar />}
|
||||||
{/*
|
{/*
|
||||||
// @ts-expect-error */}
|
// @ts-expect-error */}
|
||||||
<Suspense fallback={<Preloader type="spinner" />}>
|
<Suspense fallback={<Preloader type="spinner" />}>
|
||||||
|
|
|
@ -210,6 +210,9 @@ export default function Settings() {
|
||||||
{GIT_BRANCH === "production" ? "Stable" : "Nightly"}{" "}
|
{GIT_BRANCH === "production" ? "Stable" : "Nightly"}{" "}
|
||||||
{APP_VERSION}
|
{APP_VERSION}
|
||||||
</span>
|
</span>
|
||||||
|
{window.isNative && (
|
||||||
|
<span>Native: {window.nativeVersion}</span>
|
||||||
|
)}
|
||||||
<span>
|
<span>
|
||||||
API: {client.configuration?.revolt ?? "N/A"}
|
API: {client.configuration?.revolt ?? "N/A"}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { SyncOptions } from "../../../redux/reducers/sync";
|
import { SyncOptions } from "../../../redux/reducers/sync";
|
||||||
|
|
||||||
|
import Button from "../../../components/ui/Button";
|
||||||
import Checkbox from "../../../components/ui/Checkbox";
|
import Checkbox from "../../../components/ui/Checkbox";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -7,5 +10,126 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Native(props: 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>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue