filadelfia_archive: When generating a banner, do incremental lower quality to fit 8000 character limit
/ deploy (push) Successful in -22h35m19s Details

master filadelfia_archive_v1.0.5
Jonatan Nilsson 2023-12-05 22:57:59 +00:00
parent 533e279b0b
commit 2e7b3be8d5
5 changed files with 93 additions and 18 deletions

View File

@ -21,9 +21,22 @@ function safeParseReponse(str, status, url) {
} }
} }
let requests = new Set()
let requestIndex = 0
function clearLoading(request) {
requests.delete(request)
if (!requests.size) {
api.loading = false
window.requestAnimationFrame(m.redraw.bind(m))
}
}
const api = { const api = {
loading: false, loading: false,
sendRequest: function(options, isPagination) { sendRequest: function(options, isPagination) {
let request = requestIndex++
requests.add(request)
api.loading = true api.loading = true
let token = Authentication.getToken() let token = Authentication.getToken()
let pagination = isPagination let pagination = isPagination
@ -61,15 +74,14 @@ const api = {
} }
return out return out
} }
return m.request(options) return m.request(options)
.then(function(res) { .then(function(res) {
api.loading = false clearLoading(request)
window.requestAnimationFrame(m.redraw.bind(m))
return res return res
}) })
.catch(function (error) { .catch(function (error) {
api.loading = false clearLoading(request)
window.requestAnimationFrame(m.redraw.bind(m)) window.requestAnimationFrame(m.redraw.bind(m))
if (error.status === 403) { if (error.status === 403) {
Authentication.clearToken() Authentication.clearToken()
@ -82,10 +94,15 @@ const api = {
}) })
}, },
uploadBanner: function(bannerFile, token) { uploadBanner: function(bannerFile, token, reporter) {
let request = requestIndex++
requests.add(request)
api.loading = true
var report = reporter || function() {}
var data = new FormData() var data = new FormData()
data.append('file', bannerFile) data.append('file', bannerFile)
data.append('preview', JSON.stringify({ /*data.append('preview', JSON.stringify({
"out": "base64", "out": "base64",
"format": "avif", "format": "avif",
"resize": { "resize": {
@ -96,10 +113,10 @@ const api = {
"kernel": "mitchell" "kernel": "mitchell"
}, },
"avif": { "avif": {
"quality": 50, "quality": 40,
"effort": 9 "effort": 9
} }
})) }))*/
data.append('medium', JSON.stringify({ data.append('medium', JSON.stringify({
"format": "avif", "format": "avif",
"resize": { "resize": {
@ -115,29 +132,75 @@ const api = {
} }
})) }))
report(lang.api_banner_upload)
return api.sendRequest({ return api.sendRequest({
method: 'POST', method: 'POST',
url: token.resize + '?token=' + token.token, url: token.resize + '?token=' + token.token,
body: data, body: data,
}) })
.then(banner => { .then(async (banner) => {
let preview = null
let quality = 60
while (!preview && quality > 10) {
report(lang.format(lang.api_banner_generate, quality))
let check = await api.sendRequest({
method: 'POST',
url: token.resize + '/' + banner.filename + '?token=' + token.token,
body: {
"preview": {
"out": "base64",
"format": "avif",
"resize": {
"width": 360,
"height": 203,
"fit": "cover",
"withoutEnlargement": true,
"kernel": "mitchell"
},
"avif": {
"quality": quality,
"effort": 9
}
},
},
})
if (check.preview.base64.length < 8000) {
preview = check.preview.base64
} else {
quality -= 5
}
}
report(null)
api.sendRequest({ api.sendRequest({
method: 'DELETE', method: 'DELETE',
url: token.delete + banner.filename + '?token=' + token.token, url: token.delete + banner.filename + '?token=' + token.token,
}).catch(err => console.error(err)) }).catch(err => console.error(err))
return { return {
file: banner, file: bannerFile,
size: bannerFile.size, size: bannerFile.size,
medium: { medium: {
filename: banner.medium.filename, filename: banner.medium.filename,
path: banner.medium.path, path: banner.medium.path,
}, },
preview: { preview: {
base64: banner.preview.base64, base64: preview,
}, },
} }
}) })
.then(
function(res) {
clearLoading(request)
return res
},
function(err) {
clearLoading(request)
return Promise.reject(err)
}
)
}, },
prettyFormatBytes: function(bytes) { prettyFormatBytes: function(bytes) {
@ -153,6 +216,8 @@ const api = {
}, },
uploadFileProgress: function(options, file, reporter) { uploadFileProgress: function(options, file, reporter) {
let request = requestIndex++
requests.add(request)
api.loading = true api.loading = true
return new Promise(function(res, rej) { return new Promise(function(res, rej) {
@ -207,12 +272,10 @@ const api = {
report(request, 0) report(request, 0)
}) })
.then(function(res) { .then(function(res) {
api.loading = false clearLoading(request)
window.requestAnimationFrame(m.redraw.bind(m))
return res return res
}, function(err) { }, function(err) {
api.loading = false clearLoading(request)
window.requestAnimationFrame(m.redraw.bind(m))
return Promise.reject(err) return Promise.reject(err)
}) })
}, },

View File

@ -59,6 +59,10 @@ const i18n = {
'Villa við að eyða efni: {0}'], 'Villa við að eyða efni: {0}'],
article_error: ['Error while saving: {0}', article_error: ['Error while saving: {0}',
'Villa við að vista: {0}'], 'Villa við að vista: {0}'],
api_banner_upload: ['Uploading banner image',
'Er að senda mynd'],
api_banner_generate:['Generating preview, testing quality {0}%',
'Bý til forsíðumynd, prufa {0}% gæði'],
months: { months: {
'1': ['January', '1': ['January',
'Janúar'], 'Janúar'],

View File

@ -19,6 +19,7 @@ const Upload = {
this.cacheVideo = null this.cacheVideo = null
this.cacheImage = null this.cacheImage = null
this.uploading = null this.uploading = null
this.bannerStatus = null
this.form = { this.form = {
title: 'Sunnudagssamkoma', title: 'Sunnudagssamkoma',
date: d, date: d,
@ -49,7 +50,10 @@ const Upload = {
return this.cacheImage return this.cacheImage
} }
return api.uploadBanner(this.form.banner, res) return api.uploadBanner(this.form.banner, res, (status) => {
this.bannerStatus = status
m.redraw()
})
.then(imageData => { .then(imageData => {
this.cacheImage = imageData this.cacheImage = imageData
return res return res
@ -113,6 +117,7 @@ const Upload = {
m.route.set('/') m.route.set('/')
}) })
.catch((error) => { .catch((error) => {
this.bannerStatus = null
this.uploading = null this.uploading = null
if (!error) return if (!error) return
@ -196,6 +201,10 @@ const Upload = {
value: 'Begin upload', value: 'Begin upload',
}), }),
api.loading ? m('div.loading-spinner') : null, api.loading ? m('div.loading-spinner') : null,
this.bannerStatus ? [
m('p', this.bannerStatus),
m('.loading-bar', { style: `--progress: 0%` }),
] : null,
this.uploading ? [ this.uploading ? [
m('p', `${Math.floor(this.uploading.progress)}% (${this.uploading.perSecond}/s)`), m('p', `${Math.floor(this.uploading.progress)}% (${this.uploading.perSecond}/s)`),
m('.loading-bar', { style: `--progress: ${this.uploading.progress}%` }), m('.loading-bar', { style: `--progress: ${this.uploading.progress}%` }),

View File

@ -1,6 +1,6 @@
{ {
"name": "filadelfia_archive", "name": "filadelfia_archive",
"version": "1.0.4", "version": "1.0.5",
"port": 4130, "port": 4130,
"description": "Filadelfia archive", "description": "Filadelfia archive",
"main": "index.js", "main": "index.js",

View File

@ -145,7 +145,6 @@ footer a { font-size: 0.8rem; }
.article { width: 100%; max-width: 1280px; padding: 0.5rem; align-self: center; margin-bottom: 5rem; } .article { width: 100%; max-width: 1280px; padding: 0.5rem; align-self: center; margin-bottom: 5rem; }
.article .full-error { margin-top: 1rem; } .article .full-error { margin-top: 1rem; }
.article-name { flex: 2 1 auto; margin-left: 1rem; } .article-name { flex: 2 1 auto; margin-left: 1rem; }
.image-banner { height: 160px; }
.article h1 { margin: 0; } .article h1 { margin: 0; }
.article h1, .article h1,
.article p { padding: 0 0.5rem 0.5rem; } .article p { padding: 0 0.5rem 0.5rem; }