Skip to content

Commit

Permalink
feat: done ui
Browse files Browse the repository at this point in the history
  • Loading branch information
maiquocthinh committed Jun 30, 2023
1 parent 06494c6 commit 9f13e19
Show file tree
Hide file tree
Showing 6 changed files with 422 additions and 6 deletions.
Binary file added src/page/favicon.ico
Binary file not shown.
117 changes: 117 additions & 0 deletions src/page/home.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="./style.css" />
<title>Get Link</title>
</head>
<body>
<div class="container">
<h1>Get Link Terabox</h1>
<div class="form-group">
<label for="input-url">Enter URL:</label>
<input type="text" id="input-url" placeholder="https://terabox.com/s/117NfiRSK_e4ImEEDqQGh_g" />
</div>
<div class="form-group">
<button id="get-link-button">Get Link</button>
</div>
<div class="output">
<div class="tree-view"></div>
</div>
</div>

<script
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
integrity="sha512-fD9DI5bZwQxOi7MhYWnnNPlvXdp/2Pj3XSTRrFs5FQa4mizyGLnJcN6tuvUS6LbmgN1ut+XGSABKvjN0H6Aoow=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script src="./script.js"></script>
<script>
function fetchDownload({ shareid, uk, sign, timestamp, fs_id }) {
return fetch("/api/get-download", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ shareid, uk, sign, timestamp, fs_id }),
}).then(async function (res) {
return await res.json()
})
}

function fetchInfo(shortUrl){
return fetch("/api/get-info?shorturl=" + shortUrl).then(async function (res) {
const body = await res.json()

if (!body.ok) return alert(body.message)

// handle Info
function recursiveList(list) {
return list.map((item) => ({
isDir: item.is_dir != 0,
name: item.filename,
category: item.is_dir != 0 || parseInt(item.category),
size: item.is_dir != 0 || formatStorageSize(parseInt(item.size)),
children:
item.children && item.children.length > 0
? recursiveList(item.children)
: undefined,
downloadAction:
item.is_dir != 0 ||
async function () {
const res = await fetchDownload({
shareid: body.shareid,
uk: body.uk,
sign: body.sign,
timestamp: body.timestamp,
fs_id: item.fs_id,
})

if (!res.ok) return alert(res.message)

window.open(res.downloadLink, '_blank')
},
}))
}

return recursiveList(body.list)
})

}

const getLinkButton = document.getElementById("get-link-button")
const inputUrl = document.getElementById("input-url")
const treeViewElement = document.querySelector(".tree-view")

getLinkButton.addEventListener("click", async function () {
const url = inputUrl.value

if(!url) return alert('Url must not empty!!')

const regex = /\/([A-Za-z0-9_-]+)$/
const match = url.match(regex)
if (match) {
const shortUrl = match[1]

treeViewElement.innerHTML = '<p style="text-align:center;">Loading...</p>'

const d = await fetchInfo(shortUrl)

treeViewElement.innerHTML = ''

TreeView(d, treeViewElement)
} else {
alert("URL not support")
}
})
</script>
</body>
</html>
149 changes: 149 additions & 0 deletions src/page/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
const TreeView = (function () {
function render(data, rootList) {
for (const item of data) {
if (item.isDir) {
// create <li class="folder">
const li = document.createElement("li")
li.className = "folder"
li.setAttribute("opened", "true")

// create <div class="folder-header">
const folderHeaderDiv = document.createElement("div")
folderHeaderDiv.className = "folder-header"
folderHeaderDiv.innerHTML = `<span class="icon-arrow">
<i class="fa-solid fa-caret-right hidden"></i>
<i class="fa-solid fa-caret-down"></i>
</span>
<span class="icon-folder">
<i class="fa-solid fa-folder hidden"></i>
<i class="fa-solid fa-folder-open"></i>
</span>
<span class="folder-name">${item.name}</span>`

// append <ul class="children"> to <li class="folder">
li.appendChild(folderHeaderDiv)

// If the folder has children, recursively render them
if (item.children && item.children.length > 0) {
// create <ul class="children">
const childrenUl = document.createElement("ul")
childrenUl.className = "children"
// recursively render
render(item.children, childrenUl)
// append <ul class="children"> to <li class="folder">
li.appendChild(childrenUl)
}

// append to rootList
rootList.appendChild(li)
} else {
// create <li class="file">
const li = document.createElement("li")
li.className = "file"

li.innerHTML = `<i class="fa-solid ${getFileIcon(item.category)}"></i>
<span class="file-name">${item.name}</span>
<span class="file-size">${item.size}</span>`

// create <button class="file-download">
const fileDownloadBtn = document.createElement("button")
fileDownloadBtn.className = "file-download"
fileDownloadBtn.innerHTML = '<i class="fa-solid fa-download"></i>'
fileDownloadBtn.onclick = item.downloadAction

// append fileDownloadBtn to li
li.appendChild(fileDownloadBtn)

// append li to rootList
rootList.appendChild(li)
}
}
}

function getFileIcon(category) {
switch (category) {
case 1:
return "fa-file-video"
case 2:
return "fa-file-audio"
case 3:
return "fa-file-image"
case 4:
return "fa-file-lines"
default:
return "fa-file"
}
}

function binding() {
const listFuncs = []
const listElms = []

const folderHeaders = document.querySelectorAll(".folder-header")
folderHeaders.forEach(function (folderHeader) {
const parent = folderHeader.parentNode
const children = parent.querySelector(".children")
const iconArrow = folderHeader.querySelector(".icon-arrow")
const iconFolder = folderHeader.querySelector(".icon-folder")
if (!!children) {
function cb() {
const isOpen = parent.getAttribute("opened") == "true"
parent.setAttribute("opened", !isOpen)
children.classList.toggle("hidden", isOpen)
iconArrow.querySelector(".fa-caret-right").classList.toggle("hidden", !isOpen)
iconArrow.querySelector(".fa-caret-down").classList.toggle("hidden", isOpen)
iconFolder.querySelector(".fa-folder").classList.toggle("hidden", !isOpen)
iconFolder.querySelector(".fa-folder-open").classList.toggle("hidden", isOpen)
}
folderHeader.addEventListener("click", cb)
listFuncs.push(cb)
listElms.push(folderHeader)
} else {
iconArrow.classList.add("hidden")
}
})

return function unbinding() {
for (let index = 0; index < listFuncs.length; index++) {
const func = listFuncs[index]
const elm = listElms[index]
elm.removeEventListener("click", func)
}
}
}

let unbinding = function () {}

return function (data, treeViewElement) {
// remove event listener & clear treeViewElement
unbinding()
treeViewElement.innerHTML = ""

// create rootList
const rootList = document.createElement("ul")
rootList.className = "root"

// render tree view
render(data, rootList)

// append rootList to treeView
treeViewElement.appendChild(rootList)

// binding
unbinding = binding()
}
})()

function formatStorageSize(bytes) {
const KB = 1024
const MB = KB * 1024
const GB = MB * 1024

if (bytes >= GB) {
const gigabytes = bytes / GB
return gigabytes.toFixed(2) + "GB"
} else {
const megabytes = bytes / MB
return megabytes.toFixed(2) + "MB"
}
}
Loading

0 comments on commit 9f13e19

Please sign in to comment.