mirror of
https://github.com/danbulant/dribbblish-dynamic-theme
synced 2026-06-21 07:42:48 +00:00
Compare commits
69 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77182042dd | ||
|
|
7492c86124 | ||
|
|
55693078f6 | ||
|
|
2c8dea7f5d | ||
|
|
6d23932d0b | ||
|
|
d7e355bf46 | ||
|
|
c9ec3971ad | ||
|
|
bb7017960b | ||
|
|
1064087b48 | ||
|
|
3edfc3fa6b | ||
|
|
239033ad5e | ||
|
|
145cfe9b53 | ||
|
|
2e55b23b44 | ||
|
|
8c5a45c64a | ||
|
|
8d9cdf3df5 | ||
|
|
9f5a988eca | ||
|
|
167e253a86 | ||
|
|
ba5846bc41 | ||
|
|
d687a13cb7 | ||
|
|
33134709ed | ||
|
|
13e1f64054 | ||
|
|
827c9f3ba0 | ||
|
|
f13a3c1ff9 | ||
|
|
14da00bf74 | ||
|
|
23fe7deb15 | ||
|
|
a146134b1d | ||
|
|
4c134a94a0 | ||
|
|
14902a060f | ||
|
|
c45c5faad0 | ||
|
|
162616c2cb | ||
|
|
301a972a53 | ||
|
|
290df59e02 | ||
|
|
3e2cde1e53 | ||
|
|
eb9a7b1939 | ||
|
|
7d3341b7a7 | ||
|
|
d78ae80ef1 | ||
|
|
316e7581cf | ||
|
|
36fe1f5a2f | ||
|
|
273a5b3e7e | ||
|
|
f9c30d230a | ||
|
|
bc200bfef6 | ||
|
|
13186767e8 | ||
|
|
d69c825555 | ||
|
|
56b109cc01 | ||
|
|
decfe17aa2 | ||
|
|
b55a82bf99 | ||
|
|
c052260a8b | ||
|
|
ee98ffd134 | ||
|
|
305d70fb6d | ||
|
|
e50b8b4bb3 | ||
|
|
ca0d24fd11 | ||
|
|
fa29a12d00 | ||
|
|
0ecd8d6166 | ||
|
|
c5fec9cbd1 | ||
|
|
11eae40857 | ||
|
|
604ddfbf97 | ||
|
|
1b45d68568 | ||
|
|
2bfa6e55db | ||
|
|
48c475ee9a | ||
|
|
8517327ee6 | ||
|
|
e2e6214159 | ||
|
|
7ac95c23a9 | ||
|
|
048d007430 | ||
|
|
0e50a92431 | ||
|
|
4dd2d42ca4 | ||
|
|
ead9615ef3 | ||
|
|
cd325a3f05 | ||
|
|
6c84a848fc | ||
|
|
b3e108f2bf |
41 changed files with 9901 additions and 386 deletions
3
.babelrc
Normal file
3
.babelrc
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"presets": ["@babel/env"]
|
||||||
|
}
|
||||||
1
.github/workflows/post-release.yaml
vendored
1
.github/workflows/post-release.yaml
vendored
|
|
@ -12,6 +12,7 @@ jobs:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
|
repository: ${{ github.event.repository.full_name }}
|
||||||
ref: ${{ github.event.repository.default_branch }}
|
ref: ${{ github.event.repository.default_branch }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
|
||||||
3
.github/workflows/prettier.yml
vendored
3
.github/workflows/prettier.yml
vendored
|
|
@ -14,11 +14,12 @@ jobs:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
|
repository: ${{ github.event.repository.full_name }}
|
||||||
ref: ${{ github.head_ref }}
|
ref: ${{ github.head_ref }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Prettify code
|
- name: Prettify code
|
||||||
uses: creyD/prettier_action@v4.0
|
uses: creyD/prettier_action@v4.1.1
|
||||||
with:
|
with:
|
||||||
prettier_options: --write **/*.{js,css}
|
prettier_options: --write **/*.{js,css}
|
||||||
same_commit: True
|
same_commit: True
|
||||||
|
|
|
||||||
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: "14"
|
node-version: "15"
|
||||||
|
|
||||||
- name: Build Webpack
|
- name: Build Webpack
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
21
.github/workflows/stale.yml
vendored
Normal file
21
.github/workflows/stale.yml
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
name: 'Close stale issues and PRs'
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 1 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v4
|
||||||
|
with:
|
||||||
|
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
|
||||||
|
stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days.'
|
||||||
|
close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.'
|
||||||
|
close-pr-message: 'This PR was closed because it has been stalled for 15 days with no activity.'
|
||||||
|
days-before-issue-stale: 60
|
||||||
|
days-before-pr-stale: 60
|
||||||
|
days-before-issue-close: 7
|
||||||
|
days-before-pr-close: 15
|
||||||
|
operations-per-run: 100
|
||||||
|
ascending: true
|
||||||
3
.github/workflows/webpack-test.yml
vendored
3
.github/workflows/webpack-test.yml
vendored
|
|
@ -10,6 +10,7 @@ jobs:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
|
repository: ${{ github.event.repository.full_name }}
|
||||||
ref: ${{ github.head_ref }}
|
ref: ${{ github.head_ref }}
|
||||||
|
|
||||||
- name: Get commit SHA
|
- name: Get commit SHA
|
||||||
|
|
@ -18,7 +19,7 @@ jobs:
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: "14"
|
node-version: "15"
|
||||||
|
|
||||||
- name: Test-Build Webpack
|
- name: Test-Build Webpack
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
26
CHANGELOG.md
26
CHANGELOG.md
|
|
@ -1,23 +1,13 @@
|
||||||
Added:
|
Added:
|
||||||
- A spinning loader at startup while spotify is not ready (Can be disabled in settings)
|
- Ability to hide premium features in addition to ads
|
||||||
- The old search box in the top bar (Can be disabled in settings)
|
- Ability to show current artist's genres
|
||||||
- Ability to disable the progress transition to improve performance `Playbar > Progress Transition` (#118)
|
|
||||||
- Option to insert custom CSS
|
|
||||||
- Ability to search Settings
|
|
||||||
|
|
||||||
Fixed:
|
Fixed:
|
||||||
- Checking for update every 10 Minutes not working
|
- Custom search input not being focussed after clicking
|
||||||
- Background album art is cut off (#116)
|
- When changing songs, the color shifts to blue for a second (#179)
|
||||||
- Tall context menus not scrollable (#114)
|
|
||||||
- Default folder images not working
|
|
||||||
|
|
||||||
Improved:
|
Improved:
|
||||||
- Moved `Hide Ads` into `Main Settings`
|
- Add `embedWidgetGenerator` modals to custom modal styles. (Things like the [spicetify-marketplace](https://github.com/CharlieS1103/spicetify-marketplace) options)
|
||||||
- Added hover tooltips on playlist / folder images. Useful for collapsed sidebar
|
- Changed custom app tab styles to fit in with the theme
|
||||||
- Now also shows if a new spicetify-cli update is available (Requires spicetify-cli > 2.7.2)
|
- Changed notification styles to fit in with other elements of the theme
|
||||||
- Popups (like lyrics-plus settings) styles are now consistent with the Dribbblish settings styles
|
- The visualizer icon when playing a song from a playlist is now colored
|
||||||
- Only display option to reset setting if it was changed
|
|
||||||
- `Connect to Device` interface / selection is now more inline with other context menus
|
|
||||||
- When casting to a device it shows up as info (next to your profile picture)
|
|
||||||
- Confirmation modal styles are now more inline with other popups
|
|
||||||
- Made `System` the default theme. Windows users see [this](https://github.com/JulienMaille/dribbblish-dynamic-theme#follow-system-darklight-theme-powershell)
|
|
||||||
|
|
@ -117,12 +117,12 @@ xpui.js_repl_8008=,`${1}58,
|
||||||
|
|
||||||
Write-Part "APPLYING";
|
Write-Part "APPLYING";
|
||||||
$backupVer = $configFile -match "^version"
|
$backupVer = $configFile -match "^version"
|
||||||
$version = ConvertFrom-StringData $backupVer[0]
|
if ($backupVer.Length -gt 0) {
|
||||||
if ($version.version.Length -gt 0) {
|
|
||||||
spicetify apply
|
spicetify apply
|
||||||
} else {
|
} else {
|
||||||
spicetify backup apply
|
spicetify backup apply
|
||||||
}
|
}
|
||||||
|
Write-Done
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Write-Part "`nYour Powershell version is less than "; Write-Emphasized "$PSMinVersion";
|
Write-Part "`nYour Powershell version is less than "; Write-Emphasized "$PSMinVersion";
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"name": "Dribbblish Dynamic (Beta)",
|
|
||||||
"description": "A mod of Dribbblish theme for Spicetify with support for light/dark modes and album art based colors. (Beta Release)",
|
|
||||||
"branch": "release-beta",
|
|
||||||
"preview": "https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/main/showcase-images/preview.gif",
|
|
||||||
"readme": "https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/main/README.md",
|
|
||||||
"usercss": "user.css",
|
|
||||||
"schemes": "color.ini",
|
|
||||||
"include": ["https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/release-beta/dribbblish-dynamic.js"]
|
|
||||||
}
|
|
||||||
22
manifest.json.rem
Normal file
22
manifest.json.rem
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Dribbblish Dynamic",
|
||||||
|
"description": "A mod of Dribbblish theme for Spicetify with support for light/dark modes and album art based colors. (Beta Release)",
|
||||||
|
"branch": "release-stable",
|
||||||
|
"preview": "https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/main/showcase-images/preview.gif",
|
||||||
|
"readme": "https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/main/README.md",
|
||||||
|
"usercss": "user.css",
|
||||||
|
"schemes": "color.ini",
|
||||||
|
"include": ["https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/release-stable/dribbblish-dynamic.js"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dribbblish Dynamic (Beta)",
|
||||||
|
"description": "A mod of Dribbblish theme for Spicetify with support for light/dark modes and album art based colors. (Beta Release)",
|
||||||
|
"branch": "release-beta",
|
||||||
|
"preview": "https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/main/showcase-images/preview.gif",
|
||||||
|
"readme": "https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/main/README.md",
|
||||||
|
"usercss": "user.css",
|
||||||
|
"schemes": "color.ini",
|
||||||
|
"include": ["https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/release-beta/dribbblish-dynamic.js"]
|
||||||
|
}
|
||||||
|
]
|
||||||
9109
package-lock.json
generated
Normal file
9109
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
13
package.json
13
package.json
|
|
@ -1,11 +1,14 @@
|
||||||
{
|
{
|
||||||
"name": "dribbblish-dynamic-theme",
|
"name": "dribbblish-dynamic-theme",
|
||||||
"version": "4.0.0",
|
"version": "4.1.1",
|
||||||
"homepage": "https://github.com/JulienMaille/dribbblish-dynamic-theme",
|
"homepage": "https://github.com/JulienMaille/dribbblish-dynamic-theme",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/JulienMaille/dribbblish-dynamic-theme/issues"
|
"url": "https://github.com/JulienMaille/dribbblish-dynamic-theme/issues"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.17.0",
|
||||||
|
"@babel/preset-env": "^7.16.5",
|
||||||
|
"@babel/register": "^7.16.5",
|
||||||
"@material-icons/svg": "^1.0.22",
|
"@material-icons/svg": "^1.0.22",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"sass": "^1.43.5",
|
"sass": "^1.43.5",
|
||||||
|
|
@ -14,15 +17,17 @@
|
||||||
"webpack-cli": "^4.9.0"
|
"webpack-cli": "^4.9.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --mode=development"
|
"build": "webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chroma-js": "^2.1.2",
|
"chroma-js": "^2.1.2",
|
||||||
"colorthief": "^2.3.2",
|
"colorthief": "^2.3.2",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"markdown-it": "^12.2.0",
|
"lodash.debounce": "^4.0.8",
|
||||||
|
"lodash.defaultsdeep": "^4.6.1",
|
||||||
|
"markdown-it": "^12.3.2",
|
||||||
"markdown-it-attrs": "^4.1.0",
|
"markdown-it-attrs": "^4.1.0",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.2",
|
||||||
"node-vibrant": "^3.1.6",
|
"node-vibrant": "^3.1.6",
|
||||||
"svgson": "^5.2.1"
|
"svgson": "^5.2.1"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,20 @@
|
||||||
$sp = "$env:APPDATA\Spotify\Spotify.exe"
|
Get-Process -Name Spotify -ErrorAction SilentlyContinue | Stop-Process -Force
|
||||||
|
Get-Process -Name SpotifyWebHelper -ErrorAction SilentlyContinue | Stop-Process -Force
|
||||||
|
|
||||||
|
$sp = spicetify config spotify_path
|
||||||
|
$sp += "\Spotify.exe"
|
||||||
Copy-Item $sp ($sp + ".backup")
|
Copy-Item $sp ($sp + ".backup")
|
||||||
|
|
||||||
$bytes = [System.IO.File]::ReadAllBytes($sp);
|
$bytes = [System.IO.File]::ReadAllBytes($sp);
|
||||||
$toRemove = [System.Text.Encoding]::UTF8.GetBytes("force-dark-mode");
|
$toRemove = [System.Text.Encoding]::UTF8.GetBytes("force-dark-mode");
|
||||||
|
|
||||||
|
$sw = [System.Diagnostics.Stopwatch]::StartNew()
|
||||||
for ($i = 0; $i -lt $bytes.Length; $i++) {
|
for ($i = 0; $i -lt $bytes.Length; $i++) {
|
||||||
|
if ($sw.Elapsed.TotalMilliseconds -ge 1000) {
|
||||||
|
Write-Progress -Activity "Enabling dark mode in Spotify.exe" -status "Patching binary file $i" -percentComplete ($i / $bytes.Length*100);
|
||||||
|
$sw.Reset();
|
||||||
|
$sw.Start();
|
||||||
|
}
|
||||||
$found = $true
|
$found = $true
|
||||||
for ($j = 0; $j -lt $toRemove.Length; $j++) {
|
for ($j = 0; $j -lt $toRemove.Length; $j++) {
|
||||||
if ($bytes[$i + $j] -ne $toRemove[$j]) {
|
if ($bytes[$i + $j] -ne $toRemove[$j]) {
|
||||||
|
|
@ -22,3 +32,8 @@ for ($i = 0; $i -lt $bytes.Length; $i++) {
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.IO.File]::WriteAllBytes($sp, $bytes);
|
[System.IO.File]::WriteAllBytes($sp, $bytes);
|
||||||
|
if ( $found ) {
|
||||||
|
Write-Host "The patch is complete." -ForegroundColor "Green"
|
||||||
|
} else {
|
||||||
|
Write-Host "Failed to patch the file." -ForegroundColor "Red"
|
||||||
|
}
|
||||||
|
|
|
||||||
131
src/icons/equaliser.svg
Normal file
131
src/icons/equaliser.svg
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 24'>
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
@keyframes play {
|
||||||
|
0% {
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
3.3% {
|
||||||
|
transform: scaleY(0.9583);
|
||||||
|
}
|
||||||
|
|
||||||
|
6.6% {
|
||||||
|
transform: scaleY(0.9166);
|
||||||
|
}
|
||||||
|
|
||||||
|
9.9% {
|
||||||
|
transform: scaleY(0.8333);
|
||||||
|
}
|
||||||
|
|
||||||
|
13.3% {
|
||||||
|
transform: scaleY(0.7083);
|
||||||
|
}
|
||||||
|
|
||||||
|
16.6% {
|
||||||
|
transform: scaleY(0.5416);
|
||||||
|
}
|
||||||
|
|
||||||
|
19.9% {
|
||||||
|
transform: scaleY(0.4166);
|
||||||
|
}
|
||||||
|
|
||||||
|
23.3% {
|
||||||
|
transform: scaleY(0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
26.6% {
|
||||||
|
transform: scaleY(0.1666);
|
||||||
|
}
|
||||||
|
|
||||||
|
29.9% {
|
||||||
|
transform: scaleY(0.125);
|
||||||
|
}
|
||||||
|
|
||||||
|
33.3% {
|
||||||
|
transform: scaleY(0.125);
|
||||||
|
}
|
||||||
|
|
||||||
|
36.6% {
|
||||||
|
transform: scaleY(0.1666);
|
||||||
|
}
|
||||||
|
39.9% {
|
||||||
|
transform: scaleY(0.1666);
|
||||||
|
}
|
||||||
|
43.3% {
|
||||||
|
transform: scaleY(0.2083);
|
||||||
|
}
|
||||||
|
46.6% {
|
||||||
|
transform: scaleY(0.2916);
|
||||||
|
}
|
||||||
|
49.9% {
|
||||||
|
transform: scaleY(0.375);
|
||||||
|
}
|
||||||
|
53.3% {
|
||||||
|
transform: scaleY(0.5);
|
||||||
|
}
|
||||||
|
56.6% {
|
||||||
|
transform: scaleY(0.5833);
|
||||||
|
}
|
||||||
|
59.9% {
|
||||||
|
transform: scaleY(0.625);
|
||||||
|
}
|
||||||
|
63.3% {
|
||||||
|
transform: scaleY(0.6666);
|
||||||
|
}
|
||||||
|
66.6% {
|
||||||
|
transform: scaleY(0.6666);
|
||||||
|
}
|
||||||
|
69.9% {
|
||||||
|
transform: scaleY(0.6666);
|
||||||
|
}
|
||||||
|
73.3% {
|
||||||
|
transform: scaleY(0.6666);
|
||||||
|
}
|
||||||
|
76.6% {
|
||||||
|
transform: scaleY(0.7083);
|
||||||
|
}
|
||||||
|
79.9% {
|
||||||
|
transform: scaleY(0.75);
|
||||||
|
}
|
||||||
|
83.3% {
|
||||||
|
transform: scaleY(0.8333);
|
||||||
|
}
|
||||||
|
86.6% {
|
||||||
|
transform: scaleY(0.875);
|
||||||
|
}
|
||||||
|
89.9% {
|
||||||
|
transform: scaleY(0.9166);
|
||||||
|
}
|
||||||
|
93.3% {
|
||||||
|
transform: scaleY(0.9583);
|
||||||
|
}
|
||||||
|
96.6% {
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svg[icon-type="dribbblish"][icon-name="equaliser"] > rect[i="0"] {
|
||||||
|
transform-origin: bottom;
|
||||||
|
animation: play 0.9s -0.51s infinite;
|
||||||
|
}
|
||||||
|
svg[icon-type="dribbblish"][icon-name="equaliser"] > rect[i="1"] {
|
||||||
|
transform-origin: bottom;
|
||||||
|
animation: play 0.9s infinite;
|
||||||
|
}
|
||||||
|
svg[icon-type="dribbblish"][icon-name="equaliser"] > rect[i="2"] {
|
||||||
|
transform-origin: bottom;
|
||||||
|
animation: play 0.9s -0.15s infinite;
|
||||||
|
}
|
||||||
|
svg[icon-type="dribbblish"][icon-name="equaliser"] > rect[i="3"] {
|
||||||
|
transform-origin: bottom;
|
||||||
|
animation: play 0.9s -0.75s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<rect fill="currentColor" i="0" class='cls-1' width='4' height='24'/>
|
||||||
|
<rect fill="currentColor" i="1" class='cls-1' x='6' width='4' height='24'/>
|
||||||
|
<rect fill="currentColor" i="2" class='cls-1' x='12' width='4' height='24'/>
|
||||||
|
<rect fill="currentColor" i="3" class='cls-1' x='18' width='4' height='24'/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.8 KiB |
42
src/icons/loading.svg
Normal file
42
src/icons/loading.svg
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
<svg viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
/* From https://codepen.io/mrrocks/pen/EiplA */
|
||||||
|
@keyframes loader-rotator {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(270deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loader-dash {
|
||||||
|
0% {
|
||||||
|
stroke-dashoffset: 187;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
stroke-dashoffset: 46.75;
|
||||||
|
transform: rotate(135deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
stroke-dashoffset: 187;
|
||||||
|
transform: rotate(450deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
svg[icon-type="dribbblish"][icon-name="loading"] {
|
||||||
|
animation: loader-rotator 1.4s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg[icon-type="dribbblish"][icon-name="loading"] circle {
|
||||||
|
stroke-dasharray: 187;
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
transform-origin: center;
|
||||||
|
animation: loader-dash 1.4s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<circle fill="none" stroke="currentColor" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -1,6 +1,6 @@
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
|
|
||||||
import { renderMD } from "./Util";
|
import { renderMD, defaults } from "./Util";
|
||||||
import { icons } from "./Icons";
|
import { icons } from "./Icons";
|
||||||
|
|
||||||
export default class ConfigMenu {
|
export default class ConfigMenu {
|
||||||
|
|
@ -125,7 +125,7 @@ export default class ConfigMenu {
|
||||||
parent: null
|
parent: null
|
||||||
};
|
};
|
||||||
// Set Defaults
|
// Set Defaults
|
||||||
options = { ...defaultOptions, ...options };
|
options = defaults(options, defaultOptions);
|
||||||
if (typeof options.area == "string") options.area = { name: options.area, order: 0 };
|
if (typeof options.area == "string") options.area = { name: options.area, order: 0 };
|
||||||
options.description = options.description
|
options.description = options.description
|
||||||
.split("\n")
|
.split("\n")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import ConfigMenu from "./ConfigMenu";
|
import ConfigMenu from "./ConfigMenu";
|
||||||
import Info from "./Info";
|
import Info from "./Info";
|
||||||
import Loader from "./Loader";
|
import Loader from "./Loader";
|
||||||
import { icons } from "./Icons";
|
import Overlay from "./Overlay";
|
||||||
|
import Icon, { icons } from "./Icons";
|
||||||
|
|
||||||
export default class Dribbblish {
|
export default class Dribbblish {
|
||||||
/**
|
/**
|
||||||
|
|
@ -23,7 +24,10 @@ export default class Dribbblish {
|
||||||
/** @type {Loader} */
|
/** @type {Loader} */
|
||||||
loader;
|
loader;
|
||||||
|
|
||||||
/** @type {Icons} */
|
/** @type {Overlay} */
|
||||||
|
overlay;
|
||||||
|
|
||||||
|
/** @type {Icon} */
|
||||||
icons;
|
icons;
|
||||||
|
|
||||||
/** @type {Object.<string, listener[]>} */
|
/** @type {Object.<string, listener[]>} */
|
||||||
|
|
@ -36,9 +40,12 @@ export default class Dribbblish {
|
||||||
this.config = new ConfigMenu();
|
this.config = new ConfigMenu();
|
||||||
this.info = new Info();
|
this.info = new Info();
|
||||||
this.loader = new Loader();
|
this.loader = new Loader();
|
||||||
|
this.overlay = new Overlay();
|
||||||
this.icons = icons;
|
this.icons = icons;
|
||||||
|
|
||||||
|
let tries = 0;
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
|
if (++tries > 50) throw new Error("ready timeout");
|
||||||
if (document.querySelector("#main") == null || Spicetify?.showNotification == undefined || !this.info.isReady()) return;
|
if (document.querySelector("#main") == null || Spicetify?.showNotification == undefined || !this.info.isReady()) return;
|
||||||
this.#ready = true;
|
this.#ready = true;
|
||||||
this.emit("ready");
|
this.emit("ready");
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
|
import { defaults } from "./Util";
|
||||||
import { parseSync as parseSVG, stringify as stringifySVG } from "svgson";
|
import { parseSync as parseSVG, stringify as stringifySVG } from "svgson";
|
||||||
|
|
||||||
export default class Icons {
|
export default class Icons {
|
||||||
/** @typedef {"baseline" | "outline" | "round" | "sharp" | "twotone"} IconStyle */
|
/** @typedef {"custom" | "material:baseline" | "material:outline" | "material:round" | "material:sharp" | "material:twotone"} IconStyle */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} IconOptions
|
* @typedef {Object} IconOptions
|
||||||
* @property {IconStyle} [style="round"]
|
* @property {IconStyle} [style="round"]
|
||||||
|
* @property {String} [className=""]
|
||||||
* @property {Number} [size=16]
|
* @property {Number} [size=16]
|
||||||
* @property {Number} [scale=1]
|
* @property {Number} [scale=1]
|
||||||
* @property {String} [fill="currentColor"]
|
* @property {String} [fill="currentColor"]
|
||||||
|
|
@ -15,24 +17,45 @@ export default class Icons {
|
||||||
/** @type {Object.<String, Object.<IconStyle, String>>} */
|
/** @type {Object.<String, Object.<IconStyle, String>>} */
|
||||||
#icons;
|
#icons;
|
||||||
|
|
||||||
constructor() {
|
constructor(icons) {
|
||||||
this.#icons = process.env.DRIBBBLISH_ICONS;
|
this.#icons = icons ?? process.env.DRIBBBLISH_ICONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRawSVG(name, style = "round") {
|
/**
|
||||||
|
* @param {String} name
|
||||||
|
* @param {IconStyle} style
|
||||||
|
* @returns {String}
|
||||||
|
*/
|
||||||
|
getRawSVG(name, style) {
|
||||||
|
if (style == null) style = this.#getDefaultStyle(name);
|
||||||
if (!this.#icons.hasOwnProperty(name)) throw new Error(`Icon "${name}" does not exist`);
|
if (!this.#icons.hasOwnProperty(name)) throw new Error(`Icon "${name}" does not exist`);
|
||||||
|
|
||||||
if (typeof this.#icons[name] == "string") {
|
|
||||||
return this.#icons[name];
|
|
||||||
} else {
|
|
||||||
if (!this.#icons[name].hasOwnProperty(style)) {
|
if (!this.#icons[name].hasOwnProperty(style)) {
|
||||||
const styles = Object.keys(this.#icons[name])
|
const styles = Object.keys(this.#icons[name])
|
||||||
.map((s) => `"${s}"`)
|
.map((s) => `"${s}"`)
|
||||||
.join(", ");
|
.join(", ");
|
||||||
throw new Error(`Icon "${name}" does not have style "${style}". It is available in styles [${styles}].`);
|
throw new Error(`Icon "${name}" does not have style "${style}". It is available in styles [${styles}].`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.#icons[name][style];
|
return this.#icons[name][style];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAvailableStyles(name) {
|
||||||
|
if (!this.#icons.hasOwnProperty(name)) throw new Error(`Icon "${name}" does not exist`);
|
||||||
|
return Object.keys(this.#icons[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String} name
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
#getDefaultStyle(name) {
|
||||||
|
const styles = this.getAvailableStyles(name);
|
||||||
|
for (const s of ["custom", "material:round"]) {
|
||||||
|
if (styles.includes(s)) return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return styles[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -44,32 +67,43 @@ export default class Icons {
|
||||||
get(name, options) {
|
get(name, options) {
|
||||||
/** @type {IconOptions} */
|
/** @type {IconOptions} */
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
style: "round",
|
style: this.#getDefaultStyle(name),
|
||||||
|
className: "",
|
||||||
size: 16,
|
size: 16,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
fill: "currentColor",
|
fill: "currentColor",
|
||||||
base64: false
|
base64: false
|
||||||
};
|
};
|
||||||
options = { ...defaultOptions, ...options };
|
options = defaults(options, defaultOptions);
|
||||||
|
|
||||||
const svg = parseSVG(this.getRawSVG(name, options.style));
|
const svg = parseSVG(this.getRawSVG(name, options.style));
|
||||||
|
|
||||||
svg.attributes.type = "dribbblish-icon";
|
// Add general / required attributes
|
||||||
|
svg.attributes["icon-type"] = "dribbblish";
|
||||||
|
svg.attributes["icon-name"] = name;
|
||||||
|
svg.attributes["icon-style"] = options.style;
|
||||||
svg.attributes.fill = options.fill;
|
svg.attributes.fill = options.fill;
|
||||||
svg.attributes.width = options.size;
|
svg.attributes.width = options.size;
|
||||||
svg.attributes.height = options.size;
|
svg.attributes.height = options.size;
|
||||||
|
|
||||||
// Create CSSStyleDeclaration by creating an element since there is no constructor for it
|
// Add className
|
||||||
const styles = document.createElement("a").style;
|
if (options.className != "") svg.attributes.class = options.className;
|
||||||
|
|
||||||
|
// Add Styles
|
||||||
|
const styles = {};
|
||||||
if (options.scale != 1) {
|
if (options.scale != 1) {
|
||||||
styles.transform = `scale(${options.scale})`;
|
styles["transform"] = `scale(${options.scale})`;
|
||||||
styles.transformOrigin = "center";
|
styles["transform-origin"] = "center";
|
||||||
}
|
}
|
||||||
|
const styleStr = Object.entries(styles)
|
||||||
|
.map(([prop, val]) => `${prop}: ${val};`)
|
||||||
|
.join(" ");
|
||||||
svg.children = svg.children.map((child) => {
|
svg.children = svg.children.map((child) => {
|
||||||
child.attributes.style = styles.cssText;
|
if (styleStr != "") child.attributes.style = styleStr;
|
||||||
return child;
|
return child;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add title
|
||||||
if (options.title != null) {
|
if (options.title != null) {
|
||||||
svg.children.push({
|
svg.children.push({
|
||||||
name: "title",
|
name: "title",
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,18 @@
|
||||||
|
import Overlay from "./Overlay";
|
||||||
|
|
||||||
export default class Loader {
|
export default class Loader {
|
||||||
/** @type {HTMLDivElement} */
|
/** @type {Overlay} */
|
||||||
#container;
|
#overlay;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.#container = document.createElement("div");
|
this.#overlay = new Overlay();
|
||||||
this.#container.id = "dribbblish-loader";
|
|
||||||
this.#container.innerHTML = `
|
|
||||||
<svg width="65px" height="65px" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<circle fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
|
|
||||||
document.body.appendChild(this.#container);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
show(text) {
|
show(text) {
|
||||||
this.#container.setAttribute("text", text ?? "");
|
this.#overlay.show({ icon: "loading", text });
|
||||||
this.#container.setAttribute("active", "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
this.#container.removeAttribute("active");
|
this.#overlay.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
68
src/js/Overlay.js
Normal file
68
src/js/Overlay.js
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
import { defaults } from "./Util";
|
||||||
|
import { icons } from "./Icons";
|
||||||
|
|
||||||
|
export default class Overlay {
|
||||||
|
/**
|
||||||
|
* @typedef {Object} DribbblishOverlayOptions
|
||||||
|
* @property {String} icon
|
||||||
|
* @property {String} text
|
||||||
|
* @property {DribbblishOverlayColor} color
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} DribbblishOverlayColor
|
||||||
|
* @property {String} [icon]
|
||||||
|
* @property {String} [text]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {HTMLDivElement} */
|
||||||
|
#container;
|
||||||
|
|
||||||
|
/** @type {HTMLElement} */
|
||||||
|
#iconElem;
|
||||||
|
|
||||||
|
/** @type {HTMLSpanElement} */
|
||||||
|
#textElem;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.#container = document.createElement("div");
|
||||||
|
this.#container.id = "dribbblish-overlay";
|
||||||
|
this.#container.innerHTML = /* html */ `
|
||||||
|
<div>
|
||||||
|
<i></i>
|
||||||
|
<span>Loading...</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
this.#iconElem = this.#container.querySelector("i");
|
||||||
|
this.#textElem = this.#container.querySelector("span");
|
||||||
|
|
||||||
|
document.body.appendChild(this.#container);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {DribbblishOverlayOptions} options
|
||||||
|
*/
|
||||||
|
show(options) {
|
||||||
|
const defaultOptions = {
|
||||||
|
icon: "",
|
||||||
|
text: "",
|
||||||
|
color: {
|
||||||
|
icon: "var(--spice-text)",
|
||||||
|
text: "var(--spice-subtext)"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
options = defaults(options, defaultOptions);
|
||||||
|
if (options.icon != "" && !options.icon.startsWith("<svg")) options.icon = icons.get(options.icon, { size: 64 });
|
||||||
|
this.#iconElem.innerHTML = options.icon;
|
||||||
|
this.#iconElem.style.setProperty("--color", options.color.icon);
|
||||||
|
this.#textElem.innerHTML = options.text;
|
||||||
|
this.#textElem.style.setProperty("--color", options.color.text);
|
||||||
|
this.#container.setAttribute("active", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
hide() {
|
||||||
|
this.#container.removeAttribute("active");
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/js/SassUtil.js
Normal file
13
src/js/SassUtil.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
export function lightOffset(n, offset) {
|
||||||
|
return `calc(${n} + ${offset} * var(--is_light))`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function spiceColor(key, alpha = 1, _lightOffset = 0) {
|
||||||
|
if (alpha == 1) {
|
||||||
|
return `var(--spice-${key})`;
|
||||||
|
} else if (_lightOffset == 0) {
|
||||||
|
return `rgba(var(--spice-rgb-${key}), ${alpha})`;
|
||||||
|
} else {
|
||||||
|
return `rgba(var(--spice-rgb-${key}), ${lightOffset(alpha, _lightOffset)})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import MarkdownIt from "markdown-it";
|
import MarkdownIt from "markdown-it";
|
||||||
import MarkdownItAttrs from "markdown-it-attrs";
|
import MarkdownItAttrs from "markdown-it-attrs";
|
||||||
|
import defaultsDeep from "lodash.defaultsdeep";
|
||||||
|
import { default as _debounce } from "lodash.debounce";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @callback waitForElCb
|
* @callback waitForElCb
|
||||||
|
|
@ -69,22 +71,25 @@ export function getRandomInt(min, max) {
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
* @param {T[]} arr
|
||||||
|
* @returns {T}
|
||||||
|
*/
|
||||||
export function randomFromArray(arr) {
|
export function randomFromArray(arr) {
|
||||||
return arr[Math.floor(Math.random() * arr.length)];
|
return arr[Math.floor(Math.random() * arr.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function debounce(func, wait, immediate) {
|
/** @type {_debounce} */
|
||||||
var timeout;
|
export function debounce(fn, wait, opts) {
|
||||||
return function () {
|
return _debounce(fn, wait, opts);
|
||||||
var context = this,
|
}
|
||||||
args = arguments;
|
|
||||||
var later = function () {
|
/**
|
||||||
timeout = null;
|
* @param {Object} options
|
||||||
if (!immediate) func.apply(context, args);
|
* @param {...Object} defaults
|
||||||
};
|
* @returns {Object}
|
||||||
var callNow = immediate && !timeout;
|
*/
|
||||||
clearTimeout(timeout);
|
export function defaults(options, ...defaults) {
|
||||||
timeout = setTimeout(later, wait);
|
return defaultsDeep(options, ...defaults);
|
||||||
if (callNow) func.apply(context, args);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
113
src/js/main.js
113
src/js/main.js
|
|
@ -12,6 +12,7 @@ $("html").attr("dribbblish-js-installed", "");
|
||||||
import { waitForElement, copyToClipboard, capitalizeFirstLetter, getClosestToNum, randomFromArray, debounce } from "./Util";
|
import { waitForElement, copyToClipboard, capitalizeFirstLetter, getClosestToNum, randomFromArray, debounce } from "./Util";
|
||||||
import { default as _Dribbblish } from "./Dribbblish";
|
import { default as _Dribbblish } from "./Dribbblish";
|
||||||
import "./Folders";
|
import "./Folders";
|
||||||
|
import { spiceColor } from "./SassUtil";
|
||||||
|
|
||||||
// To expose to external scripts
|
// To expose to external scripts
|
||||||
const Dribbblish = new _Dribbblish();
|
const Dribbblish = new _Dribbblish();
|
||||||
|
|
@ -47,8 +48,8 @@ Dribbblish.on("ready", () => {
|
||||||
? {
|
? {
|
||||||
icon: "settings",
|
icon: "settings",
|
||||||
color: {
|
color: {
|
||||||
fg: "var(--spice-subtext)",
|
fg: spiceColor("subtext"),
|
||||||
bg: "rgba(var(--spice-rgb-subtext), calc(0.1 + var(--is_light) * 0.05))"
|
bg: spiceColor("subtext", 0.1, 0.05)
|
||||||
},
|
},
|
||||||
order: 999,
|
order: 999,
|
||||||
tooltip: "Open Dribbblish Settings",
|
tooltip: "Open Dribbblish Settings",
|
||||||
|
|
@ -76,7 +77,7 @@ Dribbblish.on("ready", () => {
|
||||||
input.setAttribute("spellcheck", "false");
|
input.setAttribute("spellcheck", "false");
|
||||||
input.addEventListener("click", (e) => {
|
input.addEventListener("click", (e) => {
|
||||||
if (!Spicetify.Platform.History.location.pathname.startsWith("/search")) Spicetify.Platform.History.push(`/search/${input.value}`);
|
if (!Spicetify.Platform.History.location.pathname.startsWith("/search")) Spicetify.Platform.History.push(`/search/${input.value}`);
|
||||||
waitForElement([`[data-testid="search-input"]`], ([defaultSearch]) => {
|
waitForElement([`.main-topBar-topbarContent form[role="search"]`], ([defaultSearch]) => {
|
||||||
input.focus();
|
input.focus();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -216,13 +217,28 @@ Dribbblish.on("ready", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Dribbblish.config.register({
|
Dribbblish.config.register({
|
||||||
order: 999,
|
area: "Playbar",
|
||||||
type: "checkbox",
|
type: "checkbox",
|
||||||
key: "hideAds",
|
key: "showGenreInfoInPlaybar",
|
||||||
name: "Hide Ads",
|
name: "Show Genre Info in Playbar",
|
||||||
description: `Hide ads / premium features (see: [SpotifyNoPremium](https://github.com/Daksh777/SpotifyNoPremium))`,
|
description: "Show artist's genres in the Playbar",
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
onChange: (val) => $("#main").attr("hide-ads", val)
|
onChange: (val) => $("#main").attr("playbar-genre-info", val)
|
||||||
|
});
|
||||||
|
|
||||||
|
Dribbblish.config.register({
|
||||||
|
order: 999,
|
||||||
|
type: "select",
|
||||||
|
data: { none: "Hide Nothing", ads: "Hide Ads", premium: "Hide Premium Features", both: "Hide Both" },
|
||||||
|
key: "hideAdsOrPremium",
|
||||||
|
name: "Hide Ads / Premium Features",
|
||||||
|
description: `Hide ads / premium features like Fullscreen and Download Buttons (see: [SpotifyNoPremium](https://github.com/Daksh777/SpotifyNoPremium))`,
|
||||||
|
defaultValue: "none",
|
||||||
|
onChange: (val) => {
|
||||||
|
if (val == "none") return $("#main").attr("hide-ads", null);
|
||||||
|
if (val == "both") return $("#main").attr("hide-ads", "ads premium");
|
||||||
|
$("#main").attr("hide-ads", val);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
waitForElement([".main-rootlist-rootlist", ".main-rootlist-wrapper > :nth-child(2) > :first-child", "#spicetify-show-list"], ([rootlist]) => {
|
waitForElement([".main-rootlist-rootlist", ".main-rootlist-wrapper > :nth-child(2) > :first-child", "#spicetify-show-list"], ([rootlist]) => {
|
||||||
|
|
@ -389,10 +405,11 @@ Dribbblish.on("ready", () => {
|
||||||
<!-- Leave the lines below as they are -->
|
<!-- Leave the lines below as they are -->
|
||||||
---
|
---
|
||||||
|
|
||||||
### Info for Contributors:
|
<details>
|
||||||
|
<summary>Info for Contributors</summary>
|
||||||
|
|
||||||
**Versions**
|
**Versions**
|
||||||
${Dribbblish.config.getOptions("aboutDribbblishInfo").description}
|
${Dribbblish.config.getOptions("aboutDribbblishInfo").description.split("\n").join("\n ")}
|
||||||
|
|
||||||
**Extensions**
|
**Extensions**
|
||||||
${$(`script[src^="extensions/"]`)
|
${$(`script[src^="extensions/"]`)
|
||||||
|
|
@ -402,12 +419,10 @@ Dribbblish.on("ready", () => {
|
||||||
|
|
||||||
**Settings**
|
**Settings**
|
||||||
\`\`\`json
|
\`\`\`json
|
||||||
${JSON.stringify(Dribbblish.config.export(), null, 4)}
|
${JSON.stringify(Dribbblish.config.export(), null, 4).split("\n").join("\n ")}
|
||||||
\`\`\`
|
\`\`\`
|
||||||
`
|
</details>
|
||||||
.split("\n")
|
`.replace(/^ {12}/gm, "");
|
||||||
.map((line) => line.replace(/^ {16}/, ""))
|
|
||||||
.join("\n");
|
|
||||||
|
|
||||||
const reportURL = new URL("https://github.com/JulienMaille/dribbblish-dynamic-theme/issues/new");
|
const reportURL = new URL("https://github.com/JulienMaille/dribbblish-dynamic-theme/issues/new");
|
||||||
reportURL.searchParams.set("labels", "bug");
|
reportURL.searchParams.set("labels", "bug");
|
||||||
|
|
@ -445,8 +460,13 @@ Dribbblish.on("ready", () => {
|
||||||
|
|
||||||
/* js */
|
/* js */
|
||||||
async function getAlbumRelease(uri) {
|
async function getAlbumRelease(uri) {
|
||||||
const info = await Spicetify.CosmosAsync.get(`hm://album/v1/album-app/album/${uri}/desktop`);
|
const info = await Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/albums/${uri}`);
|
||||||
return { year: info.year, month: (info.month ?? 1) - 1, day: info.day ?? 1 };
|
return { year: info.release_date };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getGenres(uri) {
|
||||||
|
const res = await Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/artists/${uri}`);
|
||||||
|
return res.genres.slice(0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLight(hex) {
|
function isLight(hex) {
|
||||||
|
|
@ -545,11 +565,10 @@ Dribbblish.on("ready", () => {
|
||||||
Algorithm of selecting colors from the albumart
|
Algorithm of selecting colors from the albumart
|
||||||
- **Colorthief [(see)](https://lokeshdhakar.com/projects/color-thief/):** Gets more fitting colors
|
- **Colorthief [(see)](https://lokeshdhakar.com/projects/color-thief/):** Gets more fitting colors
|
||||||
- **Vibrant [(see)](https://jariz.github.io/vibrant.js/):** Gets more vibrant colors *(was the default up to v3.1.1)*
|
- **Vibrant [(see)](https://jariz.github.io/vibrant.js/):** Gets more vibrant colors *(was the default up to v3.1.1)*
|
||||||
- **Spotify:** Basically Vibrant but internal and without support of local files
|
|
||||||
- **Static:** Select a static color to be used
|
- **Static:** Select a static color to be used
|
||||||
{.muted}
|
{.muted}
|
||||||
`,
|
`,
|
||||||
data: { spotify: "Spotify", colorthief: "Colorthief", vibrant: "Vibrant", static: "Static" },
|
data: { colorthief: "Colorthief", vibrant: "Vibrant", static: "Static" },
|
||||||
defaultValue: "colorthief",
|
defaultValue: "colorthief",
|
||||||
onChange: () => updateColors(),
|
onChange: () => updateColors(),
|
||||||
showChildren: (val) => {
|
showChildren: (val) => {
|
||||||
|
|
@ -733,8 +752,19 @@ Dribbblish.on("ready", () => {
|
||||||
}
|
}
|
||||||
const albumInfoSpan = document.getElementById("main-trackInfo-year");
|
const albumInfoSpan = document.getElementById("main-trackInfo-year");
|
||||||
|
|
||||||
let album_uri = Spicetify.Player.data.track.metadata.album_uri;
|
if (!document.getElementById("main-trackInfo-genre")) {
|
||||||
let bgImage = Spicetify.Player.data.track.metadata.image_url;
|
const el = document.createElement("div");
|
||||||
|
el.classList.add("main-trackInfo-release", "standalone-ellipsis-one-line", "main-type-finale");
|
||||||
|
el.setAttribute("as", "div");
|
||||||
|
el.id = "main-trackInfo-genre";
|
||||||
|
document.querySelector(".main-trackInfo-container").append(el);
|
||||||
|
}
|
||||||
|
const genreInfoSpan = document.getElementById("main-trackInfo-genre");
|
||||||
|
|
||||||
|
let track = Spicetify.Player.data.track;
|
||||||
|
let album_uri = track.metadata.album_uri;
|
||||||
|
let artist_uri = track.metadata.artist_uri;
|
||||||
|
let bgImage = track.metadata.image_url;
|
||||||
if (bgImage === undefined) {
|
if (bgImage === undefined) {
|
||||||
bgImage = "/images/tracklist-row-song-fallback.svg";
|
bgImage = "/images/tracklist-row-song-fallback.svg";
|
||||||
}
|
}
|
||||||
|
|
@ -745,22 +775,37 @@ Dribbblish.on("ready", () => {
|
||||||
const albumLinkElem = /* html */ `
|
const albumLinkElem = /* html */ `
|
||||||
<span>
|
<span>
|
||||||
<span draggable="true">
|
<span draggable="true">
|
||||||
<a draggable="false" dir="auto" href="${album_uri}">${Spicetify.Player.data.track.metadata.album_title}</a>
|
<a draggable="false" dir="auto" href="${album_uri}">${track.metadata.album_title}</a>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
`;
|
`;
|
||||||
const albumDateElem = /* html */ `<span> • <span title="${albumDate.format("L")}">${albumDate.format(moment().diff(albumDate, "months") <= 6 ? "MMM YYYY" : "YYYY")}</span></span>`;
|
const albumDateElem = /* html */ `<span> • <span title="${albumDate.format("L")}">${albumDate.format(moment().diff(albumDate, "months") <= 6 ? "MMM YYYY" : "YYYY")}</span></span>`;
|
||||||
albumInfoSpan.innerHTML = `${albumLinkElem}${albumDateElem}`;
|
albumInfoSpan.innerHTML = `${albumLinkElem}${albumDateElem}`;
|
||||||
} else if (Spicetify.Player.data.track.uri.includes("spotify:episode")) {
|
|
||||||
|
let genres = "";
|
||||||
|
if (!album_uri.includes("spotify:episode")) {
|
||||||
|
genres = await getGenres(artist_uri.replace("spotify:artist:", ""));
|
||||||
|
}
|
||||||
|
genreInfoSpan.innerHTML = /* html */ `
|
||||||
|
<span>
|
||||||
|
<span draggable="true">
|
||||||
|
<span draggable="false" dir="auto">${genres.join(", ")}</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
`;
|
||||||
|
} else if (track.uri.includes("spotify:episode")) {
|
||||||
// podcast
|
// podcast
|
||||||
bgImage = bgImage.replace("spotify:image:", "https://i.scdn.co/image/");
|
bgImage = bgImage.replace("spotify:image:", "https://i.scdn.co/image/");
|
||||||
albumInfoSpan.innerHTML = Spicetify.Player.data.track.metadata.album_title;
|
albumInfoSpan.innerHTML = track.metadata.album_title;
|
||||||
} else if (Spicetify.Player.data.track.metadata.is_local == "true") {
|
genreInfoSpan.innerHTML = "";
|
||||||
|
} else if (track.metadata.is_local == "true") {
|
||||||
// local file
|
// local file
|
||||||
albumInfoSpan.innerHTML = Spicetify.Player.data.track.metadata.album_title;
|
albumInfoSpan.innerHTML = track.metadata.album_title;
|
||||||
} else if (Spicetify.Player.data.track.provider == "ad") {
|
genreInfoSpan.innerHTML = "";
|
||||||
|
} else if (track.provider == "ad") {
|
||||||
// ad
|
// ad
|
||||||
albumInfoSpan.innerHTML = "Advertisement";
|
albumInfoSpan.innerHTML = "Advertisement";
|
||||||
|
genreInfoSpan.innerHTML = "";
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// When clicking a song from the homepage, songChange is fired with half empty metadata
|
// When clicking a song from the homepage, songChange is fired with half empty metadata
|
||||||
|
|
@ -780,19 +825,13 @@ Dribbblish.on("ready", () => {
|
||||||
|
|
||||||
$("html").css("--image-brightness", getImageLightness(img) / 255);
|
$("html").css("--image-brightness", getImageLightness(img) / 255);
|
||||||
|
|
||||||
let color = "#509bf5";
|
|
||||||
if (img.complete) {
|
if (img.complete) {
|
||||||
|
let color = "#1ed760";
|
||||||
const colorSelectionAlgorithm = Dribbblish.config.get("colorSelectionAlgorithm");
|
const colorSelectionAlgorithm = Dribbblish.config.get("colorSelectionAlgorithm");
|
||||||
const colorSelectionMode = Dribbblish.config.get("colorSelectionMode");
|
const colorSelectionMode = Dribbblish.config.get("colorSelectionMode");
|
||||||
let palette = {};
|
let palette = {};
|
||||||
|
|
||||||
if (colorSelectionAlgorithm == "spotify") {
|
if (colorSelectionAlgorithm == "colorthief") {
|
||||||
const swatches = await Spicetify.colorExtractor(Spicetify.Player.data.track.uri);
|
|
||||||
for (const col of ["VIBRANT", "VIBRANT_NON_ALARMING", "PROMINENT", "DARK_VIBRANT", "LIGHT_VIBRANT", "DESATURATED"]) {
|
|
||||||
const c = chroma(swatches[col]);
|
|
||||||
palette[c.luminance()] = c;
|
|
||||||
}
|
|
||||||
} else if (colorSelectionAlgorithm == "colorthief") {
|
|
||||||
palette = Object.fromEntries([colorThief.getColor(img), ...colorThief.getPalette(img, 24, 5)].map((c) => chroma(c)).map((c) => [c.luminance(), c]));
|
palette = Object.fromEntries([colorThief.getColor(img), ...colorThief.getPalette(img, 24, 5)].map((c) => chroma(c)).map((c) => [c.luminance(), c]));
|
||||||
} else if (colorSelectionAlgorithm == "vibrant") {
|
} else if (colorSelectionAlgorithm == "vibrant") {
|
||||||
const swatches = await new Promise((resolve, reject) => new Vibrant(img, 5).getPalette().then(resolve).catch(reject));
|
const swatches = await new Promise((resolve, reject) => new Vibrant(img, 5).getPalette().then(resolve).catch(reject));
|
||||||
|
|
@ -818,10 +857,10 @@ Dribbblish.on("ready", () => {
|
||||||
const wantedLuminance = $("html").css("--is_light") == "1" ? Dribbblish.config.get("lightModeLuminance") : Dribbblish.config.get("darkModeLuminance");
|
const wantedLuminance = $("html").css("--is_light") == "1" ? Dribbblish.config.get("lightModeLuminance") : Dribbblish.config.get("darkModeLuminance");
|
||||||
color = palette[getClosestToNum(Object.keys(palette), wantedLuminance)].hex();
|
color = palette[getClosestToNum(Object.keys(palette), wantedLuminance)].hex();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
updateColors(false, color);
|
updateColors(false, color);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var coverListener;
|
var coverListener;
|
||||||
function registerCoverListener() {
|
function registerCoverListener() {
|
||||||
|
|
@ -852,7 +891,7 @@ Dribbblish.on("ready", () => {
|
||||||
fetch("https://api.github.com/repos/JulienMaille/dribbblish-dynamic-theme/releases/latest")
|
fetch("https://api.github.com/repos/JulienMaille/dribbblish-dynamic-theme/releases/latest")
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
Dribbblish.info.set("dribbblish-update", data.tag_name > process.env.DRIBBBLISH_VERSION ? { text: `v${data.tag_name}`, tooltip: "Nev Dribbblish version available", icon: "palette", onClick: () => window.open("https://github.com/JulienMaille/dribbblish-dynamic-theme/releases/latest", "_blank") } : null);
|
Dribbblish.info.set("dribbblish-update", data.tag_name > process.env.DRIBBBLISH_VERSION ? { text: `v${data.tag_name}`, tooltip: "New Dribbblish version available", icon: "palette", onClick: () => window.open("https://github.com/JulienMaille/dribbblish-dynamic-theme/releases/latest", "_blank") } : null);
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ $colors: (
|
||||||
subtext: #f0f0f0,
|
subtext: #f0f0f0,
|
||||||
sidebar-text: #ffffff,
|
sidebar-text: #ffffff,
|
||||||
main: #000000,
|
main: #000000,
|
||||||
sidebar: #1ed760,
|
sidebar: #121212,
|
||||||
player: #000000,
|
player: #000000,
|
||||||
card: #000000,
|
card: #000000,
|
||||||
shadow: #202020,
|
shadow: #202020,
|
||||||
|
|
@ -44,16 +44,3 @@ $props-to-transition: ("sidebar", "main", "text", "button");
|
||||||
transition: all var(--song-transition-speed) linear;
|
transition: all var(--song-transition-speed) linear;
|
||||||
transition-property: $props;
|
transition-property: $props;
|
||||||
}
|
}
|
||||||
|
|
||||||
// $key: the key of the color, e.g. "main"
|
|
||||||
// $alpha: tha alpha in rgba()
|
|
||||||
// $light-offset: added when in light mode
|
|
||||||
@function spiceColor($key, $alpha: 1, $light-offset: 0) {
|
|
||||||
@if $alpha == 1 {
|
|
||||||
@return var(--spice-#{$key});
|
|
||||||
} @else if $light-offset == 0 {
|
|
||||||
@return rgba(var(--spice-rgb-#{$key}), $alpha);
|
|
||||||
} @else {
|
|
||||||
@return rgba(var(--spice-rgb-#{$key}), lightOffset($alpha, $light-offset));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,13 @@
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: clamp(500px, 50%, 650px);
|
width: clamp(500px, 50%, 650px);
|
||||||
background-color: spiceColor("main", 0.95);
|
|
||||||
backdrop-filter: blur(3px);
|
|
||||||
padding: 20px 15px;
|
padding: 20px 15px;
|
||||||
border-radius: var(--main-corner-radius);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@include spiceShadow();
|
@include spiceGlass();
|
||||||
|
|
||||||
> h2 {
|
> h2 {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,6 @@
|
||||||
.connect-device-list-container {
|
.connect-device-list-container {
|
||||||
$border-color: spiceColor("subtext", 0.1, 0.1);
|
|
||||||
|
|
||||||
border: 1px solid $border-color;
|
|
||||||
border-radius: var(--main-corner-radius);
|
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
background-color: spiceColor("main", 0.75, -0.1) !important;
|
@include spiceGlass(lightOffset(0.8, -0.1));
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
border-radius: var(--main-corner-radius);
|
|
||||||
@include spiceShadow();
|
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
.main-contextMenu-menu {
|
.main-contextMenu-menu {
|
||||||
$border-color: spiceColor("subtext", 0.1, 0.1);
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
border: 1px solid $border-color;
|
|
||||||
border-radius: var(--main-corner-radius);
|
border-radius: var(--main-corner-radius);
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
|
||||||
|
|
@ -11,10 +10,7 @@
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0px;
|
inset: 0px;
|
||||||
background-color: spiceColor("main", 0.75, -0.1) !important;
|
@include spiceGlass(lightOffset(0.8, -0.1));
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
border-radius: var(--main-corner-radius);
|
|
||||||
@include spiceShadow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-contextMenu-menuItem {
|
.main-contextMenu-menuItem {
|
||||||
|
|
@ -32,7 +28,7 @@
|
||||||
&::after {
|
&::after {
|
||||||
left: 8px;
|
left: 8px;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
border-color: $border-color;
|
border-color: spiceColor("subtext", 0.1, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
32
src/styles/CustomAppTabBar.scss
Normal file
32
src/styles/CustomAppTabBar.scss
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
.main-topBar-topbarContent {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
& > nav[class*="-tabBar"][class*="-tabBar-nav"] {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
& > ul {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
li[class*="-tabBar-headerItem"] {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
& > a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0px;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0px 8px;
|
||||||
|
border-radius: var(--sidebar-icons-border-radius);
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
line-height: 13px;
|
||||||
|
@include spiceFont("glue", 14px, "Medium");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/styles/Icons.scss
Normal file
7
src/styles/Icons.scss
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
svg[icon-type="dribbblish"] {
|
||||||
|
overflow: visible;
|
||||||
|
|
||||||
|
// &[icon-style="custom"] {}
|
||||||
|
|
||||||
|
// &[icon-style^="material:"] {}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
button.main-button {
|
.main-button {
|
||||||
&-primary {
|
&-primary {
|
||||||
$color: spiceColor("subtext");
|
$color: spiceColor("subtext");
|
||||||
color: $color;
|
color: $color;
|
||||||
|
|
@ -30,7 +30,8 @@ button.main-button {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
&-tertiary {
|
// ? the `:not(...)` is to fix #137
|
||||||
|
&-tertiary:not(.main-entityHeader-titleButton) {
|
||||||
$color: spiceColor("subtext");
|
$color: spiceColor("subtext");
|
||||||
color: $color;
|
color: $color;
|
||||||
background-color: spiceColor("selected-row", 0.2, 0.05) !important;
|
background-color: spiceColor("selected-row", 0.2, 0.05) !important;
|
||||||
|
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
// From https://codepen.io/mrrocks/pen/EiplA
|
|
||||||
@use "sass:math";
|
|
||||||
|
|
||||||
$offset: 187;
|
|
||||||
$duration: 1.4s;
|
|
||||||
|
|
||||||
#dribbblish-loader {
|
|
||||||
z-index: 999999;
|
|
||||||
position: fixed;
|
|
||||||
inset: 0px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 1s ease-in;
|
|
||||||
|
|
||||||
&[active] {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: 0px;
|
|
||||||
background-color: spiceColor("main", 0.9, -0.1);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: attr(text);
|
|
||||||
position: absolute;
|
|
||||||
bottom: 40%;
|
|
||||||
color: spiceColor("subtext");
|
|
||||||
@include spiceFont("glue", 32px, "Bold");
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
animation: rotator $duration linear infinite;
|
|
||||||
|
|
||||||
circle {
|
|
||||||
stroke: spiceColor("sidebar");
|
|
||||||
stroke-dasharray: $offset;
|
|
||||||
stroke-dashoffset: 0;
|
|
||||||
transform-origin: center;
|
|
||||||
animation: dash $duration ease-in-out infinite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes rotator {
|
|
||||||
0% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(270deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes dash {
|
|
||||||
0% {
|
|
||||||
stroke-dashoffset: $offset;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
stroke-dashoffset: math.div($offset, 4);
|
|
||||||
transform: rotate(135deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
stroke-dashoffset: $offset;
|
|
||||||
transform: rotate(450deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
src/styles/Lyrics.scss
Normal file
1
src/styles/Lyrics.scss
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
// TODO: improve default lyrics styles when the classes are mapped `see: https://github.com/JulienMaille/dribbblish-dynamic-theme/issues/144`
|
||||||
|
|
@ -5,15 +5,12 @@
|
||||||
.GenericModal {
|
.GenericModal {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: spiceColor("main", 0.95);
|
|
||||||
backdrop-filter: blur(3px);
|
|
||||||
padding: 24px 16px;
|
padding: 24px 16px;
|
||||||
border-radius: var(--main-corner-radius);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@include spiceShadow();
|
@include spiceGlass();
|
||||||
|
|
||||||
// Popups (`Spicetify.PopupModal.display()`)
|
// Popups (`Spicetify.PopupModal.display()`)
|
||||||
generic-modal & {
|
generic-modal & {
|
||||||
|
|
@ -30,13 +27,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-trackCreditsModal-container {
|
.main- {
|
||||||
|
&trackCreditsModal,
|
||||||
|
&embedWidgetGenerator {
|
||||||
|
&-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
.main-trackCreditsModal-header {
|
&-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
|
@ -56,9 +58,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-trackCreditsModal-mainSection {
|
&-mainSection {
|
||||||
padding: 0px 26px;
|
padding: 0px 26px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,31 @@
|
||||||
#main[hide-ads="true"] {
|
// Hide ads
|
||||||
/* Remove upgrade button*/
|
#main[hide-ads~="ads"] {
|
||||||
.main-topBar-UpgradeButton {
|
// Remove ad placeholder in main screen
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove upgrade to premium button in user menu */
|
|
||||||
.main-contextMenu-menuItemButton[href="https://www.spotify.com/premium/"]
|
|
||||||
{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove ad placeholder in main screen */
|
|
||||||
.main-leaderboardComponent-container {
|
.main-leaderboardComponent-container {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hide premium features
|
||||||
|
#main[hide-ads~="premium"] {
|
||||||
|
// Remove upgrade button
|
||||||
|
.main-topBar-UpgradeButton {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove upgrade to premium button in user menu
|
||||||
|
// prettier-ignore
|
||||||
|
.main-contextMenu-menuItemButton[href="https://www.spotify.com/premium/"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide fullscreen button
|
||||||
|
.volume-bar + .control-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide download buttons
|
||||||
|
.main-actionBar-ActionBarRow button[role="switch"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
42
src/styles/Overlay.scss
Normal file
42
src/styles/Overlay.scss
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
#dribbblish-overlay {
|
||||||
|
z-index: 999999;
|
||||||
|
position: fixed;
|
||||||
|
inset: 0px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 1s ease-in;
|
||||||
|
color: spiceColor("subtext");
|
||||||
|
@include spiceFont("glue", 32px, "Bold");
|
||||||
|
|
||||||
|
&[active] {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
z-index: -1;
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0px;
|
||||||
|
background-color: spiceColor("main", 0.9, -0.1);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
color: var(--color);
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
.GenericModal__overlay {
|
|
||||||
backdrop-filter: blur(3px) brightness(60%);
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
.GenericModal {
|
|
||||||
z-index: 1;
|
|
||||||
position: relative;
|
|
||||||
width: clamp(500px, 50%, 650px);
|
|
||||||
background-color: spiceColor("main", 0.95);
|
|
||||||
backdrop-filter: blur(3px);
|
|
||||||
padding: 24px 16px;
|
|
||||||
border-radius: var(--main-corner-radius);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
@include spiceShadow();
|
|
||||||
|
|
||||||
.main-trackCreditsModal-container {
|
|
||||||
display: flex;
|
|
||||||
gap: 16px;
|
|
||||||
background-color: transparent;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.main-trackCreditsModal-header {
|
|
||||||
display: flex;
|
|
||||||
gap: 16px;
|
|
||||||
padding: 0px;
|
|
||||||
width: 100%;
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
@include spiceFont("glue", 2em, "Bold");
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
position: absolute;
|
|
||||||
top: 16px;
|
|
||||||
right: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-trackCreditsModal-mainSection {
|
|
||||||
padding: 0px 26px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,11 +3,14 @@
|
||||||
@return #{"invert("}$v#{")"};
|
@return #{"invert("}$v#{")"};
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns $n and adds $offset when the theme is light
|
|
||||||
@function lightOffset($n, $offset) {
|
|
||||||
@return calc($n + $offset * var(--is_light));
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin spiceShadow() {
|
@mixin spiceShadow() {
|
||||||
box-shadow: 0px 0px 8px spiceColor("subtext", 0.1, 0.1);
|
box-shadow: 0px 0px 8px spiceColor("subtext", 0.1, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin spiceGlass($opacity: 0.95) {
|
||||||
|
background-color: spiceColor("main", $opacity);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid spiceColor("subtext", 0.1, 0.1);
|
||||||
|
border-radius: var(--main-corner-radius);
|
||||||
|
@include spiceShadow();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,12 @@
|
||||||
@import "NoAds";
|
@import "NoAds";
|
||||||
@import "Markdown";
|
@import "Markdown";
|
||||||
@import "Info";
|
@import "Info";
|
||||||
@import "Loader";
|
|
||||||
@import "Modals";
|
@import "Modals";
|
||||||
@import "ConnectDeviceList";
|
@import "ConnectDeviceList";
|
||||||
|
@import "Lyrics";
|
||||||
|
@import "Icons";
|
||||||
|
@import "Overlay";
|
||||||
|
@import "CustomAppTabBar";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--bar-height: 70px;
|
--bar-height: 70px;
|
||||||
|
|
@ -19,7 +22,7 @@
|
||||||
--scrollbar-vertical-size: 8px;
|
--scrollbar-vertical-size: 8px;
|
||||||
--cover-border-radius: 8px;
|
--cover-border-radius: 8px;
|
||||||
--playbar-movement-anim-speed: 0.5s;
|
--playbar-movement-anim-speed: 0.5s;
|
||||||
--image-radius: 10px;
|
--image-radius: 4px;
|
||||||
--sidebar-icons-border-radius: 50vh; // 50vh = round / pill
|
--sidebar-icons-border-radius: 50vh; // 50vh = round / pill
|
||||||
--song-transition-speed: 3s;
|
--song-transition-speed: 3s;
|
||||||
--is_dark: calc(1 - var(--is_light));
|
--is_dark: calc(1 - var(--is_light));
|
||||||
|
|
@ -132,13 +135,27 @@
|
||||||
box-shadow: 0 4px 20px #21212130;
|
box-shadow: 0 4px 20px #21212130;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.main-trackList-rowMarker {
|
||||||
|
color: spiceColor("text");
|
||||||
|
}
|
||||||
|
|
||||||
.main-trackList-playingIcon {
|
.main-trackList-playingIcon {
|
||||||
|
-webkit-mask-image: url(icon64("equaliser", '{"size": 14}'));
|
||||||
|
background-color: currentColor;
|
||||||
|
content-visibility: hidden;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
filter: grayscale(1);
|
}
|
||||||
|
|
||||||
|
.main-trackList-trackListRowGrid {
|
||||||
|
background-color: var(--spice-main);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-trackList-active {
|
||||||
|
background-color: spiceColor("selected-row", 0.25) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-trackList-trackListRow:hover {
|
.main-trackList-trackListRow:hover {
|
||||||
background-color: spiceColor("selected-row", 0.2) !important;
|
background-color: spiceColor("selected-row", 0.15) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-trackList-trackListRow:focus-within,
|
.main-trackList-trackListRow:focus-within,
|
||||||
|
|
@ -153,6 +170,11 @@ span.artist-artistVerifiedBadge-badge svg > path:last-of-type {
|
||||||
fill: spiceColor("text");
|
fill: spiceColor("text");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Playlist text color */
|
||||||
|
.main-entityHeader-subtitle.main-entityHeader-gra {
|
||||||
|
color: spiceColor("subtext");
|
||||||
|
}
|
||||||
|
|
||||||
/* Full window artist background */
|
/* Full window artist background */
|
||||||
.main-entityHeader-background.main-entityHeader-gradient {
|
.main-entityHeader-background.main-entityHeader-gradient {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
|
|
@ -554,6 +576,7 @@ html.sidebar-hide-text .GlueDropTarget span {
|
||||||
|
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
--progress-bar-height: 2px;
|
--progress-bar-height: 2px;
|
||||||
|
--is-active-fg-color: #{spiceColor("button-active")};
|
||||||
--fg-color: #{spiceColor("button")};
|
--fg-color: #{spiceColor("button")};
|
||||||
--bg-color: #{spiceColor("text", 0.2)};
|
--bg-color: #{spiceColor("text", 0.2)};
|
||||||
}
|
}
|
||||||
|
|
@ -591,14 +614,10 @@ html.sidebar-hide-text .GlueDropTarget span {
|
||||||
transform: translateX(calc(-50%));
|
transform: translateX(calc(-50%));
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
border: 1px solid spiceColor("subtext", 0.1, 0.1);
|
|
||||||
border-radius: var(--main-corner-radius);
|
|
||||||
color: spiceColor("subtext");
|
color: spiceColor("subtext");
|
||||||
background-color: spiceColor("main", 0.75, -0.1) !important;
|
@include spiceGlass();
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
border-radius: var(--main-corner-radius);
|
|
||||||
@include spiceShadow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.minimal-player .player-controls__buttons {
|
.minimal-player .player-controls__buttons {
|
||||||
|
|
@ -653,13 +672,17 @@ html.sidebar-hide-text .GlueDropTarget span {
|
||||||
}
|
}
|
||||||
|
|
||||||
#main-trackInfo-year {
|
#main-trackInfo-year {
|
||||||
display: block;
|
|
||||||
|
|
||||||
#main[playbar-album-info="false"] & {
|
#main[playbar-album-info="false"] & {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#main-trackInfo-genre {
|
||||||
|
#main[playbar-genre-info="false"] & {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.main-topBar-topbarContent .main-playButton-PlayButton {
|
.main-topBar-topbarContent .main-playButton-PlayButton {
|
||||||
--size: 35px !important;
|
--size: 35px !important;
|
||||||
}
|
}
|
||||||
|
|
@ -798,6 +821,10 @@ li.GlueDropTarget {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
max-width: unset;
|
max-width: unset;
|
||||||
padding: 16px 32px !important;
|
padding: 16px 32px !important;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Custom elements */
|
/** Custom elements */
|
||||||
|
|
@ -1266,13 +1293,14 @@ html.right-expanded-cover.buddyfeed-visible .main-coverSlotExpanded-container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix lyrics-plus having a scrollbar when top-bar is `solid` or `transparent`
|
// Fix main-view-containers having a scrollbar when top-bar is `solid` or `transparent`
|
||||||
.lyrics-lyricsContainer-LyricsContainer {
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
.main-view-container__scroll-node-child {
|
.main-view-container__scroll-node-child {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide default Spotify "Offline" notice
|
// Hide default Spotify "Offline" notice
|
||||||
|
|
@ -1280,8 +1308,12 @@ html.right-expanded-cover.buddyfeed-visible .main-coverSlotExpanded-container {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg[type="dribbblish-icon"] {
|
// Notifications
|
||||||
overflow: visible;
|
.main-notificationBubbleContainer-NotificationBubbleContainer {
|
||||||
|
.main-notificationBubble-NotificationBubble {
|
||||||
|
color: spiceColor("subtext");
|
||||||
|
@include spiceGlass();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! WORKAROUNDS / TEMP FIXES
|
// ! WORKAROUNDS / TEMP FIXES
|
||||||
|
|
@ -1301,3 +1333,20 @@ canvas[width="250"][height="250"] {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fix albumn name font size (#171)
|
||||||
|
.main-trackInfo-release {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix play buttons color going green (#174)
|
||||||
|
.encore-bright-accent-set {
|
||||||
|
--background-highlight: var(--spice-button) !important;
|
||||||
|
--background-press: var(--spice-button-active) !important;
|
||||||
|
color: var(--spice-sidebar-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide the triangle under the connect button
|
||||||
|
.control-button--active::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
spicetify config current_theme " " extensions dribbblish-dynamic.js-
|
spicetify config current_theme "SpicetifyDefault" extensions dribbblish-dynamic.js-
|
||||||
|
|
||||||
$spicePath = spicetify -c | Split-Path
|
$spicePath = spicetify -c | Split-Path
|
||||||
$configFile = Get-Content "$spicePath\config-xpui.ini"
|
$configFile = Get-Content "$spicePath\config-xpui.ini"
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ set -e
|
||||||
|
|
||||||
echo "UN-INSTALLING"
|
echo "UN-INSTALLING"
|
||||||
cd "$(dirname "$(spicetify -c)")"
|
cd "$(dirname "$(spicetify -c)")"
|
||||||
spicetify config current_theme " " extensions dribbblish-dynamic.js-
|
spicetify config current_theme "SpicetifyDefault" extensions dribbblish-dynamic.js-
|
||||||
|
|
||||||
echo "UN-PATCHING"
|
echo "UN-PATCHING"
|
||||||
if cat config-xpui.ini | grep -o '\[Patch\]'; then
|
if cat config-xpui.ini | grep -o '\[Patch\]'; then
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,36 @@
|
||||||
const webpack = require("webpack");
|
import webpack from "webpack";
|
||||||
const sass = require("sass");
|
import sass from "sass";
|
||||||
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
|
import { CleanWebpackPlugin } from "clean-webpack-plugin";
|
||||||
const path = require("path");
|
import path from "path";
|
||||||
const fs = require("fs");
|
import fs from "fs";
|
||||||
|
|
||||||
const icons = {};
|
import Icons from "./src/js/Icons";
|
||||||
|
import { lightOffset, spiceColor } from "./src/js/SassUtil";
|
||||||
|
|
||||||
|
const _icons = {};
|
||||||
|
function addIcon(name, style, path) {
|
||||||
|
name = name.replace(/_/g, "-");
|
||||||
|
if (!_icons.hasOwnProperty(name)) _icons[name] = {};
|
||||||
|
_icons[name][style] = fs.readFileSync(path, { encoding: "utf8" });
|
||||||
|
}
|
||||||
// Add Material Icons
|
// Add Material Icons
|
||||||
let iconDir = path.resolve(__dirname, "node_modules/@material-icons/svg/svg");
|
let iconDir = path.resolve(__dirname, "node_modules/@material-icons/svg/svg");
|
||||||
for (const dir of fs.readdirSync(iconDir)) {
|
for (const dir of fs.readdirSync(iconDir)) {
|
||||||
icons[dir.replace("_", "-")] = {};
|
|
||||||
for (const file of fs.readdirSync(path.resolve(iconDir, dir))) {
|
for (const file of fs.readdirSync(path.resolve(iconDir, dir))) {
|
||||||
icons[dir.replace("_", "-")][file.replace(/\..*?$/, "")] = fs.readFileSync(path.resolve(iconDir, dir, file), { encoding: "utf8" });
|
addIcon(dir, `material:${file.replace(/\..*?$/, "")}`, path.resolve(iconDir, dir, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add Custom Icons
|
// Add Custom Icons
|
||||||
iconDir = path.resolve(__dirname, "src/icons");
|
iconDir = path.resolve(__dirname, "src/icons");
|
||||||
for (const icon of fs.readdirSync(iconDir)) {
|
for (const icon of fs.readdirSync(iconDir)) {
|
||||||
icons[icon.replace(/\..*?$/, "")] = fs.readFileSync(path.resolve(iconDir, icon), { encoding: "utf8" });
|
addIcon(icon.replace(/\..*?$/, ""), "custom", path.resolve(iconDir, icon));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const icons = new Icons(_icons);
|
||||||
|
|
||||||
/** @type {import('webpack').Configuration} */
|
/** @type {import('webpack').Configuration} */
|
||||||
module.exports = {
|
const config = {
|
||||||
|
mode: "development",
|
||||||
entry: [path.resolve(__dirname, "src/js/main.js"), path.resolve(__dirname, "src/styles/main.scss"), path.resolve(__dirname, "src/styles/Colors.scss")],
|
entry: [path.resolve(__dirname, "src/js/main.js"), path.resolve(__dirname, "src/styles/main.scss"), path.resolve(__dirname, "src/styles/Colors.scss")],
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, "dist"),
|
path: path.resolve(__dirname, "dist"),
|
||||||
|
|
@ -46,9 +56,20 @@ module.exports = {
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
sassOptions: {
|
sassOptions: {
|
||||||
functions: {
|
functions: {
|
||||||
|
"lightOffset($n, $offset)": (n, offset) => {
|
||||||
|
return new sass.types.String(lightOffset(n.getValue(), offset.getValue()));
|
||||||
|
},
|
||||||
|
"spiceColor($key, $alpha: 1, $light-offset: 0)": (key, alpha, _lightOffset) => {
|
||||||
|
return new sass.types.String(spiceColor(key.getValue(), alpha.getValue(), _lightOffset.getValue()));
|
||||||
|
},
|
||||||
"font64($font)": (font) => {
|
"font64($font)": (font) => {
|
||||||
const file = path.resolve(__dirname, "src/fonts", font.getValue());
|
const file = path.resolve(__dirname, "src/fonts", font.getValue());
|
||||||
return new sass.types.String(`"data:font/truetype;charset=utf-8;base64,${fs.readFileSync(file, { encoding: "base64" })}"`);
|
return new sass.types.String(`"data:font/truetype;charset=utf-8;base64,${fs.readFileSync(file, { encoding: "base64" })}"`);
|
||||||
|
},
|
||||||
|
'icon64($name, $options: "{}")': (name, options) => {
|
||||||
|
name = name.getValue();
|
||||||
|
options = JSON.parse(options.getValue());
|
||||||
|
return new sass.types.String(icons.get(name, { ...options, base64: true }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +96,7 @@ module.exports = {
|
||||||
.replace(/^---(.*?\r?\n)+---(.*?\r?\n)*?(?=\S)/, "") // Replace GitHub header
|
.replace(/^---(.*?\r?\n)+---(.*?\r?\n)*?(?=\S)/, "") // Replace GitHub header
|
||||||
.replace(/\*\*Desktop Setup\*\*\r?\n(- .*?\r?\n)+\r?\n/, "") // Replace **Desktop Setup** block
|
.replace(/\*\*Desktop Setup\*\*\r?\n(- .*?\r?\n)+\r?\n/, "") // Replace **Desktop Setup** block
|
||||||
),
|
),
|
||||||
"process.env.DRIBBBLISH_ICONS": JSON.stringify(icons),
|
"process.env.DRIBBBLISH_ICONS": JSON.stringify(_icons),
|
||||||
"process.env.DRIBBBLISH_VERSION": JSON.stringify(process.env.DRIBBBLISH_VERSION ?? "Dev"),
|
"process.env.DRIBBBLISH_VERSION": JSON.stringify(process.env.DRIBBBLISH_VERSION ?? "Dev"),
|
||||||
"process.env.COMMIT_HASH": JSON.stringify(process.env.COMMIT_HASH ?? "local")
|
"process.env.COMMIT_HASH": JSON.stringify(process.env.COMMIT_HASH ?? "local")
|
||||||
}),
|
}),
|
||||||
|
|
@ -85,3 +106,5 @@ module.exports = {
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
Loading…
Reference in a new issue