Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
58250c3
fix: Massively improve voice call PIP drag performance & support touc…
Pecacheu Mar 30, 2026
fd01909
fix: Cleaner code for previous fix, avoiding unnecessary redraws
Pecacheu Mar 31, 2026
df918bc
refactor: VoiceCallCardActions
Pecacheu Mar 31, 2026
085ce19
fix: Adjust to Voice state changes in PIP
Pecacheu Apr 4, 2026
e0a9ff5
fix: Show video in PIP player when focused
Pecacheu Apr 4, 2026
b2489a6
fix: Improve mobile UI handling for 835
Pecacheu Apr 4, 2026
68665ec
fix: Use transform instead of top/left for PIP move to ensure GPU render
Pecacheu Apr 4, 2026
c32191f
refactor: Replace AutoSizer with ResizeObserver
Pecacheu Apr 12, 2026
db4647d
fix: Fix call card offset misalignment
Pecacheu Apr 12, 2026
3d947b4
refactor: Remove PR TODOs
Pecacheu May 7, 2026
0664ac0
fix: Change touchToMouse code to a more general solution (can be move…
Pecacheu May 7, 2026
6df9fe6
fix: Bug where PIP state didn't update when switching DM channels ins…
Pecacheu May 7, 2026
ef5d4ad
fix: Dim background behind muted icons
Pecacheu May 8, 2026
35e2345
fix: Shrink home-screen flex layout to single-column for mobile
Pecacheu Feb 14, 2026
3ee0d5a
fix: More mobile UI fixes
Pecacheu Feb 14, 2026
5959c9a
fix: Mobile UI marches onwards
Pecacheu Feb 15, 2026
bd20947
fix: Add back button to Channel & Server settings
Pecacheu Feb 15, 2026
16739bb
fix: Simplified CSS
Pecacheu Feb 15, 2026
12aaa2b
fix: Move the CSS again & misc
Pecacheu May 8, 2026
f091f69
feat: Mobile UI
Pecacheu Feb 17, 2026
cff524b
feat: Slide that SlideDrawer real smooth-like
Pecacheu Feb 18, 2026
a9244cf
fix: Enable mobile autocorrect and autocapitalize on text input
Pecacheu Feb 18, 2026
74c010d
fix: Un-round them corners for portrait phone view
Pecacheu Feb 19, 2026
1c8a50b
fix: Refine SlideDrawer inertia detection by always recalculating fin…
Pecacheu Mar 14, 2026
6ec0980
fix: Sensible margains for modals on mobile to prevent weird scroll b…
Pecacheu Feb 21, 2026
d01ea04
fix: Small chance that two modals have the same ID using Math.random …
Pecacheu Feb 22, 2026
2b1a04c
fix: Clicking channels/DMs/settings buttons opens slide drawer on mobile
Pecacheu Feb 22, 2026
2dbef9e
fix: Cease this madness
Pecacheu Feb 22, 2026
fb6c98d
fix: Disable context menu when editing message, so you can accept OS …
Pecacheu Feb 23, 2026
1231bf6
fix: Add shorthand names for some emojis
Pecacheu Feb 27, 2026
23a8202
fix: Off-center loading progress wheel is now nice n centered
Pecacheu Feb 27, 2026
af928a6
feat: Adding a react button to the context menu was harder than antic…
Pecacheu Feb 28, 2026
fe6eb06
fix: Prettier format
Pecacheu Mar 3, 2026
1f548c7
fix: Reset floating touch timer to prevent overlapping timer bug
Pecacheu May 9, 2026
fdd13fd
fix: Misc emoji and message box fixes
Pecacheu May 8, 2026
04a9884
fix: Misc console warnings
Pecacheu Mar 14, 2026
476ab50
fix: Make reactPicker optional to make method signatures backward com…
Pecacheu Mar 5, 2026
22c7ea7
fix: Use text cursor on mdui-text-field
Pecacheu Mar 8, 2026
3e80f41
fix: Make class naming scheme compatible with #791
Pecacheu Mar 14, 2026
643d3c7
fix: Appearance menu and role editor color pane clipping past edge on…
Pecacheu Mar 19, 2026
de76fa8
fix: Adjust channel bar bottom margin to match top margin
Pecacheu Mar 29, 2026
f162aaf
feat: Add reactive signals to SlideDrawer, will come in handy in othe…
Pecacheu Mar 30, 2026
40af7ec
fix: Use undefined rather than null for consistency
Pecacheu Apr 4, 2026
4d74dae
fix: Fixes for VoiceCallCardPiP
Pecacheu May 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,11 @@
"editor.insertSpaces": true,
"editor.tabSize": 2,
// Nix environment settings
"nixEnvSelector.nixFile": "${workspaceFolder}/default.nix"
"nixEnvSelector.nixFile": "${workspaceFolder}/default.nix",
"search.exclude": {
"**/coverage": true,
"**/dist": true,
"**/i18n": true,
"**/styled-system": true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useState } from "@revolt/state";
import {
Attachment,
Avatar,
CompositionMediaPicker,
Embed,
MessageContainer,
MessageReply,
Expand All @@ -30,6 +31,8 @@ import {
floatingUserMenusFromMessage,
} from "../../../menus/UserContextMenu";

import { startsWithPackPUA } from "@revolt/markdown/emoji/UnicodeEmoji";
import { MediaPickerProps } from "@revolt/ui/components/features/messaging/composition/picker/CompositionMediaPicker";
import { EditMessage } from "./EditMessage";

/**
Expand Down Expand Up @@ -75,6 +78,8 @@ export function Message(props: Props) {
const client = useClient();

const [isHovering, setIsHovering] = createSignal(false);
const [reactPicker, setReactPicker] = createSignal<MediaPickerProps>();
let msgRef;

/**
* Determine whether this message only contains a GIF
Expand Down Expand Up @@ -104,6 +109,8 @@ export function Message(props: Props) {

return (
<MessageContainer
ref={msgRef}
reactPicker={reactPicker}
message={props.message}
onHover={setIsHovering}
username={
Expand Down Expand Up @@ -135,7 +142,16 @@ export function Message(props: Props) {
/>
</div>
}
contextMenu={() => <MessageContextMenu message={props.message} />}
contextMenu={
props.editing
? undefined
: () => (
<MessageContextMenu
message={props.message}
reactPicker={reactPicker}
/>
)
}
timestamp={props.message.createdAt}
edited={props.message.editedAt}
mentioned={props.message.mentioned}
Expand Down Expand Up @@ -257,6 +273,29 @@ export function Message(props: Props) {
</Match>
}
>
<CompositionMediaPicker
onMessage={(content) =>
props.message?.channel?.sendMessage({
content,
replies: [{ id: props.message.id, mention: true }],
})
}
onTextReplacement={(emoji) =>
react(
emoji.startsWith(":")
? emoji.slice(1, emoji.length - 1)
: startsWithPackPUA(emoji)
? emoji.slice(1)
: emoji,
)
}
>
{(trigProps) => {
trigProps.ref(msgRef);
setReactPicker(trigProps);
return <></>;
}}
</CompositionMediaPicker>
<Show when={props.message.systemMessage}>
<SystemMessage
systemMessage={props.message.systemMessage!}
Expand All @@ -282,30 +321,25 @@ export function Message(props: Props) {
</BreakText>
</Match>
</Switch>
<Show when={props.message.attachments}>
<For each={props.message.attachments}>
{(attachment) => (
<Attachment message={props.message} file={attachment} />
)}
</For>
</Show>
<Show when={props.message.embeds}>
<For each={props.message.embeds}>
{(embed) => <Embed embed={embed} />}
</For>
</Show>
<For each={props.message.attachments}>
{(attachment) => (
<Attachment
message={props.message}
file={attachment}
reactPicker={reactPicker}
/>
)}
</For>
<For each={props.message.embeds}>
{(embed) => <Embed embed={embed} />}
</For>
<Reactions
reactions={props.message.reactions as never as Map<string, Set<string>>}
interactions={props.message.interactions}
userId={client().user!.id}
addReaction={react}
removeReaction={unreact}
sendGIF={(content) =>
props.message?.channel?.sendMessage({
content,
replies: [{ id: props.message.id, mention: true }],
})
}
reactPicker={reactPicker}
/>
</MessageContainer>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ export function Messages(props: Props) {
// If we're not at the end, restore scroll position
if (existingState && !existingState.atEnd) {
setTimeout(() =>
listRef!.scrollTo({
listRef?.scrollTo({
top: existingState.scrollTop!,
behavior: "instant",
}),
Expand All @@ -290,7 +290,7 @@ export function Messages(props: Props) {
// Or... reset scroll to the end
else if (atEnd()) {
setTimeout(() =>
listRef!.scrollTo({
listRef?.scrollTo({
top: 9999999,
behavior: "instant",
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ChannelPermissionsEditor } from "./channel/permissions/ChannelPermissio
import { ChannelPermissionsOverview } from "./channel/permissions/ChannelPermissionsOverview";
import { ViewWebhook } from "./channel/webhooks/ViewWebhook";
import { WebhooksList } from "./channel/webhooks/WebhooksList";
import { BackCard } from "./user/_AccountCard";

const Config: SettingsConfiguration<Channel> = {
/**
Expand Down Expand Up @@ -98,11 +99,12 @@ const Config: SettingsConfiguration<Channel> = {
* Generate list of categories / entries for channel settings
* @returns List
*/
list(channel) {
list(channel, onClose) {
const { openModal } = useModals();

return {
context: channel,
prepend: <BackCard onClose={onClose} />,
entries: [
{
title: <TextWithEmoji content={channel.name} />,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { EmojiList } from "./server/emojis/EmojiList";
import { ListServerInvites } from "./server/invites/ListServerInvites";
import { ServerRoleEditor } from "./server/roles/ServerRoleEditor";
import { ServerRoleOverview } from "./server/roles/ServerRoleOverview";
import { BackCard } from "./user/_AccountCard";

const Config: SettingsConfiguration<Server> = {
/**
Expand Down Expand Up @@ -89,12 +90,13 @@ const Config: SettingsConfiguration<Server> = {
* Generate list of categories / entries for server settings
* @returns List
*/
list(server) {
list(server, onClose) {
const user = useUser();
const { openModal } = useModals();

return {
context: server,
prepend: <BackCard onClose={onClose} />,
entries: [
{
title: <TextWithEmoji content={server.name} />,
Expand Down
16 changes: 12 additions & 4 deletions packages/client/components/app/interface/settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
createContext,
createMemo,
createSignal,
Setter,
untrack,
useContext,
} from "solid-js";
Expand All @@ -25,6 +26,8 @@ export interface SettingsProps {
* Settings context
*/
context: never;

contentRef: Setter<HTMLDivElement | undefined>;
}

/**
Expand Down Expand Up @@ -89,11 +92,16 @@ export function Settings(props: SettingsProps & SettingsConfiguration<never>) {
navigate,
}}
>
<MemoisedList context={props.context} list={props.list}>
<MemoisedList
context={props.context}
list={props.list}
onClose={props.onClose}
>
{(list) => (
<>
<SettingsSidebar list={list} page={page} setPage={setPage} />
<SettingsContent
ref={props.contentRef}
page={page}
list={list}
title={props.title}
Expand Down Expand Up @@ -156,14 +164,14 @@ export function Settings(props: SettingsProps & SettingsConfiguration<never>) {
*/
function MemoisedList(props: {
context: never;
list: (context: never) => SettingsList<unknown>;
onClose?: () => void;
list: (context: never, onClose?: () => void) => SettingsList<unknown>;
children: (list: Accessor<SettingsList<unknown>>) => JSX.Element;
}) {
/**
* Generate list of categories / links
*/
const list = createMemo(() => props.list(props.context));

const list = createMemo(() => props.list(props.context, props.onClose));
return <>{props.children(list)}</>;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { Feedback } from "./user/Feedback";
import { LanguageSettings } from "./user/Language";
import Native from "./user/Native";
import { Sessions } from "./user/Sessions";
import { AccountCard } from "./user/_AccountCard";
import { AccountCard, BackCard } from "./user/_AccountCard";
import { AppearanceMenu } from "./user/appearance";
import { MyBots, ViewBot } from "./user/bots";
import { EditProfile } from "./user/profile";
Expand Down Expand Up @@ -105,14 +105,15 @@ const Config: SettingsConfiguration<{ server: Server }> = {
* Generate list of categories / entries for client settings
* @returns List
*/
list() {
list(_, onClose) {
const { pop } = useModals();
const { logout } = useClientLifecycle();

return {
context: null!,
prepend: (
<Column gap="s">
<BackCard onClose={onClose} />
<AccountCard />
<div />
</Column>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Accessor, JSX, Show } from "solid-js";
import { Accessor, JSX, Setter, Show } from "solid-js";

import { css, cva } from "styled-system/css";
import { styled } from "styled-system/jsx";
Expand All @@ -19,34 +19,33 @@ export function SettingsContent(props: {
list: Accessor<SettingsList<unknown>>;
title: (ctx: SettingsList<never>, key: string) => string;
page: Accessor<string | undefined>;
ref: Setter<HTMLDivElement | undefined>;
}) {
const { navigate } = useSettingsNavigation();

return (
<div
use:scrollable={{
class: base(),
}}
>
<div ref={props.ref} class="settings" use:scrollable={{ class: base() }}>
<Show when={props.page()}>
<InnerContent>
<InnerContent class="settings_cont">
<InnerColumn>
<Text class="title" size="large">
<Breadcrumbs
elements={props.page()!.split("/")}
renderElement={(key) =>
props.title(props.list() as SettingsList<never>, key)
}
navigate={(keys) => navigate(keys.join("/"))}
/>
</Text>
<Show when={props.page() !== "account"}>
<Text class="title" size="large">
<Breadcrumbs
elements={props.page()!.split("/")}
renderElement={(key) =>
props.title(props.list() as SettingsList<never>, key)
}
navigate={(keys) => navigate(keys.join("/"))}
/>
</Text>
</Show>
{props.children}
<div class={css({ minHeight: "80px" })} />
</InnerColumn>
</InnerContent>
</Show>
<Show when={props.onClose}>
<CloseAction>
<CloseAction class="close">
<IconButton variant="tonal" onPress={props.onClose}>
<MdClose />
</IconButton>
Expand Down Expand Up @@ -121,7 +120,7 @@ const CloseAction = styled("div", {
marginTop: "4px",
display: "flex",
justifyContent: "center",
width: "36px",
width: "40px",
fontWeight: 600,
color: "var(--md-sys-color-on-surface)",
fontSize: "0.75rem",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,28 @@ import {
*/
export function SettingsSidebar(props: {
list: Accessor<SettingsList<unknown>>;

setPage: Setter<string | undefined>;
page: Accessor<string | undefined>;
}) {
const { navigate } = useSettingsNavigation();
const list = props.list();

/**
* Select first page on load
*/
onMount(() => {
if (!props.page()) {
props.setPage(props.list().entries[0].entries[0].id);
props.setPage(list.entries[0].entries[0].id);
}
});

return (
<Base>
<Base class="settings_sidebar">
<div use:invisibleScrollable>
<Content>
<Content class="content">
<Column gap="lg">
{props.list().prepend}
<For each={props.list().entries}>
{list.prepend}
<For each={list.entries}>
{(category) => (
<Show when={!category.hidden}>
<Column>
Expand Down Expand Up @@ -87,7 +87,7 @@ export function SettingsSidebar(props: {
</Show>
)}
</For>
{props.list().append}
{list.append}
</Column>
</Content>
</div>
Expand All @@ -104,6 +104,7 @@ const Base = styled("div", {
flex: "1 0 218px",
paddingLeft: "8px",
justifyContent: "flex-end",
height: "100%",
},
});

Expand Down
Loading
Loading