1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
/* 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
export const toArray = a => Array.prototype.slice.apply(a)
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
}
// Verified is 0/1 when retrieved from SQL, but 'verified' or 'unverified' when retrieved elsewhere
export const isVerified = verified => verified === 1 || verified === '1' || verified === 'verified'
export const verify = verified => isVerified(verified) ? 'verified' : 'unverified'
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, b) => n < a ? a : n < b ? n : b
/* URLs */
export const hashPath = sha256 => {
if (!sha256 || sha256.length < 9) {
throw new Error('Invalid sha256')
}
return [
sha256.slice(0, 3),
sha256.slice(3, 6),
sha256.slice(6, 9),
sha256,
].join('/')
}
export const imageUrl = (verified, sha256, frame, size = 'th') => [
'https://' + process.env.S3_HOST + '/v1/media/keyframes',
isVerified(verified) ? null : 'unverified',
hashPath(sha256),
pad(frame, 6),
size,
'index.jpg'
].filter(s => !!s).join('/')
export const metadataUri = (sha256, tag) => '/metadata/' + sha256 + '/' + tag + '/'
export const keyframeUri = (sha256, frame) => '/metadata/' + sha256 + '/keyframe/' + pad(frame, 6) + '/'
export const preloadImage = opt => {
let { verified, hash, frame, url } = opt
if (hash && frame) {
url = imageUrl(verified, hash, frame, 'md')
}
const image = new Image()
let loaded = false
image.onload = () => {
if (loaded) return
loaded = true
image.onload = null
}
// console.log(img.src)
image.crossOrigin = 'anonymous'
image.src = url
if (image.complete) {
image.onload()
}
}
/* AJAX */
let cachedAuth = null
let token = ''
let username = ''
export const post = (uri, data, credentials) => {
login()
let headers
if (data instanceof FormData) {
headers = {
Accept: 'application/json, application/xml, text/play, text/html, *.*',
}
} else {
headers = {
Accept: 'application/json, application/xml, text/play, text/html, *.*',
'Content-Type': 'application/json; charset=utf-8',
}
data = JSON.stringify(data)
}
let opt = {
method: 'POST',
body: data,
headers,
credentials: 'include',
}
if (credentials) {
headers.Authorization = 'Token ' + token
}
// console.log(headers)
// headers['X-CSRFToken'] = csrftoken
return fetch(uri, opt).then(res => res.json())
}
// api queries
export const login = () => {
if (cachedAuth) return cachedAuth
const isLocal = (window.location.hostname === '0.0.0.0' || window.location.hostname === '127.0.0.1')
try {
const auth = JSON.parse(JSON.parse(localStorage.getItem('persist:root')).auth)
// console.log('auth', auth)
token = auth.token
username = auth.user.username
if (token) {
console.log('logged in', username)
}
cachedAuth = auth
if (!token && !isLocal) {
window.location.href = '/'
}
return auth
} catch (e) {
if (!isLocal) {
window.location.href = '/'
}
return {}
}
}
|