Compare commits

..

No commits in common. "beb9d9c3e5bbb805f00f856526b57752a342d22f" and "0709d8deb9145f65540c530d884c17b6114ade9b" have entirely different histories.

12 changed files with 128 additions and 155 deletions

View file

@ -1 +1 @@
__version__ = '0.3.1' __version__ = '0.3.0'

View file

@ -44,8 +44,7 @@ def get_csp(request: web.Request) -> str:
"connect-src 'self'", "connect-src 'self'",
"img-src 'self'", "img-src 'self'",
"object-src 'none'", "object-src 'none'",
"frame-ancestors 'none'", "frame-ancestors 'none'"
f"manifest-src 'self' https://{request.app.config.domain}"
] ]
return '; '.join(data) + ';' return '; '.join(data) + ';'

View file

@ -13,7 +13,9 @@
%meta(name="viewport" content="width=device-width, initial-scale=1") %meta(name="viewport" content="width=device-width, initial-scale=1")
%link(rel="stylesheet" type="text/css" href="/theme/{{config.theme}}.css" nonce="{{view.request['hash']}}" class="theme") %link(rel="stylesheet" type="text/css" href="/theme/{{config.theme}}.css" nonce="{{view.request['hash']}}" class="theme")
%link(rel="stylesheet" type="text/css" href="/static/style.css" nonce="{{view.request['hash']}}") %link(rel="stylesheet" type="text/css" href="/static/style.css" nonce="{{view.request['hash']}}")
%link(rel="manifest" href="/manifest.json") %link(rel="stylesheet" type="text/css" href="/static/toast.css" nonce="{{view.request['hash']}}")
%script(type="application/javascript" src="/static/menu.js" nonce="{{view.request['hash']}}", defer)
%script(type="application/javascript" src="/static/toast.js" nonce="{{view.request['hash']}}", defer)
%script(type="application/javascript" src="/static/api.js" nonce="{{view.request['hash']}}", defer) %script(type="application/javascript" src="/static/api.js" nonce="{{view.request['hash']}}", defer)
-block head -block head

View file

@ -1,61 +1,3 @@
// toast notifications
const notifications = document.querySelector("#notifications")
function remove_toast(toast) {
toast.classList.add("hide");
if (toast.timeoutId) {
clearTimeout(toast.timeoutId);
}
setTimeout(() => toast.remove(), 300);
}
function toast(text, type="error", timeout=5) {
const toast = document.createElement("li");
toast.className = `section ${type}`
toast.innerHTML = `<span class=".text">${text}</span><a href="#">&#10006;</span>`
toast.querySelector("a").addEventListener("click", async (event) => {
event.preventDefault();
await remove_toast(toast);
});
notifications.appendChild(toast);
toast.timeoutId = setTimeout(() => remove_toast(toast), timeout * 1000);
}
// menu
const body = document.getElementById("container")
const menu = document.getElementById("menu");
const menu_open = document.getElementById("menu-open");
const menu_close = document.getElementById("menu-close");
menu_open.addEventListener("click", (event) => {
var new_value = menu.attributes.visible.nodeValue === "true" ? "false" : "true";
menu.attributes.visible.nodeValue = new_value;
});
menu_close.addEventListener("click", (event) => {
menu.attributes.visible.nodeValue = "false"
});
body.addEventListener("click", (event) => {
if (event.target === menu_open) {
return;
}
menu.attributes.visible.nodeValue = "false";
});
// misc
function get_date_string(date) { function get_date_string(date) {
var year = date.getFullYear().toString(); var year = date.getFullYear().toString();
var month = date.getMonth().toString(); var month = date.getMonth().toString();

View file

@ -100,7 +100,6 @@ async function req_response(domain, accept) {
} }
if (!accept) { if (!accept) {
toast("Denied instance request", "message");
return; return;
} }
@ -118,7 +117,7 @@ async function req_response(domain, accept) {
} }
}); });
toast("Accepted instance request", "message"); toast("Removed instance", "message");
} }

View file

@ -0,0 +1,21 @@
const body = document.getElementById("container")
const menu = document.getElementById("menu");
const menu_open = document.getElementById("menu-open");
const menu_close = document.getElementById("menu-close");
menu_open.addEventListener("click", (event) => {
var new_value = menu.attributes.visible.nodeValue === "true" ? "false" : "true";
menu.attributes.visible.nodeValue = new_value;
});
menu_close.addEventListener("click", (event) => {
menu.attributes.visible.nodeValue = "false"
});
body.addEventListener("click", (event) => {
if (event.target === menu_open) {
return;
}
menu.attributes.visible.nodeValue = "false";
});

View file

@ -204,37 +204,6 @@ textarea {
text-align: center; text-align: center;
} }
#notifications {
position: fixed;
top: 40px;
left: 50%;
transform: translateX(-50%);
}
#notifications li {
position: relative;
overflow: hidden;
list-style: none;
border-radius: 5px;
padding: 5px;;
margin-bottom: var(--spacing);
animation: show_toast 0.3s ease forwards;
display: grid;
grid-template-columns: auto max-content;
grid-gap: 5px;
align-items: center;
}
#notifications a {
font-size: 1.5em;
line-height: 1em;
text-decoration: none;
}
#notifications li.hide {
animation: hide_toast 0.3s ease forwards;
}
#footer { #footer {
display: grid; display: grid;
grid-template-columns: auto auto; grid-template-columns: auto auto;
@ -327,44 +296,6 @@ textarea {
} }
@keyframes show_toast {
0% {
transform: translateX(100%);
}
40% {
transform: translateX(-5%);
}
80% {
transform: translateX(0%);
}
100% {
transform: translateX(-10px);
}
}
@keyframes hide_toast {
0% {
transform: translateX(-10px);
}
40% {
transform: translateX(0%);
}
80% {
transform: translateX(-5%);
}
100% {
transform: translateX(calc(100% + 20px));
}
}
@media (max-width: 1026px) { @media (max-width: 1026px) {
body { body {
margin: 0px; margin: 0px;

View file

@ -0,0 +1,68 @@
#notifications {
position: fixed;
top: 40px;
left: 50%;
transform: translateX(-50%);
}
#notifications li {
position: relative;
overflow: hidden;
list-style: none;
border-radius: 5px;
padding: 5px;;
margin-bottom: var(--spacing);
animation: show_toast 0.3s ease forwards;
display: grid;
grid-template-columns: auto max-content;
grid-gap: 5px;
align-items: center;
}
#notifications a {
font-size: 1.5em;
line-height: 1em;
text-decoration: none;
}
#notifications li.hide {
animation: hide_toast 0.3s ease forwards;
}
@keyframes show_toast {
0% {
transform: translateX(100%);
}
40% {
transform: translateX(-5%);
}
80% {
transform: translateX(0%);
}
100% {
transform: translateX(-10px);
}
}
@keyframes hide_toast {
0% {
transform: translateX(-10px);
}
40% {
transform: translateX(0%);
}
80% {
transform: translateX(-5%);
}
100% {
transform: translateX(calc(100% + 20px));
}
}

View file

@ -0,0 +1,26 @@
const notifications = document.querySelector("#notifications")
function remove_toast(toast) {
toast.classList.add("hide");
if (toast.timeoutId) {
clearTimeout(toast.timeoutId);
}
setTimeout(() => toast.remove(), 300);
}
function toast(text, type="error", timeout=5) {
const toast = document.createElement("li");
toast.className = `section ${type}`
toast.innerHTML = `<span class=".text">${text}</span><a href="#">&#10006;</span>`
toast.querySelector("a").addEventListener("click", async (event) => {
event.preventDefault();
await remove_toast(toast);
});
notifications.appendChild(toast);
toast.timeoutId = setTimeout(() => remove_toast(toast), timeout * 1000);
}

View file

@ -38,8 +38,7 @@ MIMETYPES = {
'css': 'text/css', 'css': 'text/css',
'html': 'text/html', 'html': 'text/html',
'json': 'application/json', 'json': 'application/json',
'text': 'text/plain', 'text': 'text/plain'
'webmanifest': 'application/manifest+json'
} }
NODEINFO_NS = { NODEINFO_NS = {

View file

@ -3,6 +3,7 @@ from __future__ import annotations
import aputils import aputils
import traceback import traceback
import typing import typing
import json
from .base import View, register_route from .base import View, register_route

View file

@ -45,6 +45,7 @@ async def handle_frontend_path(request: web.Request, handler: Callable) -> Respo
response = await handler(request) response = await handler(request)
if not request['user'] and request['token']: if not request['user'] and request['token']:
print("del token")
response.del_cookie('user-token') response.del_cookie('user-token')
return response return response
@ -210,27 +211,11 @@ class AdminConfig(View):
return Response.new(data, ctype = 'html') return Response.new(data, ctype = 'html')
@register_route('/manifest.json') @register_route('/style.css')
class ManifestJson(View): class StyleCss(View):
async def get(self, request: Request) -> Response: async def get(self, request: Request) -> Response:
with self.database.session(False) as conn: data = self.template.render('style.css', self)
config = conn.get_config_all() return Response.new(data, ctype = 'css')
theme = THEMES[config.theme]
data = {
'background_color': theme['background'],
'categories': ['activitypub'],
'description': 'Message relay for the ActivityPub network',
'display': 'standalone',
'name': config['name'],
'orientation': 'portrait',
'scope': f"https://{self.config.domain}/",
'short_name': 'ActivityRelay',
'start_url': f"https://{self.config.domain}/",
'theme_color': theme['primary']
}
return Response.new(data, ctype = 'webmanifest')
@register_route('/theme/{theme}.css') @register_route('/theme/{theme}.css')