fix: drop tally embed from hosting panel

This commit is contained in:
Felitendo committed 2026-09-14 11:03:47 +02:00
1 parent 02e18e3765
commit 537b73b3dc
3 files changed
+174 -5

No files matched your search

+5
View File
@@ -77,6 +77,11 @@ cd ../..
scripts/export-patches.sh # rewrite patches/ from those commits scripts/export-patches.sh # rewrite patches/ from those commits
``` ```
The icons are the one thing that is generated rather than written. Edit
`build/upstream/apps/app/icons/modrinth-enhanced.svg`, run `scripts/render-icons.py`, and every PNG,
`.ico` and `.icns` next to it is rewritten from that source; rendering the unchanged source again
reproduces the current files byte for byte.
Patches are applied with `git am --3way`, so small upstream movements around a hunk resolve by Patches are applied with `git am --3way`, so small upstream movements around a hunk resolve by
themselves. When one genuinely conflicts, `scripts/prepare.sh` stops and leaves the conflict staged themselves. When one genuinely conflicts, `scripts/prepare.sh` stops and leaves the conflict staged
in `build/upstream` to be resolved with `git am --continue`, after which `scripts/export-patches.sh` in `build/upstream` to be resolved with `git am --continue`, after which `scripts/export-patches.sh`
+28 -5
View File
@@ -3,7 +3,7 @@ From: Modrinth Enhanced <patches@modrinth-enhanced.invalid>
Date: Mon, 14 Sep 2026 10:23:01 +0200 Date: Mon, 14 Sep 2026 10:23:01 +0200
Subject: [PATCH] Remove telemetry Subject: [PATCH] Remove telemetry
Product analytics, crash reporting and the user survey embed are all Product analytics, crash reporting and the survey embeds are all
removed, and the Modrinth analytics endpoints the launcher itself posts removed, and the Modrinth analytics endpoints the launcher itself posts
to are no longer called: to are no longer called:
@@ -13,9 +13,12 @@ to are no longer called:
PostHog SDK is no longer part of the bundle at all. PostHog SDK is no longer part of the bundle at all.
* `helpers/error-reporting.ts` no longer loads `@sentry/vue`; errors are * `helpers/error-reporting.ts` no longer loads `@sentry/vue`; errors are
logged locally, as they are in upstream development builds. logged locally, as they are in upstream development builds.
* The third-party Tally embed is dropped from `index.html` and the * The third-party Tally embed is gone. It was loaded from `index.html`
survey list is no longer fetched, so the popup that carries the on every start for the app's own survey popup, and injected again by
signed-in Modrinth user id never appears. the Modrinth Hosting panel in `@modrinth/ui` when a server carries a
survey notice. Neither loads it now, and the app no longer fetches the
survey list, so the popup that carries the signed-in Modrinth user id
never appears.
* `analytics/playtime` and `analytics/minecraft-server-play` are no * `analytics/playtime` and `analytics/minecraft-server-play` are no
longer posted from `app-lib`. The latter also removes a Mojang session longer posted from `app-lib`. The latter also removes a Mojang session
handshake whose only purpose was to authenticate that report. handshake whose only purpose was to authenticate that report.
@@ -38,7 +41,8 @@ for them.
.../app-frontend/src/locales/en-US/index.json | 2 +- .../app-frontend/src/locales/en-US/index.json | 2 +-
apps/app/tauri.conf.json | 6 +- apps/app/tauri.conf.json | 6 +-
packages/app-lib/src/api/instance/run.rs | 83 +++-------------- packages/app-lib/src/api/instance/run.rs | 83 +++--------------
8 files changed, 50 insertions(+), 218 deletions(-) .../layouts/wrapped/hosting/manage/root.vue | 8 +-
9 files changed, 53 insertions(+), 223 deletions(-)
diff --git a/apps/app-frontend/index.html b/apps/app-frontend/index.html diff --git a/apps/app-frontend/index.html b/apps/app-frontend/index.html
index 6367788..9738bbc 100644 index 6367788..9738bbc 100644
@@ -449,3 +453,22 @@ index 25626c1..d638128 100644
} else { } else {
Ok(()) Ok(())
}; };
diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/root.vue b/packages/ui/src/layouts/wrapped/hosting/manage/root.vue
index 9ccd656..065aad6 100644
--- a/packages/ui/src/layouts/wrapped/hosting/manage/root.vue
+++ b/packages/ui/src/layouts/wrapped/hosting/manage/root.vue
@@ -906,11 +906,9 @@ function showSurvey() {
}
function loadTallyScript() {
- if (document.querySelector('script[src*="tally.so"]')) return
- const script = document.createElement('script')
- script.src = 'https://tally.so/widgets/embed.js'
- script.defer = true
- document.head.appendChild(script)
+ // Modrinth Enhanced does not load the third-party Tally embed. Without it
+ // `getTally()` stays undefined and `showSurvey()` above does nothing, so a
+ // survey notice on a hosted server is simply not turned into a popup.
}
async function handleInstallationRetry() {
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env python3
"""Render the Modrinth Enhanced icon set from its vector source.
The source lives in the patched checkout as
`apps/app/icons/modrinth-enhanced.svg`; this rewrites every generated icon
next to it. Run it after editing that SVG, then commit the result in
build/upstream and re-export the patches.
Needs `rsvg-convert` (librsvg). ImageMagick is not used: the ICNS and ICO
writers below are a few lines each and work the same everywhere, whereas
ImageMagick's ICNS support depends on how it was built.
"""
import os
import shutil
import struct
import subprocess
import sys
import tempfile
REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ICONS = os.path.join(
os.environ.get("WORKTREE", os.path.join(REPO_ROOT, "build", "upstream")),
"apps",
"app",
"icons",
)
SVG = os.path.join(ICONS, "modrinth-enhanced.svg")
# Every PNG the Tauri bundles reference, and the size it has to be.
PNGS = {
"icon.png": 512,
"128x128.png": 128,
"128x128@2x.png": 256,
"StoreLogo.png": 50,
"Square30x30Logo.png": 30,
"Square44x44Logo.png": 44,
"Square71x71Logo.png": 71,
"Square89x89Logo.png": 89,
"Square107x107Logo.png": 107,
"Square142x142Logo.png": 142,
"Square150x150Logo.png": 150,
"Square284x284Logo.png": 284,
"Square310x310Logo.png": 310,
}
ICO_SIZES = [16, 24, 32, 48, 64, 256]
FAVICON_SIZES = [16, 24, 32, 64]
# ICNS chunk type -> pixel size. All chunks carry PNG payloads, which macOS
# 10.7 and newer understand.
ICNS_TYPES = [
(b"icp4", 16),
(b"icp5", 32),
(b"ic11", 32),
(b"ic12", 64),
(b"ic07", 128),
(b"ic13", 256),
(b"ic08", 256),
(b"ic14", 512),
(b"ic09", 512),
(b"ic10", 1024),
]
def render(size, path):
"""Rasterise the source at exactly `size`, rather than downscaling one
large render, so the small sizes stay crisp."""
subprocess.run(
["rsvg-convert", "-w", str(size), "-h", str(size), SVG, "-o", path],
check=True,
)
def build_ico(sizes, cache, path):
entries, blobs, offset = [], [], 6 + 16 * len(sizes)
for size in sizes:
with open(cache[size], "rb") as handle:
data = handle.read()
entries.append(
struct.pack(
"<BBBBHHII",
# 256 is written as 0 in an ICO directory entry.
size if size < 256 else 0,
size if size < 256 else 0,
0,
0,
1,
32,
len(data),
offset,
)
)
blobs.append(data)
offset += len(data)
with open(path, "wb") as handle:
handle.write(struct.pack("<HHH", 0, 1, len(sizes)))
for entry in entries:
handle.write(entry)
for blob in blobs:
handle.write(blob)
def build_icns(cache, path):
chunks = b""
for kind, size in ICNS_TYPES:
with open(cache[size], "rb") as handle:
data = handle.read()
chunks += kind + struct.pack(">I", len(data) + 8) + data
with open(path, "wb") as handle:
handle.write(b"icns" + struct.pack(">I", len(chunks) + 8) + chunks)
def main():
if not shutil.which("rsvg-convert"):
sys.exit("rsvg-convert is required (install librsvg)")
if not os.path.isfile(SVG):
sys.exit(f"No icon source at {SVG}. Run scripts/prepare.sh first.")
with tempfile.TemporaryDirectory() as tmp:
cache = {}
needed = set(PNGS.values()) | set(ICO_SIZES) | set(FAVICON_SIZES)
needed |= {size for _, size in ICNS_TYPES}
for size in sorted(needed):
cache[size] = os.path.join(tmp, f"{size}.png")
render(size, cache[size])
for name, size in PNGS.items():
shutil.copyfile(cache[size], os.path.join(ICONS, name))
build_ico(ICO_SIZES, cache, os.path.join(ICONS, "icon.ico"))
build_ico(FAVICON_SIZES, cache, os.path.join(ICONS, "favicon.ico"))
build_icns(cache, os.path.join(ICONS, "icon.icns"))
for name in sorted(os.listdir(ICONS)):
full = os.path.join(ICONS, name)
if os.path.isfile(full):
print(f"{name:24s} {os.path.getsize(full):>8d} bytes")
if __name__ == "__main__":
main()