Compare commits

...

8 commits

Author SHA1 Message Date
Declan Chidlow
b2985ae155
Merge cd4d8eb96d into 5de18192b2 2024-10-27 15:52:13 -07:00
Paul Makles
5de18192b2
chore: delete .env.production 2024-10-27 22:31:42 +00:00
Paul Makles
ef4218d12b
merge branch: 'insert/member-subscriptions' 2024-10-27 22:00:22 +00:00
Paul Makles
df4f6578f7
feat: add session token to file uploads 2024-10-27 21:59:16 +00:00
Declan Chidlow
cd4d8eb96d
Merge branch 'revoltchat:master' into master 2024-08-28 10:00:32 +08:00
Paul Makles
c972e6813f
fix: should always call subscribe 2024-06-19 18:16:30 +01:00
Paul Makles
61304f18c2
feat: implement support for Subscribe event 2024-06-19 17:40:59 +01:00
Declan Chidlow
ffee147aed Fix ability to set appearence of Focus status and remove unused references to streaming status 2024-06-05 15:33:48 +08:00
16 changed files with 139 additions and 58 deletions

4
.env
View file

@ -1,5 +1,5 @@
# VITE_API_URL=https://api.revolt.chat
VITE_API_URL=https://app.revolt.chat/api
# VITE_API_URL=https://app.revolt.chat/api
# VITE_API_URL=http://local.revolt.chat:8000
# VITE_API_URL=https://revolt.chat/api
VITE_API_URL=https://revolt.chat/api
VITE_THEMES_URL=https://themes.revolt.chat

View file

@ -1,10 +1,10 @@
import { Plugin } from "unified";
import { visit } from "unist-util-visit";
export const remarkHtmlToText: Plugin = () => {
return (tree) => {
visit(tree, "html", (node: { type: string; value: string }) => {
node.type = "text";
});
};
};
import { Plugin } from "unified";
import { visit } from "unist-util-visit";
export const remarkHtmlToText: Plugin = () => {
return (tree) => {
visit(tree, "html", (node: { type: string; value: string }) => {
node.type = "text";
});
};
};

View file

@ -106,9 +106,9 @@ export default observer(() => {
"scrollbar-thumb",
"scrollbar-track",
"status-online",
"status-away",
"status-idle",
"status-focus",
"status-busy",
"status-streaming",
"status-invisible",
"success",
"warning",

View file

@ -67,13 +67,12 @@ export function PermissionSelect({
}
return "Neutral";
}
if (Long.fromNumber(value).and(permission).eq(permission)) {
return "Allow";
}
}
if (Long.fromNumber(value).and(permission).eq(permission)) {
return "Allow";
}
return "Neutral";
return "Neutral";
}, [value]);
function onSwitch(state: State) {

View file

@ -30,10 +30,9 @@ export type Variables =
| "tertiary-foreground"
| "tooltip"
| "status-online"
| "status-away"
| "status-idle"
| "status-focus"
| "status-busy"
| "status-streaming"
| "status-invisible";
// While this isn't used, it'd be good to keep this up to date as a reference or for future use
@ -283,10 +282,9 @@ export const PRESETS: Record<string, Theme> = {
"tertiary-background": "#4D4D4D",
"tertiary-foreground": "#3a3a3a",
"status-online": "#3ABF7E",
"status-away": "#F39F00",
"status-idle": "#F39F00",
"status-focus": "#4799F0",
"status-busy": "#F84848",
"status-streaming": "#977EFF",
"status-invisible": "#A5A5A5",
},
dark: {
@ -311,10 +309,9 @@ export const PRESETS: Record<string, Theme> = {
"tertiary-background": "#4D4D4D",
"tertiary-foreground": "#848484",
"status-online": "#3ABF7E",
"status-away": "#F39F00",
"status-idle": "#F39F00",
"status-focus": "#4799F0",
"status-busy": "#F84848",
"status-streaming": "#977EFF",
"status-invisible": "#A5A5A5",
},
};

View file

@ -10,7 +10,7 @@ export function takeError(error: any): string {
case 429:
return "TooManyRequests";
case 401:
return "Unauthorized"
return "Unauthorized";
case 403:
return "Forbidden";
default:

View file

@ -12,7 +12,7 @@ import { IconButton, Preloader } from "@revoltchat/ui";
import { determineFileSize } from "../../../../lib/fileSize";
import { modalController } from "../../../modals/ModalController";
import { useClient } from "../../ClientController";
import { clientController, useClient } from "../../ClientController";
import { takeError } from "../error";
type BehaviourType =
@ -67,9 +67,16 @@ export async function uploadFile(
const formData = new FormData();
formData.append("file", file);
const client = clientController.getActiveSession()?.client;
const sesToken =
typeof client?.session === "string"
? client.session
: client?.session?.token;
const res = await Axios.post(`${autumnURL}/${tag}`, formData, {
headers: {
"Content-Type": "multipart/form-data",
"X-Session-Token": sesToken,
},
...config,
});

View file

@ -7,10 +7,10 @@ import { ModalForm } from "@revoltchat/ui";
import { noopAsync } from "../../../lib/js";
import { IS_REVOLT } from "../../../version";
import { takeError } from "../../client/jsx/error";
import { modalController } from "../ModalController";
import { ModalProps } from "../types";
import { IS_REVOLT } from "../../../version";
/**
* Code block which displays invite
@ -79,7 +79,9 @@ export default function CreateInvite({
children: <Text id="app.context_menu.copy_link" />,
onClick: () =>
modalController.writeText(
IS_REVOLT ? `https://rvlt.gg/${code}` : `${window.location.host}/invite/${code}`
IS_REVOLT
? `https://rvlt.gg/${code}`
: `${window.location.host}/invite/${code}`,
),
},
]}

View file

@ -2,29 +2,32 @@ import { ChevronRight, Trash } from "@styled-icons/boxicons-regular";
import { Cog, UserVoice } from "@styled-icons/boxicons-solid";
import { isFirefox } from "react-device-detect";
import { useHistory } from "react-router-dom";
import { Channel, Message, Server, User, API, Permission, UserPermission, Member } from "revolt.js";
import {
Channel,
Message,
Server,
User,
API,
Permission,
UserPermission,
Member,
} from "revolt.js";
import { ContextMenuWithData, MenuItem, openContextMenu } from "preact-context-menu";
import {
ContextMenuWithData,
MenuItem,
openContextMenu,
} from "preact-context-menu";
import { Text } from "preact-i18n";
import { Column, IconButton, LineDivider } from "@revoltchat/ui";
import { useApplicationState } from "../mobx/State";
import { QueuedMessage } from "../mobx/stores/MessageQueue";
import { NotificationState } from "../mobx/stores/NotificationOptions";
import CMNotifications from "./contextmenu/CMNotifications";
import Tooltip from "../components/common/Tooltip";
import UserStatus from "../components/common/user/UserStatus";
import { useSession } from "../controllers/client/ClientController";
@ -33,7 +36,6 @@ import { modalController } from "../controllers/modals/ModalController";
import { internalEmit } from "./eventEmitter";
import { getRenderer } from "./renderer/Singleton";
interface ContextMenuData {
user?: string;
server?: string;
@ -1293,4 +1295,4 @@ export default function ContextMenus() {
<CMNotifications />
</>
);
}
}

View file

@ -82,11 +82,10 @@ export default class SAudio {
getAudio(path: string) {
if (this.cache.has(path)) {
return this.cache.get(path)!;
}
const el = new Audio(path);
this.cache.set(path, el);
return el;
}
const el = new Audio(path);
this.cache.set(path, el);
return el;
}
loadCache() {
@ -100,7 +99,7 @@ export default class SAudio {
try {
audio.play();
} catch (err) {
console.error("Hit error while playing", `${sound }:`, err);
console.error("Hit error while playing", `${sound}:`, err);
}
}
}

View file

@ -110,7 +110,7 @@ export default class STheme {
for (const key of Object.keys(variables)) {
const value = variables[key];
if (typeof value === "string") {
variables[`${key }-contrast`] = getContrastingColour(value);
variables[`${key}-contrast`] = getContrastingColour(value);
}
}

View file

@ -1,5 +1,6 @@
import { Hash } from "@styled-icons/boxicons-regular";
import { Ghost } from "@styled-icons/boxicons-solid";
import dayjs from "dayjs";
import { reaction } from "mobx";
import { observer } from "mobx-react-lite";
import { Redirect, useParams } from "react-router-dom";
@ -163,6 +164,7 @@ const TextChannel = observer(({ channel }: { channel: ChannelI }) => {
const checkUnread = () =>
channel.unread &&
document.hasFocus() &&
channel.client.unreads!.markRead(
channel._id,
channel.last_message_id!,
@ -176,6 +178,46 @@ const TextChannel = observer(({ channel }: { channel: ChannelI }) => {
);
}, [channel]);
useEffect(() => {
let lastSubscribed: number | undefined;
function subscribe() {
if (document.hasFocus()) {
if (
!lastSubscribed ||
dayjs().subtract(10, "minutes").isAfter(lastSubscribed)
) {
lastSubscribed = +new Date();
channel.server?.subscribe();
}
}
}
// Trigger logic every minute
const subTimer = setInterval(subscribe, 60e3);
subscribe();
function onFocus() {
// Mark channel as read if it's unread
if (channel.unread) {
channel.client.unreads!.markRead(
channel._id,
channel.last_message_id!,
true,
);
}
// Subscribe to channel if expired
subscribe();
}
addEventListener("focus", onFocus);
return () => {
removeEventListener("focus", onFocus);
clearInterval(subTimer);
};
}, [channel]);
return (
<AgeGate
type="channel"

View file

@ -51,7 +51,7 @@ export default observer(() => {
state.settings.set("appearance:seasonal", !seasonalTheme);
const isDecember = !isTouchscreenDevice && new Date().getMonth() === 11;
const isOctober = !isTouchscreenDevice && new Date().getMonth() === 9
const isOctober = !isTouchscreenDevice && new Date().getMonth() === 9;
const snowflakes = useMemo(() => {
const flakes: string[] = [];

View file

@ -103,10 +103,43 @@ export const Members = ({ server }: Props) => {
const [query, setQuery] = useState("");
useEffect(() => {
server
.fetchMembers()
.then((data) => data.members)
.then(setData);
function fetch() {
server
.fetchMembers()
.then((data) => data.members)
.then(setData);
}
fetch();
// Members may be invalidated if we stop receiving events
// This is not very accurate, this should be tracked within
// revolt.js so we know the true validity.
let valid = true,
invalidationTimer: number;
function waitToInvalidate() {
invalidationTimer = setTimeout(() => {
valid = false;
}, 15 * 60e3) as never; // 15 minutes
}
function cancelInvalidation() {
if (!valid) {
fetch();
valid = true;
}
clearTimeout(invalidationTimer);
}
addEventListener("blur", waitToInvalidate);
addEventListener("focus", cancelInvalidation);
return () => {
removeEventListener("blur", waitToInvalidate);
removeEventListener("focus", cancelInvalidation);
};
}, [server, setData]);
const members = useMemo(

View file

@ -89,7 +89,7 @@
}
&.idle {
background: var(--status-away);
background: var(--status-idle);
}
&.focus {

View file

@ -29,7 +29,7 @@ precacheAndRoute(
}
for (const key of locale_keys) {
if (fn.startsWith(`${key }.`)) {
if (fn.startsWith(`${key}.`)) {
return false;
}
}