From 0016aaa197697ec5ff38dfb3f63ac8b6f74b48e0 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Sat, 15 Nov 2025 15:12:19 +0100 Subject: backend: add image upload --- static/api/images.js | 43 ++++++++++++++++++++++++++++++++++++++++++ static/index.js | 26 +++++++------------------ static/pages/settings/index.js | 4 +--- 3 files changed, 51 insertions(+), 22 deletions(-) (limited to 'static') diff --git a/static/api/images.js b/static/api/images.js index 915aae6..4a41a3c 100644 --- a/static/api/images.js +++ b/static/api/images.js @@ -1,6 +1,43 @@ import * as sfw from 'sfw'; const { Input } = sfw.element.native; +class FileUploader { + constructor(url) { + this.onprogress = () => {} + this.ondone = () => {} + this.url = url; + this.sessions = []; + } + + send(...files) { + let count = 0; + this.sessions = this.sessions.concat(files.map( + file => new Promise((resolve) => { + const xhr = new XMLHttpRequest(); + xhr.upload.addEventListener("progress", (event) => { + if (event.lengthComputable) { + this.onprogress(file, event.loaded, event.total) + } + }); + + xhr.addEventListener("loadend", () => { + count += 1; + + resolve(xhr.readyState === 4 && xhr.status === 200); + + if (count == files.length) { + this.ondone(); + } + }); + + xhr.open("POST", this.url, true); + xhr.setRequestHeader("Content-Type", "application/octet-stream"); + xhr.send(file.slice()); + }) + )); + } +} + export async function upload_to_timeline() { const input = Input.new({ type: 'file', @@ -8,6 +45,12 @@ export async function upload_to_timeline() { accept: 'image/jpeg', }) input.click(); + + const uploader = new FileUploader('/api/image/upload'); + + input.onchange = async () => { + uploader.send(...input.files); + } } export async function upload_to_profile() { diff --git a/static/index.js b/static/index.js index e9ef859..90b5ffd 100644 --- a/static/index.js +++ b/static/index.js @@ -16,20 +16,6 @@ sfw.theme.add_css(await sfw.css(import.meta.url, './index.css')); const image_viewer = ImageViewer.new(); -[ - '/images/0001.jpg', - '/images/0002.jpg', - '/images/0003.jpg', - '/images/0004.jpg', - '/images/0005.jpg', - '/images/0006.jpg', - '/images/0007.jpg', - '/images/0008.jpg', - '/images/0009.jpg', - '/images/0010.jpg', -].forEach(url => image_viewer.add(url)) - - const login = LoginView.new({ onlogin: async (user, password) => { if (await api.auth.login(user, password)) { @@ -102,8 +88,10 @@ document.body.append( month_select, ); -if (await api.session.is_valid()) { - login.hide(); -} else { - login.focus(); -} + +login.hide(); +//if (await api.session.is_valid()) { +// login.hide(); +//} else { +// login.focus(); +//} diff --git a/static/pages/settings/index.js b/static/pages/settings/index.js index 6a0e231..c11a3e9 100644 --- a/static/pages/settings/index.js +++ b/static/pages/settings/index.js @@ -23,9 +23,7 @@ export default class SettingsView extends sfw.element.Container { Div.new({ id: 'image-container', children: [ - Img.new({ - src: '/images/0010.jpg', - }), + Img.new(), ] }), Div.new({ -- cgit v1.2.3-70-g09d2