+16
.github/workflows/nix.yml
+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
+1
.github/workflows/types.yml
+2
-8
CHANGELOG.md
+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
+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
+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
+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
+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
package.json
+1
-1
packages/browser/manifest.json
+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
+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
+4
packages/browser/src/index.ts
+3
packages/core/src/fs.ts
+3
packages/core/src/fs.ts
+1
-1
packages/core/src/patch.ts
+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
+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
+3
packages/core-extensions/src/common/index.ts
+1
-1
packages/core-extensions/src/common/manifest.json
+1
-1
packages/core-extensions/src/common/manifest.json
+31
packages/core-extensions/src/common/webpackModules/icons.ts
+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
+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
+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
+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
+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
+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
+2
-2
packages/core-extensions/src/moonbase/webpackModules/settings.tsx
+30
-10
packages/core-extensions/src/moonbase/webpackModules/stores.ts
+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
+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
+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
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
+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
+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
+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
+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
+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
+1
packages/types/src/fs.ts
+10
-1
packages/types/src/import.d.ts
+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
-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
+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