diff --git a/README.md b/README.md
index daf71228..f1b71d9a 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
RSCord Server
## About
-This is based off spacebar, however this is not spacebar anymore because of the amount of changes done to the source code.
+This is based off Spacebar, however this is not Spacebar anymore because of the amount of changes done to the source code.
This repository contains:
@@ -17,8 +17,7 @@ This repository contains:
## [Documentation](https://docs.spacebar.chat)
-And with documentation on how to set up your own server [here](https://docs.spacebar.chat/setup/server), and docs about bots [here](https://docs.spacebar.chat/setup/bots/)
+Documentation on how to set up your own server is [here](https://docs.spacebar.chat/setup/server), and docs about bots are [here](https://docs.spacebar.chat/setup/bots/)
-## Clients
-
-It's located at localhost:3001, the client date is from the 1st of May 2021. There are more clients such as the patched up native one and the mobile one murdle made.
+## Frontend
+It's located at localhost:3001, the client date is July 2022. It also uses a custom client mod to add QoL features that were not present in the old Discord frontend.
\ No newline at end of file
diff --git a/assets/public/custom/utils.js b/assets/public/custom/utils.js
index 211cb036..4582319d 100644
--- a/assets/public/custom/utils.js
+++ b/assets/public/custom/utils.js
@@ -1,3 +1,9 @@
+const CONFIG_KEY = "rscord_config";
+const DEFAULT_CONFIG = { customCss: "", revertStatusIcons: false };
+
+window.AUTH_TOKEN = null;
+window.localStorage_ = localStorage;
+
function urlBase64ToUint8Array(base64String) {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding)
@@ -14,6 +20,24 @@ function urlBase64ToUint8Array(base64String) {
return outputArray;
}
+function loadConfig() {
+ try {
+ return {
+ ...DEFAULT_CONFIG,
+ ...JSON.parse(localStorage_.getItem(CONFIG_KEY) || "{}")
+ };
+ } catch {
+ return { ...DEFAULT_CONFIG };
+ }
+}
+
+function saveConfig(patch) {
+ const config = loadConfig();
+ const updated = { ...config, ...patch };
+ localStorage_.setItem(CONFIG_KEY, JSON.stringify(updated));
+ return updated;
+}
+
let proxied = window.XMLHttpRequest.prototype.setRequestHeader;
window.XMLHttpRequest.prototype.setRequestHeader = function() {
if (arguments[0] === "Authorization") {
@@ -44,12 +68,11 @@ window.CSS_CLASSES = {
userInfoBody: "userInfoBody-1zgAd0 markup-eYLPri clamped-2ZePhX",
userInfoSectionHeader: "defaultColor-24IHKz eyebrow-Ejf06y defaultColor-HXu-5n userInfoSectionHeader-2mYYun",
userInfoText: "userInfoText-2MFCmH markup-eYLPri clamped-2ZePhX",
+ userInfoSection: "userInfoSection-3her-v",
title: "colorStandard-1Xxp1s size14-k_3Hy4 h1-34Txb0 title-3hptVQ defaultColor-2cKwKo defaultMarginh1-EURXsm",
miniTitle: "colorStandard-1Xxp1s size14-k_3Hy4 h5-2RwDNl title-3hptVQ title-1HgbhV",
hidden: "hidden-27eifz",
hamburger: "btnHamburger-3GF0_5",
- textInput: "inputDefault-3FGxgL input-2g-os5"
-};
-
-window.AUTH_TOKEN = null;
-window.localStorage_ = localStorage;
\ No newline at end of file
+ textInput: "inputDefault-3FGxgL input-2g-os5",
+ nitroBadge: ".clickable-1knRMS[aria-label]",
+};
\ No newline at end of file
diff --git a/assets/public/custom/web/main.js b/assets/public/custom/web/main.js
index 87ceb7ab..9f26d0b2 100644
--- a/assets/public/custom/web/main.js
+++ b/assets/public/custom/web/main.js
@@ -5,9 +5,6 @@
const CUSTOM_CSS_ID = "custom-css";
const CUSTOM_CSS_INPUT_ID = "custom-css-input";
-
- const CONFIG_KEY = "rscord_config";
- const DEFAULT_CONFIG = { customCss: "", revertStatusIcons: false };
const STATUS_COLOR_MAP = {
"hsl(38, calc(var(--saturation-factor, 1) * 95.7%), 54.1%)": "#FAA61A", // Idle (yellow)
@@ -29,69 +26,63 @@
`;
- function loadConfig() {
- try {
- return {
- ...DEFAULT_CONFIG,
- ...JSON.parse(localStorage_.getItem(CONFIG_KEY) || "{}")
- };
- } catch {
- return { ...DEFAULT_CONFIG };
- }
- }
-
- function saveConfig(patch) {
- const config = loadConfig();
- const updated = { ...config, ...patch };
- localStorage_.setItem(CONFIG_KEY, JSON.stringify(updated));
- return updated;
- }
-
- // this is a shitty patch
- // you can just grab this from the request but i do not care
function addJoinDates() {
- if (document.getElementById("join-date")) return;
+ if (document.querySelector("[data-join-date]")) return;
- const infoSection = document.querySelector(".userInfoSection-2u2hir > :has(+ .note-3M15gE)")
- const firstBody = document.querySelector(".userInfoSection-3her-v > div");
- if (!infoSection && !firstBody) return;
+ const nitroBadge = document.querySelector(CSS_CLASSES.nitroBadge);
+ const date = nitroBadge?.getAttribute("aria-label")?.replace("Subscriber since ", "");
+ if (!date) return;
- const nitroBadge = document.querySelector(".clickable-1knRMS[aria-label]");
- if (!nitroBadge) return;
-
- const nitroText = nitroBadge.getAttribute("aria-label");
- if (!nitroText) return;
+ const isCompact = !!document.querySelector("h3.bodyTitle-2Az3VQ");
+ const anchor = [...document.querySelectorAll("h3")].find(h =>
+ (h.className.includes("bodyTitle") && h.textContent.includes("Role")) ||
+ h.textContent.trim() === "Note"
+ );
+ if (!anchor) return;
const infoText = document.createElement("div");
- infoText.id = "join-date";
- infoText.className = infoSection ? CSS_CLASSES.userInfoSectionHeader : CSS_CLASSES.userInfoTitle;
+ infoText.className = isCompact ? CSS_CLASSES.userInfoTitle : CSS_CLASSES.userInfoSectionHeader;
infoText.textContent = "Member since";
infoText.style.color = "var(--header-secondary)";
- infoText.style.marginTop = "10px";
+ infoText.dataset.joinDate = "title";
const dateText = document.createElement("div");
- dateText.id = "join-date";
- dateText.className = infoSection ? CSS_CLASSES.userInfoText : CSS_CLASSES.userInfoBody;
- dateText.textContent = nitroText.replace("Subscriber since ", "");
+ dateText.className = isCompact ? CSS_CLASSES.userInfoBody : CSS_CLASSES.userInfoText;
+ dateText.textContent = date;
+ dateText.dataset.joinDate = "value";
- infoSection && infoSection.insertAdjacentElement("beforebegin", infoText);
- firstBody && firstBody.insertAdjacentElement("afterend", infoText);
- infoText.insertAdjacentElement("afterend", dateText);
+ if (isCompact) {
+ let infoSection = anchor.previousElementSibling;
+ const isNewSection = !infoSection;
+
+ if (isNewSection) {
+ infoSection = document.createElement("div");
+ infoSection.className = CSS_CLASSES.userInfoSection;
+ anchor.parentNode.insertBefore(infoSection, anchor);
+ }
+
+ infoText.style.marginTop = isNewSection ? "0px" : "5px";
+ infoSection.append(infoText, dateText);
+ } else {
+ anchor.parentNode.insertBefore(infoText, anchor);
+ anchor.parentNode.insertBefore(dateText, anchor);
+ }
}
async function addSwitches(container) {
const config = loadConfig();
-
+ const pushRegistered = await isPushRegistered();
+
container.appendChild(createSwitch(
"Push Notifications",
"Sends you notifications even when you close the app",
"push-notifications",
- await isPushRegistered(),
+ pushRegistered,
async (checked) => {
const publicKey = window.GLOBAL_ENV.VAPID_KEY;
if (!publicKey) return false;
try {
- checked ? await registerPush(publicKey) : await unregisterPush();
+ await (checked ? registerPush(publicKey) : unregisterPush());
return true;
} catch {
return false;