Add free transfer limit to filesystem
This commit is contained in:
115
svelte/src/util/StatsSocket.js
Normal file
115
svelte/src/util/StatsSocket.js
Normal file
@@ -0,0 +1,115 @@
|
||||
import { readable } from "svelte/store";
|
||||
|
||||
let results = {
|
||||
connected: false,
|
||||
file_stats_init: false,
|
||||
file_stats: {
|
||||
views: 0,
|
||||
downloads: 0,
|
||||
bandwidth: 0,
|
||||
bandwidth_paid: 0,
|
||||
},
|
||||
limits_init: false,
|
||||
limits: {
|
||||
download_limit: 0,
|
||||
download_limit_used: 0,
|
||||
transfer_limit: 0,
|
||||
transfer_limit_used: 0,
|
||||
},
|
||||
}
|
||||
|
||||
export const stats = readable(
|
||||
results,
|
||||
(set) => {
|
||||
start_sock(set)
|
||||
return () => stop_sock(set)
|
||||
},
|
||||
);
|
||||
|
||||
let socket = null
|
||||
const start_sock = (set_func) => {
|
||||
if (socket !== null) {
|
||||
return
|
||||
}
|
||||
|
||||
console.log("initializing stats socket")
|
||||
socket = new WebSocket(location.origin.replace(/^http/, 'ws') + "/api/file_stats")
|
||||
|
||||
socket.onopen = () => {
|
||||
results.connected = true
|
||||
set_func(results)
|
||||
|
||||
// Subscribe to the rate limit feed. This will also process any queued
|
||||
// commands built up while the socket was down
|
||||
send_cmd({ type: "limits" })
|
||||
}
|
||||
socket.onmessage = msg => {
|
||||
let j = JSON.parse(msg.data)
|
||||
console.debug("WS update", j)
|
||||
|
||||
if (j.type === "file_stats") {
|
||||
results.file_stats = j.file_stats
|
||||
results.file_stats_init = true
|
||||
set_func(results)
|
||||
} else if (j.type === "limits") {
|
||||
results.limits = j.limits
|
||||
results.limits_init = true
|
||||
set_func(results)
|
||||
} else {
|
||||
console.error("Unknown ws message type", j.type, "data", msg.data)
|
||||
}
|
||||
}
|
||||
socket.onerror = err => {
|
||||
console.error("socket error", err)
|
||||
stop_sock(set_func)
|
||||
window.setTimeout(() => start_sock(set_func), 2000)
|
||||
}
|
||||
socket.onclose = () => {
|
||||
stop_sock(set_func)
|
||||
window.setTimeout(() => start_sock(set_func), 2000)
|
||||
}
|
||||
}
|
||||
|
||||
const stop_sock = (set_func) => {
|
||||
if (socket === null) {
|
||||
return
|
||||
}
|
||||
|
||||
// Prevent error handlers from re-initializing the socket
|
||||
socket.onerror = null
|
||||
socket.onclose = null
|
||||
|
||||
// Close and delete the socket
|
||||
socket.close()
|
||||
socket = null
|
||||
|
||||
// Reset the state
|
||||
results.connected = false
|
||||
results.file_stats_init = false
|
||||
results.limits_init = false
|
||||
set_func(results)
|
||||
}
|
||||
|
||||
export const set_file = file_id => {
|
||||
send_cmd({
|
||||
type: "file_stats",
|
||||
data: { file_id: file_id },
|
||||
})
|
||||
}
|
||||
|
||||
let queued_commands = []
|
||||
const send_cmd = cmd => {
|
||||
if (socket !== null && socket.readyState === WebSocket.OPEN) {
|
||||
|
||||
// First empty the queue
|
||||
while (queued_commands.length !== 0) {
|
||||
socket.send(JSON.stringify(queued_commands.shift()))
|
||||
}
|
||||
|
||||
// Send the requested command
|
||||
socket.send(JSON.stringify(cmd))
|
||||
} else if (cmd !== null) {
|
||||
queued_commands.push(cmd)
|
||||
console.debug("Socket is closed, command", cmd, "added to queue")
|
||||
}
|
||||
}
|
97
svelte/src/util/SwipeNavigate.ts
Normal file
97
svelte/src/util/SwipeNavigate.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
// Dead zone before the swipe action gets detected
|
||||
const swipe_inital_offset = 25
|
||||
// Amount of pixels after which the navigation triggers
|
||||
const swipe_trigger_offset = 75
|
||||
|
||||
export const swipe_nav = (node: HTMLElement, props: { enabled: boolean, prev: boolean, next: boolean }) => {
|
||||
let start_x = 0
|
||||
let start_y = 0
|
||||
let render_offset = 0
|
||||
let enabled = props.enabled === undefined ? true : props.enabled
|
||||
let prev = props.prev === undefined ? true : props.prev
|
||||
let next = props.next === undefined ? true : props.next
|
||||
|
||||
const touchstart = (e: TouchEvent) => {
|
||||
start_x = e.touches[0].clientX
|
||||
start_y = e.touches[0].clientY
|
||||
render_offset = 0
|
||||
}
|
||||
|
||||
const touchmove = (e: TouchEvent) => {
|
||||
const offset_x = e.touches[0].clientX - start_x
|
||||
if (!enabled || (offset_x < 0 && !next) || (offset_x > 0 && !prev)) {
|
||||
return
|
||||
}
|
||||
|
||||
const abs_x = Math.abs(offset_x)
|
||||
const abs_y = Math.abs(e.touches[0].clientY - start_y)
|
||||
const neg = offset_x < 0 ? -1 : 1
|
||||
|
||||
// The cursor must have moved at least 50 pixels and three times as much
|
||||
// on the x axis than the y axis for it to count as a swipe
|
||||
if (abs_x > swipe_inital_offset && abs_y < abs_x / 3) {
|
||||
set_offset((abs_x - swipe_inital_offset) * neg, false)
|
||||
} else {
|
||||
set_offset(0, true)
|
||||
}
|
||||
}
|
||||
|
||||
const touchend = (e: TouchEvent) => {
|
||||
if (!enabled) {
|
||||
return
|
||||
}
|
||||
|
||||
if (render_offset > swipe_trigger_offset) {
|
||||
set_offset(1000, true)
|
||||
node.dispatchEvent(new CustomEvent("prev"))
|
||||
} else if (render_offset < -swipe_trigger_offset) {
|
||||
set_offset(-1000, true)
|
||||
node.dispatchEvent(new CustomEvent("next"))
|
||||
} else {
|
||||
set_offset(0, true)
|
||||
}
|
||||
}
|
||||
|
||||
const set_offset = (off: number, animate: boolean) => {
|
||||
render_offset = off
|
||||
|
||||
if (off === 0) {
|
||||
// Clear the transformation if the offset is zero
|
||||
node.style.transform = ""
|
||||
node.style.transition = ""
|
||||
} else {
|
||||
node.style.transform = "translateX(" + off + "px)"
|
||||
if (animate) {
|
||||
node.style.transition = "transform 400ms"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node.addEventListener("touchstart", touchstart)
|
||||
node.addEventListener("touchmove", touchmove)
|
||||
node.addEventListener("touchend", touchend)
|
||||
|
||||
// Get the child image so we can listen for the loaded event. When the
|
||||
// loaded event fires we clear the transformations so that the image appears
|
||||
// in the original position again
|
||||
for (let i = 0; i < node.childNodes.length; i++) {
|
||||
const child = node.childNodes.item(i)
|
||||
if (child instanceof HTMLImageElement) {
|
||||
child.addEventListener("load", () => set_offset(0, false))
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
update(props: { enabled: boolean, prev: boolean, next: boolean }) {
|
||||
enabled = props.enabled === undefined ? true : props.enabled
|
||||
prev = props.prev === undefined ? true : props.prev
|
||||
next = props.next === undefined ? true : props.next
|
||||
set_offset(0, false)
|
||||
},
|
||||
destroy() {
|
||||
node.removeEventListener("touchstart", touchstart)
|
||||
node.removeEventListener("touchmove", touchmove)
|
||||
node.removeEventListener("touchend", touchend)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user