From c62e960fc87aee0eada27dd75c5ec1009889c995 Mon Sep 17 00:00:00 2001 From: ItzzExcel <98148217+ItzzExcel@users.noreply.github.com> Date: Sun, 16 Feb 2025 00:03:39 -0600 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 14 +- README.md | 21 +++ plugins/.gitignore | 142 -------------- plugins/build.js | 177 +++++++++--------- plugins/package-lock.json | 108 +++-------- plugins/package.json | 6 +- plugins/plugins/copy-lyrics/dist/index.js | 14 ++ .../plugins/copy-lyrics/dist/manifest.json | 1 + plugins/plugins/copy-lyrics/package.json | 3 +- plugins/plugins/copy-lyrics/src/index.js | 86 ++++++--- plugins/plugins/copy-lyrics/src/tracer.js | 55 ++++++ themes/black-neptune-theme.css | 68 +++++-- 12 files changed, 329 insertions(+), 366 deletions(-) create mode 100644 README.md delete mode 100644 plugins/.gitignore create mode 100644 plugins/plugins/copy-lyrics/dist/index.js create mode 100644 plugins/plugins/copy-lyrics/dist/manifest.json create mode 100644 plugins/plugins/copy-lyrics/src/tracer.js diff --git a/.gitignore b/.gitignore index c6bba59..a9e3938 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +### Node ### # Logs logs *.log @@ -89,7 +90,6 @@ out # Nuxt.js build / generate output .nuxt -dist # Gatsby files .cache/ @@ -102,7 +102,6 @@ dist # vuepress v2.x temp and cache directory .temp -.cache # Docusaurus cache and generated files .docusaurus @@ -128,3 +127,14 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +### Node Patch ### +# Serverless Webpack directories +.webpack/ + +# Optional stylelint cache + +# SvelteKit build / generate output +.svelte-kit + +# End of https://www.toptal.com/developers/gitignore/api/node \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..cc8fa3e --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# Excel's Neptune Projects + +This repository a repository containing my Neptune (TIDAL Modded Client) projects. + +## Index: +- [Copy Lyrics](#copy-lyrics) +- [ShadowX Theme](#spicetifys-shadowx-port-full-black-theme) + + +### Copy Lyrics +A plugin that allows the user copy the lyrics only selecting it. +``` +https://raw.githubusercontent.com/ItzzExcel/neptune-projects/refs/heads/main/plugins/plugins/copy-lyrics/dist/ +``` +
+ +### Spicetify's ShadowX Port (Full-black theme) +``` +https://raw.githubusercontent.com/ItzzExcel/neptune-projects/refs/heads/main/themes/black-neptune-theme.css +``` +
\ No newline at end of file diff --git a/plugins/.gitignore b/plugins/.gitignore deleted file mode 100644 index 0c50fd5..0000000 --- a/plugins/.gitignore +++ /dev/null @@ -1,142 +0,0 @@ -### Node ### -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -.pnpm-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Snowpack dependency directory (https://snowpack.dev/) -web_modules/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional stylelint cache -.stylelintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variable files -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# Next.js build output -.next -out - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# vuepress v2.x temp and cache directory -.temp - -# Docusaurus cache and generated files -.docusaurus - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -# yarn v2 -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* - -### Node Patch ### -# Serverless Webpack directories -.webpack/ - -# Optional stylelint cache - -# SvelteKit build / generate output -.svelte-kit - -# End of https://www.toptal.com/developers/gitignore/api/node -dist/ \ No newline at end of file diff --git a/plugins/build.js b/plugins/build.js index 5203610..ab9ce41 100644 --- a/plugins/build.js +++ b/plugins/build.js @@ -3,103 +3,102 @@ const fs = require("fs"); const path = require("path"); const crypto = require("crypto"); -const nativeExternals = ["@neptune", "@plugin", "electron"] +const nativeExternals = ["@plugin", "electron", "@neptune-types", "@neptune"]; const plugins = fs.readdirSync("./plugins"); for (const plugin of plugins) { - let pluginPath = path.join("./plugins/", plugin); + let pluginPath = path.join("./plugins/", plugin); - const pluginManifest = JSON.parse( - fs.readFileSync(path.join(pluginPath, "plugin.json")) - ); + const pluginManifest = JSON.parse( + fs.readFileSync(path.join(pluginPath, "plugin.json")) + ); - const outfile = path.join(pluginPath, "dist/index.js"); + const outfile = path.join(pluginPath, "dist/index.js"); - esbuild - .build({ - entryPoints: [ - "./" + path.join(pluginPath, pluginManifest.main ?? "index.js"), - ], - plugins: [ - { - name: "neptuneNativeImports", - setup(build) { - build.onLoad( - { filter: /.*[\/\\].+\.native\.[a-z]+/g }, - async (args) => { - const result = await esbuild.build({ - entryPoints: [args.path], - bundle: true, - minify: true, - platform: "node", - format: "iife", - globalName: "neptuneExports", - write: false, - external: nativeExternals - }); + esbuild + .build({ + entryPoints: [ + "./" + path.join(pluginPath, pluginManifest.main ?? "index.js"), + ], + logLevel: "debug", + plugins: [ + { + name: "neptuneNativeImports", + setup(build) { + build.onLoad( + { filter: /.*[\/\\].+\.native\.[a-z]+/g }, + async (args) => { + const result = await esbuild.build({ + entryPoints: [args.path], + bundle: true, + minify: true, + platform: "node", + format: "iife", + globalName: "neptuneExports", + write: false, + external: nativeExternals + }); - const outputCode = result.outputFiles[0].text; + const outputCode = result.outputFiles[0].text; - // HATE! WHY WHY WHY WHY WHY (globalName breaks metafile. crying emoji) - const { metafile } = await esbuild.build({ - entryPoints: [args.path], - platform: "node", - write: false, - metafile: true, - bundle: true, // I find it annoying that I have to enable bundling. - format: "esm", // This avoids exports not being properly defined, thus you do not need to change log levels. - external: nativeExternals, - }); + // HATE! WHY WHY WHY WHY WHY (globalName breaks metafile. crying emoji) + const { metafile } = await esbuild.build({ + entryPoints: [args.path], + platform: "node", + write: false, + metafile: true, + bundle: true, // I find it annoying that I have to enable bundling. + format: "esm", // This avoids exports not being properly defined, thus you do not need to change log levels. + external: nativeExternals, + }); - const builtExports = Object.values(metafile.outputs)[0].exports; + const builtExports = Object.values(metafile.outputs)[0].exports; - return { - contents: `import {addUnloadable} from "@plugin";const contextId=NeptuneNative.createEvalScope(${JSON.stringify( - outputCode - )});${builtExports - .map( - (e) => - `export ${ - e == "default" ? "default " : `const ${e} =` - } NeptuneNative.getNativeValue(contextId,${JSON.stringify( - e - )})` - ) - .join( - ";" - )};addUnloadable(() => NeptuneNative.deleteEvalScope(contextId))`, - }; - } - ); - }, - }, - ], - bundle: true, - minify: true, - format: "esm", - external: [ - "@neptune", - "@plugin", - ], - platform: "browser", - outfile, - }) - .then(() => { - fs.createReadStream(outfile) - // It being md5 does not matter, this is for caching and not security - .pipe(crypto.createHash("md5").setEncoding("hex")) - .on("finish", function () { - fs.writeFileSync( - path.join(pluginPath, "dist/manifest.json"), - JSON.stringify({ - name: pluginManifest.name, - description: pluginManifest.description, - author: pluginManifest.author, - hash: this.read(), - }) - ); + return { + contents: `import {addUnloadable} from "@plugin";const contextId=NeptuneNative.createEvalScope(${JSON.stringify( + outputCode + )});${builtExports + .map( + (e) => + `export ${e == "default" ? "default " : `const ${e} =` + } NeptuneNative.getNativeValue(contextId,${JSON.stringify( + e + )})` + ) + .join( + ";" + )};addUnloadable(() => NeptuneNative.deleteEvalScope(contextId))`, + }; + } + ); + }, + }, + ], + bundle: true, + minify: true, + format: "esm", + external: nativeExternals, + platform: "browser", + outfile, + metafile: true, // Add this line to generate a metafile + }) + .then((result) => { + fs.createReadStream(outfile) + // It being md5 does not matter, this is for caching and not security + .pipe(crypto.createHash("md5").setEncoding("hex")) + .on("finish", function () { + fs.writeFileSync( + path.join(pluginPath, "dist/manifest.json"), + JSON.stringify({ + name: pluginManifest.name, + description: pluginManifest.description, + author: pluginManifest.author, + hash: this.read(), + metafile: result.metafile, // Add this line to include the metafile in the manifest + }) + ); - console.log("Built " + pluginManifest.name + "!"); - }); - }); -} + console.log("Built " + pluginManifest.name + "!"); + }); + }); +} \ No newline at end of file diff --git a/plugins/package-lock.json b/plugins/package-lock.json index 6d8d051..11a1b74 100644 --- a/plugins/package-lock.json +++ b/plugins/package-lock.json @@ -6,18 +6,17 @@ "": { "name": "neptune-plugin-template", "dependencies": { - "react-hot-toast": "^2.5.1" + "canvas-confetti": "^1.9.3", + "neptune-types": "^1.0.1" }, "devDependencies": { - "esbuild": "^0.18.13", - "neptune-types": "^1.0.0" + "esbuild": "^0.18.13" } }, "node_modules/@babel/runtime": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", - "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", - "dev": true, + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz", + "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -400,11 +399,15 @@ "node": ">=12" } }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" + "node_modules/canvas-confetti": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.3.tgz", + "integrity": "sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } }, "node_modules/esbuild": { "version": "0.18.20", @@ -444,41 +447,28 @@ "@esbuild/win32-x64": "0.18.20" } }, - "node_modules/goober": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz", - "integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==", - "license": "MIT", - "peerDependencies": { - "csstype": "^3.0.10" - } - }, "node_modules/htm": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz", "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==", - "dev": true, "license": "Apache-2.0" }, "node_modules/idb-keyval": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==", - "dev": true, "license": "Apache-2.0" }, "node_modules/immutable": { "version": "5.0.0-beta.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.0-beta.4.tgz", "integrity": "sha512-sl9RE3lqd2LoQSESc8VV0k8qE9y57iT7dinq3Q+8mR2dqReHDZlgUrudzmFfZhDXBLXlNJMVWv3SG1YpQIokig==", - "dev": true, "license": "MIT" }, "node_modules/neptune-types": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/neptune-types/-/neptune-types-1.0.1.tgz", "integrity": "sha512-XDkESq/jNTH9La//peJQirzJTwJySxkc4pCjHz1RtgcmoFbYIZ72JR0mkFYNsCZ0oyI7gLgaApd405VzU1gqOw==", - "dev": true, "license": "MS-PL", "dependencies": { "idb-keyval": "^6.2.1", @@ -493,54 +483,12 @@ "node_modules/oby": { "version": "14.3.5", "resolved": "https://registry.npmjs.org/oby/-/oby-14.3.5.tgz", - "integrity": "sha512-0RgL6n1qmxdkUgvXFnmG/J+Lv8HWjwnWmULtu/omMxRUV9KhD/8x3sL7DmanUvEOi5wX4xTbef1sKe5NzqGm7g==", - "dev": true - }, - "node_modules/react": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", - "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", - "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "scheduler": "^0.25.0" - }, - "peerDependencies": { - "react": "^19.0.0" - } - }, - "node_modules/react-hot-toast": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.5.1.tgz", - "integrity": "sha512-54Gq1ZD1JbmAb4psp9bvFHjS7lje+8ubboUmvKZkCsQBLH6AOpZ9JemfRvIdHcfb9AZXRaFLrb3qUobGYDJhFQ==", - "license": "MIT", - "dependencies": { - "csstype": "^3.1.3", - "goober": "^2.1.16" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": ">=16", - "react-dom": ">=16" - } + "integrity": "sha512-0RgL6n1qmxdkUgvXFnmG/J+Lv8HWjwnWmULtu/omMxRUV9KhD/8x3sL7DmanUvEOi5wX4xTbef1sKe5NzqGm7g==" }, "node_modules/redux": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.9.2" @@ -550,28 +498,18 @@ "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, "license": "MIT" }, - "node_modules/scheduler": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", - "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", - "license": "MIT", - "peer": true - }, "node_modules/spitroast": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/spitroast/-/spitroast-1.4.4.tgz", "integrity": "sha512-S69rzIFjbGoEW5YCLpm1kEdqMEYqC09lmE1ZMY4gyUXfke0wi9qZjKYa0DDSv5eIy/D+/UGJT8yxgJddU3oqlA==", - "dev": true, "license": "CC0-1.0" }, "node_modules/type-fest": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.34.0.tgz", - "integrity": "sha512-Qcg88ZJsJvRcUijtD6supagRSDf0y1FPZh4NroJpwRkoPYj6gGNidREwTgDuC0Pmq0PVAAzL8C8BZW7xhx5Q4A==", - "dev": true, + "version": "4.34.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.34.1.tgz", + "integrity": "sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g==", "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=16" @@ -584,17 +522,15 @@ "version": "0.54.0", "resolved": "https://registry.npmjs.org/voby/-/voby-0.54.0.tgz", "integrity": "sha512-hH8LXcP0QR4J6nnzfSWGD13onq7hqdc/ya1r1Bb+TxibtECYKZRO1m4HdSU4RcE7MdAaQwR5pwgd+hqXCqk2OA==", - "dev": true, "dependencies": { "htm": "^3.1.1", "oby": "^14.3.0" } }, "node_modules/zod": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", - "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", - "dev": true, + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/plugins/package.json b/plugins/package.json index 070571d..f679e72 100644 --- a/plugins/package.json +++ b/plugins/package.json @@ -6,10 +6,10 @@ "build": "node ./build.js" }, "devDependencies": { - "esbuild": "^0.18.13", - "neptune-types": "^1.0.0" + "esbuild": "^0.18.13" }, "dependencies": { - "react-hot-toast": "^2.5.1" + "canvas-confetti": "^1.9.3", + "neptune-types": "^1.0.1" } } diff --git a/plugins/plugins/copy-lyrics/dist/index.js b/plugins/plugins/copy-lyrics/dist/index.js new file mode 100644 index 0000000..26bfe08 --- /dev/null +++ b/plugins/plugins/copy-lyrics/dist/index.js @@ -0,0 +1,14 @@ +var p=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var v=(t,e)=>()=>(t&&(e=t(t=0)),e);var T=(t,e)=>{for(var n in e)p(t,n,{get:e[n],enumerable:!0})},R=(t,e,n,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of S(e))!b.call(t,r)&&r!==n&&p(t,r,{get:()=>e[r],enumerable:!(a=w(e,r))||a.enumerable});return t};var L=t=>R(p({},"__esModule",{value:!0}),t);var E={};T(E,{Tracer:()=>u,libTrace:()=>N});import{actions as f}from"@neptune";var u,N,y=v(()=>{"use strict";u=t=>{let e=o=>{let c=(...i)=>{o(t,...i)};return c.withContext=i=>(...m)=>{o(t,i,...m)},c},n=e(console.log),a=e(console.warn),r=e(console.error),g=e(console.debug),s=(o,c,i)=>{let m=l=>{o(l),c({message:`${t} - ${l}`,category:"OTHER",severity:i})};return m.withContext=l=>{let C=o.withContext(l);return d=>{C(d),d instanceof Error&&(d=d.message),c({message:`${t}.${l} - ${d}`,category:"OTHER",severity:i})}},m};return{log:n,warn:a,err:r,debug:g,msg:{log:s(n,f.message.messageInfo,"INFO"),warn:s(a,f.message.messageWarn,"WARN"),err:s(r,f.message.messageError,"ERROR")}}},N=u("[lib]")});y();y();var h=u("[Copy Lyrics]"),A=` +[class^="lyricsText"]>div>span { + user-select: text; + cursor: text; + +} + +::selection { + background:rgb(0, 0, 0); + color:rgb(255, 255, 255); +} +`;function O(t){let e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.head.appendChild(e)}function $(t){let e=document.createElement("textarea");e.value=t,e.style.position="fixed",document.body.appendChild(e),e.select();try{if(!document.execCommand("copy"))throw new Error("Failed to copy text.")}catch(n){h.msg.err(n)}finally{document.body.removeChild(e)}}O(A);var x=!1;document.addEventListener("mousedown",function(){x=!0});document.addEventListener("mouseup",function(t){if(x){let e=window.getSelection();if(e.toString().length>0){let n=[],g=e.getRangeAt(0).commonAncestorContainer.getElementsByTagName("span");for(let o of g)e.containsNode(o,!0)&&n.push(o);let s="";n.forEach(o=>{s+=o.textContent+` +`,[...o.classList].some(c=>c.startsWith("endOfStanza--"))&&(s+=` +`)}),s=s.trim(),$(s),h.msg.log("Copied to clipboard!"),window.getSelection&&e.removeAllRanges()}x=!1}});function F(){styleElement&&styleElement.parentNode&&styleElement.parentNode.removeChild(styleElement),document.removeEventListener("mousedown",onMouseDown),document.removeEventListener("mouseup",onMouseUp)}export{F as onUnload}; diff --git a/plugins/plugins/copy-lyrics/dist/manifest.json b/plugins/plugins/copy-lyrics/dist/manifest.json new file mode 100644 index 0000000..7523d9b --- /dev/null +++ b/plugins/plugins/copy-lyrics/dist/manifest.json @@ -0,0 +1 @@ +{"name":"Copy Lyrics","description":"A working neptune plugin that allows the user to copy the lyrics of a song selecting it.","author":"itzzexcel@github","hash":"aeef96d8ab14451ebe3f42446de81230","metafile":{"inputs":{"plugins/copy-lyrics/src/tracer.js":{"bytes":1596,"imports":[{"path":"@neptune","kind":"import-statement","external":true}],"format":"esm"},"plugins/copy-lyrics/src/index.js":{"bytes":2930,"imports":[{"path":"plugins/copy-lyrics/src/tracer.js","kind":"import-statement","original":"./tracer"},{"path":"plugins/copy-lyrics/src/tracer.js","kind":"require-call","original":"./tracer"}],"format":"esm"}},"outputs":{"plugins/copy-lyrics/dist/index.js":{"imports":[{"path":"@neptune","kind":"import-statement","external":true}],"exports":["onUnload"],"entryPoint":"plugins/copy-lyrics/src/index.js","inputs":{"plugins/copy-lyrics/src/tracer.js":{"bytesInOutput":693},"plugins/copy-lyrics/src/index.js":{"bytesInOutput":1362}},"bytes":2525}}}} \ No newline at end of file diff --git a/plugins/plugins/copy-lyrics/package.json b/plugins/plugins/copy-lyrics/package.json index 82e2b02..d020e40 100644 --- a/plugins/plugins/copy-lyrics/package.json +++ b/plugins/plugins/copy-lyrics/package.json @@ -1,5 +1,6 @@ { "dependencies": { - "canvas-confetti": "^1.6.0" + "canvas-confetti": "^1.6.0", + "neptune-types": "1.0.1" } } \ No newline at end of file diff --git a/plugins/plugins/copy-lyrics/src/index.js b/plugins/plugins/copy-lyrics/src/index.js index c2fb08f..4d193c6 100644 --- a/plugins/plugins/copy-lyrics/src/index.js +++ b/plugins/plugins/copy-lyrics/src/index.js @@ -1,27 +1,36 @@ /* - * TODO: Check for the span to be part of the lyrics div. - * +TODO: Check for the span to be part of the lyrics div. */ -import toast, { Toaster } from 'react-hot-toast'; +require("./tracer") +import { Tracer } from "./tracer"; + +const trace = Tracer("[Copy Lyrics]"); const unlockSelection = ` [class^="lyricsText"]>div>span { user-select: text; cursor: text; -}`; + +} + +::selection { + background:rgb(0, 0, 0); + color:rgb(255, 255, 255); +} +`; function ApplyCSS(style) { - const styleElement = document.createElement('style'); - styleElement.type = 'text/css'; - if (styleElement.styleSheet) - styleElement.styleSheet.cssText = style; - else - styleElement.appendChild(document.createTextNode(style)); + const styleElement = document.createElement('style'); + styleElement.type = 'text/css'; + if (styleElement.styleSheet) + styleElement.styleSheet.cssText = style; + else + styleElement.appendChild(document.createTextNode(style)); - document.head.appendChild(styleElement); + document.head.appendChild(styleElement); } -function SetClipboar(text) { +function SetClipboard(text) { const textarea = document.createElement('textarea'); textarea.value = text; textarea.style.position = 'fixed'; // Avoid scrolling to the bottom @@ -30,15 +39,11 @@ function SetClipboar(text) { try { const success = document.execCommand('copy'); - if (success) { - console.log('Text copied to clipboard:', text); - toast.success('Copied to clipboard!'); - } else { + if (!success) throw new Error('Failed to copy text.'); - } + } catch (err) { - console.error('Failed to copy text:', err); - toast.error('Failed to copy to clipboard!'); + trace.msg.err(err); } finally { document.body.removeChild(textarea); } @@ -52,24 +57,47 @@ document.addEventListener('mousedown', function() { isSelecting = true; }); -document.addEventListener('mouseup', function() { +document.addEventListener('mouseup', function (event) { if (isSelecting) { const selection = window.getSelection(); if (selection.toString().length > 0) { - let text = selection.toString(); - SetClipboar(text); - toast.success("Copied to clipboard!"); - if (window.getSelection) { - const selection = window.getSelection(); - selection.removeAllRanges(); - } - } else { + const selectedSpans = []; + const ranges = selection.getRangeAt(0); + const container = ranges.commonAncestorContainer; + // Get all spans within the selection + const spans = container.getElementsByTagName('span'); + for (let span of spans) { + if (selection.containsNode(span, true)) { + selectedSpans.push(span); + } + } + + // Concatenate text from selected spans + let text = ''; + selectedSpans.forEach(span => { + text += span.textContent + '\n'; + if ([...span.classList].some(className => className.startsWith('endOfStanza--'))) { + text += '\n'; + } + }); + text = text.trim(); + + SetClipboard(text); + trace.msg.log("Copied to clipboard!"); + if (window.getSelection) { + selection.removeAllRanges(); + } } isSelecting = false; } }); export function onUnload() { - console.log("Goodbye world!"); + if (styleElement && styleElement.parentNode) { + styleElement.parentNode.removeChild(styleElement); + } + + document.removeEventListener('mousedown', onMouseDown); + document.removeEventListener('mouseup', onMouseUp); } diff --git a/plugins/plugins/copy-lyrics/src/tracer.js b/plugins/plugins/copy-lyrics/src/tracer.js new file mode 100644 index 0000000..f18bcd3 --- /dev/null +++ b/plugins/plugins/copy-lyrics/src/tracer.js @@ -0,0 +1,55 @@ +// Based on https://github.com/Inrixia/neptune-plugins/blob/3d28c9ea3252782da830698032dbb49dbe5b9fd6/plugins/_lib/trace.ts +// Credits to inrixia + +import { actions } from "@neptune"; + +export const Tracer = (source) => { + const createLogger = (logger) => { + const _logger = (...data) => { + logger(source, ...data); + return undefined; + }; + _logger.withContext = (context) => (...data) => { + logger(source, context, ...data); + return undefined; + }; + return _logger; + }; + + const log = createLogger(console.log); + const warn = createLogger(console.warn); + const err = createLogger(console.error); + const debug = createLogger(console.debug); + + const createMessager = (logger, messager, severity) => { + const _messager = (message) => { + logger(message); + messager({ message: `${source} - ${message}`, category: "OTHER", severity }); + return undefined; + }; + _messager.withContext = (context) => { + const loggerWithContext = logger.withContext(context); + return (message) => { + loggerWithContext(message); + if (message instanceof Error) message = message.message; + messager({ message: `${source}.${context} - ${message}`, category: "OTHER", severity }); + return undefined; + }; + }; + return _messager; + }; + + return { + log, + warn, + err, + debug, + msg: { + log: createMessager(log, actions.message.messageInfo, "INFO"), + warn: createMessager(warn, actions.message.messageWarn, "WARN"), + err: createMessager(err, actions.message.messageError, "ERROR"), + }, + }; +}; + +export const libTrace = Tracer("[lib]"); \ No newline at end of file diff --git a/themes/black-neptune-theme.css b/themes/black-neptune-theme.css index 09582dc..7cf5622 100644 --- a/themes/black-neptune-theme.css +++ b/themes/black-neptune-theme.css @@ -6,8 +6,6 @@ } */ - - ::-webkit-scrollbar { display: none; } @@ -24,6 +22,15 @@ --wave-color-solid-accent-dark: gray; } +[class^="followingButton"], +[title="Unfollow"], +[title="Follow"], +[title="Unfollow"]>span, +[title="Follow"]>span { + background-color: var(--wave-color-solid-rainbow-yellow-fill) !important; + color: var(--wave-color-solid-base-brighter); +} + [class^="_wave-badge-color-max"] { color: black !important; background-color: var(--wave-color-solid-accent-fill); @@ -61,13 +68,13 @@ } [class^="ReactVirtualized__Grid"] { - border: 1px solid rgb(25, 25, 25); border-radius: 10px; margin: 5px; } [class^="ReactVirtualized__Grid__innerScrollContainer"] { - border: 1px solid rgba(0, 0, 0, 0); + border: none; + margin: 5px; } [class^="button"]>span { @@ -90,7 +97,17 @@ display: none !important; } -[class^="headerButtons"]>button { +[data-test="current-media-imagery"] { + border: 0 !important; + margin: none; +} + +[class^="imageBorder"] { + display: none; +} + +[class^="headerButtons"]>button, +[data-test="toggle-picture-in-picture"] { background-color: var(--wave-color-solid-accent-fill) !important; color: black; } @@ -109,8 +126,8 @@ border: 0px none; } -[class^="feedSidebarVStack"] { - background-color: #1a1a1a; +[data-test="feed-sidebar"] { + margin-top: 10px; } [class^="player"] { @@ -141,7 +158,11 @@ } [class^="actionList"] { - background-color: #1a1a1a; + background-color: transparent; + border: 1px solid var(--wave-color-opacity-contrast-fill-ultra-thin) !important; + margin: 5px; + border-radius: 5px; + padding: 10px; } button[data-test="request-fullscreen"], @@ -174,10 +195,14 @@ button[data-test="close-now-playing"]:hover { opacity: 1; } -[class^="contextMenu"]>div, [data-test="main-layout-header"], [data-test="feed-sidebar"], [data-test="stream-metadata"] { - background-color: rgba(0, 0, 0, 0.5); - backdrop-filter: blur(15px); - border: 1px solid var(--wave-color-opacity-contrast-fill-ultra-thin); +[class^="contextMenu"]>div, +[data-test="main-layout-header"], +[data-test="feed-sidebar"], +[data-test="stream-metadata"], +[class^="player"] { + background-color: rgba(0, 0, 0, 0.8) !important; + backdrop-filter: blur(10px); + border: 1px solid var(--wave-color-opacity-contrast-fill-ultra-thin) !important; } [data-wave-color=textUrl] { @@ -188,12 +213,16 @@ button[data-test="close-now-playing"]:hover { margin-top: 7.5px; } -[data-test="play-all"]>div>*, [data-test="shuffle-all"]>div>*, [data-test="play-all"], [data-test="shuffle-all"] { +[data-test="play-all"]>div>*, +[data-test="shuffle-all"]>div>*, +[data-test="play-all"], +[data-test="shuffle-all"] { color: var(--wave-color-solid-accent-fill) !important; background-color: transparent !important; } -[class^="__NEPTUNE_PAGE"], [data-test="main"] { +[class^="__NEPTUNE_PAGE"], +[data-test="main"] { margin-top: 35px; } @@ -206,4 +235,15 @@ button[data-test="close-now-playing"]:hover { [data-test="button-release-notes"]:hover { background-color: lightgray !important; transition: none !important; +} + +#playQueueSidebar { + top: 50px !important; + border: 1px solid var(--wave-color-opacity-contrast-fill-ultra-thin); + margin: 2px; + margin-right: -5px !important; +} + +[class^="bottomGradient"] { + visibility: hidden; } \ No newline at end of file