diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2020-09-26 14:56:02 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2020-09-26 14:56:02 +0200 |
| commit | a17b76ac75f506f5da6fe8adf9c36632b60d4226 (patch) | |
| tree | abb0af0c4409b830dea2ef808c146223ee973933 /frontend/util/index.js | |
| parent | 2231a6e1c05b07bb7ec5906716aedec93d02429c (diff) | |
refactor to use app-rooted js imports
Diffstat (limited to 'frontend/util/index.js')
| -rw-r--r-- | frontend/util/index.js | 331 |
1 files changed, 0 insertions, 331 deletions
diff --git a/frontend/util/index.js b/frontend/util/index.js deleted file mode 100644 index 194ecf0..0000000 --- a/frontend/util/index.js +++ /dev/null @@ -1,331 +0,0 @@ -import { api as api_type } from '../types' - -// import { format, formatDistance } from 'date-fns' -import format from 'date-fns/format' -import formatDistance from 'date-fns/formatDistance' - -export const formatDateTime = dateStr => format(new Date(dateStr), 'd MMM yyyy H:mm') -export const formatDate = dateStr => format(new Date(dateStr), 'd MMM yyyy') -export const formatTime = dateStr => format(new Date(dateStr), 'H:mm') -export const formatAge = dateStr => formatDistance(new Date(), new Date(dateStr)) + ' ago.' - -/* Mobile check */ - -export const isiPhone = !!((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) -export const isiPad = !!(navigator.userAgent.match(/iPad/i)) -export const isAndroid = !!(navigator.userAgent.match(/Android/i)) -export const isMobile = isiPhone || isiPad || isAndroid -export const isDesktop = !isMobile - -const htmlClassList = document.body.parentNode.classList -htmlClassList.add(isDesktop ? 'desktop' : 'mobile') - -/* Default image dimensions */ - -export const widths = { - th: 160, - sm: 320, - md: 640, - lg: 1280, -} - -/* Formatting functions */ - -const acronyms = 'id url cc sa fp md5 sha256'.split(' ').map(s => '_' + s) -const acronymsUpperCase = acronyms.map(s => s.toUpperCase()) - -export const formatName = s => { - acronyms.forEach((acronym, i) => s = s.replace(acronym, acronymsUpperCase[i])) - return s.replace(/_/g, ' ') -} - -// Use to pad frame numbers with zeroes -export const pad = (n, m) => { - let s = String(n || 0) - while (s.length < m) { - s = '0' + s - } - return s -} - -export const courtesyS = (n, s) => n + ' ' + (n === 1 ? s : s + 's') - -export const padSeconds = n => n < 10 ? '0' + n : n - -export const timestamp = (n = 0, fps = 25) => { - n /= fps - let s = padSeconds(Math.round(n) % 60) - n = Math.floor(n / 60) - if (n > 60) { - return Math.floor(n / 60) + ':' + padSeconds(n % 60) + ':' + s - } - return (n % 60) + ':' + s -} - -export const percent = n => (n * 100).toFixed(1) + '%' - -export const px = (n, w) => Math.round(n * w) + 'px' - -export const clamp = (n, a=0, b=1) => n < a ? a : n < b ? n : b -export const dist = (x1, y1, x2, y2) => Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) -export const mod = (n, m) => n - (m * Math.floor(n / m)) -export const angle = (x1, y1, x2, y2) => Math.atan2(y2 - y1, x2 - x1) - -/* URLs */ - -export const sha256_tree = (sha256, branch_size=2, tree_depth=2) => { - const tree_size = tree_depth * branch_size - let tree = "" - for (var i = 0; i < tree_size; i += branch_size) { - tree += '/' + sha256.substr(i, branch_size) - } - return tree -} - -export const imageUrl = (sha256, frame, size = 'th') => [ - 'https://' + process.env.S3_HOST + '/v1/media/keyframes', - sha256_tree(sha256), - pad(frame, 6), - size, - 'index.jpg' -].filter(s => !!s).join('/') - -export const uploadUri = ({ sha256, ext }) => '/static/data/uploads' + sha256_tree(sha256) + '/' + sha256 + ext -export const metadataUri = (sha256, tag) => '/metadata/' + sha256 + '/' + tag + '/' -export const keyframeUri = (sha256, frame) => '/metadata/' + sha256 + '/keyframe/' + pad(frame, 6) + '/' - -export const preloadImage = url => ( - new Promise((resolve, reject) => { - const image = new Image() - let loaded = false - image.onload = () => { - if (loaded) return - loaded = true - image.onload = null - image.onerror = null - resolve(image) - } - image.onerror = () => { - if (loaded) return - image.onload = null - image.onerror = null - resolve(image) - } - // console.log(img.src) - // image.crossOrigin = 'anonymous' - image.src = url - if (image.complete) { - image.onload() - } - }) -) - -export const cropImage = (url, crop) => { - return new Promise((resolve, reject) => { - let { x, y, w, h } = crop - const image = new Image() - let loaded = false - x = parseFloat(x) - y = parseFloat(y) - w = parseFloat(w) - h = parseFloat(h) - image.onload = () => { - if (loaded) return - loaded = true - image.onload = null - const canvas = document.createElement('canvas') - const ctx = canvas.getContext('2d') - const width = image.naturalWidth - const height = image.naturalHeight - canvas.width = w * width - canvas.height = h * height - ctx.drawImage( - image, - Math.round(x * width), - Math.round(y * height), - Math.round(w * width), - Math.round(h * height), - 0, 0, canvas.width, canvas.height - ) - resolve(canvas) - } - image.onerror = () => { - console.log('image error') - reject() - } - // console.log(img.src) - image.crossOrigin = 'anonymous' - image.src = url - if (image.complete) { - image.onload() - } - }) -} -export const urlSearchParamsToDict = search => { - const params = new URLSearchParams(search) - const dict = {} - params.forEach((value, key) => { // ??? - dict[key] = value - }) - return dict -} - -/* AJAX */ - -let cachedAuth = null -let token = '' -let username = '' - -export const post = (dispatch, type=api_type, tag, url, data) => { - let headers - if (data instanceof FormData) { - headers = { - Accept: 'application/json', - } - } else if (data) { - headers = { - Accept: 'application/json', - 'Content-Type': 'application/json; charset=utf-8', - } - data = JSON.stringify(data) - } - - dispatch({ - type: type.loading, - tag, - }) - return fetch(url, { - method: 'POST', - body: data, - headers, - }) - .then(res => res.json()) - .then(res => dispatch({ - type: type.loaded, - tag, - data: res, - })) - .catch(err => dispatch({ - type: type.error, - tag, - err, - })) -} - -export const api = (dispatch, type=api_type, tag, url, data) => { - dispatch({ - type: type.loading, - tag, - }) - if (url.indexOf('http') !== 0) { - url = window.location.origin + url - } - url = new URL(url) - if (data) { - url.search = new URLSearchParams(data).toString() - } - return fetch(url, { - method: 'GET', - // mode: 'cors', - }) - .then(res => res.json()) - .then(res => dispatch({ - type: type.loaded, - tag, - data: res, - })) - .catch(err => dispatch({ - type: type.error, - tag, - err, - })) -} - -/* sorting */ - -export const numericSort = { - asc: (a,b) => a[0] - b[0], - desc: (a,b) => b[0] - a[0], -} -export const stringSort = { - asc: (a,b) => a[0].localeCompare(b[0]), - desc: (a,b) => b[0].localeCompare(a[0]), -} -export const orderByFn = (s='name asc') => { - const [field='name', direction='asc'] = s.split(' ') - let mapFn, sortFn - switch (field) { - case 'id': - mapFn = a => [parseInt(a.id) || 0, a] - sortFn = numericSort[direction] - break - case 'epoch': - mapFn = a => [parseInt(a.epoch || a.epochs) || 0, a] - sortFn = numericSort[direction] - break - case 'size': - mapFn = a => [parseInt(a.size) || 0, a] - sortFn = numericSort[direction] - break - case 'date': - mapFn = a => [+new Date(a.date || a.created_at), a] - sortFn = numericSort[direction] - break - case 'updated_at': - mapFn = a => [+new Date(a.updated_at), a] - sortFn = numericSort[direction] - break - case 'priority': - mapFn = a => [parseInt(a.priority) || parseInt(a.id) || 1000, a] - sortFn = numericSort[direction] - case 'name': - default: - mapFn = a => [a.name || "", a] - sortFn = stringSort[direction] - break - } - return { mapFn, sortFn } -} -export const getOrderedIds = (objects, sort, prepend=[]) => { - const { mapFn, sortFn } = orderByFn(sort) - return prepend.concat(objects.map(mapFn).sort(sortFn).map(a => a[1].id)) -} -export const getOrderedIdsFromLookup = (lookup, sort) => { - return getOrderedIds(Object.keys(lookup).map(key => lookup[key]), sort) -} - -/* parallel promises */ - -export const allProgress = (promises, progress_cb) => { - let d = 0 - progress_cb(0, 0, promises.length) - promises.forEach((p) => { - p.then((s) => { - d += 1 - progress_cb(Math.floor((d * 100) / promises.length), d, promises.length) - return s - }) - }) - return Promise.all(promises) -} - -/* Clipboard */ - -export function writeToClipboard(str) { - return new Promise((resolve, reject) => { - let success = false - function listener(e) { - e.clipboardData.setData("text/plain", str) - e.preventDefault() - success = true - } - document.addEventListener("copy", listener) - document.execCommand("copy") - document.removeEventListener("copy", listener) - if (success) { - resolve() - } else { - reject() - } - }) -}
\ No newline at end of file |
