this repo has no description

Compare changes

Choose any two refs to compare.

Changed files
+367 -167
.github
workflows
nix
packages
browser
core
core-extensions
src
commands
common
componentEditor
experiments
moonbase
quietLoggers
settings
types
+16
.github/workflows/nix.yml
··· 1 + name: Check Nix flake 2 + on: [push, pull_request] 3 + 4 + permissions: 5 + checks: write 6 + 7 + jobs: 8 + nix: 9 + name: Check Nix flake 10 + runs-on: ubuntu-latest 11 + steps: 12 + - uses: actions/checkout@v4 13 + - uses: DeterminateSystems/nix-installer-action@main 14 + 15 + - name: Build default flake output 16 + run: nix build
+1
.github/workflows/types.yml
··· 17 17 with: 18 18 node-version: 22 19 19 cache: pnpm 20 + registry-url: https://registry.npmjs.org 20 21 21 22 - name: Install dependencies 22 23 run: pnpm install --frozen-lockfile
+2 -8
CHANGELOG.md
··· 1 1 ## Core 2 2 3 - - Updated moonmap, now logs when remapped exports fail 4 - - Updated mappings to fix Moonbase 5 - 6 - ## Core extensions 7 - 8 - - Extensions: Visual Refresh support for staff help button (devtools) 9 - - Native Fixes: Added flag to enable HEVC on Linux (your mileage may vary) 10 - - Moonbase: Added error boundaries, should no longer crash in most cases when things break 3 + - Updated mappings 4 + - Fixed using remapped paths as patch finds not working
+4 -73
flake.lock
··· 18 18 "type": "github" 19 19 } 20 20 }, 21 - "flake-utils_2": { 22 - "inputs": { 23 - "systems": "systems_2" 24 - }, 25 - "locked": { 26 - "lastModified": 1701680307, 27 - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", 28 - "owner": "numtide", 29 - "repo": "flake-utils", 30 - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", 31 - "type": "github" 32 - }, 33 - "original": { 34 - "owner": "numtide", 35 - "repo": "flake-utils", 36 - "type": "github" 37 - } 38 - }, 39 21 "nixpkgs": { 40 22 "locked": { 41 - "lastModified": 1728067476, 42 - "narHash": "sha256-/uJcVXuBt+VFCPQIX+4YnYrHaubJSx4HoNsJVNRgANM=", 23 + "lastModified": 1744232761, 24 + "narHash": "sha256-gbl9hE39nQRpZaLjhWKmEu5ejtQsgI5TWYrIVVJn30U=", 43 25 "owner": "NixOS", 44 26 "repo": "nixpkgs", 45 - "rev": "6e6b3dd395c3b1eb9be9f2d096383a8d05add030", 27 + "rev": "f675531bc7e6657c10a18b565cfebd8aa9e24c14", 46 28 "type": "github" 47 29 }, 48 30 "original": { 49 31 "owner": "NixOS", 50 - "ref": "nixos-24.05", 51 - "repo": "nixpkgs", 52 - "type": "github" 53 - } 54 - }, 55 - "nixpkgs_2": { 56 - "locked": { 57 - "lastModified": 1736344531, 58 - "narHash": "sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc+c2c=", 59 - "owner": "nixos", 60 - "repo": "nixpkgs", 61 - "rev": "bffc22eb12172e6db3c5dde9e3e5628f8e3e7912", 62 - "type": "github" 63 - }, 64 - "original": { 65 - "owner": "nixos", 66 32 "ref": "nixos-unstable", 67 33 "repo": "nixpkgs", 68 34 "type": "github" 69 35 } 70 36 }, 71 - "pnpm2nix": { 72 - "inputs": { 73 - "flake-utils": "flake-utils_2", 74 - "nixpkgs": "nixpkgs_2" 75 - }, 76 - "locked": { 77 - "lastModified": 1736457458, 78 - "narHash": "sha256-eiw+hAsxavEgBfhwrktNI2hwvgeVDzBDYClx/yqka78=", 79 - "owner": "NotNite", 80 - "repo": "pnpm2nix-nzbr", 81 - "rev": "4ac61c6a50623da937dca005e3dbcb8862aafb83", 82 - "type": "github" 83 - }, 84 - "original": { 85 - "owner": "NotNite", 86 - "repo": "pnpm2nix-nzbr", 87 - "type": "github" 88 - } 89 - }, 90 37 "root": { 91 38 "inputs": { 92 39 "flake-utils": "flake-utils", 93 - "nixpkgs": "nixpkgs", 94 - "pnpm2nix": "pnpm2nix" 40 + "nixpkgs": "nixpkgs" 95 41 } 96 42 }, 97 43 "systems": { 98 - "locked": { 99 - "lastModified": 1681028828, 100 - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 101 - "owner": "nix-systems", 102 - "repo": "default", 103 - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 104 - "type": "github" 105 - }, 106 - "original": { 107 - "owner": "nix-systems", 108 - "repo": "default", 109 - "type": "github" 110 - } 111 - }, 112 - "systems_2": { 113 44 "locked": { 114 45 "lastModified": 1681028828, 115 46 "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+3 -4
flake.nix
··· 2 2 description = "Yet another Discord mod"; 3 3 4 4 inputs = { 5 - nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; 5 + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 6 flake-utils.url = "github:numtide/flake-utils"; 7 - pnpm2nix.url = "github:NotNite/pnpm2nix-nzbr"; 8 7 }; 9 8 10 - outputs = { self, nixpkgs, flake-utils, pnpm2nix }: 11 - let overlay = import ./nix/overlay.nix { inherit pnpm2nix; }; 9 + outputs = { self, nixpkgs, flake-utils }: 10 + let overlay = import ./nix/overlay.nix { }; 12 11 in flake-utils.lib.eachDefaultSystem (system: 13 12 let 14 13 pkgs = import nixpkgs {
+46 -17
nix/default.nix
··· 1 - { pkgs, mkPnpmPackage }: 1 + { 2 + lib, 3 + stdenv, 4 + nodejs_22, 5 + pnpm_10, 6 + }: 2 7 3 - mkPnpmPackage rec { 4 - workspace = ./..; 8 + stdenv.mkDerivation (finalAttrs: { 9 + pname = "moonlight"; 10 + version = (builtins.fromJSON (builtins.readFile ./../package.json)).version; 11 + 5 12 src = ./..; 6 13 7 - # Work around a bug with how it expects dist 8 - components = [ 9 - "packages/core" 10 - "packages/core-extensions" 11 - "packages/injector" 12 - "packages/node-preload" 13 - "packages/types" 14 - "packages/web-preload" 14 + outputs = [ "out" "firefox" ]; 15 + 16 + nativeBuildInputs = [ 17 + nodejs_22 18 + pnpm_10.configHook 15 19 ]; 16 - distDirs = [ "dist" ]; 20 + 21 + pnpmDeps = pnpm_10.fetchDeps { 22 + inherit (finalAttrs) pname version src; 23 + hash = "sha256-I+zRCUqJabpGJRFBGW0NrM9xzyzeCjioF54zlCpynBU="; 24 + }; 25 + 26 + env = { 27 + NODE_ENV = "production"; 28 + MOONLIGHT_VERSION = "v${finalAttrs.version}"; 29 + }; 30 + 31 + buildPhase = '' 32 + runHook preBuild 33 + 34 + pnpm run build 35 + pnpm run browser-mv2 36 + 37 + runHook postBuild 38 + ''; 39 + 40 + installPhase = '' 41 + runHook preInstall 17 42 18 - copyNodeModules = true; 19 - buildPhase = "pnpm run build"; 20 - installPhase = "cp -r dist $out"; 43 + cp -r dist $out 44 + 45 + mkdir -p $firefox/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ 46 + mv $out/browser-mv2 $firefox/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/{0fb6d66f-f22d-4555-a87b-34ef4bea5e2a} 47 + 48 + runHook postInstall 49 + ''; 21 50 22 - meta = with pkgs.lib; { 51 + meta = with lib; { 23 52 description = "Yet another Discord mod"; 24 53 homepage = "https://moonlight-mod.github.io/"; 25 54 license = licenses.lgpl3; 26 55 maintainers = with maintainers; [ notnite ]; 27 56 }; 28 - } 57 + })
+3 -6
nix/overlay.nix
··· 1 - { pnpm2nix }: 1 + { ... }: 2 2 3 3 let 4 4 nameTable = { ··· 29 29 ''; 30 30 31 31 packageJson = '' 32 - {"name":"discord","main":"./injector.js","private":true} 32 + {"name":"${name}","main":"./injector.js","private":true} 33 33 ''; 34 34 35 35 in old.installPhase + "\n" + '' ··· 49 49 ''; 50 50 }); 51 51 in final: prev: rec { 52 - moonlight-mod = final.callPackage ./default.nix { 53 - pkgs = final; 54 - mkPnpmPackage = pnpm2nix.packages.${final.system}.mkPnpmPackage; 55 - }; 52 + moonlight-mod = final.callPackage ./default.nix { }; 56 53 discord = mkOverride prev moonlight-mod "discord"; 57 54 discord-ptb = mkOverride prev moonlight-mod "discord-ptb"; 58 55 discord-canary = mkOverride prev moonlight-mod "discord-canary";
+1 -1
package.json
··· 1 1 { 2 2 "name": "moonlight", 3 - "version": "1.3.11", 3 + "version": "1.3.14", 4 4 "packageManager": "pnpm@10.7.1", 5 5 "description": "Yet another Discord mod", 6 6 "license": "LGPL-3.0-or-later",
+1 -1
packages/browser/manifest.json
··· 3 3 "manifest_version": 3, 4 4 "name": "moonlight", 5 5 "description": "Yet another Discord mod", 6 - "version": "1.3.11", 6 + "version": "1.3.14", 7 7 "permissions": ["declarativeNetRequestWithHostAccess", "webRequest", "scripting", "webNavigation"], 8 8 "host_permissions": [ 9 9 "https://moonlight-mod.github.io/*",
+7 -2
packages/browser/manifestv2.json
··· 3 3 "manifest_version": 2, 4 4 "name": "moonlight", 5 5 "description": "Yet another Discord mod", 6 - "version": "1.3.11", 6 + "version": "1.3.14", 7 7 "permissions": [ 8 8 "webRequest", 9 9 "webRequestBlocking", ··· 24 24 "run_at": "document_start", 25 25 "world": "MAIN" 26 26 } 27 - ] 27 + ], 28 + "browser_specific_settings": { 29 + "gecko": { 30 + "id": "{0fb6d66f-f22d-4555-a87b-34ef4bea5e2a}" 31 + } 32 + } 28 33 }
+4
packages/browser/src/index.ts
··· 90 90 dirname(path) { 91 91 const parts = getParts(path); 92 92 return "/" + parts.slice(0, parts.length - 1).join("/"); 93 + }, 94 + basename(path) { 95 + const parts = getParts(path); 96 + return parts[parts.length - 1]; 93 97 } 94 98 }, 95 99 // TODO
+3
packages/core/src/fs.ts
··· 48 48 }, 49 49 dirname(dir) { 50 50 return path.dirname(dir); 51 + }, 52 + basename(dir) { 53 + return path.basename(dir); 51 54 } 52 55 }; 53 56 }
+1 -1
packages/core/src/patch.ts
··· 116 116 const origModuleString = moduleCache[id]; 117 117 let moduleString = origModuleString; 118 118 const patchedStr = []; 119 - const mappedName = moonlight.moonmap.modules[id]; 119 + const mappedName = Object.entries(moonlight.moonmap.modules).find((m) => m[1] === id)?.[0]; 120 120 let modified = false; 121 121 let swappedModule = false; 122 122
+12 -3
packages/core-extensions/src/commands/index.ts
··· 53 53 } 54 54 }, 55 55 { 56 - find: ".icon,bot:null===", 56 + find: ".icon,bot:null==", 57 57 replace: { 58 - match: /(\.useMemo\(\(\)=>{)(if\((\i)\.type)/, 59 - replacement: (_, before, after, section) => `${before} 58 + match: /(\.useMemo\(\(\)=>{(var \i;)?)((return |if\()(\i)\.type)/, 59 + replacement: (_, before, beforeVar, after, afterIf, section) => `${before} 60 60 if (${section}.id==="${APPLICATION_ID}") return "https://moonlight-mod.github.io/favicon.png"; 61 61 ${after}` 62 62 } ··· 67 67 replace: { 68 68 match: /(\i)\.type===\i\.\i\.BUILT_IN/, 69 69 replacement: (orig, section) => `${section}.id!=="${APPLICATION_ID}"&&${orig}` 70 + } 71 + }, 72 + 73 + // tell it this app id is authorized 74 + { 75 + find: /let{customInstallUrl:\i,installParams:\i,integrationTypesConfig:\i}/, 76 + replace: { 77 + match: /\|\|(\i)===\i\.\i\.BUILT_IN/, 78 + replacement: (orig, id) => `${orig}||${id}==="${APPLICATION_ID}"` 70 79 } 71 80 } 72 81 ];
+3
packages/core-extensions/src/common/index.ts
··· 6 6 }, 7 7 ErrorBoundary: { 8 8 dependencies: [{ id: "react" }] 9 + }, 10 + icons: { 11 + dependencies: [{ id: "react" }, { id: "discord/components/common/index" }] 9 12 } 10 13 };
+1 -1
packages/core-extensions/src/common/manifest.json
··· 4 4 "apiLevel": 2, 5 5 "meta": { 6 6 "name": "Common", 7 - "tagline": "A *lot* of common clientmodding utilities from the Discord client", 7 + "tagline": "Common client modding utilities for the Discord client", 8 8 "authors": ["Cynosphere", "NotNite"], 9 9 "tags": ["library"] 10 10 },
+31
packages/core-extensions/src/common/webpackModules/icons.ts
··· 1 + import { Icons, IconSize } from "@moonlight-mod/types/coreExtensions/common"; 2 + import { tokens } from "@moonlight-mod/wp/discord/components/common/index"; 3 + 4 + // This is defined in a Webpack module but we copy it here to be less breakage-prone 5 + const sizes: Partial<Record<IconSize, number>> = { 6 + xxs: 12, 7 + xs: 16, 8 + sm: 18, 9 + md: 24, 10 + lg: 32, 11 + refresh_sm: 20 12 + }; 13 + 14 + export const icons: Icons = { 15 + parseProps(props) { 16 + // NOTE: var() fallback is non-standard behavior, just for safety reasons 17 + const color = props?.color ?? tokens?.colors?.["INTERACTIVE_NORMAL"] ?? "var(--interactive-normal)"; 18 + 19 + const size = sizes[props?.size ?? "md"]; 20 + 21 + return { 22 + // note: this default size is also non-standard behavior, just for safety 23 + width: size ?? props?.width ?? sizes.md!, 24 + height: size ?? props?.width ?? sizes.md!, 25 + 26 + fill: typeof color === "string" ? color : color.css, 27 + className: props?.colorClass ?? "" 28 + }; 29 + } 30 + }; 31 + export default icons;
+2 -1
packages/core-extensions/src/componentEditor/index.ts
··· 27 27 find: ".lostPermission", 28 28 replace: [ 29 29 { 30 - match: /(?<=\(0,\i\.jsxs\)\(\i\.Fragment,{)children:(\[\i\(\),.+?\i\(\)])/, 30 + match: 31 + /(?<=\(0,\i\.jsxs\)\(\i\.Fragment,{)children:(\[\(0,\i\.jsx\)\(\i,{user:\i}\),.+?onClickPremiumGuildIcon:\i}\)])/, 31 32 replacement: (_, decorators) => 32 33 `children:require("componentEditor_memberList").default._patchDecorators(${decorators},arguments[0])` 33 34 },
+4 -4
packages/core-extensions/src/experiments/index.ts
··· 20 20 { 21 21 find: ".HEADER_BAR)", 22 22 replace: { 23 - match: /&&\((.)\?\(0,/, 23 + match: /&&\((\i)\?\(0,/, 24 24 replacement: (_, isStaff) => 25 25 `&&(((moonlight.getConfigOption("experiments","devtools")??false)?true:${isStaff})?(0,` 26 26 } ··· 47 47 { 48 48 find: "shouldShowLurkerModeUpsellPopout:", 49 49 replace: { 50 - match: /\.useReducedMotion,isStaff:(.),/, 51 - replacement: (_, isStaff) => 52 - `.useReducedMotion,isStaff:(moonlight.getConfigOption("experiments","staffSettings")??false)?true:${isStaff},` 50 + match: /\.useReducedMotion,isStaff:(\i)(,|})/, 51 + replacement: (_, isStaff, trail) => 52 + `.useReducedMotion,isStaff:(moonlight.getConfigOption("experiments","staffSettings")??false)?true:${isStaff}${trail}` 53 53 } 54 54 } 55 55 ];
+6
packages/core-extensions/src/moonbase/index.tsx
··· 42 42 { id: "react" }, 43 43 { id: "discord/components/common/index" }, 44 44 { ext: "moonbase", id: "stores" }, 45 + { ext: "moonbase", id: "ThemeDarkIcon" }, 45 46 { id: "discord/modules/guild_settings/web/AppCard.css" }, 46 47 { ext: "contextMenu", id: "contextMenu" }, 47 48 { id: "discord/modules/modals/Modals" }, ··· 49 50 '"Missing channel in Channel.openChannelContextMenu"', 50 51 ".forumOrHome]:" 51 52 ] 53 + }, 54 + 55 + ThemeDarkIcon: { 56 + dependencies: [{ ext: "common", id: "icons" }, { id: "react" }] 52 57 }, 53 58 54 59 settings: { ··· 67 72 dependencies: [ 68 73 { id: "react" }, 69 74 { ext: "moonbase", id: "stores" }, 75 + { ext: "moonbase", id: "ThemeDarkIcon" }, 70 76 { ext: "notices", id: "notices" }, 71 77 { 72 78 ext: "spacepack",
+36
packages/core-extensions/src/moonbase/webpackModules/ThemeDarkIcon.tsx
··· 1 + // RIP to ThemeDarkIcon ????-2025 2 + // <Cynthia> Failed to remap "ThemeDarkIcon" in "discord/components/common/index" 3 + // <NotNite> bro are you fucking kidding me 4 + // <NotNite> that's literally the icon we use for the update banner 5 + 6 + import React from "@moonlight-mod/wp/react"; 7 + import icons from "@moonlight-mod/wp/common_icons"; 8 + import type { IconProps } from "@moonlight-mod/types/coreExtensions/common"; 9 + 10 + export default function ThemeDarkIcon(props?: IconProps) { 11 + const parsed = icons.parseProps(props); 12 + 13 + return ( 14 + <svg 15 + aria-hidden="true" 16 + role="img" 17 + xmlns="http://www.w3.org/2000/svg" 18 + width={parsed.width} 19 + height={parsed.height} 20 + fill="none" 21 + viewBox="0 0 24 24" 22 + > 23 + <path 24 + fill={parsed.fill} 25 + className={parsed.className} 26 + d="M20.52 18.96c.32-.4-.01-.96-.52-.96A11 11 0 0 1 9.77 2.94c.31-.78-.3-1.68-1.1-1.43a11 11 0 1 0 11.85 17.45Z" 27 + /> 28 + 29 + <path 30 + fill={parsed.fill} 31 + className={parsed.className} 32 + d="m17.73 9.27-.76-2.02a.5.5 0 0 0-.94 0l-.76 2.02-2.02.76a.5.5 0 0 0 0 .94l2.02.76.76 2.02a.5.5 0 0 0 .94 0l.76-2.02 2.02-.76a.5.5 0 0 0 0-.94l-2.02-.76ZM19.73 2.62l.45 1.2 1.2.45c.21.08.21.38 0 .46l-1.2.45-.45 1.2a.25.25 0 0 1-.46 0l-.45-1.2-1.2-.45a.25.25 0 0 1 0-.46l1.2-.45.45-1.2a.25.25 0 0 1 .46 0Z" 33 + /> 34 + </svg> 35 + ); 36 + }
+2 -2
packages/core-extensions/src/moonbase/webpackModules/crashScreen.tsx
··· 84 84 } 85 85 86 86 function ExtensionDisableCard({ ext }: { ext: DetectedExtension }) { 87 - function disableWithDependents() { 87 + async function disableWithDependents() { 88 88 const disable = new Set<string>(); 89 89 disable.add(ext.id); 90 90 for (const [id, dependencies] of moonlightNode.processedExtensions.dependencyGraph) { ··· 105 105 msg += "?"; 106 106 107 107 if (confirm(msg)) { 108 - moonlightNode.writeConfig(config); 108 + await moonlightNode.writeConfig(config); 109 109 window.location.reload(); 110 110 } 111 111 }
+2 -2
packages/core-extensions/src/moonbase/webpackModules/settings.tsx
··· 19 19 onReset={() => { 20 20 MoonbaseSettingsStore.reset(); 21 21 }} 22 - onSave={() => { 23 - MoonbaseSettingsStore.writeConfig(); 22 + onSave={async () => { 23 + await MoonbaseSettingsStore.writeConfig(); 24 24 }} 25 25 /> 26 26 );
+30 -10
packages/core-extensions/src/moonbase/webpackModules/stores.ts
··· 13 13 import { mainRepo } from "@moonlight-mod/types/constants"; 14 14 import { checkExtensionCompat, ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 15 15 import { CustomComponent } from "@moonlight-mod/types/coreExtensions/moonbase"; 16 + import { NodeEventType } from "@moonlight-mod/types/core/event"; 16 17 import { getConfigOption, setConfigOption } from "@moonlight-mod/core/util/config"; 17 18 import diff from "microdiff"; 18 19 ··· 78 79 }; 79 80 } 80 81 82 + // This is async but we're calling it without 81 83 this.checkUpdates(); 84 + 85 + // Update our state if another extension edited the config programatically 86 + moonlightNode.events.addEventListener(NodeEventType.ConfigSaved, (config) => { 87 + if (!this.submitting) { 88 + this.config = this.clone(config); 89 + // NOTE: This is also async but we're calling it without 90 + this.processConfigChanged(); 91 + } 92 + }); 82 93 } 83 94 84 95 async checkUpdates() { ··· 239 250 let val = this.config.extensions[ext.id]; 240 251 241 252 if (val == null) { 242 - this.config.extensions[ext.id] = { enabled }; 253 + this.config.extensions[ext.id] = enabled; 243 254 this.modified = this.isModified(); 244 255 this.emitChange(); 245 256 return; ··· 499 510 return returnedAdvice; 500 511 } 501 512 502 - writeConfig() { 503 - this.submitting = true; 504 - this.restartAdvice = this.#computeRestartAdvice(); 505 - const modifiedRepos = diff(this.savedConfig.repositories, this.config.repositories); 513 + async writeConfig() { 514 + try { 515 + this.submitting = true; 516 + this.emitChange(); 506 517 507 - moonlightNode.writeConfig(this.config); 508 - this.savedConfig = this.clone(this.config); 518 + await moonlightNode.writeConfig(this.config); 519 + await this.processConfigChanged(); 520 + } finally { 521 + this.submitting = false; 522 + this.emitChange(); 523 + } 524 + } 509 525 510 - this.submitting = false; 526 + private async processConfigChanged() { 527 + this.savedConfig = this.clone(this.config); 528 + this.restartAdvice = this.#computeRestartAdvice(); 511 529 this.modified = false; 512 - this.emitChange(); 513 530 514 - if (modifiedRepos.length !== 0) this.checkUpdates(); 531 + const modifiedRepos = diff(this.savedConfig.repositories, this.config.repositories); 532 + if (modifiedRepos.length !== 0) await this.checkUpdates(); 533 + 534 + this.emitChange(); 515 535 } 516 536 517 537 reset() {
+1 -1
packages/core-extensions/src/moonbase/webpackModules/ui/update.tsx
··· 7 7 import MarkupUtils from "@moonlight-mod/wp/discord/modules/markup/MarkupUtils"; 8 8 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 9 9 import { 10 - ThemeDarkIcon, 11 10 Button, 12 11 Text, 13 12 ModalRoot, ··· 19 18 openModal 20 19 } from "@moonlight-mod/wp/discord/components/common/index"; 21 20 import MarkupClasses from "@moonlight-mod/wp/discord/modules/messages/web/Markup.css"; 21 + import ThemeDarkIcon from "@moonlight-mod/wp/moonbase_ThemeDarkIcon"; 22 22 23 23 const strings: Record<UpdateState, string> = { 24 24 [UpdateState.Ready]: "A new version of moonlight is available.",
+1 -1
packages/core-extensions/src/moonbase/webpackModules/updates.tsx
··· 3 3 import Notices from "@moonlight-mod/wp/notices_notices"; 4 4 import { MoonlightBranch } from "@moonlight-mod/types"; 5 5 import React from "@moonlight-mod/wp/react"; 6 - import { ThemeDarkIcon } from "@moonlight-mod/wp/discord/components/common/index"; 6 + import ThemeDarkIcon from "@moonlight-mod/wp/moonbase_ThemeDarkIcon"; 7 7 8 8 function plural(str: string, num: number) { 9 9 return `${str}${num > 1 ? "s" : ""}`;
+5
packages/core-extensions/src/moonbase/wp.d.ts
··· 5 5 declare module "@moonlight-mod/wp/moonbase_stores" { 6 6 export * from "core-extensions/src/moonbase/webpackModules/stores"; 7 7 } 8 + 9 + declare module "@moonlight-mod/wp/moonbase_ThemeDarkIcon" { 10 + import ThemeDarkIcon from "core-extensions/src/moonbase/webpackModules/ThemeDarkIcon"; 11 + export = ThemeDarkIcon; 12 + }
+82 -14
packages/core-extensions/src/quietLoggers/index.ts
··· 18 18 { 19 19 find: '("GatewaySocket")', 20 20 replace: { 21 - match: /.\.(info|log)(\(.+?\))(;|,)/g, 22 - replacement: (_, type, body, trail) => `(()=>{})${body}${trail}` 21 + match: /\i\.(log|info)\(/g, 22 + replacement: "(()=>{})(" 23 + } 24 + }, 25 + { 26 + find: '"_connect called with already existing websocket"', 27 + replace: { 28 + match: /\i\.(log|info|verbose)\(/g, 29 + replacement: "(()=>{})(" 23 30 } 24 31 } 25 32 ]; ··· 30 37 // Patches to simply remove a logger call 31 38 const stubPatches = [ 32 39 // "sh" is not a valid locale. 33 - ["is not a valid locale", /void (.)\.error\(""\.concat\((.)," is not a valid locale\."\)\)/g], 34 - ['"[BUILD INFO] Release Channel: "', /new .{1,2}\.Z\(\)\.log\("\[BUILD INFO\] Release Channel: ".+?\)\),/], 35 - ['.APP_NATIVE_CRASH,"Storage"', /console\.log\("AppCrashedFatalReport lastCrash:",.,.\);/], 40 + ["is not a valid locale", /void \i\.error\(""\.concat\(\i," is not a valid locale\."\)\)/g], 41 + ['"[BUILD INFO] Release Channel: "', /new \i\.Z\(\)\.log\("\[BUILD INFO\] Release Channel: ".+?\)\),/], 42 + ['.APP_NATIVE_CRASH,"Storage"', /console\.log\("AppCrashedFatalReport lastCrash:",\i,\i\);/], 36 43 ['.APP_NATIVE_CRASH,"Storage"', 'void console.log("AppCrashedFatalReport: getLastCrash not supported.")'], 37 - ['"[NATIVE INFO] ', /new .{1,2}\.Z\(\)\.log\("\[NATIVE INFO] .+?\)\);/], 38 - ['"Spellchecker"', /.\.info\("Switching to ".+?"\(unavailable\)"\);?/g], 39 - ['throw Error("Messages are still loading.");', /console\.warn\("Unsupported Locale",.\),/], 40 - ["}_dispatchWithDevtools(", /.\.totalTime>.{1,2}&&.\.verbose\(.+?\);/], 41 - ['"NativeDispatchUtils"', /null==.&&.\.warn\("Tried getting Dispatch instance before instantiated"\),/], 42 - ['("DatabaseManager")', /.\.log\("removing database \(user: ".+?\)\),/], 44 + ['"[NATIVE INFO] ', /new \i\.Z\(\)\.log\("\[NATIVE INFO] .+?\)\);/], 45 + ['"Spellchecker"', /\i\.info\("Switching to ".+?"\(unavailable\)"\);?/g], 46 + ['throw Error("Messages are still loading.");', /console\.warn\("Unsupported Locale",\i\),/], 47 + ["}_dispatchWithDevtools(", /\i\.totalTime>\i&&\i\.verbose\(.+?\);/], 48 + ['"NativeDispatchUtils"', /null==\i&&\i\.warn\("Tried getting Dispatch instance before instantiated"\),/], 43 49 [ 44 50 '"Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. Action: "', 45 - /.\.has\(.\.type\)&&.\.log\(.+?\.type\)\),/ 51 + /\i\.has\(\i\.type\)&&\i\.log\(.+?\.type\)\),/ 46 52 ], 47 - ['console.warn("Window state not initialized"', /console\.warn\("Window state not initialized",.\),/] 53 + ['console.warn("Window state not initialized"', /console\.warn\("Window state not initialized",\i\),/], 54 + ['.name="MaxListenersExceededWarning",', /(?<=\.length),\i\(\i\)/], 55 + [ 56 + '"The answer for life the universe and everything is:"', 57 + /\i\.info\("The answer for life the universe and everything is:",\i\),/ 58 + ], 59 + [ 60 + '"isLibdiscoreBlockedDomainsEnabled called but libdiscore is not loaded"', 61 + /,\i\.verbose\("isLibdiscoreBlockedDomainsEnabledThisSession: ".concat\(\i\)\)/ 62 + ], 63 + [ 64 + '"Unable to determine render window for element"', 65 + /console\.warn\("Unable to determine render window for element",\i\),/ 66 + ], 67 + [ 68 + '"Unable to determine render window for element"', 69 + /console\.warn\('Unable to find element constructor "'\.concat\(\i,'" in'\),\i\),/ 70 + ], 71 + [ 72 + '"[PostMessageTransport] Protocol error: event data should be an Array!"', 73 + /void console\.warn\("\[PostMessageTransport] Protocol error: event data should be an Array!"\)/ 74 + ], 75 + [ 76 + '("ComponentDispatchUtils")', 77 + /new \i\.Z\("ComponentDispatchUtils"\)\.warn\("ComponentDispatch\.resubscribe: Resubscribe without existing subscription",\i\),/ 78 + ] 79 + ]; 80 + 81 + const stripLoggers = [ 82 + '("OverlayRenderStore")', 83 + '("FetchBlockedDomain")', 84 + '="UserSettingsProtoLastWriteTimes",', 85 + '("MessageActionCreators")', 86 + '("Routing/Utils")', 87 + '("DatabaseManager")', 88 + '("KeyboardLayoutMapUtils")', 89 + '("ChannelMessages")', 90 + '("MessageQueue")', 91 + '("RTCLatencyTestManager")', 92 + '("OverlayStoreV3")', 93 + '("OverlayBridgeStore")', 94 + '("AuthenticationStore")', 95 + '("ConnectionStore")', 96 + '"Dispatched INITIAL_GUILD "', 97 + '"handleIdentify called"', 98 + '("Spotify")' 48 99 ]; 49 100 50 101 const simplePatches = [ ··· 56 107 { 57 108 find: ".Messages.SELF_XSS_HEADER", 58 109 replace: { 59 - match: /\(null!=.{1,2}&&"0\.0\.0"===.{1,2}\.remoteApp\.getVersion\(\)\)/, 110 + match: /\(null!=\i&&"0\.0\.0"===\i\.remoteApp\.getVersion\(\)\)/, 60 111 replacement: "(true)" 61 112 } 62 113 }, 114 + { 115 + find: '("ComponentDispatchUtils")', 116 + replace: { 117 + match: 118 + /new \i\.Z\("ComponentDispatchUtils"\)\.warn\("ComponentDispatch\.subscribe: Attempting to add a duplicate listener",\i\)/, 119 + replacement: "void 0" 120 + }, 121 + prerequisite: notXssDefensesOnly 122 + }, 63 123 // Highlight.js deprecation warnings 64 124 { 65 125 find: "Deprecated as of", ··· 92 152 replace: { 93 153 match: patch[0], 94 154 replacement: patch[1] 155 + }, 156 + prerequisite: notXssDefensesOnly 157 + })), 158 + ...stripLoggers.map((find) => ({ 159 + find, 160 + replace: { 161 + match: /(\i|this\.logger)\.(log|warn|error|info|verbose)\(/g, 162 + replacement: "(()=>{})(" 95 163 }, 96 164 prerequisite: notXssDefensesOnly 97 165 }))
+1 -1
packages/core-extensions/src/settings/index.ts
··· 12 12 { 13 13 find: 'navId:"user-settings-cog",', 14 14 replace: { 15 - match: /children:\[(.)\.map\(.+?\),children:.\((.)\)/, 15 + match: /children:\[(\i)\.map\(.+?\),.*?children:\i\((\i)\)/, 16 16 replacement: (orig, sections, section) => 17 17 `${orig.replace( 18 18 /Object\.values\(.\..+?\)/,
+2 -2
packages/types/package.json
··· 1 1 { 2 2 "name": "@moonlight-mod/types", 3 - "version": "1.3.14", 3 + "version": "1.3.17", 4 4 "exports": { 5 5 ".": "./src/index.ts", 6 6 "./import": "./src/import.d.ts", ··· 17 17 }, 18 18 "dependencies": { 19 19 "@moonlight-mod/lunast": "^1.0.1", 20 - "@moonlight-mod/mappings": "^1.1.22", 20 + "@moonlight-mod/mappings": "^1.1.25", 21 21 "@moonlight-mod/moonmap": "^1.0.5", 22 22 "@types/react": "^18.3.10", 23 23 "csstype": "^3.1.3",
+22
packages/types/src/coreExtensions/common.ts
··· 1 + import type { IconProps, IconSize } from "@moonlight-mod/mappings/discord/components/common/index"; 2 + 1 3 export type ErrorBoundaryProps = React.PropsWithChildren<{ 2 4 noop?: boolean; 3 5 fallback?: React.FC<any>; ··· 9 11 error?: Error; 10 12 componentStack?: string; 11 13 }; 14 + 15 + export type ErrorBoundary = React.ComponentClass<ErrorBoundaryProps, ErrorBoundaryState>; 16 + 17 + export type ParsedIconProps = { 18 + width: number; 19 + height: number; 20 + fill: string; 21 + className: string; 22 + }; 23 + 24 + export interface Icons { 25 + /** 26 + * Parse icon props into their actual width/height. 27 + * @param props The icon props 28 + */ 29 + parseProps(props?: IconProps): ParsedIconProps; 30 + } 31 + 32 + // Re-export so extension developers don't need to depend on mappings 33 + export type { IconProps, IconSize };
+4
packages/types/src/discord/require.ts
··· 1 1 import { AppPanels } from "../coreExtensions/appPanels"; 2 2 import { Commands } from "../coreExtensions/commands"; 3 + import { ErrorBoundary, Icons } from "../coreExtensions/common"; 3 4 import { DMList, MemberList, Messages } from "../coreExtensions/componentEditor"; 4 5 import { ContextMenu, EvilItemParser } from "../coreExtensions/contextMenu"; 5 6 import { Markdown } from "../coreExtensions/markdown"; ··· 13 14 declare function WebpackRequire(id: "appPanels_appPanels"): AppPanels; 14 15 15 16 declare function WebpackRequire(id: "commands_commands"): Commands; 17 + 18 + declare function WebpackRequire(id: "common_ErrorBoundary"): ErrorBoundary; 19 + declare function WebpackRequire(id: "common_icons"): Icons; 16 20 17 21 declare function WebpackRequire(id: "componentEditor_dmList"): DMList; 18 22 declare function WebpackRequire(id: "componentEditor_memberList"): MemberList;
+1
packages/types/src/fs.ts
··· 15 15 16 16 join: (...parts: string[]) => string; 17 17 dirname: (path: string) => string; 18 + basename: (path: string) => string; 18 19 };
+10 -1
packages/types/src/import.d.ts
··· 10 10 export default commands; 11 11 } 12 12 13 - declare module "@moonlight-mod/wp/common_ErrorBoundary"; 13 + declare module "@moonlight-mod/wp/common_ErrorBoundary" { 14 + import { CoreExtensions } from "@moonlight-mod/types"; 15 + const ErrorBoundary: CoreExtensions.Common.ErrorBoundary; 16 + export = ErrorBoundary; 17 + } 18 + declare module "@moonlight-mod/wp/common_icons" { 19 + import { CoreExtensions } from "@moonlight-mod/types"; 20 + export const icons: CoreExtensions.Common.Icons; 21 + export default icons; 22 + } 14 23 declare module "@moonlight-mod/wp/common_stores"; 15 24 16 25 declare module "@moonlight-mod/wp/componentEditor_dmList" {
-1
packages/types/src/mappings.d.ts
··· 229 229 export const ScienceIcon: MappedModules["discord/components/common/index"]["ScienceIcon"]; 230 230 export const ScreenIcon: MappedModules["discord/components/common/index"]["ScreenIcon"]; 231 231 export const StarIcon: MappedModules["discord/components/common/index"]["StarIcon"]; 232 - export const ThemeDarkIcon: MappedModules["discord/components/common/index"]["ThemeDarkIcon"]; 233 232 export const TrashIcon: MappedModules["discord/components/common/index"]["TrashIcon"]; 234 233 export const WarningIcon: MappedModules["discord/components/common/index"]["WarningIcon"]; 235 234 export const WindowLaunchIcon: MappedModules["discord/components/common/index"]["WindowLaunchIcon"];
+16 -9
pnpm-lock.yaml
··· 41 41 specifier: ^1.0.1 42 42 version: 1.0.1 43 43 '@moonlight-mod/mappings': 44 - specifier: ^1.1.22 45 - version: 1.1.22 44 + specifier: ^1.1.25 45 + version: 1.1.25 46 46 '@moonlight-mod/moonmap': 47 47 specifier: ^1.0.5 48 48 version: 1.0.5 ··· 158 158 specifier: ^1.0.1 159 159 version: 1.0.1 160 160 '@moonlight-mod/mappings': 161 - specifier: ^1.1.22 162 - version: 1.1.22(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5) 161 + specifier: ^1.1.25 162 + version: 1.1.25(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5) 163 163 '@moonlight-mod/moonmap': 164 164 specifier: ^1.0.5 165 165 version: 1.0.5 ··· 183 183 version: 1.0.1 184 184 '@moonlight-mod/mappings': 185 185 specifier: catalog:prod 186 - version: 1.1.22(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5) 186 + version: 1.1.25(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5) 187 187 '@moonlight-mod/moonmap': 188 188 specifier: catalog:prod 189 189 version: 1.0.5 ··· 405 405 '@moonlight-mod/lunast@1.0.1': 406 406 resolution: {integrity: sha512-K3vxzDlfFuYKjciIW2FMlcZ1qrrkAGDGpSBlNqYGtJ0sMt9bRCd2lpSpg6AX/giSljDtmAUXa/5mOfUoDQxjBA==} 407 407 408 - '@moonlight-mod/mappings@1.1.22': 409 - resolution: {integrity: sha512-GJjAz/DwaVg724vzOWbEzANbXVIWX8zWAohIh7y6eXCxvwAgq2KuP27iiFmx4RboHQvhWP0nwyqTuKF3A1Ttgw==} 408 + '@moonlight-mod/mappings@1.1.25': 409 + resolution: {integrity: sha512-bgnSN9H/IBdMGxGev6RQKXuzhQxwo1090NhIDHnflguZnjiu2pg/usPfh76bqyhxRuX4SS7tiZSNTwBoSflCLg==} 410 + engines: {node: '>=22', npm: pnpm, pnpm: '>=10', yarn: pnpm} 410 411 peerDependencies: 411 412 '@moonlight-mod/lunast': ^1.0.1 412 413 '@moonlight-mod/moonmap': ^1.0.5 ··· 448 449 449 450 '@types/estree@1.0.6': 450 451 resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 452 + 453 + '@types/estree@1.0.7': 454 + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} 451 455 452 456 '@types/fbemitter@2.0.35': 453 457 resolution: {integrity: sha512-Xem6d7qUfmouCHntCrRYgDBwbf+WWRd6G+7WEFlEZFZ67LZXiYRvT2LV8wcZa6mIaAil95+ABQdKgB6hPIsnng==} ··· 1736 1740 estree-toolkit: 1.7.8 1737 1741 meriyah: 6.0.1 1738 1742 1739 - '@moonlight-mod/mappings@1.1.22(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5)': 1743 + '@moonlight-mod/mappings@1.1.25(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5)': 1740 1744 dependencies: 1741 1745 '@moonlight-mod/lunast': 1.0.1 1742 1746 '@moonlight-mod/moonmap': 1.0.5 ··· 1782 1786 1783 1787 '@types/eslint@9.6.1': 1784 1788 dependencies: 1785 - '@types/estree': 1.0.6 1789 + '@types/estree': 1.0.7 1786 1790 '@types/json-schema': 7.0.15 1787 1791 optional: true 1788 1792 ··· 1791 1795 '@types/estree': 1.0.6 1792 1796 1793 1797 '@types/estree@1.0.6': {} 1798 + 1799 + '@types/estree@1.0.7': 1800 + optional: true 1794 1801 1795 1802 '@types/fbemitter@2.0.35': {} 1796 1803
+1 -1
pnpm-workspace.yaml
··· 15 15 taze: ^19.0.4 16 16 prod: 17 17 "@moonlight-mod/lunast": ^1.0.1 18 - "@moonlight-mod/mappings": ^1.1.22 18 + "@moonlight-mod/mappings": ^1.1.25 19 19 "@moonlight-mod/moonmap": ^1.0.5 20 20 microdiff: ^1.5.0 21 21 nanotar: ^0.1.1