mirror of
https://github.com/danbulant/dribbblish-dynamic-theme
synced 2026-06-06 00:02:44 +00:00
updating to work with spicetify 2.5.0
This commit is contained in:
parent
b404e47f65
commit
71e2b01fc2
7 changed files with 110 additions and 42 deletions
32
README.md
32
README.md
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
### Customizable sidebar
|
### Customizable sidebar
|
||||||
Rearrange icons positions, stick icons to header or hide unnecessary to save space.
|
Rearrange icons positions, stick icons to header or hide unnecessary to save space.
|
||||||
Turn on Config mode in Profile menu and hover on icon to show control buttons.
|
Turn on "Sidebar config" mode in Profile menu and hover on icon to show control buttons.
|
||||||
After you finish customizing, turn off Config mode in Profile menu to save.
|
After you finish customizing, turn off Config mode in Profile menu to save.
|
||||||
|
|
||||||
<img src="https://i.imgur.com/86gqPe8.png" alt="img" align="center" width="500px">
|
<img src="https://i.imgur.com/86gqPe8.png" alt="img" align="center" width="500px">
|
||||||
|
|
@ -24,20 +24,27 @@ Right click at folder and choose images for your playlist folder. Every image fo
|
||||||
In profile menu, toggle option "Right expanded cover" to change expaned current track cover image to left or right side, whereever you prefer.
|
In profile menu, toggle option "Right expanded cover" to change expaned current track cover image to left or right side, whereever you prefer.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
Make sure you are using spicetify v2 and Spotify v1.1.58 or later.
|
Make sure you are using spicetify >= v2.5.0 and Spotify >= v1.1.56.
|
||||||
|
|
||||||
Run these commands:
|
Run these commands:
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
In **Powershell**:
|
||||||
|
```powershell
|
||||||
|
Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/master/install.ps1" | Invoke-Expression
|
||||||
|
```
|
||||||
|
|
||||||
### Linux and MacOS:
|
### Linux and MacOS:
|
||||||
In **Bash**:
|
In **Bash**:
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/master/install.sh | sh
|
curl -fsSL https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/master/install.sh | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows
|
From Spotify > v1.1.62, in sidebar, they use an adaptive render mechanic to actively show and hide items on scroll. It helps reducing number of items to render, hence there is significant performance boost if you have a large playlists collection. But the drawbacks is that item height is hard-coded, it messes up user interaction when we explicity change, in CSS, playlist item height bigger than original value. So you need to add these 2 lines in Patch section in config file:
|
||||||
In **Powershell**:
|
```ini
|
||||||
```powershell
|
[Patch]
|
||||||
Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/master/install.ps1" | Invoke-Expression
|
xpui.js_find_8008 = ,(\w+=)32,
|
||||||
|
xpui.js_repl_8008 = ,${1}56,
|
||||||
```
|
```
|
||||||
|
|
||||||
## Hide Window Controls
|
## Hide Window Controls
|
||||||
|
|
@ -50,11 +57,20 @@ Moreover, by default, Spotify adjusted sidebar items and profile menu icon to st
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Uninstall
|
## Auto-uninstall
|
||||||
|
### Windows
|
||||||
|
```powershell
|
||||||
|
Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/JulienMaille/dribbblish-dynamic-theme/master/uninstall.ps1" | Invoke-Expression
|
||||||
|
```
|
||||||
|
|
||||||
|
## Manual uninstall
|
||||||
Remove the dribbblish script with the following commands
|
Remove the dribbblish script with the following commands
|
||||||
|
|
||||||
```
|
```
|
||||||
spicetify config extensions dribbblish.js-
|
spicetify config extensions dribbblish.js-
|
||||||
spicetify config extensions dribbblish-dynamic.js-
|
spicetify config extensions dribbblish-dynamic.js-
|
||||||
spicetify apply
|
|
||||||
```
|
```
|
||||||
|
And remove Patch lines you added in config file earlier. Finally, run:
|
||||||
|
```
|
||||||
|
spicetify apply
|
||||||
|
```
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
let current = '1.5'
|
let current = '1.6'
|
||||||
|
|
||||||
/* css is injected so this works with untouched user.css from Dribbblish */
|
/* css is injected so this works with untouched user.css from Dribbblish */
|
||||||
/* dark theme */
|
/* dark theme */
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,16 @@ function waitForElement(els, func, timeout = 100) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForElement([".main-rootlist-rootlistPlaylistsScrollNode ul"], ([query]) => {
|
waitForElement([
|
||||||
|
`.main-rootlist-rootlistPlaylistsScrollNode ul[tabindex="0"]`,
|
||||||
|
`.main-rootlist-rootlistPlaylistsScrollNode ul[tabindex="0"] li`
|
||||||
|
], ([root, firstItem]) => {
|
||||||
|
const listElem = firstItem.parentElement;
|
||||||
|
root.classList.add("dribs-playlist-list");
|
||||||
|
|
||||||
/** Replace Playlist name with their pictures */
|
/** Replace Playlist name with their pictures */
|
||||||
function loadPlaylistImage() {
|
function loadPlaylistImage() {
|
||||||
const sidebarItem = query.querySelectorAll("li.GlueDropTarget");
|
for (const item of listElem.children) {
|
||||||
for (let i = 0; i < sidebarItem.length; i++) {
|
|
||||||
const item = sidebarItem[i];
|
|
||||||
let link = item.querySelector("a");
|
let link = item.querySelector("a");
|
||||||
if (!link) continue;
|
if (!link) continue;
|
||||||
|
|
||||||
|
|
@ -55,11 +59,7 @@ waitForElement([".main-rootlist-rootlistPlaylistsScrollNode ul"], ([query]) => {
|
||||||
img.classList.add("playlist-picture");
|
img.classList.add("playlist-picture");
|
||||||
link.prepend(img);
|
link.prepend(img);
|
||||||
}
|
}
|
||||||
if (base64) {
|
img.src = base64 || "/images/tracklist-row-song-fallback.svg";
|
||||||
img.src = base64;
|
|
||||||
} else {
|
|
||||||
img.src = "";
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ waitForElement([".main-rootlist-rootlistPlaylistsScrollNode ul"], ([query]) => {
|
||||||
loadPlaylistImage();
|
loadPlaylistImage();
|
||||||
|
|
||||||
new MutationObserver(loadPlaylistImage)
|
new MutationObserver(loadPlaylistImage)
|
||||||
.observe(query, {childList: true});
|
.observe(listElem, {childList: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
waitForElement([".Root__main-view"], ([mainView]) => {
|
waitForElement([".Root__main-view"], ([mainView]) => {
|
||||||
|
|
@ -92,10 +92,10 @@ waitForElement([".Root__main-view"], ([mainView]) => {
|
||||||
mainView.prepend(shadow);
|
mainView.prepend(shadow);
|
||||||
});
|
});
|
||||||
|
|
||||||
waitForElement([`.main-rootlist-rootlistPlaylistsScrollNode ul[tabindex="0"]`], ([query]) => {
|
waitForElement([".main-rootlist-rootlistPlaylistsScrollNode"], (queries) => {
|
||||||
const fade = document.createElement("div");
|
const fade = document.createElement("div");
|
||||||
fade.id = "dribbblish-sidebar-fade-in";
|
fade.id = "dribbblish-sidebar-fade-in";
|
||||||
query.append(fade);
|
queries[0].append(fade);
|
||||||
});
|
});
|
||||||
|
|
||||||
waitForElement([
|
waitForElement([
|
||||||
|
|
|
||||||
31
install.ps1
31
install.ps1
|
|
@ -30,6 +30,12 @@ if ($PSVersionTable.PSVersion.Major -gt $PSMinVersion) {
|
||||||
# Enable TLS 1.2 since it is required for connections to GitHub.
|
# Enable TLS 1.2 since it is required for connections to GitHub.
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
||||||
|
$checkSpice = Get-Command spicetify -ErrorAction Silent
|
||||||
|
if ($null -eq $checkSpice) {
|
||||||
|
Write-Host -ForegroundColor Red "Spicetify not found"
|
||||||
|
Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/khanhas/spicetify-cli/master/install.ps1" | Invoke-Expression
|
||||||
|
}
|
||||||
|
|
||||||
if (-not $version) {
|
if (-not $version) {
|
||||||
# Determine latest release via GitHub API.
|
# Determine latest release via GitHub API.
|
||||||
$latest_release_uri =
|
$latest_release_uri =
|
||||||
|
|
@ -68,7 +74,8 @@ if ($PSVersionTable.PSVersion.Major -gt $PSMinVersion) {
|
||||||
Write-Done
|
Write-Done
|
||||||
|
|
||||||
# Check ~\.spicetify.\Themes directory already exists
|
# Check ~\.spicetify.\Themes directory already exists
|
||||||
$sp_dot_dir = "${HOME}\.spicetify\Themes\DribbblishDynamic"
|
$spicePath = spicetify -c | Split-Path
|
||||||
|
$sp_dot_dir = "$spicePath\Themes\DribbblishDynamic"
|
||||||
if (-not (Test-Path $sp_dot_dir)) {
|
if (-not (Test-Path $sp_dot_dir)) {
|
||||||
Write-Part "MAKING FOLDER "; Write-Emphasized $sp_dot_dir
|
Write-Part "MAKING FOLDER "; Write-Emphasized $sp_dot_dir
|
||||||
New-Item -Path $sp_dot_dir -ItemType Directory | Out-Null
|
New-Item -Path $sp_dot_dir -ItemType Directory | Out-Null
|
||||||
|
|
@ -87,13 +94,29 @@ if ($PSVersionTable.PSVersion.Major -gt $PSMinVersion) {
|
||||||
Copy-Item dribbblish-dynamic.js ..\..\Extensions
|
Copy-Item dribbblish-dynamic.js ..\..\Extensions
|
||||||
Copy-Item Vibrant.min.js ..\..\Extensions
|
Copy-Item Vibrant.min.js ..\..\Extensions
|
||||||
spicetify config extensions default-dynamic.js-
|
spicetify config extensions default-dynamic.js-
|
||||||
spicetify config extensions dribbblish.js
|
spicetify config extensions dribbblish.js extensions dribbblish-dynamic.js extensions Vibrant.min.js
|
||||||
spicetify config extensions dribbblish-dynamic.js
|
|
||||||
spicetify config extensions Vibrant.min.js
|
|
||||||
spicetify config current_theme DribbblishDynamic
|
spicetify config current_theme DribbblishDynamic
|
||||||
spicetify config inject_css 1 replace_colors 1 overwrite_assets 1
|
spicetify config inject_css 1 replace_colors 1 overwrite_assets 1
|
||||||
spicetify apply
|
spicetify apply
|
||||||
Write-Done
|
Write-Done
|
||||||
|
|
||||||
|
# Add patch
|
||||||
|
Write-Part "PATCHING "; Write-Emphasized "config-xpui.ini"
|
||||||
|
$configFile = Get-Content "$spicePath\config-xpui.ini"
|
||||||
|
if (-not ($configFile -match "xpui.js_find_8008")) {
|
||||||
|
$rep = @"
|
||||||
|
[Patch]
|
||||||
|
xpui.js_find_8008=,(\w+=)32,
|
||||||
|
xpui.js_repl_8008=,`${1}56,
|
||||||
|
"@
|
||||||
|
# In case missing Patch section
|
||||||
|
if (-not ($configFile -match "\[Patch\]")) {
|
||||||
|
$configFile += "`n[Patch]`n"
|
||||||
|
}
|
||||||
|
$configFile = $configFile -replace "\[Patch\]",$rep
|
||||||
|
Set-Content "$spicePath\config-xpui.ini" $configFile
|
||||||
|
}
|
||||||
|
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";
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,7 @@ mkdir -p ../../Extensions
|
||||||
cp dribbblish.js ../../Extensions/.
|
cp dribbblish.js ../../Extensions/.
|
||||||
cp dribbblish-dynamic.js ../../Extensions/.
|
cp dribbblish-dynamic.js ../../Extensions/.
|
||||||
cp Vibrant.min.js ../../Extensions/.
|
cp Vibrant.min.js ../../Extensions/.
|
||||||
spicetify config extensions dribbblish.js
|
spicetify config extensions dribbblish.js extensions dribbblish-dynamic.js extensions Vibrant.min.js
|
||||||
spicetify config extensions dribbblish-dynamic.js
|
spicetify config current_theme DribbblishDynamic
|
||||||
spicetify config extensions Vibrant.min.js
|
|
||||||
spicetify config current_theme DribbblishDynamic color_scheme base
|
|
||||||
spicetify config inject_css 1 replace_colors 1 overwrite_assets 1
|
spicetify config inject_css 1 replace_colors 1 overwrite_assets 1
|
||||||
spicetify apply
|
spicetify apply
|
||||||
|
|
|
||||||
15
uninstall.ps1
Normal file
15
uninstall.ps1
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
spicetify config current_theme " " extensions dribbblish.js- extensions dribbblish-dynamic.js- extensions Vibrant.min.js-
|
||||||
|
|
||||||
|
$spicePath = spicetify -c | Split-Path
|
||||||
|
$configFile = Get-Content "$spicePath\config-xpui.ini"
|
||||||
|
$find = $configFile -match "xpui.js_find_8008"
|
||||||
|
if ($find) {
|
||||||
|
$configFile = $configFile -replace [regex]::escape($find),""
|
||||||
|
}
|
||||||
|
$repl = $configFile -match "xpui.js_repl_8008"
|
||||||
|
if ($repl) {
|
||||||
|
$configFile = $configFile -replace [regex]::escape($repl),""
|
||||||
|
}
|
||||||
|
Set-Content "$spicePath\config-xpui.ini" $configFile
|
||||||
|
|
||||||
|
spicetify apply
|
||||||
42
user.css
42
user.css
|
|
@ -10,28 +10,28 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Google Sans Display";
|
font-family: "Google Sans Display";
|
||||||
src: url("https://local_resource_host/fonts/GoogleSansDisplayRegular.woff2") format("woff2");
|
src: url("glue-resources/fonts/GoogleSansDisplayRegular.woff2") format("woff2");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Google Sans Display";
|
font-family: "Google Sans Display";
|
||||||
src: url("https://local_resource_host/fonts/GoogleSansDisplayMedium.woff2") format("woff2");
|
src: url("glue-resources/fonts/GoogleSansDisplayMedium.woff2") format("woff2");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Roboto";
|
font-family: "Roboto";
|
||||||
src: url("https://local_resource_host/fonts/Roboto.woff2") format("woff2");
|
src: url("glue-resources/fonts/Roboto.woff2") format("woff2");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Roboto";
|
font-family: "Roboto";
|
||||||
src: url("https://local_resource_host/fonts/RobotoMedium.woff2") format("woff2");
|
src: url("glue-resources/fonts/RobotoMedium.woff2") format("woff2");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
@ -248,6 +248,12 @@ span.artist-artistVerifiedBadge-badge svg > path:last-of-type {
|
||||||
color: rgba(var(--spice-rgb-sidebar-text), 0.8);
|
color: rgba(var(--spice-rgb-sidebar-text), 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.main-buddyFeed-buddyFeedRoot .main-avatar-avatar,
|
||||||
|
.main-buddyFeed-buddyFeedRoot .main-buddyFeed-overlay {
|
||||||
|
width: 32px !important;
|
||||||
|
height: 32px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.main-avatar-avatar.main-avatar-withBadge:after {
|
.main-avatar-avatar.main-avatar-withBadge:after {
|
||||||
box-shadow: 0 0 0 2px var(--spice-sidebar);
|
box-shadow: 0 0 0 2px var(--spice-sidebar);
|
||||||
background-color: var(--spice-notification);
|
background-color: var(--spice-notification);
|
||||||
|
|
@ -295,7 +301,6 @@ html,
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background-image: url("http://local_resource_host/dribbblish.svg");
|
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|
@ -317,6 +322,10 @@ html {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#spicetify-show-list >* {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.main-rootlist-statusIcons {
|
.main-rootlist-statusIcons {
|
||||||
color: var(--spice-sidebar-text);
|
color: var(--spice-sidebar-text);
|
||||||
padding-right: 16px;
|
padding-right: 16px;
|
||||||
|
|
@ -329,7 +338,7 @@ html {
|
||||||
.main-rootlist-expandArrow {
|
.main-rootlist-expandArrow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
right: 4px;
|
right: 12px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
color: var(--spice-sidebar-text) !important;
|
color: var(--spice-sidebar-text) !important;
|
||||||
|
|
@ -352,6 +361,10 @@ html:not(.sidebar-hide-text) .main-rootlist-expandArrow {
|
||||||
padding-bottom: 3px;
|
padding-bottom: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html.sidebar-hide-text .main-rootlist-expandArrow {
|
||||||
|
right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
html.sidebar-hide-text .main-navBar-navBarItem span,
|
html.sidebar-hide-text .main-navBar-navBarItem span,
|
||||||
html.sidebar-hide-text .main-rootlist-rootlistContent span,
|
html.sidebar-hide-text .main-rootlist-rootlistContent span,
|
||||||
html.sidebar-hide-text .main-rootlist-rootlistItem span,
|
html.sidebar-hide-text .main-rootlist-rootlistItem span,
|
||||||
|
|
@ -490,6 +503,7 @@ img.playlist-picture {
|
||||||
.main-rootlist-rootlistItem {
|
.main-rootlist-rootlistItem {
|
||||||
padding-left: calc(var(--indentation)*var(--left-sidebar-item-indentation-width));
|
padding-left: calc(var(--indentation)*var(--left-sidebar-item-indentation-width));
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
|
transition: padding-left .5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.sidebar-hide-text .main-rootlist-rootlistItem {
|
html.sidebar-hide-text .main-rootlist-rootlistItem {
|
||||||
|
|
@ -542,12 +556,12 @@ li.GlueDropTarget {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 20%;
|
height: 15%;
|
||||||
background: linear-gradient(to top, var(--spice-sidebar) 10%, transparent);
|
background: linear-gradient(to top, var(--spice-sidebar) 10%, transparent);
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
#dribs-playlist-list {
|
.dribs-playlist-list {
|
||||||
padding-bottom: 56px;
|
padding-bottom: 56px;
|
||||||
}
|
}
|
||||||
#dribbblish-back-shadow {
|
#dribbblish-back-shadow {
|
||||||
|
|
@ -621,13 +635,15 @@ li.GlueDropTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Main container */
|
/** Main container */
|
||||||
.contentSpacing {
|
.contentSpacing,
|
||||||
|
.artist-artistDiscography-headerContainer {
|
||||||
padding-left: 64px;
|
padding-left: 64px;
|
||||||
padding-right: 64px;
|
padding-right: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
.contentSpacing {
|
.contentSpacing,
|
||||||
|
.artist-artistDiscography-headerContainer {
|
||||||
padding-left: 128px;
|
padding-left: 128px;
|
||||||
padding-right: 128px;
|
padding-right: 128px;
|
||||||
}
|
}
|
||||||
|
|
@ -819,13 +835,13 @@ html.right-expanded-cover.buddyfeed-visible .main-coverSlotExpanded-container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-userWidget-dropDownMenu > context-menu-item > li > a.main-contextMenu-menuItemButton {
|
.main-userWidget-dropDownMenu > li > button {
|
||||||
color: rgba(var(--spice-rgb-selected-row), .7);
|
color: rgba(var(--spice-rgb-selected-row), .7);
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.main-userWidget-dropDownMenu > context-menu-item > li > a.main-contextMenu-menuItemButton:hover,
|
.main-userWidget-dropDownMenu > li > button:hover,
|
||||||
.main-userWidget-dropDownMenu > context-menu-item > li > a.main-contextMenu-menuItemButton:focus {
|
.main-userWidget-dropDownMenu > li > button:focus {
|
||||||
color: var(--spice-text);
|
color: var(--spice-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue