mirror of
https://github.com/danbulant/dribbblish-dynamic-theme
synced 2026-05-27 05:51:55 +00:00
add basic event functionality and a loader at startup
This commit is contained in:
parent
83b2801a36
commit
f0a562f70a
11 changed files with 805 additions and 610 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
Added:
|
||||||
|
- A spinning loader at startup while spotify is not ready
|
||||||
|
|
||||||
Fixed:
|
Fixed:
|
||||||
- Checking for update every 10 Minutes not working
|
- Checking for update every 10 Minutes not working
|
||||||
- Background album art is cut off (#116)
|
- Background album art is cut off (#116)
|
||||||
|
|
|
||||||
68
src/js/Dribbblish.js
Normal file
68
src/js/Dribbblish.js
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
import ConfigMenu from "./ConfigMenu";
|
||||||
|
import Info from "./Info";
|
||||||
|
import Loader from "./Loader";
|
||||||
|
|
||||||
|
export default class Dribbblish {
|
||||||
|
/**
|
||||||
|
* @typedef {"ready"} Event
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @callback listener
|
||||||
|
* @param {any} [data]
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {ConfigMenu} */
|
||||||
|
config;
|
||||||
|
|
||||||
|
/** @type {Info} */
|
||||||
|
info;
|
||||||
|
|
||||||
|
/** @type {Loader} */
|
||||||
|
loader;
|
||||||
|
|
||||||
|
/** @type {Object.<string, listener[]>} */
|
||||||
|
#listeners = {};
|
||||||
|
|
||||||
|
/** @type {Boolean} */
|
||||||
|
#ready = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.config = new ConfigMenu();
|
||||||
|
this.info = new Info();
|
||||||
|
this.loader = new Loader();
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
if (document.querySelector("#main") == null || Spicetify?.showNotification == undefined || !this.info.isReady()) return;
|
||||||
|
this.#ready = true;
|
||||||
|
this.emit("ready");
|
||||||
|
clearInterval(interval);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Event} event
|
||||||
|
* @param {any} data
|
||||||
|
*/
|
||||||
|
emit(event, data) {
|
||||||
|
this.#listeners[event]?.forEach((listener) => listener(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Event} event
|
||||||
|
* @param {listener} listener
|
||||||
|
*/
|
||||||
|
on(event, listener) {
|
||||||
|
this.#listeners[event] = [...(this.#listeners[event] ?? []), listener];
|
||||||
|
if (event == "ready" && this.#ready) listener();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Event} event
|
||||||
|
* @param {listener} listener
|
||||||
|
*/
|
||||||
|
off(event, listener) {
|
||||||
|
this.#listeners = this.#listeners[event].filter((f) => f != listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,10 @@ export default class Info {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isReady() {
|
||||||
|
return this.#ready;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} key
|
* @param {String} key
|
||||||
* @param {DribbblishInfo} info
|
* @param {DribbblishInfo} info
|
||||||
|
|
|
||||||
25
src/js/Loader.js
Normal file
25
src/js/Loader.js
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
export default class Loader {
|
||||||
|
/** @type {HTMLDivElement} */
|
||||||
|
#container;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.#container = document.createElement("div");
|
||||||
|
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) {
|
||||||
|
this.#container.setAttribute("text", text ?? "");
|
||||||
|
this.#container.setAttribute("active", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
hide() {
|
||||||
|
this.#container.removeAttribute("active");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -60,3 +60,17 @@ export function htmlToNode(htmlStr) {
|
||||||
div.innerHTML = htmlStr.trim();
|
div.innerHTML = htmlStr.trim();
|
||||||
return div.firstChild;
|
return div.firstChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRandomArbitrary(min, max) {
|
||||||
|
return Math.random() * (max - min) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRandomInt(min, max) {
|
||||||
|
min = Math.ceil(min);
|
||||||
|
max = Math.floor(max);
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function randomFromArray(arr) {
|
||||||
|
return arr[Math.floor(Math.random() * arr.length)];
|
||||||
|
}
|
||||||
|
|
|
||||||
1220
src/js/main.js
1220
src/js/main.js
File diff suppressed because it is too large
Load diff
|
|
@ -27,12 +27,12 @@
|
||||||
backdrop-filter: blur(3px);
|
backdrop-filter: blur(3px);
|
||||||
padding: 20px 15px;
|
padding: 20px 15px;
|
||||||
border-radius: var(--main-corner-radius);
|
border-radius: var(--main-corner-radius);
|
||||||
box-shadow: 0 0 10px 3px #0000003b;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@include spiceShadow();
|
||||||
|
|
||||||
.dribbblish-config-close {
|
.dribbblish-config-close {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
border-radius: var(--main-corner-radius);
|
border-radius: var(--main-corner-radius);
|
||||||
box-shadow: 0px 0px 8px spiceColor("subtext", 0.1, 0.1);
|
box-shadow: 0px 0px 8px spiceColor("subtext", 0.1, 0.1);
|
||||||
|
@include spiceShadow();
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-contextMenu-menuItem {
|
.main-contextMenu-menuItem {
|
||||||
|
|
|
||||||
73
src/styles/Loader.scss
Normal file
73
src/styles/Loader.scss
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
// 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;
|
||||||
|
color: spiceColor("subtext");
|
||||||
|
background-color: spiceColor("main", 0.9, -0.1);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: attr(text);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 40%;
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,3 +2,7 @@
|
||||||
@function lightOffset($n, $offset) {
|
@function lightOffset($n, $offset) {
|
||||||
@return calc($n + $offset * var(--is_light));
|
@return calc($n + $offset * var(--is_light));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin spiceShadow() {
|
||||||
|
box-shadow: 0px 0px 8px spiceColor("subtext", 0.1, 0.1);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
@import "NoAds";
|
@import "NoAds";
|
||||||
@import "Markdown";
|
@import "Markdown";
|
||||||
@import "Info";
|
@import "Info";
|
||||||
|
@import "Loader";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--bar-height: 70px;
|
--bar-height: 70px;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue