diff options
author | RaindropsSys <contact@minteck.org> | 2023-05-22 15:54:02 +0200 |
---|---|---|
committer | RaindropsSys <contact@minteck.org> | 2023-05-22 15:54:02 +0200 |
commit | af1fb5ecf169c1d2c9b565063e7383617c760455 (patch) | |
tree | 853197089451c6757adb578979cc99d4201a902a | |
parent | 7348d637ca1b4b5ad6bf840adb409eed7cc8d9ec (diff) | |
download | delta-af1fb5ecf169c1d2c9b565063e7383617c760455.tar.gz delta-af1fb5ecf169c1d2c9b565063e7383617c760455.tar.bz2 delta-af1fb5ecf169c1d2c9b565063e7383617c760455.zip |
Updated 10 files and added 4 files (automated)
-rw-r--r-- | _gallery/index.php | 13 | ||||
-rw-r--r-- | _upload/arbitrary/index.php | 48 | ||||
-rw-r--r-- | _upload/existing/index.php | 67 | ||||
-rw-r--r-- | _upload/index.php | 123 | ||||
-rw-r--r-- | _upload/new.php | 379 | ||||
-rw-r--r-- | _upload/old.php | 122 | ||||
-rw-r--r-- | _upload/save/index.php | 1 | ||||
-rw-r--r-- | admin/approve/index.php | 2 | ||||
-rw-r--r-- | admin/handoff/index.php | 19 | ||||
-rw-r--r-- | admin/requests/index.php | 2 | ||||
-rw-r--r-- | embed/index.php | 41 | ||||
-rw-r--r-- | includes/jobs-handler.php | 3 | ||||
-rw-r--r-- | lang/en.json | 26 | ||||
-rw-r--r-- | lang/fr.json | 26 |
14 files changed, 741 insertions, 131 deletions
diff --git a/_gallery/index.php b/_gallery/index.php index 102711e..450928d 100644 --- a/_gallery/index.php +++ b/_gallery/index.php @@ -61,21 +61,26 @@ if (!isset($id)): <?= doLinking($data["contents"]) ?> </div> <small class="print-ignore text-muted"><?= isset($data["update_user"]) ? str_replace("%2", "<a class='update-user' href='/profile/" . $data["update_user"] . "'>" . resolveUser($data["update_user"]) . "</a>", str_replace("%1", timeAgo($data["update"]), l("lang_time_update_user"))) : str_replace("%1", timeAgo($data["update"]), l("lang_time_update")) ?></small> - <?php endif; ?> + <?php endif; + + $images = $data["images"]; + shuffle($images); + + ?> <div style="display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 20px;"> <div> - <?php $index = 1; foreach ($data["images"] as $image): if ($index % 3 === 1): ?> + <?php $index = 1; foreach ($images as $image): if ($index % 3 === 1): ?> <a href="#" onclick="showGalleryItem(<?= $index ?>);"><img id="gallery-item-<?= $index ?>" title="<?= l("lang_gallery_uploader") . " " . resolveUser($image["author"]) . " " . timeAgo($image["date"]) ?>" src="/uploads/<?= $image["id"] ?>.webp" style="width: 100%; margin-top: 20px; border-radius: 10px;" data-bs-toggle="tooltip"></a> <?php endif; $index++; endforeach; ?> </div> <div> - <?php $index = 1; foreach ($data["images"] as $image): if ($index % 3 === 2): ?> + <?php $index = 1; foreach ($images as $image): if ($index % 3 === 2): ?> <a href="#" onclick="showGalleryItem(<?= $index ?>);"><img id="gallery-item-<?= $index ?>" title="<?= l("lang_gallery_uploader") . " " . resolveUser($image["author"]) . " " . timeAgo($image["date"]) ?>" src="/uploads/<?= $image["id"] ?>.webp" style="width: 100%; margin-top: 20px; border-radius: 10px;" data-bs-toggle="tooltip"></a> <?php endif; $index++; endforeach; ?> </div> <div> - <?php $index = 1; foreach ($data["images"] as $image): if ($index % 3 === 0): ?> + <?php $index = 1; foreach ($images as $image): if ($index % 3 === 0): ?> <a href="#" onclick="showGalleryItem(<?= $index ?>);"><img id="gallery-item-<?= $index ?>" title="<?= l("lang_gallery_uploader") . " " . resolveUser($image["author"]) . " " . timeAgo($image["date"]) ?>" src="/uploads/<?= $image["id"] ?>.webp" style="width: 100%; margin-top: 20px; border-radius: 10px;" data-bs-toggle="tooltip"></a> <?php endif; $index++; endforeach; ?> </div> diff --git a/_upload/arbitrary/index.php b/_upload/arbitrary/index.php new file mode 100644 index 0000000..2271780 --- /dev/null +++ b/_upload/arbitrary/index.php @@ -0,0 +1,48 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.php"; + +global $_PROFILE; global $_USER; + +$id = $_GET['id'] ?? null; + +header("Content-Type: text/plain"); + +if (isset($_POST["list"]) && is_array($_POST["list"])) { + foreach ($_POST["list"] as $uuid) { + if (trim($uuid) === "" || str_contains($uuid, "/") || !file_exists($_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $uuid . ".webp")) continue; + + $requestID = uuid(); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/requests/" . $requestID . ".json", pf_utf8_encode(json_encode([ + "type" => "galleryupload", + "author" => $_USER, + "id" => $id, + "uuid" => $uuid, + "contents" => null, + "summary" => $_POST["summary"], + "date" => date('c') + ]))); + + $_PROFILE["requests"][$id . ":" . $uuid] = $requestID; + } +} + +$config = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/email.json"), true); +file_get_contents('https://notifications.equestria.dev/delta', false, stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => + "Content-Type: text/plain\r\n" . + "Title: " . formatPonypush("New change request published") . "\r\n" . + "Priority: default\r\n" . + "Tags: requests\r\n" . + "Actions: view, Open change requests, https://delta.equestria.dev/admin/requests/, clear=true\r\n" . + "Authorization: Basic " . base64_encode($config["ntfyuser"] . ":" . $config["ntfypass"]), + 'content' => formatPonypush($_PROFILE['first_name'] . " " . $_PROFILE["last_name"] . " published a request to upload an image to " . getNameFromId($id) . (isset($_POST["summary"]) && trim($_POST["summary"]) !== "" ? ": " . $_POST["summary"] : "")) + ] +])); +saveProfile(); + +header("Location: /upload/$id&success"); +die();
\ No newline at end of file diff --git a/_upload/existing/index.php b/_upload/existing/index.php new file mode 100644 index 0000000..decdffb --- /dev/null +++ b/_upload/existing/index.php @@ -0,0 +1,67 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.php"; + +if (isset($_GET["p"])) { + $after = $_GET["p"]; +} else { + $after = null; +} + +$perPage = 3; +$out = []; + +$ids = []; +$list = array_reverse(json_decode(pf_utf8_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/embeds.json")), true)); + +$index = 0; +$show = !isset($after); +foreach (array_filter($list, function ($i) { + global $ids; + + if (is_string($i)) { + if (in_array($i, $ids)) { + return false; + } else { + $ids[] = $i; + return true; + } + } else { + if (in_array($i["id"], $ids)) { + return false; + } else { + $ids[] = $i["id"]; + return true; + } + } +}) as $item) { + if (is_string($item)) { + $item = [ + "id" => $item, + "author" => null + ]; + } + + if (isset($after) && !$show) { + if ($item["id"] === $after) { + $show = true; + continue; + } else { + continue; + } + } + + if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $item["id"] . ".webp") && !file_exists($_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $item["id"] . ".jpg")) continue; + + if ($index >= $perPage) break; + $out[] = [ + "id" => $item["id"], + "author" => isset($item["author"]) ? getNameFromId($item["author"]) : null + ]; + + $index++; +} + +header("Content-Type: application/json"); +die(json_encode($out, JSON_PRETTY_PRINT));
\ No newline at end of file diff --git a/_upload/index.php b/_upload/index.php index 1e42f1d..2b90a80 100644 --- a/_upload/index.php +++ b/_upload/index.php @@ -1,122 +1,7 @@ <?php -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_USER; global $_PROFILE; -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.php"; - -$id = array_values(array_filter(array_keys($_GET), function ($i) { - return str_starts_with($i, "/") && strlen($i) > 1; -}))[0] ?? null; - -if (isset($id)) { - $id = substr($id, 1); - if (!preg_match("/[a-zA-Z0-6]/m", $id)) { - header("Location: /"); - die(); - } - - if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $id . ".json")) { - header("Location: /"); - die(); - } - - if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $id . ".json")) { - $data = json_decode(pf_utf8_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $id . ".json")), true); - $title_pre = getNameFromId($id); - } else { - header("Location: /"); - die(); - } - - $title = "lang_upload_title"; +if (isset($_GET["old"])) { + require_once "./old.php"; } else { - header("Location: /"); - die(); -} - -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/header.php"; -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/navigation.php"; - -?> -<form method="post" action="/_upload/save/?id=<?= $id ?>" id="main-form" enctype="multipart/form-data"> - <div class="container"> - <br><br> - <h1> - <?php if ($id !== $_USER): ?> - <span><?= getNameFromId($id) ?></span> - <span style="float: right;"><a href="/gallery/<?= $id ?>" class="btn btn-outline-dark"><?= l("lang_edit_cancel") ?></a></span> - <?php endif; ?> - </span> - </h1> - - <?php if (isset($_GET["success"])): ?> - <div class="alert alert-success"> - <strong><?= l("lang_upload_success_0") ?></strong><?= l("lang_upload_success_1") ?> <a href="/upload/<?= $id ?>"><?= l("lang_upload_success_2") ?></a> - </div> - <?php else: ?> - <?php if (isset($_GET['error'])): ?> - <div class="alert alert-danger"> - <strong><?= l("lang_upload_error") ?></strong><?= l("lang_upload_errors_" . $_GET['error']) ?> - </div> - <?php endif; ?> - - <div> - <p><?= l("lang_upload_select") ?></p> - <input type="file" name="file" style="width: 100%;"> - <script> - window.onload = () => { - document.getElementsByName("file")[0].value = ""; - } - - document.getElementsByName("file")[0].onchange = () => { - if (document.getElementsByName("file")[0].files[0] && document.getElementsByName("file")[0].files[0].type.startsWith("image/")) { - document.getElementById("preview").src = URL.createObjectURL(document.getElementsByName("file")[0].files[0]); - document.getElementById("preview").onload = () => URL.revokeObjectURL(document.getElementById("preview").src); - document.getElementById("form-btn").classList.remove("disabled"); - } else { - document.getElementById("preview").src = "/icons/defaultpage.svg"; - document.getElementById("form-btn").classList.add("disabled"); - } - } - </script> - </div> - - <p> - <img src="/icons/defaultpage.svg" style="width: 100%; max-width: 300px; margin-top: 20px; border-radius: 10px;" id="preview"> - </p> - - <a id="form-btn" class="btn btn-primary disabled"><?= l("lang_upload_confirm") ?></a> - - <script> - document.getElementById("form-btn").onclick = (event) => { - new bootstrap.Modal(document.getElementById("confirm")).show() - } - </script> - <?php endif; ?> - - <br><br> - </div> - - <div class="modal fade" id="confirm"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title"><?= l("lang_upload_dialog") ?></h4> - <button type="button" class="btn-close" data-bs-dismiss="modal"></button> - </div> - - <div class="modal-body"> - <p><?= l("lang_upload_notice") ?></p> - <p> - <?= l("lang_upload_summary") ?><br> - <!--suppress HtmlFormInputWithoutLabel --> - <textarea class="form-control" name="summary"></textarea> - </p> - <p><?= l("lang_upload_followup") ?></p> - <button class="btn btn-primary"><?= l("lang_edit_confirm_button") ?></button> - </div> - </div> - </div> - </div> -</form> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/footer.php"; ?>
\ No newline at end of file + require_once "./new.php"; +}
\ No newline at end of file diff --git a/_upload/new.php b/_upload/new.php new file mode 100644 index 0000000..98241e7 --- /dev/null +++ b/_upload/new.php @@ -0,0 +1,379 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_USER; global $_PROFILE; +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.php"; + +$id = array_values(array_filter(array_keys($_GET), function ($i) { + return str_starts_with($i, "/") && strlen($i) > 1; +}))[0] ?? null; + +if (isset($id)) { + $id = substr($id, 1); + if (!preg_match("/[a-zA-Z0-6]/m", $id)) { + header("Location: /"); + die(); + } + + if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $id . ".json")) { + header("Location: /"); + die(); + } + + if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $id . ".json")) { + $data = json_decode(pf_utf8_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $id . ".json")), true); + $title_pre = getNameFromId($id); + } else { + header("Location: /"); + die(); + } + + $title = "lang_newgallery_title"; +} else { + header("Location: /"); + die(); +} + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/header.php"; +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/navigation.php"; global $palette; + +?> +<form method="post" action="/_upload/arbitrary/?id=<?= $id ?>" id="main-form" enctype="multipart/form-data"> + <input type="file" id="file" style="display: none;" accept="image/png,image/jpeg,image/webp,image/gif,image/bmp,image/avif" multiple> + <script> + let currentFileIndex = 0; + window.uploadQueue = []; + window.uploading = false; + + setInterval(() => { + if (!uploading && uploadQueue[0]) { + try { + uploading = true; + document.getElementById("list-group-item-" + uploadQueue[0].id + "-status").innerText = "<?= l("lang_newgallery_uploading") ?>"; + + let data = new FormData(); + data.append('upload', uploadQueue[0].file); + + window.fetch("/embed/", { + method: 'POST', + body: data + }).then((res) => { + res.text().then((_data) => { + let data; + + try { + data = JSON.parse(_data); + console.log(data); + } catch (e) { + console.log(_data); + throw e; + } + + if (data.error && data.error.message) { + document.getElementById("list-group-item-" + uploadQueue[0].id + "-status").innerText = "<?= l("lang_newgallery_error_message") ?> " + data.error.message; + document.getElementById("list-group-item-" + uploadQueue[0].id + "-remove").classList.remove("disabled"); + uploading = false; uploadQueue.shift(); + } else if (data.error) { + throw new Error(); + } else if (data['url'] && data['uuid']) { + document.getElementById("list-group-item-" + uploadQueue[0].id + "-uuid").value = data['uuid']; + document.getElementById("list-group-item-" + uploadQueue[0].id + "-status").innerText = "<?= l("lang_newgallery_complete") ?>"; + document.getElementById("list-group-item-" + uploadQueue[0].id + "-remove").classList.remove("disabled"); + document.getElementById("list-group-item-" + uploadQueue[0].id + "-preview").style.backgroundImage = `url("${data['url']}")`; + uploading = false; uploadQueue.shift(); + } else { + throw new Error(); + } + }).catch((e) => { + console.error(e); + document.getElementById("list-group-item-" + uploadQueue[0].id + "-status").innerText = "<?= l("lang_newgallery_error_generic") ?>"; + document.getElementById("list-group-item-" + uploadQueue[0].id + "-remove").classList.remove("disabled"); + uploading = false; uploadQueue.shift(); + }) + }).catch((e) => { + console.error(e); + document.getElementById("list-group-item-" + uploadQueue[0].id + "-status").innerText = "<?= l("lang_newgallery_error_generic") ?>"; + document.getElementById("list-group-item-" + uploadQueue[0].id + "-remove").classList.remove("disabled"); + uploading = false; uploadQueue.shift(); + }); + } catch (e) { + console.error(e); + document.getElementById("list-group-item-" + uploadQueue[0].id + "-status").innerText = "<?= l("lang_newgallery_error_generic") ?>"; + document.getElementById("list-group-item-" + uploadQueue[0].id + "-remove").classList.remove("disabled"); + uploading = false; uploadQueue.shift(); + } + } + + if (document.getElementById("gallery-items").children.length > 0 && !uploading) { + document.getElementById("form-btn").classList.remove("disabled"); + } else { + document.getElementById("form-btn").classList.add("disabled"); + } + }); + + function removeFile(id) { + document.getElementById("list-group-item-" + id).outerHTML = ""; + } + + window.onload = () => { + document.getElementById("file").value = ""; + } + + document.getElementById("file").onchange = () => { + for (let file of Array.from(document.getElementById("file").files)) { + picker.hide(); + let index = currentFileIndex; + console.log(file); + + if (file && file.type.startsWith("image/")) { + document.getElementById("gallery-items").insertAdjacentHTML('beforeend', ` + <div class="list-group-item" id="list-group-item-${currentFileIndex}" style="display: grid; grid-template-columns: 15% 1fr; grid-gap: 20px;"> + <div style="display: flex; align-items: center;"> + <div id="list-group-item-${currentFileIndex}-preview" style="width: 100%; aspect-ratio: 16/9; background-color: black; border-radius: 5px; background-position: center; background-size: contain; background-repeat: no-repeat;"></div> + </div> + <div style="display: flex; align-items: center;"> + <div> + <input type="hidden" name="list[${currentFileIndex}]" value="" id="list-group-item-${currentFileIndex}-uuid"> + <p> + <b>${file.name}</b><br> + <span id="list-group-item-${currentFileIndex}-status"><?= l("lang_newgallery_waiting") ?></span> + </p> + <button class="btn btn-outline-secondary disabled" id="list-group-item-${currentFileIndex}-remove"><?= l("lang_newgallery_remove") ?></button> + </div> + </div> + </div> + `); + + document.getElementById("list-group-item-" + currentFileIndex + "-preview").style.backgroundImage = `url("${URL.createObjectURL(file)}")`; + + document.getElementById("list-group-item-" + currentFileIndex + "-remove").onclick = (e) => { + e.preventDefault(); + removeFile(index); + return false; + } + + uploadQueue.push({ + file, + id: currentFileIndex + }); + document.getElementById("file").value = ""; + } + + currentFileIndex++; + } + } + + function addExisting(id) { + picker.hide(); + + let index = currentFileIndex; + + document.getElementById("gallery-items").insertAdjacentHTML('beforeend', ` + <div class="list-group-item" id="list-group-item-${currentFileIndex}" style="display: grid; grid-template-columns: 15% 1fr; grid-gap: 20px;"> + <div style="display: flex; align-items: center;"> + <div id="list-group-item-${currentFileIndex}-preview" style="width: 100%; aspect-ratio: 16/9; background-color: black; border-radius: 5px; background-position: center; background-size: contain; background-repeat: no-repeat; background-image: url('/uploads/${id}.webp');"></div> + </div> + <div style="display: flex; align-items: center;"> + <div> + <input type="hidden" name="list[${currentFileIndex}]" value="" id="list-group-item-${currentFileIndex}-uuid"> + <p> + <b>${id}.webp</b><br> + <span id="list-group-item-${currentFileIndex}-status"><?= l("lang_newgallery_complete") ?></span> + </p> + <button class="btn btn-outline-secondary" id="list-group-item-${currentFileIndex}-remove"><?= l("lang_newgallery_remove") ?></button> + </div> + </div> + </div> + `); + + document.getElementById("list-group-item-" + currentFileIndex + "-remove").onclick = (e) => { + e.preventDefault(); + removeFile(index); + return false; + } + + currentFileIndex++; + } + </script> + + <div class="container"> + <br><br> + <h1> + <?php if ($id !== $_USER): ?> + <span><?= getNameFromId($id) ?></span> + <span style="float: right;"><a href="/gallery/<?= $id ?>" class="btn btn-outline-dark"><?= l("lang_edit_cancel") ?></a></span> + <?php endif; ?> + </span> + </h1> + + <?php if (isset($_GET['error'])): ?> + <div class="alert alert-danger"> + <strong><?= l("lang_upload_error") ?></strong><?= l("lang_upload_errors_" . $_GET['error']) ?> + </div> + <?php endif; ?> + + <?php if (isset($_GET["success"])): ?> + <div class="alert alert-success"> + <strong><?= l("lang_newgallery_success_0") ?></strong><?= l("lang_newgallery_success_1") ?> + </div> + <?php endif; ?> + + <div> + <p><?= l("lang_newgallery_intro") ?></p> + + <div class="btn-group"> + <a id="upload-btn" onclick="resetPicker(); picker.show();" class="btn btn-primary"><?= l("lang_newgallery_add") ?></a> + <a id="form-btn" class="btn btn-outline-primary disabled"><?= l("lang_newgallery_upload") ?></a> + </div> + </div> + + <div class="list-group" id="gallery-items" style="margin-top: 20px;"></div> + + <script> + document.getElementById("form-btn").onclick = (event) => { + new bootstrap.Modal(document.getElementById("confirm")).show() + } + </script> + + <br><br> + </div> + + <div class="modal fade" id="confirm"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title"><?= l("lang_upload_dialog") ?></h4> + <button type="button" class="btn-close" data-bs-dismiss="modal"></button> + </div> + + <div class="modal-body"> + <p><?= l("lang_upload_notice") ?></p> + <p> + <?= l("lang_upload_summary") ?><br> + <!--suppress HtmlFormInputWithoutLabel --> + <textarea class="form-control" name="summary"></textarea> + </p> + <p><?= l("lang_upload_followup") ?></p> + <button class="btn btn-primary"><?= l("lang_edit_confirm_button") ?></button> + </div> + </div> + </div> + </div> +</form> + + +<div class="modal modal-xl fade" id="picker"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title"><?= l("lang_newgallery_picker_title") ?></h4> + <button type="button" class="btn-close" data-bs-dismiss="modal"></button> + </div> + + <div class="modal-body"> + <a class="card picker-card picker-drop" onclick="document.getElementById('file').click();" style="margin-bottom: 20px;"> + <div class="card-body"> + <img style="width: 32px;" alt="" src="/icons/upload.svg"> + <span style="vertical-align: middle;"><?= l("lang_newgallery_picker_upload") ?></span> + </div> + </a> + + <div style="display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 20px;" id="existing-list"></div> + + <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 10px; margin-top: 20px;" id="existing-loader"> + <svg class="spinner" width="32px" height="32px" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"> + <circle class="path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle> + </svg> + </div> + </div> + + <script> + let lastPageItem = null; + let doneLoading = false; + let loading = false; + window.shouldLoad = false; + + function resetPicker() { + lastPageItem = null; + document.getElementById("existing-loader").style.display = "flex"; + document.getElementById("existing-list").innerHTML = ""; + } + + let options = { + root: document.getElementById("picker"), + rootMargin: "0px", + threshold: 1.0, + }; + + let observer = new IntersectionObserver((entries) => { + shouldLoad = entries[0].isIntersecting; + }, options); + + observer.observe(document.getElementById("existing-loader")); + + setInterval(() => { + if (shouldLoad && !loading && !doneLoading) { + loading = true; + + fetch("/_upload/existing/" + (lastPageItem ? "?p=" + lastPageItem : "")).then((res) => { + res.text().then((_data) => { + let data = JSON.parse(_data); + console.log(data); + + if (data.length < 3) { + doneLoading = true; + document.getElementById("existing-loader").style.display = "none"; + } + + if (data.length > 0) { + lastPageItem = data[data.length - 1].id; + } + + for (let item of data) { + document.getElementById("existing-list").insertAdjacentHTML('beforeend', ` + <a class="card picker-card" onclick="addExisting('${item.id}');"> + <div class="card-body"> + <div style="background-image: url('/uploads/${item.id}.webp'); background-color: black;aspect-ratio: 16/9;width: calc(100% + 2rem);margin-left: -1rem;background-size: contain;background-position: center;background-repeat: no-repeat;margin-right: -1rem;border-radius: 0.375rem;margin-top: -1rem;"></div> + ${item.author ? `<span style="margin-top: 1rem;display: block; text-align: center;"><?= l("lang_newgallery_picker_uploader") ?>${item.author}</span>` : `<span style="margin-top: 1rem;display: block; text-align: center;"><?= l("lang_newgallery_picker_unknown") ?></span>`} + </div> + </a> + `); + } + + loading = false; + }) + }) + } + }); + </script> + </div> + </div> +</div> +<script> + let picker = new bootstrap.Modal(document.getElementById("picker")); +</script> + +<style> + .picker-card { + background-color: var(--palette-3); + border-color: var(--palette-5); + border-width: 2px; + color: inherit !important; + cursor: pointer; + text-decoration: inherit !important; + } + + .picker-card:hover { + opacity: .75; + } + + .picker-card:active { + opacity: .5; + } + + .picker-drop { + border-style: dashed; + text-align: center; + } +</style> + +<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/footer.php"; ?>
\ No newline at end of file diff --git a/_upload/old.php b/_upload/old.php new file mode 100644 index 0000000..1e42f1d --- /dev/null +++ b/_upload/old.php @@ -0,0 +1,122 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_USER; global $_PROFILE; +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.php"; + +$id = array_values(array_filter(array_keys($_GET), function ($i) { + return str_starts_with($i, "/") && strlen($i) > 1; +}))[0] ?? null; + +if (isset($id)) { + $id = substr($id, 1); + if (!preg_match("/[a-zA-Z0-6]/m", $id)) { + header("Location: /"); + die(); + } + + if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $id . ".json")) { + header("Location: /"); + die(); + } + + if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $id . ".json")) { + $data = json_decode(pf_utf8_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $id . ".json")), true); + $title_pre = getNameFromId($id); + } else { + header("Location: /"); + die(); + } + + $title = "lang_upload_title"; +} else { + header("Location: /"); + die(); +} + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/header.php"; +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/navigation.php"; + +?> +<form method="post" action="/_upload/save/?id=<?= $id ?>" id="main-form" enctype="multipart/form-data"> + <div class="container"> + <br><br> + <h1> + <?php if ($id !== $_USER): ?> + <span><?= getNameFromId($id) ?></span> + <span style="float: right;"><a href="/gallery/<?= $id ?>" class="btn btn-outline-dark"><?= l("lang_edit_cancel") ?></a></span> + <?php endif; ?> + </span> + </h1> + + <?php if (isset($_GET["success"])): ?> + <div class="alert alert-success"> + <strong><?= l("lang_upload_success_0") ?></strong><?= l("lang_upload_success_1") ?> <a href="/upload/<?= $id ?>"><?= l("lang_upload_success_2") ?></a> + </div> + <?php else: ?> + <?php if (isset($_GET['error'])): ?> + <div class="alert alert-danger"> + <strong><?= l("lang_upload_error") ?></strong><?= l("lang_upload_errors_" . $_GET['error']) ?> + </div> + <?php endif; ?> + + <div> + <p><?= l("lang_upload_select") ?></p> + <input type="file" name="file" style="width: 100%;"> + <script> + window.onload = () => { + document.getElementsByName("file")[0].value = ""; + } + + document.getElementsByName("file")[0].onchange = () => { + if (document.getElementsByName("file")[0].files[0] && document.getElementsByName("file")[0].files[0].type.startsWith("image/")) { + document.getElementById("preview").src = URL.createObjectURL(document.getElementsByName("file")[0].files[0]); + document.getElementById("preview").onload = () => URL.revokeObjectURL(document.getElementById("preview").src); + document.getElementById("form-btn").classList.remove("disabled"); + } else { + document.getElementById("preview").src = "/icons/defaultpage.svg"; + document.getElementById("form-btn").classList.add("disabled"); + } + } + </script> + </div> + + <p> + <img src="/icons/defaultpage.svg" style="width: 100%; max-width: 300px; margin-top: 20px; border-radius: 10px;" id="preview"> + </p> + + <a id="form-btn" class="btn btn-primary disabled"><?= l("lang_upload_confirm") ?></a> + + <script> + document.getElementById("form-btn").onclick = (event) => { + new bootstrap.Modal(document.getElementById("confirm")).show() + } + </script> + <?php endif; ?> + + <br><br> + </div> + + <div class="modal fade" id="confirm"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title"><?= l("lang_upload_dialog") ?></h4> + <button type="button" class="btn-close" data-bs-dismiss="modal"></button> + </div> + + <div class="modal-body"> + <p><?= l("lang_upload_notice") ?></p> + <p> + <?= l("lang_upload_summary") ?><br> + <!--suppress HtmlFormInputWithoutLabel --> + <textarea class="form-control" name="summary"></textarea> + </p> + <p><?= l("lang_upload_followup") ?></p> + <button class="btn btn-primary"><?= l("lang_edit_confirm_button") ?></button> + </div> + </div> + </div> + </div> +</form> + +<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/footer.php"; ?>
\ No newline at end of file diff --git a/_upload/save/index.php b/_upload/save/index.php index bfc466e..2272e5e 100644 --- a/_upload/save/index.php +++ b/_upload/save/index.php @@ -76,6 +76,7 @@ file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/requests/" . $uuid "type" => "galleryupload", "author" => $_USER, "id" => $id, + "uuid" => $uuid, "contents" => null, "summary" => $_POST["summary"], "date" => date('c') diff --git a/admin/approve/index.php b/admin/approve/index.php index fdca968..b288e18 100644 --- a/admin/approve/index.php +++ b/admin/approve/index.php @@ -50,7 +50,7 @@ if ($request["type"] === "galleryupload" && !isset($_GET['mark'])) { if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $request["id"] . ".json")) { $gallery = json_decode(pf_utf8_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gallery/" . $request["id"] . ".json")), true); $gallery["images"][] = [ - "id" => $id, + "id" => $request["uuid"], "author" => $request["author"], "date" => $request["date"] ]; diff --git a/admin/handoff/index.php b/admin/handoff/index.php index 804ecd3..86fb763 100644 --- a/admin/handoff/index.php +++ b/admin/handoff/index.php @@ -6,6 +6,19 @@ $title_pre = l("lang_admin_titles_handoff"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/navigation.php"; +$indexes = [ + "Primary", + "On Primary", + "On Background", + "On Primary Container", + "Secondary 35/Secondary 80", + "Secondary 30/Secondary 90", + "Secondary 25/Secondary 95", + "Surface Variant", + "Neutral 10/Neutral 95", + "Background" +]; + ?> <div class="container"> @@ -15,6 +28,12 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/navigation.php"; <code><?= $_COOKIE["DeltaHandoffPalette"] ?? "-" ?></code> + <ul> + <?php global $palette; foreach ($palette as $index => $color): ?> + <li>[<?= $index ?>, <?= $indexes[9 - $index] ?? "(unknown)" ?>] <code>#<?= $color ?></code> <div style="background-color: #<?= $color ?>; width: 16px; height: 16px; display: inline-block;"></div></li> + <?php endforeach; ?> + </ul> + <br><br> </div> diff --git a/admin/requests/index.php b/admin/requests/index.php index fe7491e..5e136f0 100644 --- a/admin/requests/index.php +++ b/admin/requests/index.php @@ -83,7 +83,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/navigation.php"; </details> <?php if ($request["type"] === "galleryupload"): ?> - <p><img src="/uploads/<?= $request["_id"] ?>.webp" style="max-width: 30vw; max-height: 30vh;"></p> + <p><img src="/uploads/<?= $request["uuid"] ?? $request["_id"] ?>.webp" style="max-width: 30vw; max-height: 30vh;"></p> <?php elseif(isset($request["contents"]) && trim($request["contents"]) !== ""): ?> <div style="max-height: 300px; overflow: auto; background-color: rgba(0, 0, 0, .25); padding: 5px 10px; border-radius: 10px; margin-bottom: 20px;"> <?= $request["contents"] ?> diff --git a/embed/index.php b/embed/index.php index feeb6ba..4fe3989 100644 --- a/embed/index.php +++ b/embed/index.php @@ -6,6 +6,8 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.php"; global $_PROFILE; global $_USER; $uuid = uuid(); +$json = file_get_contents('php://input'); +$obj = json_decode($json, true); header("Content-Type: application/json"); @@ -61,7 +63,12 @@ switch ($_FILES["upload"]["type"]) { break; } -imagewebp($im, $_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp"); +$res = false; + +while (!$res) { + $res = imagewebp($im, $_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp"); +} + $size = getimagesize($_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp"); $ratio_orig = $size[0] / $size[1]; @@ -76,31 +83,55 @@ if ($width / $height > $ratio_orig) { if ($size[0] > 1080 || $size[1] > 1080) { imagescale($im, $width, $height); - imagewebp($im, $_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp"); + + $res = false; + + while (!$res) { + $res = imagewebp($im, $_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp"); + } } $list = json_decode(pf_utf8_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/embeds.json")), true); foreach ($list as $item) { + if (is_string($item)) { + $list = array_map(function ($i) { + if (is_string($i)) { + return [ + "id" => $i, + "author" => null + ]; + } else { + return $i; + } + }, $list); + break; + } +} + +foreach ($list as $item) { if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $item["id"] . ".webp") && file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp") === file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $item["id"] . ".webp")) { $uuid = $item["id"]; unlink($_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp"); } elseif (file_exists($_SERVER['DOCUMENT_ROOT'] . "/uploads/archive/" . $item["id"] . ".webp") && file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp") === file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/uploads/archive/" . $item["id"] . ".webp")) { $uuid = $item["id"]; unlink($_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp"); - rename($_SERVER['DOCUMENT_ROOT'] . "/uploads/archive/" . $item["id"] . ".webp", $_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $item["id"] . ".web"); + rename($_SERVER['DOCUMENT_ROOT'] . "/uploads/archive/" . $item["id"] . ".webp", $_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $item["id"] . ".webp"); } else { - rename($_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp", $_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $uuid . ".web"); + rename($_SERVER['DOCUMENT_ROOT'] . "/uploads/temp-" . $uuid . ".webp", $_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $uuid . ".webp"); $list[] = [ "id" => $uuid, "author" => $_USER ]; + + break; } } file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/embeds.json", pf_utf8_encode(json_encode($list))); die(json_encode([ - "url" => "/uploads/" . $uuid . ".webp" + "url" => "/uploads/" . $uuid . ".webp", + "uuid" => $uuid ]));
\ No newline at end of file diff --git a/includes/jobs-handler.php b/includes/jobs-handler.php index 79bca78..5639091 100644 --- a/includes/jobs-handler.php +++ b/includes/jobs-handler.php @@ -282,8 +282,9 @@ foreach (array_filter(scandir($_SERVER['DOCUMENT_ROOT'] . "/uploads/"), function } } + println(" " . $upload . ", will delete: " . (!$used && time() - filemtime($_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $upload) > 3600 ? "yes" : "no") . ", difference: " . (time() - filemtime($_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $upload)) . ", used: " . ($used ? "yes" : "no")); + if (!$used && time() - filemtime($_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $upload) > 3600) { - println(" " . $upload); rename($_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $upload, $_SERVER['DOCUMENT_ROOT'] . "/uploads/archive/" . $upload); } } diff --git a/lang/en.json b/lang/en.json index 91235bd..478f141 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1113,5 +1113,31 @@ "description": "You are now ready to use Delta. You can use the integrated support feature if you need it. Click on Done to access Delta." } ] + }, + "newgallery": { + "title": "Add images", + "intro": "Select the files you want to publish in this album.", + "upload": "Publish images", + "add": "Add another image", + "waiting": "Waiting for upload...", + "uploading": "Uploading to server...", + "remove": "Remove image", + "error": { + "message": "Upload failed due to the following error:", + "generic": "Upload failed" + }, + "complete": "Upload completed", + "success": [ + "Success: ", + "The images you have uploaded have been successfully submitted for review to the administrators." + ], + "picker": { + "title": "Select an image", + "upload": "Upload from your device", + "uploader": "Published by ", + "unknown": "Unknown publisher" + }, + "notice": "Do you want to publish these images to be reviewed by the administrators? Make sure these are the right images before you send them, as you cannot change them afterwards.", + "summary": "Optionally describe these images and why they should be added to the album:" } }
\ No newline at end of file diff --git a/lang/fr.json b/lang/fr.json index 636b09f..9e5e0df 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -1109,5 +1109,31 @@ "description": "Vous êtes désormais prêt·e à utiliser Delta. Vous pouvez utiliser l'option d'aide intégrée si besoin. Cliquez sur Terminer pour accéder à Delta." } ] + }, + "newgallery": { + "title": "Ajouter des images", + "intro": "Sélectionnez les fichiers que vous voulez publier dans cet album.", + "upload": "Publier les images", + "add": "Ajouter une autre", + "waiting": "En attente d'envoi...", + "uploading": "Envoi au serveur...", + "remove": "Supprimer l'image", + "error": { + "message": "Échec de l'envoi en raison de l'erreur suivante :", + "generic": "Échec de l'envoi" + }, + "complete": "Envoi terminé", + "success": [ + "Terminé : ", + "Les images que vous avez envoyées ont été soumises pour relecture par les administrateur·ice·s." + ], + "picker": { + "title": "Sélectionner une image", + "upload": "Importer depuis votre appareil", + "uploader": "Publié par ", + "unknown": "Auteur inconnu" + }, + "notice": "Voulez-vous publier ces images pour être revues par les administrateur·ice·s ? Assurez-vous qu'il s'agit des bonnes images avant de les envoyer, étant donné que vous ne pouvez pas les modifier après.", + "summary": "En option, décrivez ces images et pourquoi elles doivent être ajoutées à cet album :" } }
\ No newline at end of file |