Compare commits

..
2 Commits
Author SHA1 Message Date
luzadev 891562dc88 v1.7.5: fix avvio Windows ("Failed to resolve Python.Runtime.Loader")
PyInstaller non bundlava i file di supporto di pythonnet/clr_loader
(Python.Runtime.dll, nethost.dll, runtimeconfig.json), per cui al
caricamento di webview.platforms.winforms.py l'import 'clr' moriva.

Aggiunti --collect-all pythonnet/clr_loader + copy-metadata.
Pinnata pythonnet a 3.0.3 (l'ultima compatibile con PyInstaller
senza patch aggiuntive).
2026-06-09 12:11:42 +02:00
luzadev 9d21ca051f v1.7.4: DMG macOS con Fix Gatekeeper integrato
Macos ora viene distribuito come .dmg invece di .zip:
- contiene MusicTools.app + alias Applicazioni + "Fix Gatekeeper.command"
- doppio click sullo script rimuove com.apple.quarantine senza
  Terminal manuale -> niente piu' "App non verificata"

Backend: /api/download serve .dmg con Content-Type
application/x-apple-diskimage. Landing /download aggiornata
con il nuovo flusso (3 step).
2026-06-09 11:53:37 +02:00
7 changed files with 77 additions and 14 deletions

No files matched your search

+27 -6
View File
@@ -33,17 +33,38 @@ jobs:
- name: Build app
run: python build_macos.py
- name: Package .app -> zip
- name: Create DMG
run: |
cd dist
ditto -c -k --sequesterRsrc --keepParent MusicTools.app ../MusicTools-macOS.zip
ls -lh ../MusicTools-macOS.zip
STAGING="dmg_staging"
rm -rf "$STAGING"
mkdir -p "$STAGING"
cp -R dist/MusicTools.app "$STAGING/"
cp "assets/Fix Gatekeeper.command" "$STAGING/"
chmod +x "$STAGING/Fix Gatekeeper.command"
ln -s /Applications "$STAGING/Applications"
cat > "$STAGING/LEGGIMI.txt" <<'EOF'
INSTALLAZIONE MusicTools
========================
1) Trascina MusicTools.app sulla cartella "Applicazioni"
(l'alias e' qui dentro nel DMG)
2) Doppio click su "Fix Gatekeeper.command"
Rimuove la quarantena macOS Gatekeeper (una sola volta).
3) Apri MusicTools dalle Applicazioni e attiva con email + chiave.
Problemi? scrivici a info@djluza.com
EOF
hdiutil create -volname "MusicTools" -srcfolder "$STAGING" \
-ov -format UDZO MusicTools-macOS.dmg
ls -lh MusicTools-macOS.dmg
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: MusicTools-macOS
path: MusicTools-macOS.zip
path: MusicTools-macOS.dmg
retention-days: 14
# =========================================================
@@ -107,5 +128,5 @@ jobs:
generate_release_notes: true
fail_on_unmatched_files: true
files: |
artifacts/macos/MusicTools-macOS.zip
artifacts/macos/MusicTools-macOS.dmg
artifacts/windows/MusicTools-Windows.zip
+27
View File
@@ -0,0 +1,27 @@
#!/bin/bash
# Rimuove la quarantena Gatekeeper da MusicTools.app
# Doppio click in macOS apre Terminal ed esegue questo script.
set -e
APP_NAME="MusicTools.app"
# Cerca l'app in /Applications, poi nella stessa cartella del DMG montato.
if [ -d "/Applications/${APP_NAME}" ]; then
APP="/Applications/${APP_NAME}"
elif [ -d "$(dirname "$0")/${APP_NAME}" ]; then
APP="$(dirname "$0")/${APP_NAME}"
else
osascript -e "display alert \"${APP_NAME} non trovata\" message \"Trascina MusicTools.app nella cartella Applicazioni prima di eseguire questo script.\" as critical"
exit 1
fi
echo "Rimuovo la quarantena da: ${APP}"
xattr -dr com.apple.quarantine "${APP}" 2>/dev/null || true
# Notifica visuale
osascript -e "display notification \"MusicTools puo' essere aperta normalmente con doppio click.\" with title \"Fix completato\""
echo ""
echo "Fatto. Ora puoi aprire MusicTools normalmente con doppio click."
echo "Puoi chiudere questa finestra."
+10 -1
View File
@@ -115,11 +115,20 @@ def run_pyinstaller():
# Hidden imports per pywebview (EdgeChromium su Windows)
"--hidden-import", "webview",
"--hidden-import", "webview.platforms.edgechromium",
"--hidden-import", "webview.platforms.winforms",
"--hidden-import", "clr",
"--hidden-import", "clr_loader",
"--hidden-import", "requests",
# Collegamenti completi alle DLL .NET di pywebview/pythonnet
# Collegamenti completi: webview, pythonnet, clr_loader (porta
# con se Python.Runtime.dll + nethost.dll + runtimeconfig.json
# altrimenti winforms.py fallisce con "Failed to resolve
# Python.Runtime.Loader.Initialize ...")
"--collect-all", "webview",
"--collect-all", "pythonnet",
"--collect-all", "clr_loader",
"--collect-all", "mutagen",
"--copy-metadata", "pythonnet",
"--copy-metadata", "clr_loader",
# Binari bundled
*add_binaries,
# Entry point
+1 -1
View File
@@ -5,7 +5,7 @@ import os
import sys
from pathlib import Path
VERSION = "v1.7.3"
VERSION = "v1.7.5"
APP_NAME = "MusicTools"
+4 -4
View File
@@ -175,10 +175,10 @@
<div class="dl-steps">
<h2>Installazione macOS</h2>
<ol>
<li>Apri il file <code>.zip</code> scaricato — viene estratto in <code>MusicTools.app</code></li>
<li>Trascina <strong>MusicTools.app</strong> nella cartella <strong>Applicazioni</strong></li>
<li>Vai in Applicazioni, <strong>tasto destro</strong> su MusicTools → <strong>Apri</strong> → <strong>Apri</strong> (solo la prima volta, e' la procedura standard per app non firmate)</li>
<li>Inserisci email e chiave per attivare</li>
<li>Apri il file <code>.dmg</code> scaricato — si monta come volume "MusicTools"</li>
<li>Trascina <strong>MusicTools.app</strong> sull'alias <strong>Applicazioni</strong> dentro il DMG</li>
<li>Doppio click su <strong>Fix Gatekeeper.command</strong> (dentro il DMG): autorizza l'app in 1 click. Si chiude da sola appena finito.</li>
<li>Apri MusicTools dalle Applicazioni, inserisci email e chiave per attivare</li>
</ol>
</div>
+1 -1
View File
@@ -5,4 +5,4 @@ mutagen>=1.47.0
pyobjc-core>=10.0 ; sys_platform == "darwin"
pyobjc-framework-Cocoa>=10.0 ; sys_platform == "darwin"
pyobjc-framework-WebKit>=10.0 ; sys_platform == "darwin"
pythonnet>=3.0 ; sys_platform == "win32"
pythonnet==3.0.3 ; sys_platform == "win32"
+7 -1
View File
@@ -89,7 +89,13 @@ export async function download(req, res) {
}
const name = path.basename(abs);
res.setHeader("Content-Type", "application/zip");
const ext = path.extname(name).toLowerCase();
const contentType = ext === ".dmg"
? "application/x-apple-diskimage"
: ext === ".exe"
? "application/vnd.microsoft.portable-executable"
: "application/zip";
res.setHeader("Content-Type", contentType);
res.setHeader("Content-Disposition", `attachment; filename="${name}"`);
fs.createReadStream(abs).pipe(res);
}