From 5826fb5037983bdbe04b8d3b364167e8516ab7db Mon Sep 17 00:00:00 2001 From: EuAndreh Date: Wed, 23 Oct 2024 05:20:06 -0300 Subject: WIP: Init work on HTML --- .gitignore | 1 + Makefile | 83 +++- README.adoc | 5 + deps.mk | 65 ++++ src/content/img/icon/add/light.svg | 22 ++ src/content/img/icon/archive/light.svg | 43 +++ src/content/img/icon/arrow-down/light.svg | 20 + src/content/img/icon/bookmark/light.svg | 30 ++ src/content/img/icon/calendar/light.svg | 32 ++ src/content/img/icon/check/light.svg | 17 + src/content/img/icon/chevron-down/light.svg | 17 + src/content/img/icon/chevron-left/light.svg | 18 + src/content/img/icon/chevron-right/light.svg | 18 + src/content/img/icon/clipboard/light.svg | 41 ++ src/content/img/icon/close/light.svg | 26 ++ src/content/img/icon/code-file/light.svg | 52 +++ src/content/img/icon/code/light.svg | 28 ++ src/content/img/icon/crop/light.svg | 49 +++ src/content/img/icon/delete/light.svg | 46 +++ src/content/img/icon/download/light.svg | 26 ++ src/content/img/icon/edit/light.svg | 29 ++ src/content/img/icon/filter/light.svg | 28 ++ src/content/img/icon/folder/light.svg | 27 ++ src/content/img/icon/fullscreen/light.svg | 30 ++ src/content/img/icon/hash-sign/light.svg | 22 ++ src/content/img/icon/heart/light.svg | 23 ++ src/content/img/icon/help/light.svg | 44 +++ src/content/img/icon/info/light.svg | 23 ++ src/content/img/icon/launch/light.svg | 28 ++ src/content/img/icon/link/light.svg | 28 ++ src/content/img/icon/lock/light.svg | 38 ++ src/content/img/icon/logout/light.svg | 30 ++ src/content/img/icon/needs-update/light.svg | 38 ++ src/content/img/icon/notifications-off/light.svg | 75 ++++ src/content/img/icon/notifications/light.svg | 114 ++++++ src/content/img/icon/offline/light.svg | 61 +++ src/content/img/icon/online/light.svg | 99 +++++ src/content/img/icon/password/light.svg | 60 +++ src/content/img/icon/payment-card/light.svg | 37 ++ src/content/img/icon/photo/light.svg | 35 ++ src/content/img/icon/pin/light.svg | 57 +++ src/content/img/icon/remove/light.svg | 13 + src/content/img/icon/sad/light.svg | 48 +++ src/content/img/icon/save/light.svg | 57 +++ src/content/img/icon/scissors/light.svg | 55 +++ src/content/img/icon/search/light.svg | 21 ++ src/content/img/icon/settings/light.svg | 462 +++++++++++++++++++++++ src/content/img/icon/share/light.svg | 38 ++ src/content/img/icon/shield-bad/light.svg | 36 ++ src/content/img/icon/shield-good/light.svg | 31 ++ src/content/img/icon/shield-info/light.svg | 36 ++ src/content/img/icon/shield-off/light.svg | 51 +++ src/content/img/icon/shopping-cart/light.svg | 54 +++ src/content/img/icon/star-full/light.svg | 36 ++ src/content/img/icon/star/light.svg | 36 ++ src/content/img/icon/support/light.svg | 40 ++ src/content/img/icon/tag/light.svg | 32 ++ src/content/img/icon/threads/light.svg | 27 ++ src/content/img/icon/upload/light.svg | 26 ++ src/content/img/icon/user-add/light.svg | 32 ++ src/content/img/icon/user-check/light.svg | 27 ++ src/content/img/icon/user-circle/light.svg | 32 ++ src/content/img/icon/user-group/light.svg | 33 ++ src/content/img/icon/user-remove/light.svg | 32 ++ src/content/img/icon/user/light.svg | 26 ++ src/content/img/icon/warning/light.svg | 38 ++ src/content/img/icon/zoom-in/light.svg | 41 ++ src/content/img/icon/zoom-out/light.svg | 29 ++ src/content/img/profile/fallback.svg | 1 + src/content/index.html | 415 +++++++++++++++++++- src/content/papo.js | 42 +-- src/content/style.css | 43 +++ src/content/sw.js | 270 +++++++------ tests/browser-driver.js | 1 + tests/driver.html | 12 +- tests/driver.js | 20 +- tests/node-driver.js | 43 +-- tests/papo.js | 50 ++- tests/sw.js | 118 +++++- 79 files changed, 3746 insertions(+), 223 deletions(-) create mode 100644 README.adoc create mode 100644 src/content/img/icon/add/light.svg create mode 100644 src/content/img/icon/archive/light.svg create mode 100644 src/content/img/icon/arrow-down/light.svg create mode 100644 src/content/img/icon/bookmark/light.svg create mode 100644 src/content/img/icon/calendar/light.svg create mode 100644 src/content/img/icon/check/light.svg create mode 100644 src/content/img/icon/chevron-down/light.svg create mode 100644 src/content/img/icon/chevron-left/light.svg create mode 100644 src/content/img/icon/chevron-right/light.svg create mode 100644 src/content/img/icon/clipboard/light.svg create mode 100644 src/content/img/icon/close/light.svg create mode 100644 src/content/img/icon/code-file/light.svg create mode 100644 src/content/img/icon/code/light.svg create mode 100644 src/content/img/icon/crop/light.svg create mode 100644 src/content/img/icon/delete/light.svg create mode 100644 src/content/img/icon/download/light.svg create mode 100644 src/content/img/icon/edit/light.svg create mode 100644 src/content/img/icon/filter/light.svg create mode 100644 src/content/img/icon/folder/light.svg create mode 100644 src/content/img/icon/fullscreen/light.svg create mode 100644 src/content/img/icon/hash-sign/light.svg create mode 100644 src/content/img/icon/heart/light.svg create mode 100644 src/content/img/icon/help/light.svg create mode 100644 src/content/img/icon/info/light.svg create mode 100644 src/content/img/icon/launch/light.svg create mode 100644 src/content/img/icon/link/light.svg create mode 100644 src/content/img/icon/lock/light.svg create mode 100644 src/content/img/icon/logout/light.svg create mode 100644 src/content/img/icon/needs-update/light.svg create mode 100644 src/content/img/icon/notifications-off/light.svg create mode 100644 src/content/img/icon/notifications/light.svg create mode 100644 src/content/img/icon/offline/light.svg create mode 100644 src/content/img/icon/online/light.svg create mode 100644 src/content/img/icon/password/light.svg create mode 100644 src/content/img/icon/payment-card/light.svg create mode 100644 src/content/img/icon/photo/light.svg create mode 100644 src/content/img/icon/pin/light.svg create mode 100644 src/content/img/icon/remove/light.svg create mode 100644 src/content/img/icon/sad/light.svg create mode 100644 src/content/img/icon/save/light.svg create mode 100644 src/content/img/icon/scissors/light.svg create mode 100644 src/content/img/icon/search/light.svg create mode 100644 src/content/img/icon/settings/light.svg create mode 100644 src/content/img/icon/share/light.svg create mode 100644 src/content/img/icon/shield-bad/light.svg create mode 100644 src/content/img/icon/shield-good/light.svg create mode 100644 src/content/img/icon/shield-info/light.svg create mode 100644 src/content/img/icon/shield-off/light.svg create mode 100644 src/content/img/icon/shopping-cart/light.svg create mode 100644 src/content/img/icon/star-full/light.svg create mode 100644 src/content/img/icon/star/light.svg create mode 100644 src/content/img/icon/support/light.svg create mode 100644 src/content/img/icon/tag/light.svg create mode 100644 src/content/img/icon/threads/light.svg create mode 100644 src/content/img/icon/upload/light.svg create mode 100644 src/content/img/icon/user-add/light.svg create mode 100644 src/content/img/icon/user-check/light.svg create mode 100644 src/content/img/icon/user-circle/light.svg create mode 100644 src/content/img/icon/user-group/light.svg create mode 100644 src/content/img/icon/user-remove/light.svg create mode 100644 src/content/img/icon/user/light.svg create mode 100644 src/content/img/icon/warning/light.svg create mode 100644 src/content/img/icon/zoom-in/light.svg create mode 100644 src/content/img/icon/zoom-out/light.svg create mode 100644 src/content/img/profile/fallback.svg diff --git a/.gitignore b/.gitignore index d2b9f22..21335e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/src/sw-pre.js /src/content/papo.exported.js /src/content/sw.exported.js /src/content/service-worker.js diff --git a/Makefile b/Makefile index 669e9cc..f1e01eb 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,24 @@ .POSIX: -NAME = webapp +DATE = 1970-01-01 +VERSION = 0.1.0 +NAME = chat.papo.im +NAME_UC = $(NAME) +LANGUAGES = en +## Installation prefix. Defaults to "/usr". PREFIX = /usr +BINDIR = $(PREFIX)/bin +LIBDIR = $(PREFIX)/lib +INCLUDEDIR = $(PREFIX)/include SRCDIR = $(PREFIX)/src/$(NAME) SHAREDIR = $(PREFIX)/share -# DOCDIR? JavaScript goes to DOCDIR? Really? +LOCALEDIR = $(SHAREDIR)/locale +MANDIR = $(SHAREDIR)/man DOCDIR = $(SHAREDIR)/doc/$(NAME) +HTMLDIR = $(SHAREDIR)/html/$(NAME) +EXEC = ./ +## Where to store the installation. Empty by default. +DESTDIR = +LDLIBS = @@ -12,37 +26,51 @@ DOCDIR = $(SHAREDIR)/doc/$(NAME) .SUFFIXES: .js + all: include deps.mk - -static-contents = \ +sources = \ src/content/papo.js \ src/content/style.css \ src/content/index.html \ + src/content/sw.js \ + $(img.svg) \ contents = \ + src/content/papo.js \ + src/content/style.css \ + src/content/index.html \ src/content/service-worker.js \ $(img.svg) \ derived-assets = \ + src/sw-pre.js \ src/content/papo.exported.js \ src/content/sw.exported.js \ src/content/service-worker.js \ +side-assets = \ + +## Default target. Builds all artifacts required for testing +## and installation. all: $(derived-assets) +src/sw-pre.js: Makefile deps.mk + printf 'const IMG_PATHS = [\n' > $@ + printf '\t"%s",\n' $(img.svg) >> $@ + printf '];\n\n' >> $@ ## The use of static `import` statements inside service workers ## isn't supported. So in order to have tests for the code in ## it, a "main()" function is included in the generated file ## so that is can be ran as a standalone file. -src/content/service-worker.js: src/content/sw.js src/sw-main.js Makefile - cat src/content/sw.js src/sw-main.js > $@ +src/content/service-worker.js: src/sw-pre.js src/content/sw.js src/sw-main.js + tail -n+2 src/content/sw.js | cat src/sw-pre.js - src/sw-main.js > $@ src/content/papo.exported.js src/content/sw.exported.js: \ Makefile src/exported.sh @@ -60,38 +88,63 @@ tests/sw.js-check: src/content/sw.exported.js tests/papo.js-check tests/sw.js-check: node tests/node-driver.js $*.js +src/content/service-worker.js-check: src/content/service-worker.js + test "`grep -c '^const IMG_PATHS ' $*.js`" = 1 check-unit: tests/papo.js-check tests/sw.js-check +check-unit: src/content/service-worker.js-check + + +integration-tests = \ -check-integration: +.PRECIOUS: $(integration-tests) +$(integration-tests): ALWAYS + sh $@ +check-integration: $(integration-tests) + + +## Run all tests. Each test suite is isolated, so that a parallel +## build can run tests at the same time. The required artifacts +## are created if missing. check: check-unit check-integration + +## Remove *all* derived artifacts produced during the build. +## A dedicated test asserts that this is always true. clean: rm -rf $(derived-assets) $(side-assets) -install: all - mkdir -p \ - '$(DESTDIR)$(SRCDIR)' \ - for f in $(contents) $(static-contents); do \ - dir='$(DESTDIR)$(DOCDIR)'/"`dirname "$${f#src/content/}"`"; \ +## Installs into $(DESTDIR)$(PREFIX). Its dependency target +## ensures that all installable artifacts are crafted beforehand. +install: all + for f in $(contents); do \ + dir='$(DESTDIR)$(HTMLDIR)'/"`dirname "$${f#src/content/}"`"; \ + mkdir -p "$$dir"; \ + cp -P "$$f" "$$dir"; \ + done + for f in $(sources); do \ + dir='$(DESTDIR)$(SRCDIR)'/"`dirname "$${f#src/content/}"`"; \ mkdir -p "$$dir"; \ cp -P "$$f" "$$dir"; \ done +## Uninstalls from $(DESTDIR)$(PREFIX). This is a perfect mirror +## of the "install" target, and removes *all* that was installed. +## A dedicated test asserts that this is always true. uninstall: rm -rf \ '$(DESTDIR)$(SRCDIR)' \ - '$(DESTDIR)$(DOCDIR)' \ + '$(DESTDIR)$(HTMLDIR)' \ PORT = 3334 -## Run file server for local static files +## Run file server for local static files. run: - serve -n -p $(PORT) -d '$(DESTDIR)$(DOCDIR)' + serve -n -p $(PORT) -d '$(DESTDIR)$(HTMLDIR)' ALWAYS: diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..cf16c69 --- /dev/null +++ b/README.adoc @@ -0,0 +1,5 @@ +https://www.svgrepo.com/collection/kalai-oval-interface-icons/ + +https://www.svgrepo.com/collection/minimal-ui-icons/ +https://www.svgrepo.com/collection/chunk-16px-thick-interface-icons/ +https://perchance.org/ai-face-generator diff --git a/deps.mk b/deps.mk index b5d3842..f79c950 100644 --- a/deps.mk +++ b/deps.mk @@ -1,5 +1,70 @@ img.svg = \ src/content/img/favicon.svg \ + src/content/img/icon/add/light.svg \ + src/content/img/icon/archive/light.svg \ + src/content/img/icon/arrow-down/light.svg \ + src/content/img/icon/bookmark/light.svg \ + src/content/img/icon/calendar/light.svg \ + src/content/img/icon/check/light.svg \ + src/content/img/icon/chevron-down/light.svg \ + src/content/img/icon/chevron-left/light.svg \ + src/content/img/icon/chevron-right/light.svg \ + src/content/img/icon/clipboard/light.svg \ + src/content/img/icon/close/light.svg \ + src/content/img/icon/code-file/light.svg \ + src/content/img/icon/code/light.svg \ + src/content/img/icon/crop/light.svg \ + src/content/img/icon/delete/light.svg \ + src/content/img/icon/download/light.svg \ + src/content/img/icon/edit/light.svg \ + src/content/img/icon/filter/light.svg \ + src/content/img/icon/folder/light.svg \ + src/content/img/icon/fullscreen/light.svg \ + src/content/img/icon/hash-sign/light.svg \ + src/content/img/icon/heart/light.svg \ + src/content/img/icon/help/light.svg \ + src/content/img/icon/info/light.svg \ + src/content/img/icon/launch/light.svg \ + src/content/img/icon/link/light.svg \ + src/content/img/icon/lock/light.svg \ + src/content/img/icon/logout/light.svg \ + src/content/img/icon/needs-update/light.svg \ + src/content/img/icon/notifications-off/light.svg \ + src/content/img/icon/notifications/light.svg \ + src/content/img/icon/offline/light.svg \ + src/content/img/icon/online/light.svg \ + src/content/img/icon/password/light.svg \ + src/content/img/icon/payment-card/light.svg \ + src/content/img/icon/photo/light.svg \ + src/content/img/icon/pin/light.svg \ + src/content/img/icon/remove/light.svg \ + src/content/img/icon/sad/light.svg \ + src/content/img/icon/save/light.svg \ + src/content/img/icon/scissors/light.svg \ + src/content/img/icon/search/light.svg \ + src/content/img/icon/settings/light.svg \ + src/content/img/icon/share/light.svg \ + src/content/img/icon/shield-bad/light.svg \ + src/content/img/icon/shield-good/light.svg \ + src/content/img/icon/shield-info/light.svg \ + src/content/img/icon/shield-off/light.svg \ + src/content/img/icon/shopping-cart/light.svg \ + src/content/img/icon/star-full/light.svg \ + src/content/img/icon/star/light.svg \ + src/content/img/icon/support/light.svg \ + src/content/img/icon/tag/light.svg \ + src/content/img/icon/threads/light.svg \ + src/content/img/icon/upload/light.svg \ + src/content/img/icon/user-add/light.svg \ + src/content/img/icon/user-check/light.svg \ + src/content/img/icon/user-circle/light.svg \ + src/content/img/icon/user-group/light.svg \ + src/content/img/icon/user-remove/light.svg \ + src/content/img/icon/user/light.svg \ + src/content/img/icon/warning/light.svg \ + src/content/img/icon/zoom-in/light.svg \ + src/content/img/icon/zoom-out/light.svg \ src/content/img/logo/dark.svg \ src/content/img/logo/light.svg \ + src/content/img/profile/fallback.svg \ diff --git a/src/content/img/icon/add/light.svg b/src/content/img/icon/add/light.svg new file mode 100644 index 0000000..213a211 --- /dev/null +++ b/src/content/img/icon/add/light.svg @@ -0,0 +1,22 @@ + + + diff --git a/src/content/img/icon/archive/light.svg b/src/content/img/icon/archive/light.svg new file mode 100644 index 0000000..39229c0 --- /dev/null +++ b/src/content/img/icon/archive/light.svg @@ -0,0 +1,43 @@ + + + + + diff --git a/src/content/img/icon/arrow-down/light.svg b/src/content/img/icon/arrow-down/light.svg new file mode 100644 index 0000000..943a86f --- /dev/null +++ b/src/content/img/icon/arrow-down/light.svg @@ -0,0 +1,20 @@ + + + diff --git a/src/content/img/icon/bookmark/light.svg b/src/content/img/icon/bookmark/light.svg new file mode 100644 index 0000000..f61f094 --- /dev/null +++ b/src/content/img/icon/bookmark/light.svg @@ -0,0 +1,30 @@ + + + diff --git a/src/content/img/icon/calendar/light.svg b/src/content/img/icon/calendar/light.svg new file mode 100644 index 0000000..3ac4583 --- /dev/null +++ b/src/content/img/icon/calendar/light.svg @@ -0,0 +1,32 @@ + + + diff --git a/src/content/img/icon/check/light.svg b/src/content/img/icon/check/light.svg new file mode 100644 index 0000000..b226735 --- /dev/null +++ b/src/content/img/icon/check/light.svg @@ -0,0 +1,17 @@ + + + diff --git a/src/content/img/icon/chevron-down/light.svg b/src/content/img/icon/chevron-down/light.svg new file mode 100644 index 0000000..de1f8b1 --- /dev/null +++ b/src/content/img/icon/chevron-down/light.svg @@ -0,0 +1,17 @@ + + + diff --git a/src/content/img/icon/chevron-left/light.svg b/src/content/img/icon/chevron-left/light.svg new file mode 100644 index 0000000..bbdc4bc --- /dev/null +++ b/src/content/img/icon/chevron-left/light.svg @@ -0,0 +1,18 @@ + + + diff --git a/src/content/img/icon/chevron-right/light.svg b/src/content/img/icon/chevron-right/light.svg new file mode 100644 index 0000000..58631ed --- /dev/null +++ b/src/content/img/icon/chevron-right/light.svg @@ -0,0 +1,18 @@ + + + diff --git a/src/content/img/icon/clipboard/light.svg b/src/content/img/icon/clipboard/light.svg new file mode 100644 index 0000000..5705904 --- /dev/null +++ b/src/content/img/icon/clipboard/light.svg @@ -0,0 +1,41 @@ + + + + diff --git a/src/content/img/icon/close/light.svg b/src/content/img/icon/close/light.svg new file mode 100644 index 0000000..0a29350 --- /dev/null +++ b/src/content/img/icon/close/light.svg @@ -0,0 +1,26 @@ + + + + diff --git a/src/content/img/icon/code-file/light.svg b/src/content/img/icon/code-file/light.svg new file mode 100644 index 0000000..ae40206 --- /dev/null +++ b/src/content/img/icon/code-file/light.svg @@ -0,0 +1,52 @@ + + + + + diff --git a/src/content/img/icon/code/light.svg b/src/content/img/icon/code/light.svg new file mode 100644 index 0000000..7537e04 --- /dev/null +++ b/src/content/img/icon/code/light.svg @@ -0,0 +1,28 @@ + + + + diff --git a/src/content/img/icon/crop/light.svg b/src/content/img/icon/crop/light.svg new file mode 100644 index 0000000..f90ae13 --- /dev/null +++ b/src/content/img/icon/crop/light.svg @@ -0,0 +1,49 @@ + + + + diff --git a/src/content/img/icon/delete/light.svg b/src/content/img/icon/delete/light.svg new file mode 100644 index 0000000..a3e2adf --- /dev/null +++ b/src/content/img/icon/delete/light.svg @@ -0,0 +1,46 @@ + + + + + diff --git a/src/content/img/icon/download/light.svg b/src/content/img/icon/download/light.svg new file mode 100644 index 0000000..e937c56 --- /dev/null +++ b/src/content/img/icon/download/light.svg @@ -0,0 +1,26 @@ + + + diff --git a/src/content/img/icon/edit/light.svg b/src/content/img/icon/edit/light.svg new file mode 100644 index 0000000..eea0cef --- /dev/null +++ b/src/content/img/icon/edit/light.svg @@ -0,0 +1,29 @@ + + + diff --git a/src/content/img/icon/filter/light.svg b/src/content/img/icon/filter/light.svg new file mode 100644 index 0000000..dfb45ea --- /dev/null +++ b/src/content/img/icon/filter/light.svg @@ -0,0 +1,28 @@ + + + diff --git a/src/content/img/icon/folder/light.svg b/src/content/img/icon/folder/light.svg new file mode 100644 index 0000000..06bf56a --- /dev/null +++ b/src/content/img/icon/folder/light.svg @@ -0,0 +1,27 @@ + + + diff --git a/src/content/img/icon/fullscreen/light.svg b/src/content/img/icon/fullscreen/light.svg new file mode 100644 index 0000000..3dc2668 --- /dev/null +++ b/src/content/img/icon/fullscreen/light.svg @@ -0,0 +1,30 @@ + + + diff --git a/src/content/img/icon/hash-sign/light.svg b/src/content/img/icon/hash-sign/light.svg new file mode 100644 index 0000000..7dc713e --- /dev/null +++ b/src/content/img/icon/hash-sign/light.svg @@ -0,0 +1,22 @@ + + + diff --git a/src/content/img/icon/heart/light.svg b/src/content/img/icon/heart/light.svg new file mode 100644 index 0000000..ddf97cf --- /dev/null +++ b/src/content/img/icon/heart/light.svg @@ -0,0 +1,23 @@ + + + diff --git a/src/content/img/icon/help/light.svg b/src/content/img/icon/help/light.svg new file mode 100644 index 0000000..07ee03b --- /dev/null +++ b/src/content/img/icon/help/light.svg @@ -0,0 +1,44 @@ + + + + diff --git a/src/content/img/icon/info/light.svg b/src/content/img/icon/info/light.svg new file mode 100644 index 0000000..1f533f3 --- /dev/null +++ b/src/content/img/icon/info/light.svg @@ -0,0 +1,23 @@ + + + + diff --git a/src/content/img/icon/launch/light.svg b/src/content/img/icon/launch/light.svg new file mode 100644 index 0000000..78edfda --- /dev/null +++ b/src/content/img/icon/launch/light.svg @@ -0,0 +1,28 @@ + + + diff --git a/src/content/img/icon/link/light.svg b/src/content/img/icon/link/light.svg new file mode 100644 index 0000000..672c0d4 --- /dev/null +++ b/src/content/img/icon/link/light.svg @@ -0,0 +1,28 @@ + + + diff --git a/src/content/img/icon/lock/light.svg b/src/content/img/icon/lock/light.svg new file mode 100644 index 0000000..61a2d11 --- /dev/null +++ b/src/content/img/icon/lock/light.svg @@ -0,0 +1,38 @@ + + + diff --git a/src/content/img/icon/logout/light.svg b/src/content/img/icon/logout/light.svg new file mode 100644 index 0000000..1af7165 --- /dev/null +++ b/src/content/img/icon/logout/light.svg @@ -0,0 +1,30 @@ + + + diff --git a/src/content/img/icon/needs-update/light.svg b/src/content/img/icon/needs-update/light.svg new file mode 100644 index 0000000..8609c4e --- /dev/null +++ b/src/content/img/icon/needs-update/light.svg @@ -0,0 +1,38 @@ + + + + diff --git a/src/content/img/icon/notifications-off/light.svg b/src/content/img/icon/notifications-off/light.svg new file mode 100644 index 0000000..10a9fbc --- /dev/null +++ b/src/content/img/icon/notifications-off/light.svg @@ -0,0 +1,75 @@ + + + + + + diff --git a/src/content/img/icon/notifications/light.svg b/src/content/img/icon/notifications/light.svg new file mode 100644 index 0000000..22d3290 --- /dev/null +++ b/src/content/img/icon/notifications/light.svg @@ -0,0 +1,114 @@ + + + + + diff --git a/src/content/img/icon/offline/light.svg b/src/content/img/icon/offline/light.svg new file mode 100644 index 0000000..ad170d8 --- /dev/null +++ b/src/content/img/icon/offline/light.svg @@ -0,0 +1,61 @@ + + + + diff --git a/src/content/img/icon/online/light.svg b/src/content/img/icon/online/light.svg new file mode 100644 index 0000000..34d9a76 --- /dev/null +++ b/src/content/img/icon/online/light.svg @@ -0,0 +1,99 @@ + + + diff --git a/src/content/img/icon/password/light.svg b/src/content/img/icon/password/light.svg new file mode 100644 index 0000000..e967263 --- /dev/null +++ b/src/content/img/icon/password/light.svg @@ -0,0 +1,60 @@ + + + + + + diff --git a/src/content/img/icon/payment-card/light.svg b/src/content/img/icon/payment-card/light.svg new file mode 100644 index 0000000..144f1bb --- /dev/null +++ b/src/content/img/icon/payment-card/light.svg @@ -0,0 +1,37 @@ + + + + + diff --git a/src/content/img/icon/photo/light.svg b/src/content/img/icon/photo/light.svg new file mode 100644 index 0000000..ff7e5fb --- /dev/null +++ b/src/content/img/icon/photo/light.svg @@ -0,0 +1,35 @@ + + + + diff --git a/src/content/img/icon/pin/light.svg b/src/content/img/icon/pin/light.svg new file mode 100644 index 0000000..8ba078c --- /dev/null +++ b/src/content/img/icon/pin/light.svg @@ -0,0 +1,57 @@ + + + + diff --git a/src/content/img/icon/remove/light.svg b/src/content/img/icon/remove/light.svg new file mode 100644 index 0000000..8fa74e6 --- /dev/null +++ b/src/content/img/icon/remove/light.svg @@ -0,0 +1,13 @@ + + + diff --git a/src/content/img/icon/sad/light.svg b/src/content/img/icon/sad/light.svg new file mode 100644 index 0000000..72cece1 --- /dev/null +++ b/src/content/img/icon/sad/light.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + diff --git a/src/content/img/icon/save/light.svg b/src/content/img/icon/save/light.svg new file mode 100644 index 0000000..a83069f --- /dev/null +++ b/src/content/img/icon/save/light.svg @@ -0,0 +1,57 @@ + + + + + diff --git a/src/content/img/icon/scissors/light.svg b/src/content/img/icon/scissors/light.svg new file mode 100644 index 0000000..e344df3 --- /dev/null +++ b/src/content/img/icon/scissors/light.svg @@ -0,0 +1,55 @@ + + + + + + diff --git a/src/content/img/icon/search/light.svg b/src/content/img/icon/search/light.svg new file mode 100644 index 0000000..eb13d7b --- /dev/null +++ b/src/content/img/icon/search/light.svg @@ -0,0 +1,21 @@ + + + + diff --git a/src/content/img/icon/settings/light.svg b/src/content/img/icon/settings/light.svg new file mode 100644 index 0000000..a727183 --- /dev/null +++ b/src/content/img/icon/settings/light.svg @@ -0,0 +1,462 @@ + + + + diff --git a/src/content/img/icon/share/light.svg b/src/content/img/icon/share/light.svg new file mode 100644 index 0000000..83aabdf --- /dev/null +++ b/src/content/img/icon/share/light.svg @@ -0,0 +1,38 @@ + + + diff --git a/src/content/img/icon/shield-bad/light.svg b/src/content/img/icon/shield-bad/light.svg new file mode 100644 index 0000000..1ec8b64 --- /dev/null +++ b/src/content/img/icon/shield-bad/light.svg @@ -0,0 +1,36 @@ + + + diff --git a/src/content/img/icon/shield-good/light.svg b/src/content/img/icon/shield-good/light.svg new file mode 100644 index 0000000..18bf29a --- /dev/null +++ b/src/content/img/icon/shield-good/light.svg @@ -0,0 +1,31 @@ + + + diff --git a/src/content/img/icon/shield-info/light.svg b/src/content/img/icon/shield-info/light.svg new file mode 100644 index 0000000..6553c91 --- /dev/null +++ b/src/content/img/icon/shield-info/light.svg @@ -0,0 +1,36 @@ + + + + diff --git a/src/content/img/icon/shield-off/light.svg b/src/content/img/icon/shield-off/light.svg new file mode 100644 index 0000000..4e657b8 --- /dev/null +++ b/src/content/img/icon/shield-off/light.svg @@ -0,0 +1,51 @@ + + + + diff --git a/src/content/img/icon/shopping-cart/light.svg b/src/content/img/icon/shopping-cart/light.svg new file mode 100644 index 0000000..efb1072 --- /dev/null +++ b/src/content/img/icon/shopping-cart/light.svg @@ -0,0 +1,54 @@ + + + + + + diff --git a/src/content/img/icon/star-full/light.svg b/src/content/img/icon/star-full/light.svg new file mode 100644 index 0000000..6de5029 --- /dev/null +++ b/src/content/img/icon/star-full/light.svg @@ -0,0 +1,36 @@ + + + diff --git a/src/content/img/icon/star/light.svg b/src/content/img/icon/star/light.svg new file mode 100644 index 0000000..d60f636 --- /dev/null +++ b/src/content/img/icon/star/light.svg @@ -0,0 +1,36 @@ + + + diff --git a/src/content/img/icon/support/light.svg b/src/content/img/icon/support/light.svg new file mode 100644 index 0000000..2f651fc --- /dev/null +++ b/src/content/img/icon/support/light.svg @@ -0,0 +1,40 @@ + + + diff --git a/src/content/img/icon/tag/light.svg b/src/content/img/icon/tag/light.svg new file mode 100644 index 0000000..4867adc --- /dev/null +++ b/src/content/img/icon/tag/light.svg @@ -0,0 +1,32 @@ + + + + diff --git a/src/content/img/icon/threads/light.svg b/src/content/img/icon/threads/light.svg new file mode 100644 index 0000000..01e6383 --- /dev/null +++ b/src/content/img/icon/threads/light.svg @@ -0,0 +1,27 @@ + + + + + diff --git a/src/content/img/icon/upload/light.svg b/src/content/img/icon/upload/light.svg new file mode 100644 index 0000000..0abfd7b --- /dev/null +++ b/src/content/img/icon/upload/light.svg @@ -0,0 +1,26 @@ + + + diff --git a/src/content/img/icon/user-add/light.svg b/src/content/img/icon/user-add/light.svg new file mode 100644 index 0000000..eaf415b --- /dev/null +++ b/src/content/img/icon/user-add/light.svg @@ -0,0 +1,32 @@ + + + diff --git a/src/content/img/icon/user-check/light.svg b/src/content/img/icon/user-check/light.svg new file mode 100644 index 0000000..91d8e1b --- /dev/null +++ b/src/content/img/icon/user-check/light.svg @@ -0,0 +1,27 @@ + + + diff --git a/src/content/img/icon/user-circle/light.svg b/src/content/img/icon/user-circle/light.svg new file mode 100644 index 0000000..39a5cca --- /dev/null +++ b/src/content/img/icon/user-circle/light.svg @@ -0,0 +1,32 @@ + + + diff --git a/src/content/img/icon/user-group/light.svg b/src/content/img/icon/user-group/light.svg new file mode 100644 index 0000000..dd713ee --- /dev/null +++ b/src/content/img/icon/user-group/light.svg @@ -0,0 +1,33 @@ + + + diff --git a/src/content/img/icon/user-remove/light.svg b/src/content/img/icon/user-remove/light.svg new file mode 100644 index 0000000..83d91b5 --- /dev/null +++ b/src/content/img/icon/user-remove/light.svg @@ -0,0 +1,32 @@ + + + diff --git a/src/content/img/icon/user/light.svg b/src/content/img/icon/user/light.svg new file mode 100644 index 0000000..9f68ab9 --- /dev/null +++ b/src/content/img/icon/user/light.svg @@ -0,0 +1,26 @@ + + + diff --git a/src/content/img/icon/warning/light.svg b/src/content/img/icon/warning/light.svg new file mode 100644 index 0000000..d42c8f6 --- /dev/null +++ b/src/content/img/icon/warning/light.svg @@ -0,0 +1,38 @@ + + + + + diff --git a/src/content/img/icon/zoom-in/light.svg b/src/content/img/icon/zoom-in/light.svg new file mode 100644 index 0000000..b8f3022 --- /dev/null +++ b/src/content/img/icon/zoom-in/light.svg @@ -0,0 +1,41 @@ + + + + + diff --git a/src/content/img/icon/zoom-out/light.svg b/src/content/img/icon/zoom-out/light.svg new file mode 100644 index 0000000..a5b24bb --- /dev/null +++ b/src/content/img/icon/zoom-out/light.svg @@ -0,0 +1,29 @@ + + + + + diff --git a/src/content/img/profile/fallback.svg b/src/content/img/profile/fallback.svg new file mode 100644 index 0000000..9d6cf4b --- /dev/null +++ b/src/content/img/profile/fallback.svg @@ -0,0 +1 @@ +FIXME diff --git a/src/content/index.html b/src/content/index.html index ca012d4..ea7d5cc 100644 --- a/src/content/index.html +++ b/src/content/index.html @@ -1,22 +1,421 @@ - + - - Chat with Freedom | Papo FIXME + Papo -

Loading...

+
+ + + + +
+
+ +
+
+
+
+

+ #announcements + +

+
+
+ + + A hollowed outline icon of a person head and torso + + + 12 + +
+
+ + + FIXME + +
+

+ Channel description goes here. When it is too long, I need to add some logic to add trailing ellipsis... (and on hover show the rest?) +

+
+
+ +
+
+
+
+ Profile picture of user lisa>
+                <figcaption>
+                  <h3>
+                    lisa
+                  </h3>
+                  <time datetime= + 12:33PM + + +
+

+ yep, probably something that needs more work +

+

+ we'll see how far we can go with the current solution +

+
+
+
+ + +
+
+ +
diff --git a/src/content/papo.js b/src/content/papo.js index 6935d55..5a68d56 100644 --- a/src/content/papo.js +++ b/src/content/papo.js @@ -1,15 +1,22 @@ -// import * as assert from "node:assert/strict"; - +const f1 = x => x + 1; +const f2 = x => x - 1; -// assert.deepEqual({a: 1}, {a: 1}); -// console.log(123); -// console.log({ navigator }); +const configureStorage = async ({ navigator, err }) => { + const persistent = await navigator.storage?.persist?.(); + if (persistent === undefined) { + err(`Persistent storage is not supported.`); + return; + } -const f1 = x => x + 1; -const f2 = x => x - 1; + if (!persistent) { + err(`Persistent storage is not enabled.`); + return; + } +}; -const registerServiceWorker = async ({ serviceWorkerPath, err }) => { +const registerServiceWorker = async ({ serviceWorkerPath, navigator, err }) => { + // FIXME: add explanation for permission before requesting it. try { await navigator.serviceWorker?.register(serviceWorkerPath) } catch (e) { @@ -17,26 +24,19 @@ const registerServiceWorker = async ({ serviceWorkerPath, err }) => { } }; + + export const main = async ({ serviceWorkerPath = "./service-worker.js", - out = console.log, - err = console.warn, + mknavigator = () => navigator, + out = console.log, + err = console.warn, } = {}) => { const env = { serviceWorkerPath, out, err, + navigator: mknavigator(), }; - setTimeout(() => { - fetch("index.html", { - headers: { - "Connection": "upgrade", - "Content-Type": "application/json", - }, - }); - }, 1000); await registerServiceWorker(env); - // out("main called"); }; - -// diff --git a/src/content/style.css b/src/content/style.css index e69de29..ab5e956 100644 --- a/src/content/style.css +++ b/src/content/style.css @@ -0,0 +1,43 @@ +:root { + --color-fg: black; + --color-bg: white; + --color-pre-bg: #eee; + + --green: #1a7320; + + color: var(--color-fg); + background-color: var(--color-bg); +} + +@media (prefers-color-scheme: dark) { + :root { + --color-fg: white; + --color-bg: black; + --color-pre-bg: #111; + } + + a { + color: hsl(211, 100%, 60%); + &:visited { + color: hsl(242, 100%, 80%); + } + } +} + + +pre, code { + background-color: var(--color-pre-bg); + border-radius: 5px; + padding: 5px; +} + +body { + font-family: sans-serif; + /* prevent pull to refresh */ + overscroll-behaviour-y: contain; +} + + +.unselectable { + user-select: none; +} diff --git a/src/content/sw.js b/src/content/sw.js index 03a09e4..51089f2 100644 --- a/src/content/sw.js +++ b/src/content/sw.js @@ -1,11 +1,6 @@ -const CACHE_NAME = "static-shared-assets"; +const IMG_PATHS = []; -const FALLBACK_PATHS = { - img: "/fallback-image-FIXME.svg", - data: { - static: "/fallback-data-FIXME.json", - }, -}; +const CACHE_NAME = "static-shared-assets"; const leafValues = tree => Object.values(tree).map(x => @@ -17,65 +12,86 @@ const leafValues = tree => const collectLeaves = tree => leafValues(tree).flat(Infinity); -const DEFAULT_INSTALL_PATHS = [ - "/", - "index.html", - "style.css", - "img/favicon.svg", - // "papo.js", -// ].concat(collectLeaves(FALLBACK_PATHS)); -]; - -const mkInstallHandler = ({ self, caches }) => event => { - self.skipWaiting(); - event.waitUntil( - caches.open(CACHE_NAME).then( - cache => cache.addAll(DEFAULT_INSTALL_PATHS), - ), - ); -}; const store = async (caches, request, response) => { const cache = await caches.open(CACHE_NAME); await cache.put(request, response); }; -const getPrefixIn = (paths, segments) => { - if (paths === undefined) { - return null; +const matchRoute = (segments, table) => { + if (segments.length === 0) { + return table ?? null; } - if (segments.length === 0) { + const simpleMatch = matchRoute(segments.slice(1), table?.[segments[0]]); + if (simpleMatch !== null) { + return simpleMatch; + } + + const hasGlob = table?.["*"] !== undefined; + if (!hasGlob) { return null; } - if (typeof paths === "string") { - return paths; + const keys = Object.keys(table); + const isTrailing = keys.length === 1 || ( + keys.length === 2 && + table[""] !== undefined + ); + if (isTrailing) { + return table["*"][""]; + } + + return matchRoute(segments.slice(1), table["*"]); +}; + +const fromCache = async ({ caches }, { event: { request } }) => { + const cache = await caches.open(CACHE_NAME); + return await cache.match(request); +} + +const fromNetwork = async ( + _env, + { fetch, event: { request, preloadResponse } }, +) => { + const preloadedResponse = await preloadResponse; + if (preloadResponse) { + return preloadResponse; } - return getPrefixIn(paths[segments[0]], segments.slice(1)); + return await fetch(request); +}; + +const networkThanCache = async (env, ctx) => { + const networkResponse = fromNetwork(env, ctx); + store(env.caches, ctx.event.request, networkResponse.clone()); + return networkResponse; }; -const fromCache = async (caches, fetch, { request, preloadResponse }) => { - const cachedResponse = await caches.match(request); +const immutableGet = async (env, ctx) => { + const cachedResponse = await fromCache(env, ctx); if (cachedResponse) { - fetch(request).then(async freshResponse => - store(caches, request, freshResponse)); return cachedResponse; } - const preloadedResponse = await preloadResponse; - if (preloadedResponse) { - store(caches, request, preloadeResponse.clone()); - return preloadedResponse; - } + const response = fromNetwork(env, ctx); + store(env.caches, ctx.event.request, response); + return response; +} +const staleOK = async (env, ctx) => { + return Promise.any([ + fromCache(env, ctx), + networkThanCache(env, ctx), + ]); +}; + +const staleOrFallback = async (env, ctx) => { try { - const fetchedResponse = await fetch(request); - store(caches, request, fetchedResponse.clone()); - return fetchedResponse; + return await staleOK(env, ctx); } catch (e) { - const fallbackResponse = await maybeFallback(caches, request); + const fallbackRoute = ctx.strategy.match; + const fallbackResponse = await env.caches.match(fallbackRoute); if (fallbackResponse) { return fallbackResponse; } @@ -84,121 +100,105 @@ const fromCache = async (caches, fetch, { request, preloadResponse }) => { } }; -const maybeFallback = async (caches, request, paths = FALLBACK_PATHS) => { - const url = new URL(request.url) - const segments = url.pathname.split("/").filter(s => !!s) - const fallbackPath = getPrefixIn(paths, segments); - - if (fallbackPath) { - return await caches.match(fallbackPath); - } - return null; -} - -const CONFIG_PATHS = { - immutable: { - "some": { - "path": true, - }, - }, - staleOK: { - }, -}; -const PRIORITY_ORDERING = [ - "immutable", - "staleFallback", - "stale", -]; - -const pullThroughCache = (env, ctx) => { -}; - -/* -// FIXME: handle base paths - const STRATEGIES = [ +const STRATEGIES = [ { - name: "immutable", + fn: immutableGet, routes: new Set([ - "/cas", + "cas/*", ]), - fn: immutable, }, { - name: "staleFallback", - routes: { - "/img/icon/": "", - }, - fn: staleFallback, + fn: staleOK, + routes: new Set([ + "", // FIXME: should be equivalent to "./", not "/" + "index.html", + "style.css", + "papo.js", + ...IMG_PATHS, + ]), }, { - name: "staleOnly", + fn: staleOrFallback, routes: new Set([ - // FIXME: add "/" - "/index.html": true, - "/style.css": true, - "/papo.js": true, + ["img/profile/*", "img/profile/fallback.svg"], ]), - img: "/fallback-image-FIXME.svg", - data: { - static: "/fallback-data-FIXME.json", }, - fn: staleOnly, + { + fn: fromNetwork, + routes: new Set([ + "*" + ]), }, -}; -*/ - -const asSegments = pathname => - pathname.split("/").filter(s => !!s); - -const requestSegments = ({ url }) => - asSegments(new URL(url).pathname); +]; -/* - const strategyFor = (segments, paths = CONFIG_PATHS) => { - for (const strategy of PRIORITY_ORDERING) { - if (getPrefixIn(paths[strategy.name], segments)) { - return strategy; +const strategyFor = (segments, baseSegments, strategies = STRATEGIES) => { + const effectiveSegments = segments.slice(baseSegments.length); + for (const strategy of strategies) { + const match = matchRoute(effectiveSegments, strategy.routes); + if (match) { + return { ...strategy, match }; } } }; -*/ -const networkOnly = async (_env, { fetch, event }) => { - const preloaded = await event.preloadResponse; - if (preloaded) { - return preloaded; - } +const normalizeSegments = segments => + segments.concat( + segments.length === 1 && segments[0] === "" + ? [] + : [""] + ); + +const pathToSegments = path => + normalizeSegments(path + .replace(/^\/*/, "") + .replace( /\/*$/, "") + .replace(/\/+/, "/") + .split("/")); - return await fetch(event.request); +const hasPathParams = segments => + segments.some(s => s.startsWith(":")); + +const flatten = arr => + arr.flat(Infinity); + + +/// We don't use `cache.addAll()` since we can tolerate failure to add individual +/// items, and we'd rather have a partially filled cache over an empty one. +const populateCache = async ({ caches }, paths = DEFAULT_INSTALL_PATHS) => { + const cache = await caches.open(CACHE_NAME); + return Promise.all(paths.map(cache.add)); }; -const strategyFor = (segments, paths = CONFIG_PATHS) => { - return networkOnly; +/// We don't `event.waitUntil()`, so that we can be activated sooner. +const mkInstallHandler = env => async event => { + self.skipWaiting(); + populateCache(env); }; +const mkActivateHandler = ({ self, clients }) => event => + event.waitUntil(Promise.all([ + self.registration.navigationPreload?.enable(), + clients.claim(), + ])); + // FIXME: noop if "Connection": "Upgrade" is in header // if (event.request.headers.get("Connection").toLowerCase() == "upgrade"); // out([...event.request.headers.entries()]); -const mkFetchHandler = env => (event, mkfetch = () => fetch) => { +const mkFetchHandler = env => async (event, mkfetch = () => fetch) => { if (event.request.method !== "GET") { return; } - const segments = requestSegments(event.request); - const strategyFn = strategyFor(segments); - event.respondWith(strategyFn(env, { + const segments = pathToSegments(new URL(event.request.url).pathname); + const strategy = strategyFor(segments, env.baseSegments); + event.respondWith(strategy.fn(env, { event, segments, + strategy, fetch: mkfetch(), })); }; -const mkActivateHandler = ({ self, clients }) => event => - event.waitUntil(Promise.all([ - clients.claim(), - self.registration.navigationPreload?.enable(), - ])); - const registerListeners = env => { env.self.addEventListener("install", mkInstallHandler(env)); env.self.addEventListener("activate", mkActivateHandler(env)); @@ -220,3 +220,23 @@ const main = ({ out, err, }); + +// handy resources for pushes: +// https://web.dev/articles/offline-cookbook +// https://web.dev/articles/push-notifications-overview +// https://developer.chrome.com/blog/background-sync +// https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/push +// https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/background-syncs + +// https://web.dev/learn/forms + +// https://alistapart.com/article/responsive-web-design/ + +// https://developer.chrome.com/docs/workbox/modules/workbox-background-sync + +// https://www.npmjs.com/package/idb +// https://web.dev/articles/indexeddb-best-practices-app-state + +// https://web.dev/learn/pwa/app-design +// https://web.dev/articles/accent-color +// https://jakearchibald.com/2016/caching-best-practices/#max-age-on-mutable-content-is-often-the-wrong-choice diff --git a/tests/browser-driver.js b/tests/browser-driver.js index 529d824..aa02c07 100644 --- a/tests/browser-driver.js +++ b/tests/browser-driver.js @@ -38,6 +38,7 @@ const conf = { }, }; + const TEST_PATHS = [ "tests/papo.js", "tests/sw.js", diff --git a/tests/driver.html b/tests/driver.html index e4508ec..687d704 100644 --- a/tests/driver.html +++ b/tests/driver.html @@ -4,7 +4,7 @@ - Papo | webapp tests + Papo | chat.papo.im test suite