Merge pull request 'Add Profile Pictures' (#99) from 94-add-profile-pictures into main

Reviewed-on: LibreTunes/LibreTunes#99
This commit is contained in:
Ethan Girouard 2024-10-01 17:01:56 +00:00
commit 20a3c0c7df
6 changed files with 316 additions and 62 deletions

View File

@ -3,22 +3,10 @@ on: push
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: libretunes-cicd
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Rust toolchain
id: setup-toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly
targets: wasm32-unknown-unknown,x86_64-unknown-linux-gnu
- name: Cache
uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ steps.setup-toolchain.outputs.cachekey }}
- name: Install cargo-leptos
run: cargo install cargo-leptos
- name: Build project - name: Build project
env: env:
RUSTFLAGS: "-D warnings" RUSTFLAGS: "-D warnings"
@ -58,58 +46,26 @@ jobs:
cache-to: type=inline cache-to: type=inline
test: test:
runs-on: ubuntu-latest runs-on: libretunes-cicd
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Rust toolchain
id: setup-toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly
targets: wasm32-unknown-unknown,x86_64-unknown-linux-gnu
- name: Cache
uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ steps.setup-toolchain.outputs.cachekey }}
- name: Test project - name: Test project
run: cargo test --all-targets --all-features run: cargo test --all-targets --all-features
leptos-test: leptos-test:
runs-on: ubuntu-latest runs-on: libretunes-cicd
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Rust toolchain
id: setup-toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly
targets: wasm32-unknown-unknown,x86_64-unknown-linux-gnu
- name: Cache
uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ steps.setup-toolchain.outputs.cachekey }}
- name: Install cargo-leptos
run: cargo install cargo-leptos
- name: Run Leptos tests - name: Run Leptos tests
run: cargo-leptos test run: cargo-leptos test
docs: docs:
runs-on: ubuntu-latest runs-on: libretunes-cicd
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Rust toolchain
id: setup-toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly
targets: wasm32-unknown-unknown,x86_64-unknown-linux-gnu
- name: Cache
uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ steps.setup-toolchain.outputs.cachekey }}
- name: Generate docs - name: Generate docs
run: cargo doc --no-deps run: cargo doc --no-deps
- name: Upload docs - name: Upload docs

231
Cargo.lock generated
View File

@ -17,6 +17,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.8.11" version = "0.8.11"
@ -216,7 +222,7 @@ dependencies = [
"cc", "cc",
"cfg-if", "cfg-if",
"libc", "libc",
"miniz_oxide", "miniz_oxide 0.7.2",
"object", "object",
"rustc-demangle", "rustc-demangle",
] ]
@ -233,6 +239,29 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bindgen"
version = "0.69.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
dependencies = [
"bitflags 2.5.0",
"cexpr",
"clang-sys",
"itertools",
"lazy_static",
"lazycell",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 2.0.58",
"which",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -332,6 +361,15 @@ version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -377,6 +415,17 @@ dependencies = [
"half", "half",
] ]
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]] [[package]]
name = "codee" name = "codee"
version = "0.2.0" version = "0.2.0"
@ -471,6 +520,12 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "cow-utils"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.12" version = "0.2.12"
@ -486,6 +541,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "338089f42c427b86394a5ee60ff321da23a5c89c9d89514c829687b26359fcff" checksum = "338089f42c427b86394a5ee60ff321da23a5c89c9d89514c829687b26359fcff"
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "crunchy" name = "crunchy"
version = "0.2.2" version = "0.2.2"
@ -720,6 +784,35 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "fdeflate"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab"
dependencies = [
"simd-adler32",
]
[[package]]
name = "flate2"
version = "1.0.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0"
dependencies = [
"crc32fast",
"miniz_oxide 0.8.0",
]
[[package]] [[package]]
name = "flexi_logger" name = "flexi_logger"
version = "0.28.0" version = "0.28.0"
@ -1006,6 +1099,15 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "html-escape" name = "html-escape"
version = "0.2.13" version = "0.2.13"
@ -1125,6 +1227,16 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "ico"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3804960be0bb5e4edb1e1ad67afd321a9ecfd875c3e65c099468fd2717d7cae"
dependencies = [
"byteorder",
"png",
]
[[package]] [[package]]
name = "icondata" name = "icondata"
version = "0.3.0" version = "0.3.0"
@ -1336,6 +1448,19 @@ dependencies = [
"unicode-normalization", "unicode-normalization",
] ]
[[package]]
name = "image-convert"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3eb95018550c5770e1a25219a75c192fa2f6475efef2244a0d46799d3fdf6cf"
dependencies = [
"ico",
"magick_rust",
"once_cell",
"regex",
"str-utils",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.6" version = "2.2.6"
@ -1397,6 +1522,12 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "leptos" name = "leptos"
version = "0.6.10" version = "0.6.10"
@ -1672,6 +1803,16 @@ version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets 0.52.4",
]
[[package]] [[package]]
name = "libretunes" name = "libretunes"
version = "0.1.0" version = "0.1.0"
@ -1687,6 +1828,7 @@ dependencies = [
"flexi_logger", "flexi_logger",
"http", "http",
"icondata", "icondata",
"image-convert",
"lazy_static", "lazy_static",
"leptos", "leptos",
"leptos-use", "leptos-use",
@ -1721,6 +1863,12 @@ dependencies = [
"serde_test", "serde_test",
] ]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.11" version = "0.4.11"
@ -1747,6 +1895,17 @@ dependencies = [
"hashbrown 0.14.3", "hashbrown 0.14.3",
] ]
[[package]]
name = "magick_rust"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29f862f489ba66357a730356f1d48abdb2c5028707b6c17dee7842359bc6372c"
dependencies = [
"bindgen",
"libc",
"pkg-config",
]
[[package]] [[package]]
name = "manyhow" name = "manyhow"
version = "0.10.4" version = "0.10.4"
@ -1834,6 +1993,16 @@ dependencies = [
"adler", "adler",
] ]
[[package]]
name = "miniz_oxide"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
dependencies = [
"adler2",
"simd-adler32",
]
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.11" version = "0.8.11"
@ -2059,6 +2228,19 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "png"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0"
dependencies = [
"bitflags 1.3.2",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide 0.8.0",
]
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@ -2334,6 +2516,19 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.5.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.14" version = "1.0.14"
@ -2533,6 +2728,18 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simd-adler32"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@ -2574,6 +2781,16 @@ version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "str-utils"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60bcb3d541a8fd455189b9e022f27d255d103dafd5087a93cff4c0a156a8b597"
dependencies = [
"cow-utils",
"unicase",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
@ -3285,6 +3502,18 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@ -41,6 +41,7 @@ log = { version = "0.4.21", optional = true }
flexi_logger = { version = "0.28.0", optional = true, default-features = false } flexi_logger = { version = "0.28.0", optional = true, default-features = false }
web-sys = "0.3.69" web-sys = "0.3.69"
leptos-use = "0.13.5" leptos-use = "0.13.5"
image-convert = { version = "0.18.0", optional = true, default-features = false }
[patch.crates-io] [patch.crates-io]
gloo-net = { git = "https://github.com/rustwasm/gloo.git", rev = "a823fab7ecc4068e9a28bd669da5eaf3f0a56380" } gloo-net = { git = "https://github.com/rustwasm/gloo.git", rev = "a823fab7ecc4068e9a28bd669da5eaf3f0a56380" }
@ -76,6 +77,7 @@ ssr = [
"log", "log",
"flexi_logger", "flexi_logger",
"leptos-use/ssr", "leptos-use/ssr",
"image-convert",
] ]
# Defines a size-optimized profile for the WASM bundle in release mode # Defines a size-optimized profile for the WASM bundle in release mode

View File

@ -1,8 +1,10 @@
FROM clux/muslrust:nightly AS builder FROM rust:slim as builder
WORKDIR /app WORKDIR /app
RUN rustup default nightly
RUN rustup target add wasm32-unknown-unknown RUN rustup target add wasm32-unknown-unknown
RUN cargo install cargo-leptos
# Install a few dependencies # Install a few dependencies
RUN set -eux; \ RUN set -eux; \
@ -10,19 +12,26 @@ RUN set -eux; \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
pkg-config \ pkg-config \
clang \ clang \
npm; \ build-essential \
libssl-dev \
libpq-dev \
wget; \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
RUN cargo install cargo-leptos # Install ImageMagick
RUN cd / && \
RUN npm install tailwindcss@3.1.8 -g wget https://github.com/ImageMagick/ImageMagick/archive/refs/tags/7.1.1-38.tar.gz && \
tar xf 7.1.1-38.tar.gz && \
rm 7.1.1-38.tar.gz && \
cd ImageMagick-7.1.1-38 && \
./configure && \
make install -j $(nproc) && \
cd .. && \
rm -rf ImageMagick-7.1.1-38
# Copy project dependency manifests # Copy project dependency manifests
COPY Cargo.toml Cargo.lock /app/ COPY Cargo.toml Cargo.lock /app/
# Add the target to Cargo.toml so we can statically link:
RUN echo 'bin-target-triple = "x86_64-unknown-linux-musl"' >> Cargo.toml
# Create dummy files to force cargo to build the dependencies # Create dummy files to force cargo to build the dependencies
RUN mkdir /app/src && mkdir /app/style && mkdir /app/assets && \ RUN mkdir /app/src && mkdir /app/style && mkdir /app/assets && \
echo "fn main() {}" | tee /app/src/build.rs > /app/src/main.rs && \ echo "fn main() {}" | tee /app/src/build.rs > /app/src/main.rs && \
@ -33,15 +42,12 @@ RUN mkdir /app/src && mkdir /app/style && mkdir /app/assets && \
RUN cargo-leptos build --release --precompress RUN cargo-leptos build --release --precompress
RUN rm -rf /app/src /app/style /app/assets RUN rm -rf /app/src /app/style /app/assets
COPY style /app/style
# Minify CSS
RUN npx tailwindcss -i /app/style/main.scss -o /app/style/main.scss --minify
COPY ascii_art.txt /app/ascii_art.txt COPY ascii_art.txt /app/ascii_art.txt
COPY assets /app/assets COPY assets /app/assets
COPY src /app/src COPY src /app/src
COPY migrations /app/migrations COPY migrations /app/migrations
COPY style /app/style
# Touch files to force rebuild # Touch files to force rebuild
RUN touch /app/src/main.rs && touch /app/src/lib.rs && touch /app/src/build.rs RUN touch /app/src/main.rs && touch /app/src/lib.rs && touch /app/src/build.rs
@ -49,6 +55,11 @@ RUN touch /app/src/main.rs && touch /app/src/lib.rs && touch /app/src/build.rs
# Actually build the binary # Actually build the binary
RUN cargo-leptos build --release --precompress RUN cargo-leptos build --release --precompress
# Use ldd to list all dependencies of /app/target/release/libretunes, then copy them to /app/libs
# Setting LD_LIBRARY_PATH is necessary to find the ImageMagick libraries
RUN mkdir /app/libs && LD_LIBRARY_PATH=/usr/local/lib ldd /app/target/release/libretunes | grep "=> /" | \
awk '{print $3}' | xargs -I '{}' cp '{}' /app/libs
# Build the final image # Build the final image
FROM scratch FROM scratch
@ -57,9 +68,15 @@ LABEL description="LibreTunes, an open-source browser audio player and \
library manager built for collaborative listening." library manager built for collaborative listening."
# Copy the binary and the compressed assets to the "site root" # Copy the binary and the compressed assets to the "site root"
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/libretunes /libretunes COPY --from=builder /app/target/release/libretunes /libretunes
COPY --from=builder /app/target/site /site COPY --from=builder /app/target/site /site
# Copy libraries to /lib64
COPY --from=builder /app/libs /lib64
COPY --from=builder /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
ENV LD_LIBRARY_PATH=/lib64
# Configure Leptos settings # Configure Leptos settings
ENV LEPTOS_SITE_ADDR=0.0.0.0:3000 ENV LEPTOS_SITE_ADDR=0.0.0.0:3000
ENV LEPTOS_SITE_ROOT=/site ENV LEPTOS_SITE_ROOT=/site

View File

@ -1,2 +1,3 @@
pub mod history; pub mod history;
pub mod profile;
pub mod songs; pub mod songs;

49
src/api/profile.rs Normal file
View File

@ -0,0 +1,49 @@
use leptos::*;
use server_fn::codec::{MultipartData, MultipartFormData};
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "ssr")] {
use crate::auth::get_user;
use server_fn::error::NoCustomError;
}
}
/// Handle a user uploading a profile picture. Converts the image to webp and saves it to the server.
#[server(input = MultipartFormData, endpoint = "/profile/upload_picture")]
pub async fn upload_picture(data: MultipartData) -> Result<(), ServerFnError> {
// Safe to unwrap - "On the server side, this always returns Some(_). On the client side, always returns None."
let mut data = data.into_inner().unwrap();
let field = data.next_field().await
.map_err(|e| ServerFnError::<NoCustomError>::ServerError(format!("Error getting field: {}", e)))?
.ok_or_else(|| ServerFnError::<NoCustomError>::ServerError("No field found".to_string()))?;
if field.name() != Some("picture") {
return Err(ServerFnError::ServerError("Field name is not 'picture'".to_string()));
}
// Get user id from session
let user = get_user().await
.map_err(|e| ServerFnError::<NoCustomError>::ServerError(format!("Error getting user: {}", e)))?;
let user_id = user.id.ok_or_else(|| ServerFnError::<NoCustomError>::ServerError("User has no id".to_string()))?;
// Read the image, and convert it to webp
use image_convert::{to_webp, WEBPConfig, ImageResource};
let bytes = field.bytes().await
.map_err(|e| ServerFnError::<NoCustomError>::ServerError(format!("Error getting field bytes: {}", e)))?;
let reader = std::io::Cursor::new(bytes);
let image_source = ImageResource::from_reader(reader)
.map_err(|e| ServerFnError::<NoCustomError>::ServerError(format!("Error creating image resource: {}", e)))?;
let profile_picture_path = format!("assets/images/profile/{}.webp", user_id);
let mut image_target = ImageResource::from_path(&profile_picture_path);
to_webp(&mut image_target, &image_source, &WEBPConfig::new())
.map_err(|e| ServerFnError::<NoCustomError>::ServerError(format!("Error converting image to webp: {}", e)))?;
Ok(())
}