feat: Add Neutralino desktop integration

This commit is contained in:
Julien Maille 2026-02-07 21:16:30 +01:00
parent 2e32f55b96
commit ff7b17b4eb
7 changed files with 1455 additions and 5 deletions

94
.github/workflows/desktop-build.yml vendored Normal file
View file

@ -0,0 +1,94 @@
name: Desktop Build
on:
push:
branches: [main, neutralino]
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: windows-latest
platform: windows
binary_source: Monochrome-win_x64.exe
binary_dest: Monochrome.exe
archive_ext: zip
- os: ubuntu-latest
platform: linux
binary_source: Monochrome-linux_x64
binary_dest: Monochrome
archive_ext: tar.gz
- os: macos-latest
platform: macos
binary_source: Monochrome-mac_universal
binary_dest: Monochrome
archive_ext: tar.gz
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Neutralino CLI
run: npm install -g @neutralinojs/neu
- name: Download Neutralino binaries
run: neu update
- name: Build application
run: neu build
- name: Prepare Release
run: |
mkdir release
cp dist/Monochrome/resources.neu release/
cp neutralino.config.json release/
cp dist/Monochrome/${{ matrix.binary_source }} release/${{ matrix.binary_dest }}
shell: bash
- name: Set Permissions (Linux/macOS)
if: matrix.platform != 'windows'
run: chmod +x release/${{ matrix.binary_dest }}
# Upload the uncompressed directory as the workflow artifact.
# GitHub will zip this automatically when downloaded, avoiding "zip inside zip".
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: Monochrome-${{ matrix.platform }}
path: release/
retention-days: 30
# Create an archive specifically for the GitHub Release (tags only)
- name: Create Release Archive (Windows)
if: startsWith(github.ref, 'refs/tags/v') && matrix.platform == 'windows'
run: |
Compress-Archive -Path release/* -DestinationPath monochrome-${{ matrix.platform }}-x64.zip
shell: pwsh
- name: Create Release Archive (Linux/macOS)
if: startsWith(github.ref, 'refs/tags/v') && matrix.platform != 'windows'
run: |
cd release
tar -czf ../monochrome-${{ matrix.platform }}-x64.tar.gz *
- name: Create Release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v1
with:
files: monochrome-${{ matrix.platform }}-x64.${{ matrix.archive_ext }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

7
.gitignore vendored
View file

@ -6,3 +6,10 @@ dist
# Docker
.env
# Neutralino
.tmp/
bin/
*.log
.storage/
auth_storage/

View file

@ -4,7 +4,7 @@ import prettierConfig from 'eslint-config-prettier';
export default [
{
ignores: ['dist/', 'node_modules/', 'legacy/', 'sw.js'],
ignores: ['**/dist/**', '**/node_modules/**', '**/legacy/**', '**/bin/**'],
},
js.configs.recommended,
prettierConfig,

View file

@ -378,6 +378,22 @@ document.addEventListener('DOMContentLoaded', async () => {
const { initTracker } = await loadTrackerModule();
initTracker(player);
// Initialize desktop environment (Neutralino)
if (window.Neutralino) {
await (async () => {
console.log('Initializing Neutralino desktop environment (Lite Mode)...');
try {
await Neutralino.init();
Neutralino.events.on('windowClose', () => {
Neutralino.app.exit();
});
console.log('Desktop environment initialized');
} catch (error) {
console.error('Failed to initialize desktop environment:', error);
}
})();
}
const castBtn = document.getElementById('cast-btn');
initializeCasting(audioPlayer, castBtn);
@ -497,6 +513,9 @@ document.addEventListener('DOMContentLoaded', async () => {
// Update UI with current track info for theme
ui.setCurrentTrack(player.currentTrack);
// Update Media Session with new track
updateMediaMetadata(player.currentTrack);
const currentTrackId = player.currentTrack.id;
if (currentTrackId === previousTrackId) return;
previousTrackId = currentTrackId;

41
neutralino.config.json Normal file
View file

@ -0,0 +1,41 @@
{
"applicationId": "com.monochrome.app",
"applicationName": "Monochrome",
"applicationIcon": "public/assets/512.png",
"author": "Monochrome",
"description": "Lossless music streaming",
"version": "1.0.0",
"defaultMode": "window",
"documentRoot": "public/",
"url": "https://monochrome.tf",
"enableServer": false,
"enableNativeAPI": true,
"tokenSecurity": "one-time",
"modes": {
"window": {
"title": "Monochrome",
"icon": "public/assets/512.png",
"width": 1280,
"height": 800,
"minWidth": 800,
"minHeight": 600,
"center": true,
"resizable": true,
"hidden": false,
"borderless": false,
"enableInspector": true,
"openInspectorOnStartup": false,
"exitProcessOnClose": true
}
},
"cli": {
"binaryName": "Monochrome",
"resourcesPath": "public/",
"binaryVersion": "6.5.0",
"clientVersion": "6.5.0"
},
"nativeAllowList": [
"app.exit",
"window.*"
]
}

1293
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,7 @@
},
"homepage": "https://github.com/SamidyFR/monochrome#readme",
"devDependencies": {
"@neutralinojs/neu": "^11.7.0",
"eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
"globals": "^17.0.0",
@ -44,6 +45,7 @@
"source-map": "^0.7.4"
},
"dependencies": {
"@neutralinojs/lib": "^6.5.0",
"cookie-session": "^2.1.0",
"jose": "^6.0.11",
"butterchurn": "^2.6.7",
@ -51,4 +53,4 @@
"dashjs": "^5.1.1",
"pocketbase": "^0.26.5"
}
}
}