Remove stray console.log and update translations.

Update themes endpoint and filter unmatched commits.
This commit is contained in:
Paul 2021-09-09 22:39:17 +01:00
parent efbbb6f1aa
commit 048267b419
6 changed files with 196 additions and 158 deletions

2
.env
View file

@ -1,2 +1,2 @@
VITE_API_URL=https://api.revolt.chat VITE_API_URL=https://api.revolt.chat
VITE_THEMES_URL=https://static.revolt.chat/themes VITE_THEMES_URL=https://themes.revolt.chat

View file

@ -1,2 +1,2 @@
VITE_API_URL=__API_URL__ VITE_API_URL=__API_URL__
VITE_THEMES_URL=https://static.revolt.chat/themes VITE_THEMES_URL=https://themes.revolt.chat

2
external/lang vendored

@ -1 +1 @@
Subproject commit 2d5b96a5c72bb706b73e9b67d5be395810a18c15 Subproject commit edebbe8a1d720b2ecbedbf137e2e7c2f2e3d1e13

View file

@ -150,8 +150,8 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
`<@${element.dataset.mentionId}>`, `<@${element.dataset.mentionId}>`,
"mention", "mention",
); );
ev.preventDefault() ev.preventDefault();
return return;
} }
case "channel_mention": { case "channel_mention": {
internalEmit( internalEmit(
@ -160,8 +160,8 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
`<#${element.dataset.mentionId}>`, `<#${element.dataset.mentionId}>`,
"channel_mention", "channel_mention",
); );
ev.preventDefault() ev.preventDefault();
return return;
} }
} }
} }
@ -194,7 +194,6 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
element.removeAttribute("target"); element.removeAttribute("target");
const link = determineLink(element.href); const link = determineLink(element.href);
console.log(link)
switch (link.type) { switch (link.type) {
case "profile": { case "profile": {
element.setAttribute( element.setAttribute(
@ -203,20 +202,20 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
); );
element.setAttribute( element.setAttribute(
"data-mention-id", "data-mention-id",
link.id link.id,
) );
break; break;
} }
case "navigate": { case "navigate": {
if (link.navigation_type === 'channel') { if (link.navigation_type === "channel") {
element.setAttribute( element.setAttribute(
"data-type", "data-type",
"channel_mention", "channel_mention",
); );
element.setAttribute( element.setAttribute(
"data-mention-id", "data-mention-id",
link.channel_id link.channel_id,
) );
} }
break; break;
} }

View file

@ -1,7 +1,12 @@
type LinkType = type LinkType =
| { type: "profile"; id: string } | { type: "profile"; id: string }
| { type: "navigate"; path: string; navigation_type?: null } | { type: "navigate"; path: string; navigation_type?: null }
| { type: "navigate"; path: string; navigation_type: 'channel'; channel_id: string } | {
type: "navigate";
path: string;
navigation_type: "channel";
channel_id: string;
}
| { type: "external"; href: string; url: URL } | { type: "external"; href: string; url: URL }
| { type: "none" }; | { type: "none" };
@ -12,7 +17,8 @@ const ALLOWED_ORIGINS = [
"local.revolt.chat", "local.revolt.chat",
]; ];
const CHANNEL_PATH_RE = /^\/server\/[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}\/channel\/[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/ const CHANNEL_PATH_RE =
/^\/server\/[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}\/channel\/[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/;
export function determineLink(href?: string): LinkType { export function determineLink(href?: string): LinkType {
let internal, let internal,
@ -30,9 +36,13 @@ export function determineLink(href?: string): LinkType {
return { type: "profile", id }; return { type: "profile", id };
} }
} else { } else {
console.log(path)
if (CHANNEL_PATH_RE.test(path)) { if (CHANNEL_PATH_RE.test(path)) {
return { type: 'navigate', path, navigation_type: 'channel', channel_id: path.slice(43) } return {
type: "navigate",
path,
navigation_type: "channel",
channel_id: path.slice(43),
};
} }
return { type: "navigate", path }; return { type: "navigate", path };
} }

View file

@ -1,26 +1,37 @@
import { useEffect, useState } from "preact/hooks" import styled from "styled-components";
import styled from "styled-components"
import Tip from "../../../components/ui/Tip" import { useEffect, useState } from "preact/hooks";
import { Theme, generateVariables } from '../../../context/Theme'
import { dispatch } from "../../../redux" import { dispatch } from "../../../redux";
import { Theme, generateVariables } from "../../../context/Theme";
import Tip from "../../../components/ui/Tip";
import previewPath from "../assets/preview.svg";
import { GIT_REVISION } from "../../../revision";
export const fetchManifest = (): Promise<Manifest> => export const fetchManifest = (): Promise<Manifest> =>
fetch(`${import.meta.env.VITE_THEMES_URL}/manifest.json`).then(res => res.json()) fetch(`${import.meta.env.VITE_THEMES_URL}/manifest.json`).then((res) =>
res.json(),
);
export const fetchTheme = (slug: string): Promise<Theme> => export const fetchTheme = (slug: string): Promise<Theme> =>
fetch(`${import.meta.env.VITE_THEMES_URL}/theme_${slug}.json`).then(res => res.json()) fetch(`${import.meta.env.VITE_THEMES_URL}/theme_${slug}.json`).then((res) =>
res.json(),
);
interface ThemeMetadata { interface ThemeMetadata {
name: string, name: string;
creator: string, creator: string;
description: string commit?: string;
description: string;
} }
type Manifest = { type Manifest = {
generated: string, generated: string;
themes: Record<string, ThemeMetadata> themes: Record<string, ThemeMetadata>;
} };
// TODO: ability to preview / display the settings set like in the appearance pane // TODO: ability to preview / display the settings set like in the appearance pane
const ThemeInfo = styled.article` const ThemeInfo = styled.article`
@ -74,7 +85,9 @@ const ThemeInfo = styled.article`
object-fit: contain; object-fit: contain;
} }
&:hover, &:active, &:focus-visible { &:hover,
&:active,
&:focus-visible {
outline: 3px solid var(--tertiary-background); outline: 3px solid var(--tertiary-background);
} }
} }
@ -93,86 +106,102 @@ const ThemeInfo = styled.article`
.description { .description {
grid-area: desc; grid-area: desc;
} }
` `;
const ThemeList = styled.div` const ThemeList = styled.div`
display: grid; display: grid;
gap: 1rem; gap: 1rem;
` `;
import previewPath from '../assets/preview.svg'
const ThemedSVG = styled.svg<{ theme: Theme }>` const ThemedSVG = styled.svg<{ theme: Theme }>`
${props => props.theme && generateVariables(props.theme)} ${(props) => props.theme && generateVariables(props.theme)}
` `;
type ThemePreviewProps = Omit<JSX.HTMLAttributes<SVGSVGElement>, "as"> & { type ThemePreviewProps = Omit<JSX.HTMLAttributes<SVGSVGElement>, "as"> & {
slug?: string, slug?: string;
theme?: Theme theme?: Theme;
onThemeLoaded?: (theme: Theme) => void onThemeLoaded?: (theme: Theme) => void;
}; };
const ThemePreview = ({ theme, ...props }: ThemePreviewProps) => { const ThemePreview = ({ theme, ...props }: ThemePreviewProps) => {
return <ThemedSVG {...props} theme={theme} width="323" height="202" aria-hidden="true" data-loaded={!!theme}> return (
<ThemedSVG
{...props}
theme={theme}
width="323"
height="202"
aria-hidden="true"
data-loaded={!!theme}>
<use href={`${previewPath}#preview`} width="100%" height="100%" /> <use href={`${previewPath}#preview`} width="100%" height="100%" />
</ThemedSVG> </ThemedSVG>
} );
};
const ThemeShopRoot = styled.div` const ThemeShopRoot = styled.div`
display: grid; display: grid;
gap: 1rem; gap: 1rem;
` `;
export function ThemeShop() { export function ThemeShop() {
// setThemeList is for adding more / lazy loading in the future // setThemeList is for adding more / lazy loading in the future
const [themeList, setThemeList] = useState<[string, ThemeMetadata][] | null>(null); const [themeList, setThemeList] = useState<
[string, ThemeMetadata][] | null
>(null);
const [themeData, setThemeData] = useState<Record<string, Theme>>({}); const [themeData, setThemeData] = useState<Record<string, Theme>>({});
async function fetchThemeList() { async function fetchThemeList() {
const manifest = await fetchManifest() const manifest = await fetchManifest();
setThemeList(Object.entries(manifest.themes)) setThemeList(
Object.entries(manifest.themes).filter((x) =>
x[1].commit ? x[1].commit === GIT_REVISION : true,
),
);
} }
async function getTheme(slug: string) { async function getTheme(slug: string) {
const theme = await fetchTheme(slug); const theme = await fetchTheme(slug);
setThemeData(data => ({ ...data, [slug]: theme })) setThemeData((data) => ({ ...data, [slug]: theme }));
} }
useEffect(() => { useEffect(() => {
fetchThemeList() fetchThemeList();
}, []) }, []);
useEffect(() => { useEffect(() => {
themeList?.forEach(([slug]) => { themeList?.forEach(([slug]) => {
getTheme(slug) getTheme(slug);
}) });
}, [themeList]) }, [themeList]);
return (<ThemeShopRoot> return (
<Tip warning>This section is under construction.</Tip> <ThemeShopRoot>
<Tip warning hideSeparator>
This section is under construction.
</Tip>
<ThemeList> <ThemeList>
{themeList?.map(([slug, theme]) => ( {themeList?.map(([slug, theme]) => (
<ThemeInfo key={slug} data-loaded={Reflect.has(themeData, slug)}> <ThemeInfo
key={slug}
data-loaded={Reflect.has(themeData, slug)}>
<h2 class="name">{theme.name}</h2> <h2 class="name">{theme.name}</h2>
{/* Maybe id's of the users should be included as well / instead? */} {/* Maybe id's of the users should be included as well / instead? */}
<div class="creator">by {theme.creator}</div> <div class="creator">by {theme.creator}</div>
<div class="description">{theme.description}</div> <div class="description">{theme.description}</div>
<button <button
class="preview" class="preview"
onClick={() => dispatch({ onClick={() =>
dispatch({
type: "SETTINGS_SET_THEME", type: "SETTINGS_SET_THEME",
theme: { theme: {
custom: themeData[slug], custom: themeData[slug],
} },
})} })
> }>
<ThemePreview <ThemePreview slug={slug} theme={themeData[slug]} />
slug={slug}
theme={themeData[slug]}
/>
</button> </button>
</ThemeInfo> </ThemeInfo>
))} ))}
</ThemeList> </ThemeList>
</ThemeShopRoot>) </ThemeShopRoot>
);
} }