From e8fe05ecee3a80e8ee891f840edde9ba9fd73aa6 Mon Sep 17 00:00:00 2001 From: Vincent Boutour Date: Tue, 22 Aug 2023 11:57:00 +0200 Subject: [PATCH] chore(deps): Bumping absto Signed-off-by: Vincent Boutour --- cmd/fibr/adapter.go | 2 +- cmd/fibr/static/scripts/async-image.js | 58 ++++---- cmd/fibr/static/scripts/confirm.js | 8 +- cmd/fibr/static/scripts/error.js | 12 +- cmd/fibr/static/scripts/index.min.js | 2 +- cmd/fibr/static/scripts/map.js | 58 ++++---- cmd/fibr/static/scripts/navigation.js | 22 +-- cmd/fibr/static/scripts/throbber.js | 8 +- cmd/fibr/static/scripts/upload.js | 192 ++++++++++++------------- cmd/fibr/static/scripts/webhook.js | 58 ++++---- go.mod | 4 +- go.sum | 8 +- pkg/mocks/storage.go | 4 +- 13 files changed, 217 insertions(+), 219 deletions(-) diff --git a/cmd/fibr/adapter.go b/cmd/fibr/adapter.go index bf9bb840..4f692d8f 100644 --- a/cmd/fibr/adapter.go +++ b/cmd/fibr/adapter.go @@ -16,7 +16,7 @@ type adapters struct { } func newAdapters(config configuration, clients client) (adapters, error) { - storageApp, err := absto.New(config.absto, clients.telemetry.TracerProvider().Tracer("absto")) + storageApp, err := absto.New(config.absto, clients.telemetry.TracerProvider()) if err != nil { return adapters{}, err } diff --git a/cmd/fibr/static/scripts/async-image.js b/cmd/fibr/static/scripts/async-image.js index 018abc7f..f9a08215 100644 --- a/cmd/fibr/static/scripts/async-image.js +++ b/cmd/fibr/static/scripts/async-image.js @@ -1,7 +1,7 @@ // from https://developers.google.com/speed/webp/faq#how_can_i_detect_browser_support_for_webp function isWebPCompatible() { const animatedImage = - 'UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA'; + "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"; return new Promise((resolve, reject) => { const image = new Image(); @@ -79,7 +79,7 @@ function encode(content) { output.push(String.fromCharCode(rune)); } - return btoa(output.join('')); + return btoa(output.join("")); } /** @@ -87,24 +87,24 @@ function encode(content) { */ async function fetchThumbnail() { let fetchURL = document.location.search; - if (fetchURL.includes('?')) { - if (!fetchURL.endsWith('&')) { - fetchURL += '&'; + if (fetchURL.includes("?")) { + if (!fetchURL.endsWith("&")) { + fetchURL += "&"; } - fetchURL += 'thumbnail'; + fetchURL += "thumbnail"; } else { - fetchURL += '?thumbnail'; + fetchURL += "?thumbnail"; } - const response = await fetch(fetchURL, { credentials: 'same-origin' }); + const response = await fetch(fetchURL, { credentials: "same-origin" }); if (response.status >= 400) { - throw new Error('unable to load thumbnails'); + throw new Error("unable to load thumbnails"); } let lazyImageObserver; - if (typeof lazyLoadThumbnail !== 'undefined' && lazyLoadThumbnail) { + if (typeof lazyLoadThumbnail !== "undefined" && lazyLoadThumbnail) { lazyImageObserver = new IntersectionObserver(async (entries, observer) => { for (const entry of entries) { if (!entry.isIntersecting) { @@ -115,20 +115,20 @@ async function fetchThumbnail() { const parent = lazyImage.parentElement.parentElement; const storyThrobber = generateThrobber([ - 'throbber-white', - 'throbber-overlay', + "throbber-white", + "throbber-overlay", ]); parent.appendChild(storyThrobber); lazyImage.addEventListener( - 'load', + "load", () => parent.removeChild(storyThrobber), { once: true }, ); if (window.webpHero) { const response = await fetch(lazyImage.dataset.src, { - credentials: 'same-origin', + credentials: "same-origin", }); const content = await response.arrayBuffer(); @@ -147,7 +147,7 @@ async function fetchThumbnail() { for await (let chunk of readChunk(response)) { const commaIndex = chunk.findIndex((element) => element === 44); if (commaIndex === -1) { - console.error('invalid line for thumbnail:', line); + console.error("invalid line for thumbnail:", line); continue; } @@ -162,7 +162,7 @@ async function fetchThumbnail() { img.src = `data:image/webp;base64,${encode(chunk.slice(commaIndex + 1))}`; img.alt = picture.dataset.alt; img.dataset.src = picture.dataset.src; - img.classList.add('thumbnail', 'full', 'block'); + img.classList.add("thumbnail", "full", "block"); replaceContent(picture, img); @@ -172,48 +172,48 @@ async function fetchThumbnail() { } } -document.addEventListener('readystatechange', async (event) => { - if (event.target.readyState !== 'complete') { +document.addEventListener("readystatechange", async (event) => { + if (event.target.readyState !== "complete") { return; } let dateTimeFormatter = new Intl.DateTimeFormat(navigator.language, { - dateStyle: 'full', - timeStyle: 'long', + dateStyle: "full", + timeStyle: "long", }); - document.querySelectorAll('.date').forEach((item) => { + document.querySelectorAll(".date").forEach((item) => { item.innerHTML = dateTimeFormatter.format(new Date(item.innerHTML)); }); }); document.addEventListener( - 'readystatechange', + "readystatechange", async (event) => { - if (event.target.readyState !== 'complete') { + if (event.target.readyState !== "complete") { return; } - if (typeof hasThumbnail === 'undefined' || !hasThumbnail) { + if (typeof hasThumbnail === "undefined" || !hasThumbnail) { return; } - const thumbnailsElem = document.querySelectorAll('[data-thumbnail]'); + const thumbnailsElem = document.querySelectorAll("[data-thumbnail]"); if (!thumbnailsElem) { return; } thumbnailsElem.forEach((picture) => { - replaceContent(picture, generateThrobber(['throbber-white'])); + replaceContent(picture, generateThrobber(["throbber-white"])); }); try { await isWebPCompatible(); } catch (e) { await resolveScript( - 'https://unpkg.com/webp-hero@0.0.2/dist-cjs/webp-hero.bundle.js', - 'sha512-DA6h9H5Sqn55/uVn4JI4aSPFnAWoCQYYDXUnvjOAMNVx11///hX4QaFbQt5yWsrIm9hSI5fLJYfRWt3KXneSXQ==', - 'anonymous', + "https://unpkg.com/webp-hero@0.0.2/dist-cjs/webp-hero.bundle.js", + "sha512-DA6h9H5Sqn55/uVn4JI4aSPFnAWoCQYYDXUnvjOAMNVx11///hX4QaFbQt5yWsrIm9hSI5fLJYfRWt3KXneSXQ==", + "anonymous", ); } diff --git a/cmd/fibr/static/scripts/confirm.js b/cmd/fibr/static/scripts/confirm.js index 493350f1..6628a12b 100644 --- a/cmd/fibr/static/scripts/confirm.js +++ b/cmd/fibr/static/scripts/confirm.js @@ -1,10 +1,10 @@ -document.addEventListener('readystatechange', (event) => { - if (event.target.readyState !== 'complete') { +document.addEventListener("readystatechange", (event) => { + if (event.target.readyState !== "complete") { return; } - document.querySelectorAll('[data-confirm]').forEach((element) => { - element.addEventListener('click', (e) => { + document.querySelectorAll("[data-confirm]").forEach((element) => { + element.addEventListener("click", (e) => { if ( !confirm(`Are you sure you want to delete ${element.dataset.confirm}?`) ) { diff --git a/cmd/fibr/static/scripts/error.js b/cmd/fibr/static/scripts/error.js index b9862180..22be8993 100644 --- a/cmd/fibr/static/scripts/error.js +++ b/cmd/fibr/static/scripts/error.js @@ -1,15 +1,15 @@ -document.addEventListener('readystatechange', (event) => { - if (event.target.readyState !== 'complete') { +document.addEventListener("readystatechange", (event) => { + if (event.target.readyState !== "complete") { return; } - const link = document.getElementById('go-back'); + const link = document.getElementById("go-back"); if (link) { - link.setAttribute('href', document.referrer); - link.addEventListener('click', (e) => { + link.setAttribute("href", document.referrer); + link.addEventListener("click", (e) => { e.preventDefault(); - window.addEventListener('popstate', () => { + window.addEventListener("popstate", () => { window.location.reload(true); }); history.back(); diff --git a/cmd/fibr/static/scripts/index.min.js b/cmd/fibr/static/scripts/index.min.js index 02b8711f..52c9ef8d 100644 --- a/cmd/fibr/static/scripts/index.min.js +++ b/cmd/fibr/static/scripts/index.min.js @@ -1 +1 @@ -function isWebPCompatible(){const e="UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA";return new Promise((t,n)=>{const s=new Image;s.onload=()=>{s.width>0&&s.height>0?t():n()},s.onerror=n.bind(null,!0),s.src=`data:image/webp;base64,${e}`})}function appendChunk(e,t){const n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}function findIndexEscapeSequence(e,t){let n=0;for(let s=0;s=400)throw new Error("unable to load thumbnails");let t;typeof lazyLoadThumbnail!="undefined"&&lazyLoadThumbnail&&(t=new IntersectionObserver(async(e)=>{for(const s of e){if(!s.isIntersecting)continue;const n=s.target,o=n.parentElement.parentElement,i=generateThrobber(["throbber-white","throbber-overlay"]);if(o.appendChild(i),n.addEventListener("load",()=>o.removeChild(i),{once:!0}),window.webpHero){const t=await fetch(n.dataset.src,{credentials:"same-origin"}),s=await t.arrayBuffer(),e=new webpHero.WebpMachine;n.src=await e.decode(new Uint8Array(s)),e.clearCache()}else n.src=n.dataset.src;t.unobserve(n)}}));for await(let o of readChunk(n)){const i=o.findIndex(e=>e===44);if(i===-1){console.error("invalid line for thumbnail:",line);continue}const s=document.getElementById(`picture-${String.fromCharCode.apply(null,o.slice(0,i))}`);if(!s)continue;const e=new Image;e.src=`data:image/webp;base64,${encode(o.slice(i+1))}`,e.alt=s.dataset.alt,e.dataset.src=s.dataset.src,e.classList.add("thumbnail","full","block"),replaceContent(s,e),t!==void 0&&t.observe(e)}}document.addEventListener("readystatechange",async e=>{if(e.target.readyState!=="complete")return;let t=new Intl.DateTimeFormat(navigator.language,{dateStyle:"full",timeStyle:"long"});document.querySelectorAll(".date").forEach(e=>{e.innerHTML=t.format(new Date(e.innerHTML))})}),document.addEventListener("readystatechange",async e=>{if(e.target.readyState!=="complete")return;if(typeof hasThumbnail=="undefined"||!hasThumbnail)return;const t=document.querySelectorAll("[data-thumbnail]");if(!t)return;t.forEach(e=>{replaceContent(e,generateThrobber(["throbber-white"]))});try{await isWebPCompatible()}catch{await resolveScript("https://unpkg.com/webp-hero@0.0.2/dist-cjs/webp-hero.bundle.js","sha512-DA6h9H5Sqn55/uVn4JI4aSPFnAWoCQYYDXUnvjOAMNVx11///hX4QaFbQt5yWsrIm9hSI5fLJYfRWt3KXneSXQ==","anonymous")}try{await fetchThumbnail()}catch(e){console.error(e)}if(window.webpHero){const e=new webpHero.WebpMachine;e.polyfillDocument(),e.clearCache()}},!1),document.addEventListener("readystatechange",e=>{if(e.target.readyState!=="complete")return;document.querySelectorAll("[data-confirm]").forEach(e=>{e.addEventListener("click",t=>{confirm(`Are you sure you want to delete ${e.dataset.confirm}?`)||t.preventDefault()})})}),document.addEventListener("readystatechange",e=>{if(e.target.readyState!=="complete")return;const t=document.getElementById("go-back");t&&(t.setAttribute("href",document.referrer),t.addEventListener("click",e=>(e.preventDefault(),window.addEventListener("popstate",()=>{window.location.reload(!0)}),history.back(),!1)))});async function fetchGeoJSON(e){const t=await fetch(e,{credentials:"same-origin"});if(t.status>=400)throw new Error("unable to load geojson");return t.status===204?null:t.json()}async function addStyle(e,t,n){return new Promise(s=>{const o=document.createElement("link");o.rel="stylesheet",o.href=e,o.onload=s,t&&(o.integrity=t,o.crossOrigin=n),document.querySelector("head").appendChild(o)})}async function loadLeaflet(){const e="1.9.4";await addStyle(`https://unpkg.com/leaflet@${e}/dist/leaflet.css`,"sha512-Zcn6bjR/8RZbLEpLIeOwNtzREBAJnUKESxces60Mpoj+2okopSAcSUIUOseddDm0cxnGQzxIR7vJgsLZbdLE3w==","anonymous"),await addStyle("https://unpkg.com/leaflet.markercluster@1.5.1/dist/MarkerCluster.Default.css","sha512-6ZCLMiYwTeli2rVh3XAPxy3YoR5fVxGdH/pz+KMCzRY2M65Emgkw00Yqmhh8qLGeYQ3LbVZGdmOX9KUjSKr0TA==","anonymous"),await resolveScript(`https://unpkg.com/leaflet@${e}/dist/leaflet.js`,"sha512-BwHfrr4c9kmRkLw6iXFdzcdWV/PGkVgiIyIWLLlTSXzWQzxuSg4DiQUCpauz/EWjgk5TYQqX/kvn9pG1NpYfqg==","anonymous"),await resolveScript("https://unpkg.com/leaflet.markercluster@1.5.1/dist/leaflet.markercluster.js","sha512-+Zr0llcuE/Ho6wXRYtlWypMyWSEMxrWJxrYgeAMDRSf1FF46gQ3PAVOVp5RHdxdzikZXuHZ0soHpqRkkPkI3KA==","anonymous")}let map;async function renderMap(e){if(map){map.invalidateSize();return}const t=document.getElementById("map-container"),n=generateThrobber(["map-throbber","throbber-white"]);t&&t.appendChild(n),await loadLeaflet(),map=L.map("map-container",{center:[46.227638,2.213749],zoom:5}),L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{maxZoom:19,attribution:'© OpenStreetMap contributors'}).addTo(map);const s=await fetchGeoJSON(e);if(!s||!s.features)return;const o=L.markerClusterGroup({zoomToBoundsOnClick:!1}),i=[];s.features.map(e=>{const t=L.GeoJSON.coordsToLatLng(e.geometry.coordinates);i.push(t),o.addLayer(L.circleMarker(t).bindPopup(`Image thumbnail
${e.properties.date}`,{maxWidth:"auto",closeButton:!1,className:"thumbnail-popup"}))}),o.on("clusterclick",e=>{map.fitBounds(e.layer.getAllChildMarkers().map(e=>e.getLatLng()))}),i.length?(map.once("zoomend",()=>{t.removeChild(n)}),map.fitBounds(i)):t.removeChild(n),map.addLayer(o)}document.addEventListener("readystatechange",async e=>{if(e.target.readyState!=="complete")return;document.location.hash==="#map"?await renderMap(geoURL):window.addEventListener("popstate",async()=>{document.location.hash==="#map"&&await renderMap(geoURL)})});function resolveScript(e,t,n){return new Promise((s,o)=>{const i=document.createElement("script");i.type="text/javascript",i.src=e,i.async=!0,i.onload=s.bind(null,!0),i.onerror=o.bind(null,!0),t&&(i.integrity=t,i.crossOrigin=n),document.querySelector("head").appendChild(i)})}window.onkeyup=e=>{switch(e.key){case"ArrowLeft":goToPrevious();break;case"ArrowRight":goToNext();break;case"Escape":goBack(e);break}};function goBack(e){const t=document.location.hash;if(t){if(typeof abort=="function"&&typeof aborter!="undefined"){abort(e);return}document.location.hash="",/success$/gim.test(t)&&window.location.reload(!0);return}if(typeof parentPage=="undefined")return;window.location.href=parentPage}function goToPrevious(){if(typeof previousFile=="undefined")return;window.location.href=previousFile}function goToNext(){if(typeof nextFile=="undefined")return;window.location.href=nextFile}function replaceContent(e,t){for(;e.firstChild;)e.removeChild(e.firstChild);t&&e.appendChild(t)}function generateThrobber(e=[]){const t=document.createElement("div");t.classList.add("throbber"),e.forEach(e=>t.classList.add(e));for(let e=1;e<4;e++){const n=document.createElement("div");n.classList.add("throbber-dot",`throbber-dot-${e}`),t.appendChild(n)}return t}let fileInput,uploadList,cancelButton;function eventNoop(e){e.preventDefault(),e.stopPropagation()}document.addEventListener("readystatechange",async e=>{if(e.target.readyState!=="complete")return;const t=document.getElementsByTagName("body")[0];t.addEventListener("dragover",eventNoop),t.addEventListener("dragleave",eventNoop),t.addEventListener("drop",e=>{eventNoop(e),window.location.hash="#upload-modal",fileInput&&(fileInput.files=e.dataTransfer.files,fileInput.dispatchEvent(new Event("change")))})});function bufferToHex(e){return Array.prototype.map.call(new Uint8Array(e),e=>`00${e.toString(16)}`.slice(-2)).join("")}async function sha(e){const t=await crypto.subtle.digest("SHA-256",new TextEncoder("utf-8").encode(e));return bufferToHex(t)}async function fileMessageId(e){const t=await sha(JSON.stringify({name:e.name,size:e.size,type:e.type,lastModified:e.lastModified}));return`upload-file-${t}`}function humanFileSize(e){return e<1024?e+"bytes":e<1048576?(e/1024).toFixed(0)+" KB":(e/1048576).toFixed(0)+" MB"}async function addUploadItem(e,t){const c=await fileMessageId(t),n=document.createElement("div");n.id=c,n.classList.add("flex","flex-center","margin");const o=document.createElement("div");o.classList.add("upload-item"),n.appendChild(o);const s=document.createElement("input");s.id=`${c}-filename`,s.classList.add("upload-name","full"),s.type="text",s.value=t.name,o.appendChild(s);const i=document.createElement("div");i.classList.add("full","flex","flex-center");const r=document.createElement("em");r.innerHTML=humanFileSize(t.size),r.style.width="8rem",i.appendChild(r);const a=document.createElement("progress");a.classList.add("flex-grow","margin-left"),a.max=100,a.value=0,i.appendChild(a),o.appendChild(i);const l=document.createElement("span");l.classList.add("upload-status"),n.appendChild(l),e.appendChild(n)}function getFiles(e){return[].filter.call(e.target,e=>e.nodeName.toLowerCase()==="input").reduce((e,t)=>(t.type==="file"?e.files=t.files:e[t.name]=t.value,e),{})}function getFilename(e,t){const n=document.getElementById(`${e}-filename`);return n&&n.value?n.value:t.name}function clearUploadStatus(e){if(!e)return;const t=e.querySelector(".upload-status");if(!t)return;t.classList.remove("danger"),t.classList.remove("success")}async function setUploadStatus(e,t,n,s){if(!e)return;const o=e.querySelector(".upload-status");if(!o)return;o.innerHTML=t,o.classList.add(n),s&&(o.title=s)}let uploadFile,aborter;const chunkSize=1024*1024;let currentUpload={};async function uploadFileByChunks(e,t,n,s){let i;if(e&&(i=e.querySelector("progress"),clearUploadStatus(e)),s.name!==currentUpload.filename){currentUpload.filename=s.name,currentUpload.chunks=[];for(let e=0;e=400)return Promise.reject(await a.text());currentUpload.chunks[e].done=!0,i&&(i.value=chunkSize*(e+1)/s.size*100)}const o=new FormData;o.append("method",t),o.append("filename",n),o.append("size",s.size);const a=await fetch("",{method:"POST",credentials:"same-origin",headers:{"X-Chunk-Upload":!0,Accept:"text/plain"},body:o}),r=await a.text();return a.status>=400?Promise.reject(r):(currentUpload={},Promise.resolve(r))}async function uploadFileByXHR(e,t,n,s){let o;e&&(o=e.querySelector("progress"),clearUploadStatus(e));const i=new FormData;return i.append("method",t),i.append("filename",n),i.append("size",s.size),i.append("file",s),new Promise((e,t)=>{let n=new XMLHttpRequest;aborter=n,o&&n.upload.addEventListener("progress",e=>o.value=parseInt(e.loaded/e.total*100,10),!1),n.addEventListener("readystatechange",s=>{if(n.readyState===XMLHttpRequest.UNSENT){t(new Error("request aborted")),n=void 0;return}if(n.readyState!==XMLHttpRequest.DONE)return;n.status>=200&&n.status<400?(o&&(o.value=100),e(n.responseText),n=void 0):(t(s),n=void 0)},!1),n.open("POST","",!0),n.setRequestHeader("Accept","text/plain"),n.send(i)})}function sliceFileList(e,t){const n=document.getElementById(e),s=new DataTransfer;for(;t{if(e.target.readyState!=="complete")return;if(typeof chunkUpload!="undefined"&&(chunkUpload?uploadFile=uploadFileByChunks:uploadFile=uploadFileByXHR),fileInput=document.getElementById("file"),uploadList=document.getElementById("upload-list"),cancelButton=document.getElementById("upload-cancel"),fileInput){fileInput.classList.add("opacity"),fileInput.multiple=!0,fileInput.addEventListener("change",()=>{window.location.hash="#upload-modal",replaceContent(uploadList);for(const e of fileInput.files)addUploadItem(uploadList,e)});const e=document.getElementById("upload-button-link");e&&e.addEventListener("click",e=>{eventNoop(e),fileInput.click()})}const t=document.getElementById("file-label");t&&(t.classList.remove("hidden"),t.innerHTML="Choose files..."),uploadList&&uploadList.classList.remove("hidden"),cancelButton&&cancelButton.addEventListener("click",goBack);const n=document.getElementById("upload-form");n&&n.addEventListener("submit",upload)}),document.addEventListener("readystatechange",e=>{if(e.target.readyState!=="complete")return;const t=document.getElementById("webhook-url-label");if(!t)return;const n=document.getElementById("webhook-url"),s=document.getElementById("telegram-chat-id");document.getElementById("webhook-kind-raw").addEventListener("change",e=>{e.target.value==="raw"&&(n.placeholder="https://website.com/fibr",t.innerHTML="URL",s.classList.add("hidden"))}),document.getElementById("webhook-kind-discord").addEventListener("change",e=>{e.target.value==="discord"&&(n.placeholder="https://discord.com/api/webhooks/...",t.innerHTML="URL",s.classList.add("hidden"))}),document.getElementById("webhook-kind-slack").addEventListener("change",e=>{e.target.value==="slack"&&(n.placeholder="https://hooks.slack.com/services/...",t.innerHTML="URL",s.classList.add("hidden"))}),document.getElementById("webhook-kind-telegram").addEventListener("change",e=>{e.target.value==="telegram"&&(t.innerHTML="Token",n.placeholder="Bot token",s.classList.remove("hidden"))})}) \ No newline at end of file +function isWebPCompatible(){const e="UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA";return new Promise((t,n)=>{const s=new Image;s.onload=()=>{s.width>0&&s.height>0?t():n()},s.onerror=n.bind(null,!0),s.src=`data:image/webp;base64,${e}`})}function appendChunk(e,t){const n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}function findIndexEscapeSequence(e,t){let n=0;for(let s=0;s=400)throw new Error("unable to load thumbnails");let t;typeof lazyLoadThumbnail!="undefined"&&lazyLoadThumbnail&&(t=new IntersectionObserver(async(e)=>{for(const s of e){if(!s.isIntersecting)continue;const n=s.target,o=n.parentElement.parentElement,i=generateThrobber(["throbber-white","throbber-overlay"]);if(o.appendChild(i),n.addEventListener("load",()=>o.removeChild(i),{once:!0}),window.webpHero){const t=await fetch(n.dataset.src,{credentials:"same-origin"}),s=await t.arrayBuffer(),e=new webpHero.WebpMachine;n.src=await e.decode(new Uint8Array(s)),e.clearCache()}else n.src=n.dataset.src;t.unobserve(n)}}));for await(let o of readChunk(n)){const i=o.findIndex(e=>e===44);if(i===-1){console.error("invalid line for thumbnail:",line);continue}const s=document.getElementById(`picture-${String.fromCharCode.apply(null,o.slice(0,i))}`);if(!s)continue;const e=new Image;e.src=`data:image/webp;base64,${encode(o.slice(i+1))}`,e.alt=s.dataset.alt,e.dataset.src=s.dataset.src,e.classList.add("thumbnail","full","block"),replaceContent(s,e),t!==void 0&&t.observe(e)}}document.addEventListener("readystatechange",async e=>{if(e.target.readyState!=="complete")return;let t=new Intl.DateTimeFormat(navigator.language,{dateStyle:"full",timeStyle:"long"});document.querySelectorAll(".date").forEach(e=>{e.innerHTML=t.format(new Date(e.innerHTML))})}),document.addEventListener("readystatechange",async e=>{if(e.target.readyState!=="complete")return;if(typeof hasThumbnail=="undefined"||!hasThumbnail)return;const t=document.querySelectorAll("[data-thumbnail]");if(!t)return;t.forEach(e=>{replaceContent(e,generateThrobber(["throbber-white"]))});try{await isWebPCompatible()}catch{await resolveScript("https://unpkg.com/webp-hero@0.0.2/dist-cjs/webp-hero.bundle.js","sha512-DA6h9H5Sqn55/uVn4JI4aSPFnAWoCQYYDXUnvjOAMNVx11///hX4QaFbQt5yWsrIm9hSI5fLJYfRWt3KXneSXQ==","anonymous")}try{await fetchThumbnail()}catch(e){console.error(e)}if(window.webpHero){const e=new webpHero.WebpMachine;e.polyfillDocument(),e.clearCache()}},!1),document.addEventListener("readystatechange",e=>{if(e.target.readyState!=="complete")return;document.querySelectorAll("[data-confirm]").forEach(e=>{e.addEventListener("click",t=>{confirm(`Are you sure you want to delete ${e.dataset.confirm}?`)||t.preventDefault()})})}),document.addEventListener("readystatechange",e=>{if(e.target.readyState!=="complete")return;const t=document.getElementById("go-back");t&&(t.setAttribute("href",document.referrer),t.addEventListener("click",e=>(e.preventDefault(),window.addEventListener("popstate",()=>{window.location.reload(!0)}),history.back(),!1)))});async function fetchGeoJSON(e){const t=await fetch(e,{credentials:"same-origin"});if(t.status>=400)throw new Error("unable to load geojson");return t.status===204?null:t.json()}async function addStyle(e,t,n){return new Promise(s=>{const o=document.createElement("link");o.rel="stylesheet",o.href=e,o.onload=s,t&&(o.integrity=t,o.crossOrigin=n),document.querySelector("head").appendChild(o)})}async function loadLeaflet(){const e="1.9.4";await addStyle(`https://unpkg.com/leaflet@${e}/dist/leaflet.css`,"sha512-Zcn6bjR/8RZbLEpLIeOwNtzREBAJnUKESxces60Mpoj+2okopSAcSUIUOseddDm0cxnGQzxIR7vJgsLZbdLE3w==","anonymous"),await addStyle("https://unpkg.com/leaflet.markercluster@1.5.1/dist/MarkerCluster.Default.css","sha512-6ZCLMiYwTeli2rVh3XAPxy3YoR5fVxGdH/pz+KMCzRY2M65Emgkw00Yqmhh8qLGeYQ3LbVZGdmOX9KUjSKr0TA==","anonymous"),await resolveScript(`https://unpkg.com/leaflet@${e}/dist/leaflet.js`,"sha512-BwHfrr4c9kmRkLw6iXFdzcdWV/PGkVgiIyIWLLlTSXzWQzxuSg4DiQUCpauz/EWjgk5TYQqX/kvn9pG1NpYfqg==","anonymous"),await resolveScript("https://unpkg.com/leaflet.markercluster@1.5.1/dist/leaflet.markercluster.js","sha512-+Zr0llcuE/Ho6wXRYtlWypMyWSEMxrWJxrYgeAMDRSf1FF46gQ3PAVOVp5RHdxdzikZXuHZ0soHpqRkkPkI3KA==","anonymous")}let map;async function renderMap(e){if(map){map.invalidateSize();return}const t=document.getElementById("map-container"),n=generateThrobber(["map-throbber","throbber-white"]);t&&t.appendChild(n),await loadLeaflet(),map=L.map("map-container",{center:[46.227638,2.213749],zoom:5}),L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{maxZoom:19,attribution:'© OpenStreetMap contributors'}).addTo(map);const s=await fetchGeoJSON(e);if(!s||!s.features)return;const o=L.markerClusterGroup({zoomToBoundsOnClick:!1}),i=[];s.features.map(e=>{const t=L.GeoJSON.coordsToLatLng(e.geometry.coordinates);i.push(t),o.addLayer(L.circleMarker(t).bindPopup(`Image thumbnail
${e.properties.date}`,{maxWidth:"auto",closeButton:!1,className:"thumbnail-popup"}))}),o.on("clusterclick",e=>{map.fitBounds(e.layer.getAllChildMarkers().map(e=>e.getLatLng()))}),i.length?(map.once("zoomend",()=>{t.removeChild(n)}),map.fitBounds(i)):t.removeChild(n),map.addLayer(o)}document.addEventListener("readystatechange",async e=>{if(e.target.readyState!=="complete")return;document.location.hash==="#map"?await renderMap(geoURL):window.addEventListener("popstate",async()=>{document.location.hash==="#map"&&await renderMap(geoURL)})});function resolveScript(e,t,n){return new Promise((s,o)=>{const i=document.createElement("script");i.type="text/javascript",i.src=e,i.async=!0,i.onload=s.bind(null,!0),i.onerror=o.bind(null,!0),t&&(i.integrity=t,i.crossOrigin=n),document.querySelector("head").appendChild(i)})}window.onkeyup=e=>{switch(e.key){case"ArrowLeft":goToPrevious();break;case"ArrowRight":goToNext();break;case"Escape":goBack(e);break}};function goBack(e){const t=document.location.hash;if(t){if(typeof abort=="function"&&typeof aborter!="undefined"){abort(e);return}document.location.hash="",/success$/gim.test(t)&&window.location.reload(!0);return}if(typeof parentPage=="undefined")return;window.location.href=parentPage}function goToPrevious(){if(typeof previousFile=="undefined")return;window.location.href=previousFile}function goToNext(){if(typeof nextFile=="undefined")return;window.location.href=nextFile}function replaceContent(e,t){for(;e.firstChild;)e.removeChild(e.firstChild);t&&e.appendChild(t)}function generateThrobber(e=[]){const t=document.createElement("div");t.classList.add("throbber"),e.forEach(e=>t.classList.add(e));for(let e=1;e<4;e++){const n=document.createElement("div");n.classList.add("throbber-dot",`throbber-dot-${e}`),t.appendChild(n)}return t}let fileInput,uploadList,cancelButton;function eventNoop(e){e.preventDefault(),e.stopPropagation()}document.addEventListener("readystatechange",async e=>{if(e.target.readyState!=="complete")return;const t=document.getElementsByTagName("body")[0];t.addEventListener("dragover",eventNoop),t.addEventListener("dragleave",eventNoop),t.addEventListener("drop",e=>{eventNoop(e),window.location.hash="#upload-modal",fileInput&&(fileInput.files=e.dataTransfer.files,fileInput.dispatchEvent(new Event("change")))})});function bufferToHex(e){return Array.prototype.map.call(new Uint8Array(e),e=>`00${e.toString(16)}`.slice(-2)).join("")}async function sha(e){const t=await crypto.subtle.digest("SHA-256",new TextEncoder("utf-8").encode(e));return bufferToHex(t)}async function fileMessageId(e){const t=await sha(JSON.stringify({name:e.name,size:e.size,type:e.type,lastModified:e.lastModified}));return`upload-file-${t}`}function humanFileSize(e){return e<1024?e+"bytes":e<1048576?(e/1024).toFixed(0)+" KB":(e/1048576).toFixed(0)+" MB"}async function addUploadItem(e,t){const c=await fileMessageId(t),n=document.createElement("div");n.id=c,n.classList.add("flex","flex-center","margin");const o=document.createElement("div");o.classList.add("upload-item"),n.appendChild(o);const s=document.createElement("input");s.id=`${c}-filename`,s.classList.add("upload-name","full"),s.type="text",s.value=t.name,o.appendChild(s);const i=document.createElement("div");i.classList.add("full","flex","flex-center");const r=document.createElement("em");r.innerHTML=humanFileSize(t.size),r.style.width="8rem",i.appendChild(r);const a=document.createElement("progress");a.classList.add("flex-grow","margin-left"),a.max=100,a.value=0,i.appendChild(a),o.appendChild(i);const l=document.createElement("span");l.classList.add("upload-status"),n.appendChild(l),e.appendChild(n)}function getFiles(e){return[].filter.call(e.target,e=>e.nodeName.toLowerCase()==="input").reduce((e,t)=>(t.type==="file"?e.files=t.files:e[t.name]=t.value,e),{})}function getFilename(e,t){const n=document.getElementById(`${e}-filename`);return n&&n.value?n.value:t.name}function clearUploadStatus(e){if(!e)return;const t=e.querySelector(".upload-status");if(!t)return;t.classList.remove("danger"),t.classList.remove("success")}async function setUploadStatus(e,t,n,s){if(!e)return;const o=e.querySelector(".upload-status");if(!o)return;o.innerHTML=t,o.classList.add(n),s&&(o.title=s)}let uploadFile,aborter;const chunkSize=1024*1024;let currentUpload={};async function uploadFileByChunks(e,t,n,s){let i;if(e&&(i=e.querySelector("progress"),clearUploadStatus(e)),s.name!==currentUpload.filename){currentUpload.filename=s.name,currentUpload.chunks=[];for(let e=0;e=400)return Promise.reject(await a.text());currentUpload.chunks[e].done=!0,i&&(i.value=chunkSize*(e+1)/s.size*100)}const o=new FormData;o.append("method",t),o.append("filename",n),o.append("size",s.size);const a=await fetch("",{method:"POST",credentials:"same-origin",headers:{"X-Chunk-Upload":!0,Accept:"text/plain"},body:o}),r=await a.text();return a.status>=400?Promise.reject(r):(currentUpload={},Promise.resolve(r))}async function uploadFileByXHR(e,t,n,s){let o;e&&(o=e.querySelector("progress"),clearUploadStatus(e));const i=new FormData;return i.append("method",t),i.append("filename",n),i.append("size",s.size),i.append("file",s),new Promise((e,t)=>{let n=new XMLHttpRequest;aborter=n,o&&n.upload.addEventListener("progress",e=>o.value=parseInt(e.loaded/e.total*100,10),!1),n.addEventListener("readystatechange",s=>{if(n.readyState===XMLHttpRequest.UNSENT){t(new Error("request aborted")),n=void 0;return}if(n.readyState!==XMLHttpRequest.DONE)return;n.status>=200&&n.status<400?(o&&(o.value=100),e(n.responseText),n=void 0):(t(s),n=void 0)},!1),n.open("POST","",!0),n.setRequestHeader("Accept","text/plain"),n.send(i)})}function sliceFileList(e,t){const n=document.getElementById(e),s=new DataTransfer;for(;t{if(e.target.readyState!=="complete")return;if(typeof chunkUpload!="undefined"&&chunkUpload?uploadFile=uploadFileByChunks:uploadFile=uploadFileByXHR,fileInput=document.getElementById("file"),uploadList=document.getElementById("upload-list"),cancelButton=document.getElementById("upload-cancel"),fileInput){fileInput.classList.add("opacity"),fileInput.multiple=!0,fileInput.addEventListener("change",()=>{window.location.hash="#upload-modal",replaceContent(uploadList);for(const e of fileInput.files)addUploadItem(uploadList,e)});const e=document.getElementById("upload-button-link");e&&e.addEventListener("click",e=>{eventNoop(e),fileInput.click()})}const t=document.getElementById("file-label");t&&(t.classList.remove("hidden"),t.innerHTML="Choose files..."),uploadList&&uploadList.classList.remove("hidden"),cancelButton&&cancelButton.addEventListener("click",goBack);const n=document.getElementById("upload-form");n&&n.addEventListener("submit",upload)}),document.addEventListener("readystatechange",e=>{if(e.target.readyState!=="complete")return;const t=document.getElementById("webhook-url-label");if(!t)return;const n=document.getElementById("webhook-url"),s=document.getElementById("telegram-chat-id");document.getElementById("webhook-kind-raw").addEventListener("change",e=>{e.target.value==="raw"&&(n.placeholder="https://website.com/fibr",t.innerHTML="URL",s.classList.add("hidden"))}),document.getElementById("webhook-kind-discord").addEventListener("change",e=>{e.target.value==="discord"&&(n.placeholder="https://discord.com/api/webhooks/...",t.innerHTML="URL",s.classList.add("hidden"))}),document.getElementById("webhook-kind-slack").addEventListener("change",e=>{e.target.value==="slack"&&(n.placeholder="https://hooks.slack.com/services/...",t.innerHTML="URL",s.classList.add("hidden"))}),document.getElementById("webhook-kind-telegram").addEventListener("change",e=>{e.target.value==="telegram"&&(t.innerHTML="Token",n.placeholder="Bot token",s.classList.remove("hidden"))})}) \ No newline at end of file diff --git a/cmd/fibr/static/scripts/map.js b/cmd/fibr/static/scripts/map.js index 5c1ca523..ad225f87 100644 --- a/cmd/fibr/static/scripts/map.js +++ b/cmd/fibr/static/scripts/map.js @@ -1,8 +1,8 @@ async function fetchGeoJSON(geoURL) { - const response = await fetch(geoURL, { credentials: 'same-origin' }); + const response = await fetch(geoURL, { credentials: "same-origin" }); if (response.status >= 400) { - throw new Error('unable to load geojson'); + throw new Error("unable to load geojson"); } if (response.status === 204) { @@ -14,8 +14,8 @@ async function fetchGeoJSON(geoURL) { async function addStyle(src, integrity, crossorigin) { return new Promise((resolve) => { - const style = document.createElement('link'); - style.rel = 'stylesheet'; + const style = document.createElement("link"); + style.rel = "stylesheet"; style.href = src; style.onload = resolve; @@ -24,32 +24,32 @@ async function addStyle(src, integrity, crossorigin) { style.crossOrigin = crossorigin; } - document.querySelector('head').appendChild(style); + document.querySelector("head").appendChild(style); }); } async function loadLeaflet() { - const leafletVersion = '1.9.4'; + const leafletVersion = "1.9.4"; await addStyle( `https://unpkg.com/leaflet@${leafletVersion}/dist/leaflet.css`, - 'sha512-Zcn6bjR/8RZbLEpLIeOwNtzREBAJnUKESxces60Mpoj+2okopSAcSUIUOseddDm0cxnGQzxIR7vJgsLZbdLE3w==', - 'anonymous', + "sha512-Zcn6bjR/8RZbLEpLIeOwNtzREBAJnUKESxces60Mpoj+2okopSAcSUIUOseddDm0cxnGQzxIR7vJgsLZbdLE3w==", + "anonymous", ); await addStyle( - 'https://unpkg.com/leaflet.markercluster@1.5.1/dist/MarkerCluster.Default.css', - 'sha512-6ZCLMiYwTeli2rVh3XAPxy3YoR5fVxGdH/pz+KMCzRY2M65Emgkw00Yqmhh8qLGeYQ3LbVZGdmOX9KUjSKr0TA==', - 'anonymous', + "https://unpkg.com/leaflet.markercluster@1.5.1/dist/MarkerCluster.Default.css", + "sha512-6ZCLMiYwTeli2rVh3XAPxy3YoR5fVxGdH/pz+KMCzRY2M65Emgkw00Yqmhh8qLGeYQ3LbVZGdmOX9KUjSKr0TA==", + "anonymous", ); await resolveScript( `https://unpkg.com/leaflet@${leafletVersion}/dist/leaflet.js`, - 'sha512-BwHfrr4c9kmRkLw6iXFdzcdWV/PGkVgiIyIWLLlTSXzWQzxuSg4DiQUCpauz/EWjgk5TYQqX/kvn9pG1NpYfqg==', - 'anonymous', + "sha512-BwHfrr4c9kmRkLw6iXFdzcdWV/PGkVgiIyIWLLlTSXzWQzxuSg4DiQUCpauz/EWjgk5TYQqX/kvn9pG1NpYfqg==", + "anonymous", ); await resolveScript( - 'https://unpkg.com/leaflet.markercluster@1.5.1/dist/leaflet.markercluster.js', - 'sha512-+Zr0llcuE/Ho6wXRYtlWypMyWSEMxrWJxrYgeAMDRSf1FF46gQ3PAVOVp5RHdxdzikZXuHZ0soHpqRkkPkI3KA==', - 'anonymous', + "https://unpkg.com/leaflet.markercluster@1.5.1/dist/leaflet.markercluster.js", + "sha512-+Zr0llcuE/Ho6wXRYtlWypMyWSEMxrWJxrYgeAMDRSf1FF46gQ3PAVOVp5RHdxdzikZXuHZ0soHpqRkkPkI3KA==", + "anonymous", ); } @@ -60,8 +60,8 @@ async function renderMap(geoURL) { return; } - const container = document.getElementById('map-container'); - const throbber = generateThrobber(['map-throbber', 'throbber-white']); + const container = document.getElementById("map-container"); + const throbber = generateThrobber(["map-throbber", "throbber-white"]); if (container) { container.appendChild(throbber); } @@ -69,13 +69,13 @@ async function renderMap(geoURL) { await loadLeaflet(); // create Leaflet map - map = L.map('map-container', { + map = L.map("map-container", { center: [46.227638, 2.213749], // France 🇫🇷 zoom: 5, }); // add the OpenStreetMap tiles - L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { maxZoom: 19, attribution: '© OpenStreetMap contributors', @@ -99,21 +99,21 @@ async function renderMap(geoURL) { L.circleMarker(coord).bindPopup( `Image thumbnail
${f.properties.date}`, { - maxWidth: 'auto', + maxWidth: "auto", closeButton: false, - className: 'thumbnail-popup', + className: "thumbnail-popup", }, ), ); }); - markers.on('clusterclick', (a) => { + markers.on("clusterclick", (a) => { map.fitBounds(a.layer.getAllChildMarkers().map((m) => m.getLatLng())); }); // fit bounds of map if (bounds.length) { - map.once('zoomend', () => { + map.once("zoomend", () => { container.removeChild(throbber); }); map.fitBounds(bounds); @@ -124,16 +124,16 @@ async function renderMap(geoURL) { map.addLayer(markers); } -document.addEventListener('readystatechange', async (event) => { - if (event.target.readyState !== 'complete') { +document.addEventListener("readystatechange", async (event) => { + if (event.target.readyState !== "complete") { return; } - if (document.location.hash === '#map') { + if (document.location.hash === "#map") { await renderMap(geoURL); } else { - window.addEventListener('popstate', async () => { - if (document.location.hash === '#map') { + window.addEventListener("popstate", async () => { + if (document.location.hash === "#map") { await renderMap(geoURL); } }); diff --git a/cmd/fibr/static/scripts/navigation.js b/cmd/fibr/static/scripts/navigation.js index 9492f966..051bab77 100644 --- a/cmd/fibr/static/scripts/navigation.js +++ b/cmd/fibr/static/scripts/navigation.js @@ -7,8 +7,8 @@ */ function resolveScript(src, integrity, crossorigin) { return new Promise((resolve, reject) => { - const script = document.createElement('script'); - script.type = 'text/javascript'; + const script = document.createElement("script"); + script.type = "text/javascript"; script.src = src; script.async = true; script.onload = resolve.bind(null, true); @@ -19,7 +19,7 @@ function resolveScript(src, integrity, crossorigin) { script.crossOrigin = crossorigin; } - document.querySelector('head').appendChild(script); + document.querySelector("head").appendChild(script); }); } @@ -28,15 +28,15 @@ function resolveScript(src, integrity, crossorigin) { */ window.onkeyup = (e) => { switch (e.key) { - case 'ArrowLeft': + case "ArrowLeft": goToPrevious(); break; - case 'ArrowRight': + case "ArrowRight": goToNext(); break; - case 'Escape': + case "Escape": goBack(e); break; } @@ -46,12 +46,12 @@ function goBack(e) { const previousHash = document.location.hash; if (previousHash) { - if (typeof abort === 'function' && typeof aborter !== 'undefined') { + if (typeof abort === "function" && typeof aborter !== "undefined") { abort(e); return; } - document.location.hash = ''; + document.location.hash = ""; if (/success$/gim.test(previousHash)) { window.location.reload(true); @@ -60,7 +60,7 @@ function goBack(e) { return; } - if (typeof parentPage === 'undefined') { + if (typeof parentPage === "undefined") { return; } @@ -71,7 +71,7 @@ function goBack(e) { * Go to the previous item. */ function goToPrevious() { - if (typeof previousFile === 'undefined') { + if (typeof previousFile === "undefined") { return; } @@ -82,7 +82,7 @@ function goToPrevious() { * Go to the next item. */ function goToNext() { - if (typeof nextFile === 'undefined') { + if (typeof nextFile === "undefined") { return; } diff --git a/cmd/fibr/static/scripts/throbber.js b/cmd/fibr/static/scripts/throbber.js index b2d38ed0..dc3cba11 100644 --- a/cmd/fibr/static/scripts/throbber.js +++ b/cmd/fibr/static/scripts/throbber.js @@ -3,13 +3,13 @@ * @return {Element} */ function generateThrobber(classNames = []) { - const wrapper = document.createElement('div'); - wrapper.classList.add('throbber'); + const wrapper = document.createElement("div"); + wrapper.classList.add("throbber"); classNames.forEach((className) => wrapper.classList.add(className)); for (let i = 1; i < 4; i++) { - const dot = document.createElement('div'); - dot.classList.add('throbber-dot', `throbber-dot-${i}`); + const dot = document.createElement("div"); + dot.classList.add("throbber-dot", `throbber-dot-${i}`); wrapper.appendChild(dot); } diff --git a/cmd/fibr/static/scripts/upload.js b/cmd/fibr/static/scripts/upload.js index 031aee5f..b73dca70 100644 --- a/cmd/fibr/static/scripts/upload.js +++ b/cmd/fibr/static/scripts/upload.js @@ -11,22 +11,22 @@ function eventNoop(e) { e.stopPropagation(); } -document.addEventListener('readystatechange', async (event) => { - if (event.target.readyState !== 'complete') { +document.addEventListener("readystatechange", async (event) => { + if (event.target.readyState !== "complete") { return; } - const dropZone = document.getElementsByTagName('body')[0]; + const dropZone = document.getElementsByTagName("body")[0]; - dropZone.addEventListener('dragover', eventNoop); - dropZone.addEventListener('dragleave', eventNoop); - dropZone.addEventListener('drop', (e) => { + dropZone.addEventListener("dragover", eventNoop); + dropZone.addEventListener("dragleave", eventNoop); + dropZone.addEventListener("drop", (e) => { eventNoop(e); - window.location.hash = '#upload-modal'; + window.location.hash = "#upload-modal"; if (fileInput) { fileInput.files = e.dataTransfer.files; - fileInput.dispatchEvent(new Event('change')); + fileInput.dispatchEvent(new Event("change")); } }); }); @@ -39,7 +39,7 @@ document.addEventListener('readystatechange', async (event) => { function bufferToHex(buffer) { return Array.prototype.map .call(new Uint8Array(buffer), (x) => `00${x.toString(16)}`.slice(-2)) - .join(''); + .join(""); } /** @@ -49,8 +49,8 @@ function bufferToHex(buffer) { */ async function sha(data) { const buffer = await crypto.subtle.digest( - 'SHA-256', - new TextEncoder('utf-8').encode(data), + "SHA-256", + new TextEncoder("utf-8").encode(data), ); return bufferToHex(buffer); } @@ -79,14 +79,14 @@ async function fileMessageId(file) { */ function humanFileSize(number) { if (number < 1024) { - return number + 'bytes'; + return number + "bytes"; } if (number < 1048576) { - return (number / 1024).toFixed(0) + ' KB'; + return (number / 1024).toFixed(0) + " KB"; } - return (number / 1048576).toFixed(0) + ' MB'; + return (number / 1048576).toFixed(0) + " MB"; } /** @@ -97,39 +97,39 @@ function humanFileSize(number) { async function addUploadItem(container, file) { const messageId = await fileMessageId(file); - const item = document.createElement('div'); + const item = document.createElement("div"); item.id = messageId; - item.classList.add('flex', 'flex-center', 'margin'); + item.classList.add("flex", "flex-center", "margin"); - const itemWrapper = document.createElement('div'); - itemWrapper.classList.add('upload-item'); + const itemWrapper = document.createElement("div"); + itemWrapper.classList.add("upload-item"); item.appendChild(itemWrapper); - const filename = document.createElement('input'); + const filename = document.createElement("input"); filename.id = `${messageId}-filename`; - filename.classList.add('upload-name', 'full'); - filename.type = 'text'; + filename.classList.add("upload-name", "full"); + filename.type = "text"; filename.value = file.name; itemWrapper.appendChild(filename); - const progressContainer = document.createElement('div'); - progressContainer.classList.add('full', 'flex', 'flex-center'); + const progressContainer = document.createElement("div"); + progressContainer.classList.add("full", "flex", "flex-center"); - const size = document.createElement('em'); + const size = document.createElement("em"); size.innerHTML = humanFileSize(file.size); - size.style.width = '8rem'; + size.style.width = "8rem"; progressContainer.appendChild(size); - const progress = document.createElement('progress'); - progress.classList.add('flex-grow', 'margin-left'); + const progress = document.createElement("progress"); + progress.classList.add("flex-grow", "margin-left"); progress.max = 100; progress.value = 0; progressContainer.appendChild(progress); itemWrapper.appendChild(progressContainer); - const status = document.createElement('span'); - status.classList.add('upload-status'); + const status = document.createElement("span"); + status.classList.add("upload-status"); item.appendChild(status); container.appendChild(item); @@ -140,9 +140,9 @@ async function addUploadItem(container, file) { */ function getFiles(event) { return [].filter - .call(event.target, (e) => e.nodeName.toLowerCase() === 'input') + .call(event.target, (e) => e.nodeName.toLowerCase() === "input") .reduce((acc, cur) => { - if (cur.type === 'file') { + if (cur.type === "file") { acc.files = cur.files; } else { acc[cur.name] = cur.value; @@ -175,13 +175,13 @@ function clearUploadStatus(container) { return; } - const statusContainer = container.querySelector('.upload-status'); + const statusContainer = container.querySelector(".upload-status"); if (!statusContainer) { return; } - statusContainer.classList.remove('danger'); - statusContainer.classList.remove('success'); + statusContainer.classList.remove("danger"); + statusContainer.classList.remove("success"); } /** @@ -196,7 +196,7 @@ async function setUploadStatus(container, content, style, title) { return; } - const statusContainer = container.querySelector('.upload-status'); + const statusContainer = container.querySelector(".upload-status"); if (!statusContainer) { return; } @@ -226,7 +226,7 @@ let currentUpload = {}; async function uploadFileByChunks(container, method, filename, file) { let progress; if (container) { - progress = container.querySelector('progress'); + progress = container.querySelector("progress"); clearUploadStatus(container); } @@ -247,23 +247,23 @@ async function uploadFileByChunks(container, method, filename, file) { continue; } - if (typeof AbortController !== 'undefined') { + if (typeof AbortController !== "undefined") { aborter = new AbortController(); } const formData = new FormData(); - formData.append('method', method); - formData.append('filename', filename); - formData.append('file', currentUpload.chunks[i].content); + formData.append("method", method); + formData.append("filename", filename); + formData.append("file", currentUpload.chunks[i].content); - const response = await fetch('', { - method: 'POST', - credentials: 'same-origin', + const response = await fetch("", { + method: "POST", + credentials: "same-origin", signal: aborter.signal, headers: { - 'X-Chunk-Upload': true, - 'X-Chunk-Number': i + 1, - Accept: 'text/plain', + "X-Chunk-Upload": true, + "X-Chunk-Number": i + 1, + Accept: "text/plain", }, body: formData, }); @@ -279,16 +279,16 @@ async function uploadFileByChunks(container, method, filename, file) { } const formData = new FormData(); - formData.append('method', method); - formData.append('filename', filename); - formData.append('size', file.size); + formData.append("method", method); + formData.append("filename", filename); + formData.append("size", file.size); - const response = await fetch('', { - method: 'POST', - credentials: 'same-origin', + const response = await fetch("", { + method: "POST", + credentials: "same-origin", headers: { - 'X-Chunk-Upload': true, - Accept: 'text/plain', + "X-Chunk-Upload": true, + Accept: "text/plain", }, body: formData, }); @@ -313,15 +313,15 @@ async function uploadFileByChunks(container, method, filename, file) { async function uploadFileByXHR(container, method, filename, file) { let progress; if (container) { - progress = container.querySelector('progress'); + progress = container.querySelector("progress"); clearUploadStatus(container); } const formData = new FormData(); - formData.append('method', method); - formData.append('filename', filename); - formData.append('size', file.size); - formData.append('file', file); + formData.append("method", method); + formData.append("filename", filename); + formData.append("size", file.size); + formData.append("file", file); return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); @@ -329,17 +329,17 @@ async function uploadFileByXHR(container, method, filename, file) { if (progress) { xhr.upload.addEventListener( - 'progress', + "progress", (e) => (progress.value = parseInt((e.loaded / e.total) * 100, 10)), false, ); } xhr.addEventListener( - 'readystatechange', + "readystatechange", (e) => { if (xhr.readyState === XMLHttpRequest.UNSENT) { - reject(new Error('request aborted')); + reject(new Error("request aborted")); xhr = undefined; return; @@ -364,8 +364,8 @@ async function uploadFileByXHR(container, method, filename, file) { false, ); - xhr.open('POST', '', true); - xhr.setRequestHeader('Accept', 'text/plain'); + xhr.open("POST", "", true); + xhr.setRequestHeader("Accept", "text/plain"); xhr.send(formData); }); } @@ -393,14 +393,14 @@ function sliceFileList(name, index) { async function upload(event) { event.preventDefault(); - const uploadButton = document.getElementById('upload-button'); + const uploadButton = document.getElementById("upload-button"); if (uploadButton) { uploadButton.disabled = true; - replaceContent(uploadButton, generateThrobber(['throbber-white'])); + replaceContent(uploadButton, generateThrobber(["throbber-white"])); } if (cancelButton) { - cancelButton.innerHTML = 'Cancel'; + cancelButton.innerHTML = "Cancel"; } const values = getFiles(event); @@ -416,14 +416,14 @@ async function upload(event) { const filename = getFilename(messageId, file); await uploadFile(container, values.method, filename, file); - await setUploadStatus(container, '✓', 'success'); + await setUploadStatus(container, "✓", "success"); } catch (err) { - sliceFileList('file', i); + sliceFileList("file", i); if (uploadButton) { uploadButton.disabled = false; - uploadButton.innerHTML = 'Retry'; + uploadButton.innerHTML = "Retry"; } - await setUploadStatus(container, 'X', 'danger', err); + await setUploadStatus(container, "X", "danger", err); success = false; console.error(err); @@ -435,9 +435,9 @@ async function upload(event) { } if (success) { - document.location.hash = '#upload-success'; + document.location.hash = "#upload-success"; } else if (cancelButton) { - cancelButton.innerHTML = 'Close'; + cancelButton.innerHTML = "Close"; } return false; @@ -454,36 +454,34 @@ function abort(e) { aborter = undefined; if (cancelButton) { - cancelButton.innerHTML = 'Close'; + cancelButton.innerHTML = "Close"; } } return false; } -document.addEventListener('readystatechange', async (event) => { - if (event.target.readyState !== 'complete') { +document.addEventListener("readystatechange", async (event) => { + if (event.target.readyState !== "complete") { return; } - if (typeof chunkUpload !== 'undefined') { - if (chunkUpload) { - uploadFile = uploadFileByChunks; - } else { - uploadFile = uploadFileByXHR; - } + if (typeof chunkUpload !== "undefined" && chunkUpload) { + uploadFile = uploadFileByChunks; + } else { + uploadFile = uploadFileByXHR; } - fileInput = document.getElementById('file'); - uploadList = document.getElementById('upload-list'); - cancelButton = document.getElementById('upload-cancel'); + fileInput = document.getElementById("file"); + uploadList = document.getElementById("upload-list"); + cancelButton = document.getElementById("upload-cancel"); if (fileInput) { - fileInput.classList.add('opacity'); + fileInput.classList.add("opacity"); fileInput.multiple = true; - fileInput.addEventListener('change', () => { - window.location.hash = '#upload-modal'; + fileInput.addEventListener("change", () => { + window.location.hash = "#upload-modal"; replaceContent(uploadList); @@ -492,9 +490,9 @@ document.addEventListener('readystatechange', async (event) => { } }); - const uploadButtonLink = document.getElementById('upload-button-link'); + const uploadButtonLink = document.getElementById("upload-button-link"); if (uploadButtonLink) { - uploadButtonLink.addEventListener('click', (e) => { + uploadButtonLink.addEventListener("click", (e) => { eventNoop(e); fileInput.click(); @@ -502,22 +500,22 @@ document.addEventListener('readystatechange', async (event) => { } } - const fileInputLabel = document.getElementById('file-label'); + const fileInputLabel = document.getElementById("file-label"); if (fileInputLabel) { - fileInputLabel.classList.remove('hidden'); - fileInputLabel.innerHTML = 'Choose files...'; + fileInputLabel.classList.remove("hidden"); + fileInputLabel.innerHTML = "Choose files..."; } if (uploadList) { - uploadList.classList.remove('hidden'); + uploadList.classList.remove("hidden"); } if (cancelButton) { - cancelButton.addEventListener('click', goBack); + cancelButton.addEventListener("click", goBack); } - const form = document.getElementById('upload-form'); + const form = document.getElementById("upload-form"); if (form) { - form.addEventListener('submit', upload); + form.addEventListener("submit", upload); } }); diff --git a/cmd/fibr/static/scripts/webhook.js b/cmd/fibr/static/scripts/webhook.js index a03294ba..62a4e801 100644 --- a/cmd/fibr/static/scripts/webhook.js +++ b/cmd/fibr/static/scripts/webhook.js @@ -1,53 +1,53 @@ -document.addEventListener('readystatechange', (event) => { - if (event.target.readyState !== 'complete') { +document.addEventListener("readystatechange", (event) => { + if (event.target.readyState !== "complete") { return; } - const urlLabel = document.getElementById('webhook-url-label'); + const urlLabel = document.getElementById("webhook-url-label"); if (!urlLabel) { return; } - const urlWebhook = document.getElementById('webhook-url'); - const telegramChatID = document.getElementById('telegram-chat-id'); + const urlWebhook = document.getElementById("webhook-url"); + const telegramChatID = document.getElementById("telegram-chat-id"); document - .getElementById('webhook-kind-raw') - .addEventListener('change', (e) => { - if (e.target.value === 'raw') { - urlWebhook.placeholder = 'https://website.com/fibr'; - urlLabel.innerHTML = 'URL'; - telegramChatID.classList.add('hidden'); + .getElementById("webhook-kind-raw") + .addEventListener("change", (e) => { + if (e.target.value === "raw") { + urlWebhook.placeholder = "https://website.com/fibr"; + urlLabel.innerHTML = "URL"; + telegramChatID.classList.add("hidden"); } }); document - .getElementById('webhook-kind-discord') - .addEventListener('change', (e) => { - if (e.target.value === 'discord') { - urlWebhook.placeholder = 'https://discord.com/api/webhooks/...'; - urlLabel.innerHTML = 'URL'; - telegramChatID.classList.add('hidden'); + .getElementById("webhook-kind-discord") + .addEventListener("change", (e) => { + if (e.target.value === "discord") { + urlWebhook.placeholder = "https://discord.com/api/webhooks/..."; + urlLabel.innerHTML = "URL"; + telegramChatID.classList.add("hidden"); } }); document - .getElementById('webhook-kind-slack') - .addEventListener('change', (e) => { - if (e.target.value === 'slack') { - urlWebhook.placeholder = 'https://hooks.slack.com/services/...'; - urlLabel.innerHTML = 'URL'; - telegramChatID.classList.add('hidden'); + .getElementById("webhook-kind-slack") + .addEventListener("change", (e) => { + if (e.target.value === "slack") { + urlWebhook.placeholder = "https://hooks.slack.com/services/..."; + urlLabel.innerHTML = "URL"; + telegramChatID.classList.add("hidden"); } }); document - .getElementById('webhook-kind-telegram') - .addEventListener('change', (e) => { - if (e.target.value === 'telegram') { - urlLabel.innerHTML = 'Token'; - urlWebhook.placeholder = 'Bot token'; - telegramChatID.classList.remove('hidden'); + .getElementById("webhook-kind-telegram") + .addEventListener("change", (e) => { + if (e.target.value === "telegram") { + urlLabel.innerHTML = "Token"; + urlWebhook.placeholder = "Bot token"; + telegramChatID.classList.remove("hidden"); } }); }); diff --git a/go.mod b/go.mod index 3baf3b92..8e2f134c 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/ViBiOh/ChatPotte v0.3.1 - github.com/ViBiOh/absto v1.6.1 + github.com/ViBiOh/absto v1.7.0 github.com/ViBiOh/auth/v2 v2.15.2 github.com/ViBiOh/exas v0.7.1 github.com/ViBiOh/flags v1.3.1 @@ -37,7 +37,7 @@ require ( github.com/klauspost/compress v1.16.7 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/minio-go/v7 v7.0.61 // indirect + github.com/minio/minio-go/v7 v7.0.62 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/go.sum b/go.sum index d1c0b0f0..f546e590 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/ViBiOh/ChatPotte v0.3.1 h1:F+FFEtS59sI65DdQ04d+7dCE4OmsTx683RRW1AX8lkE= github.com/ViBiOh/ChatPotte v0.3.1/go.mod h1:8qXlxb6BW3TYb3P8h4lndGthm9qheEfgw3QUZ/OXjxQ= -github.com/ViBiOh/absto v1.6.1 h1:Di2/aXhwBgZjNgBn1N1M4ukaaI//jxsNrpohrrUcv8I= -github.com/ViBiOh/absto v1.6.1/go.mod h1:EeeJl8HEpA9eEidC7TVV1SI4uUkx7XLoX0oxMuFuQgs= +github.com/ViBiOh/absto v1.7.0 h1:u60N+cgUe9PWDdeX6ixqX3jQISqeip1Q+ZhzFqaGrWU= +github.com/ViBiOh/absto v1.7.0/go.mod h1:0F1g0DknHQZvDP+bEF4B9qBhaln/8PcW5YZ1QYdimRM= github.com/ViBiOh/auth/v2 v2.15.2 h1:VA7IvD/wuZaVPo0BNftp8wEBS+2NmF+3+xmdM3X01Fw= github.com/ViBiOh/auth/v2 v2.15.2/go.mod h1:NdDMEVvcQ1Eptw4mPz/iyQt+RiyrCnxDce9nafr28Nk= github.com/ViBiOh/exas v0.7.1 h1:nzh6E1668OFRgoTIJZJa1RybCW64Gd918qi0Z+0Q4WA= @@ -66,8 +66,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.61 h1:87c+x8J3jxQ5VUGimV9oHdpjsAvy3fhneEBKuoKEVUI= -github.com/minio/minio-go/v7 v7.0.61/go.mod h1:BTu8FcrEw+HidY0zd/0eny43QnVNkXRPXrLXFuQBHXg= +github.com/minio/minio-go/v7 v7.0.62 h1:qNYsFZHEzl+NfH8UxW4jpmlKav1qUAgfY30YNRneVhc= +github.com/minio/minio-go/v7 v7.0.62/go.mod h1:Q6X7Qjb7WMhvG65qKf4gUgA5XaiSox74kR1uAEjxRS4= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/pkg/mocks/storage.go b/pkg/mocks/storage.go index 42ad1b90..deee9f18 100644 --- a/pkg/mocks/storage.go +++ b/pkg/mocks/storage.go @@ -110,10 +110,10 @@ func (mr *StorageMockRecorder) Name() *gomock.Call { } // OpenFile mocks base method. -func (m *Storage) OpenFile(arg0 context.Context, arg1 string, arg2 int, arg3 fs.FileMode) (*model.FileItem, error) { +func (m *Storage) OpenFile(arg0 context.Context, arg1 string, arg2 int, arg3 fs.FileMode) (model.File, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "OpenFile", arg0, arg1, arg2, arg3) - ret0, _ := ret[0].(*model.FileItem) + ret0, _ := ret[0].(model.File) ret1, _ := ret[1].(error) return ret0, ret1 }