From a981d90c680a6b1d8abf4b2038c45d73538465c2 Mon Sep 17 00:00:00 2001 From: Xaiya Schumin Date: Sun, 11 May 2025 21:44:54 +0200 Subject: [PATCH 01/23] =?UTF-8?q?=E2=9C=A8=F0=9F=9A=A7=20-=20Added=20nix?= =?UTF-8?q?=20packages=20with=20some=20bugs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xaiya Schumin --- .gitignore | 5 +++- flake.lock | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 21 +++++++++++++++ package.nix | 38 +++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 package.nix diff --git a/.gitignore b/.gitignore index 04c01ba..eb50cd0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ node_modules/ -dist/ \ No newline at end of file +dist/ + +# Jetbrains IDE +.idea/ \ No newline at end of file diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..35433bb --- /dev/null +++ b/flake.lock @@ -0,0 +1,76 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", + "type": "github" + }, + "original": { + "id": "flake-parts", + "type": "indirect" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1746978854, + "narHash": "sha256-FRqTP344StS/H3IDO33S221GC1gmsdKYfn4/VrAfSrc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "53b8217da3ef7b76d52b56aefed5de7f713c1072", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1743296961, + "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "systems": "systems" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..b21e83d --- /dev/null +++ b/flake.nix @@ -0,0 +1,21 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/release-24.11"; + systems.url = "github:nix-systems/default"; + }; + + outputs = inputs@{ self, systems, flake-parts, nixpkgs, ... }: flake-parts.lib.mkFlake { inherit inputs; } { + systems = import systems; + + imports = [ ./package.nix ]; + + perSystem = { config, pkgs, system, ... }: { + _module.args.pkgs = import inputs.nixpkgs { + inherit system; + overlays = [ self.overlays.default ]; + }; + + packages.default = pkgs.tidaLuna; + }; + }; +} \ No newline at end of file diff --git a/package.nix b/package.nix new file mode 100644 index 0000000..4216a3b --- /dev/null +++ b/package.nix @@ -0,0 +1,38 @@ +{ withSystem, ... }: { + flake.overlays.default = final: prev: + withSystem prev.stdenv.hostPlatform.system ( + { config, ... }: + let + injection = prev.fetchzip { + url = "https://github.com/Inrixia/TidaLuna/releases/download/1.1.0-alpha/luna.zip"; + sha256 = "bOjA+slsjYmG+kmjTgN8yYKJCciwsnGHZ7kjozC4ZiA="; + stripRoot = false; + }; + in + { + tidaLuna = prev.tidal-hifi.overrideAttrs (old: { + installPhase = '' + runHook preInstall + + # Default installation from tidal-hifi + mkdir -p "$out/bin" + cp -R "opt" "$out" + cp -R "usr/share" "$out/share" + + # Rename app.asar to original.asar + mv $out/opt/tidal-hifi/resources/app.asar $out/opt/tidal-hifi/resources/original.asar + + # Move injection into app folder + mkdir -p "$out/opt/tidal-hifi/resources/app/" + cp -R ${injection}/* $out/opt/tidal-hifi/resources/app/ + + chmod -R g-w "$out" + + runHook postInstall + ''; + + tidaLuna = final.tidal-hifi; + }); + } + ); +} \ No newline at end of file From 985a028f7a75fef0533bb108ba3a1940985bf4c2 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Mon, 19 May 2025 23:42:38 +1200 Subject: [PATCH 02/23] Ensure liveReload is disabled on load --- render/src/LunaPlugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/src/LunaPlugin.ts b/render/src/LunaPlugin.ts index b52219c..6d9ea56 100644 --- a/render/src/LunaPlugin.ts +++ b/render/src/LunaPlugin.ts @@ -108,7 +108,7 @@ export class LunaPlugin { if (name in this.plugins) return this.plugins[name]; // Disable liveReload on load so people dont accidentally leave it on - storeInit.liveReload ??= false; + storeInit.liveReload = false; const store = await LunaPlugin.pluginStorage.getReactive(name); Object.assign(store, storeInit); From 6c1fdce5c6ebac391439db86f8ae2361bc59a8d6 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Mon, 19 May 2025 23:42:48 +1200 Subject: [PATCH 03/23] Expose MediaItem.availableTags --- plugins/lib/src/classes/MediaItem/MediaItem.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/lib/src/classes/MediaItem/MediaItem.ts b/plugins/lib/src/classes/MediaItem/MediaItem.ts index 081092f..5c3e6c8 100644 --- a/plugins/lib/src/classes/MediaItem/MediaItem.ts +++ b/plugins/lib/src/classes/MediaItem/MediaItem.ts @@ -13,7 +13,7 @@ import { PlayState } from "../PlayState"; import { Quality } from "../Quality"; import { TidalApi } from "../TidalApi"; import { download, downloadProgress } from "./MediaItem.download.native"; -import { makeTags, MetaTags } from "./MediaItem.tags"; +import { availableTags, makeTags, MetaTags } from "./MediaItem.tags"; type MediaFormat = { bitDepth?: number; @@ -29,6 +29,7 @@ type MediaItemCache = { export class MediaItem extends ContentBase { public static readonly trace: Tracer = libTrace.withSource(".MediaItem").trace; + public static readonly availableTags = availableTags; private static cache = ReactiveStore.getStore("@luna/MediaItemCache"); From 98b7912e63206d9a28e2f1001e10588ffbbed3a8 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Tue, 20 May 2025 00:06:24 +1200 Subject: [PATCH 04/23] LunaButtonSetting use props.title if children undefined --- plugins/ui/src/components/settings/LunaButtonSetting.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ui/src/components/settings/LunaButtonSetting.tsx b/plugins/ui/src/components/settings/LunaButtonSetting.tsx index 68bbeef..cc9e3f3 100644 --- a/plugins/ui/src/components/settings/LunaButtonSetting.tsx +++ b/plugins/ui/src/components/settings/LunaButtonSetting.tsx @@ -20,7 +20,7 @@ export const LunaButtonSetting = React.memo((props: LunaButtonSettingProps) => ( height: 40, ...props.sx, }} - children={props.children} + children={props.children ?? props.title} /> } /> From 576706a68b1b25859d1317348ec96fd9bf5ed0bc Mon Sep 17 00:00:00 2001 From: Inrixia Date: Tue, 20 May 2025 00:21:03 +1200 Subject: [PATCH 05/23] LunaStore fix support for spaces in plugin names --- package.json | 2 +- plugins/ui/src/SettingsPage/PluginStoreTab/LunaStore.tsx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c5dea64..da6b577 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "luna", - "version": "1.2.6-alpha", + "version": "1.2.6-alpha-hotfix", "description": "A client mod for the Tidal music app for plugins", "author": { "name": "Inrixia", diff --git a/plugins/ui/src/SettingsPage/PluginStoreTab/LunaStore.tsx b/plugins/ui/src/SettingsPage/PluginStoreTab/LunaStore.tsx index 67cae90..df028b9 100644 --- a/plugins/ui/src/SettingsPage/PluginStoreTab/LunaStore.tsx +++ b/plugins/ui/src/SettingsPage/PluginStoreTab/LunaStore.tsx @@ -82,7 +82,9 @@ export const LunaStore = React.memo(({ url, onRemove }: { url: string; onRemove: } /> - {pkg?.plugins.map((plugin) => } />)} + {pkg?.plugins.map((plugin) => ( + } /> + ))} ); From b2b52a7f5ed1a7edb0befbd710f468122bd93232 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Tue, 20 May 2025 01:28:51 +1200 Subject: [PATCH 06/23] Fix TidalApi.albumItems/Album.mediaItems --- package.json | 2 +- plugins/lib/src/classes/Album.ts | 4 ++-- plugins/lib/src/classes/TidalApi/index.ts | 12 ++++++++++-- .../lib/src/classes/TidalApi/types/AlbumPage.ts | 15 +++++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 plugins/lib/src/classes/TidalApi/types/AlbumPage.ts diff --git a/package.json b/package.json index da6b577..157dd47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "luna", - "version": "1.2.6-alpha-hotfix", + "version": "1.2.7-alpha", "description": "A client mod for the Tidal music app for plugins", "author": { "name": "Inrixia", diff --git a/plugins/lib/src/classes/Album.ts b/plugins/lib/src/classes/Album.ts index 6645d4c..0bf1476 100644 --- a/plugins/lib/src/classes/Album.ts +++ b/plugins/lib/src/classes/Album.ts @@ -82,8 +82,8 @@ export class Album extends ContentBase implements MediaCollection { return this.tidalAlbum.numberOfTracks!; } public tMediaItems: () => Promise = memoize(async () => { - const playlistIitems = await TidalApi.albumItems(this.id); - return playlistIitems?.items ?? []; + const albumItems = await TidalApi.albumItems(this.id); + return albumItems ?? []; }); public async mediaItems() { return MediaItem.fromTMediaItems(await this.tMediaItems()); diff --git a/plugins/lib/src/classes/TidalApi/index.ts b/plugins/lib/src/classes/TidalApi/index.ts index 4304fb3..2147b11 100644 --- a/plugins/lib/src/classes/TidalApi/index.ts +++ b/plugins/lib/src/classes/TidalApi/index.ts @@ -8,6 +8,7 @@ import { getCredentials } from "../../helpers"; import { libTrace } from "../../index.safe"; import * as redux from "../../redux"; +import type { AlbumPage } from "./types/AlbumPage"; import { PlaybackInfoResponse } from "./types/PlaybackInfo"; export type * from "./types"; @@ -61,9 +62,16 @@ export class TidalApi { return this.fetch(`https://desktop.tidal.com/v1/albums/${albumId}?${this.queryArgs()}`); } public static async albumItems(albumId: redux.ItemId) { - return this.fetch<{ items: redux.MediaItem[]; totalNumberOfItems: number; offset: number; limit: -1 }>( - `https://desktop.tidal.com/v1/albums/${albumId}/items?${this.queryArgs()}&limit=-1`, + const albumPage = await this.fetch( + `https://desktop.tidal.com/v1/pages/album?albumId=${albumId}&countryCode=NZ&locale=en_US&deviceType=DESKTOP`, ); + for (const row of albumPage?.rows ?? []) { + for (const module of row.modules) { + if (module.type === "ALBUM_ITEMS" && module.pagedList) { + return module.pagedList.items; + } + } + } } public static playlist(playlistUUID: redux.ItemId) { diff --git a/plugins/lib/src/classes/TidalApi/types/AlbumPage.ts b/plugins/lib/src/classes/TidalApi/types/AlbumPage.ts new file mode 100644 index 0000000..a3f40c1 --- /dev/null +++ b/plugins/lib/src/classes/TidalApi/types/AlbumPage.ts @@ -0,0 +1,15 @@ +import type { redux } from "@luna/lib"; + +export type AlbumPage = { + id: string; + title: string; + rows: { + modules: { + /** ALBUM_ITEMS is what we want */ + type: string; + pagedList?: { + items: redux.MediaItem[]; + }; + }[]; + }[]; +}; From 5d51cdfb82c564f33948cc054859db7423d68153 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Tue, 20 May 2025 15:41:42 +1200 Subject: [PATCH 07/23] Improve MediaItem date parsing for releaseDate --- plugins/lib/src/classes/MediaItem/MediaItem.ts | 15 +++++++++------ plugins/lib/src/helpers/index.ts | 1 + plugins/lib/src/helpers/parseDate.ts | 6 ++++++ 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 plugins/lib/src/helpers/parseDate.ts diff --git a/plugins/lib/src/classes/MediaItem/MediaItem.ts b/plugins/lib/src/classes/MediaItem/MediaItem.ts index 5c3e6c8..d155786 100644 --- a/plugins/lib/src/classes/MediaItem/MediaItem.ts +++ b/plugins/lib/src/classes/MediaItem/MediaItem.ts @@ -3,7 +3,7 @@ import type { IRecording, ITrack } from "musicbrainz-api"; import { ftch, ReactiveStore, type Tracer } from "@luna/core"; -import { getPlaybackInfo, type PlaybackInfo } from "../../helpers"; +import { getPlaybackInfo, parseDate, type PlaybackInfo } from "../../helpers"; import { libTrace, unloads } from "../../index.safe"; import * as redux from "../../redux"; import { Album } from "../Album"; @@ -260,17 +260,20 @@ export class MediaItem extends ContentBase { }); public releaseDate: () => Promise = memoize(async () => { - let releaseDate = this.tidalItem.releaseDate ?? this.tidalItem.streamStartDate; + let releaseDate = parseDate(this.tidalItem.releaseDate) ?? parseDate(this.tidalItem.streamStartDate); if (releaseDate === undefined) { const brainzItem = await this.brainzItem(); - releaseDate = brainzItem?.recording?.["first-release-date"] ?? releaseDate; + releaseDate = parseDate(brainzItem?.recording?.["first-release-date"]); } if (releaseDate === undefined) { const album = await this.album(); - releaseDate = album?.releaseDate ?? releaseDate; - releaseDate ??= (await album?.brainzAlbum())?.date ?? releaseDate; + releaseDate = parseDate(album?.releaseDate); + if (releaseDate === undefined) { + const brainzAlbum = await album?.brainzAlbum(); + releaseDate ??= parseDate(brainzAlbum?.date); + } } - if (releaseDate) return new Date(releaseDate); + return releaseDate; }); /** diff --git a/plugins/lib/src/helpers/index.ts b/plugins/lib/src/helpers/index.ts index 7e4b1f7..b38e3d3 100644 --- a/plugins/lib/src/helpers/index.ts +++ b/plugins/lib/src/helpers/index.ts @@ -2,4 +2,5 @@ export * from "./getCredentials"; export * from "./getPlaybackInfo"; export * from "./getPlaybackInfo.dasha.native"; export * from "./observable"; +export * from "./parseDate"; export * from "./safeTimeout"; diff --git a/plugins/lib/src/helpers/parseDate.ts b/plugins/lib/src/helpers/parseDate.ts new file mode 100644 index 0000000..54bee04 --- /dev/null +++ b/plugins/lib/src/helpers/parseDate.ts @@ -0,0 +1,6 @@ +export const parseDate = (date: string | Date | null | undefined): Date | undefined => { + if (date === null || date === undefined) return undefined; + if (typeof date === "string") date = new Date(date); + if (isNaN(date.getTime())) return undefined; + return date; +}; From c4f8bd713eadff7958517b4ecb6d6f749713d3f7 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Tue, 20 May 2025 15:42:05 +1200 Subject: [PATCH 08/23] Add unloads to observable --- package.json | 2 +- plugins/lib/src/helpers/observable.ts | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 157dd47..21c5f0e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "luna", - "version": "1.2.7-alpha", + "version": "1.2.8-alpha", "description": "A client mod for the Tidal music app for plugins", "author": { "name": "Inrixia", diff --git a/plugins/lib/src/helpers/observable.ts b/plugins/lib/src/helpers/observable.ts index 94bd26d..b974939 100644 --- a/plugins/lib/src/helpers/observable.ts +++ b/plugins/lib/src/helpers/observable.ts @@ -1,6 +1,7 @@ // based on: https://github.com/KaiHax/kaihax/blob/master/src/patcher.ts import type { VoidFn } from "@inrixia/helpers"; +import type { LunaUnloads } from "@luna/core"; import { unloads } from "../index.safe"; export type ObserveCallback = (elem: E) => unknown; @@ -31,7 +32,7 @@ const observer = new MutationObserver((records) => { * @param cb The callback function to execute when a matching element is found cast to type T. * @returns An `Unload` function that, when called, will stop observing for this selector and callback pair. */ -export const observe = (selector: string, cb: ObserveCallback): VoidFn => { +export const observe = (unloads: LunaUnloads, selector: string, cb: ObserveCallback): VoidFn => { if (observables.size === 0) observer.observe(document.body, { subtree: true, @@ -39,10 +40,12 @@ export const observe = (selector: string, cb: Obser }); const entry: ObserveEntry = [selector, cb as ObserveCallback]; observables.add(entry); - return () => { + const unload = () => { observables.delete(entry); if (observables.size === 0) observer.disconnect(); }; + unloads.add(unload); + return unload; }; // Disconnect and remove observables on unload @@ -56,9 +59,9 @@ unloads.add(observables.clear.bind(observables)); * @param timeoutMs The maximum time (in milliseconds) to wait for the element to appear. * @returns A Promise that resolves with the found Element (cast to type T) or null if the timeout is reached. */ -export const observePromise = (selector: string, timeoutMs: number = 1000): Promise => +export const observePromise = (unloads: LunaUnloads, selector: string, timeoutMs: number = 1000): Promise => new Promise((res) => { - const unob = observe(selector, (elem) => { + const unob = observe(unloads, selector, (elem) => { unob(); clearTimeout(timeout); res(elem as T); From f8c3d632048f729a98c3ab3c245a9cad2644edd4 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Tue, 20 May 2025 17:20:50 +1200 Subject: [PATCH 09/23] Fix missing unloads for observe in @luna/lib --- plugins/lib/src/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/lib/src/index.ts b/plugins/lib/src/index.ts index 5d26b8d..15fa195 100644 --- a/plugins/lib/src/index.ts +++ b/plugins/lib/src/index.ts @@ -8,7 +8,9 @@ export * as redux from "./redux"; import { observePromise } from "./helpers/observable"; -observePromise("div[class^='_mainContainer'] > div[class^='_bar'] > div[class^='_title']", 30000).then((title) => { +import { unloads} from "./index.safe"; + +observePromise(unloads, "div[class^='_mainContainer'] > div[class^='_bar'] > div[class^='_title']", 30000).then((title) => { if (title !== null) title.innerHTML = 'TIDALuna BETA'; }); From 902ae5dbe980a051471d269a3b030574ee31ac3b Mon Sep 17 00:00:00 2001 From: Xaiya Schumin Date: Tue, 20 May 2025 13:32:39 +0200 Subject: [PATCH 10/23] =?UTF-8?q?=E2=9C=A8=20-=20Software=20is=20now=20bui?= =?UTF-8?q?lded=20in=20git=20-=20Version=20will=20now=20be=20updated=20in?= =?UTF-8?q?=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xaiya Schumin --- .github/workflows/releaseDev.yml | 8 ++++++ .github/workflows/releaseMaster.yml | 9 +++++++ flake.nix | 6 +++-- package.nix => nix/default.nix | 10 +++---- nix/package.nix | 41 +++++++++++++++++++++++++++++ 5 files changed, 65 insertions(+), 9 deletions(-) rename package.nix => nix/default.nix (76%) create mode 100644 nix/package.nix diff --git a/.github/workflows/releaseDev.yml b/.github/workflows/releaseDev.yml index 0af21bb..72a2a1a 100644 --- a/.github/workflows/releaseDev.yml +++ b/.github/workflows/releaseDev.yml @@ -37,3 +37,11 @@ jobs: prerelease: true title: Release ${{ env.VERSION }} files: ./dist/luna.zip + + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v18 + - uses: workflow/nix-shell-action@v3 + with: + packages: nix-update + script: | + nix-update --flake --version=unstable --subpackage pnpmDeps injection diff --git a/.github/workflows/releaseMaster.yml b/.github/workflows/releaseMaster.yml index d715a27..39a43ee 100644 --- a/.github/workflows/releaseMaster.yml +++ b/.github/workflows/releaseMaster.yml @@ -37,3 +37,12 @@ jobs: prerelease: false title: Release ${{ env.VERSION }} files: ./dist/luna.zip + + + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v18 + - uses: workflow/nix-shell-action@v3 + with: + packages: nix-update + script: | + nix-update --flake --version=unstable --subpackage pnpmDeps injection diff --git a/flake.nix b/flake.nix index b21e83d..f0e0032 100644 --- a/flake.nix +++ b/flake.nix @@ -1,13 +1,13 @@ { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/release-24.11"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; systems.url = "github:nix-systems/default"; }; outputs = inputs@{ self, systems, flake-parts, nixpkgs, ... }: flake-parts.lib.mkFlake { inherit inputs; } { systems = import systems; - imports = [ ./package.nix ]; + imports = [ ./nix ]; perSystem = { config, pkgs, system, ... }: { _module.args.pkgs = import inputs.nixpkgs { @@ -15,6 +15,8 @@ overlays = [ self.overlays.default ]; }; + packages.injection = + pkgs.callPackage ./nix/package.nix { inherit (pkgs) nodejs fetchFromGitHub; pnpm = pkgs.pnpm_9; }; packages.default = pkgs.tidaLuna; }; }; diff --git a/package.nix b/nix/default.nix similarity index 76% rename from package.nix rename to nix/default.nix index 4216a3b..025e17b 100644 --- a/package.nix +++ b/nix/default.nix @@ -3,11 +3,7 @@ withSystem prev.stdenv.hostPlatform.system ( { config, ... }: let - injection = prev.fetchzip { - url = "https://github.com/Inrixia/TidaLuna/releases/download/1.1.0-alpha/luna.zip"; - sha256 = "bOjA+slsjYmG+kmjTgN8yYKJCciwsnGHZ7kjozC4ZiA="; - stripRoot = false; - }; + injection = prev.callPackage ./package.nix { nodejs = prev.nodejs; pnpm = prev.pnpm_9; }; in { tidaLuna = prev.tidal-hifi.overrideAttrs (old: { @@ -26,7 +22,6 @@ mkdir -p "$out/opt/tidal-hifi/resources/app/" cp -R ${injection}/* $out/opt/tidal-hifi/resources/app/ - chmod -R g-w "$out" runHook postInstall ''; @@ -35,4 +30,5 @@ }); } ); -} \ No newline at end of file +} + diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 0000000..51d3535 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,41 @@ +{ stdenv, nodejs, pnpm, fetchFromGitHub, ... }: +stdenv.mkDerivation (finalAttrs: rec { + name = "TidaLuna"; + pname = "${name}"; + version = "1.1.0-alpha"; + src = fetchFromGitHub { + owner = "Inrixia"; + repo = "${name}"; + rev = "${version}"; + hash = "sha256-T6J6mI3oxQ7tD8b76M15ajka1S8G9QW8Am3rqj0MaTo="; + }; + + nativeBuildInputs = [ + nodejs + pnpm.configHook + ]; + + pnpmDeps = pnpm.fetchDeps { + inherit (finalAttrs) pname src version; + hash = "sha256-pnuDLjUAOxQUFlf+2FXeX2mpZcahzzVPMRpWZpbyDE4="; + }; + + buildPhase = '' + runHook preBuild + + pnpm install + pnpm run build + + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + cp -R "dist" "$out" + + runHook postInstall + ''; + +}) From 205dcf9d22cade1bee0da3b05dbced61dc3c8a30 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Sun, 25 May 2025 11:26:07 +1200 Subject: [PATCH 11/23] Fix missing unloads for ContextMenu observePromise --- plugins/lib/src/classes/ContextMenu.ts | 2 +- plugins/lib/src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/lib/src/classes/ContextMenu.ts b/plugins/lib/src/classes/ContextMenu.ts index 6ac63e0..9e4db73 100644 --- a/plugins/lib/src/classes/ContextMenu.ts +++ b/plugins/lib/src/classes/ContextMenu.ts @@ -19,7 +19,7 @@ export class ContextMenu { * Will return null if the element is not found (usually means no context menu is open) */ public static async getCurrent() { - const contextMenu = await observePromise(`[data-type="list-container__context-menu"]`, 1000); + const contextMenu = await observePromise(unloads, `[data-type="list-container__context-menu"]`, 1000); if (contextMenu !== null) { const templateButton = contextMenu.querySelector(`div[data-type="contextmenu-item"]`) as Element | undefined; contextMenu.addButton = (text, onClick) => { diff --git a/plugins/lib/src/index.ts b/plugins/lib/src/index.ts index 15fa195..ec6cb80 100644 --- a/plugins/lib/src/index.ts +++ b/plugins/lib/src/index.ts @@ -8,7 +8,7 @@ export * as redux from "./redux"; import { observePromise } from "./helpers/observable"; -import { unloads} from "./index.safe"; +import { unloads } from "./index.safe"; observePromise(unloads, "div[class^='_mainContainer'] > div[class^='_bar'] > div[class^='_title']", 30000).then((title) => { if (title !== null) title.innerHTML = 'TIDALuna BETA'; From 0340fdef7d49b008cb7d4da78843a56c8731ca95 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Sun, 25 May 2025 11:33:31 +1200 Subject: [PATCH 12/23] @luna/ui properly indicate when plugins are loaded from dev url --- plugins/ui/src/SettingsPage/PluginsTab/LunaPluginSettings.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/ui/src/SettingsPage/PluginsTab/LunaPluginSettings.tsx b/plugins/ui/src/SettingsPage/PluginsTab/LunaPluginSettings.tsx index bd817bb..dc865ee 100644 --- a/plugins/ui/src/SettingsPage/PluginsTab/LunaPluginSettings.tsx +++ b/plugins/ui/src/SettingsPage/PluginsTab/LunaPluginSettings.tsx @@ -51,9 +51,11 @@ export const LunaPluginSettings = React.memo(({ plugin }: { plugin: LunaPlugin } const disabled = !enabled || loading; + const isDev = plugin.store.url.startsWith("http://127.0.0.1"); + const author = pkg.author; const desc = pkg.description; - const name = pkg.name; + const name = isDev ? `${pkg.name} [DEV]` : pkg.name; const link = pkg.homepage ?? pkg.repository?.url; // Dont allow disabling core plugins From 3470ee423435736301ebec44d0d7eacd0f56ca93 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Sun, 25 May 2025 11:52:34 +1200 Subject: [PATCH 13/23] Show version/dev in plugin header --- .../src/SettingsPage/PluginStoreTab/LunaStorePlugin.tsx | 3 +++ .../ui/src/SettingsPage/PluginsTab/LunaPluginHeader.tsx | 8 ++++++-- .../ui/src/SettingsPage/PluginsTab/LunaPluginSettings.tsx | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/plugins/ui/src/SettingsPage/PluginStoreTab/LunaStorePlugin.tsx b/plugins/ui/src/SettingsPage/PluginStoreTab/LunaStorePlugin.tsx index 5d505a2..5a63e77 100644 --- a/plugins/ui/src/SettingsPage/PluginStoreTab/LunaStorePlugin.tsx +++ b/plugins/ui/src/SettingsPage/PluginStoreTab/LunaStorePlugin.tsx @@ -18,6 +18,8 @@ export const LunaStorePlugin = React.memo(({ url }: { url: string }) => { if (!plugin) return null; + const version = url.startsWith("http://127.0.0.1") ? `${plugin.package?.version ?? ""} [DEV]` : plugin.package?.version; + return ( setIsHovered(true)} @@ -41,6 +43,7 @@ export const LunaStorePlugin = React.memo(({ url }: { url: string }) => { ( +export const LunaPluginHeader = React.memo(({ name, version, loadError, author, desc, children, sx, link }: LunaPluginComponentProps) => ( - } /> + + {name} + {version && } + {children} {loadError && ( Date: Sun, 25 May 2025 11:55:45 +1200 Subject: [PATCH 14/23] Add @jxnxsdev & @wont-stream stores --- package.json | 2 +- plugins/ui/src/SettingsPage/PluginStoreTab/index.tsx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 21c5f0e..8d5907b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "luna", - "version": "1.2.8-alpha", + "version": "1.2.9-alpha", "description": "A client mod for the Tidal music app for plugins", "author": { "name": "Inrixia", diff --git a/plugins/ui/src/SettingsPage/PluginStoreTab/index.tsx b/plugins/ui/src/SettingsPage/PluginStoreTab/index.tsx index 2d4c465..b3c56c8 100644 --- a/plugins/ui/src/SettingsPage/PluginStoreTab/index.tsx +++ b/plugins/ui/src/SettingsPage/PluginStoreTab/index.tsx @@ -18,8 +18,10 @@ export const addToStores = (url: string) => { }; // Devs! Add your stores here <3 -// TODO: Abstract this to a git repo with versioned stores +// TODO: Abstract this to a git repo addToStores("https://github.com/Inrixia/neptune-plugins/releases/download/dev/store.json"); +addToStores("https://github.com/wont-stream/lunar/releases/download/dev/store.json"); +addToStores("https://github.com/jxnxsdev/luna-plugins/releases/download/latest/store.json"); export const PluginStoreTab = React.memo(() => { const [_storeUrls, setPluginStores] = useState(obyStore.unwrap(storeUrls)); From c0d675305ba5ff3c6c38f31873b7e27e482cf674 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Sun, 25 May 2025 12:10:25 +1200 Subject: [PATCH 15/23] Fix MediaItem.contentType undefined --- .../classes/MediaItem/MediaItem.download.native.ts | 2 +- plugins/lib/src/classes/MediaItem/MediaItem.ts | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/plugins/lib/src/classes/MediaItem/MediaItem.download.native.ts b/plugins/lib/src/classes/MediaItem/MediaItem.download.native.ts index 72317de..4c9cd20 100644 --- a/plugins/lib/src/classes/MediaItem/MediaItem.download.native.ts +++ b/plugins/lib/src/classes/MediaItem/MediaItem.download.native.ts @@ -13,7 +13,7 @@ import type { PlaybackInfo } from "../../helpers"; import type { MetaTags } from "./MediaItem.tags"; const downloads: Record } | undefined> = {}; -export const downloadProgress = async (trackId: redux.ItemId) => downloads[trackId]; +export const downloadProgress = async (trackId: redux.ItemId) => downloads[trackId]?.progress; export const download = async (playbackInfo: PlaybackInfo, path: string, tags?: MetaTags): Promise => { if (downloads[playbackInfo.trackId] !== undefined) return downloads[playbackInfo.trackId]!.promise; try { diff --git a/plugins/lib/src/classes/MediaItem/MediaItem.ts b/plugins/lib/src/classes/MediaItem/MediaItem.ts index d155786..1789ce2 100644 --- a/plugins/lib/src/classes/MediaItem/MediaItem.ts +++ b/plugins/lib/src/classes/MediaItem/MediaItem.ts @@ -56,7 +56,7 @@ export class MediaItem extends ContentBase { return super.fromStore(itemId, "mediaItems", async (mediaItem) => { mediaItem = mediaItem ??= await this.fetchMediaItem(itemId, contentType); if (mediaItem === undefined) return; - return new MediaItem(itemId, mediaItem, await mediaItemCache); + return new MediaItem(itemId, mediaItem, contentType, await mediaItemCache); }); } public static fromIsrc: (isrc: string) => Promise = memoize(async (isrc) => { @@ -146,6 +146,7 @@ export class MediaItem extends ContentBase { constructor( public readonly id: redux.ItemId, tidalMediaItem: redux.MediaItem, + public readonly contentType: redux.ContentType, private readonly cache: MediaItemCache, ) { super(); @@ -231,7 +232,7 @@ export class MediaItem extends ContentBase { }); public async *isrcs(): AsyncIterable { - if (this.tidalItem.contentType !== "track") return; + if (this.contentType !== "track") return; const seen = new Set(); if (this.tidalItem.isrc) { yield this.tidalItem.isrc; @@ -302,9 +303,6 @@ export class MediaItem extends ContentBase { // #endregion // #region Properties - public get contentType() { - return this.tidalItem.contentType; - } public get trackNumber() { return this.tidalItem.trackNumber; } @@ -315,18 +313,18 @@ export class MediaItem extends ContentBase { return this.tidalItem.peak; } public get replayGain(): number { - if (this.tidalItem.contentType !== "track") return 0; + if (this.contentType !== "track") return 0; return this.tidalItem.replayGain; } public get url(): string { return this.tidalItem.url; } public get qualityTags(): Quality[] { - if (this.tidalItem.contentType !== "track") return []; + if (this.contentType !== "track") return []; return Quality.fromMetaTags(this.tidalItem.mediaMetadata?.tags); } public get bestQuality(): Quality { - if (this.tidalItem.contentType !== "track") { + if (this.contentType !== "track") { this.trace.warn("MediaItem quality called on non-track!", this); return Quality.High; } From a4f0f06c2b3540a5bdf4835521632fd8d1e1bb09 Mon Sep 17 00:00:00 2001 From: Xaiya Schumin Date: Mon, 26 May 2025 18:35:41 +0200 Subject: [PATCH 16/23] =?UTF-8?q?=F0=9F=90=9B=F0=9F=9A=80=20Fixed=20instal?= =?UTF-8?q?l=20hook,=20now=20using=20postInstall=20which=20will=20not=20br?= =?UTF-8?q?eak=20things?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xaiya Schumin --- flake.lock | 8 ++++---- flake.nix | 2 +- nix/default.nix | 18 ++++-------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/flake.lock b/flake.lock index 35433bb..078da89 100644 --- a/flake.lock +++ b/flake.lock @@ -19,16 +19,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1746978854, - "narHash": "sha256-FRqTP344StS/H3IDO33S221GC1gmsdKYfn4/VrAfSrc=", + "lastModified": 1748186667, + "narHash": "sha256-UQubDNIQ/Z42R8tPCIpY+BOhlxO8t8ZojwC9o2FW3c8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "53b8217da3ef7b76d52b56aefed5de7f713c1072", + "rev": "bdac72d387dca7f836f6ef1fe547755fb0e9df61", "type": "github" }, "original": { "owner": "NixOS", - "ref": "release-24.11", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index f0e0032..66c930d 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,6 @@ { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; systems.url = "github:nix-systems/default"; }; diff --git a/nix/default.nix b/nix/default.nix index 025e17b..543d0e6 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -7,23 +7,13 @@ in { tidaLuna = prev.tidal-hifi.overrideAttrs (old: { - installPhase = '' - runHook preInstall - - # Default installation from tidal-hifi - mkdir -p "$out/bin" - cp -R "opt" "$out" - cp -R "usr/share" "$out/share" - + postInstall = '' # Rename app.asar to original.asar - mv $out/opt/tidal-hifi/resources/app.asar $out/opt/tidal-hifi/resources/original.asar + mv $out/share/tidal-hifi/resources/app.asar $out/share/tidal-hifi/resources/original.asar # Move injection into app folder - mkdir -p "$out/opt/tidal-hifi/resources/app/" - cp -R ${injection}/* $out/opt/tidal-hifi/resources/app/ - - - runHook postInstall + mkdir -p "$out/share/tidal-hifi/resources/app/" + cp -R ${injection}/* $out/share/tidal-hifi/resources/app/ ''; tidaLuna = final.tidal-hifi; From 74ebdd90ea80a231e24bdf0d77e2c7a446e986da Mon Sep 17 00:00:00 2001 From: Xaiya Schumin Date: Mon, 26 May 2025 20:03:40 +0200 Subject: [PATCH 17/23] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB?= =?UTF-8?q?=F0=9F=94=A8=20-=20Changed=20injection=20version=20for=20develo?= =?UTF-8?q?ping=20-=20Added=20devenv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xaiya Schumin --- .envrc | 7 ++ .gitignore | 17 ++- .vscode/settings.json | 10 -- devenv.lock | 103 ++++++++++++++++++ devenv.nix | 13 +++ devenv.yaml | 5 + flake.lock | 245 ++++++++++++++++++++++++++++++++++++++++-- flake.nix | 7 +- native/injector.ts | 4 + nix/package.nix | 9 +- result | 1 + 11 files changed, 395 insertions(+), 26 deletions(-) create mode 100644 .envrc delete mode 100644 .vscode/settings.json create mode 100644 devenv.lock create mode 100644 devenv.nix create mode 100644 devenv.yaml create mode 120000 result diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..e3c2943 --- /dev/null +++ b/.envrc @@ -0,0 +1,7 @@ +export DIRENV_WARN_TIMEOUT=20s + +eval "$(devenv direnvrc)" + +# The use_devenv function supports passing flags to the devenv command +# For example: use devenv --impure --option services.postgres.enable:bool true +use devenv diff --git a/.gitignore b/.gitignore index eb50cd0..d8dec56 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,18 @@ node_modules/ dist/ +result/ -# Jetbrains IDE -.idea/ \ No newline at end of file +# IDEs +.idea/ +.vscode/ + +# Devenv +.devenv* +devenv.local.nix + + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a1a7bdf..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "exportall.config.folderListener": [ - "/plugins/ui/src/components", - "/plugins/ui/src/components/settings", - "/plugins/ui/src/helpers", - "/plugins/lib/src/helpers", - "/plugins/lib/src/classes", - "/plugins/lib/src/redux" - ] -} diff --git a/devenv.lock b/devenv.lock new file mode 100644 index 0000000..c4b1cb2 --- /dev/null +++ b/devenv.lock @@ -0,0 +1,103 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1748273445, + "owner": "cachix", + "repo": "devenv", + "rev": "668a50d8b7bdb19a0131f53c9f6c25c9071e1ffb", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1747046372, + "owner": "edolstra", + "repo": "flake-compat", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1747372754, + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1746807397, + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "c5208b594838ea8e6cca5997fbf784b7cca1ca90", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "git-hooks": "git-hooks", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": [ + "git-hooks" + ] + } + } + }, + "root": "root", + "version": 7 +} diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 0000000..6dbfa9f --- /dev/null +++ b/devenv.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: + +{ + languages.javascript = { + enable = true; + corepack.enable = true; + pnpm = { + enable = true; + install.enable = true; + }; + + }; +} diff --git a/devenv.yaml b/devenv.yaml new file mode 100644 index 0000000..c8da167 --- /dev/null +++ b/devenv.yaml @@ -0,0 +1,5 @@ +inputs: + nixpkgs: + url: github:cachix/devenv-nixpkgs/rolling + +allowUnfree: true diff --git a/flake.lock b/flake.lock index 078da89..d93bf7c 100644 --- a/flake.lock +++ b/flake.lock @@ -1,6 +1,94 @@ { "nodes": { + "cachix": { + "inputs": { + "devenv": [ + "devenv" + ], + "flake-compat": [ + "devenv" + ], + "git-hooks": [ + "devenv" + ], + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1744206633, + "narHash": "sha256-pb5aYkE8FOoa4n123slgHiOf1UbNSnKe5pEZC+xXD5g=", + "owner": "cachix", + "repo": "cachix", + "rev": "8a60090640b96f9df95d1ab99e5763a586be1404", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "latest", + "repo": "cachix", + "type": "github" + } + }, + "devenv": { + "inputs": { + "cachix": "cachix", + "flake-compat": "flake-compat", + "git-hooks": "git-hooks", + "nix": "nix", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1748273445, + "narHash": "sha256-5V0dzpNgQM0CHDsMzh+ludYeu1S+Y+IMjbaskSSdFh0=", + "owner": "cachix", + "repo": "devenv", + "rev": "668a50d8b7bdb19a0131f53c9f6c25c9071e1ffb", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, @@ -17,18 +105,114 @@ "type": "indirect" } }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "devenv" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1746537231, + "narHash": "sha256-Wb2xeSyOsCoTCTj7LOoD6cdKLEROyFAArnYoS+noCWo=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "fa466640195d38ec97cf0493d6d6882bc4d14969", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "devenv", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "libgit2": { + "flake": false, + "locked": { + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", + "type": "github" + }, + "original": { + "owner": "libgit2", + "repo": "libgit2", + "type": "github" + } + }, + "nix": { + "inputs": { + "flake-compat": [ + "devenv" + ], + "flake-parts": "flake-parts", + "libgit2": "libgit2", + "nixpkgs": "nixpkgs_2", + "nixpkgs-23-11": [ + "devenv" + ], + "nixpkgs-regression": [ + "devenv" + ], + "pre-commit-hooks": [ + "devenv" + ] + }, + "locked": { + "lastModified": 1745930071, + "narHash": "sha256-bYyjarS3qSNqxfgc89IoVz8cAFDkF9yPE63EJr+h50s=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b455edf3505f1bf0172b39a735caef94687d0d9c", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.24", + "repo": "nix", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1748186667, - "narHash": "sha256-UQubDNIQ/Z42R8tPCIpY+BOhlxO8t8ZojwC9o2FW3c8=", + "lastModified": 1733212471, + "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bdac72d387dca7f836f6ef1fe547755fb0e9df61", + "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } @@ -48,10 +232,59 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1746807397, + "narHash": "sha256-zU2z0jlkJGWLhdNr/8AJSxqK8XD0IlQgHp3VZcP56Aw=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "c5208b594838ea8e6cca5997fbf784b7cca1ca90", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1748186667, + "narHash": "sha256-UQubDNIQ/Z42R8tPCIpY+BOhlxO8t8ZojwC9o2FW3c8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bdac72d387dca7f836f6ef1fe547755fb0e9df61", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs", + "devenv": "devenv", + "flake-parts": "flake-parts_2", + "nixpkgs": "nixpkgs_4", "systems": "systems" } }, diff --git a/flake.nix b/flake.nix index 66c930d..66805f5 100644 --- a/flake.nix +++ b/flake.nix @@ -2,12 +2,16 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; systems.url = "github:nix-systems/default"; + devenv.url = "github:cachix/devenv"; }; outputs = inputs@{ self, systems, flake-parts, nixpkgs, ... }: flake-parts.lib.mkFlake { inherit inputs; } { systems = import systems; - imports = [ ./nix ]; + imports = [ + ./nix + inputs.devenv.flakeModule + ]; perSystem = { config, pkgs, system, ... }: { _module.args.pkgs = import inputs.nixpkgs { @@ -17,6 +21,7 @@ packages.injection = pkgs.callPackage ./nix/package.nix { inherit (pkgs) nodejs fetchFromGitHub; pnpm = pkgs.pnpm_9; }; + packages.default = pkgs.tidaLuna; }; }; diff --git a/native/injector.ts b/native/injector.ts index bc62111..a500256 100644 --- a/native/injector.ts +++ b/native/injector.ts @@ -1,4 +1,5 @@ import electron from "electron"; +import os from "os"; import { readFile, rm, writeFile } from "fs/promises"; import mime from "mime"; @@ -25,6 +26,7 @@ declare global { tidalWindow?: Electron.BrowserWindow; }; } + globalThis.luna = { modules: {}, }; @@ -211,7 +213,9 @@ const requirePrefix = `import { createRequire } from 'module';const require = cr ipcHandle("__Luna.registerNative", async (_, name: string, code: string) => { const tempPath = path.join(bundleDir, Math.random().toString() + ".mjs"); try { + console.error('AAARG') await writeFile(tempPath, requirePrefix + code, "utf8"); + // Load module const exports = (globalThis.luna.modules[name] = await import(pathToFileURL(tempPath).href)); const channel = `__LunaNative.${name}`; diff --git a/nix/package.nix b/nix/package.nix index 51d3535..8612e2f 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -3,12 +3,7 @@ stdenv.mkDerivation (finalAttrs: rec { name = "TidaLuna"; pname = "${name}"; version = "1.1.0-alpha"; - src = fetchFromGitHub { - owner = "Inrixia"; - repo = "${name}"; - rev = "${version}"; - hash = "sha256-T6J6mI3oxQ7tD8b76M15ajka1S8G9QW8Am3rqj0MaTo="; - }; + src = ./..; # TODO: dont forget to change! nativeBuildInputs = [ nodejs @@ -17,7 +12,7 @@ stdenv.mkDerivation (finalAttrs: rec { pnpmDeps = pnpm.fetchDeps { inherit (finalAttrs) pname src version; - hash = "sha256-pnuDLjUAOxQUFlf+2FXeX2mpZcahzzVPMRpWZpbyDE4="; + hash = "sha256-2Nf7kzmiJT7P9jNCPI16VHTPREjKR1l2yoxdtNReCx0="; }; buildPhase = '' diff --git a/result b/result new file mode 120000 index 0000000..710bbed --- /dev/null +++ b/result @@ -0,0 +1 @@ +/nix/store/7p4zs2g89m1l498vszvb5hnfq0n0yk45-tidal-hifi-5.19.0 \ No newline at end of file From cdd77bc50f330be32c2cfe7f6d7b3ff362c9f40b Mon Sep 17 00:00:00 2001 From: Xaiya Schumin Date: Mon, 26 May 2025 20:05:19 +0200 Subject: [PATCH 18/23] =?UTF-8?q?=F0=9F=99=88=20Update=20ignore=20for=20re?= =?UTF-8?q?sult?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xaiya Schumin --- .gitignore | 4 ++-- result | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) delete mode 120000 result diff --git a/.gitignore b/.gitignore index d8dec56..7892c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ node_modules/ dist/ -result/ +result # IDEs .idea/ @@ -15,4 +15,4 @@ devenv.local.nix .direnv # pre-commit -.pre-commit-config.yaml \ No newline at end of file +.pre-commit-config.yaml diff --git a/result b/result deleted file mode 120000 index 710bbed..0000000 --- a/result +++ /dev/null @@ -1 +0,0 @@ -/nix/store/7p4zs2g89m1l498vszvb5hnfq0n0yk45-tidal-hifi-5.19.0 \ No newline at end of file From 588e55ce75d34c205227cddb8c59a5dc6ed02057 Mon Sep 17 00:00:00 2001 From: Xaiya Schumin Date: Tue, 27 May 2025 10:47:21 +0200 Subject: [PATCH 19/23] =?UTF-8?q?=E2=9C=A8=20tempPath=20now=20in=20tempDir?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xaiya Schumin --- .gitignore | 1 + native/injector.ts | 21 +++++++++++++++------ nix/package.nix | 1 - 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 7892c4a..9949668 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ node_modules/ dist/ result +result-original # IDEs .idea/ diff --git a/native/injector.ts b/native/injector.ts index a500256..534ef98 100644 --- a/native/injector.ts +++ b/native/injector.ts @@ -64,6 +64,7 @@ ipcHandle("__Luna.renderJs", () => lunaBundle); // Ensure app is ready electron.app.whenReady().then(async () => { electron.protocol.handle("https", async (req) => { + if (req.url.startsWith("https://luna/")) { try { return new Response(...(await bundleFile(req.url))); @@ -71,6 +72,7 @@ electron.app.whenReady().then(async () => { return new Response(err.message, { status: err.message.startsWith("ENOENT") ? 404 : 500, statusText: err.message }); } } + // Bypass CSP & Mark meta scripts for quartz injection if (req.url === "https://desktop.tidal.com/" || req.url === "https://listen.tidal.com/") { const res = await electron.net.fetch(req, { bypassCustomProtocolHandlers: true }); @@ -85,6 +87,7 @@ electron.app.whenReady().then(async () => { // Mark module scripts for quartz injection return `