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
Showing
with 2202 additions and 1817 deletions
...@@ -6,33 +6,33 @@ import { Language, Languages } from "../../context/Locale"; ...@@ -6,33 +6,33 @@ import { Language, Languages } from "../../context/Locale";
import ComboBox from "../ui/ComboBox"; import ComboBox from "../ui/ComboBox";
type Props = { type Props = {
locale: string; locale: string;
}; };
export function LocaleSelector(props: Props) { export function LocaleSelector(props: Props) {
return ( return (
<ComboBox <ComboBox
value={props.locale} value={props.locale}
onChange={(e) => onChange={(e) =>
dispatch({ dispatch({
type: "SET_LOCALE", type: "SET_LOCALE",
locale: e.currentTarget.value as Language, locale: e.currentTarget.value as Language,
}) })
}> }>
{Object.keys(Languages).map((x) => { {Object.keys(Languages).map((x) => {
const l = Languages[x as keyof typeof Languages]; const l = Languages[x as keyof typeof Languages];
return ( return (
<option value={x}> <option value={x} key={x}>
{l.emoji} {l.display} {l.emoji} {l.display}
</option> </option>
); );
})} })}
</ComboBox> </ComboBox>
); );
} }
export default connectState(LocaleSelector, (state) => { export default connectState(LocaleSelector, (state) => {
return { return {
locale: state.locale, locale: state.locale,
}; };
}); });
import { Cog } from "@styled-icons/boxicons-solid"; import { Cog } from "@styled-icons/boxicons-solid";
import { observer } from "mobx-react-lite";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Server } from "revolt.js/dist/api/objects";
import { ServerPermission } from "revolt.js/dist/api/permissions"; import { ServerPermission } from "revolt.js/dist/api/permissions";
import { Server } from "revolt.js/dist/maps/Servers";
import styled from "styled-components"; import styled from "styled-components";
import { HookContext, useServerPermission } from "../../context/revoltjs/hooks";
import Header from "../ui/Header"; import Header from "../ui/Header";
import IconButton from "../ui/IconButton"; import IconButton from "../ui/IconButton";
interface Props { interface Props {
server: Server; server: Server;
ctx: HookContext;
} }
const ServerName = styled.div` const ServerName = styled.div`
flex-grow: 1; flex-grow: 1;
`; `;
export default function ServerHeader({ server, ctx }: Props) { export default observer(({ server }: Props) => {
const permissions = useServerPermission(server._id, ctx); const bannerURL = server.generateBannerURL({ width: 480 });
const bannerURL = ctx.client.servers.getBannerURL(
server._id,
{ width: 480 },
true,
);
return ( return (
<Header <Header
borders borders
placement="secondary" placement="secondary"
background={typeof bannerURL !== "undefined"} background={typeof bannerURL !== "undefined"}
style={{ style={{
background: bannerURL ? `url('${bannerURL}')` : undefined, background: bannerURL ? `url('${bannerURL}')` : undefined,
}}> }}>
<ServerName>{server.name}</ServerName> <ServerName>{server.name}</ServerName>
{(permissions & ServerPermission.ManageServer) > 0 && ( {(server.permission & ServerPermission.ManageServer) > 0 && (
<div className="actions"> <div className="actions">
<Link to={`/server/${server._id}/settings`}> <Link to={`/server/${server._id}/settings`}>
<IconButton> <IconButton>
<Cog size={24} /> <Cog size={24} />
</IconButton> </IconButton>
</Link> </Link>
</div> </div>
)} )}
</Header> </Header>
); );
} });
import { Server } from "revolt.js/dist/api/objects"; import { observer } from "mobx-react-lite";
import { Server } from "revolt.js/dist/maps/Servers";
import styled from "styled-components"; import styled from "styled-components";
import { useContext } from "preact/hooks"; import { useContext } from "preact/hooks";
...@@ -8,61 +9,60 @@ import { AppContext } from "../../context/revoltjs/RevoltClient"; ...@@ -8,61 +9,60 @@ import { AppContext } from "../../context/revoltjs/RevoltClient";
import { IconBaseProps, ImageIconBase } from "./IconBase"; import { IconBaseProps, ImageIconBase } from "./IconBase";
interface Props extends IconBaseProps<Server> { interface Props extends IconBaseProps<Server> {
server_name?: string; server_name?: string;
} }
const ServerText = styled.div` const ServerText = styled.div`
display: grid; display: grid;
padding: 0.2em; padding: 0.2em;
overflow: hidden; overflow: hidden;
border-radius: 50%; border-radius: 50%;
place-items: center; place-items: center;
color: var(--foreground); color: var(--foreground);
background: var(--primary-background); background: var(--primary-background);
`; `;
const fallback = "/assets/group.png"; // const fallback = "/assets/group.png";
export default function ServerIcon( export default observer(
props: Props & Omit<JSX.HTMLAttributes<HTMLImageElement>, keyof Props>, (
) { props: Props &
const client = useContext(AppContext); Omit<
JSX.HTMLAttributes<HTMLImageElement>,
keyof Props | "children" | "as"
>,
) => {
const client = useContext(AppContext);
const { const { target, attachment, size, animate, server_name, ...imgProps } =
target, props;
attachment, const iconURL = client.generateFileURL(
size, target?.icon ?? attachment,
animate, { max_side: 256 },
server_name, animate,
children, );
as,
...imgProps
} = props;
const iconURL = client.generateFileURL(
target?.icon ?? attachment,
{ max_side: 256 },
animate,
);
if (typeof iconURL === "undefined") { if (typeof iconURL === "undefined") {
const name = target?.name ?? server_name ?? ""; const name = target?.name ?? server_name ?? "";
return ( return (
<ServerText style={{ width: size, height: size }}> <ServerText style={{ width: size, height: size }}>
{name {name
.split(" ") .split(" ")
.map((x) => x[0]) .map((x) => x[0])
.filter((x) => typeof x !== "undefined")} .filter((x) => typeof x !== "undefined")}
</ServerText> </ServerText>
); );
} }
return ( return (
<ImageIconBase <ImageIconBase
{...imgProps} {...imgProps}
width={size} width={size}
height={size} height={size}
aria-hidden="true" src={iconURL}
src={iconURL} loading="lazy"
/> aria-hidden="true"
); />
} );
},
);
This diff is collapsed.
This diff is collapsed.
import styled from "styled-components";
import { Text } from "preact-i18n";
const Base = styled.div`
display: grid;
place-items: center;
z-index: 1;
grid-area: 1 / 1;
cursor: pointer;
user-select: none;
text-transform: uppercase;
span {
padding: 8px;
color: var(--foreground);
background: var(--primary-background);
border-radius: calc(var(--border-radius) * 4);
}
`;
interface Props {
set: (v: boolean) => void;
}
export default function Spoiler({ set }: Props) {
return (
<Base onClick={() => set(false)}>
<span>
<Text id="app.main.channel.misc.spoiler_attachment" />
</span>
</Base>
);
}