Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
@import "variables";
@import "context-menu";
@import "elements"; @import "elements";
@import "fonts";
@import "page"; @import "page";
@import "react-overlapping-panels/dist";
@import "tippy.js/dist/tippy.css";
.tippy-box {
background: var(--secondary-background);
}
.tippy-content {
padding: 8px;
font-size: 12px;
}
.tippy-arrow {
color: var(--secondary-background);
}
/// <reference lib="webworker" />
import { precacheAndRoute } from "workbox-precaching";
declare let self: ServiceWorkerGlobalScope;
self.addEventListener("message", (event) => {
if (event.data && event.data.type === "SKIP_WAITING") self.skipWaiting();
});
precacheAndRoute(self.__WB_MANIFEST);
self.addEventListener("push", (event) => {
async function process() {
if (event.data === null) return;
// Need to write notification generator on server.
}
event.waitUntil(process());
});
// ? Open the app on notification click.
// https://stackoverflow.com/a/39457287
self.addEventListener("notificationclick", (event) => {
const url = event.notification.data;
event.notification.close();
event.waitUntil(
self.clients
.matchAll({ includeUncontrolled: true, type: "window" })
.then((windowClients) => {
// Check if there is already a window/tab open with the target URL
for (let i = 0; i < windowClients.length; i++) {
const client = windowClients[i];
// If so, just focus it.
if (client.url === url && "focus" in client) {
return client.focus();
}
}
// If not, then open the target URL in a new window/tab.
if (self.clients.openWindow) {
return self.clients.openWindow(url);
}
}),
);
});
import { VNode } from 'preact'; import { VNode } from "preact";
export type Children = VNode | (VNode | string)[] | string; export type Child = VNode | string | number | boolean | undefined | null;
export type Children = Child | Child[] | Children[];
export const APP_VERSION = "__APP_VERSION__";
{ {
"compilerOptions": { "compilerOptions": {
"target": "ESNext", "target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"], "lib": ["DOM", "DOM.Iterable", "ESNext", "WebWorker"],
"allowJs": false, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": false, "esModuleInterop": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"strict": true, "strict": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"module": "ESNext", "module": "ESNext",
"moduleResolution": "Node", "moduleResolution": "Node",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "preserve", "jsx": "preserve",
"jsxFactory": "h", "jsxFactory": "h",
"jsxFragmentFactory": "Fragment" "jsxFragmentFactory": "Fragment",
}, "types": ["vite-plugin-pwa/client"],
"include": ["src", "ui/ui.tsx"] "experimentalDecorators": true
},
"include": ["src", "ui/ui.tsx"]
} }
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>REVOLT UI</title> <title>Revolt UI</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
......
import { useState } from 'preact/hooks'; import styled from "styled-components";
import styled from 'styled-components';
import '../src/styles/index.scss'
import { render } from 'preact'
import { GlobalTheme } from '../src/context/Theme'; import "../src/styles/index.scss";
import { render } from "preact";
import { useState } from "preact/hooks";
import Theme from "../src/context/Theme";
import Banner from "../src/components/ui/Banner";
import Button from "../src/components/ui/Button";
import Checkbox from "../src/components/ui/Checkbox";
import ColourSwatches from "../src/components/ui/ColourSwatches";
import ComboBox from "../src/components/ui/ComboBox";
import InputBox from "../src/components/ui/InputBox";
import Overline from "../src/components/ui/Overline";
import Radio from "../src/components/ui/Radio";
import Tip from "../src/components/ui/Tip";
export const UIDemo = styled.div` export const UIDemo = styled.div`
gap: 12px; gap: 12px;
padding: 12px; padding: 12px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
`; `;
import Button from '../src/components/ui/Button';
import Banner from '../src/components/ui/Banner';
import Checkbox from '../src/components/ui/Checkbox';
import ComboBox from '../src/components/ui/ComboBox';
import InputBox from '../src/components/ui/InputBox';
import ColourSwatches from '../src/components/ui/ColourSwatches';
import Tip from '../src/components/ui/Tip';
import Radio from '../src/components/ui/Radio';
import Overline from '../src/components/ui/Overline';
export function UI() { export function UI() {
let [checked, setChecked] = useState(false); let [checked, setChecked] = useState(false);
let [colour, setColour] = useState('#FD6671'); let [colour, setColour] = useState("#FD6671");
let [selected, setSelected] = useState<'a' | 'b' | 'c'>('a'); let [selected, setSelected] = useState<"a" | "b" | "c">("a");
return ( return (
<> <>
<Button>Button (normal)</Button> <Button>Button (normal)</Button>
<Button contrast>Button (contrast)</Button> <Button contrast>Button (contrast)</Button>
<Button error>Button (error)</Button> <Button error>Button (error)</Button>
<Button contrast error>Button (contrast + error)</Button> <Button contrast error>
Button (contrast + error)
</Button>
<Banner>I am a banner!</Banner> <Banner>I am a banner!</Banner>
<Checkbox checked={checked} onChange={setChecked} description="ok gamer">Do you want thing??</Checkbox> <Checkbox
checked={checked}
onChange={setChecked}
description="ok gamer">
Do you want thing??
</Checkbox>
<ComboBox> <ComboBox>
<option>Select an option.</option> <option>Select an option.</option>
<option>1</option> <option>1</option>
...@@ -46,23 +54,35 @@ export function UI() { ...@@ -46,23 +54,35 @@ export function UI() {
<InputBox placeholder="Contrast input box..." contrast /> <InputBox placeholder="Contrast input box..." contrast />
<InputBox value="Input box with value" /> <InputBox value="Input box with value" />
<InputBox value="Contrast with value" contrast /> <InputBox value="Contrast with value" contrast />
<ColourSwatches value={colour} onChange={v => setColour(v)} /> <ColourSwatches value={colour} onChange={(v) => setColour(v)} />
<Tip>I am a tip! I provide valuable information.</Tip> <Tip hideSeparator>I am a tip! I provide valuable information.</Tip>
<Radio checked={selected === 'a'} onSelect={() => setSelected('a')}>First option</Radio> <Radio checked={selected === "a"} onSelect={() => setSelected("a")}>
<Radio checked={selected === 'b'} onSelect={() => setSelected('b')}>Second option</Radio> First option
<Radio checked={selected === 'c'} onSelect={() => setSelected('c')}>Last option</Radio> </Radio>
<Radio checked={selected === "b"} onSelect={() => setSelected("b")}>
Second option
</Radio>
<Radio checked={selected === "c"} onSelect={() => setSelected("c")}>
Last option
</Radio>
<Overline>Normal overline</Overline> <Overline>Normal overline</Overline>
<Overline type="subtle">Subtle overline</Overline> <Overline type="subtle">Subtle overline</Overline>
<Overline type="error">Error overline</Overline> <Overline type="error">Error overline</Overline>
<Overline error="with error">Normal overline</Overline> <Overline error="with error">Normal overline</Overline>
<Overline type="subtle" error="with error">Subtle overline</Overline> <Overline type="subtle" error="with error">
Subtle overline
</Overline>
</> </>
) );
} }
render(<> render(
<GlobalTheme /> <>
<UIDemo> <Theme>
<UI /> <UIDemo>
</UIDemo> <UI />
</>, document.getElementById('app')!) </UIDemo>
</Theme>
</>,
document.getElementById("app")!,
);
{
"routes": [{ "src": "/[^.]+", "dest": "/", "status": 200 }]
}
\ No newline at end of file
import { resolve } from 'path' import replace from "@rollup/plugin-replace";
import { defineConfig } from 'vite' import { readFileSync } from "fs";
import preact from '@preact/preset-vite' import { resolve } from "path";
import { defineConfig } from "vite";
import { VitePWA } from "vite-plugin-pwa";
// https://vitejs.dev/config/ import preact from "@preact/preset-vite";
export default defineConfig({
plugins: [preact()], function getGitRevision() {
build: { try {
rollupOptions: { const rev = readFileSync(".git/HEAD").toString().trim();
input: { if (rev.indexOf(":") === -1) {
main: resolve(__dirname, 'index.html'), return rev;
ui: resolve(__dirname, 'ui/index.html') } else {
} return readFileSync(".git/" + rev.substring(5))
.toString()
.trim();
}
} catch (err) {
console.error("Failed to get Git revision.");
return "?";
}
}
function getGitBranch() {
try {
const rev = readFileSync(".git/HEAD").toString().trim();
if (rev.indexOf(":") === -1) {
return "DETACHED";
} else {
return rev.split("/").pop();
}
} catch (err) {
console.error("Failed to get Git branch.");
return "?";
} }
} }
})
function getVersion() {
return readFileSync("VERSION").toString();
}
const branch = getGitBranch();
const isNightly = false; //branch !== 'production';
const iconPrefix = isNightly ? "nightly-" : "";
export default defineConfig({
plugins: [
preact(),
VitePWA({
srcDir: "src",
filename: "sw.ts",
strategies: "injectManifest",
manifest: {
name: isNightly ? "Revolt Nightly" : "Revolt",
short_name: "Revolt",
description: isNightly
? "Early preview builds of Revolt."
: "User-first, privacy-focused chat platform.",
categories: ["messaging"],
start_url: "/",
orientation: "portrait",
display: "standalone",
background_color: "#101823",
theme_color: "#101823",
icons: [
{
src: `/assets/icons/${iconPrefix}android-chrome-192x192.png`,
type: "image/png",
sizes: "192x192",
},
{
src: `/assets/icons/${iconPrefix}android-chrome-512x512.png`,
type: "image/png",
sizes: "512x512",
},
{
src: `/assets/icons/monochrome.svg`,
type: "image/svg+xml",
sizes: "48x48 72x72 96x96 128x128 256x256",
purpose: "monochrome",
},
{
src: `/assets/icons/masking-512x512.png`,
type: "image/png",
sizes: "512x512",
purpose: "maskable",
},
],
},
}),
replace({
__GIT_REVISION__: getGitRevision(),
__GIT_BRANCH__: getGitBranch(),
__APP_VERSION__: getVersion(),
preventAssignment: true,
}),
],
build: {
sourcemap: true,
rollupOptions: {
input: {
main: resolve(__dirname, "index.html"),
ui: resolve(__dirname, "ui/index.html"),
},
},
},
});
This source diff could not be displayed because it is too large. You can view the blob instead.