mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-10 23:23:04 -04:00
Visual Refresh
Co-Authored-By: sadan4 <117494111+sadan4@users.noreply.github.com> Co-Authored-By: doyle31 <abacubabacus@gmail.com> Co-Authored-By: iilwy <iilwy@omg.games> Co-Authored-By: Noa <164402463+nroggendorff@users.noreply.github.com> Co-Authored-By: rini c <rini@rinici.de> Co-Authored-By: Cassie <37855219+codef53@users.noreply.github.com> Co-Authored-By: jamesbt365 <moxy@mothoxi.de> Co-Authored-By: khcrysalis <97859147+khcrysalis@users.noreply.github.com> Co-Authored-By: nin0dev <75569739+nin0-dev@users.noreply.github.com>
This commit is contained in:
parent
fce4ffaabb
commit
ca4b63c386
23 changed files with 283 additions and 101 deletions
|
@ -49,10 +49,27 @@ if (IS_REPORTER) {
|
|||
}
|
||||
|
||||
async function syncSettings() {
|
||||
// Check if cloud auth exists for current user before attempting sync
|
||||
const hasCloudAuth = await dsGet("Vencord_cloudSecret");
|
||||
if (!hasCloudAuth) {
|
||||
if (Settings.cloud.authenticated) {
|
||||
// User switched to an account that isn't connected to cloud
|
||||
showNotification({
|
||||
title: "Cloud Settings",
|
||||
body: "Cloud sync was disabled because this account isn't connected to the Vencloud App. You can enable it again by connecting this account in Cloud Settings. (note: it will store your preferences separately)",
|
||||
color: "var(--yellow-360)",
|
||||
onClick: () => SettingsRouter.open("VencordCloud")
|
||||
});
|
||||
// Disable cloud sync globally
|
||||
Settings.cloud.authenticated = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// pre-check for local shared settings
|
||||
if (
|
||||
Settings.cloud.authenticated &&
|
||||
!await dsGet("Vencord_cloudSecret") // this has been enabled due to local settings share or some other bug
|
||||
!hasCloudAuth // this has been enabled due to local settings share or some other bug
|
||||
) {
|
||||
// show a notification letting them know and tell them how to fix it
|
||||
showNotification({
|
||||
|
|
|
@ -11,6 +11,11 @@
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.visual-refresh .vc-addon-card {
|
||||
background-color: var(--button-secondary-background);
|
||||
border: 1px solid var(--border-subtle);
|
||||
}
|
||||
|
||||
.vc-addon-card-disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
@ -21,6 +26,10 @@
|
|||
box-shadow: var(--elevation-high);
|
||||
}
|
||||
|
||||
.visual-refresh .vc-addon-card:hover {
|
||||
background-color: var(--button-secondary-background-hover);
|
||||
}
|
||||
|
||||
.vc-addon-header {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
|
|
|
@ -36,6 +36,14 @@
|
|||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.visual-refresh .vc-settings-quickActions-pill {
|
||||
background: var(--button-secondary-background);
|
||||
}
|
||||
|
||||
.visual-refresh .vc-settings-quickActions-pill:hover {
|
||||
background: var(--button-secondary-background-hover);
|
||||
}
|
||||
|
||||
.vc-settings-quickActions-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
|
|
|
@ -85,6 +85,11 @@ if (!IS_VANILLA) {
|
|||
options.backgroundColor = "#00000000";
|
||||
}
|
||||
|
||||
if (settings.disableMinSize) {
|
||||
options.minWidth = 0;
|
||||
options.minHeight = 0;
|
||||
}
|
||||
|
||||
const needsVibrancy = process.platform === "darwin" && settings.macosVibrancyStyle;
|
||||
|
||||
if (needsVibrancy) {
|
||||
|
@ -97,6 +102,12 @@ if (!IS_VANILLA) {
|
|||
process.env.DISCORD_PRELOAD = original;
|
||||
|
||||
super(options);
|
||||
|
||||
if (settings.disableMinSize) {
|
||||
// Disable the Electron call entirely so that Discord can't override it
|
||||
this.setMinimumSize = () => { };
|
||||
}
|
||||
|
||||
initIpc(this);
|
||||
} else super(options);
|
||||
}
|
||||
|
@ -115,16 +126,9 @@ if (!IS_VANILLA) {
|
|||
BrowserWindow
|
||||
};
|
||||
|
||||
// Patch appSettings to force enable devtools and optionally disable min size
|
||||
// Patch appSettings to force enable devtools
|
||||
onceDefined(global, "appSettings", s => {
|
||||
s.set("DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING", true);
|
||||
if (settings.disableMinSize) {
|
||||
s.set("MIN_WIDTH", 0);
|
||||
s.set("MIN_HEIGHT", 0);
|
||||
} else {
|
||||
s.set("MIN_WIDTH", 940);
|
||||
s.set("MIN_HEIGHT", 500);
|
||||
}
|
||||
});
|
||||
|
||||
process.env.DATA_DIR = join(app.getPath("userData"), "..", "Equicord");
|
||||
|
|
|
@ -32,7 +32,7 @@ export default definePlugin({
|
|||
{
|
||||
find: '"Message Username"',
|
||||
replacement: {
|
||||
match: /#{intl::GUILD_COMMUNICATION_DISABLED_BOTTOM_SHEET_TITLE}.+?}\)\)(?=\])/,
|
||||
match: /#{intl::GUILD_COMMUNICATION_DISABLED_BOTTOM_SHEET_TITLE}.+?renderPopout:.+?(?=\])/,
|
||||
replace: "$&,Vencord.Api.MessageDecorations.__addDecorationsToMessage(arguments[0])"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,8 +81,8 @@ export default definePlugin({
|
|||
replace: (_, rest, popoutProps, originalPopout, currentUser) => `${rest}$self.UserProfile({popoutProps:${popoutProps},currentUser:${currentUser},originalRenderPopout:()=>{${originalPopout}}})`
|
||||
},
|
||||
{
|
||||
match: /\.AVATAR,children:.+?(?=renderPopout:)/,
|
||||
replace: "$&onRequestClose:$self.onPopoutClose,"
|
||||
match: /(\.AVATAR,children:.+?onRequestClose:\(\)=>\{)/,
|
||||
replace: "$&onRequestClose:$self.onPopoutClose();"
|
||||
},
|
||||
{
|
||||
match: /(?<=#{intl::SET_STATUS}\),)/,
|
||||
|
|
|
@ -45,6 +45,7 @@ export default ErrorBoundary.wrap(guildsBarProps => {
|
|||
// Also display flex otherwise to fix scrolling
|
||||
const barStyle = {
|
||||
display: isFullscreen ? "none" : "flex",
|
||||
gridArea: "sidebar"
|
||||
} as CSSProperties;
|
||||
|
||||
if (!guilds || !settings.store.sidebarAnim) {
|
||||
|
|
|
@ -104,10 +104,14 @@ export const settings = definePluginSettings({
|
|||
}
|
||||
});
|
||||
|
||||
let cssMade = false;
|
||||
|
||||
const cssElementId = "VC-BetterFolders";
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterFolders",
|
||||
description: "Shows server folders on dedicated sidebar and adds folder related improvements",
|
||||
authors: [Devs.juby, Devs.AutumnVN, Devs.Nuckyz],
|
||||
authors: [Devs.juby, Devs.AutumnVN, Devs.Nuckyz, Devs.sadan],
|
||||
|
||||
settings,
|
||||
|
||||
|
@ -213,11 +217,18 @@ export default definePlugin({
|
|||
{
|
||||
find: "#{intl::DISCODO_DISABLED}",
|
||||
predicate: () => settings.store.closeAllHomeButton,
|
||||
replacement: {
|
||||
// Close all folders when clicking the home button
|
||||
match: /(?<=onClick:\(\)=>{)(?=.{0,300}"discodo")/,
|
||||
replace: "$self.closeFolders();"
|
||||
group: true,
|
||||
replacement: [
|
||||
{
|
||||
// Render the Better Folders sidebar
|
||||
match: /(?<=[[,])((?:!?\i&&)+)\(.{0,50}({className:\i\.guilds,themeOverride:\i})\)/g,
|
||||
replace: (_, conditions, props) => `${_},${conditions}$self.FolderSideBar({...${props}})`
|
||||
},
|
||||
{
|
||||
match: /(?<=className:)(\i\.base)(?=,)/,
|
||||
replace: "($self.makePatchedBaseCSS($1))"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
|
@ -265,6 +276,47 @@ export default definePlugin({
|
|||
}
|
||||
},
|
||||
|
||||
gridStyle: "vc-BetterFolders-sidebar-grid",
|
||||
makePatchedBaseCSS(className: string) {
|
||||
done: try {
|
||||
if (cssMade) break done;
|
||||
const rule = [...document.styleSheets]
|
||||
.flatMap(x => [...x.cssRules])
|
||||
// cant do includes because they have a `not ((grid-template-columns`
|
||||
// dumb type inference
|
||||
.filter((x): x is CSSSupportsRule => x instanceof CSSSupportsRule && x.conditionText.startsWith("(grid-template-columns"))
|
||||
.flatMap(x => [...x.cssRules])
|
||||
.filter(x => x instanceof CSSStyleRule)
|
||||
.find(x => x.selectorText.endsWith(`.${className}`));
|
||||
if (!rule) {
|
||||
console.error("Failed to find css rule for betterFolders");
|
||||
break done;
|
||||
}
|
||||
const areas = rule.style.gridTemplateAreas
|
||||
.split('" "')
|
||||
.map(x => x.replace(/"/g, "").split(" "));
|
||||
areas[0].splice(1, 0, areas[0][0]);
|
||||
areas[1].splice(1, 0, "sidebar");
|
||||
areas[2].splice(1, 0, "sidebar");
|
||||
const css = `
|
||||
.visual-refresh .${this.gridStyle} {
|
||||
grid-template-areas: ${areas.map(x => `"${x.join(" ")}"`).join(" ")};
|
||||
grid-template-columns: ${rule.style.gridTemplateColumns.replace(/(?<=guildsEnd\])/, " min-content [sidebarEnd]")};
|
||||
}
|
||||
`;
|
||||
const element = document.createElement("style");
|
||||
element.id = cssElementId;
|
||||
element.textContent = css;
|
||||
document.getElementById(cssElementId)?.remove();
|
||||
document.head.appendChild(element);
|
||||
cssMade = true;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return className;
|
||||
}
|
||||
return `${className} ${this.gridStyle}`;
|
||||
},
|
||||
|
||||
getGuildTree(isBetterFolders: boolean, originalTree: any, expandedFolderIds?: Set<any>) {
|
||||
return useMemo(() => {
|
||||
if (!isBetterFolders || expandedFolderIds == null) return originalTree;
|
||||
|
|
|
@ -120,7 +120,7 @@ export default definePlugin({
|
|||
|
||||
const styles = await getStyles();
|
||||
generateColorOffsets(styles);
|
||||
generateLightModeFixes(styles);
|
||||
// generateLightModeFixes(styles);
|
||||
},
|
||||
|
||||
stop() {
|
||||
|
@ -130,15 +130,12 @@ export default definePlugin({
|
|||
}
|
||||
});
|
||||
|
||||
const variableRegex = /(--primary-\d{3}-hsl):.*?(\S*)%;/g;
|
||||
const lightVariableRegex = /^--primary-[1-5]\d{2}-hsl/g;
|
||||
const darkVariableRegex = /^--primary-[5-9]\d{2}-hsl/g;
|
||||
const variableRegex = /(--neutral-\d{1,3}-hsl):.*?(\S*)%;/g;
|
||||
|
||||
// generates variables per theme by:
|
||||
// - matching regex (so we can limit what variables are included in light/dark theme, otherwise text becomes unreadable)
|
||||
// - offset from specified center (light/dark theme get different offsets because light uses 100 for background-primary, while dark uses 600)
|
||||
function genThemeSpecificOffsets(variableLightness: Record<string, number>, regex: RegExp, centerVariable: string): string {
|
||||
return Object.entries(variableLightness).filter(([key]) => key.search(regex) > -1)
|
||||
function genThemeSpecificOffsets(variableLightness: Record<string, number>, centerVariable: string): string {
|
||||
return Object.entries(variableLightness)
|
||||
.map(([key, lightness]) => {
|
||||
const lightnessOffset = lightness - variableLightness[centerVariable];
|
||||
const plusOrMinus = lightnessOffset >= 0 ? "+" : "-";
|
||||
|
@ -147,7 +144,6 @@ function genThemeSpecificOffsets(variableLightness: Record<string, number>, rege
|
|||
.join("\n");
|
||||
}
|
||||
|
||||
|
||||
function generateColorOffsets(styles) {
|
||||
const variableLightness = {} as Record<string, number>;
|
||||
|
||||
|
@ -160,50 +156,12 @@ function generateColorOffsets(styles) {
|
|||
}
|
||||
|
||||
createStyleSheet("clientThemeOffsets", [
|
||||
`.theme-light {\n ${genThemeSpecificOffsets(variableLightness, lightVariableRegex, "--primary-345-hsl")} \n}`,
|
||||
`.theme-dark {\n ${genThemeSpecificOffsets(variableLightness, darkVariableRegex, "--primary-600-hsl")} \n}`,
|
||||
// you can determine the "center color" by looking at the variable used by `--background-primary`
|
||||
`.theme-light {\n ${genThemeSpecificOffsets(variableLightness, "--neutral-2-hsl")} \n}`,
|
||||
`.theme-dark {\n ${genThemeSpecificOffsets(variableLightness, "--neutral-69-hsl")} \n}`,
|
||||
].join("\n\n"));
|
||||
}
|
||||
|
||||
function generateLightModeFixes(styles) {
|
||||
const groupLightUsesW500Regex = /\.theme-light[^{]*\{[^}]*var\(--white-500\)[^}]*}/gm;
|
||||
// get light capturing groups that mention --white-500
|
||||
const relevantStyles = [...styles.matchAll(groupLightUsesW500Regex)].flat();
|
||||
|
||||
const groupBackgroundRegex = /^([^{]*)\{background:var\(--white-500\)/m;
|
||||
const groupBackgroundColorRegex = /^([^{]*)\{background-color:var\(--white-500\)/m;
|
||||
// find all capturing groups that assign background or background-color directly to w500
|
||||
const backgroundGroups = mapReject(relevantStyles, entry => captureOne(entry, groupBackgroundRegex)).join(",\n");
|
||||
const backgroundColorGroups = mapReject(relevantStyles, entry => captureOne(entry, groupBackgroundColorRegex)).join(",\n");
|
||||
// create css to reassign them to --primary-100
|
||||
const reassignBackgrounds = `${backgroundGroups} {\n background: var(--primary-100) \n}`;
|
||||
const reassignBackgroundColors = `${backgroundColorGroups} {\n background-color: var(--primary-100) \n}`;
|
||||
|
||||
const groupBgVarRegex = /\.theme-light\{([^}]*--[^:}]*(?:background|bg)[^:}]*:var\(--white-500\)[^}]*)\}/m;
|
||||
const bgVarRegex = /^(--[^:]*(?:background|bg)[^:]*):var\(--white-500\)/m;
|
||||
// get all global variables used for backgrounds
|
||||
const lightVars = mapReject(relevantStyles, style => captureOne(style, groupBgVarRegex)) // get the insides of capture groups that have at least one background var with w500
|
||||
.map(str => str.split(";")).flat(); // captureGroupInsides[] -> cssRule[]
|
||||
const lightBgVars = mapReject(lightVars, variable => captureOne(variable, bgVarRegex)); // remove vars that aren't for backgrounds or w500
|
||||
// create css to reassign every var
|
||||
const reassignVariables = `.theme-light {\n ${lightBgVars.map(variable => `${variable}: var(--primary-100);`).join("\n")} \n}`;
|
||||
|
||||
createStyleSheet("clientThemeLightModeFixes", [
|
||||
reassignBackgrounds,
|
||||
reassignBackgroundColors,
|
||||
reassignVariables,
|
||||
].join("\n\n"));
|
||||
}
|
||||
|
||||
function captureOne(str, regex) {
|
||||
const result = str.match(regex);
|
||||
return (result === null) ? null : result[1];
|
||||
}
|
||||
|
||||
function mapReject(arr, mapFunc) {
|
||||
return arr.map(mapFunc).filter(Boolean);
|
||||
}
|
||||
|
||||
function updateColorVars(color: string) {
|
||||
const { hue, saturation, lightness } = hexToHSL(color);
|
||||
|
||||
|
|
|
@ -153,7 +153,15 @@ function makeShortcuts() {
|
|||
openModal: { getter: () => ModalAPI.openModal },
|
||||
openModalLazy: { getter: () => ModalAPI.openModalLazy },
|
||||
|
||||
Stores: Webpack.fluxStores
|
||||
Stores: Webpack.fluxStores,
|
||||
|
||||
setExperiment: (id: string, bucket: number) => {
|
||||
Common.FluxDispatcher.dispatch({
|
||||
type: "EXPERIMENT_OVERRIDE_BUCKET",
|
||||
experimentId: id,
|
||||
experimentBucket: bucket,
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -65,10 +65,12 @@ function GameActivityToggleButton() {
|
|||
|
||||
return (
|
||||
<Button
|
||||
className="vc-game-activity"
|
||||
tooltipText={showCurrentGame ? "Disable Game Activity" : "Enable Game Activity"}
|
||||
icon={makeIcon(showCurrentGame)}
|
||||
role="switch"
|
||||
aria-checked={!showCurrentGame}
|
||||
redGlow={!showCurrentGame}
|
||||
onClick={() => ShowCurrentGame.updateSetting(old => !old)}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
[class*="panels"] [class*="avatarWrapper"] {
|
||||
[class^="panels"] [class^="avatarWrapper"] {
|
||||
min-width: 88px;
|
||||
}
|
||||
|
||||
.vc-game-activity {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
|
|
@ -31,5 +31,12 @@ export default definePlugin({
|
|||
replace: "!0",
|
||||
},
|
||||
},
|
||||
{
|
||||
find: ".ageVerificationStatus=null",
|
||||
replacement: {
|
||||
match: /(?<=\.ageVerificationStatus=)null!==.+?(?=[,;])/,
|
||||
replace: "3",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
@ -20,11 +20,17 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
|||
import { Devs } from "@utils/constants";
|
||||
import { getIntlMessage } from "@utils/discord";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Constants, GuildStore, RestAPI } from "@webpack/common";
|
||||
import { Constants, GuildStore, PermissionStore, RestAPI } from "@webpack/common";
|
||||
|
||||
function showDisableInvites(guildId: string) {
|
||||
const guild = GuildStore.getGuild(guildId);
|
||||
if (!guild) return false;
|
||||
|
||||
return (
|
||||
// @ts-ignore
|
||||
return !GuildStore.getGuild(guildId).hasFeature("INVITES_DISABLED");
|
||||
!guild.hasFeature("INVITES_DISABLED") &&
|
||||
PermissionStore.getGuildPermissionProps(guild).canManageRoles
|
||||
);
|
||||
}
|
||||
|
||||
function disableInvites(guildId: string) {
|
||||
|
|
|
@ -25,9 +25,19 @@ export default definePlugin({
|
|||
authors: [Devs.botato],
|
||||
patches: [{
|
||||
find: ".expandedFolderIconWrapper",
|
||||
replacement: [{
|
||||
replacement: [
|
||||
// there are two elements, the first one is the plain folder icon
|
||||
// the second is the four guild preview icons
|
||||
// always show this one (the plain icons)
|
||||
{
|
||||
match: /\(\w\|\|\w\)&&(\(.{0,40}\(.{1,3}\.animated)/,
|
||||
replace: "$1",
|
||||
}]
|
||||
},
|
||||
// and never show this one (the guild preview icons)
|
||||
{
|
||||
match: /\(\w\|\|!\w\)&&(\(.{0,40}\(.{1,3}\.animated)/,
|
||||
replace: "false&&$1",
|
||||
}
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
import "./spotifyStyles.css";
|
||||
import "./visualRefreshSpotifyStyles.css"; // TODO: merge with spotifyStyles.css and remove when old UI is discontinued
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { classNameFactory } from "@api/Styles";
|
||||
|
@ -307,7 +308,8 @@ function Info({ track }: { track: Track; }) {
|
|||
{track.name}
|
||||
</Forms.FormText>
|
||||
{track.artists.some(a => a.name) && (
|
||||
<Forms.FormText variant="text-sm/normal" className={cl("ellipoverflow")}>
|
||||
<Forms.FormText variant="text-sm/normal" className={cl(["ellipoverflow", "secondary-song-info"])}>
|
||||
<span className={cl("song-info-prefix")}>by </span>
|
||||
by
|
||||
{track.artists.map((a, i) => (
|
||||
<React.Fragment key={a.name}>
|
||||
|
@ -325,7 +327,8 @@ function Info({ track }: { track: Track; }) {
|
|||
</Forms.FormText>
|
||||
)}
|
||||
{track.album.name && (
|
||||
<Forms.FormText variant="text-sm/normal" className={cl("ellipoverflow")}>
|
||||
<Forms.FormText variant="text-sm/normal" className={cl(["ellipoverflow", "secondary-song-info"])}>
|
||||
<span className={cl("song-info-prefix")}>on </span>
|
||||
on
|
||||
<span
|
||||
id={cl("album-title")}
|
||||
|
|
|
@ -32,7 +32,7 @@ function toggleHoverControls(value: boolean) {
|
|||
export default definePlugin({
|
||||
name: "SpotifyControls",
|
||||
description: "Adds a Spotify player above the account panel",
|
||||
authors: [Devs.Ven, Devs.afn, Devs.KraXen72, Devs.Av32000],
|
||||
authors: [Devs.Ven, Devs.afn, Devs.KraXen72, Devs.Av32000, Devs.nin0dev],
|
||||
options: {
|
||||
hoverControls: {
|
||||
description: "Show controls on hover",
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
padding: 0.375rem 0.5rem;
|
||||
border-bottom: 1px solid var(--background-modifier-accent);
|
||||
|
||||
--vc-spotify-green: #1db954; /* so custom themes can easily change it */
|
||||
--vc-spotify-green: var(--spotify, #1db954); /* so custom themes can easily change it */
|
||||
--vc-spotify-green-90: color-mix(in hsl, var(--vc-spotify-green), transparent 90%);
|
||||
--vc-spotify-green-80: color-mix(in hsl, var(--vc-spotify-green), transparent 80%);
|
||||
}
|
||||
|
||||
.theme-light #vc-spotify-player {
|
||||
|
|
82
src/plugins/spotifyControls/visualRefreshSpotifyStyles.css
Normal file
82
src/plugins/spotifyControls/visualRefreshSpotifyStyles.css
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* TODO: merge with spotifyStyles.css and remove when old UI is discontinued */
|
||||
.visual-refresh {
|
||||
#vc-spotify-player {
|
||||
padding: 12px;
|
||||
background: var(--bg-overlay-floating, var(--background-base-low, var(--background-secondary-alt)));
|
||||
margin: 0;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
}
|
||||
|
||||
.vc-spotify-song-info-prefix {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.vc-spotify-artist,
|
||||
.vc-spotify-album {
|
||||
color: var(--header-primary);
|
||||
}
|
||||
|
||||
.vc-spotify-secondary-song-info {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#vc-spotify-progress-bar {
|
||||
position: relative;
|
||||
color: var(--text-normal);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#vc-spotify-progress-bar>[class^="slider"] {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#vc-spotify-progress-bar>[class^="slider"] [class^="bar"] {
|
||||
height: 3px !important;
|
||||
top: calc(12px - 4px / 2 + var(--bar-offset));
|
||||
}
|
||||
|
||||
#vc-spotify-progress-bar>[class^="slider"] [class^="barFill"] {
|
||||
background-color: var(--interactive-active);
|
||||
}
|
||||
|
||||
#vc-spotify-progress-bar>[class^="slider"]:hover [class^="barFill"] {
|
||||
background-color: var(--vc-spotify-green);
|
||||
}
|
||||
|
||||
#vc-spotify-progress-bar>[class^="slider"] [class^="grabber"] {
|
||||
background-color: var(--interactive-active);
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
margin-top: calc(17px/-2 + var(--bar-offset)/2);
|
||||
margin-left: -0.5px;
|
||||
}
|
||||
|
||||
.vc-spotify-progress-time {
|
||||
margin-top: 8px;
|
||||
font-family: var(--font-code);
|
||||
}
|
||||
|
||||
.vc-spotify-button-row {
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.vc-spotify-button {
|
||||
margin: 0 2px;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.vc-spotify-repeat-context,
|
||||
.vc-spotify-repeat-track,
|
||||
.vc-spotify-shuffle-on {
|
||||
background-color: var(--vc-spotify-green-90);
|
||||
}
|
||||
|
||||
.vc-spotify-repeat-context:hover,
|
||||
.vc-spotify-repeat-track:hover,
|
||||
.vc-spotify-shuffle-on:hover {
|
||||
background-color: var(--vc-spotify-green-80);
|
||||
}
|
||||
}
|
|
@ -54,8 +54,8 @@ export default definePlugin({
|
|||
}
|
||||
],
|
||||
|
||||
getAvatarStyles(src: string) {
|
||||
if (src.startsWith("data:")) return {};
|
||||
getAvatarStyles(src: string | null) {
|
||||
if (src == null || src.startsWith("data:")) return {};
|
||||
|
||||
return Object.fromEntries(
|
||||
[128, 256, 512, 1024, 2048, 4096].map(size => [
|
||||
|
|
|
@ -26,6 +26,8 @@ import { Avatar, GuildMemberStore, React, RelationshipStore } from "@webpack/com
|
|||
import { User } from "discord-types/general";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
import managedStyle from "./styles.css?managed";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
showAvatars: {
|
||||
type: OptionType.BOOLEAN,
|
||||
|
@ -67,24 +69,19 @@ function typingUserColor(guildId: string, userId: string) {
|
|||
const TypingUser = ErrorBoundary.wrap(function ({ user, guildId }: Props) {
|
||||
return (
|
||||
<strong
|
||||
className="vc-typing-user"
|
||||
role="button"
|
||||
onClick={() => {
|
||||
openUserProfile(user.id);
|
||||
}}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "4px",
|
||||
color: typingUserColor(guildId, user.id),
|
||||
cursor: "pointer"
|
||||
}}
|
||||
>
|
||||
{settings.store.showAvatars && (
|
||||
<div>
|
||||
<Avatar
|
||||
size="SIZE_16"
|
||||
src={user.getAvatarURL(guildId, 128)} />
|
||||
</div>
|
||||
)}
|
||||
{GuildMemberStore.getNick(guildId!, user.id)
|
||||
|| (!guildId && RelationshipStore.getNickname(user.id))
|
||||
|
@ -100,7 +97,7 @@ export default definePlugin({
|
|||
description: "Show avatars and role colours in the typing indicator",
|
||||
authors: [Devs.zt],
|
||||
settings,
|
||||
|
||||
managedStyle,
|
||||
patches: [
|
||||
{
|
||||
find: "#{intl::THREE_USERS_TYPING}",
|
||||
|
@ -108,7 +105,7 @@ export default definePlugin({
|
|||
{
|
||||
// Style the indicator and add function call to modify the children before rendering
|
||||
match: /(?<=children:\[(\i)\.length>0.{0,200}?"aria-atomic":!0,children:)\i(?<=guildId:(\i).+?)/,
|
||||
replace: "$self.renderTypingUsers({ users: $1, guildId: $2, children: $& }),style:$self.TYPING_TEXT_STYLE"
|
||||
replace: "$self.renderTypingUsers({ users: $1, guildId: $2, children: $& })"
|
||||
},
|
||||
{
|
||||
// Changes the indicator to keep the user object when creating the list of typing users
|
||||
|
@ -125,12 +122,6 @@ export default definePlugin({
|
|||
}
|
||||
],
|
||||
|
||||
TYPING_TEXT_STYLE: {
|
||||
display: "grid",
|
||||
gridAutoFlow: "column",
|
||||
gridGap: "0.25em"
|
||||
},
|
||||
|
||||
buildSeveralUsers,
|
||||
|
||||
renderTypingUsers: ErrorBoundary.wrap(({ guildId, users, children }: PropsWithChildren<{ guildId: string, users: User[]; }>) => {
|
||||
|
|
5
src/plugins/typingTweaks/styles.css
Normal file
5
src/plugins/typingTweaks/styles.css
Normal file
|
@ -0,0 +1,5 @@
|
|||
.vc-typing-user [class^="wrapper"] {
|
||||
display: inline-block;
|
||||
margin-right: 0.25em;
|
||||
vertical-align: -4px;
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
import { DataStore } from "@api/index";
|
||||
import { showNotification } from "@api/Notifications";
|
||||
import { PlainSettings, Settings } from "@api/Settings";
|
||||
import { moment, Toasts } from "@webpack/common";
|
||||
import { moment, SettingsRouter, Toasts } from "@webpack/common";
|
||||
import { deflateSync, inflateSync } from "fflate";
|
||||
|
||||
import { getCloudAuth, getCloudUrl } from "./cloud";
|
||||
|
@ -172,6 +172,19 @@ export async function getCloudSettings(shouldNotify = true, force = false) {
|
|||
},
|
||||
});
|
||||
|
||||
if (res.status === 401) {
|
||||
// User switched to an account that isn't connected to cloud
|
||||
showNotification({
|
||||
title: "Cloud Settings",
|
||||
body: "Cloud sync was disabled because this account isn't connected to the Vencloud App. You can enable it again by connecting this account in Cloud Settings. (note: it will store your preferences separately)",
|
||||
color: "var(--yellow-360)",
|
||||
onClick: () => SettingsRouter.open("VencordCloud")
|
||||
});
|
||||
// Disable cloud sync globally
|
||||
Settings.cloud.authenticated = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (res.status === 404) {
|
||||
cloudSettingsLogger.info("No settings on the cloud");
|
||||
if (shouldNotify)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue