image upload spinner
This commit is contained in:
parent
2026a8f457
commit
e43bee9e2e
5 changed files with 90 additions and 13 deletions
|
@ -308,6 +308,7 @@ footer {
|
||||||
background-color: var(--hover);
|
background-color: var(--hover);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
image-rendering: crisp-edges;
|
image-rendering: crisp-edges;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nb {
|
.nb {
|
||||||
|
@ -379,3 +380,51 @@ form {
|
||||||
background-color: #bbbbbb !important;
|
background-color: #bbbbbb !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fullwidth {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading div {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
margin: 8px;
|
||||||
|
border: 3px solid var(--text);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: loading 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||||
|
border-color: var(--text) transparent transparent transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading div:nth-child(1) {
|
||||||
|
animation-delay: -0.45s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading div:nth-child(2) {
|
||||||
|
animation-delay: -0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading div:nth-child(3) {
|
||||||
|
animation-delay: -0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loading {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ body {
|
||||||
height: inherit;
|
height: inherit;
|
||||||
background-color: var(--hover);
|
background-color: var(--hover);
|
||||||
border-radius: 0px 0px 20px 20px;
|
border-radius: 0px 0px 20px 20px;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
#info {
|
#info {
|
||||||
|
|
|
@ -23,12 +23,27 @@ function changeimage(fn) {
|
||||||
input.accept= 'image/png'
|
input.accept= 'image/png'
|
||||||
|
|
||||||
input.onchange = async (e) => {
|
input.onchange = async (e) => {
|
||||||
|
|
||||||
|
var popup = document.getElementById("popup")
|
||||||
|
var loader = popup.getElementsByClassName("loading")[0]
|
||||||
|
var message = popup.getElementsByClassName("message")[0]
|
||||||
|
|
||||||
|
loader.classList.add("hidden")
|
||||||
|
message.innerHTML = '';
|
||||||
|
popup.classList.remove("hidden")
|
||||||
|
|
||||||
var file = e.target.files[0];
|
var file = e.target.files[0];
|
||||||
if (file.type !== 'image/png') {
|
if (file.type !== 'image/png') {
|
||||||
|
message.innerHTML = 'Image must be a PNG';
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loader.classList.remove("hidden")
|
||||||
|
|
||||||
let response = await fn(file);
|
let response = await fn(file);
|
||||||
alert(response.msg)
|
|
||||||
|
loader.classList.add("hidden")
|
||||||
|
message.innerHTML = response.msg
|
||||||
}
|
}
|
||||||
|
|
||||||
input.click();
|
input.click();
|
||||||
|
@ -92,6 +107,20 @@ function render() {
|
||||||
|
|
||||||
append(about)
|
append(about)
|
||||||
|
|
||||||
|
const popup = `
|
||||||
|
<div id="popup" class="hidden">
|
||||||
|
<div class="createpost">
|
||||||
|
<div class="close" onclick="document.getElementById('popup').classList.add('hidden')"></div>
|
||||||
|
<span class="ltext ctext bold">Uploading</span>
|
||||||
|
<div class="fullline"></div>
|
||||||
|
<div class="fullwidth"><div class="loading"><div></div><div></div><div></div><div></div></div></div>
|
||||||
|
<span class="message ctext" style="padding-top: 10px"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
|
||||||
|
append(popup)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logout_button() {
|
async function logout_button() {
|
||||||
|
|
|
@ -7,25 +7,23 @@ use serde::Deserialize;
|
||||||
|
|
||||||
use crate::types::http::ResponseCode;
|
use crate::types::http::ResponseCode;
|
||||||
|
|
||||||
use super::console;
|
|
||||||
|
|
||||||
pub async fn js(Path(path): Path<String>) -> Response {
|
pub async fn js(Path(path): Path<String>) -> Response {
|
||||||
let path = format!("/js/{}", path);
|
let path = format!("/js/{path}");
|
||||||
super::serve(&path).await
|
super::serve(&path).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn css(Path(path): Path<String>) -> Response {
|
pub async fn css(Path(path): Path<String>) -> Response {
|
||||||
let path = format!("/css/{}", path);
|
let path = format!("/css/{path}");
|
||||||
super::serve(&path).await
|
super::serve(&path).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fonts(Path(path): Path<String>) -> Response {
|
pub async fn fonts(Path(path): Path<String>) -> Response {
|
||||||
let path = format!("/fonts/{}", path);
|
let path = format!("/fonts/{path}");
|
||||||
super::serve(&path).await
|
super::serve(&path).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn image(Path(path): Path<String>) -> Response {
|
pub async fn image(Path(path): Path<String>) -> Response {
|
||||||
let path = format!("/image/{}", path);
|
let path = format!("/image/{path}");
|
||||||
super::serve(&path).await
|
super::serve(&path).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ where
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(forwardedfor) = forwardedfor {
|
if let Some(forwardedfor) = forwardedfor {
|
||||||
return Ok(RequestIp(forwardedfor));
|
return Ok(Self(forwardedfor));
|
||||||
}
|
}
|
||||||
|
|
||||||
let realip = headers
|
let realip = headers
|
||||||
|
@ -57,7 +57,7 @@ where
|
||||||
.and_then(|s| s.parse::<IpAddr>().ok());
|
.and_then(|s| s.parse::<IpAddr>().ok());
|
||||||
|
|
||||||
if let Some(realip) = realip {
|
if let Some(realip) = realip {
|
||||||
return Ok(RequestIp(realip));
|
return Ok(Self(realip));
|
||||||
}
|
}
|
||||||
|
|
||||||
let realip = headers
|
let realip = headers
|
||||||
|
@ -66,13 +66,13 @@ where
|
||||||
.and_then(|s| s.parse::<IpAddr>().ok());
|
.and_then(|s| s.parse::<IpAddr>().ok());
|
||||||
|
|
||||||
if let Some(realip) = realip {
|
if let Some(realip) = realip {
|
||||||
return Ok(RequestIp(realip));
|
return Ok(Self(realip));
|
||||||
}
|
}
|
||||||
|
|
||||||
let info = parts.extensions.get::<ConnectInfo<SocketAddr>>();
|
let info = parts.extensions.get::<ConnectInfo<SocketAddr>>();
|
||||||
|
|
||||||
if let Some(info) = info {
|
if let Some(info) = info {
|
||||||
return Ok(RequestIp(info.0.ip()));
|
return Ok(Self(info.0.ip()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(ResponseCode::Forbidden.text("You have no ip"))
|
Err(ResponseCode::Forbidden.text("You have no ip"))
|
||||||
|
|
Loading…
Reference in a new issue