diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/albums.js | 16 | ||||
| -rw-r--r-- | src/connector.js | 19 | ||||
| -rw-r--r-- | src/icons.js | 7 | ||||
| -rw-r--r-- | src/icons/check_circle_24dp_E3E3E3_FILL1_wght400_GRAD0_opsz24.svg | 1 | ||||
| -rw-r--r-- | src/icons/deselect_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg | 1 | ||||
| -rw-r--r-- | src/icons/open_in_new_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg | 1 | ||||
| -rwxr-xr-x | src/icons/removefill.sh | 3 | ||||
| -rw-r--r-- | src/icons/search_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg | 1 | ||||
| -rw-r--r-- | src/icons/select_all_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg | 1 | ||||
| -rw-r--r-- | src/index.js | 2 | ||||
| -rw-r--r-- | src/slides.js | 37 | ||||
| -rw-r--r-- | src/style.css | 97 |
12 files changed, 161 insertions, 25 deletions
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) { |
