more work
This commit is contained in:
parent
fb64a35759
commit
2c21698841
7 changed files with 1253 additions and 64 deletions
41
web/dist/index.html
vendored
41
web/dist/index.html
vendored
|
@ -1,41 +0,0 @@
|
||||||
<!DOCTYPE html><html><head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Omegaupload</title>
|
|
||||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/styles/github-dark.min.css">
|
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js"></script>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<link rel="preload" href="/index-c5eae97b1d11880a_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
|
|
||||||
<link rel="modulepreload" href="/index-c5eae97b1d11880a.js"></head>
|
|
||||||
|
|
||||||
<body><script type="module">import init from '/index-c5eae97b1d11880a.js';init('/index-c5eae97b1d11880a_bg.wasm');</script><script>(function () {
|
|
||||||
var url = 'ws://' + window.location.host + '/_trunk/ws';
|
|
||||||
var poll_interval = 5000;
|
|
||||||
var reload_upon_connect = () => {
|
|
||||||
window.setTimeout(
|
|
||||||
() => {
|
|
||||||
// when we successfully reconnect, we'll force a
|
|
||||||
// reload (since we presumably lost connection to
|
|
||||||
// trunk due to it being killed, so it will have
|
|
||||||
// rebuilt on restart)
|
|
||||||
var ws = new WebSocket(url);
|
|
||||||
ws.onopen = () => window.location.reload();
|
|
||||||
ws.onclose = reload_upon_connect;
|
|
||||||
},
|
|
||||||
poll_interval);
|
|
||||||
};
|
|
||||||
|
|
||||||
var ws = new WebSocket(url);
|
|
||||||
ws.onmessage = (ev) => {
|
|
||||||
const msg = JSON.parse(ev.data);
|
|
||||||
if (msg.reload) {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ws.onclose = reload_upon_connect;
|
|
||||||
})()
|
|
||||||
</script></body></html>
|
|
|
@ -1,14 +1,50 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>Omegaupload</title>
|
<title>Omegaupload</title>
|
||||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/styles/github-dark.min.css">
|
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js"></script>
|
<link data-trunk rel="copy-file" href="src/Mplus2-Regular.ttf" dest="/" />
|
||||||
|
<link data-trunk rel="copy-file" href="src/MplusCodeLatin-varwidthweight.ttf" dest="/" />
|
||||||
|
<link data-trunk rel="copy-file" href="src/highlight.min.js" dest="/" />
|
||||||
|
<link data-trunk rel="css" href="src/github-dark.min.css" />
|
||||||
|
|
||||||
|
<link rel="preload" href="highlight.min.js" as="script" type="application/javascript">
|
||||||
|
<link rel="preload" href="Mplus2-Regular.ttf" as="font" type="font/ttf" crossorigin>
|
||||||
|
<link rel="preload" href="MplusCodeLatin-varwidthweight.ttf" as="font" type="font/ttf" crossorigin>
|
||||||
|
|
||||||
|
<script src="highlight.min.js"></script>
|
||||||
<style>
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: "Mplus2 Regular";
|
||||||
|
src: url("./Mplus2-Regular.ttf") format("truetype");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Mplus Code";
|
||||||
|
src: url("./MplusCodeLatin-varwidthweight.ttf") format("truetype");
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
background-color: #404040;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.banner {
|
||||||
|
font-family: 'Mplus2 Regular', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paste {
|
||||||
|
border-radius: 1em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
padding: 1em;
|
||||||
|
background-color: #0d1117;
|
||||||
|
box-shadow: 0 0 1em black;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
font-family: 'Mplus Code', sans-serif;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
BIN
web/src/Mplus2-Regular.ttf
Normal file
BIN
web/src/Mplus2-Regular.ttf
Normal file
Binary file not shown.
BIN
web/src/MplusCodeLatin-varwidthweight.ttf
Normal file
BIN
web/src/MplusCodeLatin-varwidthweight.ttf
Normal file
Binary file not shown.
10
web/src/github-dark.min.css
vendored
Normal file
10
web/src/github-dark.min.css
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
|
||||||
|
Theme: GitHub Dark
|
||||||
|
Description: Dark theme as seen on github.com
|
||||||
|
Author: github.com
|
||||||
|
Maintainer: @Hirse
|
||||||
|
Updated: 2021-05-15
|
||||||
|
|
||||||
|
Outdated base version: https://github.com/primer/github-syntax-dark
|
||||||
|
Current colors taken from GitHub's CSS
|
||||||
|
*/.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#79c0ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-code,.hljs-comment,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}
|
1149
web/src/highlight.min.js
vendored
Normal file
1149
web/src/highlight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -5,10 +5,11 @@ use std::str::FromStr;
|
||||||
use anyhow::{anyhow, bail};
|
use anyhow::{anyhow, bail};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use downcast_rs::{impl_downcast, Downcast};
|
use downcast_rs::{impl_downcast, Downcast};
|
||||||
|
use http::header::EXPIRES;
|
||||||
use http::uri::PathAndQuery;
|
use http::uri::PathAndQuery;
|
||||||
use http::{StatusCode, Uri};
|
use http::{StatusCode, Uri};
|
||||||
use omegaupload_common::crypto::{open, Key, Nonce};
|
use omegaupload_common::crypto::{open, Key, Nonce};
|
||||||
use omegaupload_common::PartialParsedUrl;
|
use omegaupload_common::{Expiration, PartialParsedUrl};
|
||||||
use yew::format::Nothing;
|
use yew::format::Nothing;
|
||||||
use yew::utils::window;
|
use yew::utils::window;
|
||||||
use yew::Properties;
|
use yew::Properties;
|
||||||
|
@ -91,9 +92,14 @@ impl Component for Paste {
|
||||||
link.send_future(async move {
|
link.send_future(async move {
|
||||||
match reqwest::get(&request_uri.to_string()).await {
|
match reqwest::get(&request_uri.to_string()).await {
|
||||||
Ok(resp) if resp.status() == StatusCode::OK => {
|
Ok(resp) if resp.status() == StatusCode::OK => {
|
||||||
|
let expires = resp
|
||||||
|
.headers()
|
||||||
|
.get(EXPIRES)
|
||||||
|
.and_then(|v| Expiration::try_from(v).ok());
|
||||||
let partial = match resp.bytes().await {
|
let partial = match resp.bytes().await {
|
||||||
Ok(bytes) => PastePartial::new(
|
Ok(bytes) => PastePartial::new(
|
||||||
bytes,
|
bytes,
|
||||||
|
expires,
|
||||||
url.split_once('#')
|
url.split_once('#')
|
||||||
.map(|(_, fragment)| PartialParsedUrl::from(fragment))
|
.map(|(_, fragment)| PartialParsedUrl::from(fragment))
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
|
@ -173,7 +179,8 @@ struct PasteError(anyhow::Error);
|
||||||
#[derive(Properties, Clone, Debug)]
|
#[derive(Properties, Clone, Debug)]
|
||||||
struct PastePartial {
|
struct PastePartial {
|
||||||
parent: ComponentLink<Paste>,
|
parent: ComponentLink<Paste>,
|
||||||
data: Option<Bytes>,
|
data: Bytes,
|
||||||
|
expires: Option<Expiration>,
|
||||||
key: Option<Key>,
|
key: Option<Key>,
|
||||||
nonce: Option<Nonce>,
|
nonce: Option<Nonce>,
|
||||||
password: Option<Key>,
|
password: Option<Key>,
|
||||||
|
@ -183,6 +190,7 @@ struct PastePartial {
|
||||||
#[derive(Properties, Clone)]
|
#[derive(Properties, Clone)]
|
||||||
struct PasteComplete {
|
struct PasteComplete {
|
||||||
data: Bytes,
|
data: Bytes,
|
||||||
|
expires: Option<Expiration>,
|
||||||
key: Key,
|
key: Key,
|
||||||
nonce: Nonce,
|
nonce: Nonce,
|
||||||
password: Option<Key>,
|
password: Option<Key>,
|
||||||
|
@ -198,13 +206,15 @@ impl PasteState for PasteComplete {}
|
||||||
|
|
||||||
impl PastePartial {
|
impl PastePartial {
|
||||||
fn new(
|
fn new(
|
||||||
resp: Bytes,
|
data: Bytes,
|
||||||
|
expires: Option<Expiration>,
|
||||||
partial_parsed_url: PartialParsedUrl,
|
partial_parsed_url: PartialParsedUrl,
|
||||||
parent: ComponentLink<Paste>,
|
parent: ComponentLink<Paste>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
parent,
|
parent,
|
||||||
data: Some(resp),
|
data,
|
||||||
|
expires,
|
||||||
key: partial_parsed_url.decryption_key,
|
key: partial_parsed_url.decryption_key,
|
||||||
nonce: partial_parsed_url.nonce,
|
nonce: partial_parsed_url.nonce,
|
||||||
password: None,
|
password: None,
|
||||||
|
@ -235,17 +245,21 @@ impl Component for PastePartial {
|
||||||
PartialPasteMessage::Password(password) => self.password = Some(password),
|
PartialPasteMessage::Password(password) => self.password = Some(password),
|
||||||
}
|
}
|
||||||
|
|
||||||
match (self.data.clone(), self.key, self.nonce, self.password) {
|
match (self.key, self.nonce, self.password) {
|
||||||
(Some(data), Some(key), Some(nonce), Some(password)) if self.needs_pw => {
|
(Some(key), Some(nonce), maybe_password)
|
||||||
self.parent.callback(move |Nothing| {
|
if (self.needs_pw && maybe_password.is_some())
|
||||||
Box::new(PasteComplete::new(data.clone(), key, nonce, Some(password)))
|
|| (!self.needs_pw && maybe_password.is_none()) =>
|
||||||
as Box<dyn PasteState>
|
{
|
||||||
});
|
let data = self.data.clone();
|
||||||
}
|
let expires = self.expires.clone();
|
||||||
(Some(data), Some(key), Some(nonce), None) if !self.needs_pw => {
|
self.parent.callback_once(move |Nothing| {
|
||||||
self.parent.callback(move |Nothing| {
|
Box::new(PasteComplete::new(
|
||||||
Box::new(PasteComplete::new(data.clone(), key, nonce, None))
|
data,
|
||||||
as Box<dyn PasteState>
|
expires,
|
||||||
|
key,
|
||||||
|
nonce,
|
||||||
|
maybe_password,
|
||||||
|
)) as Box<dyn PasteState>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -272,27 +286,31 @@ impl TryFrom<PastePartial> for PasteComplete {
|
||||||
fn try_from(partial: PastePartial) -> Result<Self, Self::Error> {
|
fn try_from(partial: PastePartial) -> Result<Self, Self::Error> {
|
||||||
match partial {
|
match partial {
|
||||||
PastePartial {
|
PastePartial {
|
||||||
data: Some(data),
|
data,
|
||||||
key: Some(key),
|
key: Some(key),
|
||||||
|
expires,
|
||||||
nonce: Some(nonce),
|
nonce: Some(nonce),
|
||||||
password: Some(password),
|
password: Some(password),
|
||||||
needs_pw: true,
|
needs_pw: true,
|
||||||
..
|
..
|
||||||
} => Ok(PasteComplete {
|
} => Ok(PasteComplete {
|
||||||
data,
|
data,
|
||||||
|
expires,
|
||||||
key,
|
key,
|
||||||
nonce,
|
nonce,
|
||||||
password: Some(password),
|
password: Some(password),
|
||||||
}),
|
}),
|
||||||
PastePartial {
|
PastePartial {
|
||||||
data: Some(data),
|
data,
|
||||||
key: Some(key),
|
key: Some(key),
|
||||||
|
expires,
|
||||||
nonce: Some(nonce),
|
nonce: Some(nonce),
|
||||||
needs_pw: false,
|
needs_pw: false,
|
||||||
..
|
..
|
||||||
} => Ok(PasteComplete {
|
} => Ok(PasteComplete {
|
||||||
data,
|
data,
|
||||||
key,
|
key,
|
||||||
|
expires,
|
||||||
nonce,
|
nonce,
|
||||||
password: None,
|
password: None,
|
||||||
}),
|
}),
|
||||||
|
@ -302,9 +320,16 @@ impl TryFrom<PastePartial> for PasteComplete {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PasteComplete {
|
impl PasteComplete {
|
||||||
fn new(data: Bytes, key: Key, nonce: Nonce, password: Option<Key>) -> Self {
|
fn new(
|
||||||
|
data: Bytes,
|
||||||
|
expires: Option<Expiration>,
|
||||||
|
key: Key,
|
||||||
|
nonce: Nonce,
|
||||||
|
password: Option<Key>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data,
|
data,
|
||||||
|
expires,
|
||||||
key,
|
key,
|
||||||
nonce,
|
nonce,
|
||||||
password,
|
password,
|
||||||
|
@ -323,9 +348,19 @@ impl PasteComplete {
|
||||||
if let Ok(str) = String::from_utf8(decrypted) {
|
if let Ok(str) = String::from_utf8(decrypted) {
|
||||||
html! {
|
html! {
|
||||||
<>
|
<>
|
||||||
<pre><code>{str}</code></pre>
|
<header class={"hljs paste banner"}>{
|
||||||
|
if let Some(expires) = &self.expires {
|
||||||
|
match expires {
|
||||||
|
Expiration::BurnAfterReading => "This paste has been burned. You now have the only copy.".to_string(),
|
||||||
|
Expiration::UnixTime(time) => time.format("This paste will expire on %A, %B %-d, %Y at %T %Z.").to_string(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"This paste will not expire.".to_string()
|
||||||
|
}
|
||||||
|
}</header>
|
||||||
|
<pre class={"paste"}><code>{str}</code></pre>
|
||||||
|
|
||||||
<script>{ "hljs.highlightAll();" }</script>
|
<script>{"hljs.highlightAll();"}</script>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue