summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json679
-rw-r--r--package.json4
-rw-r--r--postcss.config.js7
-rw-r--r--public/index.html28
-rw-r--r--src/albums.js16
-rw-r--r--src/connector.js19
-rw-r--r--src/icons.js7
-rw-r--r--src/icons/check_circle_24dp_E3E3E3_FILL1_wght400_GRAD0_opsz24.svg1
-rw-r--r--src/icons/deselect_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg1
-rw-r--r--src/icons/open_in_new_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg1
-rwxr-xr-xsrc/icons/removefill.sh3
-rw-r--r--src/icons/search_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg1
-rw-r--r--src/icons/select_all_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg1
-rw-r--r--src/index.js2
-rw-r--r--src/slides.js37
-rw-r--r--src/style.css97
-rw-r--r--webpack.config.js13
17 files changed, 870 insertions, 47 deletions
diff --git a/package-lock.json b/package-lock.json
index a2bc97d..eefecf6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
"socket.io-client": "^4.8.1"
},
"devDependencies": {
+ "@tailwindcss/postcss": "^4.1.10",
"autoprefixer": "^10.4.21",
"css-loader": "^7.1.2",
"postcss": "^8.5.3",
@@ -17,11 +18,39 @@
"postcss-nested": "^7.0.2",
"style-loader": "^4.0.0",
"svg-sprite-loader": "^6.0.11",
- "webpack": "^5.99.7",
+ "tailwindcss": "^4.1.10",
+ "webpack": "^5.99.9",
"webpack-cli": "^6.0.1",
"webpack-dev-server": "^5.2.1"
}
},
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -66,6 +95,19 @@
"url": "https://github.com/sponsors/ayuhito"
}
},
+ "node_modules/@isaacs/fs-minipass": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
+ "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
@@ -200,6 +242,292 @@
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
"license": "MIT"
},
+ "node_modules/@tailwindcss/node": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.10.tgz",
+ "integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.3.0",
+ "enhanced-resolve": "^5.18.1",
+ "jiti": "^2.4.2",
+ "lightningcss": "1.30.1",
+ "magic-string": "^0.30.17",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.1.10"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/jiti": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
+ "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.10.tgz",
+ "integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.4",
+ "tar": "^7.4.3"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.1.10",
+ "@tailwindcss/oxide-darwin-arm64": "4.1.10",
+ "@tailwindcss/oxide-darwin-x64": "4.1.10",
+ "@tailwindcss/oxide-freebsd-x64": "4.1.10",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.10",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.1.10",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.1.10",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.1.10",
+ "@tailwindcss/oxide-linux-x64-musl": "4.1.10",
+ "@tailwindcss/oxide-wasm32-wasi": "4.1.10",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.1.10",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.1.10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.10.tgz",
+ "integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.10.tgz",
+ "integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.10.tgz",
+ "integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.10.tgz",
+ "integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.10.tgz",
+ "integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.10.tgz",
+ "integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.10.tgz",
+ "integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.10.tgz",
+ "integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.10.tgz",
+ "integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.10.tgz",
+ "integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.4.3",
+ "@emnapi/runtime": "^1.4.3",
+ "@emnapi/wasi-threads": "^1.0.2",
+ "@napi-rs/wasm-runtime": "^0.2.10",
+ "@tybys/wasm-util": "^0.9.0",
+ "tslib": "^2.8.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.10.tgz",
+ "integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.10.tgz",
+ "integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/postcss": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.10.tgz",
+ "integrity": "sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "@tailwindcss/node": "4.1.10",
+ "@tailwindcss/oxide": "4.1.10",
+ "postcss": "^8.4.41",
+ "tailwindcss": "4.1.10"
+ }
+ },
"node_modules/@types/body-parser": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
@@ -1281,6 +1609,16 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/chownr": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+ "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/chrome-trace-event": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
@@ -1784,6 +2122,16 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
+ "node_modules/detect-libc": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
+ "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
@@ -3966,6 +4314,245 @@
"shell-quote": "^1.8.1"
}
},
+ "node_modules/lightningcss": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
+ "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-darwin-arm64": "1.30.1",
+ "lightningcss-darwin-x64": "1.30.1",
+ "lightningcss-freebsd-x64": "1.30.1",
+ "lightningcss-linux-arm-gnueabihf": "1.30.1",
+ "lightningcss-linux-arm64-gnu": "1.30.1",
+ "lightningcss-linux-arm64-musl": "1.30.1",
+ "lightningcss-linux-x64-gnu": "1.30.1",
+ "lightningcss-linux-x64-musl": "1.30.1",
+ "lightningcss-win32-arm64-msvc": "1.30.1",
+ "lightningcss-win32-x64-msvc": "1.30.1"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz",
+ "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz",
+ "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz",
+ "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz",
+ "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz",
+ "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz",
+ "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz",
+ "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz",
+ "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz",
+ "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz",
+ "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -4011,6 +4598,16 @@
"node": ">=8"
}
},
+ "node_modules/magic-string": {
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0"
+ }
+ },
"node_modules/map-cache": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
@@ -4191,6 +4788,29 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
+ "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/mitt": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-1.1.2.tgz",
@@ -4225,6 +4845,22 @@
"node": ">=0.10.0"
}
},
+ "node_modules/mkdirp": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
+ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -6638,6 +7274,13 @@
"node": ">=6"
}
},
+ "node_modules/tailwindcss": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz",
+ "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@@ -6648,6 +7291,24 @@
"node": ">=6"
}
},
+ "node_modules/tar": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
+ "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@isaacs/fs-minipass": "^4.0.0",
+ "chownr": "^3.0.0",
+ "minipass": "^7.1.2",
+ "minizlib": "^3.0.1",
+ "mkdirp": "^3.0.1",
+ "yallist": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/terser": {
"version": "5.39.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz",
@@ -7228,9 +7889,9 @@
}
},
"node_modules/webpack": {
- "version": "5.99.7",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.7.tgz",
- "integrity": "sha512-CNqKBRMQjwcmKR0idID5va1qlhrqVUKpovi+Ec79ksW8ux7iS1+A6VqzfZXgVYCFRKl7XL5ap3ZoMpwBJxcg0w==",
+ "version": "5.99.9",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz",
+ "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -7614,6 +8275,16 @@
"engines": {
"node": ">=0.4.0"
}
+ },
+ "node_modules/yallist": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+ "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
}
}
}
diff --git a/package.json b/package.json
index 7034250..e27733c 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
"socket.io-client": "^4.8.1"
},
"devDependencies": {
+ "@tailwindcss/postcss": "^4.1.10",
"autoprefixer": "^10.4.21",
"css-loader": "^7.1.2",
"postcss": "^8.5.3",
@@ -16,7 +17,8 @@
"postcss-nested": "^7.0.2",
"style-loader": "^4.0.0",
"svg-sprite-loader": "^6.0.11",
- "webpack": "^5.99.7",
+ "tailwindcss": "^4.1.10",
+ "webpack": "^5.99.9",
"webpack-cli": "^6.0.1",
"webpack-dev-server": "^5.2.1"
}
diff --git a/postcss.config.js b/postcss.config.js
index 5307961..52b9b4b 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -1,6 +1,5 @@
module.exports = {
- plugins: [
- require("autoprefixer"),
- require("postcss-nested"),
- ],
+ plugins: {
+ '@tailwindcss/postcss': {},
+ },
}
diff --git a/public/index.html b/public/index.html
index 20f210b..df128f2 100644
--- a/public/index.html
+++ b/public/index.html
@@ -16,13 +16,10 @@
<!-- <button id="hide"><svg alt="Don't Show This Image"><use href="#skip_next"></use></svg></button> -->
</div>
</div>
- <div id="slideshow-carousel">
- <div class="carousel-cell"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/tulip.jpg" /></div>
- <div class="carousel-cell"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/grapes.jpg" /></div>
- <div class="carousel-cell"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/raspberries.jpg"/></div>
- <div class="carousel-cell"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/wolf.jpg" /></div>
- <div class="carousel-cell"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/shore.jpg" /></div>
- </div>
+ <div id="slideshow-carousel"></div>
+ <template id="carousel-cell-template">
+ <div class="carousel-cell"><img src="" /></div>
+ </template>
<div id="slideshow-bottom-controls">
<button id="prevSlide"><svg alt="Previous Slide"><use href="#sprite-skip_previous"></use></svg></button>
<button id="playPause"><svg alt="Pause"><use href="#sprite-pause"></use></svg></button>
@@ -30,15 +27,22 @@
</div>
</div>
<div id="albums" style="display:none">
+ <input id="album-search" placeholder="Search your albums" />
<div id="albums-container"></div>
<template id="album-template">
<div class="album">
- <img class="album-thumb" />
- <span class="album-name font-bold"></span>
- <div class="album-info">
- <span><span class="album-assets-count"></span> items</span>
- <span class="album-shared">&bull; Shared</span>
+ <svg class="album-selector p24" alt="Select Album"><use href="#sprite-check_circle"></use></svg>
+ <img class="album-thumb hover:invert" />
+ <div class="album-desc-grid">
+ <div>
+ <span class="album-name font-bold"></span>
+ <div class="album-info">
+ <span><span class="album-assets-count"></span> items</span>
+ <span class="album-shared">&bull; Shared</span>
+ </div>
+ </div>
</div>
+ <svg class="album-open p24" alt="View album in Immich"><use href="#sprite-open_in_new"></use></svg>
</div>
</template>
</div>
diff --git a/src/albums.js b/src/albums.js
index e10dd54..19602df 100644
--- a/src/albums.js
+++ b/src/albums.js
@@ -8,7 +8,8 @@ export default async function initAlbums(albumsPageContainer) {
async function createAlbum(res) {
console.log(res.albumName, res.id, res.startDate, res.endDate, res.assetCount, res.shared)
const albumClone = albumTemplate.content.cloneNode(true)
- albumClone.querySelector(".album-thumb").src = apiConnector.albumThumbSrc(res.albumThumbnailAssetId)
+ albumClone.querySelector(".album").dataset.key = res.id
+ albumClone.querySelector(".album-thumb").src = apiConnector.assetThumbnailSrc(res.albumThumbnailAssetId)
albumClone.querySelector(".album-name").textContent = res.albumName
albumClone.querySelector(".album-assets-count").textContent = res.assetCount.toLocaleString()
if (!res.shared)
@@ -22,5 +23,18 @@ export default async function initAlbums(albumsPageContainer) {
for (const res of albumsResponse)
createAlbum(res)
+ albumsContainer.addEventListener("click", e => {
+ // find album element
+ let album = e.target
+ while (album && !album.classList.contains("album"))
+ album = album.parentElement
+
+ if (album === null)
+ return
+
+ console.log(album)
+ album.classList.toggle("selected")
+ })
+
return true
}
diff --git a/src/connector.js b/src/connector.js
index 6c557a8..03e6f3d 100644
--- a/src/connector.js
+++ b/src/connector.js
@@ -6,16 +6,14 @@ class APIConnector {
this.socket = io(url)
this.asset_index = 0
- this.asset = null
- this.prevAssets = null
- this.nextAssets = null
+ this.movement = 0
+ this.assets = null
this.seekCallbacks = []
this.socket.on("seek", e => {
- this.asset_index = e.asset_index
- this.asset = e.asset
- this.prevAssets = e.prev_assets
- this.nextAssets = e.next_assets
+ this.assetIndex = e.asset_index
+ this.movement = e.movement
+ this.assets = e.assets
for (const cb of this.seekCallbacks)
cb()
})
@@ -46,12 +44,11 @@ class APIConnector {
}
fetchAlbums() {
- return this.fetch("/albums/get")
+ return this.fetch("/albums")
}
- albumThumbSrc(key) {
- return `${this.url}/api/albums/thumb/${key}`
- }
+ assetSrc(key) { return `${this.url}/api/asset/${key}` }
+ assetThumbnailSrc(key) { return `${this.url}/api/asset/${key}/thumbnail` }
}
const apiConnector = new APIConnector("http://localhost:5000")
diff --git a/src/icons.js b/src/icons.js
index dd75a4a..099db45 100644
--- a/src/icons.js
+++ b/src/icons.js
@@ -1,11 +1,16 @@
+import "./icons/check_circle_24dp_E3E3E3_FILL1_wght400_GRAD0_opsz24.svg"
+import "./icons/deselect_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg"
import "./icons/download_24dp_FFFFFF_FILL0_wght400_GRAD0_opsz24.svg"
import "./icons/image_24dp_FFFFFF_FILL1_wght400_GRAD0_opsz24.svg"
+import "./icons/open_in_new_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg"
import "./icons/pause_24dp_FFFFFF_FILL1_wght400_GRAD0_opsz24.svg"
import "./icons/photo_album_24dp_FFFFFF_FILL1_wght400_GRAD0_opsz24.svg"
import "./icons/photo_frame_24dp_FFFFFF_FILL1_wght400_GRAD0_opsz24.svg"
import "./icons/play_arrow_24dp_FFFFFF_FILL1_wght400_GRAD0_opsz24.svg"
-import "./icons/share_24dp_FFFFFF_FILL0_wght400_GRAD0_opsz24.svg"
+import "./icons/search_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg"
+import "./icons/select_all_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg"
import "./icons/settings_24dp_FFFFFF_FILL1_wght400_GRAD0_opsz24.svg"
+import "./icons/share_24dp_FFFFFF_FILL0_wght400_GRAD0_opsz24.svg"
import "./icons/skip_next_24dp_FFFFFF_FILL1_wght400_GRAD0_opsz24.svg"
import "./icons/skip_previous_24dp_FFFFFF_FILL1_wght400_GRAD0_opsz24.svg"
import "./icons/slideshow_24dp_FFFFFF_FILL1_wght400_GRAD0_opsz24.svg"
diff --git a/src/icons/check_circle_24dp_E3E3E3_FILL1_wght400_GRAD0_opsz24.svg b/src/icons/check_circle_24dp_E3E3E3_FILL1_wght400_GRAD0_opsz24.svg
new file mode 100644
index 0000000..028526b
--- /dev/null
+++ b/src/icons/check_circle_24dp_E3E3E3_FILL1_wght400_GRAD0_opsz24.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="m424-296 282-282-56-56-226 226-114-114-56 56 170 170Zm56 216q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z"/></svg> \ No newline at end of file
diff --git a/src/icons/deselect_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg b/src/icons/deselect_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg
new file mode 100644
index 0000000..dd46e14
--- /dev/null
+++ b/src/icons/deselect_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="M791-56 567-280H280v-287L56-791l56-57 736 736-57 56ZM360-360h127L360-487v127Zm320-33-80-80v-127H473l-80-80h287v287ZM200-200v80q-33 0-56.5-23.5T120-200h80Zm-80-80v-80h80v80h-80Zm0-160v-80h80v80h-80Zm0-160v-80h80v80h-80Zm160 480v-80h80v80h-80Zm0-640v-80h80v80h-80Zm160 640v-80h80v80h-80Zm0-640v-80h80v80h-80Zm160 640v-80h80v80h-80Zm0-640v-80h80v80h-80Zm160 480v-80h80v80h-80Zm0-160v-80h80v80h-80Zm0-160v-80h80v80h-80Zm0-160v-80q33 0 56.5 23.5T840-760h-80Z"/></svg> \ No newline at end of file
diff --git a/src/icons/open_in_new_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg b/src/icons/open_in_new_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg
new file mode 100644
index 0000000..12e0802
--- /dev/null
+++ b/src/icons/open_in_new_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h280v80H200v560h560v-280h80v280q0 33-23.5 56.5T760-120H200Zm188-212-56-56 372-372H560v-80h280v280h-80v-144L388-332Z"/></svg> \ No newline at end of file
diff --git a/src/icons/removefill.sh b/src/icons/removefill.sh
index c61fd98..399e8e4 100755
--- a/src/icons/removefill.sh
+++ b/src/icons/removefill.sh
@@ -1,3 +1,6 @@
#!/bin/sh
# Google Material Icons -- complete default settings
sed -Ei 's/ ?fill="#[0-9a-fA-F]{6}"//' *.svg
+for svg in *.svg; do
+ echo "import \"./icons/$svg\""
+done
diff --git a/src/icons/search_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg b/src/icons/search_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg
new file mode 100644
index 0000000..1d95298
--- /dev/null
+++ b/src/icons/search_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z"/></svg> \ No newline at end of file
diff --git a/src/icons/select_all_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg b/src/icons/select_all_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg
new file mode 100644
index 0000000..3a6618e
--- /dev/null
+++ b/src/icons/select_all_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="M280-280v-400h400v400H280Zm80-80h240v-240H360v240ZM200-200v80q-33 0-56.5-23.5T120-200h80Zm-80-80v-80h80v80h-80Zm0-160v-80h80v80h-80Zm0-160v-80h80v80h-80Zm80-160h-80q0-33 23.5-56.5T200-840v80Zm80 640v-80h80v80h-80Zm0-640v-80h80v80h-80Zm160 640v-80h80v80h-80Zm0-640v-80h80v80h-80Zm160 640v-80h80v80h-80Zm0-640v-80h80v80h-80Zm160 640v-80h80q0 33-23.5 56.5T760-120Zm0-160v-80h80v80h-80Zm0-160v-80h80v80h-80Zm0-160v-80h80v80h-80Zm0-160v-80q33 0 56.5 23.5T840-760h-80Z"/></svg> \ No newline at end of file
diff --git a/src/index.js b/src/index.js
index a6d2130..d27c8db 100644
--- a/src/index.js
+++ b/src/index.js
@@ -20,7 +20,7 @@ function softRedirect(e) {
e.preventDefault()
let a = e.target
if (a === null) return
- while (a.tagName !== "A" && a !== null)
+ while (a !== null && a.tagName !== "A")
a = a.parentElement
if (a === null) return
Page.softRedirect(a.href)
diff --git a/src/slides.js b/src/slides.js
index 94af74e..fad6472 100644
--- a/src/slides.js
+++ b/src/slides.js
@@ -6,11 +6,19 @@ class Slides {
constructor(slidesContainer) {
/* previous selected index */
this.selectedIndex = 0
+ this.assetIndex = 0
this.slidesContainer = slidesContainer
+ /* append 11 cells to carousel */
+ const carousel = this.slidesContainer.querySelector("#slideshow-carousel")
+ const cellTemplate = this.slidesContainer.querySelector("#carousel-cell-template")
+ this.cells = []
+ for (let i = 0; i < 11; i++)
+ carousel.appendChild(cellTemplate.content.cloneNode(true))
+
/* initialize slides */
- this.flickity = new Flickity("#slideshow-carousel", {
+ this.flickity = new Flickity(carousel, {
wrapAround: true,
prevNextButtons: false,
pageDots: false,
@@ -29,6 +37,9 @@ class Slides {
seekPrevButton.addEventListener("click", () => { this.flickity.previous() ; this.seek() })
seekNextButton.addEventListener("click", () => { this.flickity.next() ; this.seek() })
+
+ /* initialize seek callback */
+ apiConnector.seekCallbacks.push(c => { this.seekCallback() })
}
seek() {
@@ -40,9 +51,31 @@ class Slides {
this.flickity.cells.length - this.selectedIndex, // wrap forwards (-1 -> 0)
].reduce((key, v) => Math.abs(v) < Math.abs(key) ? v : key)
this.selectedIndex = this.flickity.selectedIndex
+ this.assetIndex += increment
apiConnector.seek(increment)
}
+ seekCallback() {
+ let i
+ if (this.assetIndex !== apiConnector.assetIndex) {
+ this.assetIndex = apiConnector.assetIndex
+ i = apiConnector.movement
+
+ for (; i > 0; i--) this.flickity.next()
+ for (; i < 0; i++) this.flickity.previous()
+ this.selectedIndex = this.flickity.selectedIndex
+ }
+
+ // load new imgs
+ // TODO need to make the 11 cells a constant somehow
+ for (i = 0; i < this.flickity.cells.length; i++) {
+ const x = (i + this.selectedIndex + 6) % this.flickity.cells.length
+ const e = this.flickity.cells[x].element
+ const img = e.firstElementChild
+ img.src = apiConnector.assetSrc(apiConnector.assets[i])
+ }
+ }
+
/* Flickity function for scrolling to ensure next and prev pics are always
* visible and to transition between states */
scroll(progress) {
@@ -89,7 +122,7 @@ class Slides {
for (let i = 0; i < imgs.length; i++) {
const img = imgs[i]
img.dataset.index = i
- img.addEventListener("load", this.imageLoaded)
+ img.addEventListener("load", e => { this.imageLoaded(e) })
if (img.complete)
this.positionImageStatic(img)
}
diff --git a/src/style.css b/src/style.css
index e84921e..f370f2c 100644
--- a/src/style.css
+++ b/src/style.css
@@ -1,11 +1,21 @@
+@import "tailwindcss" source(none);
+@source "../public/*.html";
+
:root {
--immich-dark-primary: rgb(172 203 250);
+ --immich-dark-secondary: rgb(33 33 33);
+ --immich-dark-secondary-border: rgb(33 33 33 / .1);
+ --selected-bg: rgb(172 203 250 / .1);
+ --selected-border: rgb(172 203 250 / .1);
+ --immich-dark-hover-bg: rgb(17 24 39);
+ --immich-dark-hover-border: rgb(31 41 55);
}
.font-bold { font-weight: 700 }
body {
background: black;
+ color-scheme: dark;
color: white;
height: 100vh;
max-height: 100vh;
@@ -13,18 +23,25 @@ body {
flex-direction: column;
margin: 0;
font-family: "Overpass", sans-serif;
+ overflow: hidden;
}
main, #slideshow {
height: 100%;
display: flex;
flex-direction: column;
+ overflow: hidden;
}
svg {
fill: white;
width: 100%;
height: 100%;
+
+ &.p24 {
+ width: 24px;
+ height: 24px;
+ }
}
/* slideshow */
@@ -35,10 +52,7 @@ svg {
.carousel-cell {
height: 100%;
width: 80vw;
-
margin: 24px;
-
-
}
.carousel-cell img {
@@ -86,26 +100,91 @@ svg {
/* albums */
#albums {
- width: 100%;
height: 100%;
overflow: scroll;
+ margin-inline: 1rem;
+}
+#album-search {
+ display: block;
+ padding: 1rem;
+ border-radius: 1rem;
+ border: 0;
+ margin: 1rem auto;
+ width: 100%;
+ max-width: 768px;
+ background-color: var(--immich-dark-secondary);
+ font-family: "Overpass", sans-serif;
+
+ &:focus { outline: 2px solid rgb(55, 65, 81) }
}
#albums-container {
display: grid;
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
- gap: 2.5rem;
- max-width: 1366px;
+ grid-template-columns: repeat(auto-fill, minmax(768px, 1fr));
+ width: max-content;
margin: auto;
padding: 2rem;
+ .album {
+ position: relative;
+ display: flex;
+ height: 10rem;
+ gap: 1.5em;
+ padding: 1rem;
+ border: 1px solid transparent;
+ border-bottom: 1px solid var(--selected-border);
+ border-top: 1px solid var(--selected-border);
+ /*border-bottom: 1px solid var(--immich-dark-hover-border);*/
+
+ .album-selector {
+ opacity: 0;
+ border-radius: 50%;
+ align-self: center
+ }
+
+ &.selected {
+ background: var(--selected-bg);
+ }
+
+ &:hover {
+ cursor: pointer;
+ background: var(--immich-dark-hover-bg);
+ border: 1px solid var(--immich-dark-hover-border);
+
+ .album-selector { opacity: .5 }
+ .album-thumb {
+ box-shadow: rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.1) 0px 4px 6px -4px;
+ }
+ .album-name { color: var(--immich-dark-primary) }
+ .album-open { opacity: 1 }
+ }
+
+
+ &.selected .album-selector {
+ opacity: 1;
+ fill: var(--immich-dark-primary);
+ background: black;
+ }
+ }
+
.album-thumb {
- width: 100%;
aspect-ratio: 1/1;
object-fit: cover;
border-radius: 1rem;
- margin-bottom: 1rem;
}
+ .album-desc-grid {
+ display: flex;
+ justify-content: space-between;
+ align-self: center;
+ font-size: 18px;
+ }
+
+ .album-open {
+ position: absolute;
+ bottom: 1rem;
+ right: 1rem;
+ opacity: 0;
+ }
}
@media (max-width: 512px) {
diff --git a/webpack.config.js b/webpack.config.js
index 529e222..ba6756e 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -8,7 +8,18 @@ module.exports = {
use: [
"style-loader",
"css-loader",
- "postcss-loader",
+ {
+ loader: "postcss-loader",
+ options: {
+ postcssOptions: {
+ plugins: [
+ require("autoprefixer"),
+ require("postcss-nested"),
+ require("@tailwindcss/postcss"),
+ ]
+ }
+ }
+ },
],
},
{