Compare commits

...

27 commits
1.0-1 ... main

Author SHA1 Message Date
7961d3c568 Remove gitignore 2024-05-11 10:35:42 +01:00
cabd84710e Made the website automatically fetch and upgrade 2024-05-11 10:35:19 +01:00
a4851fa6d3 Get website relative to executable 2024-04-25 18:08:29 +01:00
4753feeab9 Make install work offline 2024-04-25 17:58:39 +01:00
fccd97e498 Custom go 2024-04-25 17:07:22 +01:00
89efef2036 oops 2024-04-25 16:44:52 +01:00
ca162da742 Migrated to a 4.1 version so that it doesn't brutally murder flatpak 2024-04-25 16:44:42 +01:00
a9b20ae3f0 Fixed makefile 2024-04-25 07:43:30 +00:00
f3e75789aa Remove accidental binary 2024-04-25 07:37:34 +01:00
901147bf76 Go rewrite: release 1 2024-04-25 07:37:16 +01:00
f9ffc9b521 1.3 2024-04-22 07:52:41 +00:00
b2afe8f6f5 Update org.hectabit.Burgernotes.metainfo.xml 2024-04-22 08:49:30 +01:00
33d6c4667b Fixed homeservers lol 2024-03-15 19:32:54 +00:00
82b6316e4a Updated to 1.2 2024-03-15 13:09:55 +00:00
c5a8d7995a Update org.hectabit.Burgernotes.metainfo.xml 2024-03-15 12:57:09 +00:00
e51a3eb785 Fixed desktop files 2024-02-29 20:11:06 +00:00
4bb06f8514 Update org.hectabit.Burgernotes.desktop 2024-02-29 20:08:25 +00:00
ddc34acb9a Fixed makefile 2024-02-29 19:01:15 +00:00
28dcc001b5 Migrate to burgernotes name and appid 2024-02-29 18:16:43 +00:00
efe8a51c5f Updated with login screen 2024-02-28 13:15:54 +00:00
e897c7d563 Big 2024-02-27 20:04:26 +00:00
5c23acb91c Merge branch 'main' of ssh://hectabit.org/HectaBit/PageBurger-App 2024-02-26 19:21:04 +00:00
994e1880e5 Updated so website loads locally 2024-02-26 19:20:46 +00:00
639596bd38 Update org.hectabit.PageBurger.metainfo.xml 2024-02-26 15:56:52 +00:00
ea62220a03 Update org.hectabit.PageBurger.metainfo.xml 2024-02-26 15:56:09 +00:00
84dfcaf03d Update org.hectabit.PageBurger.metainfo.xml 2024-02-26 07:48:50 +00:00
c21619c687 Update org.hectabit.PageBurger.metainfo.xml 2024-02-26 07:46:22 +00:00
104 changed files with 38530 additions and 190 deletions

View file

@ -1,37 +1,27 @@
CC = gcc
DESTDIR = /usr/bin
SHAREDIR = /usr/share
CFLAGS = -Wall -Wextra -g
PKG_CONFIG = pkg-config
GTK_LIBS = $(shell $(PKG_CONFIG) --libs gtk+-3.0)
WEBKIT_LIBS = $(shell $(PKG_CONFIG) --libs webkit2gtk-4.1)
LIBS = $(GTK_LIBS) $(WEBKIT_LIBS)
INCLUDES = $(shell $(PKG_CONFIG) --cflags gtk+-3.0 webkit2gtk-4.1)
SRCS = pageburger.c
OBJS = $(SRCS:.c=.o)
TARGET = pageburger
GO = /usr/bin/go
.PHONY: all clean
all: pageburger
all: burgernotes
pageburger: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(TARGET) $(LIBS)
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
burgernotes:
$(GO) build
clean:
rm -f $(OBJS) $(TARGET)
rm -f burgernotes-app
install: pageburger
install: burgernotes
mkdir -p $(DESTDIR)
cp pageburger $(DESTDIR)
mkdir -p $(SHAREDIR)/burgernotes
cp burgernotes-app $(SHAREDIR)/burgernotes/burgernotes
ln -sf $(SHAREDIR)/burgernotes/burgernotes $(DESTDIR)/burgernotes
mkdir -p $(SHAREDIR)/icons/hicolor/scalable/apps/
mkdir -p $(SHAREDIR)/applications/
mkdir -p $(SHAREDIR)/metainfo/
cp org.hectabit.PageBurger.svg $(SHAREDIR)/icons/hicolor/scalable/apps/
cp org.hectabit.PageBurger.desktop $(SHAREDIR)/applications/
cp org.hectabit.PageBurger.metainfo.xml $(SHAREDIR)/metainfo/
cp org.hectabit.Burgernotes.svg $(SHAREDIR)/icons/hicolor/scalable/apps/
cp org.hectabit.Burgernotes.desktop $(SHAREDIR)/applications/
cp org.hectabit.Burgernotes.metainfo.xml $(SHAREDIR)/metainfo/
cp -r website $(SHAREDIR)/burgernotes/website
cp createwebsite.sh $(SHAREDIR)/burgernotes/

View file

@ -1,3 +1,3 @@
# PageBurger-App
# Burgernotes-App
Native desktop app for PageBurger
Native desktop app for Burgernotes

8
createwebsite.sh Executable file
View file

@ -0,0 +1,8 @@
#!/bin/sh
rm -rf website/*
mkdir -p website
rm -rf burgernotes-client-web
git clone https://centrifuge.hectabit.org/hectabit/burgernotes-client-web.git --depth=1
mv burgernotes-client-web/* website/
cp rdir.html website/index.html
rm -rf burgernotes-client-web website/README.md website/LICENSE.md

10
go.mod Normal file
View file

@ -0,0 +1,10 @@
module hectabit.org/burgernotes-app
go 1.22.2
require (
github.com/arzumify/webview_go-4.1 v0.0.0-20240425153857-cdb51de8ba32
github.com/gotk3/gotk3 v0.6.3
)
replace github.com/arzumify/webview_go-4.1 v0.0.0-20240425153857-cdb51de8ba32 => ./webkit-4.1

2
go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/gotk3/gotk3 v0.6.3 h1:+Ke4WkM1TQUNOlM2TZH6szqknqo+zNbX3BZWVXjSHYw=
github.com/gotk3/gotk3 v0.6.3/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=

160
main.go Normal file
View file

@ -0,0 +1,160 @@
package main
import (
"fmt"
"path/filepath"
"archive/zip"
"github.com/arzumify/webview_go-4.1"
"net/http"
"os"
"io"
"strconv"
)
func upgrade(path string) {
err := os.RemoveAll(filepath.Join(path, "website"))
if err != nil {
fmt.Println("[ERROR] Failed to delete current version:", err)
return
}
err = os.MkdirAll(filepath.Join(path, "website"), os.ModePerm)
if err != nil {
fmt.Println("[ERROR] Failed to create website directory:", err)
return
}
resp, err := http.Get("https://centrifuge.hectabit.org/HectaBit/Burgernotes-client-web/archive/main.zip")
if err != nil {
fmt.Println("[ERROR] Cannot fetch latest version:", err)
return
}
defer resp.Body.Close()
tempFile, err := os.CreateTemp("", "upgrade_*.zip")
if err != nil {
fmt.Println("[ERROR] Failed to create temporary file:", err)
return
}
defer os.Remove(tempFile.Name())
_, err = io.Copy(tempFile, resp.Body)
if err != nil {
fmt.Println("[ERROR] Failed to copy zip content to temporary file:", err)
return
}
zipReader, err := zip.OpenReader(tempFile.Name())
if err != nil {
fmt.Println("[ERROR] Failed to open zip file:", err)
return
}
defer zipReader.Close()
for _, file := range zipReader.File {
dstPath := filepath.Join(filepath.Join(path, "website"), file.Name)
if file.FileInfo().IsDir() {
os.MkdirAll(dstPath, os.ModePerm)
continue
}
fileReader, err := file.Open()
if err != nil {
fmt.Println("[ERROR] Failed to open file in zip:", err)
return
}
defer fileReader.Close()
dstFile, err := os.Create(dstPath)
if err != nil {
fmt.Println("[ERROR] Failed to create destination file:", err)
return
}
defer dstFile.Close()
_, err = io.Copy(dstFile, fileReader)
if err != nil {
fmt.Println("[ERROR] Failed to copy file contents:", err)
return
}
}
src, err := os.Open(filepath.Join(filepath.Join(path, "website"), "burgernotes-client-web"))
if err != nil {
fmt.Println("[ERROR] Cannot find created folder:", err)
return
}
files, err := src.Readdir(-1)
if err != nil {
fmt.Println("[ERROR] Failed to read files:", err)
return
}
for _, file := range files {
srcPath := filepath.Join(filepath.Join(filepath.Join(path, "website"), "burgernotes-client-web"), file.Name())
dstPath := filepath.Join(filepath.Join(path, "website"), file.Name())
err := os.Rename(srcPath, dstPath)
if err != nil {
fmt.Println("[ERROR] Failed to move files:", err)
return
}
}
err = os.Remove(filepath.Join(filepath.Join(path, "website"), "burgernotes-client-web"))
if err != nil {
fmt.Println("[ERROR] Failed to delete source directory:", err)
return
}
file, err := os.OpenFile(filepath.Join(filepath.Join(path, "website"), "index.html"), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
fmt.Println("[ERROR] Failed to open index.html:", err)
return
}
defer file.Close()
filecontent := "<!DOCTYPE html><html><head><title>Burgernotes</title><meta charset=\"UTF-8\" /><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" /><meta http-equiv=\"refresh\" content=\"0; url=/app\"><head>Redirecting...<script>window.location.replace(\"/app\")</script>"
_, err = file.WriteString(filecontent)
if err != nil {
fmt.Println("[ERROR] Failed to replace index.html:", err)
return
}
}
func vcheck(path string) {
localVersion, err := os.ReadFile(path + "/website/static/version.txt")
if err != nil {
fmt.Println("[ERROR] Cannot get local version:", err)
os.Exit(1)
}
localVersionNum, err := strconv.Atoi(string(localVersion))
if err != nil {
fmt.Println("[ERROR] Failed to convert local version to integer:", err)
return
}
resp, err := http.Get("https://notes.hectabit.org/static/version.txt")
if err != nil {
fmt.Println("[ERROR] Cannot fetch remote version:", err)
return
}
remoteVersion, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("[ERROR] Failed to read remote version:", err)
return
}
defer resp.Body.Close()
remoteVersionNum, err := strconv.Atoi(string(remoteVersion))
if err != nil {
fmt.Println("[ERROR] Failed to convert remote version to integer:", err)
return
}
if localVersionNum < remoteVersionNum {
fmt.Println("[INFO] Local version is old. Attempting upgrade...")
upgrade(path)
} else {
fmt.Println("[INFO] Up to date")
}
}
func main() {
exepath, _ := os.Executable()
path, _ := filepath.EvalSymlinks(exepath)
go func() {
http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(filepath.Dir(path) + "/website"))))
http.ListenAndServe("localhost:52064", nil)
}()
vcheck(filepath.Dir(path))
w := webview.New(false)
defer w.Destroy()
w.SetTitle("Burgernotes")
w.SetSize(800, 800, webview.HintNone)
w.Navigate("http://localhost:52064")
w.Run()
}

View file

@ -1,7 +1,7 @@
[Desktop Entry]
Type=Application
Name=PageBurger
Name=Burgernotes
Comment=Simple, private noting service
Icon=org.hectabit.PageBurger
Exec=pageburger
Icon=org.hectabit.Burgernotes
Exec=burgernotes
Categories=Office;WordProcessor

View file

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>org.hectabit.Burgernotes</id>
<name>Burgernotes</name>
<summary>Simple, private notes app</summary>
<developer_name>Hectabit</developer_name>
<metadata_license>MIT</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<supports>
<control>pointing</control>
<control>keyboard</control>
<control>touch</control>
</supports>
<description>
<p>
Burgernotes is a simple, private-by-default and easy to use notes app. All your notes seamlessly sync across your devices, and are 100% end-to-end encrypted, so no one but you can access them.
</p>
</description>
<launchable type="desktop-id">org.hectabit.Burgernotes.desktop</launchable>
<screenshots>
<screenshot type="default">
<image>https://www.hectabit.org/assets/img/pscreenshot.png</image>
</screenshot>
<screenshot>
<image>https://www.hectabit.org/assets/img/pscreenshot2.png</image>
</screenshot>
</screenshots>
<url type="homepage">http://notes.hectabit.org/</url>
<project_group>HectaBit</project_group>
<categories>
<category>Office</category>
<category>WordProcessor</category>
</categories>
<provides>
<binary>burgernotes</binary>
</provides>
<content_rating type="oars-1.1" />
<branding>
<color type="primary" scheme_preference="light">#ffffff</color>
<color type="primary" scheme_preference="dark">#202124</color>
</branding>
<releases>
<release version="1.3" date="2024-04-22">
<url type="details">https://centrifuge.hectabit.org/HectaBit/Burgernotes-App/releases/tag/1.3</url>
<description>
<p>Release 1.3</p>
<ul>
<li>Update to latest version of client</li>
<li>Updated to a newer golang client</li>
</ul>
</description>
</release>
<release version="1.2" date="2024-03-15">
<url type="details">https://centrifuge.hectabit.org/HectaBit/Burgernotes-App/releases/tag/1.2</url>
<description>
<p>Release 1.2</p>
<ul>
<li>Update to latest website version</li>
</ul>
</description>
</release>
<release version="1.1-2" date="2024-02-29">
<url type="details">https://centrifuge.hectabit.org/HectaBit/Burgernotes-App/releases/tag/1.1-2</url>
<description>
<p>Release 1.1-2</p>
<ul>
<li>Migrate AppID</li>
</ul>
</description>
</release>
<release version="1.1-1" date="2024-02-28">
<url type="details">https://centrifuge.hectabit.org/HectaBit/Burgernotes-App/releases/tag/1.1-1</url>
<description>
<p>Release 1.1-1</p>
<ul>
<li>Updated website</li>
</ul>
</description>
</release>
<release version="1.1" date="2024-02-26">
<url type="details">https://centrifuge.hectabit.org/HectaBit/Burgernotes-App/releases/tag/1.1</url>
<description>
<p>Release 1.1</p>
<ul>
<li>Make website local to prevent MITMs</li>
<li>Make icon smaller</li>
<li>Changed name</li>
<li>Fixed developer name</li>
</ul>
</description>
</release>
<release version="1.0-3" date="2024-02-26">
<url type="details">https://centrifuge.hectabit.org/HectaBit/Burgernotes-App/releases/tag/1.0-3</url>
<description>
<p>Release 1.0-3</p>
<ul>
<li>Updated metainfo</li>
</ul>
</description>
</release>
<release version="1.0-2" date="2024-02-26">
<url type="details">https://centrifuge.hectabit.org/HectaBit/Burgernotes-App/releases/tag/1.0-2</url>
<description>
<p>Release 1.0-2</p>
<ul>
<li>Updated metainfo</li>
</ul>
</description>
</release>
<release version="1.0-1" date="2024-02-25">
<url type="details">https://centrifuge.hectabit.org/HectaBit/Burgernotes-App/releases/tag/1.0-1</url>
<description>
<p>Release 1.0-1</p>
<ul>
<li>Updated metainfo</li>
<li>Updated app logo</li>
</ul>
</description>
</release>
<release version="1.0" date="2024-02-25">
<url type="details">https://centrifuge.hectabit.org/HectaBit/Burgernotes-App/releases/tag/1.0-1</url>
<description>
<p>Initial Release</p>
<ul>
<li>Created program</li>
</ul>
</description>
</release>
</releases>
</component>

View file

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="384"
height="384"
viewBox="0 0 384 384"
fill="none"
version="1.1"
id="svg33"
sodipodi:docname="org.hectabit.PageBurger.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview33"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1"
inkscape:cx="124.5"
inkscape:cy="279.5"
inkscape:window-width="1432"
inkscape:window-height="831"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg33" /><defs
id="defs33"><linearGradient
id="paint0_linear_5_50"
x1="213.333"
y1="21.3295"
x2="213.333"
y2="362.667"
gradientUnits="userSpaceOnUse"><stop
stop-color="#CCD6DD"
id="stop21" /><stop
offset="1"
stop-color="#CCD6DD"
stop-opacity="0"
id="stop22" /></linearGradient><linearGradient
id="paint1_linear_5_50"
x1="43.118"
y1="309.376"
x2="43.118"
y2="384"
gradientUnits="userSpaceOnUse"><stop
stop-color="#66757F"
id="stop23" /><stop
offset="1"
stop-color="#50585C"
id="stop24" /><stop
offset="1"
stop-color="#50585C"
id="stop25" /></linearGradient><linearGradient
id="paint2_linear_5_50"
x1="43.118"
y1="224.043"
x2="43.118"
y2="298.667"
gradientUnits="userSpaceOnUse"><stop
stop-color="#66757F"
id="stop26" /><stop
offset="1"
stop-color="#50585C"
id="stop27" /></linearGradient><linearGradient
id="paint3_linear_5_50"
x1="43.118"
y1="138.709"
x2="43.118"
y2="213.333"
gradientUnits="userSpaceOnUse"><stop
stop-color="#66757F"
id="stop28" /><stop
offset="1"
stop-color="#50585C"
id="stop29" /></linearGradient><linearGradient
id="paint4_linear_5_50"
x1="43.118"
y1="53.376"
x2="43.118"
y2="128"
gradientUnits="userSpaceOnUse"><stop
stop-color="#66757F"
id="stop30" /><stop
offset="1"
stop-color="#50585C"
id="stop31" /></linearGradient><linearGradient
id="paint5_linear_5_50"
x1="186.667"
y1="85.3333"
x2="186.667"
y2="384"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.59873694,0,0,0.59873694,77.220137,77.042507)"><stop
stop-color="#55ACEE"
id="stop32" /><stop
offset="1"
stop-color="#55ACEE"
stop-opacity="0"
id="stop33" /></linearGradient><clipPath
id="clip0_5_50"><rect
width="384"
height="384"
fill="white"
id="rect33" /></clipPath></defs><g
id="g1"
transform="matrix(14.587349,0,0,14.587349,-525.96684,-2077.4268)"
style="display:inline"><g
clip-path="url(#clip0_5_50)"
id="g18"
transform="matrix(0.04909581,0,0,0.04909581,39.800677,146.14861)"
style="display:inline"><path
d="M 384,277.333 C 384,300.896 364.896,320 341.333,320 H 85.3333 C 61.7707,320 42.6667,300.896 42.6667,277.333 V 67.3387 C 42.6667,43.776 104.437,0 128,0 H 326.667 C 359.669,0 384,24.6613 384,57.3333 Z"
fill="#226699"
id="path1" /><path
d="m 362.667,320 c 0,23.563 -19.104,42.667 -42.667,42.667 H 106.667 C 83.104,362.667 64,343.563 64,320 V 64 C 64,20.064 63.776,21.3333 117.333,21.3333 H 320 c 23.563,0 42.667,19.104 42.667,42.6667 z"
fill="url(#paint0_linear_5_50)"
id="path2"
style="fill:url(#paint0_linear_5_50)" /><path
d="m 341.333,330.667 c 0,17.674 -14.325,32 -32,32 H 74.6667 c -17.6747,0 -32,-14.326 -32,-32 V 74.6667 c 0,-17.6747 14.3253,-32 32,-32 H 309.333 c 17.675,0 32,14.3253 32,32 z"
fill="#e1e8ed"
id="path3" /><path
d="m 91.1147,351.776 c 0,7.488 -7.1147,13.557 -15.8934,13.557 -8.768,0 -15.8826,-6.069 -15.8826,-13.557 0,-7.477 7.1146,-13.557 15.8826,-13.557 8.7787,0 15.8934,6.069 15.8934,13.557 z"
fill="#662113"
id="path4" /><path
d="m 73.536,344.224 c -5.12,0.587 -8.448,4 -10.848,7.776 -3.2747,5.173 -10.7413,10.667 -20.0213,10.667 -11.776,0 -21.3334,-7.158 -21.3334,-16 0,-8.843 9.5574,-16 21.3334,-16 V 309.376 C 19.552,309.6 0.885345,326.176 0.885345,346.667 0.885345,367.296 19.7867,384 43.104,384 62.88,384 78.8053,372.853 84.7147,356.597 87.6693,348.501 79.712,343.541 73.536,344.224 Z"
fill="url(#paint1_linear_5_50)"
id="path5"
style="fill:url(#paint1_linear_5_50)" /><path
d="M 91.1147,266.443 C 91.1147,273.931 84,280 75.2213,280 c -8.768,0 -15.8826,-6.069 -15.8826,-13.557 0,-7.478 7.1146,-13.558 15.8826,-13.558 8.7787,0 15.8934,6.07 15.8934,13.558 z"
fill="#662113"
id="path6" /><path
d="m 73.536,258.891 c -5.12,0.586 -8.448,4 -10.848,7.776 -3.2747,5.173 -10.7413,10.666 -20.0213,10.666 -11.776,0 -21.3334,-7.157 -21.3334,-16 0,-8.842 9.5574,-16 21.3334,-16 v -21.29 c -23.1147,0.224 -41.781355,16.8 -41.781355,37.29 0,20.63 18.901355,37.334 42.218655,37.334 19.776,0 35.7013,-11.147 41.6107,-27.403 2.9546,-8.096 -5.0027,-13.056 -11.1787,-12.373 z"
fill="url(#paint2_linear_5_50)"
id="path7"
style="fill:url(#paint2_linear_5_50)" /><path
d="m 91.1147,181.109 c 0,7.488 -7.1147,13.558 -15.8934,13.558 -8.768,0 -15.8826,-6.07 -15.8826,-13.558 0,-7.477 7.1146,-13.557 15.8826,-13.557 8.7787,0 15.8934,6.069 15.8934,13.557 z"
fill="#662113"
id="path8" /><path
d="m 73.536,173.557 c -5.12,0.587 -8.448,4 -10.848,7.776 C 59.4133,186.507 51.9467,192 42.6667,192 c -11.776,0 -21.3334,-7.157 -21.3334,-16 0,-8.843 9.5574,-16 21.3334,-16 V 138.709 C 19.552,138.933 0.885345,155.509 0.885345,176 c 0,20.629 18.901355,37.333 42.218655,37.333 19.776,0 35.7013,-11.146 41.6107,-27.402 2.9546,-8.096 -5.0027,-13.056 -11.1787,-12.374 z"
fill="url(#paint3_linear_5_50)"
id="path9"
style="fill:url(#paint3_linear_5_50)" /><path
d="m 91.1147,95.776 c 0,7.488 -7.1147,13.557 -15.8934,13.557 -8.768,0 -15.8826,-6.069 -15.8826,-13.557 0,-7.4773 7.1146,-13.5573 15.8826,-13.5573 8.7787,0 15.8934,6.0693 15.8934,13.5573 z"
fill="#662113"
id="path10" /><path
d="m 73.536,88.224 c -5.12,0.5867 -8.448,4 -10.848,7.776 -3.2747,5.173 -10.7413,10.667 -20.0213,10.667 -11.776,0 -21.3334,-7.1577 -21.3334,-16.0003 0,-8.8427 9.5574,-16 21.3334,-16 V 53.376 C 19.5627,53.5893 0.885345,70.176 0.885345,90.6667 0.885345,111.296 19.7867,128 43.104,128 62.88,128 78.8053,116.853 84.7147,100.597 87.6693,92.5013 79.712,87.5413 73.536,88.224 Z"
fill="url(#paint4_linear_5_50)"
id="path11"
style="fill:url(#paint4_linear_5_50)" /><path
d="m 214,225.771 c -88.504,0 -160.2439,-2.125 -160.2439,60.699 0,62.796 71.7399,77.086 160.2439,77.086 88.504,0 160.244,-14.29 160.244,-77.086 0,-62.815 -71.74,-60.699 -160.244,-60.699 z"
fill="#d99e82"
id="path12" /><path
d="m 369.55,230.54 c 0,0 -77.624,-9.293 -155.55,-9.69 -77.926,0.397 -155.55,9.69 -155.55,9.69 -7.6783,61.143 56.072,86.332 155.55,86.332 99.478,0 163.228,-25.189 155.55,-86.332 z"
fill="#662113"
id="path13" /><path
d="m 364.034,206.098 -300.8523,6.101 c -10.3889,0 -19.0873,21.052 -8.0656,26.558 82.2419,25.575 148.3529,51.453 148.3529,51.453 9.086,5.024 12.155,5.043 21.25,0.028 0,0 91.29,-36.531 149.931,-51.878 8.321,-2.172 -0.236,-32.262 -10.616,-32.262 z"
fill="#ffcc4d"
id="path14" /><path
d="m 371.958,206.891 c -17.944,-16.537 -16.905,-7.735 -30.656,-11.617 -5.223,-1.473 -42.595,-49.781 -127.774,-49.781 h -0.189 c -85.18,0 -122.5512,48.308 -127.774,49.781 -13.7511,3.882 -12.7122,-4.92 -30.6567,11.617 -8.2355,7.593 -10.4644,11.541 -1.7755,13.506 13.09,2.956 11.9,10.88 21.2783,13.637 11.3522,3.334 16.0178,-2.757 34.3209,-0.264 15.612,2.125 16.632,22.374 32.385,22.374 15.754,0 15.754,-7.556 31.497,-7.556 15.744,0 25.057,20.268 40.81,20.268 15.753,0 25.056,-20.268 40.809,-20.268 15.754,0 15.754,7.556 31.498,7.556 15.753,0 16.773,-20.249 32.385,-22.374 18.303,-2.484 22.978,3.598 34.321,0.264 9.378,-2.757 8.188,-10.672 21.278,-13.637 8.708,-1.955 6.488,-5.913 -1.757,-13.506 z"
fill="#77b255"
id="path15" /><path
d="m 365.838,189.022 c 0,28.182 -67.981,41.49 -151.838,41.49 -83.857,0 -151.8383,-13.308 -151.8383,-41.49 0,-51.028 9.1233,-51.028 151.8383,-51.028 142.715,0 151.838,0.009 151.838,51.028 z"
fill="#dd2e44"
id="path16" /><path
d="m 214,37.9489 c -88.504,0 -160.2439,41.4705 -160.2439,104.2851 0,57.848 71.7399,60.209 160.2439,60.209 88.504,0 160.244,-2.361 160.244,-60.209 C 374.244,79.41 302.504,37.9489 214,37.9489 Z"
fill="#d99e82"
id="path17" /><path
d="m 145.849,67.8972 c -4.703,-3.0128 -10.946,-1.6339 -13.95,3.0695 -3.003,4.7033 -1.633,10.9555 3.07,13.9494 4.703,3.0128 16.622,5.2606 19.635,0.5572 3.003,-4.7033 -4.052,-14.5727 -8.755,-17.5761 z m 91.932,-9.775 c -5.308,1.7189 -14.629,9.5011 -12.901,14.8089 1.728,5.3078 13.827,6.12 19.134,4.4011 5.308,-1.7189 8.208,-7.4233 6.479,-12.7311 -1.719,-5.2983 -7.423,-8.2072 -12.712,-6.4789 z m 103.03,66.4418 c -4.269,-3.589 -14.97,2.125 -18.568,6.394 -3.589,4.278 -3.032,10.644 1.237,14.233 4.269,3.588 10.644,3.031 14.233,-1.238 3.598,-4.278 7.376,-15.8 3.098,-19.389 z M 306.404,77.3417 c -4.703,-3.0034 -10.946,-1.6245 -13.958,3.0789 -3.004,4.7033 -1.625,10.9461 3.078,13.9494 4.704,3.0128 16.623,5.2606 19.626,0.5572 3.013,-4.7128 -4.042,-14.5822 -8.746,-17.5855 z M 164.738,143.453 c -4.704,-3.004 -10.946,-1.625 -13.959,3.079 -3.003,4.694 -1.625,10.946 3.079,13.94 4.703,3.012 16.622,5.27 19.625,0.557 3.013,-4.703 -4.042,-14.573 -8.745,-17.576 z m 28.768,-45.4091 c -3.174,4.5901 -5.856,16.4241 -1.257,19.5971 4.59,3.173 14.705,-3.532 17.879,-8.122 3.173,-4.59 2.011,-10.8801 -2.579,-14.0534 -4.58,-3.1734 -10.88,-2.0117 -14.043,2.5783 z m 75.121,45.4091 c -4.704,-3.004 -10.946,-1.625 -13.959,3.079 -3.004,4.694 -1.625,10.955 3.079,13.94 4.703,3.012 16.622,5.27 19.625,0.557 3.013,-4.703 -4.042,-14.573 -8.745,-17.576 z M 90.7311,106.742 c -3.7211,4.165 -7.8672,15.565 -3.7022,19.286 4.1461,3.721 15.0261,-1.644 18.7471,-5.809 3.731,-4.155 3.372,-10.54 -0.784,-14.27 -4.146,-3.721 -10.5398,-3.362 -14.2609,0.793 z"
fill="#ffe8b6"
id="path18" /></g><path
d="m 281.58883,281.41119 c 0,14.10803 -11.43829,25.5463 -25.54573,25.5463 H 134.69889 c -14.10786,0 -25.54614,-11.43827 -25.54614,-25.5463 V 140.90797 c 0,-14.10803 11.43828,-25.54629 25.54614,-25.54629 H 256.0431 c 14.10744,0 25.54573,11.43826 25.54573,25.54629 z"
fill="#3b88c3"
id="path19"
style="display:inline;stroke-width:0.598737"
transform="matrix(0.08199896,0,0,0.08199896,33.468706,139.8312)" /><path
d="m 268.81596,281.41119 c 0,14.10803 -11.43829,25.5463 -25.54631,25.5463 H 134.69889 c -14.10786,0 -25.54614,-11.43827 -25.54614,-25.5463 V 153.68084 c 0,-14.10804 11.43828,-25.54614 25.54614,-25.54614 h 110.71064 c 14.10743,0 23.40643,9.29881 23.40643,23.40686 z"
fill="url(#paint5_linear_5_50)"
id="path20"
style="display:inline;fill:url(#paint5_linear_5_50);stroke-width:0.598737"
transform="matrix(0.08199896,0,0,0.08199896,33.468706,139.8312)" /><path
d="m 134.69889,115.36168 c -10.78045,0 -11.05509,-12.27489 -6.38649,-17.562938 5.31356,-6.009763 13.57133,-7.9832 28.34335,-7.9832 h 9.97556 V 77.042507 h -17.36456 c -25.34831,0 -46.50048,15.96634 -46.50048,34.327563 v 170.04112 c 0,14.10803 11.43827,25.5463 25.54613,25.5463 h 12.77321 V 115.36168 Z"
fill="#226699"
id="path21"
style="display:inline;stroke-width:0.598737"
transform="matrix(0.08199896,0,0,0.08199896,33.468706,139.8312)" /></g></svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>org.hectabit.PageBurger</id>
<name>PageBurger</name>
<summary>Simple, private noting service</summary>
<developer_name>Arzumify</developer_name>
<metadata_license>MIT</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<supports>
<control>pointing</control>
<control>keyboard</control>
<control>touch</control>
</supports>
<description>
<p>
PageBurger is a simple, private-by-default and easy to use noting service. All your notes seamlessly sync across your devices, and are 100% end-to-end encrypted, so no one but you can access it.
</p>
</description>
<launchable type="desktop-id">org.hectabit.PageBurger.desktop</launchable>
<screenshots>
<screenshot type="default">
<image>https://www.hectabit.org/assets/img/screenshot.png</image>
</screenshot>
<screenshot>
<image>https://www.hectabit.org/assets/img/screenshot2.png</image>
</screenshot>
</screenshots>
<url type="homepage">http://notes.hectabit.org/</url>
<project_group>HectaBit</project_group>
<categories>
<category>Office</category>
<category>WordProcessor</category>
</categories>
<provides>
<binary>pageburger</binary>
</provides>
<content_rating type="oars-1.1" />
<releases>
<release version="1.0-1" date="2024-02-16">
<url type="details">https://centrifuge.hectabit.org/HectaBit/PageBurger-App/releases/tag/1.0</url>
<description>
<p>Release 1.0</p>
<ul>
<li>Updated metainfo</li>
<li>Updated app logo</li>
</ul>
</description>
</release>
<release version="1.0" date="2024-02-25">
<url type="details">https://centrifuge.hectabit.org/HectaBit/PageBurger-App/releases/tag/1.0-1</url>
<description>
<p>Initial Release</p>
<ul>
<li>Created program</li>
</ul>
</description>
</release>
</releases>
</component>

View file

@ -1,55 +0,0 @@
<svg width="384" height="384" viewBox="0 0 384 384" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_5_50)">
<path d="M384 277.333C384 300.896 364.896 320 341.333 320H85.3333C61.7707 320 42.6667 300.896 42.6667 277.333V67.3387C42.6667 43.776 104.437 0 128 0H326.667C359.669 0 384 24.6613 384 57.3333V277.333Z" fill="#226699"/>
<path d="M362.667 320C362.667 343.563 343.563 362.667 320 362.667H106.667C83.104 362.667 64 343.563 64 320V64C64 20.064 63.776 21.3333 117.333 21.3333H320C343.563 21.3333 362.667 40.4373 362.667 64V320Z" fill="url(#paint0_linear_5_50)"/>
<path d="M341.333 330.667C341.333 348.341 327.008 362.667 309.333 362.667H74.6667C56.992 362.667 42.6667 348.341 42.6667 330.667V74.6667C42.6667 56.992 56.992 42.6667 74.6667 42.6667H309.333C327.008 42.6667 341.333 56.992 341.333 74.6667V330.667Z" fill="#E1E8ED"/>
<path d="M91.1147 351.776C91.1147 359.264 84 365.333 75.2213 365.333C66.4533 365.333 59.3387 359.264 59.3387 351.776C59.3387 344.299 66.4533 338.219 75.2213 338.219C84 338.219 91.1147 344.288 91.1147 351.776Z" fill="#662113"/>
<path d="M73.536 344.224C68.416 344.811 65.088 348.224 62.688 352C59.4133 357.173 51.9467 362.667 42.6667 362.667C30.8907 362.667 21.3333 355.509 21.3333 346.667C21.3333 337.824 30.8907 330.667 42.6667 330.667V309.376C19.552 309.6 0.885345 326.176 0.885345 346.667C0.885345 367.296 19.7867 384 43.104 384C62.88 384 78.8053 372.853 84.7147 356.597C87.6693 348.501 79.712 343.541 73.536 344.224Z" fill="url(#paint1_linear_5_50)"/>
<path d="M91.1147 266.443C91.1147 273.931 84 280 75.2213 280C66.4533 280 59.3387 273.931 59.3387 266.443C59.3387 258.965 66.4533 252.885 75.2213 252.885C84 252.885 91.1147 258.955 91.1147 266.443Z" fill="#662113"/>
<path d="M73.536 258.891C68.416 259.477 65.088 262.891 62.688 266.667C59.4133 271.84 51.9467 277.333 42.6667 277.333C30.8907 277.333 21.3333 270.176 21.3333 261.333C21.3333 252.491 30.8907 245.333 42.6667 245.333V224.043C19.552 224.267 0.885345 240.843 0.885345 261.333C0.885345 281.963 19.7867 298.667 43.104 298.667C62.88 298.667 78.8053 287.52 84.7147 271.264C87.6693 263.168 79.712 258.208 73.536 258.891Z" fill="url(#paint2_linear_5_50)"/>
<path d="M91.1147 181.109C91.1147 188.597 84 194.667 75.2213 194.667C66.4533 194.667 59.3387 188.597 59.3387 181.109C59.3387 173.632 66.4533 167.552 75.2213 167.552C84 167.552 91.1147 173.621 91.1147 181.109Z" fill="#662113"/>
<path d="M73.536 173.557C68.416 174.144 65.088 177.557 62.688 181.333C59.4133 186.507 51.9467 192 42.6667 192C30.8907 192 21.3333 184.843 21.3333 176C21.3333 167.157 30.8907 160 42.6667 160V138.709C19.552 138.933 0.885345 155.509 0.885345 176C0.885345 196.629 19.7867 213.333 43.104 213.333C62.88 213.333 78.8053 202.187 84.7147 185.931C87.6693 177.835 79.712 172.875 73.536 173.557Z" fill="url(#paint3_linear_5_50)"/>
<path d="M91.1147 95.776C91.1147 103.264 84 109.333 75.2213 109.333C66.4533 109.333 59.3387 103.264 59.3387 95.776C59.3387 88.2987 66.4533 82.2187 75.2213 82.2187C84 82.2187 91.1147 88.288 91.1147 95.776Z" fill="#662113"/>
<path d="M73.536 88.224C68.416 88.8107 65.088 92.224 62.688 96C59.4133 101.173 51.9467 106.667 42.6667 106.667C30.8907 106.667 21.3333 99.5093 21.3333 90.6667C21.3333 81.824 30.8907 74.6667 42.6667 74.6667V53.376C19.5627 53.5893 0.885345 70.176 0.885345 90.6667C0.885345 111.296 19.7867 128 43.104 128C62.88 128 78.8053 116.853 84.7147 100.597C87.6693 92.5013 79.712 87.5413 73.536 88.224Z" fill="url(#paint4_linear_5_50)"/>
<path d="M214 225.771C125.496 225.771 53.7561 223.646 53.7561 286.47C53.7561 349.266 125.496 363.556 214 363.556C302.504 363.556 374.244 349.266 374.244 286.47C374.244 223.655 302.504 225.771 214 225.771Z" fill="#D99E82"/>
<path d="M369.55 230.54C369.55 230.54 291.926 221.247 214 220.85C136.074 221.247 58.45 230.54 58.45 230.54C50.7717 291.683 114.522 316.872 214 316.872C313.478 316.872 377.228 291.683 369.55 230.54Z" fill="#662113"/>
<path d="M364.034 206.098L63.1817 212.199C52.7928 212.199 44.0944 233.251 55.1161 238.757C137.358 264.332 203.469 290.21 203.469 290.21C212.555 295.234 215.624 295.253 224.719 290.238C224.719 290.238 316.009 253.707 374.65 238.36C382.971 236.188 374.414 206.098 364.034 206.098Z" fill="#FFCC4D"/>
<path d="M371.958 206.891C354.014 190.354 355.053 199.156 341.302 195.274C336.079 193.801 298.707 145.493 213.528 145.493H213.339C128.159 145.493 90.7878 193.801 85.565 195.274C71.8139 199.156 72.8528 190.354 54.9083 206.891C46.6728 214.484 44.4439 218.432 53.1328 220.397C66.2228 223.353 65.0328 231.277 74.4111 234.034C85.7633 237.368 90.4289 231.277 108.732 233.77C124.344 235.895 125.364 256.144 141.117 256.144C156.871 256.144 156.871 248.588 172.614 248.588C188.358 248.588 197.671 268.856 213.424 268.856C229.177 268.856 238.48 248.588 254.233 248.588C269.987 248.588 269.987 256.144 285.731 256.144C301.484 256.144 302.504 235.895 318.116 233.77C336.419 231.286 341.094 237.368 352.437 234.034C361.815 231.277 360.625 223.362 373.715 220.397C382.423 218.442 380.203 214.484 371.958 206.891Z" fill="#77B255"/>
<path d="M365.838 189.022C365.838 217.204 297.857 230.512 214 230.512C130.143 230.512 62.1617 217.204 62.1617 189.022C62.1617 137.994 71.285 137.994 214 137.994C356.715 137.994 365.838 138.003 365.838 189.022Z" fill="#DD2E44"/>
<path d="M214 37.9489C125.496 37.9489 53.7561 79.4194 53.7561 142.234C53.7561 200.082 125.496 202.443 214 202.443C302.504 202.443 374.244 200.082 374.244 142.234C374.244 79.41 302.504 37.9489 214 37.9489Z" fill="#D99E82"/>
<path d="M145.849 67.8972C141.146 64.8844 134.903 66.2633 131.899 70.9667C128.896 75.67 130.266 81.9222 134.969 84.9161C139.672 87.9289 151.591 90.1767 154.604 85.4733C157.607 80.77 150.552 70.9006 145.849 67.8972ZM237.781 58.1222C232.473 59.8411 223.152 67.6233 224.88 72.9311C226.608 78.2389 238.707 79.0511 244.014 77.3322C249.322 75.6133 252.222 69.9089 250.493 64.6011C248.774 59.3028 243.07 56.3939 237.781 58.1222ZM340.811 124.564C336.542 120.975 325.841 126.689 322.243 130.958C318.654 135.236 319.211 141.602 323.48 145.191C327.749 148.779 334.124 148.222 337.713 143.953C341.311 139.675 345.089 128.153 340.811 124.564ZM306.404 77.3417C301.701 74.3383 295.458 75.7172 292.446 80.4206C289.442 85.1239 290.821 91.3667 295.524 94.37C300.228 97.3828 312.147 99.6306 315.15 94.9272C318.163 90.2144 311.108 80.345 306.404 77.3417ZM164.738 143.453C160.034 140.449 153.792 141.828 150.779 146.532C147.776 151.226 149.154 157.478 153.858 160.472C158.561 163.484 170.48 165.742 173.483 161.029C176.496 156.326 169.441 146.456 164.738 143.453ZM193.506 98.0439C190.332 102.634 187.65 114.468 192.249 117.641C196.839 120.814 206.954 114.109 210.128 109.519C213.301 104.929 212.139 98.6389 207.549 95.4656C202.969 92.2922 196.669 93.4539 193.506 98.0439ZM268.627 143.453C263.923 140.449 257.681 141.828 254.668 146.532C251.664 151.226 253.043 157.487 257.747 160.472C262.45 163.484 274.369 165.742 277.372 161.029C280.385 156.326 273.33 146.456 268.627 143.453ZM90.7311 106.742C87.01 110.907 82.8639 122.307 87.0289 126.028C91.175 129.749 102.055 124.384 105.776 120.219C109.507 116.064 109.148 109.679 104.992 105.949C100.846 102.228 94.4522 102.587 90.7311 106.742Z" fill="#FFE8B6"/>
</g>
<path d="M341.333 341.333C341.333 364.896 322.229 384 298.667 384H96C72.4373 384 53.3333 364.896 53.3333 341.333V106.667C53.3333 83.104 72.4373 64 96 64H298.667C322.229 64 341.333 83.104 341.333 106.667V341.333Z" fill="#3B88C3"/>
<path d="M320 341.333C320 364.896 300.896 384 277.333 384H96C72.4373 384 53.3333 364.896 53.3333 341.333V128C53.3333 104.437 72.4373 85.3333 96 85.3333H280.907C304.469 85.3333 320 100.864 320 124.427V341.333Z" fill="url(#paint5_linear_5_50)"/>
<path d="M96 64C77.9947 64 77.536 43.4987 85.3334 34.6667C94.208 24.6293 108 21.3333 132.672 21.3333H149.333V0H120.331C77.9947 0 42.6667 26.6667 42.6667 57.3333V341.333C42.6667 364.896 61.7707 384 85.3334 384H106.667V64H96Z" fill="#226699"/>
<defs>
<linearGradient id="paint0_linear_5_50" x1="213.333" y1="21.3295" x2="213.333" y2="362.667" gradientUnits="userSpaceOnUse">
<stop stop-color="#CCD6DD"/>
<stop offset="1" stop-color="#CCD6DD" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint1_linear_5_50" x1="43.118" y1="309.376" x2="43.118" y2="384" gradientUnits="userSpaceOnUse">
<stop stop-color="#66757F"/>
<stop offset="1" stop-color="#50585C"/>
<stop offset="1" stop-color="#50585C"/>
</linearGradient>
<linearGradient id="paint2_linear_5_50" x1="43.118" y1="224.043" x2="43.118" y2="298.667" gradientUnits="userSpaceOnUse">
<stop stop-color="#66757F"/>
<stop offset="1" stop-color="#50585C"/>
</linearGradient>
<linearGradient id="paint3_linear_5_50" x1="43.118" y1="138.709" x2="43.118" y2="213.333" gradientUnits="userSpaceOnUse">
<stop stop-color="#66757F"/>
<stop offset="1" stop-color="#50585C"/>
</linearGradient>
<linearGradient id="paint4_linear_5_50" x1="43.118" y1="53.376" x2="43.118" y2="128" gradientUnits="userSpaceOnUse">
<stop stop-color="#66757F"/>
<stop offset="1" stop-color="#50585C"/>
</linearGradient>
<linearGradient id="paint5_linear_5_50" x1="186.667" y1="85.3333" x2="186.667" y2="384" gradientUnits="userSpaceOnUse">
<stop stop-color="#55ACEE"/>
<stop offset="1" stop-color="#55ACEE" stop-opacity="0"/>
</linearGradient>
<clipPath id="clip0_5_50">
<rect width="384" height="384" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 9.1 KiB

View file

@ -1,38 +0,0 @@
#include <webkit2/webkit2.h>
#include <gtk/gtk.h>
static void cookie_changed_cb(WebKitCookieManager *cookie_manager, GParamSpec *pspec, gpointer user_data) {
// Handle cookie changes here
g_print("Cookie changed\n");
}
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
// Create a new window
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "PageBurger");
gtk_window_set_default_size(GTK_WINDOW(window), 1000, 600);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
// Create a web view widget
WebKitWebView *webview = WEBKIT_WEB_VIEW(webkit_web_view_new());
// Load a web page
webkit_web_view_load_uri(webview, "https://notes.hectabit.org/app");
// Add the web view to the window
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(webview));
// Show all widgets
gtk_widget_show_all(window);
// Connect signals for handling cookies
WebKitCookieManager *cookie_manager = webkit_web_context_get_cookie_manager(webkit_web_view_get_context(webview));
g_signal_connect(cookie_manager, "notify::cookie-accept-policy", G_CALLBACK(cookie_changed_cb), NULL);
// Run the main GTK event loop
gtk_main();
return 0;
}

15
webkit-4.1/.gitignore vendored Normal file
View file

@ -0,0 +1,15 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/

15
webkit-4.1/CHANGELOG.md Normal file
View file

@ -0,0 +1,15 @@
# Changelog
### Migrating from v0.1.1 to v0.10.0
1. `Webview.Open()` has been removed. Use other webview APIs to create a window, open a link and run main UI loop.
2. `Webview.Debug()` and `webview.Debugf()` have been removed. Use your favorite logging library to debug webview apps.
3. `Webview.Settings` struct has been removed. Title, URL and size are controlled via other API setters and can be updated at any time, not only when webview is created.
4. `Webview.Loop()` has been removed. Use `Run()` instead.
5. `WebView.Run()`, `WebView.Terminate()`, `WebView.SetTitle()`, `WebView.Dispatch()` stayed the same.
6. `WebView.Exit()` has been renamed to `WebView.Destroy()`
7. `WebView.SetColor()` and `WebView.SetFullScreen()` have been removed. Use `Window()` to get native window handle and probably write some Cgo code to adjust native window to your taste.
8. `Webview.Dialog` has been removed. But it is likely to be brought back as a standalone module.
9. `WebView.Eval()` remained the same.
10. `WebView.InjectCSS()` has been removed. Use eval to inject style tag with CSS inside.
11. `WebView.Bind()` kept the name, but changed the semantics. Only functions can be bound. Not the structs, like in Lorca.

22
webkit-4.1/LICENSE Normal file
View file

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2017 Serge Zaitsev
Copyright (c) 2020 webview
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

51
webkit-4.1/README.md Normal file
View file

@ -0,0 +1,51 @@
# webview_go-4.1
[![GoDoc](https://godoc.org/github.com/arzumify/webview_go-4.1?status.svg)](https://godoc.org/github.com/arzumify/webview_go-4.1)
[![Go Report Card](https://goreportcard.com/badge/github.com/arzumify/webview_go-4.1)](https://goreportcard.com/report/github.com/webview/webview_go)
Go language binding for the [webview library][webview], for webkitgtk-4.1.
This is entirely backwards compatible with webview_go 4.0, and needs only a dependency replacement.
> [!NOTE]
> Versions <= 0.1.1 are available in the [old repository][webview].
### Getting Started
See [Go package documentation][go-docs] for the Go API documentation, or simply read the source code.
Start with creating a new directory structure for your project.
```sh
mkdir my-project && cd my-project
```
Create a new Go module.
```sh
go mod init example.com/app
```
Save one of the example programs into your project directory.
```sh
curl -sSLo main.go "https://raw.githubusercontent.com/arzumify/webview_go-4.1/master/examples/basic/main.go"
```
Install dependencies.
```sh
go get github.com/webview/webview_go
```
Build the example. On Windows, add `-ldflags="-H windowsgui"` to the command line.
```sh
go build
```
### Notes
Calling `Eval()` or `Dispatch()` before `Run()` does not work because the webview instance has only been configured and not yet started.
[go-docs]: https://pkg.go.dev/github.com/arzumify/webview_go-4.1
[webview]: https://github.com/webview/webview

View file

@ -0,0 +1,12 @@
package main
import webview "github.com/webview/webview_go"
func main() {
w := webview.New(false)
defer w.Destroy()
w.SetTitle("Basic Example")
w.SetSize(480, 320, webview.HintNone)
w.SetHtml("Thanks for using webview!")
w.Run()
}

View file

@ -0,0 +1,38 @@
package main
import webview "github.com/webview/webview_go"
const html = `<button id="increment">Tap me</button>
<div>You tapped <span id="count">0</span> time(s).</div>
<script>
const [incrementElement, countElement] =
document.querySelectorAll("#increment, #count");
document.addEventListener("DOMContentLoaded", () => {
incrementElement.addEventListener("click", () => {
window.increment().then(result => {
countElement.textContent = result.count;
});
});
});
</script>`
type IncrementResult struct {
Count uint `json:"count"`
}
func main() {
var count uint = 0
w := webview.New(false)
defer w.Destroy()
w.SetTitle("Bind Example")
w.SetSize(480, 320, webview.HintNone)
// A binding that increments a value and immediately returns the new value.
w.Bind("increment", func() IncrementResult {
count++
return IncrementResult{Count: count}
})
w.SetHtml(html)
w.Run()
}

36
webkit-4.1/glue.c Normal file
View file

@ -0,0 +1,36 @@
#include "webview.h"
#include <stdlib.h>
#include <stdint.h>
struct binding_context {
webview_t w;
uintptr_t index;
};
void _webviewDispatchGoCallback(void *);
void _webviewBindingGoCallback(webview_t, char *, char *, uintptr_t);
static void _webview_dispatch_cb(webview_t w, void *arg) {
_webviewDispatchGoCallback(arg);
}
static void _webview_binding_cb(const char *id, const char *req, void *arg) {
struct binding_context *ctx = (struct binding_context *) arg;
_webviewBindingGoCallback(ctx->w, (char *)id, (char *)req, ctx->index);
}
void CgoWebViewDispatch(webview_t w, uintptr_t arg) {
webview_dispatch(w, _webview_dispatch_cb, (void *)arg);
}
void CgoWebViewBind(webview_t w, const char *name, uintptr_t index) {
struct binding_context *ctx = calloc(1, sizeof(struct binding_context));
ctx->w = w;
ctx->index = index;
webview_bind(w, name, _webview_binding_cb, (void *)ctx);
}
void CgoWebViewUnbind(webview_t w, const char *name) {
webview_unbind(w, name);
}

3
webkit-4.1/go.mod Normal file
View file

@ -0,0 +1,3 @@
module github.com/arzumify/webview_go-4.1
go 1.13

0
webkit-4.1/go.sum Normal file
View file

View file

@ -0,0 +1,27 @@
Copyright (C) Microsoft Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* The name of Microsoft Corporation, or the names of its contributors
may not be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
1.0.1150.38

View file

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2017 Serge Zaitsev
Copyright (c) 2022 Steffen André Langnes
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
fb6b17d826041411e6346cd9a785a5ceba7987c4

1
webkit-4.1/webview.cc Normal file
View file

@ -0,0 +1 @@
#include "webview.h"

327
webkit-4.1/webview.go Normal file
View file

@ -0,0 +1,327 @@
package webview
/*
#cgo CFLAGS: -I${SRCDIR}/libs/webview/include
#cgo CXXFLAGS: -I${SRCDIR}/libs/webview/include -DWEBVIEW_STATIC
#cgo linux openbsd freebsd netbsd CXXFLAGS: -DWEBVIEW_GTK -std=c++11
#cgo linux openbsd freebsd netbsd LDFLAGS: -ldl
#cgo linux openbsd freebsd netbsd pkg-config: gtk+-3.0 webkit2gtk-4.1
#cgo darwin CXXFLAGS: -DWEBVIEW_COCOA -std=c++11
#cgo darwin LDFLAGS: -framework WebKit -ldl
#cgo windows CXXFLAGS: -DWEBVIEW_EDGE -std=c++14 -I${SRCDIR}/libs/mswebview2/include
#cgo windows LDFLAGS: -static -ladvapi32 -lole32 -lshell32 -lshlwapi -luser32 -lversion
#include "webview.h"
#include <stdlib.h>
#include <stdint.h>
void CgoWebViewDispatch(webview_t w, uintptr_t arg);
void CgoWebViewBind(webview_t w, const char *name, uintptr_t index);
void CgoWebViewUnbind(webview_t w, const char *name);
*/
import "C"
import (
"encoding/json"
"errors"
"reflect"
"runtime"
"sync"
"unsafe"
)
func init() {
// Ensure that main.main is called from the main thread
runtime.LockOSThread()
}
// Hints are used to configure window sizing and resizing
type Hint int
const (
// Width and height are default size
HintNone = C.WEBVIEW_HINT_NONE
// Window size can not be changed by a user
HintFixed = C.WEBVIEW_HINT_FIXED
// Width and height are minimum bounds
HintMin = C.WEBVIEW_HINT_MIN
// Width and height are maximum bounds
HintMax = C.WEBVIEW_HINT_MAX
)
type WebView interface {
// Run runs the main loop until it's terminated. After this function exits -
// you must destroy the webview.
Run()
// Terminate stops the main loop. It is safe to call this function from
// a background thread.
Terminate()
// Dispatch posts a function to be executed on the main thread. You normally
// do not need to call this function, unless you want to tweak the native
// window.
Dispatch(f func())
// Destroy destroys a webview and closes the native window.
Destroy()
// Window returns a native window handle pointer. When using GTK backend the
// pointer is GtkWindow pointer, when using Cocoa backend the pointer is
// NSWindow pointer, when using Win32 backend the pointer is HWND pointer.
Window() unsafe.Pointer
// SetTitle updates the title of the native window. Must be called from the UI
// thread.
SetTitle(title string)
// SetSize updates native window size. See Hint constants.
SetSize(w int, h int, hint Hint)
// Navigate navigates webview to the given URL. URL may be a properly encoded data.
// URI. Examples:
// w.Navigate("https://github.com/webview/webview")
// w.Navigate("data:text/html,%3Ch1%3EHello%3C%2Fh1%3E")
// w.Navigate("data:text/html;base64,PGgxPkhlbGxvPC9oMT4=")
Navigate(url string)
// SetHtml sets the webview HTML directly.
// Example: w.SetHtml(w, "<h1>Hello</h1>");
SetHtml(html string)
// Init injects JavaScript code at the initialization of the new page. Every
// time the webview will open a the new page - this initialization code will
// be executed. It is guaranteed that code is executed before window.onload.
Init(js string)
// Eval evaluates arbitrary JavaScript code. Evaluation happens asynchronously,
// also the result of the expression is ignored. Use RPC bindings if you want
// to receive notifications about the results of the evaluation.
Eval(js string)
// Bind binds a callback function so that it will appear under the given name
// as a global JavaScript function. Internally it uses webview_init().
// Callback receives a request string and a user-provided argument pointer.
// Request string is a JSON array of all the arguments passed to the
// JavaScript function.
//
// f must be a function
// f must return either value and error or just error
Bind(name string, f interface{}) error
// Removes a callback that was previously set by Bind.
Unbind(name string) error
}
type webview struct {
w C.webview_t
}
var (
m sync.Mutex
index uintptr
dispatch = map[uintptr]func(){}
bindings = map[uintptr]func(id, req string) (interface{}, error){}
)
func boolToInt(b bool) C.int {
if b {
return 1
}
return 0
}
// New calls NewWindow to create a new window and a new webview instance. If debug
// is non-zero - developer tools will be enabled (if the platform supports them).
func New(debug bool) WebView { return NewWindow(debug, nil) }
// NewWindow creates a new webview instance. If debug is non-zero - developer
// tools will be enabled (if the platform supports them). Window parameter can be
// a pointer to the native window handle. If it's non-null - then child WebView is
// embedded into the given parent window. Otherwise a new window is created.
// Depending on the platform, a GtkWindow, NSWindow or HWND pointer can be passed
// here.
func NewWindow(debug bool, window unsafe.Pointer) WebView {
w := &webview{}
w.w = C.webview_create(boolToInt(debug), window)
return w
}
func (w *webview) Destroy() {
C.webview_destroy(w.w)
}
func (w *webview) Run() {
C.webview_run(w.w)
}
func (w *webview) Terminate() {
C.webview_terminate(w.w)
}
func (w *webview) Window() unsafe.Pointer {
return C.webview_get_window(w.w)
}
func (w *webview) Navigate(url string) {
s := C.CString(url)
defer C.free(unsafe.Pointer(s))
C.webview_navigate(w.w, s)
}
func (w *webview) SetHtml(html string) {
s := C.CString(html)
defer C.free(unsafe.Pointer(s))
C.webview_set_html(w.w, s)
}
func (w *webview) SetTitle(title string) {
s := C.CString(title)
defer C.free(unsafe.Pointer(s))
C.webview_set_title(w.w, s)
}
func (w *webview) SetSize(width int, height int, hint Hint) {
C.webview_set_size(w.w, C.int(width), C.int(height), C.webview_hint_t(hint))
}
func (w *webview) Init(js string) {
s := C.CString(js)
defer C.free(unsafe.Pointer(s))
C.webview_init(w.w, s)
}
func (w *webview) Eval(js string) {
s := C.CString(js)
defer C.free(unsafe.Pointer(s))
C.webview_eval(w.w, s)
}
func (w *webview) Dispatch(f func()) {
m.Lock()
for ; dispatch[index] != nil; index++ {
}
dispatch[index] = f
m.Unlock()
C.CgoWebViewDispatch(w.w, C.uintptr_t(index))
}
//export _webviewDispatchGoCallback
func _webviewDispatchGoCallback(index unsafe.Pointer) {
m.Lock()
f := dispatch[uintptr(index)]
delete(dispatch, uintptr(index))
m.Unlock()
f()
}
//export _webviewBindingGoCallback
func _webviewBindingGoCallback(w C.webview_t, id *C.char, req *C.char, index uintptr) {
m.Lock()
f := bindings[uintptr(index)]
m.Unlock()
jsString := func(v interface{}) string { b, _ := json.Marshal(v); return string(b) }
status, result := 0, ""
if res, err := f(C.GoString(id), C.GoString(req)); err != nil {
status = -1
result = jsString(err.Error())
} else if b, err := json.Marshal(res); err != nil {
status = -1
result = jsString(err.Error())
} else {
status = 0
result = string(b)
}
s := C.CString(result)
defer C.free(unsafe.Pointer(s))
C.webview_return(w, id, C.int(status), s)
}
func (w *webview) Bind(name string, f interface{}) error {
v := reflect.ValueOf(f)
// f must be a function
if v.Kind() != reflect.Func {
return errors.New("only functions can be bound")
}
// f must return either value and error or just error
if n := v.Type().NumOut(); n > 2 {
return errors.New("function may only return a value or a value+error")
}
binding := func(id, req string) (interface{}, error) {
raw := []json.RawMessage{}
if err := json.Unmarshal([]byte(req), &raw); err != nil {
return nil, err
}
isVariadic := v.Type().IsVariadic()
numIn := v.Type().NumIn()
if (isVariadic && len(raw) < numIn-1) || (!isVariadic && len(raw) != numIn) {
return nil, errors.New("function arguments mismatch")
}
args := []reflect.Value{}
for i := range raw {
var arg reflect.Value
if isVariadic && i >= numIn-1 {
arg = reflect.New(v.Type().In(numIn - 1).Elem())
} else {
arg = reflect.New(v.Type().In(i))
}
if err := json.Unmarshal(raw[i], arg.Interface()); err != nil {
return nil, err
}
args = append(args, arg.Elem())
}
errorType := reflect.TypeOf((*error)(nil)).Elem()
res := v.Call(args)
switch len(res) {
case 0:
// No results from the function, just return nil
return nil, nil
case 1:
// One result may be a value, or an error
if res[0].Type().Implements(errorType) {
if res[0].Interface() != nil {
return nil, res[0].Interface().(error)
}
return nil, nil
}
return res[0].Interface(), nil
case 2:
// Two results: first one is value, second is error
if !res[1].Type().Implements(errorType) {
return nil, errors.New("second return value must be an error")
}
if res[1].Interface() == nil {
return res[0].Interface(), nil
}
return res[0].Interface(), res[1].Interface().(error)
default:
return nil, errors.New("unexpected number of return values")
}
}
m.Lock()
for ; bindings[index] != nil; index++ {
}
bindings[index] = binding
m.Unlock()
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
C.CgoWebViewBind(w.w, cname, C.uintptr_t(index))
return nil
}
func (w *webview) Unbind(name string) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
C.CgoWebViewUnbind(w.w, cname)
return nil
}

View file

@ -0,0 +1,50 @@
package webview
import (
"flag"
"log"
"os"
"testing"
)
func Example() {
w := New(true)
defer w.Destroy()
w.SetTitle("Hello")
w.Bind("noop", func() string {
log.Println("hello")
return "hello"
})
w.Bind("add", func(a, b int) int {
return a + b
})
w.Bind("quit", func() {
w.Terminate()
})
w.SetHtml(`<!doctype html>
<html>
<body>hello</body>
<script>
window.onload = function() {
document.body.innerText = ` + "`hello, ${navigator.userAgent}`" + `;
noop().then(function(res) {
console.log('noop res', res);
add(1, 2).then(function(res) {
console.log('add res', res);
quit();
});
});
};
</script>
</html>
)`)
w.Run()
}
func TestMain(m *testing.M) {
flag.Parse()
if testing.Verbose() {
Example()
}
os.Exit(m.Run())
}

87
website/app/index.html Normal file
View file

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Burgernotes</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="/static/css/style.css" />
<script type="text/javascript" src="/static/js/crypto-js.js"></script>
<script type="text/javascript" src="/static/js/marked.js"></script>
<link rel="icon" href="/static/svg/favicon.svg">
</head>
<body>
<div class="topBar">
<p tabindex="0" class="logo" id="burgerButton">Burgernotes</p>
<p tabindex="0" id="usernameBox" class="usernameBox"></p>
</div>
<div class="bottomBar">
<button id="removeBox" class="removeButton"></button>
<button id="wordCountBox">0 words</button>
<button onclick="toggleMarkdown()">Toggle Markdown</button>
<div class="textManipulator">
<button id="textMinusBox">-</button>
<button id="textSizeBox">16px</button>
<button id="textPlusBox">+</button>
</div>
</div>
<div id="notesBar" class="notesBar">
<button id="newNote" class="newNote"><img id="newNoteImage" draggable="false" alt=""
src="/static/svg/add.svg">New note</button>
<div id="notesDiv" class="notesDiv">
<button class="loadingStuff" id="loadingStuff"></button>
</div>
</div>
<div id="optionsCoverDiv" class="optionsCoverDiv hidden">
<div id="optionsDiv" class="optionsDiv hidden">
<button class="exit" id="exitThing">X</button>
<h3 class="w300">Your account</h3>
<p id="usernameThing"></p>
<p id="passwordThing"></p>
<div class="section"></div>
<p>Storage</p>
<progress id="storageProgressThing" value="0" max="100"></progress><br>
<p id="storageThing"></p>
<div class="section"></div>
<p>Account managment</p>
<button id="deleteMyAccountButton"><img src="/static/svg/delete_forever.svg" alt="">Delete my account</button>
<button id="exportNotesButton"><img src="/static/svg/download.svg" alt="">Export notes</button>
<button id="sessionManagerButton"><img src="/static/svg/list.svg" alt="">Session manager</button>
<button class="lastButton" id="logOutButton"><img src="/static/svg/logout.svg" alt="">Log out</button>
</div>
<div id="sessionManagerDiv" class="optionsDiv hidden">
<button class="exit" id="exitSessionsThing">X</button>
<h3 class="w300">Session manager</h3>
<p>Manage your sessions</p>
<div class="section"></div>
<div class="sessionDiv" id="sessionDiv">
</div>
</div>
<div id="errorDiv" class="optionsDiv hidden">
<p id="errorMessageThing"></p>
<input class="hidden" id="errorInput" type="text" placeholder=""><br>
<button class="normalButton" id="closeErrorButton">Ok</button>
<button class="normalButton hidden" id="cancelErrorButton">Cancel</button>
</div>
</div>
<div class="noteBox">
<textarea id="noteBox" class="noteBoxText"></textarea>
<iframe id="markdown" style="display: none;" sandbox="allow-scripts"></iframe>
</div>
<script type="text/javascript" src="/static/js/main.js"></script>
<script>
for (let i = 0; i < 40; i++) {
notesDiv.appendChild(loadingStuff.cloneNode())
}
loadingStuff.remove()
</script>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Signup - Burgernotes</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="../static/css/style.css">
<link rel="icon" href="/static/svg/favicon.svg">
<script src="/static/js/hash-wasm.js"></script>
</head>
<body>
<p class="credit">Image by perga (@pergagreen on discord)</p>
<img src="/static/img/background.jpg" class="background" alt="">
<div class="inoutdiv">
<h2 class="w300">Homeserver</h2>
<p>Change your Burgernotes homeserver</p>
<p id="statusBox"></p>
<input type="text" value="https://" id="homeserverBox"><br>
<button id="changeButton">Change</button><br><br>
<p>Please put in the URL in standard format; https://, http://, etc.</p>
</div>
<script type="text/javascript" src="/static/js/homeserver.js"></script>
</body>
</html>

1
website/index.html Normal file
View file

@ -0,0 +1 @@
<!DOCTYPE html><html><head><title>Burgernotes</title><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta http-equiv="refresh" content="0; url=/app"><head>Redirecting...<script>window.location.replace("/app")</script>

33
website/login/index.html Normal file
View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Login - Burgernotes</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="/static/css/style.css" />
<script src="/static/js/hash-wasm.js"></script>
<link rel="icon" href="/static/svg/favicon.svg">
</head>
<body>
<p class="credit">Image by perga (@pergagreen on discord)</p>
<img src="/static/img/background.jpg" class="background" alt="">
<div class="inoutdiv">
<h2 class="w300">Login</h2>
<p id="statusBox"></p>
<span id="inputNameBox" style="margin-right: 10px;color: var(--text-color);"></span>
<input id="usernameBox" class="hidden" type="text" placeholder="Enter your username">
<input id="passwordBox" class="hidden" type="password" placeholder="Enter your password">
<button id="signupButton">Next</button>
<button id="backButton" class="hidden">Back</button>
<br>
<br>
<p>Don't have an account? If so, <a href="/signup/">Create one here!</a></p>
<div style="display: flex;"><p id="homeserver">Your homeserver is loading... </p><div style="display: flex;flex-direction: column;justify-content: center;"><a href="/homeserver">Change</a></div></div>
<a href="/privacy/">Privacy &amp; Terms</a>
</div>
<script type="text/javascript" src="../static/js/login.js"></script>
</body>

16
website/logout/index.html Normal file
View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Burgernotes</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="icon" href="/static/svg/favicon.svg">
</head>
<p>Logging out...</p>
<script>
localStorage.removeItem("DONOTSHARE-secretkey")
localStorage.removeItem("DONOTSHARE-password")
localStorage.removeItem("CACHE-username")
window.location.replace("/login")
</script>

View file

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Burgernotes Privacy &amp; Terms</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="/static/css/style.css" />
<link rel="icon" href="/static/svg/favicon.svg">
</head>
<body>
<h1 class="w300">Burgernotes Privacy Policy &amp; Terms & Conditions</h1>
<h2 class="w300">Preamble</h2>
<p><i>Please note that I am not a lawyer, please don't expect too much of this policy :3</i></p>
<p>Welcome to the Burgernotes privacy policy! Burgernotes is <a
href="https://centrifuge.hectabit.org/hectabit/burgernotes">free & open source</a> software licensed under <a
href="https://www.gnu.org/licenses/agpl-3.0.en.html">GNU AGPL-3.0</a>.</p>
<h2 class="w300">Information collected when signing up</h2>
<p>When signing up for an account, we collect and store the following information:</p>
<ul>
<li>Username, and your password hashed</li>
<li>Date of creating account</li>
<li>Web browser "User Agent"</li>
</ul>
<h2 class="w300">Information collected when logging in</h2>
<p>When logging back in to your account, we collect and store the following information:</p>
<ul>
<li>Web browser "User agent"</li>
</ul>
<h2 class="w300">Information we collect while using our services</h2>
<p>When you create a note, we collect and use this information:</p>
<ul>
<li>Encrypted note content and title</li>
<li>Note creator</li>
<li>Note creation date</li>
<li>Note last edited date</li>
</ul>
<p>When you edit a note, we collect and use this information:</p>
<ul>
<li>Encrypted note content and title</li>
<li>Note last edited date</li>
</ul>
<h2 class="w300">How we use your data</h2>
<p>We use your data to make our services work. We don't share your information with third-parties.</p>
<h2 class="w300">We can't see the content and title of the notes you create</h2>
<p>Your notes are <a href="https://en.wikipedia.org/wiki/End-to-end_encryption">encrypted end-to-end</a> using AES
(Advanced Encryption Standard) 256-bit encryption.</p>
<p>We can only see:</p>
<ul>
<li>Note creation date</li>
<li>Note last edited date</li>
<li>Note creator</li>
</ul>
<p>Not note content or title.</p>
<h2 class="w300">We don't sell your data</h2>
<p>We don't sell or share your data to advertisers or third-parties.</p>
<h2 class="w300">Liability</h2>
<p>We take no responsibility for the use of burgernotes, or any external instances provided by third-parties. We
refuse liability for any inappropriate or illegal use of burgernotes.</p>
<p>You may view the AGPL-3.0 license which this software is provided to you with. A copy of the section is below.</p>
<p>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.</p>
<br>
<button onclick="if(document.referrer!==' '){if(document.referrer!==''){window.location.href=document.referrer;}else{window.location.href='/';}window.location.href=document.referrer; }else{window.location.href='../index.html';}" style="cursor: pointer; padding: 15px 20px;margin-right: auto;color: white;text-decoration: none;background-color: var(--theme-color);border-radius: 8px;border: medium;font-size: 15px;">Take me back where I was!</button>
<br><br>
</body>
<style>
body {
margin-left: 15px;
}
</style>
</html>

30
website/signup/index.html Normal file
View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Signup - Burgernotes</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="/static/css/style.css" />
<script src="/static/js/hash-wasm.js"></script>
<link rel="icon" href="/static/svg/favicon.svg">
</head>
<body>
<p class="credit">Image by perga (@pergagreen on discord)</p>
<img src="/static/img/background.jpg" class="background" alt="">
<div class="inoutdiv">
<h2 class="w300">Signup</h2>
<p>Signup for a Burgernotes account</p>
<p id="statusBox"></p>
<input id="usernameBox" type="text" placeholder="Username">
<input id="passwordBox" type="password" placeholder="Password"><br>
<button id="signupButton">Signup</button><br><br>
<p>Already have an account? If so, <a href="/login/">Login</a> instead!</p>
<p>Please note that it's impossible to reset your password, do not forget it!</p>
<div style="display: flex;"><p id="homeserver">Your homeserver is loading... </p><div style="display: flex;flex-direction: column;justify-content: center;"><a href="/homeserver">Change</a></div></div>
<a href="/privacy/">Privacy &amp; Terms</a>
</div>
<script type="text/javascript" src="/static/js/signup.js"></script>
</body>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,728 @@
@import url("../fonts/inter.css");
:root {
--contrast: #eee;
--contrast2: #fff;
--invertdm: 0%;
--bar: #f4f4f4;
--editor: #ffffff;
--text-color: #000000;
--border-color: #dadada;
--theme-color: #157efb;
--theme-text-color: #ffffff;
--exit-color: #e9e9e9;
--session-color: #f4f4f4;
--note-button: #ffffff;
--note-button-text-color: #ffffff;
--unselected-note-button-text-color: #000000;
--option-background: #ffffff;
--invert: 100%;
--bottomBarHover: #e4e4e4;
}
/* dark mode */
@media (prefers-color-scheme: dark) {
:root {
--invertdm: 100%;
--contrast: #2d2f21;
--contrast2: #2d2f21;
--bar: #2d2f31;
--editor: #202124;
--text-color: #ffffff;
--border-color: #393b3d;
--theme-color: #157efb;
--theme-text-color: #ffffff;
--exit-color: #454649;
--session-color: #2d2f31;
--note-button: #202124;
--note-button-text-color: #ffffff;
--unselected-note-button-text-color: #ffffff;
--option-background: #202124;
--invert: 100%;
--bottomBarHover: #e4e4e4;
}
.startDiv p {
color: white !important;
}
.topBar p {
color: white !important;
}
.newNote {
color: white !important;
}
.newNote img {
filter: invert(100%);
}
#errorDiv p {
color: white !important;
}
.optionsCoverDiv p {
color: white !important;
}
.burgerSession img {
filter: invert(100%) !important;
}
.links a {
color: white !important;
}
.inoutdiv p {
color: white !important;
}
.inoutdiv a {
color: #969696 !important;
}
.inoutdiv input {
color: white;
background-color: var(--editor);
}
.flathubLogo {
filter: invert(100%);
}
.feature {
background-color: rgba(0, 0, 0, 0) !important;
color: var(--text-color);
}
.mainDiv .yellow {
border-color: #e9e98d !important;
}
.mainDiv .green {
border-color: #a9f9a9 !important;
}
}
p,
li,
h1,
h2,
h3,
h4,
h5,
h6 {
color: var(--text-color);
white-space: break-spaces;
}
h7 {
display: block;
font-size: 20px;
margin-top: 0.67em;
margin-bottom: 0.67em;
margin-left: 0;
margin-right: 0;
}
body {
margin: 0;
background-color: var(--editor);
font-family: "Inter", sans-serif;
}
.hiddenButton {
right: 0px;
position: fixed;
background-color: var(--editor);
color: var(--editor);
padding: 20px;
}
/* Web app */
.topBar {
position: fixed;
width: 100%;
height: 50px;
background-color: var(--bar);
border: solid;
border-color: var(--border-color);
border-width: 0px;
border-bottom-width: 1px;
}
.bottomBar {
position: fixed;
width: 100%;
height: 29px;
bottom: 0;
background-color: var(--bar);
border: solid;
border-color: var(--border-color);
border-width: 0px;
border-top-width: 1px;
display: flex;
}
.bottomBar button {
background-color: rgba(0, 0, 0, 0);
color: var(--text-color);
height: 100%;
border: none;
font-size: 14px;
padding-left: 7.5px;
padding-right: 7.5px;
}
.bottomBar .removeButton {
filter: invert(var(--invertdm));
padding-left: 17.5px;
padding-right: 17.5px;
background-image: url("../../static/svg/delete.svg");
background-position: center;
background-repeat: no-repeat;
background-size: 55%;
}
.bottomBar .textManipulator {
margin-left: auto;
}
.bottomBar button:hover {
background-color: var(--bottomBarHover);
}
.bottomBar .right {
float: right;
}
.burgerDropdown {
position: fixed;
z-index: 2;
left: 7px;
top: 30px;
width: 160px;
height: 90px;
background-color: var(--bar);
border: solid;
border-color: var(--border-color);
border-width: 1px;
border-radius: 8px;
}
.burgerDropdown a {
position: absolute;
width: calc(100% - 14px - 4px - 7px);
color: var(--text-color);
background-color: #ffffff;
height: 35px;
line-height: 35px;
margin: 7px;
padding-left: 7px;
border: solid;
border-color: var(--border-color);
border-width: 1px;
border-radius: 8px;
font-size: 15px;
text-decoration: none;
}
.topBar p {
display: inline-block;
}
.topBar .logo {
padding-left: 12px;
}
.topBar .usernameBox {
text-align: right;
position: absolute;
cursor: pointer;
right: 12px;
}
.notesBar {
position: fixed;
width: 180px;
top: 50px;
height: calc(100% - 50px - 30px - 1px);
background-color: var(--bar);
border: solid;
border-color: var(--border-color);
border-width: 0px;
border-right-width: 1px;
border-top-width: 1px;
}
.notesDiv {
height: calc(100% - 50px);
overflow-y: scroll;
}
.notesBar .noteButton, .notesBar .loadingStuff {
width: calc(100% - 7px - 7px - 3.5px);
height: 35px;
line-height: 0px;
padding: 10px;
margin: 5px;
margin-bottom: 0;
background-color: var(--note-button);
color: var(--unselected-note-button-text-color);
border-radius: 8px;
border: solid;
border-color: var(--border-color);
border-width: 1px;
font-size: 15px;
text-align: left;
cursor: pointer;
white-space: nowrap;
overflow-x: hidden;
}
.notesBar .loadingStuff {
border: none;
background:
linear-gradient(0.25turn, transparent, var(--contrast2), transparent),
linear-gradient(var(--contrast), var(--contrast)),
radial-gradient(38px circle at 19px 19px, #eee 50%, transparent 51%),
linear-gradient(var(--contrast), var(--contrast));
background-repeat: no-repeat;
background-size: 315px 250px, 315px 180px, 100px 100px, 225px 30px;
background-position: -315px 0, 0 0, 0px 190px, 50px 195px;
animation: loading 1.5s infinite;
}
@keyframes loading {
to {
background-position: 315px 0, 0 0, 0 190px, 50px 195px;
}
}
.notesBar .selected {
background-color: var(--theme-color) !important;
border: none;
color: var(--note-button-text-color);
}
.notesBar .newNote {
height: 41px;
line-height: 41px;
width: 100%;
text-align: left;
background-color: rgba(0, 0, 0, 0);
border: none;
font-size: 16px;
margin-bottom: 5px;
cursor: pointer;
}
.notesBar .newNote img {
height: 32px;
padding-right: 5px;
transform: translateY(30%);
}
.noteBox {
resize: none;
position: fixed;
right: 0;
top: 55px;
padding: 4px;
border: none;
font-size: 16px;
color: var(--text-color);
background-color: var(--editor);
width: calc(100% - 180px - 7px - 6px);
height: calc(100% - 50px - 6px - 8px - 30px);
font-family: "Inter", sans-serif;
display: flex;
}
.noteBoxText {
background-color: var(--editor);
color: var(--text-color);
border: none;
width: 100%;
font-family: "Inter", sans-serif;
}
iframe#markdown {
width: 100%;
border: none;
border-left: solid var(--bar) 1px;
}
.noteBox:focus {
outline: none;
}
.optionsCoverDiv {
position: fixed;
width: 100%;
height: 100%;
z-index: 2;
background-color: rgba(0, 0, 0, 0.7);
transition: opacity 1s;
}
.optionsDiv {
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
position: fixed;
background-color: var(--option-background);
padding: 10px;
color: var(--text-color);
border-radius: 8px;
min-width: 300px;
z-index: 3;
}
.optionsDiv button {
width: 100%;
padding: 10px;
padding-bottom: 13px;
margin-right: 5px;
margin-bottom: 7px;
padding-left: 15px;
padding-right: 15px;
color: var(--theme-text-color);
border: none;
text-decoration: none;
background-color: var(--theme-color);
border-radius: 8px;
cursor: pointer;
}
.optionsDiv .normalButton {
width: auto;
margin-bottom: 0px;
}
.optionsDiv .lastButton {
margin-bottom: 0px;
}
.optionsDiv input {
width: calc(100% - 12px);
height: 25px;
background-color: #ffffff;
padding-left: 5px;
padding-right: 5px;
margin-bottom: 7px;
border: solid;
border-color: var(--border-color);
border-width: 1px;
border-radius: 8px;
}
.optionsDiv .mfacheckbox {
display: inline;
margin: 0;
margin-left: 5px;
margin-bottom: 12px;
padding: 0;
height: 17px;
width: 17px;
}
.optionsDiv input:focus {
outline: 0;
border-color: var(--theme-color);
}
.optionsDiv code {
padding: 7px;
font-size: 14px;
border-radius: 8px;
background-color: var(--session-color);
}
.optionsDiv progress {
width: 100%;
background-color: var(--session-color);
border: none;
border-radius: 99px;
height: 7px;
}
.optionsDiv progress::-moz-progress-bar {
background: var(--theme-color);
}
.optionsDiv progresss::-webkit-progress-value {
background: var(--theme-color);
}
.optionsDiv .exit {
position: absolute;
right: 5px;
width: 40px;
height: 40px;
font-size: 16px;
background-color: var(--exit-color);
color: var(--text-color);
border-radius: 100%;
}
.optionsDiv img {
height: 18px;
padding-right: 5px;
filter: invert(var(--invert));
transform: translateY(3.25px);
}
.optionsDiv .section {
width: 100%;
height: 1px;
background-color: var(--border-color);
margin-top: 2px;
margin-bottom: 10px;
}
.sessionDiv {
max-height: 255px;
overflow-y: auto;
}
.sessionDiv div {
position: relative;
background-color: var(--session-color);
border-radius: 8px;
margin-bottom: 5px;
padding: 10px;
height: 35px;
}
.sessionDiv div p {
display: inline;
position: absolute;
transform: translateY(-7.5px);
}
.sessionDiv div button {
position: absolute;
border-radius: 99px;
right: 15px;
width: 40px;
height: 40px;
font-size: 16px;
transform: translateY(-2px);
}
.sessionDiv img {
display: inline;
filter: none;
height: 100%;
}
/* Sign up/log in div */
.inoutdiv {
border-radius: 8px;
margin: 10%;
padding: 30px;
border: solid 1px var(--border-color);
background-color: var(--bar);
}
.inoutdiv input {
width: calc(100% - 120px);
height: 30px;
margin-bottom: 10px;
padding-left: 10px;
padding-right: 10px;
border: solid;
border-color: var(--border-color);
border-width: 1px;
border-radius: 8px;
}
.inoutdiv button {
background-color: var(--theme-color);
color: white;
padding: 10px;
margin-right: 5px;
padding-left: 20px;
padding-right: 20px;
border: none;
border-radius: 8px;
font-size: 14px;
}
.inoutdiv a {
color: grey;
text-align: center;
}
.background {
position: fixed;
z-index: -2;
top: 0;
width: 100%;
min-height: 100%;
}
.credit {
position: fixed;
left: 5px;
color: white;
z-index: -1;
margin: 0;
bottom: 5px;
}
.hidden {
display: none !important;
}
.w100 {
font-weight: 300;
}
.w200 {
font-weight: 300;
}
.w300 {
font-weight: 300;
}
.w400 {
font-weight: 400;
}
.w500 {
font-weight: 500;
}
.w600 {
font-weight: 600;
}
.w700 {
font-weight: 700;
}
.w800 {
font-weight: 800;
}
.w900 {
font-weight: 900;
}
.alertDiv {
position: fixed;
margin: 0;
width: 100%;
background-color: #ffffeb;
height: 25px;
z-index: 9999;
top: 0;
}
/* main */
.mainDiv {
text-align: center;
}
.startDiv {
text-align: left;
margin-top: 8vh;
margin-left: 7vh;
display: flex;
flex-direction: column;
}
.startDiv h1 {
margin: 0;
}
.mainDiv a {
padding: 15px;
padding-left: 20px;
padding-right: 20px;
margin-right: auto;
color: white;
text-decoration: none;
background-color: var(--theme-color);
border-radius: 8px;
}
.mainDiv .feature {
width: calc(100% - 7vh - 7vh - 3.5vh);
margin-bottom: 10px;
margin-left: 7vh;
margin-right: 7vh;
padding-left: 10px;
padding-right: 10px;
border: solid;
border-radius: 8px;
border-width: 1px;
border-color: var(--border-color);
padding-top: 15px;
padding-bottom: 15px;
font-size: 17px;
padding-bottom: 30px;
}
.mainDiv .green {
background-color: #ebffeb;
}
.mainDiv .yellow {
background-color: #ffffeb;
}
.links {
text-align: center;
padding: 10px;
}
.links a {
margin-left: 5px;
text-decoration: none;
background-color: var(--bar);
color: var(--text-color);
padding: 10px;
padding-top: 2.5px;
margin-bottom: 10px;
border-radius: 10px;
transition: background-color .2s;
display: inline-block;
}
.links a:hover {
background-color: var(--editor);
}
.links a img {
transform: translateY(5px);
padding-right: 10px;
filter: invert(var(--invertdm));
}
.links a:hover {
text-decoration: dashed;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,57 @@
/* Variable fonts usage:
:root { font-family: "Inter", sans-serif; }
@supports (font-variation-settings: normal) {
:root { font-family: "InterVariable", sans-serif; font-optical-sizing: auto; }
} */
@font-face {
font-family: InterVariable;
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url("InterVariable.woff2") format("woff2");
}
@font-face {
font-family: InterVariable;
font-style: italic;
font-weight: 100 900;
font-display: swap;
src: url("InterVariable-Italic.woff2") format("woff2");
}
/* static fonts */
@font-face { font-family: "Inter"; font-style: normal; font-weight: 100; font-display: swap; src: url("Inter-Thin.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 100; font-display: swap; src: url("Inter-ThinItalic.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 200; font-display: swap; src: url("Inter-ExtraLight.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 200; font-display: swap; src: url("Inter-ExtraLightItalic.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 300; font-display: swap; src: url("Inter-Light.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 300; font-display: swap; src: url("Inter-LightItalic.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap; src: url("Inter-Regular.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 400; font-display: swap; src: url("Inter-Italic.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap; src: url("Inter-Medium.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 500; font-display: swap; src: url("Inter-MediumItalic.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap; src: url("Inter-SemiBold.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 600; font-display: swap; src: url("Inter-SemiBoldItalic.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap; src: url("Inter-Bold.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 700; font-display: swap; src: url("Inter-BoldItalic.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 800; font-display: swap; src: url("Inter-ExtraBold.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 800; font-display: swap; src: url("Inter-ExtraBoldItalic.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 900; font-display: swap; src: url("Inter-Black.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 900; font-display: swap; src: url("Inter-BlackItalic.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 100; font-display: swap; src: url("InterDisplay-Thin.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 100; font-display: swap; src: url("InterDisplay-ThinItalic.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 200; font-display: swap; src: url("InterDisplay-ExtraLight.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 200; font-display: swap; src: url("InterDisplay-ExtraLightItalic.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 300; font-display: swap; src: url("InterDisplay-Light.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 300; font-display: swap; src: url("InterDisplay-LightItalic.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 400; font-display: swap; src: url("InterDisplay-Regular.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 400; font-display: swap; src: url("InterDisplay-Italic.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 500; font-display: swap; src: url("InterDisplay-Medium.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 500; font-display: swap; src: url("InterDisplay-MediumItalic.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 600; font-display: swap; src: url("InterDisplay-SemiBold.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 600; font-display: swap; src: url("InterDisplay-SemiBoldItalic.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 700; font-display: swap; src: url("InterDisplay-Bold.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 700; font-display: swap; src: url("InterDisplay-BoldItalic.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 800; font-display: swap; src: url("InterDisplay-ExtraBold.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 800; font-display: swap; src: url("InterDisplay-ExtraBoldItalic.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 900; font-display: swap; src: url("InterDisplay-Black.woff2") format("woff2"); }
@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 900; font-display: swap; src: url("InterDisplay-BlackItalic.woff2") format("woff2"); }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,54 @@
let homeserverBox = document.getElementById("homeserverBox")
let statusBox = document.getElementById("statusBox")
let changeButton = document.getElementById("changeButton")
function showElements(yesorno) {
if (!yesorno) {
homeserverBox.classList.add("hidden")
changeButton.classList.add("hidden")
}
else {
homeserverBox.classList.remove("hidden")
changeButton.classList.remove("hidden")
}
}
changeButton.addEventListener("click", (event) => {
async function doStuff() {
let remote = homeserverBox.value
if (remote == "") {
statusBox.innerText = "A homeserver is required!"
return
}
showElements(false)
statusBox.innerText = "Connecting to homeserver..."
fetch(remote + "/api/version")
.then((response) => response)
.then((response) => {
async function doStuff() {
if (response.status == 200) {
localStorage.setItem("homeserverURL", remote)
if (document.referrer !== "") {
window.location.href = document.referrer;
}
else {
window.location.href = "https://notes.hectabit.org/login";
}
}
else if (response.status == 404) {
statusBox.innerText = "Not a valid homeserver!"
}
else {
statusBox.innerText = "Something went wrong!"
showElements(true)
}
}
doStuff()
});
}
doStuff()
});

198
website/static/js/login.js Normal file
View file

@ -0,0 +1,198 @@
if (localStorage.getItem("DONOTSHARE-secretkey") !== null) {
window.location.replace("/app/")
document.body.innerHTML = "Redirecting..."
throw new Error();
}
if (localStorage.getItem("DONOTSHARE-password") !== null) {
window.location.replace("/app/")
document.body.innerHTML = "Redirecting..."
throw new Error();
}
let remote = localStorage.getItem("homeserverURL")
if (remote == null) {
localStorage.setItem("homeserverURL", "https://notes.hectabit.org")
remote = "https://notes.hectabit.org"
}
let usernameBox = document.getElementById("usernameBox")
let passwordBox = document.getElementById("passwordBox")
let statusBox = document.getElementById("statusBox")
let signupButton = document.getElementById("signupButton")
let inputNameBox = document.getElementById("inputNameBox")
let backButton = document.getElementById("backButton")
usernameBox.classList.remove("hidden")
inputNameBox.innerText = "Username:"
let currentInputType = 0
function showInput(inputType) {
if (inputType === 0) {
usernameBox.classList.remove("hidden")
passwordBox.classList.add("hidden")
backButton.classList.add("hidden")
inputNameBox.innerText = "Username:"
statusBox.innerText = "Login to your Burgernotes account!"
currentInputType = 0
} else if (inputType === 1) {
usernameBox.classList.add("hidden")
passwordBox.classList.remove("hidden")
backButton.classList.remove("hidden")
inputNameBox.innerText = "Password:"
currentInputType = 1
} else if (inputType === 2) {
usernameBox.classList.add("hidden")
passwordBox.classList.add("hidden")
signupButton.classList.add("hidden")
backButton.classList.add("hidden")
inputNameBox.classList.add("hidden")
inputNameBox.innerText = "Password:"
currentInputType = 2
}
}
function showElements(yesorno) {
if (!yesorno) {
usernameBox.classList.add("hidden")
passwordBox.classList.add("hidden")
signupButton.classList.add("hidden")
backButton.classList.add("hidden")
inputNameBox.classList.add("hidden")
showInput(currentInputType)
}
else {
usernameBox.classList.remove("hidden")
passwordBox.classList.remove("hidden")
signupButton.classList.remove("hidden")
backButton.classList.remove("hidden")
inputNameBox.classList.remove("hidden")
showInput(currentInputType)
}
}
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("homeserver").innerText = "Your homeserver is: " + remote + ". "
});
signupButton.addEventListener("click", () => {
if (passwordBox.classList.contains("hidden")) {
if (usernameBox.value === "") {
statusBox.innerText = "A username is required!"
return
} else {
statusBox.innerText = "Welcome back, " + usernameBox.value + "!"
}
showInput(1)
} else {
async function doStuff() {
let username = usernameBox.value
let password = passwordBox.value
if (password === "") {
statusBox.innerText = "A password is required!"
return
}
showInput(2)
showElements(true)
statusBox.innerText = "Signing in..."
async function hashpassold(pass) {
return await hashwasm.argon2id({
password: pass,
salt: await hashwasm.sha512(pass),
parallelism: 1,
iterations: 256,
memorySize: 512,
hashLength: 32,
outputType: "encoded"
})
}
async function hashpass(pass) {
let key = pass
for (let i = 0; i < 128; i++) {
key = await hashwasm.sha3(key)
}
return key
}
fetch(remote + "/api/login", {
method: "POST",
body: JSON.stringify({
username: username,
password: await hashpass(password),
passwordchange: "no",
newpass: "null"
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then((response) => response)
.then((response) => {
async function doStuff() {
let responseData = await response.json()
if (response.status === 200) {
localStorage.setItem("DONOTSHARE-secretkey", responseData["key"])
localStorage.setItem("DONOTSHARE-password", await hashwasm.sha512(password))
window.location.href = "/app/"
}
else if (response.status === 401) {
console.log("Trying oldhash")
fetch(remote + "/api/login", {
method: "POST",
body: JSON.stringify({
username: username,
password: await hashpassold(password),
passwordchange: "yes",
newpass: await hashpass(password)
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then((response) => response)
.then((response) => {
async function doStuff2() {
let responseData = await response.json()
if (response.status === 200) {
localStorage.setItem("DONOTSHARE-secretkey", responseData["key"])
localStorage.setItem("DONOTSHARE-password", await hashwasm.sha512(password))
window.location.href = "/app/"
}
else if (response.status === 401) {
statusBox.innerText = "Wrong username or password..."
showInput(1)
showElements(true)
}
else {
statusBox.innerText = "Something went wrong! (error code: " + response.status + ")"
showInput(1)
showElements(true)
}
}
doStuff2()
});
}
else {
statusBox.innerText = "Something went wrong! (error code: " + response.status + ")"
showInput(1)
showElements(true)
}
}
doStuff()
});
}
doStuff()
}
});
backButton.addEventListener("click", () => {
showInput(0)
});
showInput(0)

648
website/static/js/main.js Normal file
View file

@ -0,0 +1,648 @@
if (localStorage.getItem("DONOTSHARE-secretkey") === null) {
window.location.replace("/login")
document.body.innerHTML = "Redirecting..."
throw new Error();
}
if (localStorage.getItem("DONOTSHARE-password") === null) {
window.location.replace("/login")
document.body.innerHTML = "Redirecting..."
throw new Error();
}
if (localStorage.getItem("CACHE-username") !== null) {
document.getElementById("usernameBox").innerText = localStorage.getItem("CACHE-username")
}
let remote = localStorage.getItem("homeserverURL")
if (remote == null) {
localStorage.setItem("homeserverURL", "https://notes.hectabit.org")
remote = "https://notes.hectabit.org"
}
function formatBytes(a, b = 2) { if (!+a) return "0 Bytes"; const c = 0 > b ? 0 : b, d = Math.floor(Math.log(a) / Math.log(1000)); return `${parseFloat((a / Math.pow(1000, d)).toFixed(c))} ${["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"][d]}` }
let secretkey = localStorage.getItem("DONOTSHARE-secretkey")
let password = localStorage.getItem("DONOTSHARE-password")
let currentFontSize = 16
let markdowntoggle = false
let usernameBox = document.getElementById("usernameBox")
let optionsCoverDiv = document.getElementById("optionsCoverDiv")
let optionsDiv = document.getElementById("optionsDiv")
let errorDiv = document.getElementById("errorDiv")
let errorMessageThing = document.getElementById("errorMessageThing")
let closeErrorButton = document.getElementById("closeErrorButton")
let cancelErrorButton = document.getElementById("cancelErrorButton")
let errorInput = document.getElementById("errorInput")
let exitThing = document.getElementById("exitThing")
let exitSessionsThing = document.getElementById("exitSessionsThing")
let sessionManagerButton = document.getElementById("sessionManagerButton")
let sessionManagerDiv = document.getElementById("sessionManagerDiv")
let sessionDiv = document.getElementById("sessionDiv")
let deleteMyAccountButton = document.getElementById("deleteMyAccountButton")
let storageThing = document.getElementById("storageThing")
let storageProgressThing = document.getElementById("storageProgressThing")
let usernameThing = document.getElementById("usernameThing")
let logOutButton = document.getElementById("logOutButton")
let notesBar = document.getElementById("notesBar")
let notesDiv = document.getElementById("notesDiv")
let newNote = document.getElementById("newNote")
let noteBox = document.getElementById("noteBox")
let loadingStuff = document.getElementById("loadingStuff")
let exportNotesButton = document.getElementById("exportNotesButton")
let markdown = document.getElementById('markdown');
let textSizeBox = document.getElementById('textSizeBox');
let textPlusBox = document.getElementById('textPlusBox');
let textMinusBox = document.getElementById('textMinusBox');
let wordCountBox = document.getElementById('wordCountBox');
let removeBox = document.getElementById("removeBox")
let selectedNote = 0
let timer
let waitTime = 400
if (/Android|iPhone|iPod/i.test(navigator.userAgent)) {
noteBox.style.width = "10px";
notesBar.style.width = "calc(100% - 10px)"
noteBox.readOnly = true
noteBox.style.fontSize = "18px"
noteBox.classList.add("hidden")
let touchstartX, touchstartY, touchendX, touchendY
notesBar.addEventListener("touchstart", function (event) {
touchstartX = event.changedTouches[0].screenX;
touchstartY = event.changedTouches[0].screenY;
}, false);
notesBar.addEventListener("touchend", function (event) {
touchendX = event.changedTouches[0].screenX;
touchendY = event.changedTouches[0].screenY;
handleGesture();
}, false);
noteBox.addEventListener("touchstart", function (event) {
touchstartX = event.changedTouches[0].screenX;
touchstartY = event.changedTouches[0].screenY;
}, false);
noteBox.addEventListener("touchend", function (event) {
touchendX = event.changedTouches[0].screenX;
touchendY = event.changedTouches[0].screenY;
handleGesture();
}, false);
function handleGesture() {
if (touchendX > touchstartX + 75) {
notesBar.style.width = "calc(100% - 10px)";
noteBox.style.width = "10px"
if (selectedNote !== 0) {
noteBox.readOnly = true
}
notesDiv.classList.remove("hidden")
noteBox.classList.add("hidden")
newNote.classList.remove("hidden")
}
if (touchendX < touchstartX - 75) {
noteBox.style.width = "calc(100% - 30px)";
notesBar.style.width = "10px"
if (selectedNote !== 0) {
noteBox.readOnly = false
}
notesDiv.classList.add("hidden")
noteBox.classList.remove("hidden")
newNote.classList.add("hidden")
}
}
}
noteBox.value = ""
noteBox.readOnly = true
let noteCount = 0
function displayError(message) {
errorDiv.classList.remove("hidden")
optionsCoverDiv.classList.remove("hidden")
errorMessageThing.innerHTML = message
}
closeErrorButton.addEventListener("click", () => {
errorDiv.classList.add("hidden")
optionsCoverDiv.classList.add("hidden")
});
closeErrorButton.addEventListener("click", () => {
errorDiv.classList.add("hidden")
optionsCoverDiv.classList.add("hidden")
errorInput.classList.add("hidden")
cancelErrorButton.classList.add("hidden")
});
function updateFont() {
currentFontSize = localStorage.getItem("SETTING-fontsize")
noteBox.style.fontSize = currentFontSize + "px"
textSizeBox.innerText = currentFontSize + "px"
if (markdowntoggle) {
markdown.srcdoc = "<!DOCTYPE html><html lang='en'><style>html { height: 100% } body { font-family: 'Inter', sans-serif; height: 100%; color: " + getComputedStyle(document.documentElement).getPropertyValue('--text-color') + "; font-size: " + currentFontSize + "px; }</style>" + marked.parse(noteBox.value) + "</html>";
}
}
async function waitforedit() {
while(true) {
await fetch(remote + "/api/waitforedit", {
method: "POST",
body: JSON.stringify({
"secretKey": localStorage.getItem("DONOTSHARE-secretkey")
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then(async (response) => {
async function doStuff() {
const data = await response.json();
// Access the "note" field from the response
const note = data["note"];
if (note === selectedNote) {
selectNote(selectedNote)
}
}
doStuff()
});
}
}
if (localStorage.getItem("SETTING-fontsize") === null) {
localStorage.setItem("SETTING-fontsize", "16")
updateFont()
} else {
updateFont()
}
textPlusBox.addEventListener("click", () => {
localStorage.setItem("SETTING-fontsize", String(Number(localStorage.getItem("SETTING-fontsize")) + Number(1)))
updateFont()
});
textMinusBox.addEventListener("click", () => {
localStorage.setItem("SETTING-fontsize", String(Number(localStorage.getItem("SETTING-fontsize")) - Number(1)))
updateFont()
});
function truncateString(str, num) {
if (str.length > num) {
return str.slice(0, num) + "..";
} else {
return str;
}
}
function updateUserInfo() {
fetch(remote + "/api/userinfo", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.catch(() => {
noteBox.readOnly = true
noteBox.value = ""
noteBox.placeholder = "Failed to connect to the server.\nPlease check your internet connection."
})
.then((response) => {
async function doStuff() {
if (response.status === 500) {
displayError("Something went wrong! Signing you out..")
closeErrorButton.classList.add("hidden")
usernameBox.innerText = ""
setTimeout(function () {
window.location.replace("/logout")
}, 2500);
} else {
let responseData = await response.json()
usernameBox.innerText = responseData["username"]
usernameThing.innerText = "Username: " + responseData["username"]
storageThing.innerText = "You've used " + formatBytes(responseData["storageused"]) + " out of " + formatBytes(responseData["storagemax"])
storageProgressThing.value = responseData["storageused"]
storageProgressThing.max = responseData["storagemax"]
noteCount = responseData["notecount"]
localStorage.setItem("CACHE-username", responseData["username"])
}
}
doStuff()
});
}
usernameBox.addEventListener("click", () => {
optionsCoverDiv.classList.remove("hidden")
optionsDiv.classList.remove("hidden")
updateUserInfo()
});
logOutButton.addEventListener("click", () => {
window.location.replace("/logout")
});
exitThing.addEventListener("click", () => {
optionsDiv.classList.add("hidden")
optionsCoverDiv.classList.add("hidden")
});
deleteMyAccountButton.addEventListener("click", () => {
if (confirm("Are you REALLY sure that you want to delete your account? There's no going back!") === true) {
fetch(remote + "/api/deleteaccount", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then((response) => {
if (response.status === 200) {
window.location.href = "/logout"
} else {
displayError("Failed to delete account (HTTP error code " + response.status + ")")
}
})
}
});
sessionManagerButton.addEventListener("click", () => {
optionsDiv.classList.add("hidden")
sessionManagerDiv.classList.remove("hidden")
fetch(remote + "/api/sessions/list", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then((response) => {
async function doStuff() {
let responseData = await response.json()
document.querySelectorAll(".burgerSession").forEach((el) => el.remove());
let ua;
for (let i in responseData) {
let sessionElement = document.createElement("div")
let sessionText = document.createElement("p")
let sessionImage = document.createElement("img")
let sessionRemoveButton = document.createElement("button")
sessionText.classList.add("w300")
if (responseData[i]["thisSession"] === true) {
sessionText.innerText = "(current) " + responseData[i]["device"]
} else {
sessionText.innerText = responseData[i]["device"]
}
sessionText.title = responseData[i]["device"]
sessionRemoveButton.innerText = "x"
sessionImage.src = "/static/svg/device_other.svg"
ua = responseData[i]["device"]
if (ua.includes("NT") || ua.includes("Linux")) {
sessionImage.src = "/static/svg/device_computer.svg"
}
if (ua.includes("iPhone" || ua.includes("Android") || ua.includes("iPod"))) {
sessionImage.src = "/static/svg/device_smartphone.svg"
}
sessionRemoveButton.addEventListener("click", () => {
fetch(remote + "/api/sessions/remove", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey,
sessionId: responseData[i]["id"]
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then(() => {
if (responseData[i]["thisSession"] === true) {
window.location.replace("/logout")
}
});
sessionElement.remove()
});
sessionElement.append(sessionImage)
sessionElement.append(sessionText)
sessionElement.append(sessionRemoveButton)
sessionElement.classList.add("burgerSession")
sessionDiv.append(sessionElement)
}
}
doStuff()
});
});
exitSessionsThing.addEventListener("click", () => {
optionsDiv.classList.remove("hidden")
sessionManagerDiv.classList.add("hidden")
});
updateUserInfo()
function updateWordCount() {
let wordCount = noteBox.value.split(" ").length
if (wordCount === 1) {
wordCount = 0
}
wordCountBox.innerText = wordCount + " words"
}
function renderMarkDown() {
if (markdowntoggle) {
markdown.srcdoc = "<!DOCTYPE html><html lang='en'><style>html { height: 100% } body { font-family: 'Inter', sans-serif; height: 100%; color: " + getComputedStyle(document.documentElement).getPropertyValue('--text-color') + "; font-size: " + currentFontSize + "px; }</style>" + marked.parse(noteBox.value) + "</html>"
}
}
function selectNote(nameithink) {
document.querySelectorAll(".noteButton").forEach((el) => el.classList.remove("selected"));
let thingArray = Array.from(document.querySelectorAll(".noteButton")).find(el => String(nameithink) === String(el.id));
thingArray.classList.add("selected")
fetch(remote + "/api/readnote", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey,
noteId: nameithink,
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.catch(() => {
noteBox.readOnly = true
noteBox.value = ""
noteBox.placeholder = ""
displayError("Something went wrong... Please try again later!")
})
.then((response) => {
selectedNote = nameithink
noteBox.readOnly = false
noteBox.placeholder = "Type something!"
async function doStuff() {
let responseData = await response.json()
let bytes = CryptoJS.AES.decrypt(responseData["content"], password);
noteBox.value = bytes.toString(CryptoJS.enc.Utf8)
updateWordCount()
renderMarkDown()
noteBox.addEventListener("input", () => {
updateWordCount()
renderMarkDown()
clearTimeout(timer);
timer = setTimeout(() => {
let encryptedTitle = "New note"
if (noteBox.value.substring(0, noteBox.value.indexOf("\n")) !== "") {
let firstTitle = noteBox.value.substring(0, noteBox.value.indexOf("\n"));
document.getElementById(nameithink).innerText = firstTitle
encryptedTitle = CryptoJS.AES.encrypt(firstTitle, password).toString();
}
let encryptedText = CryptoJS.AES.encrypt(noteBox.value, password).toString();
if (selectedNote === nameithink) {
fetch(remote + "/api/editnote", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey,
noteId: nameithink,
content: encryptedText,
title: encryptedTitle
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then((response) => {
if (response.status === 418) {
displayError("You've ran out of storage... Changes will not be saved until you free up storage!")
}
})
.catch(() => {
displayError("Failed to save changes, please try again later...")
})
}
}, waitTime);
});
}
doStuff()
});
}
function updateNotes() {
fetch(remote + "/api/listnotes", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then((response) => {
async function doStuff() {
document.querySelectorAll(".noteButton").forEach((el) => el.remove());
noteBox.readOnly = true
selectedNote = 0
noteBox.placeholder = ""
noteBox.value = ""
clearTimeout(timer)
updateWordCount()
renderMarkDown()
let responseData = await response.json()
for (let i in responseData) {
let noteButton = document.createElement("button");
noteButton.classList.add("noteButton")
notesDiv.append(noteButton)
let bytes = CryptoJS.AES.decrypt(responseData[i]["title"], password);
let originalTitle = bytes.toString(CryptoJS.enc.Utf8);
noteButton.id = responseData[i]["id"]
noteButton.innerText = truncateString(originalTitle, 15)
noteButton.addEventListener("click", (event) => {
if (event.ctrlKey) {
fetch(remote + "/api/removenote", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey,
noteId: responseData[i]["id"]
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then(() => {
updateNotes()
})
.catch(() => {
displayError("Something went wrong! Please try again later...")
})
} else {
selectNote(responseData[i]["id"])
}
});
}
document.querySelectorAll(".loadingStuff").forEach((el) => el.remove());
}
doStuff()
});
}
updateNotes()
newNote.addEventListener("click", () => {
let noteName = "New note"
let encryptedName = CryptoJS.AES.encrypt(noteName, password).toString(CryptoJS.enc.Utf8);
fetch(remote + "/api/newnote", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey,
noteName: encryptedName,
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.catch(() => {
displayError("Failed to create new note, please try again later...")
})
.then((response) => {
if (response.status !== 200) {
updateNotes()
displayError("Failed to create new note (HTTP error code " + response.status + ")")
} else {
updateNotes()
}
});
});
function downloadObjectAsJson(exportObj, exportName) {
let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));
let downloadAnchorNode = document.createElement("a");
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", exportName + ".json");
document.body.appendChild(downloadAnchorNode);
downloadAnchorNode.click();
downloadAnchorNode.remove();
}
function exportNotes() {
fetch(remote + "/api/exportnotes", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then((response) => {
async function doStuff() {
let responseData = await response.json()
for (let i in responseData) {
exportNotes.innerText = "Decrypting " + i + "/" + noteCount
let bytes = CryptoJS.AES.decrypt(responseData[i]["title"], password);
responseData[i]["title"] = bytes.toString(CryptoJS.enc.Utf8)
let bytesd = CryptoJS.AES.decrypt(responseData[i]["content"], password);
responseData[i]["content"] = bytesd.toString(CryptoJS.enc.Utf8)
}
let jsonString = JSON.parse(JSON.stringify(responseData))
exportNotesButton.innerText = "Export notes"
downloadObjectAsJson(jsonString, "data")
optionsDiv.classList.add("hidden")
displayError("Exported notes!")
}
doStuff()
})
}
function isFirstTimeVisitor() {
if (localStorage.getItem("FIRSTVISIT") === null) {
localStorage.setItem("FIRSTVISIT", "1")
return true;
} else {
return false;
}
}
function firstNewVersion() {
if (localStorage.getItem("NEWVERSION") === "1.2") {
return false;
} else {
localStorage.setItem("NEWVERSION", "1.2")
return true;
}
}
function toggleMarkdown() {
if (markdown.style.display === 'none') {
markdown.style.display = 'inherit';
markdowntoggle = true
renderMarkDown()
} else {
markdown.style.display = 'none';
markdowntoggle = false
markdown.srcdoc = ""
}
}
exportNotesButton.addEventListener("click", () => {
exportNotesButton.innerText = "Downloading..."
exportNotes()
});
removeBox.addEventListener("click", () => {
if (selectedNote === 0) {
displayError("You need to select a note first!")
} else {
fetch(remote + "/api/removenote", {
method: "POST",
body: JSON.stringify({
secretKey: secretkey,
noteId: selectedNote
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then(() => {
updateNotes()
})
.catch(() => {
displayError("Something went wrong! Please try again later...")
})
}
});
document.addEventListener("DOMContentLoaded", function() {
markdown.srcdoc = "<!DOCTYPE html><html lang='en'><style>html { height: 100% } body { font-family: 'Inter', sans-serif; height: 100%; color: " + getComputedStyle(document.documentElement).getPropertyValue('--text-color') + "; font-size: " + currentFontSize + "px; }</style>" + marked.parse(noteBox.value) + "</html>"
});
if (isFirstTimeVisitor() && /Android|iPhone|iPod/i.test(navigator.userAgent)) {
displayError("To use Burgernotes:\n Swipe Right on a note to open it\n Swipe left in the text boxes to return to notes\n Click on a note to highlight it")
}
if (firstNewVersion()) {
displayError("What's new in Burgernotes 1.2-1?\nNotes now support live editing\nFixed various bugs and issues in the client")
}
waitforedit()

1297
website/static/js/marked.js Normal file

File diff suppressed because it is too large Load diff

109
website/static/js/signup.js Normal file
View file

@ -0,0 +1,109 @@
if (localStorage.getItem("DONOTSHARE-secretkey") !== null) {
window.location.replace("/app/")
document.body.innerHTML = "Redirecting..."
throw new Error();
}
if (localStorage.getItem("DONOTSHARE-password") !== null) {
window.location.replace("/app/")
document.body.innerHTML = "Redirecting..."
throw new Error();
}
let remote = localStorage.getItem("homeserverURL")
if (remote == null) {
localStorage.setItem("homeserverURL", "https://notes.hectabit.org")
remote = "https://notes.hectabit.org"
}
let usernameBox = document.getElementById("usernameBox")
let passwordBox = document.getElementById("passwordBox")
let statusBox = document.getElementById("statusBox")
let signupButton = document.getElementById("signupButton")
function showElements(yesorno) {
if (!yesorno) {
usernameBox.classList.add("hidden")
passwordBox.classList.add("hidden")
signupButton.classList.add("hidden")
}
else {
usernameBox.classList.remove("hidden")
passwordBox.classList.remove("hidden")
signupButton.classList.remove("hidden")
}
}
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("homeserver").innerText = "Your homeserver is: " + remote + ". "
});
signupButton.addEventListener("click", () => {
async function doStuff() {
let username = usernameBox.value
let password = passwordBox.value
if (username === "") {
statusBox.innerText = "A username is required!"
return
}
if ((username).length > 20) {
statusBox.innerText = "Username cannot be more than 20 characters!"
return
}
if (password === "") {
statusBox.innerText = "A password is required!"
return
}
if ((password).length < 8) {
statusBox.innerText = "8 or more characters are required!"
return
}
showElements(false)
statusBox.innerText = "Creating account, please hold on..."
async function hashpass(pass) {
let key = pass
for (let i = 0; i < 128; i++) {
key = await hashwasm.sha3(key)
}
return key
}
fetch(remote + "/api/signup", {
method: "POST",
body: JSON.stringify({
username: username,
password: await hashpass(password)
}),
headers: {
"Content-Type": "application/json; charset=UTF-8"
}
})
.then((response) => response)
.then((response) => {
async function doStuff() {
let responseData = await response.json()
if (response.status === 200) {
statusBox.innerText = "Redirecting...."
localStorage.setItem("DONOTSHARE-secretkey", responseData["key"])
localStorage.setItem("DONOTSHARE-password", await hashwasm.sha512(password))
window.location.href = "/app/"
}
else if (response.status === 409) {
statusBox.innerText = "Username already taken!"
showElements(true)
}
else {
statusBox.innerText = "Something went wrong!"
showElements(true)
}
}
doStuff()
});
}
doStuff()
});

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M450-450H200v-60h250v-250h60v250h250v60H510v250h-60v-250Z"/></svg>

After

Width:  |  Height:  |  Size: 163 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-240 80-480l240-240 57 57-184 184 183 183-56 56Zm320 0-57-57 184-184-183-183 56-56 240 240-240 240Z"/></svg>

After

Width:  |  Height:  |  Size: 209 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/></svg>

After

Width:  |  Height:  |  Size: 300 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="m361-299 119-121 120 121 47-48-119-121 119-121-47-48-120 121-119-121-48 48 120 121-120 121 48 48ZM261-120q-24 0-42-18t-18-42v-570h-41v-60h188v-30h264v30h188v60h-41v570q0 24-18 42t-42 18H261Zm438-630H261v570h438v-570Zm-438 0v570-570Z"/></svg>

After

Width:  |  Height:  |  Size: 338 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M70-120q-12.75 0-21.375-8.675Q40-137.351 40-150.175 40-163 48.625-171.5T70-180h820q12.75 0 21.375 8.675 8.625 8.676 8.625 21.5 0 12.825-8.625 21.325T890-120H70Zm70-120q-24 0-42-18t-18-42v-480q0-24 18-42t42-18h680q24 0 42 18t18 42v480q0 24-18 42t-42 18H140Zm0-60h680v-480H140v480Zm0 0v-480 480Z"/></svg>

After

Width:  |  Height:  |  Size: 399 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M140-160q-24 0-42-18t-18-42v-520q0-24 18-42t42-18h680q24 0 42 18t18 42v520q0 24-18 42t-42 18H140Zm0-60h680v-436H140v436Zm160-72-42-42 103-104-104-104 43-42 146 146-146 146Zm190 4v-60h220v60H490Z"/></svg>

After

Width:  |  Height:  |  Size: 300 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M260-40q-24 0-42-18t-18-42v-760q0-24 18-42t42-18h440q24 0 42 18t18 42v760q0 24-18 42t-42 18H260Zm0-90v30h440v-30H260Zm0-60h440v-580H260v580Zm0-640h440v-30H260v30Zm0 0v-30 30Zm0 700v30-30Z"/></svg>

After

Width:  |  Height:  |  Size: 293 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M480-313 287-506l43-43 120 120v-371h60v371l120-120 43 43-193 193ZM220-160q-24 0-42-18t-18-42v-143h60v143h520v-143h60v143q0 24-18 42t-42 18H220Z"/></svg>

After

Width:  |  Height:  |  Size: 249 B

View file

@ -0,0 +1,55 @@
<svg width="527" height="533" viewBox="0 0 527 533" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6_27)">
<path d="M451 352.333C451 375.896 431.896 395 408.333 395H152.333C128.771 395 109.667 375.896 109.667 352.333V142.339C109.667 118.776 171.437 75 195 75H393.667C426.669 75 451 99.6613 451 132.333V352.333Z" fill="#226699"/>
<path d="M429.667 395C429.667 418.563 410.563 437.667 387 437.667H173.667C150.104 437.667 131 418.563 131 395V139C131 95.064 130.776 96.3333 184.333 96.3333H387C410.563 96.3333 429.667 115.437 429.667 139V395Z" fill="url(#paint0_linear_6_27)"/>
<path d="M408.333 405.667C408.333 423.341 394.008 437.667 376.333 437.667H141.667C123.992 437.667 109.667 423.341 109.667 405.667V149.667C109.667 131.992 123.992 117.667 141.667 117.667H376.333C394.008 117.667 408.333 131.992 408.333 149.667V405.667Z" fill="#E1E8ED"/>
<path d="M158.115 426.776C158.115 434.264 151 440.333 142.221 440.333C133.453 440.333 126.339 434.264 126.339 426.776C126.339 419.299 133.453 413.219 142.221 413.219C151 413.219 158.115 419.288 158.115 426.776Z" fill="#662113"/>
<path d="M140.536 419.224C135.416 419.811 132.088 423.224 129.688 427C126.413 432.173 118.947 437.667 109.667 437.667C97.8906 437.667 88.3333 430.509 88.3333 421.667C88.3333 412.824 97.8906 405.667 109.667 405.667V384.376C86.552 384.6 67.8853 401.176 67.8853 421.667C67.8853 442.296 86.7866 459 110.104 459C129.88 459 145.805 447.853 151.715 431.597C154.669 423.501 146.712 418.541 140.536 419.224Z" fill="url(#paint1_linear_6_27)"/>
<path d="M158.115 341.443C158.115 348.931 151 355 142.221 355C133.453 355 126.339 348.931 126.339 341.443C126.339 333.965 133.453 327.885 142.221 327.885C151 327.885 158.115 333.955 158.115 341.443Z" fill="#662113"/>
<path d="M140.536 333.891C135.416 334.477 132.088 337.891 129.688 341.667C126.413 346.84 118.947 352.333 109.667 352.333C97.8906 352.333 88.3333 345.176 88.3333 336.333C88.3333 327.491 97.8906 320.333 109.667 320.333V299.043C86.552 299.267 67.8853 315.843 67.8853 336.333C67.8853 356.963 86.7866 373.667 110.104 373.667C129.88 373.667 145.805 362.52 151.715 346.264C154.669 338.168 146.712 333.208 140.536 333.891Z" fill="url(#paint2_linear_6_27)"/>
<path d="M158.115 256.109C158.115 263.597 151 269.667 142.221 269.667C133.453 269.667 126.339 263.597 126.339 256.109C126.339 248.632 133.453 242.552 142.221 242.552C151 242.552 158.115 248.621 158.115 256.109Z" fill="#662113"/>
<path d="M140.536 248.557C135.416 249.144 132.088 252.557 129.688 256.333C126.413 261.507 118.947 267 109.667 267C97.8906 267 88.3333 259.843 88.3333 251C88.3333 242.157 97.8906 235 109.667 235V213.709C86.552 213.933 67.8853 230.509 67.8853 251C67.8853 271.629 86.7866 288.333 110.104 288.333C129.88 288.333 145.805 277.187 151.715 260.931C154.669 252.835 146.712 247.875 140.536 248.557Z" fill="url(#paint3_linear_6_27)"/>
<path d="M158.115 170.776C158.115 178.264 151 184.333 142.221 184.333C133.453 184.333 126.339 178.264 126.339 170.776C126.339 163.299 133.453 157.219 142.221 157.219C151 157.219 158.115 163.288 158.115 170.776Z" fill="#662113"/>
<path d="M140.536 163.224C135.416 163.811 132.088 167.224 129.688 171C126.413 176.173 118.947 181.667 109.667 181.667C97.8906 181.667 88.3333 174.509 88.3333 165.667C88.3333 156.824 97.8906 149.667 109.667 149.667V128.376C86.5626 128.589 67.8853 145.176 67.8853 165.667C67.8853 186.296 86.7866 203 110.104 203C129.88 203 145.805 191.853 151.715 175.597C154.669 167.501 146.712 162.541 140.536 163.224Z" fill="url(#paint4_linear_6_27)"/>
<path d="M281 300.771C192.496 300.771 120.756 298.646 120.756 361.47C120.756 424.266 192.496 438.556 281 438.556C369.504 438.556 441.244 424.266 441.244 361.47C441.244 298.655 369.504 300.771 281 300.771Z" fill="#D99E82"/>
<path d="M436.55 305.54C436.55 305.54 358.926 296.247 281 295.85C203.074 296.247 125.45 305.54 125.45 305.54C117.772 366.683 181.522 391.872 281 391.872C380.478 391.872 444.228 366.683 436.55 305.54Z" fill="#662113"/>
<path d="M431.035 281.098L130.182 287.199C119.793 287.199 111.095 308.251 122.116 313.757C204.358 339.332 270.47 365.21 270.47 365.21C279.555 370.234 282.625 370.253 291.72 365.238C291.72 365.238 383.009 328.707 441.65 313.36C449.971 311.188 441.414 281.098 431.035 281.098Z" fill="#FFCC4D"/>
<path d="M438.958 281.891C421.014 265.354 422.053 274.156 408.302 270.274C403.079 268.801 365.707 220.493 280.528 220.493H280.339C195.159 220.493 157.788 268.801 152.565 270.274C138.814 274.156 139.853 265.354 121.908 281.891C113.673 289.484 111.444 293.432 120.133 295.397C133.223 298.353 132.033 306.277 141.411 309.034C152.763 312.368 157.429 306.277 175.732 308.77C191.344 310.895 192.364 331.144 208.117 331.144C223.871 331.144 223.871 323.588 239.614 323.588C255.358 323.588 264.671 343.856 280.424 343.856C296.177 343.856 305.48 323.588 321.233 323.588C336.987 323.588 336.987 331.144 352.731 331.144C368.484 331.144 369.504 310.895 385.116 308.77C403.419 306.286 408.094 312.368 419.437 309.034C428.815 306.277 427.625 298.362 440.715 295.397C449.423 293.442 447.203 289.484 438.958 281.891Z" fill="#77B255"/>
<path d="M432.838 264.022C432.838 292.204 364.857 305.512 281 305.512C197.143 305.512 129.162 292.204 129.162 264.022C129.162 212.994 138.285 212.994 281 212.994C423.715 212.994 432.838 213.003 432.838 264.022Z" fill="#DD2E44"/>
<path d="M281 112.949C192.496 112.949 120.756 154.419 120.756 217.234C120.756 275.082 192.496 277.443 281 277.443C369.504 277.443 441.244 275.082 441.244 217.234C441.244 154.41 369.504 112.949 281 112.949Z" fill="#D99E82"/>
<path d="M212.849 142.897C208.146 139.884 201.903 141.263 198.899 145.967C195.896 150.67 197.266 156.922 201.969 159.916C206.672 162.929 218.591 165.177 221.604 160.473C224.607 155.77 217.552 145.901 212.849 142.897ZM304.781 133.122C299.473 134.841 290.152 142.623 291.88 147.931C293.608 153.239 305.707 154.051 311.014 152.332C316.322 150.613 319.222 144.909 317.493 139.601C315.774 134.303 310.07 131.394 304.781 133.122ZM407.811 199.564C403.542 195.975 392.841 201.689 389.243 205.958C385.654 210.236 386.211 216.602 390.48 220.191C394.749 223.779 401.124 223.222 404.713 218.953C408.311 214.675 412.089 203.153 407.811 199.564ZM373.404 152.342C368.701 149.338 362.458 150.717 359.446 155.421C356.442 160.124 357.821 166.367 362.524 169.37C367.228 172.383 379.147 174.631 382.15 169.927C385.163 165.214 378.108 155.345 373.404 152.342ZM231.738 218.453C227.034 215.449 220.792 216.828 217.779 221.532C214.776 226.226 216.154 232.478 220.858 235.472C225.561 238.484 237.48 240.742 240.483 236.029C243.496 231.326 236.441 221.456 231.738 218.453ZM260.506 173.044C257.332 177.634 254.65 189.468 259.249 192.641C263.839 195.814 273.954 189.109 277.128 184.519C280.301 179.929 279.139 173.639 274.549 170.466C269.969 167.292 263.669 168.454 260.506 173.044ZM335.627 218.453C330.923 215.449 324.681 216.828 321.668 221.532C318.664 226.226 320.043 232.487 324.747 235.472C329.45 238.484 341.369 240.742 344.372 236.029C347.385 231.326 340.33 221.456 335.627 218.453ZM157.731 181.742C154.01 185.907 149.864 197.307 154.029 201.028C158.175 204.749 169.055 199.384 172.776 195.219C176.507 191.064 176.148 184.679 171.992 180.949C167.846 177.228 161.452 177.587 157.731 181.742Z" fill="#FFE8B6"/>
</g>
<path d="M408.333 416.333C408.333 439.896 389.229 459 365.667 459H163C139.437 459 120.333 439.896 120.333 416.333V181.667C120.333 158.104 139.437 139 163 139H365.667C389.229 139 408.333 158.104 408.333 181.667V416.333Z" fill="#3B88C3"/>
<path d="M387 416.333C387 439.896 367.896 459 344.333 459H163C139.437 459 120.333 439.896 120.333 416.333V203C120.333 179.437 139.437 160.333 163 160.333H347.907C371.469 160.333 387 175.864 387 199.427V416.333Z" fill="url(#paint5_linear_6_27)"/>
<path d="M163 139C144.995 139 144.536 118.499 152.333 109.667C161.208 99.6293 175 96.3333 199.672 96.3333H216.333V75H187.331C144.995 75 109.667 101.667 109.667 132.333V416.333C109.667 439.896 128.771 459 152.333 459H173.667V139H163Z" fill="#226699"/>
<defs>
<linearGradient id="paint0_linear_6_27" x1="280.333" y1="96.3295" x2="280.333" y2="437.667" gradientUnits="userSpaceOnUse">
<stop stop-color="#CCD6DD"/>
<stop offset="1" stop-color="#CCD6DD" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint1_linear_6_27" x1="110.118" y1="384.376" x2="110.118" y2="459" gradientUnits="userSpaceOnUse">
<stop stop-color="#66757F"/>
<stop offset="1" stop-color="#50585C"/>
<stop offset="1" stop-color="#50585C"/>
</linearGradient>
<linearGradient id="paint2_linear_6_27" x1="110.118" y1="299.043" x2="110.118" y2="373.667" gradientUnits="userSpaceOnUse">
<stop stop-color="#66757F"/>
<stop offset="1" stop-color="#50585C"/>
</linearGradient>
<linearGradient id="paint3_linear_6_27" x1="110.118" y1="213.709" x2="110.118" y2="288.333" gradientUnits="userSpaceOnUse">
<stop stop-color="#66757F"/>
<stop offset="1" stop-color="#50585C"/>
</linearGradient>
<linearGradient id="paint4_linear_6_27" x1="110.118" y1="128.376" x2="110.118" y2="203" gradientUnits="userSpaceOnUse">
<stop stop-color="#66757F"/>
<stop offset="1" stop-color="#50585C"/>
</linearGradient>
<linearGradient id="paint5_linear_6_27" x1="253.667" y1="160.333" x2="253.667" y2="459" gradientUnits="userSpaceOnUse">
<stop stop-color="#55ACEE"/>
<stop offset="1" stop-color="#55ACEE" stop-opacity="0"/>
</linearGradient>
<clipPath id="clip0_6_27">
<rect width="384" height="384" fill="white" transform="translate(67 75)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 9.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.1 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M280-240q-17 0-28.5-11.5T240-280v-80h520v-360h80q17 0 28.5 11.5T880-680v600L720-240H280ZM80-280v-560q0-17 11.5-28.5T120-880h520q17 0 28.5 11.5T680-840v360q0 17-11.5 28.5T640-440H240L80-280Zm520-240v-280H160v280h440Zm-440 0v-280 280Z"/></svg>

After

Width:  |  Height:  |  Size: 338 B

3535
website/static/svg/grid.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 244 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>

After

Width:  |  Height:  |  Size: 516 B

Some files were not shown because too many files have changed in this diff Show more