Compare commits
489 Commits
Author | SHA1 | Date | |
---|---|---|---|
09ae4e2096 | |||
0b46efe4ea | |||
f1dda43e66 | |||
ce483138d7 | |||
73cc39226d | |||
57257f63dd | |||
88b25790e8 | |||
e01defc4aa | |||
cb50c43e93 | |||
5908d15f91 | |||
f66cfaec12 | |||
259f92c53b | |||
a84f850e91 | |||
5a765e6f07 | |||
791889c659 | |||
5da63faf1f | |||
30d108fc35 | |||
a09fefab5e | |||
f74ca1c236 | |||
30e027092b | |||
fd4ac7c9b9 | |||
4482049b94 | |||
5839380437 | |||
2152470fdc | |||
93b2a81495 | |||
e139e952c0 | |||
cf1c57ccb8 | |||
f7a2138488 | |||
9614d03bef | |||
32a335c676 | |||
06e27fc1e0 | |||
1f40e8dcd9 | |||
77ff8cef1f | |||
ef844fbccb | |||
070dc5a4c0 | |||
177ef1cdcc | |||
4b1ebf02e1 | |||
863e50203e | |||
01b8c209de | |||
30e92f2bc1 | |||
02accabb4a | |||
fa00a41fe0 | |||
2e66666bdf | |||
4fe3c9a751 | |||
0a35e14590 | |||
e979c176e3 | |||
a0d9c3dc29 | |||
efcb68351c | |||
94e8bf2e1c | |||
82d1a294a6 | |||
de20274589 | |||
2f193e64c8 | |||
86751362cb | |||
4118323631 | |||
0d134f7f10 | |||
409724cfcd | |||
799a33be40 | |||
2fa9c66495 | |||
ad818a8e7e | |||
581f72b3f8 | |||
1dd7e4347c | |||
36cc9398c7 | |||
68817feeec | |||
97661e2ca2 | |||
72def5ae6d | |||
e638b155a1 | |||
32db18b0d6 | |||
b653a5250d | |||
30329f7cad | |||
29a1478c86 | |||
c882bf31ec | |||
17ccb8f083 | |||
0e7d2a8b0e | |||
3743543ef8 | |||
700dd7b45a | |||
c2eb73fd8a | |||
e1f4f7f95b | |||
37401409c6 | |||
b282631cd5 | |||
9618d3b3f3 | |||
c9f997d121 | |||
f1dee2a089 | |||
8273277c91 | |||
9758844da3 | |||
e41c7fbbc7 | |||
24db8a5a49 | |||
36e82b9873 | |||
8a32f2b8b1 | |||
277830bc3c | |||
a8fa969114 | |||
c3f3dced68 | |||
85fce59c0c | |||
8a6147d512 | |||
e799b256b2 | |||
b222dc0ca8 | |||
c52c6b04ca | |||
b95eed46bb | |||
7c36a543da | |||
90e000c18e | |||
1bb9d737d8 | |||
9a5db2ec51 | |||
dbed29a044 | |||
681859531c | |||
8e1ad6b16a | |||
5448f1ba2d | |||
e43da4e1a3 | |||
eaa9da49cc | |||
40873b529c | |||
8cc4c19d73 | |||
bb9c18faf1 | |||
fabdfb76b9 | |||
bce263a928 | |||
195920e476 | |||
a821d895c5 | |||
ab1b6ec27d | |||
6dc099809f | |||
03c8b75994 | |||
38887452ad | |||
7512edad59 | |||
944c895bcd | |||
e7d87ee8e2 | |||
cfdbd10635 | |||
d3a2d8733f | |||
a7e623d817 | |||
3f0c37cea4 | |||
2c96a6d22a | |||
57b4214a72 | |||
433b3d39d9 | |||
26441ed45c | |||
92cd38c2a0 | |||
3b5a06794f | |||
d104409272 | |||
e5f58c2898 | |||
f83863ef01 | |||
837f069cf5 | |||
9f057dc29a | |||
c4904f176c | |||
d3a5aba703 | |||
9e283e427c | |||
133ba31d66 | |||
241a65a92a | |||
0b54795bab | |||
6208193de5 | |||
c53321532f | |||
34f25e3e06 | |||
c46244366e | |||
6518af04fc | |||
bf137ff1f7 | |||
1877955b62 | |||
50d0875de2 | |||
bf151e6b7d | |||
82893402d0 | |||
8049102787 | |||
f42cc3d9fd | |||
5f9a5208db | |||
6df506d238 | |||
2bd3354256 | |||
b55aaa1d18 | |||
34e19505bd | |||
6e06ec0904 | |||
a5814074fe | |||
d7479df5a2 | |||
34508aa0ae | |||
ae096b2c9c | |||
95d036e34a | |||
4af5e8ec42 | |||
2a5f71bd5d | |||
97fb63dda1 | |||
87d42e3b3b | |||
0394129a4c | |||
3c499c834b | |||
17d6cc7d46 | |||
646bd7dc38 | |||
56e483782d | |||
e1b9066b26 | |||
7114ce2516 | |||
9240c6570a | |||
f80a44ccd7 | |||
e6f5eb244e | |||
ab62e83110 | |||
aeefb9e536 | |||
ee0efa536a | |||
2523130fdc | |||
c024777184 | |||
5951d7cd2d | |||
011670c70b | |||
6cebd6c769 | |||
546ae5cbf1 | |||
f543cc642e | |||
8ac3c5ea22 | |||
63918f0680 | |||
bfb3d8b8a2 | |||
e38ff99607 | |||
b0e3d922c8 | |||
a15bb8e994 | |||
6f487100cd | |||
0693a2315f | |||
f360e886ff | |||
6ea08cc5dc | |||
347c706d6f | |||
5f5e6616c7 | |||
657bcadc7e | |||
107666cc60 | |||
b37669184a | |||
163a01f224 | |||
3d58094199 | |||
463951a4f1 | |||
34804d5162 | |||
3895c33915 | |||
17f4eb1a56 | |||
0abdffdea6 | |||
d32999f178 | |||
f621feb843 | |||
8d277f029d | |||
1788a02338 | |||
ba0800d16c | |||
4008c7d8f6 | |||
610a2e2afc | |||
6f3715d1eb | |||
b78ecaa814 | |||
e6f5399d53 | |||
0e5806cadd | |||
68c9d4afa7 | |||
f0ea38fe49 | |||
b0332f923e | |||
8a76c25394 | |||
fd96126e3e | |||
ff3fbedc18 | |||
8791419f8e | |||
5447b247a0 | |||
aabbb10564 | |||
3ccd6c9a3e | |||
c290240de7 | |||
8e799b174b | |||
a9c3a93989 | |||
3ef8698f42 | |||
fa4e843c30 | |||
9a4d11f4d9 | |||
eed2b8d618 | |||
13f02c2aca | |||
d50f8fbc8b | |||
155238a516 | |||
427fcdbdca | |||
ca05d402a7 | |||
c5a80b68ca | |||
c1fb15b135 | |||
4b2c131836 | |||
9ca1e69b3c | |||
082d041d44 | |||
221f276c4b | |||
24cec21465 | |||
9f71ec6194 | |||
bb36afc390 | |||
b53bf0ff64 | |||
3ebc6f2436 | |||
2eef6778a6 | |||
81fabec810 | |||
dc6e7924b5 | |||
48dec5a2c8 | |||
9b500e1da9 | |||
a038820112 | |||
70a15973b6 | |||
09b6a00731 | |||
883c3cf0e9 | |||
a46bb8183c | |||
d5d5a7b012 | |||
a120efdc91 | |||
d48f4b06eb | |||
f078912736 | |||
63b0f0dedd | |||
84c22dbf5f | |||
b8cd1232be | |||
a518ab07f4 | |||
9e5a1ee975 | |||
95bf3f0316 | |||
d69dd513bc | |||
525cdf571a | |||
9cfe0a8804 | |||
50b54599ef | |||
ed6bef6d24 | |||
71268636df | |||
568729ecd6 | |||
9139725be6 | |||
969a8da6bf | |||
2338b26329 | |||
d4df206740 | |||
8a93cdd33c | |||
92b31de4a9 | |||
5452f3f623 | |||
256614dbaf | |||
049449b213 | |||
85b46336b1 | |||
590afa7b01 | |||
574292b798 | |||
21cf503a59 | |||
3630cdbfe0 | |||
0f3be229e6 | |||
8e5a024d3d | |||
410bb7c09d | |||
9de8b0f449 | |||
d47c3a1222 | |||
df99b3aa90 | |||
0090850e10 | |||
9efd64bd18 | |||
b16c37e48b | |||
3ee2c00726 | |||
d5a7e19f1a | |||
9b52415b35 | |||
dbe24494d9 | |||
3eab5a5f70 | |||
548febfb22 | |||
b40f72443a | |||
2c03496373 | |||
b6a937c954 | |||
63776d40bd | |||
cb3c7afade | |||
991022adfc | |||
2bc71a18a6 | |||
57ca864fbb | |||
a09edfb612 | |||
7997a739ab | |||
248b258413 | |||
0423ed7fb4 | |||
c29378c2f8 | |||
163fbd85e7 | |||
58bb86ebe1 | |||
c5140ee8e8 | |||
6270fd8118 | |||
3fff706848 | |||
c259defab5 | |||
e5fee5c306 | |||
9d35b4bdfb | |||
9497d7cf64 | |||
c7d3e602cb | |||
0076eb4ed4 | |||
6070bde413 | |||
c7a6d426f0 | |||
f66cf0f802 | |||
e4b6c81024 | |||
44d784cd04 | |||
0394201113 | |||
e270c16516 | |||
4c10538632 | |||
71329c5532 | |||
feb4bf9e87 | |||
5d5567e94c | |||
684e6fb9cb | |||
ee21fa6d03 | |||
7a2974e54f | |||
f4dfc1dd98 | |||
2eebfa9a7a | |||
10097ffeb8 | |||
cbe1f54a2a | |||
4d8f081a59 | |||
29e79c9484 | |||
ba35869b0a | |||
580688381e | |||
e63d69a440 | |||
be64fe04fb | |||
801ab20723 | |||
d974a5e044 | |||
1be94ae0be | |||
b883e6a485 | |||
a0210379ae | |||
e56dc207d1 | |||
523c9c9ad2 | |||
74bb2151c1 | |||
f79d7b35a4 | |||
3b36496dac | |||
4ebd6c24a9 | |||
05451d98b3 | |||
22a4bce3c8 | |||
76d499f00b | |||
f0772f9b99 | |||
46e711f0a5 | |||
abffac3f82 | |||
27b275548e | |||
93ce253d1e | |||
a5af312b39 | |||
4b5e8e8a43 | |||
443dd4d168 | |||
907479df84 | |||
9887a78e98 | |||
f669371349 | |||
24c720c79a | |||
4485234980 | |||
b6871c0b1f | |||
47838d5e48 | |||
69fccd56d3 | |||
ca00c4fb5d | |||
427ca3f265 | |||
c1a80e50e7 | |||
52962f3a5e | |||
b3f095b61f | |||
a5004c8ba9 | |||
7d9b1b508b | |||
5e265dfc83 | |||
3a43d6f8ac | |||
11a6649847 | |||
7caf4a0173 | |||
385524352c | |||
5ca5323782 | |||
ba6da856bb | |||
c0e72246cc | |||
c7ab5447ea | |||
5fdd461159 | |||
421955f2a0 | |||
a28f6985ed | |||
8244dddab7 | |||
a5ca436eaa | |||
d7fc1c2c88 | |||
382627ef8d | |||
17667b4cf8 | |||
5231ec22e7 | |||
929ae1b709 | |||
f01f7a5ab9 | |||
a2dce833f8 | |||
de6c7a4fd4 | |||
4edee0f7f6 | |||
988a807fa4 | |||
5258e4253d | |||
09ba86dec5 | |||
78d8a1aa23 | |||
22def15209 | |||
4cbda7a849 | |||
be85a620ef | |||
0b07b678b4 | |||
4733ce9287 | |||
48d6bf4c15 | |||
8c759bcbac | |||
b5ed7014f6 | |||
6cd9dea186 | |||
202b416acf | |||
93d46f5610 | |||
c5ddf3ac99 | |||
a9cb913a47 | |||
b7b5d4f1a5 | |||
a947396bad | |||
d528bc808e | |||
c6fd05c2cf | |||
d6bb9d311a | |||
53b4cbbf8c | |||
628716ec28 | |||
bd14168627 | |||
96037d4da6 | |||
5448e773d8 | |||
848ef21c7c | |||
2ecae7da93 | |||
d9ce569eb9 | |||
eacaf392b1 | |||
ce16592b6a | |||
295d76d354 | |||
23b3c998bd | |||
b5e966c9a1 | |||
96cb6f4b12 | |||
e2c0f82ec0 | |||
dbf28c03e6 | |||
26165e30de | |||
c52331a23a | |||
8007e71e1d | |||
28d08e013f | |||
64bbd383de | |||
8a9f53102b | |||
0412b97170 | |||
c8b8a8fc03 | |||
95d3090b9b | |||
49129ee6dd | |||
6a7ecb0d4a | |||
1ceeed1007 | |||
a7922ff44e | |||
a421604ed5 | |||
7d182db32f | |||
c5cb9979d3 | |||
b9a73106ed | |||
c674cca482 | |||
81d1228b92 | |||
6ae61d5b81 | |||
9cb872eec2 | |||
68e8c010b7 | |||
9671413906 | |||
4c8d24c319 | |||
e50144bd34 | |||
9f3171e3f1 | |||
cc92748747 | |||
0a0b0c1adb | |||
92a74026a6 | |||
3fa1c6c420 | |||
b04eccdbda | |||
9ce30dee70 |
@ -14,7 +14,7 @@ IndentWidth: 4
|
|||||||
MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 1
|
||||||
ObjCBlockIndentWidth: 4
|
ObjCBlockIndentWidth: 4
|
||||||
ObjCBreakBeforeNestedBlockParam: false
|
ObjCBreakBeforeNestedBlockParam: false
|
||||||
SortIncludes: false
|
SortIncludes: true
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
UseTab: Always
|
UseTab: Always
|
||||||
...
|
...
|
||||||
|
38
.gitea/workflows/build.yaml
Normal file
38
.gitea/workflows/build.yaml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
name: Build Tilde Friends
|
||||||
|
run-name: ${{ gitea.actor }} running 🚀
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Build-All:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
valid_volumes: ['/opt/keys']
|
||||||
|
volumes:
|
||||||
|
- /opt/keys:/opt/keys
|
||||||
|
steps:
|
||||||
|
- name: check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- run: ln -s /opt/keys .keys
|
||||||
|
- name: Setup JDK
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Setup Android SDK
|
||||||
|
uses: android-actions/setup-android@v3
|
||||||
|
with:
|
||||||
|
packages: 'tools platform-tools build-tools;34.0.0 platforms;android-34 ndk;26.3.11579264'
|
||||||
|
- run: sudo apt update && sudo apt install -y doxygen graphviz mingw-w64 libgpgme11
|
||||||
|
- run: ANDROID_SDK=$HOME/.android/sdk make -j`nproc` all docs
|
||||||
|
- run: docker build .
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
path: out/TildeFriends-release.fdroid.apk
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
path: out/winrelease/tildefriends.exe
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
path: out/tildefriends-x86_64.AppImage
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,10 +1,18 @@
|
|||||||
|
build/
|
||||||
|
*.core
|
||||||
db.*
|
db.*
|
||||||
deps/ios_toolchain/
|
deps/ios_toolchain/
|
||||||
deps/openssl/
|
deps/openssl/
|
||||||
dist/
|
dist/
|
||||||
|
.flatpak-builder
|
||||||
.keys
|
.keys
|
||||||
|
logs/
|
||||||
**/node_modules
|
**/node_modules
|
||||||
out
|
out
|
||||||
|
repo/
|
||||||
|
result
|
||||||
*.swo
|
*.swo
|
||||||
*.swp
|
*.swp
|
||||||
|
tmp/
|
||||||
|
unsigned/
|
||||||
.zsign_cache/
|
.zsign_cache/
|
||||||
|
28
.gitmodules
vendored
Normal file
28
.gitmodules
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[submodule "deps/zlib"]
|
||||||
|
path = deps/zlib
|
||||||
|
url = https://github.com/madler/zlib.git
|
||||||
|
[submodule "deps/libsodium"]
|
||||||
|
path = deps/libsodium
|
||||||
|
url = https://github.com/jedisct1/libsodium.git
|
||||||
|
[submodule "deps/quickjs"]
|
||||||
|
path = deps/quickjs
|
||||||
|
url = https://github.com/bellard/quickjs.git
|
||||||
|
[submodule "deps/crypt_blowfish"]
|
||||||
|
path = deps/crypt_blowfish
|
||||||
|
url = https://github.com/openwall/crypt_blowfish.git
|
||||||
|
[submodule "deps/libbacktrace"]
|
||||||
|
path = deps/libbacktrace
|
||||||
|
url = https://github.com/ianlancetaylor/libbacktrace.git
|
||||||
|
[submodule "deps/libuv"]
|
||||||
|
path = deps/libuv
|
||||||
|
url = https://github.com/libuv/libuv.git
|
||||||
|
[submodule "deps/picohttpparser"]
|
||||||
|
path = deps/picohttpparser
|
||||||
|
url = https://github.com/h2o/picohttpparser.git
|
||||||
|
[submodule "deps/openssl_src"]
|
||||||
|
path = deps/openssl_src
|
||||||
|
url = https://github.com/openssl/openssl.git
|
||||||
|
shallow = true
|
||||||
|
[submodule "deps/c-ares"]
|
||||||
|
path = deps/c-ares
|
||||||
|
url = https://github.com/c-ares/c-ares.git
|
@ -2,6 +2,7 @@ node_modules
|
|||||||
src
|
src
|
||||||
deps
|
deps
|
||||||
.clang-format
|
.clang-format
|
||||||
|
flake.lock
|
||||||
|
|
||||||
# Minified files
|
# Minified files
|
||||||
**/*.min.css
|
**/*.min.css
|
||||||
|
362
GNUmakefile
362
GNUmakefile
@ -3,12 +3,14 @@
|
|||||||
MAKEFLAGS += --warn-undefined-variables
|
MAKEFLAGS += --warn-undefined-variables
|
||||||
MAKEFLAGS += --no-builtin-rules
|
MAKEFLAGS += --no-builtin-rules
|
||||||
|
|
||||||
VERSION_CODE := 17
|
VERSION_CODE := 30
|
||||||
VERSION_NUMBER := 0.0.17
|
VERSION_NUMBER := 0.0.25-wip
|
||||||
VERSION_NAME := Please enjoy responsibly.
|
VERSION_NAME := This program kills fascists.
|
||||||
|
|
||||||
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3450200.zip
|
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3470000.zip
|
||||||
LIBUV_URL := https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz
|
BUNDLETOOL_URL := https://github.com/google/bundletool/releases/download/1.17.0/bundletool-all-1.17.0.jar
|
||||||
|
APPIMAGETOOL_URL := https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||||
|
APPIMAGETOOL_MD5 := e989fadfc4d685fd3d6aeeb9b525d74d out/appimagetool
|
||||||
|
|
||||||
PROJECT = tildefriends
|
PROJECT = tildefriends
|
||||||
BUILD_DIR ?= out
|
BUILD_DIR ?= out
|
||||||
@ -16,6 +18,12 @@ UNAME_S := $(shell uname -s)
|
|||||||
UNAME_M := $(shell uname -m)
|
UNAME_M := $(shell uname -m)
|
||||||
|
|
||||||
ANDROID_SDK ?= ~/Android/Sdk
|
ANDROID_SDK ?= ~/Android/Sdk
|
||||||
|
BUNDLETOOL = out/bundletool.jar
|
||||||
|
|
||||||
|
HAVE_WIN := 0
|
||||||
|
|
||||||
|
export SOURCE_DATE_EPOCH=1
|
||||||
|
export TZ=UTC
|
||||||
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
BUILD_TYPES := macosdebug macosrelease iosdebug iosrelease iossimdebug iossimrelease
|
BUILD_TYPES := macosdebug macosrelease iosdebug iosrelease iossimdebug iossimrelease
|
||||||
@ -29,7 +37,8 @@ BUILD_TYPES := debug release
|
|||||||
CFLAGS += -Dstatic_assert=_Static_assert
|
CFLAGS += -Dstatic_assert=_Static_assert
|
||||||
LDFLAGS += \
|
LDFLAGS += \
|
||||||
-lbsd \
|
-lbsd \
|
||||||
-lnetwork
|
-lnetwork \
|
||||||
|
-Wno-stringop-overflow
|
||||||
else ifeq ($(UNAME_S),OpenBSD)
|
else ifeq ($(UNAME_S),OpenBSD)
|
||||||
BUILD_TYPES := debug release
|
BUILD_TYPES := debug release
|
||||||
CFLAGS += \
|
CFLAGS += \
|
||||||
@ -39,7 +48,6 @@ LDFLAGS += \
|
|||||||
-lc++abi
|
-lc++abi
|
||||||
HAVE_ANDROID := 0
|
HAVE_ANDROID := 0
|
||||||
HAVE_LINUX_IOS := 0
|
HAVE_LINUX_IOS := 0
|
||||||
HAVE_WIN := 0
|
|
||||||
else
|
else
|
||||||
$(error Unexpected host platform $(UNAME_S).)
|
$(error Unexpected host platform $(UNAME_S).)
|
||||||
endif
|
endif
|
||||||
@ -49,18 +57,23 @@ CFLAGS += \
|
|||||||
-Wall \
|
-Wall \
|
||||||
-Wextra \
|
-Wextra \
|
||||||
-Wno-unused-parameter \
|
-Wno-unused-parameter \
|
||||||
|
-Wno-unknown-warning-option \
|
||||||
-MMD \
|
-MMD \
|
||||||
-MP \
|
-MP \
|
||||||
-ffunction-sections \
|
-ffunction-sections \
|
||||||
-fdata-sections \
|
-fdata-sections \
|
||||||
-fno-exceptions \
|
-fno-exceptions \
|
||||||
-g
|
-g
|
||||||
|
LDFLAGS += \
|
||||||
|
-Wno-attributes \
|
||||||
|
-Wno-aggressive-loop-optimizations \
|
||||||
|
-flto=auto
|
||||||
|
|
||||||
ANDROID_BUILD_TOOLS := $(ANDROID_SDK)/build-tools/34.0.0
|
|
||||||
ANDROID_PLATFORM := $(ANDROID_SDK)/platforms/android-34
|
|
||||||
ANDROID_NDK ?= $(ANDROID_SDK)/ndk/26.2.11394342
|
|
||||||
ANDROID_MIN_SDK_VERSION := 24
|
ANDROID_MIN_SDK_VERSION := 24
|
||||||
ANDROID_TARGET_SDK_VERSION := 34
|
ANDROID_TARGET_SDK_VERSION := 34
|
||||||
|
ANDROID_BUILD_TOOLS := $(ANDROID_SDK)/build-tools/34.0.0
|
||||||
|
ANDROID_PLATFORM := $(ANDROID_SDK)/platforms/android-$(ANDROID_TARGET_SDK_VERSION)
|
||||||
|
ANDROID_NDK ?= $(ANDROID_SDK)/ndk/26.3.11579264
|
||||||
|
|
||||||
ANDROID_ARMV7A_TARGETS := \
|
ANDROID_ARMV7A_TARGETS := \
|
||||||
out/androiddebug-armv7a/tildefriends \
|
out/androiddebug-armv7a/tildefriends \
|
||||||
@ -89,7 +102,7 @@ BUILD_TYPES += \
|
|||||||
androidrelease-x86 \
|
androidrelease-x86 \
|
||||||
androiddebug-x86_64 \
|
androiddebug-x86_64 \
|
||||||
androidrelease-x86_64
|
androidrelease-x86_64
|
||||||
all: out/TildeFriends-arm-debug.apk out/TildeFriends-arm-release.apk out/TildeFriends-x86-debug.apk out/TildeFriends-x86-release.apk
|
all: out/TildeFriends-arm-debug.apk out/TildeFriends-arm-release.apk out/TildeFriends-x86-debug.apk out/TildeFriends-x86-release.apk out/TildeFriends-release.fdroid.apk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
WINDOWS_TARGETS := \
|
WINDOWS_TARGETS := \
|
||||||
@ -149,19 +162,26 @@ ANDROID_RELEASE_TARGETS := $(filter-out $(DEBUG_TARGETS),$(ANDROID_TARGETS))
|
|||||||
NONANDROID_RELEASE_TARGETS := $(filter-out $(ANDROID_ARM64_TARGETS),$(RELEASE_TARGETS))
|
NONANDROID_RELEASE_TARGETS := $(filter-out $(ANDROID_ARM64_TARGETS),$(RELEASE_TARGETS))
|
||||||
NONANDROID_TARGETS := $(filter-out $(ANDROID_TARGETS),$(ALL_TARGETS))
|
NONANDROID_TARGETS := $(filter-out $(ANDROID_TARGETS),$(ALL_TARGETS))
|
||||||
NONMACOS_TARGETS := $(filter-out $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS),$(ALL_TARGETS))
|
NONMACOS_TARGETS := $(filter-out $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS),$(ALL_TARGETS))
|
||||||
|
DEADSTRIP_TARGETS := $(filter-out $(ANDROID_TARGETS),$(NONMACOS_TARGETS))
|
||||||
|
ifneq ($(UNAME_S),OpenBSD)
|
||||||
|
$(NONMACOS_TARGETS): LDFLAGS += -static-libgcc
|
||||||
|
endif
|
||||||
|
|
||||||
$(NONANDROID_TARGETS): CFLAGS += -fno-omit-frame-pointer
|
$(NONANDROID_TARGETS): CFLAGS += -fno-omit-frame-pointer
|
||||||
$(filter-out $(ANDROID_TARGETS) $(WINDOWS_TARGETS),$(ALL_TARGETS)): LDFLAGS += -rdynamic
|
$(filter-out $(WINDOWS_TARGETS),$(ALL_TARGETS)): LDFLAGS += -rdynamic
|
||||||
$(ANDROID_TARGETS): CFLAGS += \
|
$(ANDROID_TARGETS): CFLAGS += \
|
||||||
--sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
|
--sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
|
||||||
-fPIC \
|
-fPIC \
|
||||||
-fdebug-compilation-dir . \
|
-fdebug-compilation-dir . \
|
||||||
-fomit-frame-pointer \
|
-fomit-frame-pointer \
|
||||||
-fno-asynchronous-unwind-tables \
|
-fno-asynchronous-unwind-tables \
|
||||||
-funwind-tables
|
-funwind-tables \
|
||||||
|
-Wno-unknown-warning-option
|
||||||
$(ANDROID_TARGETS): LDFLAGS += --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC
|
$(ANDROID_TARGETS): LDFLAGS += --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC
|
||||||
$(DEBUG_TARGETS): CFLAGS += -DDEBUG -Og
|
$(DEBUG_TARGETS): CFLAGS += -DDEBUG -Og
|
||||||
$(RELEASE_TARGETS): CFLAGS += -DNDEBUG
|
$(RELEASE_TARGETS): CFLAGS += \
|
||||||
|
-DNDEBUG \
|
||||||
|
-flto
|
||||||
$(NONANDROID_RELEASE_TARGETS): CFLAGS += -O3
|
$(NONANDROID_RELEASE_TARGETS): CFLAGS += -O3
|
||||||
$(ANDROID_RELEASE_TARGETS): CFLAGS += -Oz
|
$(ANDROID_RELEASE_TARGETS): CFLAGS += -Oz
|
||||||
$(WINDOWS_TARGETS): CC = x86_64-w64-mingw32-gcc-win32
|
$(WINDOWS_TARGETS): CC = x86_64-w64-mingw32-gcc-win32
|
||||||
@ -204,13 +224,16 @@ $(ANDROID_X86_TARGETS): LDFLAGS += -Ldeps/openssl/android/x86/usr/local/lib
|
|||||||
$(ANDROID_X86_64_TARGETS): CFLAGS += -Ideps/openssl/android/x86_64/usr/local/include
|
$(ANDROID_X86_64_TARGETS): CFLAGS += -Ideps/openssl/android/x86_64/usr/local/include
|
||||||
$(ANDROID_X86_64_TARGETS): LDFLAGS += -Ldeps/openssl/android/x86_64/usr/local/lib
|
$(ANDROID_X86_64_TARGETS): LDFLAGS += -Ldeps/openssl/android/x86_64/usr/local/lib
|
||||||
$(NONMACOS_TARGETS): CFLAGS += -Wno-cast-function-type
|
$(NONMACOS_TARGETS): CFLAGS += -Wno-cast-function-type
|
||||||
$(NONMACOS_TARGETS): LDFLAGS += -Wl,--gc-sections
|
$(DEADSTRIP_TARGETS): LDFLAGS += -Wl,--gc-sections
|
||||||
$(IOS_TARGETS): CFLAGS += -mios-version-min=9.0 -Ideps/openssl/ios/ios64-xcrun/usr/local/include
|
$(IOS_TARGETS): CFLAGS += -miphoneos-version-min=9.0 -Ideps/openssl/ios/ios64-xcrun/usr/local/include
|
||||||
$(IOS_TARGETS): LDFLAGS += -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib
|
$(IOS_TARGETS): LDFLAGS += -miphoneos-version-min=9.0 -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib
|
||||||
$(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include
|
$(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include
|
||||||
$(IOSSIM_TARGETS): LDFLAGS += -Ldeps/openssl/ios/iossimulator-xcrun/usr/local/lib
|
$(IOSSIM_TARGETS): LDFLAGS += -Ldeps/openssl/ios/iossimulator-xcrun/usr/local/lib
|
||||||
|
|
||||||
ifeq ($(UNAME_M),x86_64)
|
ifeq ($(UNAME_M),x86_64)
|
||||||
|
ifeq ($(UNAME_S),Linux)
|
||||||
|
all: appimage
|
||||||
|
endif
|
||||||
ifneq ($(UNAME_S),Haiku)
|
ifneq ($(UNAME_S),Haiku)
|
||||||
out/debug/tildefriends: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common
|
out/debug/tildefriends: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common
|
||||||
out/debug/tildefriends: LDFLAGS += -fsanitize=address -fsanitize=undefined
|
out/debug/tildefriends: LDFLAGS += -fsanitize=address -fsanitize=undefined
|
||||||
@ -237,6 +260,8 @@ APP_SOURCES_ios := $(wildcard src/*.m)
|
|||||||
APP_OBJS := $(call get_objs,APP_SOURCES)
|
APP_OBJS := $(call get_objs,APP_SOURCES)
|
||||||
$(APP_OBJS): CFLAGS += \
|
$(APP_OBJS): CFLAGS += \
|
||||||
-Ideps/base64c/include \
|
-Ideps/base64c/include \
|
||||||
|
-Ideps/c-ares/include \
|
||||||
|
-Ideps/c-ares_config \
|
||||||
-Ideps/crypt_blowfish \
|
-Ideps/crypt_blowfish \
|
||||||
-Ideps/libbacktrace \
|
-Ideps/libbacktrace \
|
||||||
-Ideps/libsodium \
|
-Ideps/libsodium \
|
||||||
@ -255,6 +280,108 @@ $(filter-out $(BUILD_DIR)/android% $(BUILD_DIR)/macos% $(BUILD_DIR)/ios%,$(APP_O
|
|||||||
-fanalyzer
|
-fanalyzer
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ARES_SOURCES := \
|
||||||
|
deps/c-ares/src/lib/ares_addrinfo2hostent.c \
|
||||||
|
deps/c-ares/src/lib/ares_addrinfo_localhost.c \
|
||||||
|
deps/c-ares/src/lib/ares_android.c \
|
||||||
|
deps/c-ares/src/lib/ares_cancel.c \
|
||||||
|
deps/c-ares/src/lib/ares_close_sockets.c \
|
||||||
|
deps/c-ares/src/lib/ares_conn.c \
|
||||||
|
deps/c-ares/src/lib/ares_cookie.c \
|
||||||
|
deps/c-ares/src/lib/ares_data.c \
|
||||||
|
deps/c-ares/src/lib/ares_destroy.c \
|
||||||
|
deps/c-ares/src/lib/ares_free_hostent.c \
|
||||||
|
deps/c-ares/src/lib/ares_free_string.c \
|
||||||
|
deps/c-ares/src/lib/ares_freeaddrinfo.c \
|
||||||
|
deps/c-ares/src/lib/ares_getaddrinfo.c \
|
||||||
|
deps/c-ares/src/lib/ares_getenv.c \
|
||||||
|
deps/c-ares/src/lib/ares_gethostbyaddr.c \
|
||||||
|
deps/c-ares/src/lib/ares_gethostbyname.c \
|
||||||
|
deps/c-ares/src/lib/ares_getnameinfo.c \
|
||||||
|
deps/c-ares/src/lib/ares_hosts_file.c \
|
||||||
|
deps/c-ares/src/lib/ares_init.c \
|
||||||
|
deps/c-ares/src/lib/ares_library_init.c \
|
||||||
|
deps/c-ares/src/lib/ares_metrics.c \
|
||||||
|
deps/c-ares/src/lib/ares_options.c \
|
||||||
|
deps/c-ares/src/lib/ares_parse_into_addrinfo.c \
|
||||||
|
deps/c-ares/src/lib/ares_process.c \
|
||||||
|
deps/c-ares/src/lib/ares_qcache.c \
|
||||||
|
deps/c-ares/src/lib/ares_query.c \
|
||||||
|
deps/c-ares/src/lib/ares_search.c \
|
||||||
|
deps/c-ares/src/lib/ares_send.c \
|
||||||
|
deps/c-ares/src/lib/ares_set_socket_functions.c \
|
||||||
|
deps/c-ares/src/lib/ares_socket.c \
|
||||||
|
deps/c-ares/src/lib/ares_sortaddrinfo.c \
|
||||||
|
deps/c-ares/src/lib/ares_strerror.c \
|
||||||
|
deps/c-ares/src/lib/ares_sysconfig.c \
|
||||||
|
deps/c-ares/src/lib/ares_sysconfig_files.c \
|
||||||
|
deps/c-ares/src/lib/ares_sysconfig_mac.c \
|
||||||
|
deps/c-ares/src/lib/ares_sysconfig_win.c \
|
||||||
|
deps/c-ares/src/lib/ares_update_servers.c \
|
||||||
|
deps/c-ares/src/lib/ares_version.c \
|
||||||
|
deps/c-ares/src/lib/dsa/ares_array.c \
|
||||||
|
deps/c-ares/src/lib/dsa/ares_htable.c \
|
||||||
|
deps/c-ares/src/lib/dsa/ares_htable_asvp.c \
|
||||||
|
deps/c-ares/src/lib/dsa/ares_htable_dict.c \
|
||||||
|
deps/c-ares/src/lib/dsa/ares_htable_strvp.c \
|
||||||
|
deps/c-ares/src/lib/dsa/ares_htable_szvp.c \
|
||||||
|
deps/c-ares/src/lib/dsa/ares_htable_vpvp.c \
|
||||||
|
deps/c-ares/src/lib/dsa/ares_llist.c \
|
||||||
|
deps/c-ares/src/lib/dsa/ares_slist.c \
|
||||||
|
deps/c-ares/src/lib/event/ares_event_configchg.c \
|
||||||
|
deps/c-ares/src/lib/event/ares_event_epoll.c \
|
||||||
|
deps/c-ares/src/lib/event/ares_event_kqueue.c \
|
||||||
|
deps/c-ares/src/lib/event/ares_event_poll.c \
|
||||||
|
deps/c-ares/src/lib/event/ares_event_select.c \
|
||||||
|
deps/c-ares/src/lib/event/ares_event_thread.c \
|
||||||
|
deps/c-ares/src/lib/event/ares_event_wake_pipe.c \
|
||||||
|
deps/c-ares/src/lib/event/ares_event_win32.c \
|
||||||
|
deps/c-ares/src/lib/inet_net_pton.c \
|
||||||
|
deps/c-ares/src/lib/inet_ntop.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_create_query.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_expand_name.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_expand_string.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_fds.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_getsock.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_a_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_caa_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_mx_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_naptr_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_ns_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_ptr_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_soa_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_srv_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_txt_reply.c \
|
||||||
|
deps/c-ares/src/lib/legacy/ares_parse_uri_reply.c \
|
||||||
|
deps/c-ares/src/lib/record/ares_dns_mapping.c \
|
||||||
|
deps/c-ares/src/lib/record/ares_dns_multistring.c \
|
||||||
|
deps/c-ares/src/lib/record/ares_dns_name.c \
|
||||||
|
deps/c-ares/src/lib/record/ares_dns_parse.c \
|
||||||
|
deps/c-ares/src/lib/record/ares_dns_record.c \
|
||||||
|
deps/c-ares/src/lib/record/ares_dns_write.c \
|
||||||
|
deps/c-ares/src/lib/str/ares_buf.c \
|
||||||
|
deps/c-ares/src/lib/str/ares_str.c \
|
||||||
|
deps/c-ares/src/lib/str/ares_strsplit.c \
|
||||||
|
deps/c-ares/src/lib/util/ares_iface_ips.c \
|
||||||
|
deps/c-ares/src/lib/util/ares_math.c \
|
||||||
|
deps/c-ares/src/lib/util/ares_rand.c \
|
||||||
|
deps/c-ares/src/lib/util/ares_threads.c \
|
||||||
|
deps/c-ares/src/lib/util/ares_timeval.c \
|
||||||
|
deps/c-ares/src/lib/util/ares_uri.c \
|
||||||
|
deps/c-ares/src/lib/windows_port.c \
|
||||||
|
deps/c-ares/src/lib/ares_timeout.c
|
||||||
|
ARES_OBJS := $(call get_objs,ARES_SOURCES)
|
||||||
|
$(ARES_OBJS): CFLAGS += \
|
||||||
|
-Ideps/c-ares/include \
|
||||||
|
-Ideps/c-ares/src/lib \
|
||||||
|
-Ideps/c-ares/src/lib/include \
|
||||||
|
-Ideps/c-ares_config/ \
|
||||||
|
-D_GNU_SOURCE \
|
||||||
|
-Wno-unused-function \
|
||||||
|
-Wno-deprecated-declarations \
|
||||||
|
-Wno-unused-result
|
||||||
|
|
||||||
BLOWFISH_SOURCES := \
|
BLOWFISH_SOURCES := \
|
||||||
deps/crypt_blowfish/crypt_blowfish.c \
|
deps/crypt_blowfish/crypt_blowfish.c \
|
||||||
deps/crypt_blowfish/crypt_gensalt.c \
|
deps/crypt_blowfish/crypt_gensalt.c \
|
||||||
@ -382,10 +509,17 @@ $(UV_OBJS): CFLAGS += \
|
|||||||
-Wno-incompatible-pointer-types \
|
-Wno-incompatible-pointer-types \
|
||||||
-Wno-maybe-uninitialized \
|
-Wno-maybe-uninitialized \
|
||||||
-Wno-sign-compare \
|
-Wno-sign-compare \
|
||||||
|
-Wno-unknown-attributes \
|
||||||
-Wno-unused-but-set-parameter \
|
-Wno-unused-but-set-parameter \
|
||||||
-Wno-unused-but-set-variable \
|
-Wno-unused-but-set-variable \
|
||||||
-Wno-unused-result \
|
-Wno-unused-result \
|
||||||
-Wno-unused-variable
|
-Wno-unused-variable \
|
||||||
|
-Wno-nonnull
|
||||||
|
$(UV_OBJS): CFLAGS += -fno-lto
|
||||||
|
$(filter out/win%,$(UV_OBJS)): \
|
||||||
|
CFLAGS += \
|
||||||
|
-Wno-cast-function-type \
|
||||||
|
-Wno-missing-braces
|
||||||
ifeq ($(UNAME_S),Linux)
|
ifeq ($(UNAME_S),Linux)
|
||||||
$(UV_OBJS): CFLAGS += \
|
$(UV_OBJS): CFLAGS += \
|
||||||
-D_GNU_SOURCE
|
-D_GNU_SOURCE
|
||||||
@ -620,6 +754,7 @@ all: $(BUILD_TYPES)
|
|||||||
|
|
||||||
ALL_APP_OBJS := \
|
ALL_APP_OBJS := \
|
||||||
$(APP_OBJS) \
|
$(APP_OBJS) \
|
||||||
|
$(ARES_OBJS) \
|
||||||
$(BLOWFISH_OBJS) \
|
$(BLOWFISH_OBJS) \
|
||||||
$(LIBBACKTRACE_OBJS) \
|
$(LIBBACKTRACE_OBJS) \
|
||||||
$(MINIUNZIP_OBJS) \
|
$(MINIUNZIP_OBJS) \
|
||||||
@ -684,20 +819,37 @@ out/res/drawable_icon.xml.flat: src/android/res/drawable/icon.xml
|
|||||||
@$(ANDROID_BUILD_TOOLS)/aapt2 compile -o out/res/ src/android/res/drawable/icon.xml
|
@$(ANDROID_BUILD_TOOLS)/aapt2 compile -o out/res/ src/android/res/drawable/icon.xml
|
||||||
|
|
||||||
out/apk/res.apk out/gen/com/unprompted/tildefriends/R.java: out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat src/android/AndroidManifest.xml
|
out/apk/res.apk out/gen/com/unprompted/tildefriends/R.java: out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat src/android/AndroidManifest.xml
|
||||||
@mkdir -p $(dir $@)
|
@echo [aapt2 link] res.apk
|
||||||
@$(ANDROID_BUILD_TOOLS)/aapt2 link -I $(ANDROID_PLATFORM)/android.jar out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat --manifest src/android/AndroidManifest.xml -o out/apk/res.apk --java out/gen/
|
@mkdir -p out/apk/
|
||||||
|
@$(ANDROID_BUILD_TOOLS)/aapt2 link -I $(ANDROID_PLATFORM)/android.jar out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat \
|
||||||
|
--min-sdk-version $(ANDROID_MIN_SDK_VERSION) \
|
||||||
|
--target-sdk-version $(ANDROID_TARGET_SDK_VERSION) \
|
||||||
|
--manifest src/android/AndroidManifest.xml \
|
||||||
|
-o out/apk/res.apk \
|
||||||
|
--java out/gen/
|
||||||
|
|
||||||
|
out/apk/res.fdroid.apk out/gen_fdroid/com/unprompted/tildefriends/R.java: out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat src/android/AndroidManifest.xml
|
||||||
|
@echo [aapt2 link] res.fdroid.apk
|
||||||
|
@mkdir -p out/apk/
|
||||||
|
@$(ANDROID_BUILD_TOOLS)/aapt2 link -I $(ANDROID_PLATFORM)/android.jar out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat \
|
||||||
|
--min-sdk-version $(ANDROID_MIN_SDK_VERSION) \
|
||||||
|
--target-sdk-version $(ANDROID_TARGET_SDK_VERSION) \
|
||||||
|
--rename-manifest-package com.unprompted.tildefriends.fdroid \
|
||||||
|
--manifest src/android/AndroidManifest.xml \
|
||||||
|
-o out/apk/res.fdroid.apk \
|
||||||
|
--java out/gen_fdroid/
|
||||||
|
|
||||||
JAVA_FILES := out/gen/com/unprompted/tildefriends/R.java $(wildcard src/android/com/unprompted/tildefriends/*.java)
|
JAVA_FILES := out/gen/com/unprompted/tildefriends/R.java $(wildcard src/android/com/unprompted/tildefriends/*.java)
|
||||||
CLASS_FILES := $(foreach src,$(JAVA_FILES),out/classes/com/unprompted/tildefriends/$(notdir $(src:.java=.class)))
|
CLASS_FILES := $(foreach src,$(JAVA_FILES),out/classes/com/unprompted/tildefriends/$(notdir $(src:.java=.class)))
|
||||||
|
|
||||||
$(CLASS_FILES) &: $(JAVA_FILES)
|
$(CLASS_FILES) &: $(JAVA_FILES)
|
||||||
@echo "[javac] $(CLASS_FILES)"
|
@echo "[javac] $(CLASS_FILES)"
|
||||||
@javac --release 8 -Xlint:deprecation -classpath $(ANDROID_PLATFORM)/android.jar -d out/classes $(JAVA_FILES)
|
@javac --release 8 -encoding UTF-8 -Xlint:deprecation -XDuseUnsharedTable=true -classpath $(ANDROID_PLATFORM)/android.jar:$(ANDROID_BUILD_TOOLS)/core-lambda-stubs.jar -d out/classes $(JAVA_FILES)
|
||||||
|
|
||||||
out/apk/classes.dex: $(CLASS_FILES)
|
out/apk/classes.dex: $(CLASS_FILES)
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
@echo "[d8] $@"
|
@echo "[d8] $@"
|
||||||
@$(ANDROID_BUILD_TOOLS)/d8 --$(BUILD_TYPE) --lib $(ANDROID_PLATFORM)/android.jar --output $(dir $@) out/classes/com/unprompted/tildefriends/*.class
|
@$(ANDROID_BUILD_TOOLS)/d8 --lib $(ANDROID_PLATFORM)/android.jar --output $(dir $@) out/classes/com/unprompted/tildefriends/*.class
|
||||||
|
|
||||||
PACKAGE_DIRS := \
|
PACKAGE_DIRS := \
|
||||||
apps/ \
|
apps/ \
|
||||||
@ -706,25 +858,79 @@ PACKAGE_DIRS := \
|
|||||||
deps/prettier/ \
|
deps/prettier/ \
|
||||||
deps/lit/
|
deps/lit/
|
||||||
|
|
||||||
RAW_FILES := $(filter-out apps/blog% apps/issues% apps/welcome% apps/journal% %.map, $(shell find $(PACKAGE_DIRS) -type f))
|
RAW_FILES := $(sort $(filter-out apps/blog% apps/issues% apps/welcome% apps/journal% %.map, $(shell find $(PACKAGE_DIRS) -type f -not -name '.*')))
|
||||||
|
|
||||||
out/apk/TildeFriends-arm-debug.unsigned.apk: BUILD_TYPE := debug
|
out/apk/TildeFriends-arm-debug.unsigned.apk: BUILD_TYPE := debug
|
||||||
out/apk/TildeFriends-arm-release.unsigned.apk: BUILD_TYPE := release
|
out/apk/TildeFriends-arm-release.unsigned.apk: BUILD_TYPE := release
|
||||||
out/apk/TildeFriends-x86-debug.unsigned.apk: BUILD_TYPE := debug
|
out/apk/TildeFriends-x86-debug.unsigned.apk: BUILD_TYPE := debug
|
||||||
out/apk/TildeFriends-x86-release.unsigned.apk: BUILD_TYPE := release
|
out/apk/TildeFriends-x86-release.unsigned.apk: BUILD_TYPE := release
|
||||||
|
out/apk/TildeFriends-release.fdroid.unsigned.apk: BUILD_TYPE := release
|
||||||
|
|
||||||
out/apk/TildeFriends-arm-debug.unsigned.apk: out/apk/classes.dex out/androiddebug/tildefriends out/androiddebug-armv7a/tildefriends $(RAW_FILES) out/apk/res.apk
|
out/apk/TildeFriends-arm-debug.unsigned.apk: out/apk/classes.dex out/androiddebug/tildefriends out/androiddebug-armv7a/tildefriends $(RAW_FILES) out/apk/res.apk
|
||||||
out/apk/TildeFriends-arm-release.unsigned.apk: out/apk/classes.dex out/androidrelease/tildefriends out/androidrelease-armv7a/tildefriends $(RAW_FILES) out/apk/res.apk
|
out/apk/TildeFriends-arm-release.unsigned.apk: out/apk/classes.dex out/androidrelease/tildefriends out/androidrelease-armv7a/tildefriends $(RAW_FILES) out/apk/res.apk
|
||||||
out/apk/TildeFriends-x86-debug.unsigned.apk: out/apk/classes.dex out/androiddebug-x86_64/tildefriends out/androiddebug-x86/tildefriends $(RAW_FILES) out/apk/res.apk
|
out/apk/TildeFriends-x86-debug.unsigned.apk: out/apk/classes.dex out/androiddebug-x86_64/tildefriends out/androiddebug-x86/tildefriends $(RAW_FILES) out/apk/res.apk
|
||||||
out/apk/TildeFriends-x86-release.unsigned.apk: out/apk/classes.dex out/androidrelease-x86_64/tildefriends out/androidrelease-x86/tildefriends $(RAW_FILES) out/apk/res.apk
|
out/apk/TildeFriends-x86-release.unsigned.apk: out/apk/classes.dex out/androidrelease-x86_64/tildefriends out/androidrelease-x86/tildefriends $(RAW_FILES) out/apk/res.apk
|
||||||
|
out/apk/TildeFriends-release.fdroid.unsigned.apk: out/apk/classes.dex out/androidrelease/tildefriends out/androidrelease-armv7a/tildefriends out/androidrelease-x86_64/tildefriends out/androidrelease-x86/tildefriends $(RAW_FILES) out/apk/res.fdroid.apk
|
||||||
|
|
||||||
|
$(BUNDLETOOL):
|
||||||
|
@echo [curl] $(BUNDLETOOL_URL) TO $@
|
||||||
|
@curl -q -L --create-dirs -o $@ $(BUNDLETOOL_URL)
|
||||||
|
|
||||||
|
out/TildeFriends.aab: out/apk/classes.dex $(filter-out %debug%, $(ANDROID_TARGETS)) $(RAW_FILES) out/apk/res.apk src/android/AndroidManifest.xml $(BUNDLETOOL)
|
||||||
|
@rm -rf out/aab/staging/
|
||||||
|
@mkdir -p out/aab/staging
|
||||||
|
@$(ANDROID_BUILD_TOOLS)/aapt2 link --proto-format -o out/aab/temporary.apk \
|
||||||
|
-I $(ANDROID_PLATFORM)/android.jar \
|
||||||
|
--min-sdk-version $(ANDROID_MIN_SDK_VERSION) \
|
||||||
|
--target-sdk-version $(ANDROID_TARGET_SDK_VERSION) \
|
||||||
|
--manifest src/android/AndroidManifest.xml \
|
||||||
|
-R out/res/layout_activity_main.xml.flat \
|
||||||
|
-R out/res/drawable_icon.xml.flat \
|
||||||
|
--auto-add-overlay
|
||||||
|
@unzip out/aab/temporary.apk -d out/aab/staging/
|
||||||
|
@mkdir -p out/aab/staging/root/deps
|
||||||
|
@mkdir -p out/aab/staging/classes
|
||||||
|
@mkdir -p out/aab/staging/dex
|
||||||
|
@mkdir -p out/aab/staging/manifest
|
||||||
|
@mv out/aab/staging/AndroidManifest.xml out/aab/staging/manifest/AndroidManifest.xml
|
||||||
|
@cp out/apk/classes.dex out/aab/staging/dex/
|
||||||
|
@rm -fv out/base.zip
|
||||||
|
@mkdir -p out/aab/staging/lib/arm64-v8a out/aab/staging/lib/armeabi-v7a out/aab/staging/lib/x86_64 out/aab/staging/lib/x86
|
||||||
|
@cp out/androidrelease/tildefriends out/aab/staging/lib/arm64-v8a/libtildefriends.so
|
||||||
|
@cp out/androidrelease-armv7a/tildefriends out/aab/staging/lib/armeabi-v7a/libtildefriends.so
|
||||||
|
@cp out/androidrelease-x86_64/tildefriends out/aab/staging/lib/x86_64/libtildefriends.so
|
||||||
|
@cp out/androidrelease-x86/tildefriends out/aab/staging/lib/x86/libtildefriends.so
|
||||||
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/aab/staging/lib/arm64-v8a/libtildefriends.so
|
||||||
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/aab/staging/lib/armeabi-v7a/libtildefriends.so
|
||||||
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/aab/staging/lib/x86_64/libtildefriends.so
|
||||||
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/aab/staging/lib/x86/libtildefriends.so
|
||||||
|
@cp -r apps/ out/aab/staging/root/
|
||||||
|
@rm -rf out/aab/staging/root/apps/welcome*
|
||||||
|
@cp -r core/ out/aab/staging/root/
|
||||||
|
@cp -r deps/prettier/ out/aab/staging/root/deps/
|
||||||
|
@cp -r deps/lit/ out/aab/staging/root/deps/
|
||||||
|
@cp -r deps/codemirror/ out/aab/staging/root/deps/
|
||||||
|
@cd out/aab/staging/; zip -r ../base.zip *; cd ../../../
|
||||||
|
@java -jar $(BUNDLETOOL) build-bundle --overwrite --config=src/android/BundleConfig.json --modules=out/aab/base.zip --output=$@
|
||||||
|
@jarsigner -keystore .keys/android.jks $@ androidKey -storepass android
|
||||||
|
|
||||||
|
aab: out/TildeFriends.aab
|
||||||
|
.PHONY: aab
|
||||||
|
|
||||||
|
out/TildeFriends.apks: out/TildeFriends.aab $(BUNDLETOOL)
|
||||||
|
@java -jar $(BUNDLETOOL) build-apks --bundle out/TildeFriends.aab --overwrite --output $@ --ks .keys/android.jks --ks-key-alias androidKey --ks-pass pass:android
|
||||||
|
|
||||||
|
aabgo: out/TildeFriends.apks $(BUNDLETOOL)
|
||||||
|
@java -jar $(BUNDLETOOL) install-apks --apks out/TildeFriends.apks
|
||||||
|
@adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity
|
||||||
|
|
||||||
out/apk/TildeFriends-arm-%.unsigned.apk:
|
out/apk/TildeFriends-arm-%.unsigned.apk:
|
||||||
@mkdir -p $(dir $@) out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/ out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/
|
@mkdir -p $(dir $@) out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/ out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/
|
||||||
@echo "[aapt] $@"
|
@echo "[aapt] $@"
|
||||||
@cp out/android$(BUILD_TYPE)/tildefriends out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/tildefriends.so
|
@cp out/android$(BUILD_TYPE)/tildefriends out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/libtildefriends.so
|
||||||
@cp out/android$(BUILD_TYPE)-armv7a/tildefriends out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/tildefriends.so
|
@cp out/android$(BUILD_TYPE)-armv7a/tildefriends out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/libtildefriends.so
|
||||||
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/tildefriends.so
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/libtildefriends.so
|
||||||
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/tildefriends.so
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/libtildefriends.so
|
||||||
@cp out/apk/res.apk $@.zip
|
@cp out/apk/res.apk $@.zip
|
||||||
@cp out/apk/classes.dex out/apk-arm-$(BUILD_TYPE)/
|
@cp out/apk/classes.dex out/apk-arm-$(BUILD_TYPE)/
|
||||||
@cd out/apk-arm-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../
|
@cd out/apk-arm-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../
|
||||||
@ -734,16 +940,38 @@ out/apk/TildeFriends-arm-%.unsigned.apk:
|
|||||||
out/apk/TildeFriends-x86-%.unsigned.apk:
|
out/apk/TildeFriends-x86-%.unsigned.apk:
|
||||||
@mkdir -p $(dir $@) out/apk-x86-$(BUILD_TYPE)/lib/x86_64/ out/apk-x86-$(BUILD_TYPE)/lib/x86/
|
@mkdir -p $(dir $@) out/apk-x86-$(BUILD_TYPE)/lib/x86_64/ out/apk-x86-$(BUILD_TYPE)/lib/x86/
|
||||||
@echo "[aapt] $@"
|
@echo "[aapt] $@"
|
||||||
@cp out/android$(BUILD_TYPE)-x86_64/tildefriends out/apk-x86-$(BUILD_TYPE)/lib/x86_64/tildefriends.so
|
@cp out/android$(BUILD_TYPE)-x86_64/tildefriends out/apk-x86-$(BUILD_TYPE)/lib/x86_64/libtildefriends.so
|
||||||
@cp out/android$(BUILD_TYPE)-x86/tildefriends out/apk-x86-$(BUILD_TYPE)/lib/x86/tildefriends.so
|
@cp out/android$(BUILD_TYPE)-x86/tildefriends out/apk-x86-$(BUILD_TYPE)/lib/x86/libtildefriends.so
|
||||||
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86_64/tildefriends.so
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86_64/libtildefriends.so
|
||||||
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86/tildefriends.so
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86/libtildefriends.so
|
||||||
@cp out/apk/res.apk $@.zip
|
@cp out/apk/res.apk $@.zip
|
||||||
@cp out/apk/classes.dex out/apk-x86-$(BUILD_TYPE)/
|
@cp out/apk/classes.dex out/apk-x86-$(BUILD_TYPE)/
|
||||||
@cd out/apk-x86-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../
|
@cd out/apk-x86-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../
|
||||||
@zip -u $@.zip -q -9 $(RAW_FILES)
|
@zip -u $@.zip -q -9 $(RAW_FILES)
|
||||||
@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@
|
@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@
|
||||||
|
|
||||||
|
out/apk/TildeFriends-%.fdroid.unsigned.apk:
|
||||||
|
@rm -rf out/apk-fdroid-$(BUILD_TYPE) out/apk-fdroid-$(BUILD_TYPE)-raw
|
||||||
|
@mkdir -p $(dir $@) out/apk-fdroid-$(BUILD_TYPE)/lib/x86_64/ out/apk-fdroid-$(BUILD_TYPE)/lib/x86/ out/apk-fdroid-$(BUILD_TYPE)/lib/arm64-v8a/ out/apk-fdroid-$(BUILD_TYPE)/lib/armeabi-v7a/
|
||||||
|
@echo "[aapt] $@"
|
||||||
|
@cp out/android$(BUILD_TYPE)-x86_64/tildefriends out/apk-fdroid-$(BUILD_TYPE)/lib/x86_64/libtildefriends.so
|
||||||
|
@cp out/android$(BUILD_TYPE)-x86/tildefriends out/apk-fdroid-$(BUILD_TYPE)/lib/x86/libtildefriends.so
|
||||||
|
@cp out/android$(BUILD_TYPE)/tildefriends out/apk-fdroid-$(BUILD_TYPE)/lib/arm64-v8a/libtildefriends.so
|
||||||
|
@cp out/android$(BUILD_TYPE)-armv7a/tildefriends out/apk-fdroid-$(BUILD_TYPE)/lib/armeabi-v7a/libtildefriends.so
|
||||||
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-fdroid-$(BUILD_TYPE)/lib/x86_64/libtildefriends.so
|
||||||
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-fdroid-$(BUILD_TYPE)/lib/x86/libtildefriends.so
|
||||||
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-fdroid-$(BUILD_TYPE)/lib/arm64-v8a/libtildefriends.so
|
||||||
|
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-fdroid-$(BUILD_TYPE)/lib/armeabi-v7a/libtildefriends.so
|
||||||
|
@cp out/apk/res.fdroid.apk $@.zip
|
||||||
|
@cp out/apk/classes.dex out/apk-fdroid-$(BUILD_TYPE)/classes.dex
|
||||||
|
@touch -d @0 out/apk-fdroid-$(BUILD_TYPE)/classes.dex out/apk-fdroid-$(BUILD_TYPE)/lib/*/libtildefriends.so
|
||||||
|
@chmod 755 out/apk-fdroid-$(BUILD_TYPE)/classes.dex out/apk-fdroid-$(BUILD_TYPE)/lib/*/libtildefriends.so
|
||||||
|
@cd out/apk-fdroid-$(BUILD_TYPE) && zip -X -u ../../$@.zip -q classes.dex lib/*/libtildefriends.so && cd ../../
|
||||||
|
@mkdir out/apk-fdroid-$(BUILD_TYPE)-raw
|
||||||
|
@for i in $(RAW_FILES); do mkdir -p $$(dirname out/apk-fdroid-$(BUILD_TYPE)-raw/$$i) && cp $$i out/apk-fdroid-$(BUILD_TYPE)-raw/$$i && touch -d @0 out/apk-fdroid-$(BUILD_TYPE)-raw/$$i && chmod 644 out/apk-fdroid-$(BUILD_TYPE)-raw/$$i; done
|
||||||
|
@cd out/apk-fdroid-$(BUILD_TYPE)-raw && zip -X -u ../../$@.zip -q $(RAW_FILES) && cd ../../
|
||||||
|
@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@
|
||||||
|
|
||||||
out/%.apk: out/apk/%.unsigned.apk
|
out/%.apk: out/apk/%.unsigned.apk
|
||||||
@echo "[apksigner] $(notdir $@)"
|
@echo "[apksigner] $(notdir $@)"
|
||||||
@$(ANDROID_BUILD_TOOLS)/apksigner sign --ks .keys/android.jks --ks-key-alias androidKey --ks-pass pass:android --key-pass pass:android --min-sdk-version $(ANDROID_MIN_SDK_VERSION) --out $@ $<
|
@$(ANDROID_BUILD_TOOLS)/apksigner sign --ks .keys/android.jks --ks-key-alias androidKey --ks-pass pass:android --key-pass pass:android --min-sdk-version $(ANDROID_MIN_SDK_VERSION) --out $@ $<
|
||||||
@ -756,9 +984,14 @@ out/%.zopfli.apk: out/%.apk
|
|||||||
release-apk: out/TildeFriends-arm-release.zopfli.apk out/TildeFriends-x86-release.zopfli.apk
|
release-apk: out/TildeFriends-arm-release.zopfli.apk out/TildeFriends-x86-release.zopfli.apk
|
||||||
.PHONY: release-apk
|
.PHONY: release-apk
|
||||||
|
|
||||||
|
apkgo: out/TildeFriends-arm-debug.apk
|
||||||
|
@adb install -r $<
|
||||||
|
@adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity
|
||||||
|
.PHONY: apkgo
|
||||||
|
|
||||||
releaseapkgo: out/TildeFriends-arm-release.apk
|
releaseapkgo: out/TildeFriends-arm-release.apk
|
||||||
@adb install -r $<
|
@adb install -r $<
|
||||||
@adb shell am start com.unprompted.tildefriends/.MainActivity
|
@adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity
|
||||||
.PHONY: releaseapkgo
|
.PHONY: releaseapkgo
|
||||||
|
|
||||||
# iOS Support
|
# iOS Support
|
||||||
@ -775,6 +1008,7 @@ out/data.zip: $(RAW_FILES)
|
|||||||
out/tildefriends-%.app/tildefriends: out/%/tildefriends out/tildefriends-%.app/Info.plist out/tildefriends-%.app/tildefriends.png out/data.zip
|
out/tildefriends-%.app/tildefriends: out/%/tildefriends out/tildefriends-%.app/Info.plist out/tildefriends-%.app/tildefriends.png out/data.zip
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
@cp -v $< $@
|
@cp -v $< $@
|
||||||
|
@cp -v out/data.zip $(@D)/
|
||||||
ifeq ($(HAVE_LINUX_IOS),1)
|
ifeq ($(HAVE_LINUX_IOS),1)
|
||||||
@zsign -q -k .keys/apple.p12 -f -m src/ios/embedded.mobileprovision $(realpath $(dir $@))
|
@zsign -q -k .keys/apple.p12 -f -m src/ios/embedded.mobileprovision $(realpath $(dir $@))
|
||||||
endif
|
endif
|
||||||
@ -792,6 +1026,10 @@ out/%/tildefriends.standalone: out/%/tildefriends out/data.zip
|
|||||||
@echo "[standalone] $@"
|
@echo "[standalone] $@"
|
||||||
@cat $< out/data.zip > $@
|
@cat $< out/data.zip > $@
|
||||||
@chmod +x $@
|
@chmod +x $@
|
||||||
|
out/%/tildefriends.standalone.exe: out/%/tildefriends.exe out/data.zip
|
||||||
|
@echo "[standalone] $@"
|
||||||
|
@cat $< out/data.zip > $@
|
||||||
|
@chmod +x $@
|
||||||
|
|
||||||
iossimdebug-app: out/tildefriends-iossimdebug.app/tildefriends
|
iossimdebug-app: out/tildefriends-iossimdebug.app/tildefriends
|
||||||
iossimrelease-app: out/tildefriends-iossimrelease.app/tildefriends
|
iossimrelease-app: out/tildefriends-iossimrelease.app/tildefriends
|
||||||
@ -815,10 +1053,6 @@ apklog:
|
|||||||
.PHONY: apklog
|
.PHONY: apklog
|
||||||
|
|
||||||
fetchdeps:
|
fetchdeps:
|
||||||
@echo "[fetch] libuv"
|
|
||||||
@test -f out/deps/libuv.tar.gz && test "$$(cat out/deps/libuv.txt 2>/dev/null)" = $(LIBUV_URL) || (mkdir -p out/deps/ && curl -q $(LIBUV_URL) -o out/deps/libuv.tar.gz)
|
|
||||||
@test -d deps/libuv/ && test "$$(cat out/deps/libuv.txt 2>/dev/null)" = $(LIBUV_URL) || (rm -rf deps/libuv/ && mkdir -p deps/libuv/ && tar -C deps/libuv/ -m --strip=1 -xf out/deps/libuv.tar.gz)
|
|
||||||
@echo -n $(LIBUV_URL) > out/deps/libuv.txt
|
|
||||||
@echo "[fetch] sqlite"
|
@echo "[fetch] sqlite"
|
||||||
@test -f out/deps/sqlite.zip && test "$$(cat out/deps/sqlite.txt 2>/dev/null)" = $(SQLITE_URL) || (mkdir -p out/deps/ && curl -q $(SQLITE_URL) -o out/deps/sqlite.zip)
|
@test -f out/deps/sqlite.zip && test "$$(cat out/deps/sqlite.txt 2>/dev/null)" = $(SQLITE_URL) || (mkdir -p out/deps/ && curl -q $(SQLITE_URL) -o out/deps/sqlite.zip)
|
||||||
@test -d deps/sqlite/ && test "$$(cat out/deps/sqlite.txt 2>/dev/null)" = $(SQLITE_URL) || (mkdir -p deps/sqlite/ && unzip -qDjo -d deps/sqlite/ out/deps/sqlite.zip)
|
@test -d deps/sqlite/ && test "$$(cat out/deps/sqlite.txt 2>/dev/null)" = $(SQLITE_URL) || (mkdir -p deps/sqlite/ && unzip -qDjo -d deps/sqlite/ out/deps/sqlite.zip)
|
||||||
@ -832,7 +1066,7 @@ fetchdeps:
|
|||||||
|
|
||||||
ANDROID_DEPS := deps/openssl/android/arm64-v8a/usr/local/lib/libssl.a
|
ANDROID_DEPS := deps/openssl/android/arm64-v8a/usr/local/lib/libssl.a
|
||||||
$(ANDROID_DEPS):
|
$(ANDROID_DEPS):
|
||||||
+@tools/ssl-android
|
+@ANDROID_NDK_ROOT=$(ANDROID_NDK) tools/ssl-android
|
||||||
$(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
|
$(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
|
||||||
|
|
||||||
ifeq ($(HAVE_WIN),1)
|
ifeq ($(HAVE_WIN),1)
|
||||||
@ -849,15 +1083,42 @@ $(IOS_DEPS):
|
|||||||
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(IOS_DEPS)
|
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(IOS_DEPS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
out/tildefriends-x86_64.AppImage: out/release/tildefriends out/data.zip
|
||||||
|
@echo "[appimage] $$@"
|
||||||
|
@rm -rf out/tildefriends.AppDir
|
||||||
|
@mkdir -p out/tildefriends.AppDir/usr/bin
|
||||||
|
@mkdir -p out/tildefriends.AppDir/usr/share/applications
|
||||||
|
@mkdir -p out/tildefriends.AppDir/usr/share/icons/hicolor/scalable/apps
|
||||||
|
@mkdir -p out/tildefriends.AppDir/usr/share/tildefriends
|
||||||
|
@echo $(APPIMAGETOOL_MD5) > out/appimagetool.md5
|
||||||
|
@test -x out/appimagetool || curl -q -L -o out/appimagetool $(APPIMAGETOOL_URL) && md5sum -c out/appimagetool.md5 && chmod +x out/appimagetool
|
||||||
|
@echo "[Desktop Entry]\nName=tildefriends\nExec=/usr/bin/tildefriends\nIcon=/usr/share/icons/hicolor/scalable/apps/tildefriends\nType=Application\nCategories=Network" > out/tildefriends.AppDir/tildefriends.desktop
|
||||||
|
@cp src/ios/tildefriends.svg out/tildefriends.AppDir/usr/share/icons/hicolor/scalable/apps/
|
||||||
|
@cp src/ios/tildefriends.svg out/tildefriends.AppDir/
|
||||||
|
@cp out/release/tildefriends out/tildefriends.AppDir/usr/bin/
|
||||||
|
@cp out/data.zip out/tildefriends.AppDir/usr/share/tildefriends/data.zip
|
||||||
|
@echo "#!/bin/sh\n\$${APPDIR}/usr/bin/tildefriends run -z \$$APPDIR/usr/share/tildefriends/data.zip" > out/tildefriends.AppDir/AppRun
|
||||||
|
@chmod +x out/tildefriends.AppDir/AppRun
|
||||||
|
@cd out; ./appimagetool --appimage-extract; cd ..
|
||||||
|
@cd out; unset SOURCE_DATE_EPOCH; PATH=$$PATH:squashfs-root/usr/bin ARCH=x86_64 squashfs-root/usr/bin/appimagetool -u 'zsync|https://dev.tildefriends.net/releases/tildefriends-x86_64.AppImage.zsync' tildefriends.AppDir tildefriends-x86_64.AppImage; cd ..
|
||||||
|
|
||||||
|
appimage: out/tildefriends-x86_64.AppImage
|
||||||
|
.PHONY: appimage
|
||||||
|
|
||||||
|
flatpak: out/
|
||||||
|
flatpak-builder --force-clean --user --install-deps-from=flathub --install --repo=out/flatpak-repo out/flatpak src/com.unprompted.tildefriends.yml
|
||||||
|
flatpak build-bundle out/flatpak-repo out/tildefriends.flatpak com.unprompted.tildefriends
|
||||||
|
.PHONY: flatpak
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)
|
rm -rf $(BUILD_DIR)
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
dist: release-apk iosrelease-ipa
|
tarball:
|
||||||
@echo [archive] dist/tildefriends-$(VERSION_NUMBER).tar.xz
|
@echo [archive] out/tildefriends-$(VERSION_NUMBER).tar.xz
|
||||||
@rm -rf out/tildefriends-$(VERSION_NUMBER)
|
@rm -rf out/tildefriends-$(VERSION_NUMBER)
|
||||||
@mkdir -p dist/ out/tildefriends-$(VERSION_NUMBER)
|
@mkdir -p out/tildefriends-$(VERSION_NUMBER)
|
||||||
@git archive HEAD | tar -x -C out/tildefriends-$(VERSION_NUMBER)
|
@git ls-files --recurse-submodules | tar -c -T- | tar -x -C out/tildefriends-$(VERSION_NUMBER)
|
||||||
@tar \
|
@tar \
|
||||||
--exclude=apps/welcome* \
|
--exclude=apps/welcome* \
|
||||||
--exclude=deps/libbacktrace/Isaac.Newton-Opticks.txt \
|
--exclude=deps/libbacktrace/Isaac.Newton-Opticks.txt \
|
||||||
@ -873,15 +1134,29 @@ dist: release-apk iosrelease-ipa
|
|||||||
--exclude=deps/sqlite/shell.c \
|
--exclude=deps/sqlite/shell.c \
|
||||||
--exclude=deps/zlib/contrib/vstudio \
|
--exclude=deps/zlib/contrib/vstudio \
|
||||||
--exclude=deps/zlib/doc \
|
--exclude=deps/zlib/doc \
|
||||||
-caf dist/tildefriends-$(VERSION_NUMBER).tar.xz \
|
-caf out/tildefriends-$(VERSION_NUMBER).tar.xz \
|
||||||
-C out/ \
|
-C out/ \
|
||||||
tildefriends-$(VERSION_NUMBER)
|
tildefriends-$(VERSION_NUMBER)
|
||||||
|
.PHONY: tarball
|
||||||
|
|
||||||
|
dist: release-apk iosrelease-ipa aab $(if $(HAVE_WIN), out/winrelease/tildefriends.standalone.exe) out/TildeFriends-release.fdroid.apk appimage tarball
|
||||||
|
@mkdir -p dist/
|
||||||
|
@echo "[cp] tildefriends-$(VERSION_NUMBER).tar.xz"
|
||||||
|
@cp out/tildefriends-$(VERSION_NUMBER).tar.xz dist/tildefriends-$(VERSION_NUMBER).tar.xz
|
||||||
@echo "[cp] TildeFriends-x86-$(VERSION_NUMBER).apk"
|
@echo "[cp] TildeFriends-x86-$(VERSION_NUMBER).apk"
|
||||||
@cp out/TildeFriends-x86-release.zopfli.apk dist/TildeFriends-x86-$(VERSION_NUMBER).apk
|
@cp out/TildeFriends-x86-release.zopfli.apk dist/TildeFriends-x86-$(VERSION_NUMBER).apk
|
||||||
@echo "[cp] TildeFriends-arm-$(VERSION_NUMBER).apk"
|
@echo "[cp] TildeFriends-arm-$(VERSION_NUMBER).apk"
|
||||||
@cp out/TildeFriends-arm-release.zopfli.apk dist/TildeFriends-arm-$(VERSION_NUMBER).apk
|
@cp out/TildeFriends-arm-release.zopfli.apk dist/TildeFriends-arm-$(VERSION_NUMBER).apk
|
||||||
@echo "[cp] TildeFriends-$(VERSION_NUMBER).ipa"
|
@echo "[cp] TildeFriends-$(VERSION_NUMBER).ipa"
|
||||||
@cp out/tildefriends-release.ipa dist/TildeFriends-$(VERSION_NUMBER).ipa
|
@cp out/tildefriends-release.ipa dist/TildeFriends-$(VERSION_NUMBER).ipa
|
||||||
|
@test $(HAVE_WIN) && echo "[cp] tildefriends-$(VERSION_NUMBER).exe"
|
||||||
|
@test $(HAVE_WIN) && cp out/winrelease/tildefriends.standalone.exe dist/tildefriends-$(VERSION_NUMBER).exe
|
||||||
|
@echo "[cp] TildeFriends-$(VERSION_NUMBER).aab"
|
||||||
|
@cp out/TildeFriends.aab dist/TildeFriends-$(VERSION_NUMBER).aab
|
||||||
|
@echo "[cp] TildeFriends-$(VERSION_NUMBER).fdroid.apk"
|
||||||
|
@cp out/TildeFriends-release.fdroid.apk dist/TildeFriends-$(VERSION_NUMBER).fdroid.apk
|
||||||
|
@echo "[cp] TildeFriends-x86_64-$(VERSION_NUMBER).AppImage"
|
||||||
|
@cp out/tildefriends-x86_64.AppImage dist/TildeFriends-x86_64-$(VERSION_NUMBER).AppImage
|
||||||
.PHONY: dist
|
.PHONY: dist
|
||||||
|
|
||||||
dist-test: dist
|
dist-test: dist
|
||||||
@ -902,3 +1177,6 @@ prettier:
|
|||||||
docs:
|
docs:
|
||||||
@doxygen
|
@doxygen
|
||||||
.PHONY: docs
|
.PHONY: docs
|
||||||
|
|
||||||
|
fdroid: out/apk/TildeFriends-release.fdroid.unsigned.apk
|
||||||
|
.PHONY: fdroid
|
||||||
|
20
README.md
20
README.md
@ -19,8 +19,24 @@ Scuttlebutt, as well as a platform for writing and running web applications.
|
|||||||
Builds on Linux (x86_64 and aarch64), MacOS, OpenBSD, and Haiku. Builds for
|
Builds on Linux (x86_64 and aarch64), MacOS, OpenBSD, and Haiku. Builds for
|
||||||
all of those host platforms plus mingw64, iOS, and android.
|
all of those host platforms plus mingw64, iOS, and android.
|
||||||
|
|
||||||
1. Requires openssl (`libssl-dev`, in debian-speak). All other dependencies
|
Tilde Friends uses git submodules, so either:
|
||||||
are kept up to date in the tree.
|
|
||||||
|
```
|
||||||
|
git clone --recurse-submodules https://dev.tildefriends.net/cory/tildefriends.git
|
||||||
|
```
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://dev.tildefriends.net/cory/tildefriends.git
|
||||||
|
cd tildefriends
|
||||||
|
git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
The `.tar.xz` source releases are all-inclusive.
|
||||||
|
|
||||||
|
1. On Linux only, system OpenSSL libraries (`libssl-dev`, in debian-speak) are
|
||||||
|
assumed to be available.
|
||||||
2. To build, run `make debug` or `make release`. An executable will be
|
2. To build, run `make debug` or `make release`. An executable will be
|
||||||
generated in a subdirectory of `out/`.
|
generated in a subdirectory of `out/`.
|
||||||
3. It's possible to build for Android, iOS, and Windows on Linux, if you have
|
3. It's possible to build for Android, iOS, and Windows on Linux, if you have
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🎛"
|
"emoji": "🎛",
|
||||||
|
"previous": "&R49FywYF8CXPhoSEydLbSCgvCddeyTiBwGuDU/gqY+M=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,38 @@
|
|||||||
<script>
|
<script>
|
||||||
const g_data = $data;
|
const g_data = $data;
|
||||||
</script>
|
</script>
|
||||||
|
<link rel="stylesheet" href="w3.css" />
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<style>
|
||||||
|
/* 2018 Valiant Poppy */
|
||||||
|
.w3-theme-l5 {color:#000 !important; background-color:#fbf3f3 !important}
|
||||||
|
.w3-theme-l4 {color:#000 !important; background-color:#f3d7d6 !important}
|
||||||
|
.w3-theme-l3 {color:#000 !important; background-color:#e6afae !important}
|
||||||
|
.w3-theme-l2 {color:#fff !important; background-color:#da8785 !important}
|
||||||
|
.w3-theme-l1 {color:#fff !important; background-color:#cd5f5d !important}
|
||||||
|
.w3-theme-d1 {color:#fff !important; background-color:#a93634 !important}
|
||||||
|
.w3-theme-d2 {color:#fff !important; background-color:#96302e !important}
|
||||||
|
.w3-theme-d3 {color:#fff !important; background-color:#832a28 !important}
|
||||||
|
.w3-theme-d4 {color:#fff !important; background-color:#702423 !important}
|
||||||
|
.w3-theme-d5 {color:#fff !important; background-color:#5e1e1d !important}
|
||||||
|
|
||||||
|
.w3-theme-light {color:#000 !important; background-color:#fbf3f3 !important}
|
||||||
|
.w3-theme-dark {color:#fff !important; background-color:#5e1e1d !important}
|
||||||
|
.w3-theme-action {color:#fff !important; background-color:#5e1e1d !important}
|
||||||
|
|
||||||
|
.w3-theme {color:#fff !important; background-color:#bd3d3a !important}
|
||||||
|
.w3-text-theme {color:#bd3d3a !important}
|
||||||
|
.w3-border-theme {border-color:#bd3d3a !important}
|
||||||
|
|
||||||
|
.w3-hover-theme:hover {color:#fff !important; background-color:#bd3d3a !important}
|
||||||
|
.w3-hover-text-theme:hover {color:#bd3d3a !important}
|
||||||
|
.w3-hover-border-theme:hover {border-color:#bd3d3a !important}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body style="color: #fff; width: 100%">
|
<body class="w3-theme-l4">
|
||||||
<h1>Tilde Friends Administration</h1>
|
<header class="w3-row w3-padding w3-header w3-theme-l1">
|
||||||
|
<h1>Tilde Friends Administration</h1>
|
||||||
|
</header>
|
||||||
</body>
|
</body>
|
||||||
<script type="module" src="script.js"></script>
|
<script type="module" src="script.js"></script>
|
||||||
</html>
|
</html>
|
||||||
|
@ -27,64 +27,87 @@ function global_settings_set(key, value) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function title_case(name) {
|
||||||
|
return name
|
||||||
|
.split('_')
|
||||||
|
.map((x) => x.charAt(0).toUpperCase() + x.substring(1))
|
||||||
|
.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('load', function () {
|
window.addEventListener('load', function () {
|
||||||
const permission_template = (permission) => html` <code>${permission}</code>`;
|
const permission_template = (permission) => html` <code>${permission}</code>`;
|
||||||
function input_template(key, description) {
|
function input_template(key, description) {
|
||||||
if (description.type === 'boolean') {
|
if (description.type === 'boolean') {
|
||||||
return html`
|
return html`
|
||||||
<div style="margin-top: 1em">
|
<li class="w3-row">
|
||||||
<label for=${'gs_' + key} style="font-weight: bold">${key}: </label>
|
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${title_case(key)}</label>
|
||||||
<div>
|
<div class="w3-quarter w3-padding">${description.description}</div>
|
||||||
<input type="checkbox" ?checked=${description.value} id=${'gs_' + key}></input>
|
<div class="w3-quarter w3-padding w3-center"><input class="w3-check" type="checkbox" ?checked=${description.value} id=${'gs_' + key}></input></div>
|
||||||
<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.checked)}>Set</button>
|
<button class="w3-quarter w3-button w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.firstChild.checked)}>Set</button>
|
||||||
<div>${description.description}</div>
|
</li>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
`;
|
||||||
} else if (description.type === 'textarea') {
|
} else if (description.type === 'textarea') {
|
||||||
return html`
|
return html`
|
||||||
<div style="margin-top: 1em"">
|
<li class="w3-row">
|
||||||
<label for=${'gs_' + key} style="font-weight: bold">${key}: </label>
|
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold"
|
||||||
<div style="width: 100%; padding: 0; margin: 0">
|
>${title_case(key)}</label
|
||||||
<div style="width: 90%; padding: 0 margin: 0">
|
>
|
||||||
<textarea style="vertical-align: top; width: 100%" rows=20 cols=80 id=${'gs_' + key}>${description.value}</textarea>
|
<div class="w3-rest w3-padding">${description.description}</div>
|
||||||
</div>
|
<textarea
|
||||||
<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.firstElementChild.value)}>Set</button>
|
class="w3-input"
|
||||||
<div>${description.description}</div>
|
style="vertical-align: top; resize: vertical"
|
||||||
</div>
|
id=${'gs_' + key}
|
||||||
</div>
|
>
|
||||||
|
${description.value}</textarea
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="w3-button w3-right w3-quarter w3-theme-action"
|
||||||
|
@click=${(e) =>
|
||||||
|
global_settings_set(
|
||||||
|
key,
|
||||||
|
e.srcElement.previousElementSibling.value
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
Set
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
return html`
|
return html`
|
||||||
<div style="margin-top: 1em">
|
<li class="w3-row">
|
||||||
<label for=${'gs_' + key} style="font-weight: bold">${key}: </label>
|
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${title_case(key)}</label>
|
||||||
<div>
|
<div class="w3-quarter w3-padding">${description.description}</div>
|
||||||
<input type="text" value="${description.value}" id=${'gs_' + key}></input>
|
<input class="w3-input w3-quarter" type="text" value="${description.value}" id=${'gs_' + key}></input>
|
||||||
<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.value)}>Set</button>
|
<button class="w3-button w3-quarter w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.value)}>Set</button>
|
||||||
<div>${description.description}</div>
|
</li>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const user_template = (user, permissions) => html`
|
const user_template = (user, permissions) => html`
|
||||||
<li>
|
<li class="w3-card w3-margin">
|
||||||
<button @click=${(e) => delete_user(user)}>Delete</button>
|
<button
|
||||||
|
class="w3-button w3-theme-action"
|
||||||
|
@click=${(e) => delete_user(user)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
${user}: ${permissions.map((x) => permission_template(x))}
|
${user}: ${permissions.map((x) => permission_template(x))}
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
const users_template = (users) =>
|
const users_template = (users) =>
|
||||||
html`<h2>Users</h2>
|
html` <header class="w3-container w3-theme-l2"><h2>Users</h2></header>
|
||||||
<ul>
|
<ul class="w3-ul">
|
||||||
${Object.entries(users).map((u) => user_template(u[0], u[1]))}
|
${Object.entries(users).map((u) => user_template(u[0], u[1]))}
|
||||||
</ul>`;
|
</ul>`;
|
||||||
const page_template = (data) =>
|
const page_template = (data) =>
|
||||||
html`<div style="padding: 0; margin: 0; width: 100%; max-width: 100%">
|
html`<div style="padding: 0; margin: 0; width: 100%; max-width: 100%">
|
||||||
<h2>Global Settings</h2>
|
<header class="w3-container w3-theme-l2"><h2>Global Settings</h2></header>
|
||||||
<div>
|
<div class="w3-container">
|
||||||
${Object.keys(data.settings)
|
<ul class="w3-ul">
|
||||||
.sort()
|
${Object.keys(data.settings)
|
||||||
.map((x) => html`${input_template(x, data.settings[x])}`)}
|
.sort()
|
||||||
|
.map((x) => html`${input_template(x, data.settings[x])}`)}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
${users_template(data.users)}
|
${users_template(data.users)}
|
||||||
</div> `;
|
</div> `;
|
||||||
|
235
apps/admin/w3.css
Normal file
235
apps/admin/w3.css
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */
|
||||||
|
html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
|
||||||
|
/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */
|
||||||
|
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
|
||||||
|
article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}
|
||||||
|
audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
|
||||||
|
audio:not([controls]){display:none;height:0}[hidden],template{display:none}
|
||||||
|
a{background-color:transparent}a:active,a:hover{outline-width:0}
|
||||||
|
abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
|
||||||
|
b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000}
|
||||||
|
small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||||||
|
sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}
|
||||||
|
code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
|
||||||
|
button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold}
|
||||||
|
button,input{overflow:visible}button,select{text-transform:none}
|
||||||
|
button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}
|
||||||
|
button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}
|
||||||
|
button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}
|
||||||
|
fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
|
||||||
|
legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
|
||||||
|
[type=checkbox],[type=radio]{padding:0}
|
||||||
|
[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
|
||||||
|
[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
|
||||||
|
[type=search]::-webkit-search-decoration{-webkit-appearance:none}
|
||||||
|
::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
|
||||||
|
/* End extract */
|
||||||
|
html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
|
||||||
|
h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}
|
||||||
|
.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace}
|
||||||
|
h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
|
||||||
|
hr{border:0;border-top:1px solid #eee;margin:20px 0}
|
||||||
|
.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit}
|
||||||
|
.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
|
||||||
|
.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
|
||||||
|
.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
|
||||||
|
.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
|
||||||
|
.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
|
||||||
|
.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
|
||||||
|
.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
|
||||||
|
.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
|
||||||
|
.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
||||||
|
.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
|
||||||
|
.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
|
||||||
|
.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
|
||||||
|
.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
|
||||||
|
.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
|
||||||
|
.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
|
||||||
|
.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
|
||||||
|
.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
|
||||||
|
.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
|
||||||
|
.w3-dropdown-hover:hover .w3-dropdown-content{display:block}
|
||||||
|
.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
|
||||||
|
.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
|
||||||
|
.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1}
|
||||||
|
.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
|
||||||
|
.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
|
||||||
|
.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
|
||||||
|
.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
|
||||||
|
.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
|
||||||
|
.w3-main,#main{transition:margin-left .4s}
|
||||||
|
.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
|
||||||
|
.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
|
||||||
|
.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
|
||||||
|
.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0}
|
||||||
|
.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
|
||||||
|
.w3-bar .w3-button{white-space:normal}
|
||||||
|
.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
|
||||||
|
.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
|
||||||
|
.w3-responsive{display:block;overflow-x:auto}
|
||||||
|
.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
|
||||||
|
.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
|
||||||
|
.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
|
||||||
|
.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
|
||||||
|
.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
|
||||||
|
.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
|
||||||
|
@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
|
||||||
|
.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
|
||||||
|
.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
|
||||||
|
@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
|
||||||
|
.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
|
||||||
|
.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
|
||||||
|
.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px}
|
||||||
|
.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px}
|
||||||
|
.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
|
||||||
|
.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
|
||||||
|
.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
|
||||||
|
@media (max-width:1205px){.w3-auto{max-width:95%}}
|
||||||
|
@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
|
||||||
|
.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}
|
||||||
|
.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
|
||||||
|
.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
|
||||||
|
@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
|
||||||
|
@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
|
||||||
|
@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
|
||||||
|
@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}}
|
||||||
|
.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
|
||||||
|
.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
|
||||||
|
.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
|
||||||
|
.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
|
||||||
|
.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
|
||||||
|
.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
|
||||||
|
.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
|
||||||
|
.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
|
||||||
|
.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
|
||||||
|
.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
|
||||||
|
.w3-display-position{position:absolute}
|
||||||
|
.w3-circle{border-radius:50%}
|
||||||
|
.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
|
||||||
|
.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
|
||||||
|
.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px}
|
||||||
|
.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
|
||||||
|
.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
|
||||||
|
.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
|
||||||
|
.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
|
||||||
|
.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
|
||||||
|
.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
|
||||||
|
.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
|
||||||
|
.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
|
||||||
|
.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
|
||||||
|
.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
|
||||||
|
.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
|
||||||
|
.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
|
||||||
|
.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
|
||||||
|
.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
|
||||||
|
.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
|
||||||
|
.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
|
||||||
|
.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
|
||||||
|
.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
|
||||||
|
.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
|
||||||
|
.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
|
||||||
|
.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
|
||||||
|
.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
|
||||||
|
.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
|
||||||
|
.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
|
||||||
|
.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
|
||||||
|
.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
|
||||||
|
.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
|
||||||
|
.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
|
||||||
|
.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
|
||||||
|
.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
|
||||||
|
.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
|
||||||
|
.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
|
||||||
|
.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
|
||||||
|
.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
|
||||||
|
.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important}
|
||||||
|
.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important}
|
||||||
|
.w3-left{float:left!important}.w3-right{float:right!important}
|
||||||
|
.w3-button:hover{color:#000!important;background-color:#ccc!important}
|
||||||
|
.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
|
||||||
|
.w3-hover-none:hover{box-shadow:none!important}
|
||||||
|
/* Colors */
|
||||||
|
.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
|
||||||
|
.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
|
||||||
|
.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
|
||||||
|
.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
|
||||||
|
.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
|
||||||
|
.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
|
||||||
|
.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
|
||||||
|
.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
|
||||||
|
.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
|
||||||
|
.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
|
||||||
|
.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
|
||||||
|
.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
|
||||||
|
.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
|
||||||
|
.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
|
||||||
|
.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
|
||||||
|
.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
|
||||||
|
.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
|
||||||
|
.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
|
||||||
|
.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
|
||||||
|
.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
|
||||||
|
.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
|
||||||
|
.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
|
||||||
|
.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
|
||||||
|
.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important}
|
||||||
|
.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
|
||||||
|
.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
|
||||||
|
.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
|
||||||
|
.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
|
||||||
|
.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
|
||||||
|
.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
|
||||||
|
.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
|
||||||
|
.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
|
||||||
|
.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
|
||||||
|
.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
|
||||||
|
.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
|
||||||
|
.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
|
||||||
|
.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important}
|
||||||
|
.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
|
||||||
|
.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
|
||||||
|
.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
|
||||||
|
.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
|
||||||
|
.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
|
||||||
|
.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
|
||||||
|
.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
|
||||||
|
.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
|
||||||
|
.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
|
||||||
|
.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
|
||||||
|
.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
|
||||||
|
.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
|
||||||
|
.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
|
||||||
|
.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
|
||||||
|
.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
|
||||||
|
.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
|
||||||
|
.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
|
||||||
|
.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
|
||||||
|
.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
|
||||||
|
.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important}
|
||||||
|
.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important}
|
||||||
|
.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
|
||||||
|
.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important}
|
||||||
|
.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important}
|
||||||
|
.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important}
|
||||||
|
.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important}
|
||||||
|
.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
|
||||||
|
.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important}
|
||||||
|
.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important}
|
||||||
|
.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important}
|
||||||
|
.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important}
|
||||||
|
.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important}
|
||||||
|
.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important}
|
||||||
|
.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important}
|
||||||
|
.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important}
|
||||||
|
.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important}
|
||||||
|
.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
|
||||||
|
.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important}
|
||||||
|
.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important}
|
||||||
|
.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
|
||||||
|
.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
|
||||||
|
.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
|
||||||
|
.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important}
|
||||||
|
.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important}
|
||||||
|
.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important}
|
||||||
|
.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important}
|
||||||
|
.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}
|
2
apps/blog/commonmark.min.js
vendored
2
apps/blog/commonmark.min.js
vendored
File diff suppressed because one or more lines are too long
42
apps/blog/lit-all.min.js
vendored
42
apps/blog/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "💽"
|
"emoji": "💽",
|
||||||
|
"previous": "&uQzkIe/Aj8yNhLKe3hEq+5fEJsGwIUx8NVBjJKwoV2U=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,19 @@ async function key_list(db) {
|
|||||||
app.setDocument(doc);
|
app.setDocument(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function load() {
|
||||||
|
if (core.user?.credentials?.session) {
|
||||||
|
database_list();
|
||||||
|
} else {
|
||||||
|
app.setDocument(`<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body style="background: #888">
|
||||||
|
<h1>Must be signed in to examine databases.</h1>
|
||||||
|
</body>
|
||||||
|
</html>`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
core.register('message', async function (message) {
|
core.register('message', async function (message) {
|
||||||
if (message.event == 'hashChange') {
|
if (message.event == 'hashChange') {
|
||||||
let hash = message.hash.substring(1);
|
let hash = message.hash.substring(1);
|
||||||
@ -62,9 +75,9 @@ core.register('message', async function (message) {
|
|||||||
} else if (hash.length) {
|
} else if (hash.length) {
|
||||||
key_list(await database(hash.split(':').slice(1).join(':')));
|
key_list(await database(hash.split(':').slice(1).join(':')));
|
||||||
} else {
|
} else {
|
||||||
database_list();
|
load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
database_list();
|
load();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🪪",
|
"emoji": "🪪",
|
||||||
"previous": "&kgukkyDk1RxgfzgMH6H/0QeDPIuwPZypLuAFax21ljk=.sha256"
|
"previous": "&5kw/2PgcySwOYCmAkjHTR2xTkIx3i7UjQmtQ8MfgWw8=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import * as tfrpc from '/tfrpc.js';
|
import * as tfrpc from '/tfrpc.js';
|
||||||
|
|
||||||
|
const is_admin = core.user?.credentials?.permissions?.administration;
|
||||||
|
|
||||||
tfrpc.register(async function get_private_key(id) {
|
tfrpc.register(async function get_private_key(id) {
|
||||||
return bip39Words(await ssb.getPrivateKey(id));
|
return bip39Words(await ssb.getPrivateKey(id));
|
||||||
});
|
});
|
||||||
@ -15,11 +17,44 @@ tfrpc.register(async function delete_id(id) {
|
|||||||
tfrpc.register(async function reload() {
|
tfrpc.register(async function reload() {
|
||||||
await main();
|
await main();
|
||||||
});
|
});
|
||||||
|
tfrpc.register(async function make_server(id) {
|
||||||
|
return await ssb.swapWithServerIdentity(id);
|
||||||
|
});
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
let ids = await ssb.getIdentities();
|
let ids = await ssb.getIdentities();
|
||||||
|
let server_id = await ssb.getServerIdentity();
|
||||||
await app.setDocument(
|
await app.setDocument(
|
||||||
`<body style="color: #fff">
|
`
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="w3.css"></link>
|
||||||
|
<style>
|
||||||
|
/* "2018 Sargasso Sea" */
|
||||||
|
.w3-theme-l5 {color:#000 !important; background-color:#f3f4f7 !important}
|
||||||
|
.w3-theme-l4 {color:#000 !important; background-color:#d7dbe3 !important}
|
||||||
|
.w3-theme-l3 {color:#000 !important; background-color:#b0b6c8 !important}
|
||||||
|
.w3-theme-l2 {color:#fff !important; background-color:#8892ac !important}
|
||||||
|
.w3-theme-l1 {color:#fff !important; background-color:#636f8e !important}
|
||||||
|
.w3-theme-d1 {color:#fff !important; background-color:#40485c !important}
|
||||||
|
.w3-theme-d2 {color:#fff !important; background-color:#394052 !important}
|
||||||
|
.w3-theme-d3 {color:#fff !important; background-color:#323848 !important}
|
||||||
|
.w3-theme-d4 {color:#fff !important; background-color:#2b303d !important}
|
||||||
|
.w3-theme-d5 {color:#fff !important; background-color:#242833 !important}
|
||||||
|
|
||||||
|
.w3-theme-light {color:#000 !important; background-color:#f3f4f7 !important}
|
||||||
|
.w3-theme-dark {color:#fff !important; background-color:#242833 !important}
|
||||||
|
.w3-theme-action {color:#fff !important; background-color:#242833 !important}
|
||||||
|
|
||||||
|
.w3-theme {color:#fff !important; background-color:#485167 !important}
|
||||||
|
.w3-text-theme {color:#485167 !important}
|
||||||
|
.w3-border-theme {border-color:#485167 !important}
|
||||||
|
|
||||||
|
.w3-hover-theme:hover {color:#fff !important; background-color:#485167 !important}
|
||||||
|
.w3-hover-text-theme:hover {color:#485167 !important}
|
||||||
|
.w3-hover-border-theme:hover {border-color:#485167 !important}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="w3-theme-l3">
|
||||||
<script>const handler = {};</script>
|
<script>const handler = {};</script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import * as tfrpc from '/static/tfrpc.js';
|
import * as tfrpc from '/static/tfrpc.js';
|
||||||
@ -27,7 +62,8 @@ async function main() {
|
|||||||
let id = event.srcElement.dataset.id;
|
let id = event.srcElement.dataset.id;
|
||||||
let element = document.createElement('textarea');
|
let element = document.createElement('textarea');
|
||||||
element.value = await tfrpc.rpc.get_private_key(id);
|
element.value = await tfrpc.rpc.get_private_key(id);
|
||||||
element.style = 'width: 100%; read-only: true';
|
element.style = 'width: 100%; height: auto; read-only: true; resize: none';
|
||||||
|
element.classList.add('w3-input');
|
||||||
element.readOnly = true;
|
element.readOnly = true;
|
||||||
event.srcElement.parentElement.appendChild(element);
|
event.srcElement.parentElement.appendChild(element);
|
||||||
event.srcElement.onclick = event => handler.hide_id(event, element);
|
event.srcElement.onclick = event => handler.hide_id(event, element);
|
||||||
@ -48,7 +84,7 @@ async function main() {
|
|||||||
alert('Successfully created: ' + id);
|
alert('Successfully created: ' + id);
|
||||||
await tfrpc.rpc.reload();
|
await tfrpc.rpc.reload();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert('Error creating identity: ' + e);
|
alert('Error creating identity: ' + e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handler.hide_id = function hide_id(event, element) {
|
handler.hide_id = function hide_id(event, element) {
|
||||||
@ -68,24 +104,48 @@ async function main() {
|
|||||||
alert('Error deleting ID: ' + e);
|
alert('Error deleting ID: ' + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handler.make_server = async function make_server(event) {
|
||||||
|
let id = event.srcElement.dataset.id;
|
||||||
|
try {
|
||||||
|
if (confirm('Are you sure you want to make "' + id + '" the server identity?\\n\\nFor it to take effect, you will need to both sign in again and restart Tilde Friends.')) {
|
||||||
|
await tfrpc.rpc.make_server(id);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
alert('Error making server ID: ' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<h1>SSB Identity Management</h1>
|
<header class="w3-theme w3-padding"><h1>SSB Identity Management</h1></header>
|
||||||
<h2>Create a new identity</h2>
|
<div class="w3-card-4 w3-margin">
|
||||||
<button id="create_id" onclick="handler.create_id()">Create Identity</button>
|
<header class="w3-container w3-theme-l2"><h2>Create a new identity</h2></header>
|
||||||
<h2>Import an SSB Identity from 12 BIP39 English Words</h2>
|
<footer class="w3-padding">
|
||||||
<textarea id="add_id" style="width: 100%" rows="4"></textarea><button id="add" onclick="handler.add_id(event)">Import Identity</button>
|
<button id="create_id" onclick="handler.create_id()" class="w3-button w3-theme">Create Identity</button>
|
||||||
<h2>Identities</h2>
|
</footer>
|
||||||
<ul>` +
|
</div>
|
||||||
ids
|
<div class="w3-card-4 w3-margin">
|
||||||
|
<header class="w3-container w3-theme-l2"><h2>Import an SSB Identity from 12 BIP39 English Words</h2></header>
|
||||||
|
<textarea id="add_id" style="width: 100%" rows="4" class="w3-input"></textarea>
|
||||||
|
<footer class="w3-padding">
|
||||||
|
<button id="add" onclick="handler.add_id(event)" class="w3-button w3-theme">Import Identity</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
<div class="w3-card-4 w3-margin">
|
||||||
|
<header class="w3-container w3-theme-l2"><h2>Identities</h2></header>
|
||||||
|
<ul class="w3-ul">` +
|
||||||
|
(ids ?? [])
|
||||||
.map(
|
.map(
|
||||||
(id) => `<li>
|
(
|
||||||
<button onclick="handler.export_id(event)" data-id="${id}">Export Identity</button>
|
id
|
||||||
<button onclick="handler.delete_id(event)" data-id="${id}">Delete Identity</button>
|
) => `<li style="overflow: hidden; text-wrap: nowrap; text-overflow: ellipsis">
|
||||||
${id}
|
<button onclick="handler.export_id(event)" data-id="${id}" class="w3-button w3-theme">Export Identity</button>
|
||||||
</li>`
|
<button onclick="handler.delete_id(event)" data-id="${id}" class="w3-button w3-theme">Delete Identity</button>
|
||||||
|
${is_admin && id != server_id ? `<button onclick="handler.make_server(event)" data-id="${id}" class="w3-button w3-theme">Make Server Identity</button>` : ''}
|
||||||
|
${id}${id == server_id ? ' <div class="w3-tag w3-theme-l4 w3-round">🖥 local server</div>' : ''}
|
||||||
|
</li>`
|
||||||
)
|
)
|
||||||
.join('\n') +
|
.join('\n') +
|
||||||
` </ul>
|
` </ul>
|
||||||
|
</div>
|
||||||
</body>`
|
</body>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
235
apps/identity/w3.css
Normal file
235
apps/identity/w3.css
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */
|
||||||
|
html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
|
||||||
|
/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */
|
||||||
|
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
|
||||||
|
article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}
|
||||||
|
audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
|
||||||
|
audio:not([controls]){display:none;height:0}[hidden],template{display:none}
|
||||||
|
a{background-color:transparent}a:active,a:hover{outline-width:0}
|
||||||
|
abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
|
||||||
|
b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000}
|
||||||
|
small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||||||
|
sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}
|
||||||
|
code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
|
||||||
|
button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold}
|
||||||
|
button,input{overflow:visible}button,select{text-transform:none}
|
||||||
|
button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}
|
||||||
|
button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}
|
||||||
|
button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}
|
||||||
|
fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
|
||||||
|
legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
|
||||||
|
[type=checkbox],[type=radio]{padding:0}
|
||||||
|
[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
|
||||||
|
[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
|
||||||
|
[type=search]::-webkit-search-decoration{-webkit-appearance:none}
|
||||||
|
::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
|
||||||
|
/* End extract */
|
||||||
|
html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
|
||||||
|
h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}
|
||||||
|
.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace}
|
||||||
|
h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
|
||||||
|
hr{border:0;border-top:1px solid #eee;margin:20px 0}
|
||||||
|
.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit}
|
||||||
|
.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
|
||||||
|
.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
|
||||||
|
.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
|
||||||
|
.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
|
||||||
|
.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
|
||||||
|
.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
|
||||||
|
.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
|
||||||
|
.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
|
||||||
|
.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
||||||
|
.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
|
||||||
|
.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
|
||||||
|
.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
|
||||||
|
.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
|
||||||
|
.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
|
||||||
|
.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
|
||||||
|
.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
|
||||||
|
.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
|
||||||
|
.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
|
||||||
|
.w3-dropdown-hover:hover .w3-dropdown-content{display:block}
|
||||||
|
.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
|
||||||
|
.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
|
||||||
|
.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1}
|
||||||
|
.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
|
||||||
|
.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
|
||||||
|
.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
|
||||||
|
.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
|
||||||
|
.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
|
||||||
|
.w3-main,#main{transition:margin-left .4s}
|
||||||
|
.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
|
||||||
|
.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
|
||||||
|
.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
|
||||||
|
.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0}
|
||||||
|
.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
|
||||||
|
.w3-bar .w3-button{white-space:normal}
|
||||||
|
.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
|
||||||
|
.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
|
||||||
|
.w3-responsive{display:block;overflow-x:auto}
|
||||||
|
.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
|
||||||
|
.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
|
||||||
|
.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
|
||||||
|
.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
|
||||||
|
.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
|
||||||
|
.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
|
||||||
|
@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
|
||||||
|
.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
|
||||||
|
.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
|
||||||
|
@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
|
||||||
|
.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
|
||||||
|
.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
|
||||||
|
.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px}
|
||||||
|
.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px}
|
||||||
|
.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
|
||||||
|
.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
|
||||||
|
.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
|
||||||
|
@media (max-width:1205px){.w3-auto{max-width:95%}}
|
||||||
|
@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
|
||||||
|
.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}
|
||||||
|
.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
|
||||||
|
.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
|
||||||
|
@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
|
||||||
|
@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
|
||||||
|
@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
|
||||||
|
@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}}
|
||||||
|
.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
|
||||||
|
.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
|
||||||
|
.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
|
||||||
|
.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
|
||||||
|
.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
|
||||||
|
.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
|
||||||
|
.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
|
||||||
|
.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
|
||||||
|
.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
|
||||||
|
.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
|
||||||
|
.w3-display-position{position:absolute}
|
||||||
|
.w3-circle{border-radius:50%}
|
||||||
|
.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
|
||||||
|
.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
|
||||||
|
.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px}
|
||||||
|
.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
|
||||||
|
.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
|
||||||
|
.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
|
||||||
|
.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
|
||||||
|
.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
|
||||||
|
.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
|
||||||
|
.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
|
||||||
|
.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
|
||||||
|
.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
|
||||||
|
.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
|
||||||
|
.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
|
||||||
|
.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
|
||||||
|
.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
|
||||||
|
.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
|
||||||
|
.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
|
||||||
|
.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
|
||||||
|
.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
|
||||||
|
.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
|
||||||
|
.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
|
||||||
|
.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
|
||||||
|
.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
|
||||||
|
.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
|
||||||
|
.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
|
||||||
|
.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
|
||||||
|
.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
|
||||||
|
.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
|
||||||
|
.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
|
||||||
|
.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
|
||||||
|
.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
|
||||||
|
.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
|
||||||
|
.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
|
||||||
|
.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
|
||||||
|
.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
|
||||||
|
.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
|
||||||
|
.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important}
|
||||||
|
.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important}
|
||||||
|
.w3-left{float:left!important}.w3-right{float:right!important}
|
||||||
|
.w3-button:hover{color:#000!important;background-color:#ccc!important}
|
||||||
|
.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
|
||||||
|
.w3-hover-none:hover{box-shadow:none!important}
|
||||||
|
/* Colors */
|
||||||
|
.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
|
||||||
|
.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
|
||||||
|
.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
|
||||||
|
.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
|
||||||
|
.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
|
||||||
|
.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
|
||||||
|
.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
|
||||||
|
.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
|
||||||
|
.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
|
||||||
|
.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
|
||||||
|
.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
|
||||||
|
.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
|
||||||
|
.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
|
||||||
|
.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
|
||||||
|
.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
|
||||||
|
.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
|
||||||
|
.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
|
||||||
|
.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
|
||||||
|
.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
|
||||||
|
.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
|
||||||
|
.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
|
||||||
|
.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
|
||||||
|
.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
|
||||||
|
.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important}
|
||||||
|
.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
|
||||||
|
.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
|
||||||
|
.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
|
||||||
|
.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
|
||||||
|
.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
|
||||||
|
.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
|
||||||
|
.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
|
||||||
|
.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
|
||||||
|
.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
|
||||||
|
.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
|
||||||
|
.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
|
||||||
|
.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
|
||||||
|
.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important}
|
||||||
|
.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
|
||||||
|
.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
|
||||||
|
.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
|
||||||
|
.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
|
||||||
|
.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
|
||||||
|
.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
|
||||||
|
.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
|
||||||
|
.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
|
||||||
|
.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
|
||||||
|
.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
|
||||||
|
.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
|
||||||
|
.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
|
||||||
|
.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
|
||||||
|
.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
|
||||||
|
.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
|
||||||
|
.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
|
||||||
|
.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
|
||||||
|
.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
|
||||||
|
.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
|
||||||
|
.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important}
|
||||||
|
.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important}
|
||||||
|
.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
|
||||||
|
.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important}
|
||||||
|
.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important}
|
||||||
|
.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important}
|
||||||
|
.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important}
|
||||||
|
.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
|
||||||
|
.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important}
|
||||||
|
.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important}
|
||||||
|
.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important}
|
||||||
|
.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important}
|
||||||
|
.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important}
|
||||||
|
.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important}
|
||||||
|
.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important}
|
||||||
|
.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important}
|
||||||
|
.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important}
|
||||||
|
.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
|
||||||
|
.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important}
|
||||||
|
.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important}
|
||||||
|
.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
|
||||||
|
.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
|
||||||
|
.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
|
||||||
|
.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important}
|
||||||
|
.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important}
|
||||||
|
.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important}
|
||||||
|
.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important}
|
||||||
|
.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🦟",
|
"emoji": "🦟",
|
||||||
"previous": "&TegdzvFE+im94shygaHkgDYSaSrwY2h0OKUXSRPBQDM=.sha256"
|
"previous": "&cUqvSDUls3jn0haD85LPFAGdkc8wFuy347TtATNcJgg=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -67,9 +67,6 @@ tfrpc.register(function getHash(id, message) {
|
|||||||
tfrpc.register(function setHash(hash) {
|
tfrpc.register(function setHash(hash) {
|
||||||
return app.setHash(hash);
|
return app.setHash(hash);
|
||||||
});
|
});
|
||||||
ssb.addEventListener('message', async function (id) {
|
|
||||||
await tfrpc.rpc.notifyNewMessage(id);
|
|
||||||
});
|
|
||||||
tfrpc.register(async function store_blob(blob) {
|
tfrpc.register(async function store_blob(blob) {
|
||||||
if (Array.isArray(blob)) {
|
if (Array.isArray(blob)) {
|
||||||
blob = Uint8Array.from(blob);
|
blob = Uint8Array.from(blob);
|
||||||
@ -85,13 +82,18 @@ tfrpc.register(async function store_message(message) {
|
|||||||
tfrpc.register(function apps() {
|
tfrpc.register(function apps() {
|
||||||
return core.apps();
|
return core.apps();
|
||||||
});
|
});
|
||||||
|
tfrpc.register(function getActiveIdentity() {
|
||||||
|
return ssb.getActiveIdentity();
|
||||||
|
});
|
||||||
tfrpc.register(async function try_decrypt(id, content) {
|
tfrpc.register(async function try_decrypt(id, content) {
|
||||||
return await ssb.privateMessageDecrypt(id, content);
|
return await ssb.privateMessageDecrypt(id, content);
|
||||||
});
|
});
|
||||||
ssb.addEventListener('broadcasts', async function () {
|
core.register('onMessage', async function (id) {
|
||||||
|
await tfrpc.rpc.notifyNewMessage(id);
|
||||||
|
});
|
||||||
|
core.register('onBroadcastsChanged', async function () {
|
||||||
await tfrpc.rpc.set('broadcasts', await ssb.getBroadcasts());
|
await tfrpc.rpc.set('broadcasts', await ssb.getBroadcasts());
|
||||||
});
|
});
|
||||||
|
|
||||||
core.register('onConnectionsChanged', async function () {
|
core.register('onConnectionsChanged', async function () {
|
||||||
await tfrpc.rpc.set('connections', await ssb.connections());
|
await tfrpc.rpc.set('connections', await ssb.connections());
|
||||||
});
|
});
|
||||||
|
2
apps/issues/commonmark.min.js
vendored
2
apps/issues/commonmark.min.js
vendored
File diff suppressed because one or more lines are too long
42
apps/issues/lit-all.min.js
vendored
42
apps/issues/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -4,48 +4,6 @@ import * as tfutils from './tf-utils.js';
|
|||||||
|
|
||||||
const k_project = '%Hr+4xEVtjplidSKBlRWi4Aw/0Tfw7B+1OR9BzlDKmOI=.sha256';
|
const k_project = '%Hr+4xEVtjplidSKBlRWi4Aw/0Tfw7B+1OR9BzlDKmOI=.sha256';
|
||||||
|
|
||||||
class TfIdPickerElement extends LitElement {
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
ids: {type: Array},
|
|
||||||
selected: {type: String},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
async load() {
|
|
||||||
this.selected = await tfrpc.rpc.localStorageGet('whoami');
|
|
||||||
this.ids = (await tfrpc.rpc.getIdentities()) || [];
|
|
||||||
}
|
|
||||||
|
|
||||||
changed(event) {
|
|
||||||
this.selected = event.srcElement.value;
|
|
||||||
tfrpc.rpc.localStorageSet('whoami', this.selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.ids) {
|
|
||||||
return html`
|
|
||||||
<select @change=${this.changed} style="max-width: 100%">
|
|
||||||
${this.ids.map(
|
|
||||||
(id) =>
|
|
||||||
html`<option ?selected=${id == this.selected} value=${id}>
|
|
||||||
${id}
|
|
||||||
</option>`
|
|
||||||
)}
|
|
||||||
</select>
|
|
||||||
`;
|
|
||||||
} else {
|
|
||||||
return html`<div>Loading...</div>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
customElements.define('tf-id-picker', TfIdPickerElement);
|
|
||||||
|
|
||||||
class TfComposeElement extends LitElement {
|
class TfComposeElement extends LitElement {
|
||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
@ -105,10 +63,10 @@ class TfIssuesAppElement extends LitElement {
|
|||||||
let issues = {};
|
let issues = {};
|
||||||
let messages = await tfrpc.rpc.query(
|
let messages = await tfrpc.rpc.query(
|
||||||
`
|
`
|
||||||
WITH issues AS (SELECT messages.* FROM messages_refs JOIN messages ON
|
WITH issues AS (SELECT messages.id, json(messages.content) AS content, messages.author, messages.timestamp FROM messages_refs JOIN messages ON
|
||||||
messages.id = messages_refs.message
|
messages.id = messages_refs.message
|
||||||
WHERE messages_refs.ref = ? AND json_extract(messages.content, '$.type') = 'issue'),
|
WHERE messages_refs.ref = ? AND json_extract(messages.content, '$.type') = 'issue'),
|
||||||
edits AS (SELECT messages.* FROM issues JOIN messages_refs ON
|
edits AS (SELECT messages.id, json(messages.content) AS content, messages.author, messages.timestamp FROM issues JOIN messages_refs ON
|
||||||
issues.id = messages_refs.ref JOIN messages ON
|
issues.id = messages_refs.ref JOIN messages ON
|
||||||
messages.id = messages_refs.message
|
messages.id = messages_refs.message
|
||||||
WHERE json_extract(messages.content, '$.type') IN ('issue-edit', 'post'))
|
WHERE json_extract(messages.content, '$.type') IN ('issue-edit', 'post'))
|
||||||
@ -206,7 +164,7 @@ class TfIssuesAppElement extends LitElement {
|
|||||||
if (
|
if (
|
||||||
confirm(`Are you sure you want to ${open ? 'open' : 'close'} this issue?`)
|
confirm(`Are you sure you want to ${open ? 'open' : 'close'} this issue?`)
|
||||||
) {
|
) {
|
||||||
let whoami = this.shadowRoot.getElementById('picker').selected;
|
let whoami = await tfrpc.rpc.getActiveIdentity();
|
||||||
await tfrpc.rpc.appendMessage(whoami, {
|
await tfrpc.rpc.appendMessage(whoami, {
|
||||||
type: 'issue-edit',
|
type: 'issue-edit',
|
||||||
issues: [
|
issues: [
|
||||||
@ -221,7 +179,7 @@ class TfIssuesAppElement extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async create_issue(event) {
|
async create_issue(event) {
|
||||||
let whoami = this.shadowRoot.getElementById('picker').selected;
|
let whoami = await tfrpc.rpc.getActiveIdentity();
|
||||||
await tfrpc.rpc.appendMessage(whoami, {
|
await tfrpc.rpc.appendMessage(whoami, {
|
||||||
type: 'issue',
|
type: 'issue',
|
||||||
project: k_project,
|
project: k_project,
|
||||||
@ -231,7 +189,7 @@ class TfIssuesAppElement extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async reply_to_issue(event) {
|
async reply_to_issue(event) {
|
||||||
let whoami = this.shadowRoot.getElementById('picker').selected;
|
let whoami = await tfrpc.rpc.getActiveIdentity();
|
||||||
await tfrpc.rpc.appendMessage(whoami, {
|
await tfrpc.rpc.appendMessage(whoami, {
|
||||||
type: 'post',
|
type: 'post',
|
||||||
text: event.detail.value,
|
text: event.detail.value,
|
||||||
@ -249,10 +207,7 @@ class TfIssuesAppElement extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let header = html`
|
let header = html` <h1>Tilde Friends Issues</h1> `;
|
||||||
<h1>Tilde Friends Issues</h1>
|
|
||||||
<tf-id-picker id="picker"></tf-id-picker>
|
|
||||||
`;
|
|
||||||
if (this.selected) {
|
if (this.selected) {
|
||||||
return html`
|
return html`
|
||||||
${header}
|
${header}
|
||||||
|
@ -55,7 +55,7 @@ function new_message() {
|
|||||||
return g_new_message_promise;
|
return g_new_message_promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssb.addEventListener('message', function (id) {
|
core.register('onMessage', function (id) {
|
||||||
let resolve = g_new_message_resolve;
|
let resolve = g_new_message_resolve;
|
||||||
g_new_message_promise = new Promise(function (resolve, reject) {
|
g_new_message_promise = new Promise(function (resolve, reject) {
|
||||||
g_new_message_resolve = resolve;
|
g_new_message_resolve = resolve;
|
||||||
|
2
apps/journal/commonmark.min.js
vendored
2
apps/journal/commonmark.min.js
vendored
File diff suppressed because one or more lines are too long
42
apps/journal/lit-all.min.js
vendored
42
apps/journal/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "📦",
|
"emoji": "🚪",
|
||||||
"previous": "&IU+TwyM7TznD8NBfnw7tgW2zxVlMqTVxSqWFjuosLwo=.sha256"
|
"previous": "&HXCdDG8gGYXElTyEFbg85jqa6lDXNL2ENPIA9UoJNbI=.sha256"
|
||||||
}
|
}
|
||||||
|
42
apps/sneaker/lit-all.min.js
vendored
42
apps/sneaker/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🐌",
|
"emoji": "🐌",
|
||||||
"previous": "&Xs1X5TzLCk6KVr+5IDc80JAHYxJyoD10cXKBUYpFqWQ=.sha256"
|
"previous": "&0ZjcRFTyAmJMm3qhqKy5Ffrue23G1CAUfc1i2WYZrzQ=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ tfrpc.register(function getHash(id, message) {
|
|||||||
tfrpc.register(function setHash(hash) {
|
tfrpc.register(function setHash(hash) {
|
||||||
return app.setHash(hash);
|
return app.setHash(hash);
|
||||||
});
|
});
|
||||||
ssb.addEventListener('message', async function (id) {
|
core.register('onMessage', async function (id) {
|
||||||
await tfrpc.rpc.notifyNewMessage(id);
|
await tfrpc.rpc.notifyNewMessage(id);
|
||||||
});
|
});
|
||||||
tfrpc.register(async function store_blob(blob) {
|
tfrpc.register(async function store_blob(blob) {
|
||||||
@ -100,13 +100,22 @@ tfrpc.register(async function try_decrypt(id, content) {
|
|||||||
tfrpc.register(async function encrypt(id, recipients, content) {
|
tfrpc.register(async function encrypt(id, recipients, content) {
|
||||||
return await ssb.privateMessageEncrypt(id, recipients, content);
|
return await ssb.privateMessageEncrypt(id, recipients, content);
|
||||||
});
|
});
|
||||||
ssb.addEventListener('broadcasts', async function () {
|
tfrpc.register(async function getActiveIdentity() {
|
||||||
|
return await ssb.getActiveIdentity();
|
||||||
|
});
|
||||||
|
tfrpc.register(async function sync() {
|
||||||
|
return await ssb.sync();
|
||||||
|
});
|
||||||
|
core.register('onBroadcastsChanged', async function () {
|
||||||
await tfrpc.rpc.set('broadcasts', await ssb.getBroadcasts());
|
await tfrpc.rpc.set('broadcasts', await ssb.getBroadcasts());
|
||||||
});
|
});
|
||||||
|
|
||||||
core.register('onConnectionsChanged', async function () {
|
core.register('onConnectionsChanged', async function () {
|
||||||
await tfrpc.rpc.set('connections', await ssb.connections());
|
await tfrpc.rpc.set('connections', await ssb.connections());
|
||||||
});
|
});
|
||||||
|
core.register('setActiveIdentity', async function (id) {
|
||||||
|
await tfrpc.rpc.set('identity', id);
|
||||||
|
});
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
if (typeof database !== 'undefined') {
|
if (typeof database !== 'undefined') {
|
||||||
|
@ -1,90 +1,94 @@
|
|||||||
function textNode(text) {
|
function textNode(text) {
|
||||||
const node = new commonmark.Node("text", undefined);
|
const node = new commonmark.Node('text', undefined);
|
||||||
node.literal = text;
|
node.literal = text;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
function linkNode(text, link) {
|
function linkNode(text, link) {
|
||||||
const linkNode = new commonmark.Node("link", undefined);
|
const linkNode = new commonmark.Node('link', undefined);
|
||||||
linkNode.destination = `#q=${encodeURIComponent(link)}`;
|
if (link.startsWith('#')) {
|
||||||
linkNode.appendChild(textNode(text));
|
linkNode.destination = `#q=${encodeURIComponent(link)}`;
|
||||||
return linkNode;
|
} else {
|
||||||
|
linkNode.destination = link;
|
||||||
|
}
|
||||||
|
linkNode.appendChild(textNode(text));
|
||||||
|
return linkNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function splitMatches(text, regexp) {
|
function splitMatches(text, regexp) {
|
||||||
// Regexp must be sticky.
|
// Regexp must be sticky.
|
||||||
regexp = new RegExp(regexp, "gm");
|
regexp = new RegExp(regexp, 'gm');
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
const result = [];
|
const result = [];
|
||||||
|
|
||||||
let match = regexp.exec(text);
|
let match = regexp.exec(text);
|
||||||
while (match) {
|
while (match) {
|
||||||
const matchText = match[0];
|
const matchText = match[0];
|
||||||
|
|
||||||
if (match.index > i) {
|
if (match.index > i) {
|
||||||
result.push([text.substring(i, match.index), false]);
|
result.push([text.substring(i, match.index), false]);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push([matchText, true]);
|
result.push([matchText, true]);
|
||||||
i = match.index + matchText.length;
|
i = match.index + matchText.length;
|
||||||
|
|
||||||
match = regexp.exec(text);
|
match = regexp.exec(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < text.length) {
|
if (i < text.length) {
|
||||||
result.push([text.substring(i, text.length), false]);
|
result.push([text.substring(i, text.length), false]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const regex = new RegExp("(?<!\\w)#[\\w-]+");
|
const regex = new RegExp('(?:https?://[^ ]+[^ .,])|(?:(?<!\\w)#[\\w-]+)|(?:@[A-Za-z0-9+/]+=.ed25519)|(?:[%&][A-Za-z0-9+/]+=.sha256)');
|
||||||
|
|
||||||
function split(textNodes) {
|
function split(textNodes) {
|
||||||
const text = textNodes.map(n => n.literal).join("");
|
const text = textNodes.map((n) => n.literal).join('');
|
||||||
const parts = splitMatches(text, regex);
|
const parts = splitMatches(text, regex);
|
||||||
|
|
||||||
return parts.map(part => {
|
return parts.map((part) => {
|
||||||
if (part[1]) {
|
if (part[1]) {
|
||||||
return linkNode(part[0], part[0]);
|
return linkNode(part[0], part[0]);
|
||||||
} else {
|
} else {
|
||||||
return textNode(part[0]);
|
return textNode(part[0]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transform(parsed) {
|
export function transform(parsed) {
|
||||||
const walker = parsed.walker();
|
const walker = parsed.walker();
|
||||||
let event;
|
let event;
|
||||||
|
|
||||||
let nodes = [];
|
let nodes = [];
|
||||||
while ((event = walker.next())) {
|
while ((event = walker.next())) {
|
||||||
const node = event.node;
|
const node = event.node;
|
||||||
if (event.entering && node.type === "text") {
|
if (event.entering && node.type === 'text') {
|
||||||
nodes.push(node);
|
nodes.push(node);
|
||||||
} else {
|
} else {
|
||||||
if (nodes.length > 0) {
|
if (nodes.length > 0) {
|
||||||
split(nodes)
|
split(nodes)
|
||||||
.reverse()
|
.reverse()
|
||||||
.forEach(newNode => {
|
.forEach((newNode) => {
|
||||||
nodes[0].insertAfter(newNode);
|
nodes[0].insertAfter(newNode);
|
||||||
});
|
});
|
||||||
|
|
||||||
nodes.forEach(n => n.unlink());
|
nodes.forEach((n) => n.unlink());
|
||||||
nodes = [];
|
nodes = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodes.length > 0) {
|
if (nodes.length > 0) {
|
||||||
split(nodes)
|
split(nodes)
|
||||||
.reverse()
|
.reverse()
|
||||||
.forEach(newNode => {
|
.forEach((newNode) => {
|
||||||
nodes[0].insertAfter(newNode);
|
nodes[0].insertAfter(newNode);
|
||||||
});
|
});
|
||||||
nodes.forEach(n => n.unlink());
|
nodes.forEach((n) => n.unlink());
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
function textNode(text) {
|
|
||||||
const node = new commonmark.Node("text", undefined);
|
|
||||||
node.literal = text;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
function linkNode(text, url) {
|
|
||||||
const urlNode = new commonmark.Node("link", undefined);
|
|
||||||
urlNode.destination = url;
|
|
||||||
urlNode.appendChild(textNode(text));
|
|
||||||
|
|
||||||
return urlNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
function splitMatches(text, regexp) {
|
|
||||||
// Regexp must be sticky.
|
|
||||||
regexp = new RegExp(regexp, "gm");
|
|
||||||
|
|
||||||
let i = 0;
|
|
||||||
const result = [];
|
|
||||||
|
|
||||||
let match = regexp.exec(text);
|
|
||||||
while (match) {
|
|
||||||
const matchText = match[0];
|
|
||||||
|
|
||||||
if (match.index > i) {
|
|
||||||
result.push([text.substring(i, match.index), false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push([matchText, true]);
|
|
||||||
i = match.index + matchText.length;
|
|
||||||
|
|
||||||
match = regexp.exec(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < text.length) {
|
|
||||||
result.push([text.substring(i, text.length), false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const urlRegexp = new RegExp("https?://[^ ]+[^ .,]");
|
|
||||||
|
|
||||||
function splitURLs(textNodes) {
|
|
||||||
const text = textNodes.map(n => n.literal).join("");
|
|
||||||
const parts = splitMatches(text, urlRegexp);
|
|
||||||
|
|
||||||
return parts.map(part => {
|
|
||||||
if (part[1]) {
|
|
||||||
return linkNode(part[0], part[0]);
|
|
||||||
} else {
|
|
||||||
return textNode(part[0]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function transform(parsed) {
|
|
||||||
const walker = parsed.walker();
|
|
||||||
let event;
|
|
||||||
|
|
||||||
let nodes = [];
|
|
||||||
while ((event = walker.next())) {
|
|
||||||
const node = event.node;
|
|
||||||
if (event.entering && node.type === "text") {
|
|
||||||
nodes.push(node);
|
|
||||||
} else {
|
|
||||||
if (nodes.length > 0) {
|
|
||||||
splitURLs(nodes)
|
|
||||||
.reverse()
|
|
||||||
.forEach(newNode => {
|
|
||||||
nodes[0].insertAfter(newNode);
|
|
||||||
});
|
|
||||||
|
|
||||||
nodes.forEach(n => n.unlink());
|
|
||||||
nodes = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodes.length > 0) {
|
|
||||||
splitURLs(nodes)
|
|
||||||
.reverse()
|
|
||||||
.forEach(newNode => {
|
|
||||||
nodes[0].insertAfter(newNode);
|
|
||||||
});
|
|
||||||
nodes.forEach(n => n.unlink());
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsed;
|
|
||||||
}
|
|
2
apps/ssb/commonmark.min.js
vendored
2
apps/ssb/commonmark.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,3 +1,7 @@
|
|||||||
|
import * as tfrpc from '/static/tfrpc.js';
|
||||||
|
import {html, render} from './lit-all.min.js';
|
||||||
|
import {styles} from './tf-styles.js';
|
||||||
|
|
||||||
let g_emojis;
|
let g_emojis;
|
||||||
|
|
||||||
function get_emojis() {
|
function get_emojis() {
|
||||||
@ -10,105 +14,151 @@ function get_emojis() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function picker(callback, anchor) {
|
async function get_recent(author) {
|
||||||
get_emojis().then(function (json) {
|
let recent = await tfrpc.rpc.query(
|
||||||
let div = document.createElement('div');
|
`
|
||||||
div.id = 'emoji_picker';
|
SELECT DISTINCT content ->> '$.vote.expression' AS value
|
||||||
div.style.color = '#000';
|
FROM messages
|
||||||
div.style.background = '#fff';
|
WHERE author = ? AND
|
||||||
div.style.border = '1px solid #000';
|
content ->> '$.type' = 'vote'
|
||||||
div.style.display = 'block';
|
ORDER BY timestamp DESC LIMIT 10
|
||||||
div.style.position = 'absolute';
|
`,
|
||||||
div.style.minWidth = 'min(16em, 90vw)';
|
[author]
|
||||||
div.style.width = 'min(16em, 90vw)';
|
);
|
||||||
div.style.maxWidth = 'min(16em, 90vw)';
|
return recent.map((x) => x.value);
|
||||||
div.style.maxHeight = '16em';
|
}
|
||||||
div.style.overflow = 'scroll';
|
|
||||||
div.style.fontWeight = 'bold';
|
|
||||||
div.style.fontSize = 'xx-large';
|
|
||||||
let input = document.createElement('input');
|
|
||||||
input.type = 'text';
|
|
||||||
input.style.display = 'block';
|
|
||||||
input.style.boxSizing = 'border-box';
|
|
||||||
input.style.width = '100%';
|
|
||||||
input.style.margin = '0';
|
|
||||||
input.style.position = 'relative';
|
|
||||||
div.appendChild(input);
|
|
||||||
let list = document.createElement('div');
|
|
||||||
div.appendChild(list);
|
|
||||||
div.addEventListener('mousedown', function (event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
});
|
|
||||||
|
|
||||||
function cleanup() {
|
export async function picker(callback, anchor, author) {
|
||||||
console.log('emoji cleanup');
|
let json = await get_emojis();
|
||||||
div.parentElement.removeChild(div);
|
let recent = await get_recent(author);
|
||||||
window.removeEventListener('keydown', key_down);
|
|
||||||
console.log('removing click');
|
|
||||||
document.body.removeEventListener('mousedown', cleanup);
|
|
||||||
}
|
|
||||||
|
|
||||||
function key_down(event) {
|
let div = document.createElement('div');
|
||||||
if (event.key == 'Escape') {
|
div.id = 'emoji_picker';
|
||||||
cleanup();
|
div.style.color = '#000';
|
||||||
}
|
div.style.background = '#fff';
|
||||||
}
|
div.style.border = '1px solid #000';
|
||||||
|
div.style.display = 'block';
|
||||||
|
div.style.overflow = 'scroll';
|
||||||
|
div.style.fontWeight = 'bold';
|
||||||
|
div.style.fontSize = 'xx-large';
|
||||||
|
let input = document.createElement('input');
|
||||||
|
input.type = 'text';
|
||||||
|
input.style.display = 'block';
|
||||||
|
input.style.boxSizing = 'border-box';
|
||||||
|
input.style.width = '100%';
|
||||||
|
input.style.margin = '0';
|
||||||
|
input.style.position = 'relative';
|
||||||
|
div.appendChild(input);
|
||||||
|
let list = document.createElement('div');
|
||||||
|
div.appendChild(list);
|
||||||
|
div.addEventListener('mousedown', function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
function chosen(event) {
|
function key_down(event) {
|
||||||
console.log(event.srcElement.innerText);
|
if (event.key == 'Escape') {
|
||||||
callback(event.srcElement.innerText);
|
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function refresh() {
|
function chosen(event) {
|
||||||
while (list.firstChild) {
|
console.log(event.srcElement.innerText);
|
||||||
list.removeChild(list.firstChild);
|
callback(event.srcElement.innerText);
|
||||||
}
|
cleanup();
|
||||||
let search = input.value.toLowerCase();
|
}
|
||||||
let any_at_all = false;
|
|
||||||
for (let row of Object.entries(json)) {
|
function refresh() {
|
||||||
let header = document.createElement('div');
|
while (list.firstChild) {
|
||||||
header.appendChild(document.createTextNode(row[0]));
|
list.removeChild(list.firstChild);
|
||||||
list.appendChild(header);
|
}
|
||||||
let any = false;
|
let search = input.value.toLowerCase();
|
||||||
for (let entry of Object.entries(row[1])) {
|
let any_at_all = false;
|
||||||
if (
|
if (recent) {
|
||||||
search &&
|
let emoji_to_name = {};
|
||||||
search.length &&
|
for (let row of Object.values(json)) {
|
||||||
entry[0].toLowerCase().indexOf(search) == -1
|
for (let entry of Object.entries(row)) {
|
||||||
) {
|
emoji_to_name[entry[1]] = entry[0];
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let emoji = document.createElement('span');
|
|
||||||
const k_size = '1.25em';
|
|
||||||
emoji.style.display = 'inline-block';
|
|
||||||
emoji.style.overflow = 'hidden';
|
|
||||||
emoji.style.cursor = 'pointer';
|
|
||||||
emoji.onclick = chosen;
|
|
||||||
emoji.title = entry[0];
|
|
||||||
emoji.appendChild(document.createTextNode(entry[1]));
|
|
||||||
list.appendChild(emoji);
|
|
||||||
any = true;
|
|
||||||
any_at_all = true;
|
|
||||||
}
|
|
||||||
if (!any) {
|
|
||||||
list.removeChild(header);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!any_at_all) {
|
let header = document.createElement('div');
|
||||||
list.appendChild(document.createTextNode('No matches found.'));
|
header.appendChild(document.createTextNode('Recent'));
|
||||||
|
list.appendChild(header);
|
||||||
|
let any = false;
|
||||||
|
for (let entry of recent) {
|
||||||
|
if (
|
||||||
|
search &&
|
||||||
|
search.length &&
|
||||||
|
(emoji_to_name[entry] || '').toLowerCase().indexOf(search) == -1
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let emoji = document.createElement('span');
|
||||||
|
const k_size = '1.25em';
|
||||||
|
emoji.style.display = 'inline-block';
|
||||||
|
emoji.style.overflow = 'hidden';
|
||||||
|
emoji.style.cursor = 'pointer';
|
||||||
|
emoji.onclick = chosen;
|
||||||
|
emoji.title = emoji_to_name[entry] || entry;
|
||||||
|
emoji.appendChild(document.createTextNode(entry));
|
||||||
|
list.appendChild(emoji);
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
if (!any) {
|
||||||
|
list.removeChild(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
refresh();
|
for (let row of Object.entries(json)) {
|
||||||
input.oninput = refresh;
|
let header = document.createElement('div');
|
||||||
document.body.appendChild(div);
|
header.appendChild(document.createTextNode(row[0]));
|
||||||
div.style.position = 'fixed';
|
list.appendChild(header);
|
||||||
div.style.top = '50%';
|
let any = false;
|
||||||
div.style.left = '50%';
|
for (let entry of Object.entries(row[1])) {
|
||||||
div.style.transform = 'translate(-50%, -50%)';
|
if (
|
||||||
input.focus();
|
search &&
|
||||||
console.log('adding click');
|
search.length &&
|
||||||
document.body.addEventListener('mousedown', cleanup);
|
entry[0].toLowerCase().indexOf(search) == -1
|
||||||
window.addEventListener('keydown', key_down);
|
) {
|
||||||
});
|
continue;
|
||||||
|
}
|
||||||
|
let emoji = document.createElement('span');
|
||||||
|
const k_size = '1.25em';
|
||||||
|
emoji.style.display = 'inline-block';
|
||||||
|
emoji.style.overflow = 'hidden';
|
||||||
|
emoji.style.cursor = 'pointer';
|
||||||
|
emoji.onclick = chosen;
|
||||||
|
emoji.title = entry[0];
|
||||||
|
emoji.appendChild(document.createTextNode(entry[1]));
|
||||||
|
list.appendChild(emoji);
|
||||||
|
any = true;
|
||||||
|
any_at_all = true;
|
||||||
|
}
|
||||||
|
if (!any) {
|
||||||
|
list.removeChild(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!any_at_all) {
|
||||||
|
list.appendChild(document.createTextNode('No matches found.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
input.oninput = refresh;
|
||||||
|
let modal = html`
|
||||||
|
<style>
|
||||||
|
${styles}
|
||||||
|
</style>
|
||||||
|
<div class="w3-modal" style="display: block">
|
||||||
|
<div class="w3-modal-content w3-card-4">${div}</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
let parent = document.createElement('div');
|
||||||
|
document.body.appendChild(parent);
|
||||||
|
function cleanup() {
|
||||||
|
parent.parentElement.removeChild(parent);
|
||||||
|
window.removeEventListener('keydown', key_down);
|
||||||
|
document.body.removeEventListener('mousedown', cleanup);
|
||||||
|
}
|
||||||
|
render(modal, parent);
|
||||||
|
input.focus();
|
||||||
|
document.body.addEventListener('mousedown', cleanup);
|
||||||
|
window.addEventListener('keydown', key_down);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html style="color: #fff">
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Tilde Friends</title>
|
<title>Tilde Friends</title>
|
||||||
<base target="_top" />
|
<base target="_top" />
|
||||||
@ -10,14 +10,14 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body style="background-color: #223a5e">
|
<body style="margin: 0; padding: 0">
|
||||||
<tf-app class="w3-deep-purple" />
|
<tf-app></tf-app>
|
||||||
|
<tf-reactions-modal id="reactions_modal"></tf-reactions-modal>
|
||||||
<script>
|
<script>
|
||||||
window.litDisableBundleWarning = true;
|
window.litDisableBundleWarning = true;
|
||||||
</script>
|
</script>
|
||||||
<script src="filesaver.min.js"></script>
|
<script src="filesaver.min.js"></script>
|
||||||
<script src="commonmark.min.js"></script>
|
<script src="commonmark.min.js"></script>
|
||||||
<script src="commonmark-linkify.js" type="module"></script>
|
|
||||||
<script src="commonmark-hashtag.js" type="module"></script>
|
<script src="commonmark-hashtag.js" type="module"></script>
|
||||||
<script src="script.js" type="module"></script>
|
<script src="script.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
|
42
apps/ssb/lit-all.min.js
vendored
42
apps/ssb/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,13 +1,13 @@
|
|||||||
import {LitElement, html} from './lit-all.min.js';
|
import {LitElement, html} from './lit-all.min.js';
|
||||||
import * as tfrpc from '/static/tfrpc.js';
|
import * as tfrpc from '/static/tfrpc.js';
|
||||||
|
|
||||||
import * as tf_id_picker from './tf-id-picker.js';
|
|
||||||
import * as tf_app from './tf-app.js';
|
import * as tf_app from './tf-app.js';
|
||||||
import * as tf_message from './tf-message.js';
|
import * as tf_message from './tf-message.js';
|
||||||
import * as tf_user from './tf-user.js';
|
import * as tf_user from './tf-user.js';
|
||||||
import * as tf_compose from './tf-compose.js';
|
import * as tf_compose from './tf-compose.js';
|
||||||
import * as tf_news from './tf-news.js';
|
import * as tf_news from './tf-news.js';
|
||||||
import * as tf_profile from './tf-profile.js';
|
import * as tf_profile from './tf-profile.js';
|
||||||
|
import * as tf_reactions_modal from './tf-reactions-modal.js';
|
||||||
import * as tf_tab_mentions from './tf-tab-mentions.js';
|
import * as tf_tab_mentions from './tf-tab-mentions.js';
|
||||||
import * as tf_tab_news from './tf-tab-news.js';
|
import * as tf_tab_news from './tf-tab-news.js';
|
||||||
import * as tf_tab_news_feed from './tf-tab-news-feed.js';
|
import * as tf_tab_news_feed from './tf-tab-news-feed.js';
|
||||||
|
@ -52,20 +52,22 @@ class TfElement extends LitElement {
|
|||||||
self.broadcasts = value;
|
self.broadcasts = value;
|
||||||
} else if (name === 'connections') {
|
} else if (name === 'connections') {
|
||||||
self.connections = value;
|
self.connections = value;
|
||||||
|
} else if (name === 'identity') {
|
||||||
|
self.whoami = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.initial_load();
|
this.initial_load();
|
||||||
}
|
}
|
||||||
|
|
||||||
async initial_load() {
|
async initial_load() {
|
||||||
let whoami = await tfrpc.rpc.localStorageGet('whoami');
|
let whoami = await tfrpc.rpc.getActiveIdentity();
|
||||||
let ids = (await tfrpc.rpc.getIdentities()) || [];
|
let ids = (await tfrpc.rpc.getIdentities()) || [];
|
||||||
this.whoami = whoami ?? (ids.length ? ids[0] : undefined);
|
this.whoami = whoami ?? (ids.length ? ids[0] : undefined);
|
||||||
this.ids = ids;
|
this.ids = ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_hash(hash) {
|
set_hash(hash) {
|
||||||
this.hash = hash || '#';
|
this.hash = decodeURIComponent(hash || '#');
|
||||||
if (this.hash.startsWith('#q=')) {
|
if (this.hash.startsWith('#q=')) {
|
||||||
this.tab = 'search';
|
this.tab = 'search';
|
||||||
} else if (this.hash === '#connections') {
|
} else if (this.hash === '#connections') {
|
||||||
@ -193,29 +195,6 @@ class TfElement extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_id_picker() {
|
|
||||||
return html`
|
|
||||||
<div style="display: flex; gap: 8px">
|
|
||||||
<tf-id-picker
|
|
||||||
id="picker"
|
|
||||||
style="flex: 1 1 auto"
|
|
||||||
selected=${this.whoami}
|
|
||||||
.ids=${this.ids}
|
|
||||||
.users=${this.users}
|
|
||||||
@change=${this._handle_whoami_changed}
|
|
||||||
></tf-id-picker>
|
|
||||||
<button
|
|
||||||
class="w3-button w3-dark-grey w3-border"
|
|
||||||
style="flex: 0 0 auto"
|
|
||||||
@click=${this.create_identity}
|
|
||||||
id="create_identity"
|
|
||||||
>
|
|
||||||
Create Identity
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async load_recent_tags() {
|
async load_recent_tags() {
|
||||||
let start = new Date();
|
let start = new Date();
|
||||||
this.tags = await tfrpc.rpc.query(
|
this.tags = await tfrpc.rpc.query(
|
||||||
@ -255,7 +234,15 @@ class TfElement extends LitElement {
|
|||||||
by_count.push({count: v.of, id: id});
|
by_count.push({count: v.of, id: id});
|
||||||
}
|
}
|
||||||
console.log(by_count.sort((x, y) => y.count - x.count).slice(0, 20));
|
console.log(by_count.sort((x, y) => y.count - x.count).slice(0, 20));
|
||||||
|
let start_time = new Date();
|
||||||
users = await this.fetch_about(Object.keys(following).sort(), users);
|
users = await this.fetch_about(Object.keys(following).sort(), users);
|
||||||
|
console.log(
|
||||||
|
'about took',
|
||||||
|
(new Date() - start_time) / 1000.0,
|
||||||
|
'seconds for',
|
||||||
|
Object.keys(users).length,
|
||||||
|
'users'
|
||||||
|
);
|
||||||
this.following = Object.keys(following);
|
this.following = Object.keys(following);
|
||||||
this.users = users;
|
this.users = users;
|
||||||
await tags;
|
await tags;
|
||||||
@ -277,6 +264,7 @@ class TfElement extends LitElement {
|
|||||||
hash=${this.hash}
|
hash=${this.hash}
|
||||||
.unread=${this.unread}
|
.unread=${this.unread}
|
||||||
@refresh=${() => (this.unread = [])}
|
@refresh=${() => (this.unread = [])}
|
||||||
|
?loading=${this.loading}
|
||||||
></tf-tab-news>
|
></tf-tab-news>
|
||||||
`;
|
`;
|
||||||
} else if (this.tab === 'connections') {
|
} else if (this.tab === 'connections') {
|
||||||
@ -352,18 +340,20 @@ class TfElement extends LitElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let tabs = html`
|
let tabs = html`
|
||||||
<div class="w3-bar w3-black">
|
<div class="w3-bar w3-theme-l1">
|
||||||
${Object.entries(k_tabs).map(
|
${Object.entries(k_tabs).map(
|
||||||
([k, v]) => html`
|
([k, v]) => html`
|
||||||
<button
|
<button
|
||||||
title=${v}
|
title=${v}
|
||||||
class="w3-bar-item w3-padding-large w3-hover-gray tab ${self.tab ==
|
class="w3-bar-item w3-padding w3-hover-theme tab ${self.tab == v
|
||||||
v
|
? 'w3-theme-l2'
|
||||||
? 'w3-red'
|
: 'w3-theme-l1'}"
|
||||||
: 'w3-black'}"
|
|
||||||
@click=${() => self.set_tab(v)}
|
@click=${() => self.set_tab(v)}
|
||||||
>
|
>
|
||||||
${k}
|
${k}
|
||||||
|
<span class=${self.tab == v ? '' : 'w3-hide-small'}
|
||||||
|
>${v.charAt(0).toUpperCase() + v.substring(1)}</span
|
||||||
|
>
|
||||||
</button>
|
</button>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
@ -371,15 +361,27 @@ class TfElement extends LitElement {
|
|||||||
`;
|
`;
|
||||||
let contents = !this.loaded
|
let contents = !this.loaded
|
||||||
? this.loading
|
? this.loading
|
||||||
? html`<div>Loading...</div>`
|
? html`<div
|
||||||
|
class="w3-panel w3-theme-l5 w3-card-4 w3-padding-large w3-round-xlarge"
|
||||||
|
>
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
${this.render_tab()}`
|
||||||
: html`<div>Select or create an identity.</div>`
|
: html`<div>Select or create an identity.</div>`
|
||||||
: this.render_tab();
|
: this.render_tab();
|
||||||
return html`
|
return html`
|
||||||
${this.render_id_picker()} ${tabs}
|
<div
|
||||||
${this.tags.map(
|
style="width: 100vw; min-height: 100vh; height: 100%"
|
||||||
(x) => html`<tf-tag tag=${x.tag} count=${x.count}></tf-tag>`
|
class="w3-theme-dark"
|
||||||
)}
|
>
|
||||||
${contents}
|
${tabs}
|
||||||
|
<div style="padding: 8px">
|
||||||
|
${this.tags.map(
|
||||||
|
(x) => html`<tf-tag tag=${x.tag} count=${x.count}></tf-tag>`
|
||||||
|
)}
|
||||||
|
${contents}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {LitElement, html, unsafeHTML} from './lit-all.min.js';
|
import {LitElement, html, unsafeHTML, live} from './lit-all.min.js';
|
||||||
import * as tfutils from './tf-utils.js';
|
import * as tfutils from './tf-utils.js';
|
||||||
import * as tfrpc from '/static/tfrpc.js';
|
import * as tfrpc from '/static/tfrpc.js';
|
||||||
import {styles} from './tf-styles.js';
|
import {styles} from './tf-styles.js';
|
||||||
@ -13,6 +13,7 @@ class TfComposeElement extends LitElement {
|
|||||||
branch: {type: String},
|
branch: {type: String},
|
||||||
apps: {type: Object},
|
apps: {type: Object},
|
||||||
drafts: {type: Object},
|
drafts: {type: Object},
|
||||||
|
author: {type: String},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ class TfComposeElement extends LitElement {
|
|||||||
this.branch = undefined;
|
this.branch = undefined;
|
||||||
this.apps = undefined;
|
this.apps = undefined;
|
||||||
this.drafts = {};
|
this.drafts = {};
|
||||||
|
this.author = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_text(text) {
|
process_text(text) {
|
||||||
@ -64,7 +66,7 @@ class TfComposeElement extends LitElement {
|
|||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
if (updated) {
|
if (updated) {
|
||||||
this.requestUpdate();
|
setTimeout(() => this.notify(draft), 0);
|
||||||
}
|
}
|
||||||
return tfutils.markdown(text);
|
return tfutils.markdown(text);
|
||||||
}
|
}
|
||||||
@ -72,14 +74,12 @@ class TfComposeElement extends LitElement {
|
|||||||
input(event) {
|
input(event) {
|
||||||
let edit = this.renderRoot.getElementById('edit');
|
let edit = this.renderRoot.getElementById('edit');
|
||||||
let preview = this.renderRoot.getElementById('preview');
|
let preview = this.renderRoot.getElementById('preview');
|
||||||
preview.innerHTML = this.process_text(edit.value);
|
preview.innerHTML = this.process_text(edit.innerText);
|
||||||
let content_warning = this.renderRoot.getElementById('content_warning');
|
let content_warning = this.renderRoot.getElementById('content_warning');
|
||||||
let content_warning_preview = this.renderRoot.getElementById(
|
let draft = this.get_draft();
|
||||||
'content_warning_preview'
|
draft.text = edit.innerText;
|
||||||
);
|
draft.content_warning = content_warning?.value;
|
||||||
if (content_warning && content_warning_preview) {
|
setTimeout(() => this.notify(draft), 0);
|
||||||
content_warning_preview.innerText = content_warning.value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notify(draft) {
|
notify(draft) {
|
||||||
@ -95,14 +95,6 @@ class TfComposeElement extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
change() {
|
|
||||||
let draft = this.get_draft();
|
|
||||||
draft.text = this.renderRoot.getElementById('edit')?.value;
|
|
||||||
draft.content_warning =
|
|
||||||
this.renderRoot.getElementById('content_warning')?.value;
|
|
||||||
this.notify(draft);
|
|
||||||
}
|
|
||||||
|
|
||||||
convert_to_format(buffer, type, mime_type) {
|
convert_to_format(buffer, type, mime_type) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
let img = new Image();
|
let img = new Image();
|
||||||
@ -169,8 +161,7 @@ class TfComposeElement extends LitElement {
|
|||||||
size: buffer.length ?? buffer.byteLength,
|
size: buffer.length ?? buffer.byteLength,
|
||||||
};
|
};
|
||||||
let edit = self.renderRoot.getElementById('edit');
|
let edit = self.renderRoot.getElementById('edit');
|
||||||
edit.value += `\n![${name}](${id})`;
|
edit.innerText += `\n![${name}](${id})`;
|
||||||
self.change();
|
|
||||||
self.input();
|
self.input();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(e?.message);
|
alert(e?.message);
|
||||||
@ -189,6 +180,13 @@ class TfComposeElement extends LitElement {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
document.execCommand(
|
||||||
|
'insertText',
|
||||||
|
false,
|
||||||
|
event.clipboardData.getData('text/plain')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
@ -197,7 +195,7 @@ class TfComposeElement extends LitElement {
|
|||||||
let edit = this.renderRoot.getElementById('edit');
|
let edit = this.renderRoot.getElementById('edit');
|
||||||
let message = {
|
let message = {
|
||||||
type: 'post',
|
type: 'post',
|
||||||
text: edit.value,
|
text: edit.innerText,
|
||||||
};
|
};
|
||||||
if (this.root || this.branch) {
|
if (this.root || this.branch) {
|
||||||
message.root = this.root;
|
message.root = this.root;
|
||||||
@ -224,29 +222,19 @@ class TfComposeElement extends LitElement {
|
|||||||
console.log('encrypted as', message);
|
console.log('encrypted as', message);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await tfrpc.rpc.appendMessage(this.whoami, message).then(function () {
|
await tfrpc.rpc.appendMessage(this.whoami, message);
|
||||||
edit.value = '';
|
self.notify(undefined);
|
||||||
self.change();
|
|
||||||
self.notify(undefined);
|
|
||||||
self.requestUpdate();
|
|
||||||
});
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error.message);
|
alert(error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
discard() {
|
discard() {
|
||||||
let edit = this.renderRoot.getElementById('edit');
|
|
||||||
edit.value = '';
|
|
||||||
this.change();
|
|
||||||
let preview = this.renderRoot.getElementById('preview');
|
|
||||||
preview.innerHTML = '';
|
|
||||||
this.notify(undefined);
|
this.notify(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
attach() {
|
attach() {
|
||||||
let self = this;
|
let self = this;
|
||||||
let edit = this.renderRoot.getElementById('edit');
|
|
||||||
let input = document.createElement('input');
|
let input = document.createElement('input');
|
||||||
input.type = 'file';
|
input.type = 'file';
|
||||||
input.onchange = function (event) {
|
input.onchange = function (event) {
|
||||||
@ -262,9 +250,9 @@ class TfComposeElement extends LitElement {
|
|||||||
try {
|
try {
|
||||||
let rows = await tfrpc.rpc.query(
|
let rows = await tfrpc.rpc.query(
|
||||||
`
|
`
|
||||||
SELECT json(messages.content) FROM messages_fts(?)
|
SELECT json(messages.content) AS content FROM messages_fts(?)
|
||||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||||
WHERE messages.content LIKE ?
|
WHERE json(messages.content) LIKE ?
|
||||||
ORDER BY timestamp DESC LIMIT 10
|
ORDER BY timestamp DESC LIMIT 10
|
||||||
`,
|
`,
|
||||||
['"' + text.replace('"', '""') + '"', `%![%${text}%](%)%`]
|
['"' + text.replace('"', '""') + '"', `%![%${text}%](%)%`]
|
||||||
@ -284,22 +272,39 @@ class TfComposeElement extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
|
let values = Object.entries(this.users).map((x) => ({
|
||||||
|
key: x[1].name ?? x[0],
|
||||||
|
value: x[0],
|
||||||
|
}));
|
||||||
|
if (this.author) {
|
||||||
|
values = [].concat(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
key: this.users[this.author]?.name,
|
||||||
|
value: this.author,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
values
|
||||||
|
);
|
||||||
|
}
|
||||||
let tribute = new Tribute({
|
let tribute = new Tribute({
|
||||||
|
iframe: this.shadowRoot,
|
||||||
collection: [
|
collection: [
|
||||||
{
|
{
|
||||||
values: Object.entries(this.users).map((x) => ({
|
values: values,
|
||||||
key: x[1].name,
|
|
||||||
value: x[0],
|
|
||||||
})),
|
|
||||||
selectTemplate: function (item) {
|
selectTemplate: function (item) {
|
||||||
return `[@${item.original.key}](${item.original.value})`;
|
return item
|
||||||
|
? `[@${item.original.key}](${item.original.value})`
|
||||||
|
: undefined;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
trigger: '&',
|
trigger: '&',
|
||||||
values: this.autocomplete,
|
values: this.autocomplete,
|
||||||
selectTemplate: function (item) {
|
selectTemplate: function (item) {
|
||||||
return `![${item.original.key}](${item.original.value})`;
|
return item
|
||||||
|
? `![${item.original.key}](${item.original.value})`
|
||||||
|
: undefined;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -310,14 +315,15 @@ class TfComposeElement extends LitElement {
|
|||||||
updated() {
|
updated() {
|
||||||
super.updated();
|
super.updated();
|
||||||
let edit = this.renderRoot.getElementById('edit');
|
let edit = this.renderRoot.getElementById('edit');
|
||||||
if (this.last_updated_text !== edit.value) {
|
if (this.last_updated_text !== edit.innerText) {
|
||||||
let preview = this.renderRoot.getElementById('preview');
|
let preview = this.renderRoot.getElementById('preview');
|
||||||
preview.innerHTML = this.process_text(edit.value);
|
preview.innerHTML = this.process_text(edit.innerText);
|
||||||
this.last_updated_text = edit.value;
|
this.last_updated_text = edit.innerText;
|
||||||
}
|
}
|
||||||
let encrypt = this.renderRoot.getElementById('encrypt_to');
|
let encrypt = this.renderRoot.getElementById('encrypt_to');
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
let tribute = new Tribute({
|
let tribute = new Tribute({
|
||||||
|
iframe: this.shadowRoot,
|
||||||
values: Object.entries(this.users).map((x) => ({
|
values: Object.entries(this.users).map((x) => ({
|
||||||
key: x[1].name,
|
key: x[1].name,
|
||||||
value: x[0],
|
value: x[0],
|
||||||
@ -333,8 +339,7 @@ class TfComposeElement extends LitElement {
|
|||||||
remove_mention(id) {
|
remove_mention(id) {
|
||||||
let draft = this.get_draft();
|
let draft = this.get_draft();
|
||||||
delete draft.mentions[id];
|
delete draft.mentions[id];
|
||||||
this.notify(draft);
|
setTimeout(() => this.notify(), 0);
|
||||||
this.requestUpdate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render_mention(mention) {
|
render_mention(mention) {
|
||||||
@ -342,7 +347,7 @@ class TfComposeElement extends LitElement {
|
|||||||
return html` <div style="display: flex; flex-direction: row">
|
return html` <div style="display: flex; flex-direction: row">
|
||||||
<div style="align-self: center; margin: 0.5em">
|
<div style="align-self: center; margin: 0.5em">
|
||||||
<button
|
<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
title="Remove ${mention.name} mention"
|
title="Remove ${mention.name} mention"
|
||||||
@click=${() => self.remove_mention(mention.link)}
|
@click=${() => self.remove_mention(mention.link)}
|
||||||
>
|
>
|
||||||
@ -396,16 +401,16 @@ class TfComposeElement extends LitElement {
|
|||||||
if (this.apps) {
|
if (this.apps) {
|
||||||
return html`
|
return html`
|
||||||
<div class="w3-card-4 w3-margin w3-padding">
|
<div class="w3-card-4 w3-margin w3-padding">
|
||||||
<select id="select" class="w3-select w3-dark-grey">
|
<select id="select" class="w3-select w3-theme-d1">
|
||||||
${Object.keys(self.apps).map(
|
${Object.keys(self.apps).map(
|
||||||
(app) => html`<option value=${app}>${app}</option>`
|
(app) => html`<option value=${app}>${app}</option>`
|
||||||
)}
|
)}
|
||||||
</select>
|
</select>
|
||||||
<button class="w3-button w3-dark-grey" @click=${attach_selected_app}>
|
<button class="w3-button w3-theme-d1" @click=${attach_selected_app}>
|
||||||
Attach
|
Attach
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => (this.apps = null)}
|
@click=${() => (this.apps = null)}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
@ -421,12 +426,12 @@ class TfComposeElement extends LitElement {
|
|||||||
self.apps = await tfrpc.rpc.apps();
|
self.apps = await tfrpc.rpc.apps();
|
||||||
}
|
}
|
||||||
if (!this.apps) {
|
if (!this.apps) {
|
||||||
return html`<button class="w3-button w3-dark-grey" @click=${attach_app}>
|
return html`<button class="w3-button w3-theme-d1" @click=${attach_app}>
|
||||||
Attach App
|
Attach App
|
||||||
</button>`;
|
</button>`;
|
||||||
} else {
|
} else {
|
||||||
return html`<button
|
return html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => (this.apps = null)}
|
@click=${() => (this.apps = null)}
|
||||||
>
|
>
|
||||||
Discard App
|
Discard App
|
||||||
@ -448,15 +453,15 @@ class TfComposeElement extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div class="w3-container w3-padding">
|
<div class="w3-container w3-padding">
|
||||||
<p>
|
<p>
|
||||||
<input type="checkbox" class="w3-check w3-dark-grey" id="cw" @change=${() => self.set_content_warning(undefined)} checked="checked"></input>
|
<input type="checkbox" class="w3-check w3-theme-d1" id="cw" @change=${() => self.set_content_warning(undefined)} checked="checked"></input>
|
||||||
<label for="cw">CW</label>
|
<label for="cw">CW</label>
|
||||||
</p>
|
</p>
|
||||||
<input type="text" class="w3-input w3-border w3-dark-grey" id="content_warning" placeholder="Enter a content warning here." @input=${this.input} @change=${this.change} value=${draft.content_warning}></input>
|
<input type="text" class="w3-input w3-border w3-theme-d1" id="content_warning" placeholder="Enter a content warning here." @input=${self.input} value=${draft.content_warning}></input>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
return html`
|
return html`
|
||||||
<input type="checkbox" class="w3-check w3-dark-grey" id="cw" @change=${() => self.set_content_warning('')}></input>
|
<input type="checkbox" class="w3-check w3-theme-d1" id="cw" @change=${() => self.set_content_warning('')}></input>
|
||||||
<label for="cw">CW</label>
|
<label for="cw">CW</label>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -486,14 +491,14 @@ class TfComposeElement extends LitElement {
|
|||||||
<div style="display: flex; flex-direction: row; width: 100%">
|
<div style="display: flex; flex-direction: row; width: 100%">
|
||||||
<label for="encrypt_to">🔐 To:</label>
|
<label for="encrypt_to">🔐 To:</label>
|
||||||
<input type="text" id="encrypt_to" style="display: flex; flex: 1 1" @input=${this.update_encrypt}></input>
|
<input type="text" id="encrypt_to" style="display: flex; flex: 1 1" @input=${this.update_encrypt}></input>
|
||||||
<button class="w3-button w3-dark-grey" @click=${() => this.set_encrypt(undefined)}>🚮</button>
|
<button class="w3-button w3-theme-d1" @click=${() => this.set_encrypt(undefined)}>🚮</button>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
${draft.encrypt_to.map(
|
${draft.encrypt_to.map(
|
||||||
(x) => html`
|
(x) => html`
|
||||||
<li>
|
<li>
|
||||||
<tf-user id=${x} .users=${this.users}></tf-user>
|
<tf-user id=${x} .users=${this.users}></tf-user>
|
||||||
<input type="button" class="w3-button w3-dark-grey" value="🚮" @click=${() => this.set_encrypt(draft.encrypt_to.filter((id) => id != x))}></input>
|
<input type="button" class="w3-button w3-theme-d1" value="🚮" @click=${() => this.set_encrypt(draft.encrypt_to.filter((id) => id != x))}></input>
|
||||||
</li>`
|
</li>`
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
@ -512,7 +517,7 @@ class TfComposeElement extends LitElement {
|
|||||||
let draft = self.get_draft();
|
let draft = self.get_draft();
|
||||||
let content_warning =
|
let content_warning =
|
||||||
draft.content_warning !== undefined
|
draft.content_warning !== undefined
|
||||||
? html`<div class="w3-panel w3-round-xlarge w3-blue">
|
? html`<div class="w3-panel w3-round-xlarge w3-theme-d2">
|
||||||
<p id="content_warning_preview">${draft.content_warning}</p>
|
<p id="content_warning_preview">${draft.content_warning}</p>
|
||||||
</div>`
|
</div>`
|
||||||
: undefined;
|
: undefined;
|
||||||
@ -520,34 +525,31 @@ class TfComposeElement extends LitElement {
|
|||||||
draft.encrypt_to !== undefined
|
draft.encrypt_to !== undefined
|
||||||
? undefined
|
? undefined
|
||||||
: html`<button
|
: html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => this.set_encrypt([])}
|
@click=${() => this.set_encrypt([])}
|
||||||
>
|
>
|
||||||
🔐
|
🔐
|
||||||
</button>`;
|
</button>`;
|
||||||
let result = html`
|
let result = html`
|
||||||
<div
|
<div
|
||||||
class="w3-card-4 w3-blue-grey w3-padding"
|
class="w3-card-4 w3-theme-d4 w3-padding-small"
|
||||||
style="box-sizing: border-box"
|
style="box-sizing: border-box"
|
||||||
>
|
>
|
||||||
${this.render_encrypt()}
|
${this.render_encrypt()}
|
||||||
<div style="display: flex; flex-direction: row; width: 100%; gap: 4px">
|
<div class="w3-container w3-padding-small">
|
||||||
<div style="flex: 1 0 50%">
|
<div class="w3-half">
|
||||||
<p>
|
<span
|
||||||
<textarea
|
class="w3-input w3-theme-d1 w3-border"
|
||||||
class="w3-input w3-dark-grey w3-border"
|
style="resize: vertical; width: 100%; overflow: hidden; white-space: pre-wrap"
|
||||||
style="resize: vertical"
|
placeholder="Write a post here."
|
||||||
placeholder="Write a post here."
|
id="edit"
|
||||||
id="edit"
|
@input=${this.input}
|
||||||
@input=${this.input}
|
@paste=${this.paste}
|
||||||
@change=${this.change}
|
contenteditable="plaintext-only"
|
||||||
@paste=${this.paste}
|
.innerText=${live(draft.text ?? '')}
|
||||||
>
|
></span>
|
||||||
${draft.text}</textarea
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="flex: 1 0 50%">
|
<div class="w3-half w3-padding">
|
||||||
${content_warning}
|
${content_warning}
|
||||||
<div id="preview"></div>
|
<div id="preview"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -556,18 +558,14 @@ ${draft.text}</textarea
|
|||||||
self.render_mention(x)
|
self.render_mention(x)
|
||||||
)}
|
)}
|
||||||
${this.render_attach_app()} ${this.render_content_warning()}
|
${this.render_attach_app()} ${this.render_content_warning()}
|
||||||
<button
|
<button class="w3-button w3-theme-d1" id="submit" @click=${this.submit}>
|
||||||
class="w3-button w3-dark-grey"
|
|
||||||
id="submit"
|
|
||||||
@click=${this.submit}
|
|
||||||
>
|
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
<button class="w3-button w3-dark-grey" @click=${this.attach}>
|
<button class="w3-button w3-theme-d1" @click=${this.attach}>
|
||||||
Attach
|
Attach
|
||||||
</button>
|
</button>
|
||||||
${this.render_attach_app_button()} ${encrypt}
|
${this.render_attach_app_button()} ${encrypt}
|
||||||
<button class="w3-button w3-dark-grey" @click=${this.discard}>
|
<button class="w3-button w3-theme-d1" @click=${this.discard}>
|
||||||
Discard
|
Discard
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
import {LitElement, html} from './lit-all.min.js';
|
|
||||||
import * as tfrpc from '/static/tfrpc.js';
|
|
||||||
import {styles} from './tf-styles.js';
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Provide a list of IDs, and this lets the user pick one.
|
|
||||||
*/
|
|
||||||
class TfIdentityPickerElement extends LitElement {
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
ids: {type: Array},
|
|
||||||
selected: {type: String},
|
|
||||||
users: {type: Object},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = styles;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.ids = [];
|
|
||||||
this.users = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
changed(event) {
|
|
||||||
this.selected = event.srcElement.value;
|
|
||||||
this.dispatchEvent(
|
|
||||||
new Event('change', {
|
|
||||||
srcElement: this,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return html`
|
|
||||||
<select
|
|
||||||
class="w3-select w3-dark-grey w3-padding w3-border"
|
|
||||||
@change=${this.changed}
|
|
||||||
style="max-width: 100%; overflow: hidden"
|
|
||||||
>
|
|
||||||
${(this.ids ?? []).map(
|
|
||||||
(id) =>
|
|
||||||
html`<option ?selected=${id == this.selected} value=${id}>
|
|
||||||
${this.users[id]?.name
|
|
||||||
? this.users[id]?.name + ' - '
|
|
||||||
: undefined}<small>${id}</small>
|
|
||||||
</option>`
|
|
||||||
)}
|
|
||||||
</select>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define('tf-id-picker', TfIdentityPickerElement);
|
|
@ -1,4 +1,4 @@
|
|||||||
import {LitElement, html, unsafeHTML} from './lit-all.min.js';
|
import {LitElement, html, render, unsafeHTML} from './lit-all.min.js';
|
||||||
import * as tfrpc from '/static/tfrpc.js';
|
import * as tfrpc from '/static/tfrpc.js';
|
||||||
import * as tfutils from './tf-utils.js';
|
import * as tfutils from './tf-utils.js';
|
||||||
import * as emojis from './emojis.js';
|
import * as emojis from './emojis.js';
|
||||||
@ -54,6 +54,12 @@ class TfMessageElement extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
show_reactions() {
|
||||||
|
let modal = document.getElementById('reactions_modal');
|
||||||
|
modal.users = this.users;
|
||||||
|
modal.votes = this.message?.votes || [];
|
||||||
|
}
|
||||||
|
|
||||||
render_votes() {
|
render_votes() {
|
||||||
function normalize_expression(expression) {
|
function normalize_expression(expression) {
|
||||||
if (expression === 'Like' || !expression) {
|
if (expression === 'Like' || !expression) {
|
||||||
@ -66,19 +72,26 @@ class TfMessageElement extends LitElement {
|
|||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return html`<div>
|
if (this.message?.votes?.length) {
|
||||||
${(this.message.votes || []).map(
|
return html` <div class="w3-container">
|
||||||
(vote) => html`
|
<div
|
||||||
<span
|
class="w3-button w3-bar w3-padding-small"
|
||||||
title="${this.users[vote.author]?.name ?? vote.author} ${new Date(
|
@click=${this.show_reactions}
|
||||||
vote.timestamp
|
>
|
||||||
)}"
|
${(this.message.votes || []).map(
|
||||||
>
|
(vote) => html`
|
||||||
${normalize_expression(vote.content.vote.expression)}
|
<span
|
||||||
</span>
|
class="w3-bar-item w3-padding-small"
|
||||||
`
|
title="${this.users[vote.author]?.name ??
|
||||||
)}
|
vote.author} ${new Date(vote.timestamp)}"
|
||||||
</div>`;
|
>
|
||||||
|
${normalize_expression(vote.content.vote.expression)}
|
||||||
|
</span>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_raw() {
|
render_raw() {
|
||||||
@ -125,7 +138,7 @@ class TfMessageElement extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
react(event) {
|
react(event) {
|
||||||
emojis.picker((x) => this.vote(x));
|
emojis.picker((x) => this.vote(x), null, this.whoami);
|
||||||
}
|
}
|
||||||
|
|
||||||
show_image(link) {
|
show_image(link) {
|
||||||
@ -164,7 +177,7 @@ class TfMessageElement extends LitElement {
|
|||||||
event.srcElement.classList.contains('img_caption')
|
event.srcElement.classList.contains('img_caption')
|
||||||
) {
|
) {
|
||||||
let next = event.srcElement.nextSibling;
|
let next = event.srcElement.nextSibling;
|
||||||
if (next.style.display == 'block') {
|
if (next.style.display != 'none') {
|
||||||
next.style.display = 'none';
|
next.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
next.style.display = 'block';
|
next.style.display = 'block';
|
||||||
@ -239,9 +252,7 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
if (mentions.length) {
|
if (mentions.length) {
|
||||||
let self = this;
|
let self = this;
|
||||||
return html`
|
return html`
|
||||||
<fieldset
|
<fieldset style="padding: 0.5em; border: 1px solid black">
|
||||||
style="background-color: rgba(0, 0, 0, 0.1); padding: 0.5em; border: 1px solid black"
|
|
||||||
>
|
|
||||||
<legend>Mentions</legend>
|
<legend>Mentions</legend>
|
||||||
${mentions.map((x) => self.render_mention(x))}
|
${mentions.map((x) => self.render_mention(x))}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@ -282,14 +293,14 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
if (this.message.child_messages?.length) {
|
if (this.message.child_messages?.length) {
|
||||||
if (!this.expanded[this.message.id]) {
|
if (!this.expanded[this.message.id]) {
|
||||||
return html`<button
|
return html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => self.set_expanded(true)}
|
@click=${() => self.set_expanded(true)}
|
||||||
>
|
>
|
||||||
+ ${this.total_child_messages(this.message) + ' More'}
|
+ ${this.total_child_messages(this.message) + ' More'}
|
||||||
</button>`;
|
</button>`;
|
||||||
} else {
|
} else {
|
||||||
return html`<button
|
return html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => self.set_expanded(false)}
|
@click=${() => self.set_expanded(false)}
|
||||||
>
|
>
|
||||||
Collapse</button
|
Collapse</button
|
||||||
@ -331,20 +342,23 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
if (this.message?.decrypted?.type == 'post') {
|
if (this.message?.decrypted?.type == 'post') {
|
||||||
content = this.message.decrypted;
|
content = this.message.decrypted;
|
||||||
}
|
}
|
||||||
|
let class_background = this.message?.decrypted
|
||||||
|
? 'w3-pale-red'
|
||||||
|
: 'w3-theme-d4';
|
||||||
let self = this;
|
let self = this;
|
||||||
let raw_button;
|
let raw_button;
|
||||||
switch (this.format) {
|
switch (this.format) {
|
||||||
case 'raw':
|
case 'raw':
|
||||||
if (content?.type == 'post' || content?.type == 'blog') {
|
if (content?.type == 'post' || content?.type == 'blog') {
|
||||||
raw_button = html`<button
|
raw_button = html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => (self.format = 'md')}
|
@click=${() => (self.format = 'md')}
|
||||||
>
|
>
|
||||||
Markdown
|
Markdown
|
||||||
</button>`;
|
</button>`;
|
||||||
} else {
|
} else {
|
||||||
raw_button = html`<button
|
raw_button = html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => (self.format = 'message')}
|
@click=${() => (self.format = 'message')}
|
||||||
>
|
>
|
||||||
Message
|
Message
|
||||||
@ -353,7 +367,7 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
break;
|
break;
|
||||||
case 'md':
|
case 'md':
|
||||||
raw_button = html`<button
|
raw_button = html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => (self.format = 'message')}
|
@click=${() => (self.format = 'message')}
|
||||||
>
|
>
|
||||||
Message
|
Message
|
||||||
@ -361,7 +375,7 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
break;
|
break;
|
||||||
case 'decrypted':
|
case 'decrypted':
|
||||||
raw_button = html`<button
|
raw_button = html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => (self.format = 'raw')}
|
@click=${() => (self.format = 'raw')}
|
||||||
>
|
>
|
||||||
Raw
|
Raw
|
||||||
@ -370,14 +384,14 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
default:
|
default:
|
||||||
if (this.message.decrypted) {
|
if (this.message.decrypted) {
|
||||||
raw_button = html`<button
|
raw_button = html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => (self.format = 'decrypted')}
|
@click=${() => (self.format = 'decrypted')}
|
||||||
>
|
>
|
||||||
Decrypted
|
Decrypted
|
||||||
</button>`;
|
</button>`;
|
||||||
} else {
|
} else {
|
||||||
raw_button = html`<button
|
raw_button = html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => (self.format = 'raw')}
|
@click=${() => (self.format = 'raw')}
|
||||||
>
|
>
|
||||||
Raw
|
Raw
|
||||||
@ -389,8 +403,8 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
let body;
|
let body;
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
class="w3-card-4"
|
class="w3-card-4 w3-theme-d4 w3-border-theme"
|
||||||
style="background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; display: inline-block; overflow-wrap: anywhere"
|
style="margin-top: 8px; padding: 16px; display: inline-block; overflow-wrap: anywhere"
|
||||||
>
|
>
|
||||||
<tf-user id=${self.message.author} .users=${self.users}></tf-user>
|
<tf-user id=${self.message.author} .users=${self.users}></tf-user>
|
||||||
<span style="padding-right: 8px"
|
<span style="padding-right: 8px"
|
||||||
@ -400,13 +414,24 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
>
|
>
|
||||||
${raw_button} ${self.format == 'raw' ? self.render_raw() : inner}
|
${raw_button} ${self.format == 'raw' ? self.render_raw() : inner}
|
||||||
${self.render_votes()}
|
${self.render_votes()}
|
||||||
|
${(self.message.child_messages || []).map(
|
||||||
|
(x) => html`
|
||||||
|
<tf-message
|
||||||
|
.message=${x}
|
||||||
|
whoami=${self.whoami}
|
||||||
|
.users=${self.users}
|
||||||
|
.drafts=${self.drafts}
|
||||||
|
.expanded=${self.expanded}
|
||||||
|
></tf-message>
|
||||||
|
`
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
if (this.message?.type === 'contact_group') {
|
if (this.message?.type === 'contact_group') {
|
||||||
return html` <div
|
return html` <div
|
||||||
class="w3-card-4"
|
class="w3-card-4 w3-theme-d4 w3-border-theme"
|
||||||
style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
|
style="margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
|
||||||
>
|
>
|
||||||
${this.message.messages.map(
|
${this.message.messages.map(
|
||||||
(x) =>
|
(x) =>
|
||||||
@ -421,8 +446,8 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
</div>`;
|
</div>`;
|
||||||
} else if (this.message.placeholder) {
|
} else if (this.message.placeholder) {
|
||||||
return html` <div
|
return html` <div
|
||||||
class="w3-card-4"
|
class="w3-card-4 w3-theme-d4 w3-border-theme"
|
||||||
style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
|
style="margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
|
||||||
>
|
>
|
||||||
<a target="_top" href=${'#' + this.message.id}>${this.message.id}</a>
|
<a target="_top" href=${'#' + this.message.id}>${this.message.id}</a>
|
||||||
(placeholder)
|
(placeholder)
|
||||||
@ -498,13 +523,11 @@ ${JSON.stringify(mention, null, 2)}</pre
|
|||||||
branch=${this.message.id}
|
branch=${this.message.id}
|
||||||
.drafts=${this.drafts}
|
.drafts=${this.drafts}
|
||||||
@tf-discard=${this.discard_reply}
|
@tf-discard=${this.discard_reply}
|
||||||
|
author=${this.message.author}
|
||||||
></tf-compose>
|
></tf-compose>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<button
|
<button class="w3-button w3-theme-d1" @click=${this.show_reply}>
|
||||||
class="w3-button w3-dark-grey"
|
|
||||||
@click=${this.show_reply}
|
|
||||||
>
|
|
||||||
Reply
|
Reply
|
||||||
</button>
|
</button>
|
||||||
`;
|
`;
|
||||||
@ -533,7 +556,7 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
}
|
}
|
||||||
let content_warning = html`
|
let content_warning = html`
|
||||||
<div
|
<div
|
||||||
class="w3-panel w3-round-xlarge w3-blue"
|
class="w3-panel w3-round-xlarge w3-theme-l4"
|
||||||
style="cursor: pointer"
|
style="cursor: pointer"
|
||||||
@click=${(x) => this.toggle_expanded(':cw')}
|
@click=${(x) => this.toggle_expanded(':cw')}
|
||||||
>
|
>
|
||||||
@ -553,9 +576,6 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
let is_encrypted = this.message?.decrypted
|
let is_encrypted = this.message?.decrypted
|
||||||
? html`<span style="align-self: center">🔓</span>`
|
? html`<span style="align-self: center">🔓</span>`
|
||||||
: undefined;
|
: undefined;
|
||||||
let style_background = this.message?.decrypted
|
|
||||||
? 'rgba(255, 0, 0, 0.2)'
|
|
||||||
: 'rgba(255, 255, 255, 0.1)';
|
|
||||||
return html`
|
return html`
|
||||||
<style>
|
<style>
|
||||||
code {
|
code {
|
||||||
@ -572,8 +592,8 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div
|
<div
|
||||||
class="w3-card-4"
|
class="w3-card-4 ${class_background} w3-border-theme"
|
||||||
style="border: 1px solid black; background-color: ${style_background}; margin-top: 8px; padding: 16px"
|
style="margin-top: 8px; padding: 16px"
|
||||||
>
|
>
|
||||||
<div style="display: flex; flex-direction: row">
|
<div style="display: flex; flex-direction: row">
|
||||||
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
||||||
@ -588,7 +608,7 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
${payload} ${this.render_votes()}
|
${payload} ${this.render_votes()}
|
||||||
<p>
|
<p>
|
||||||
${reply}
|
${reply}
|
||||||
<button class="w3-button w3-dark-grey" @click=${this.react}>
|
<button class="w3-button w3-theme-d1" @click=${this.react}>
|
||||||
React
|
React
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
@ -599,9 +619,6 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
let is_encrypted = this.message?.decrypted
|
let is_encrypted = this.message?.decrypted
|
||||||
? html`<span style="align-self: center">🔓</span>`
|
? html`<span style="align-self: center">🔓</span>`
|
||||||
: undefined;
|
: undefined;
|
||||||
let style_background = this.message?.decrypted
|
|
||||||
? 'rgba(255, 0, 0, 0.2)'
|
|
||||||
: 'rgba(255, 255, 255, 0.1)';
|
|
||||||
return html`
|
return html`
|
||||||
<style>
|
<style>
|
||||||
code {
|
code {
|
||||||
@ -618,8 +635,8 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div
|
<div
|
||||||
class="w3-card-4"
|
class="w3-card-4 ${class_background} w3-border-theme"
|
||||||
style="border: 1px solid black; background-color: ${style_background}; margin-top: 8px; padding: 16px"
|
style="margin-top: 8px; padding: 16px"
|
||||||
>
|
>
|
||||||
<div style="display: flex; flex-direction: row">
|
<div style="display: flex; flex-direction: row">
|
||||||
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
||||||
@ -633,7 +650,7 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
</div>
|
</div>
|
||||||
${content.text} ${this.render_votes()}
|
${content.text} ${this.render_votes()}
|
||||||
<p>
|
<p>
|
||||||
<button class="w3-button w3-dark-grey" @click=${this.react}>
|
<button class="w3-button w3-theme-d1" @click=${this.react}>
|
||||||
React
|
React
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
@ -685,13 +702,11 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
branch=${this.message.id}
|
branch=${this.message.id}
|
||||||
.drafts=${this.drafts}
|
.drafts=${this.drafts}
|
||||||
@tf-discard=${this.discard_reply}
|
@tf-discard=${this.discard_reply}
|
||||||
|
author=${this.message.author}
|
||||||
></tf-compose>
|
></tf-compose>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<button
|
<button class="w3-button w3-theme-d1" @click=${this.show_reply}>
|
||||||
class="w3-button w3-dark-grey"
|
|
||||||
@click=${this.show_reply}
|
|
||||||
>
|
|
||||||
Reply
|
Reply
|
||||||
</button>
|
</button>
|
||||||
`;
|
`;
|
||||||
@ -711,8 +726,8 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div
|
<div
|
||||||
class="w3-card-4"
|
class="w3-card-4 w3-theme-d4 w3-border-theme"
|
||||||
style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px"
|
style="margin-top: 8px; padding: 16px"
|
||||||
>
|
>
|
||||||
<div style="display: flex; flex-direction: row">
|
<div style="display: flex; flex-direction: row">
|
||||||
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
||||||
@ -728,7 +743,7 @@ ${JSON.stringify(content, null, 2)}</pre
|
|||||||
${this.render_mentions()}
|
${this.render_mentions()}
|
||||||
<div>
|
<div>
|
||||||
${reply}
|
${reply}
|
||||||
<button class="w3-button w3-dark-grey" @click=${this.react}>
|
<button class="w3-button w3-theme-d1" @click=${this.react}>
|
||||||
React
|
React
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -188,6 +188,10 @@ class TfProfileElement extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copy_id() {
|
||||||
|
navigator.clipboard.writeText(this.id);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (
|
if (
|
||||||
this.id == this.whoami &&
|
this.id == this.whoami &&
|
||||||
@ -215,49 +219,49 @@ class TfProfileElement extends LitElement {
|
|||||||
let server_follow;
|
let server_follow;
|
||||||
if (this.server_follows_me === true) {
|
if (this.server_follows_me === true) {
|
||||||
server_follow = html`<button
|
server_follow = html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => this.server_follow_me(false)}
|
@click=${() => this.server_follow_me(false)}
|
||||||
>
|
>
|
||||||
Server, Stop Following Me
|
Server, Stop Following Me
|
||||||
</button>`;
|
</button>`;
|
||||||
} else if (this.server_follows_me === false) {
|
} else if (this.server_follows_me === false) {
|
||||||
server_follow = html`<button
|
server_follow = html`<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => this.server_follow_me(true)}
|
@click=${() => this.server_follow_me(true)}
|
||||||
>
|
>
|
||||||
Server, Follow Me
|
Server, Follow Me
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
edit = html`
|
edit = html`
|
||||||
<button class="w3-button w3-dark-grey" @click=${this.save_edits}>
|
<button class="w3-button w3-theme-d1" @click=${this.save_edits}>
|
||||||
Save Profile
|
Save Profile
|
||||||
</button>
|
</button>
|
||||||
<button class="w3-button w3-dark-grey" @click=${this.discard_edits}>
|
<button class="w3-button w3-theme-d1" @click=${this.discard_edits}>
|
||||||
Discard
|
Discard
|
||||||
</button>
|
</button>
|
||||||
${server_follow}
|
${server_follow}
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
edit = html`<button class="w3-button w3-dark-grey" @click=${this.edit}>
|
edit = html`<button class="w3-button w3-theme-d1" @click=${this.edit}>
|
||||||
Edit Profile
|
Edit Profile
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.id !== this.whoami && this.following !== undefined) {
|
if (this.id !== this.whoami && this.following !== undefined) {
|
||||||
follow = this.following
|
follow = this.following
|
||||||
? html`<button class="w3-button w3-dark-grey" @click=${this.unfollow}>
|
? html`<button class="w3-button w3-theme-d1" @click=${this.unfollow}>
|
||||||
Unfollow
|
Unfollow
|
||||||
</button>`
|
</button>`
|
||||||
: html`<button class="w3-button w3-dark-grey" @click=${this.follow}>
|
: html`<button class="w3-button w3-theme-d1" @click=${this.follow}>
|
||||||
Follow
|
Follow
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
if (this.id !== this.whoami && this.blocking !== undefined) {
|
if (this.id !== this.whoami && this.blocking !== undefined) {
|
||||||
block = this.blocking
|
block = this.blocking
|
||||||
? html`<button class="w3-button w3-dark-grey" @click=${this.unblock}>
|
? html`<button class="w3-button w3-theme-d1" @click=${this.unblock}>
|
||||||
Unblock
|
Unblock
|
||||||
</button>`
|
</button>`
|
||||||
: html`<button class="w3-button w3-dark-grey" @click=${this.block}>
|
: html`<button class="w3-button w3-theme-d1" @click=${this.block}>
|
||||||
Block
|
Block
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
@ -267,16 +271,16 @@ class TfProfileElement extends LitElement {
|
|||||||
<div class="w3-container">
|
<div class="w3-container">
|
||||||
<div>
|
<div>
|
||||||
<label for="name">Name:</label>
|
<label for="name">Name:</label>
|
||||||
<input class="w3-input w3-dark-grey" type="text" id="name" value=${this.editing.name} @input=${(event) => (this.editing = Object.assign({}, this.editing, {name: event.srcElement.value}))}></input>
|
<input class="w3-input w3-theme-d1" type="text" id="name" value=${this.editing.name} @input=${(event) => (this.editing = Object.assign({}, this.editing, {name: event.srcElement.value}))}></input>
|
||||||
</div>
|
</div>
|
||||||
<div><label for="description">Description:</label></div>
|
<div><label for="description">Description:</label></div>
|
||||||
<textarea class="w3-input w3-dark-grey" style="resize: vertical" rows="8" id="description" @input=${(event) => (this.editing = Object.assign({}, this.editing, {description: event.srcElement.value}))}>${this.editing.description}</textarea>
|
<textarea class="w3-input w3-theme-d1" style="resize: vertical" rows="8" id="description" @input=${(event) => (this.editing = Object.assign({}, this.editing, {description: event.srcElement.value}))}>${this.editing.description}</textarea>
|
||||||
<div>
|
<div>
|
||||||
<label for="public_web_hosting">Public Web Hosting:</label>
|
<label for="public_web_hosting">Public Web Hosting:</label>
|
||||||
<input class="w3-check w3-dark-grey" type="checkbox" id="public_web_hosting" ?checked=${this.editing.publicWebHosting} @input=${(event) => (self.editing = Object.assign({}, self.editing, {publicWebHosting: event.srcElement.checked}))}></input>
|
<input class="w3-check w3-theme-d1" type="checkbox" id="public_web_hosting" ?checked=${this.editing.publicWebHosting} @input=${(event) => (self.editing = Object.assign({}, self.editing, {publicWebHosting: event.srcElement.checked}))}></input>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button class="w3-button w3-dark-grey" @click=${this.attach_image}>Attach Image</button>
|
<button class="w3-button w3-theme-d1" @click=${this.attach_image}>Attach Image</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`
|
||||||
@ -285,8 +289,10 @@ class TfProfileElement extends LitElement {
|
|||||||
typeof profile.image == 'string' ? profile.image : profile.image?.link;
|
typeof profile.image == 'string' ? profile.image : profile.image?.link;
|
||||||
image = this.editing?.image ?? image;
|
image = this.editing?.image ?? image;
|
||||||
let description = this.editing?.description ?? profile.description;
|
let description = this.editing?.description ?? profile.description;
|
||||||
return html`<div style="border: 2px solid black; background-color: rgba(255, 255, 255, 0.2); padding: 16px">
|
return html`<div class="w3-container" style="box-sizing: border-box; border: 2px solid black; background-color: rgba(255, 255, 255, 0.2)">
|
||||||
<tf-user id=${this.id} .users=${this.users}></tf-user> (${tfutils.human_readable_size(this.size)})
|
<p><tf-user id=${this.id} .users=${this.users}></tf-user> (${tfutils.human_readable_size(this.size)})
|
||||||
|
<input type="text" class="w3-input w3-border w3-theme-d1" readonly value=${this.id}></input>
|
||||||
|
<button class="w3-button w3-theme-d1 w3-ripple" @click=${this.copy_id}>Copy</button>
|
||||||
<div style="display: flex; flex-direction: row; gap: 1em">
|
<div style="display: flex; flex-direction: row; gap: 1em">
|
||||||
${edit_profile}
|
${edit_profile}
|
||||||
<div style="flex: 1 0 50%">
|
<div style="flex: 1 0 50%">
|
||||||
@ -300,11 +306,11 @@ class TfProfileElement extends LitElement {
|
|||||||
Blocking ${profile.blocking} identities.
|
Blocking ${profile.blocking} identities.
|
||||||
Blocked by ${profile.blocked} identities.
|
Blocked by ${profile.blocked} identities.
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<p>
|
||||||
${edit}
|
${edit}
|
||||||
${follow}
|
${follow}
|
||||||
${block}
|
${block}
|
||||||
</div>
|
</p>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
72
apps/ssb/tf-reactions-modal.js
Normal file
72
apps/ssb/tf-reactions-modal.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import {LitElement, html, unsafeHTML} from './lit-all.min.js';
|
||||||
|
import {styles} from './tf-styles.js';
|
||||||
|
|
||||||
|
class TfReactionsModalElement extends LitElement {
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
users: {type: Object},
|
||||||
|
votes: {type: Array},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = styles;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.votes = [];
|
||||||
|
this.users = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.votes = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let self = this;
|
||||||
|
return this.votes?.length
|
||||||
|
? html` <div
|
||||||
|
class="w3-modal w3-animate-opacity"
|
||||||
|
style="display: block; box-sizing: border-box"
|
||||||
|
@click=${this.clear}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="w3-modal-content w3-card-4 w3-theme-d1"
|
||||||
|
onclick="event.stopPropagation()"
|
||||||
|
>
|
||||||
|
<div class="w3-container w3-padding">
|
||||||
|
<header class="w3-container">
|
||||||
|
<h2>Reactions</h2>
|
||||||
|
<span class="w3-button w3-display-topright" @click=${this.clear}
|
||||||
|
>×</span
|
||||||
|
>
|
||||||
|
</header>
|
||||||
|
<ul class="w3-theme-dark w3-container w3-ul">
|
||||||
|
${this.votes.map(
|
||||||
|
(x) => html`
|
||||||
|
<li class="w3-bar">
|
||||||
|
<span class="w3-bar-item"
|
||||||
|
>${x?.content?.vote?.expression}</span
|
||||||
|
>
|
||||||
|
<tf-user
|
||||||
|
class="w3-bar-item"
|
||||||
|
id=${x.author}
|
||||||
|
.users=${this.users}
|
||||||
|
></tf-user>
|
||||||
|
<span class="w3-bar-item w3-right"
|
||||||
|
>${new Date(x?.timestamp).toLocaleString()}</span
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
<footer class="w3-container w3-padding">
|
||||||
|
<button class="w3-button" @click=${this.clear}>Close</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
: undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('tf-reactions-modal', TfReactionsModalElement);
|
File diff suppressed because it is too large
Load Diff
@ -7,35 +7,52 @@ class TfTabConnectionsElement extends LitElement {
|
|||||||
return {
|
return {
|
||||||
broadcasts: {type: Array},
|
broadcasts: {type: Array},
|
||||||
identities: {type: Array},
|
identities: {type: Array},
|
||||||
|
my_identities: {type: Array},
|
||||||
connections: {type: Array},
|
connections: {type: Array},
|
||||||
stored_connections: {type: Array},
|
stored_connections: {type: Array},
|
||||||
users: {type: Object},
|
users: {type: Object},
|
||||||
|
server_identity: {type: String},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = styles;
|
static styles = styles;
|
||||||
|
|
||||||
|
static k_broadcast_emojis = {
|
||||||
|
discovery: '🏓',
|
||||||
|
room: '🚪',
|
||||||
|
peer_exchange: '🕸',
|
||||||
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
let self = this;
|
let self = this;
|
||||||
this.broadcasts = [];
|
this.broadcasts = [];
|
||||||
this.identities = [];
|
this.identities = [];
|
||||||
|
this.my_identities = [];
|
||||||
this.connections = [];
|
this.connections = [];
|
||||||
this.stored_connections = [];
|
this.stored_connections = [];
|
||||||
this.users = {};
|
this.users = {};
|
||||||
|
tfrpc.rpc.getIdentities().then(function (identities) {
|
||||||
|
self.my_identities = identities || [];
|
||||||
|
});
|
||||||
tfrpc.rpc.getAllIdentities().then(function (identities) {
|
tfrpc.rpc.getAllIdentities().then(function (identities) {
|
||||||
self.identities = identities || [];
|
self.identities = identities || [];
|
||||||
});
|
});
|
||||||
tfrpc.rpc.getStoredConnections().then(function (connections) {
|
tfrpc.rpc.getStoredConnections().then(function (connections) {
|
||||||
self.stored_connections = connections || [];
|
self.stored_connections = connections || [];
|
||||||
});
|
});
|
||||||
|
tfrpc.rpc.getServerIdentity().then(function (identity) {
|
||||||
|
self.server_identity = identity;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render_connection_summary(connection) {
|
render_connection_summary(connection) {
|
||||||
if (connection.address && connection.port) {
|
if (connection.address && connection.port) {
|
||||||
return html`(<small>${connection.address}:${connection.port}</small>)`;
|
return html`<div>
|
||||||
|
<small>${connection.address}:${connection.port}</small>
|
||||||
|
</div>`;
|
||||||
} else if (connection.tunnel) {
|
} else if (connection.tunnel) {
|
||||||
return html`(room peer)`;
|
return html`<div>room peer</div>`;
|
||||||
} else {
|
} else {
|
||||||
return JSON.stringify(connection);
|
return JSON.stringify(connection);
|
||||||
}
|
}
|
||||||
@ -61,7 +78,7 @@ class TfTabConnectionsElement extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => self._tunnel(connection.tunnel.id, connection.pubkey)}
|
@click=${() => self._tunnel(connection.tunnel.id, connection.pubkey)}
|
||||||
>
|
>
|
||||||
Connect
|
Connect
|
||||||
@ -73,15 +90,18 @@ class TfTabConnectionsElement extends LitElement {
|
|||||||
|
|
||||||
render_broadcast(connection) {
|
render_broadcast(connection) {
|
||||||
return html`
|
return html`
|
||||||
<li>
|
<li class="w3-bar" style="overflow: hidden; overflow-wrap: nowrap">
|
||||||
<button
|
<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-bar-item w3-button w3-theme-d1"
|
||||||
@click=${() => tfrpc.rpc.connect(connection)}
|
@click=${() => tfrpc.rpc.connect(connection)}
|
||||||
>
|
>
|
||||||
Connect
|
Connect
|
||||||
</button>
|
</button>
|
||||||
<tf-user id=${connection.pubkey} .users=${this.users}></tf-user>
|
<div class="w3-bar-item">
|
||||||
${this.render_connection_summary(connection)}
|
${TfTabConnectionsElement.k_broadcast_emojis[connection.origin]}
|
||||||
|
<tf-user id=${connection.pubkey} .users=${this.users}></tf-user>
|
||||||
|
${this.render_connection_summary(connection)}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -92,17 +112,44 @@ class TfTabConnectionsElement extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render_connection(connection) {
|
render_connection(connection) {
|
||||||
|
let requests = Object.values(
|
||||||
|
connection.requests.reduce(function (accumulator, value) {
|
||||||
|
let key = `${value.name}:${Math.sign(value.request_number)}`;
|
||||||
|
if (!accumulator[key]) {
|
||||||
|
accumulator[key] = Object.assign({count: 0}, value);
|
||||||
|
}
|
||||||
|
accumulator[key].count++;
|
||||||
|
return accumulator;
|
||||||
|
}, {})
|
||||||
|
);
|
||||||
return html`
|
return html`
|
||||||
<button
|
<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() => tfrpc.rpc.closeConnection(connection.id)}
|
@click=${() => tfrpc.rpc.closeConnection(connection.id)}
|
||||||
>
|
>
|
||||||
Close
|
Close
|
||||||
</button>
|
</button>
|
||||||
|
${connection.flags.one_shot ? '🔃' : undefined}
|
||||||
<tf-user id=${connection.id} .users=${this.users}></tf-user>
|
<tf-user id=${connection.id} .users=${this.users}></tf-user>
|
||||||
${connection.tunnel !== undefined
|
${connection.tunnel !== undefined
|
||||||
? '🚇'
|
? '🚇'
|
||||||
: html`(${connection.host}:${connection.port})`}
|
: html`(${connection.host}:${connection.port})`}
|
||||||
|
<div>
|
||||||
|
${requests.map(
|
||||||
|
(x) => html`
|
||||||
|
<span
|
||||||
|
class=${'w3-tag w3-small ' +
|
||||||
|
(x.active ? 'w3-theme-l3' : 'w3-theme-d3')}
|
||||||
|
>${x.request_number > 0 ? '🟩' : '🟥'} ${x.name}
|
||||||
|
<span
|
||||||
|
class="w3-badge w3-white"
|
||||||
|
style=${x.count > 1 ? undefined : 'display: none'}
|
||||||
|
>${x.count}</span
|
||||||
|
></span
|
||||||
|
>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
${this.connections
|
${this.connections
|
||||||
.filter((x) => x.tunnel === this.connections.indexOf(connection))
|
.filter((x) => x.tunnel === this.connections.indexOf(connection))
|
||||||
@ -112,59 +159,87 @@ class TfTabConnectionsElement extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
tfrpc.rpc.sync();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let self = this;
|
let self = this;
|
||||||
return html`
|
return html`
|
||||||
<div class="w3-container">
|
<div class="w3-container" style="box-sizing: border-box">
|
||||||
<h2>New Connection</h2>
|
|
||||||
<textarea class="w3-input w3-dark-grey" id="code"></textarea>
|
|
||||||
<button
|
<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-l3 w3-circle w3-ripple w3-large"
|
||||||
|
@click=${this.refresh}
|
||||||
|
>
|
||||||
|
🔃
|
||||||
|
</button>
|
||||||
|
<h2>New Connection</h2>
|
||||||
|
<textarea class="w3-input w3-theme-d1" id="code"></textarea>
|
||||||
|
<button
|
||||||
|
class="w3-button w3-theme-d1"
|
||||||
@click=${() =>
|
@click=${() =>
|
||||||
tfrpc.rpc.connect(self.renderRoot.getElementById('code').value)}
|
tfrpc.rpc.connect(self.renderRoot.getElementById('code').value)}
|
||||||
>
|
>
|
||||||
Connect
|
Connect
|
||||||
</button>
|
</button>
|
||||||
<h2>Broadcasts</h2>
|
<h2>Broadcasts</h2>
|
||||||
<ul>
|
<ul class="w3-ul w3-border">
|
||||||
${this.broadcasts
|
${this.broadcasts
|
||||||
.filter((x) => x.address)
|
.filter((x) => x.address)
|
||||||
.map((x) => self.render_broadcast(x))}
|
.map((x) => self.render_broadcast(x))}
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Connections</h2>
|
<h2>Connections</h2>
|
||||||
<ul>
|
<ul class="w3-ul w3-border">
|
||||||
${this.connections
|
${this.connections
|
||||||
.filter((x) => x.tunnel === undefined)
|
.filter((x) => x.tunnel === undefined)
|
||||||
.map((x) => html` <li>${this.render_connection(x)}</li> `)}
|
.map(
|
||||||
|
(x) => html`
|
||||||
|
<li class="w3-bar">${this.render_connection(x)}</li>
|
||||||
|
`
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Stored Connections (WIP)</h2>
|
<h2>Stored Connections</h2>
|
||||||
<ul>
|
<ul class="w3-ul w3-border">
|
||||||
${this.stored_connections.map(
|
${this.stored_connections.map(
|
||||||
(x) => html`
|
(x) => html`
|
||||||
<li>
|
<li class="w3-bar">
|
||||||
<button
|
<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-bar-item w3-button w3-theme-d1"
|
||||||
@click=${() => self.forget_stored_connection(x)}
|
@click=${() => self.forget_stored_connection(x)}
|
||||||
>
|
>
|
||||||
Forget
|
Forget
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-bar-item w3-button w3-theme-d1"
|
||||||
@click=${() => tfrpc.rpc.connect(x)}
|
@click=${() => tfrpc.rpc.connect(x)}
|
||||||
>
|
>
|
||||||
Connect
|
Connect
|
||||||
</button>
|
</button>
|
||||||
${x.address}:${x.port}
|
<div class="w3-bar-item">
|
||||||
<tf-user id=${x.pubkey} .users=${self.users}></tf-user>
|
<tf-user id=${x.pubkey} .users=${self.users}></tf-user>
|
||||||
|
<div><small>${x.address}:${x.port}</small></div>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Local Accounts</h2>
|
<h2>Local Accounts</h2>
|
||||||
<ul>
|
<ul class="w3-ul w3-border">
|
||||||
${this.identities.map(
|
${this.identities.map(
|
||||||
(x) =>
|
(x) =>
|
||||||
html`<li><tf-user id=${x} .users=${this.users}></tf-user></li>`
|
html`<li class="w3-bar">
|
||||||
|
${x == this.server_identity
|
||||||
|
? html`<span class="w3-tag w3-medium w3-round w3-theme-l1"
|
||||||
|
>🖥 local server</span
|
||||||
|
>`
|
||||||
|
: undefined}
|
||||||
|
${this.my_identities.indexOf(x) != -1
|
||||||
|
? html`<span class="w3-tag w3-medium w3-round w3-theme-d1"
|
||||||
|
>😎 you</span
|
||||||
|
>`
|
||||||
|
: undefined}
|
||||||
|
<tf-user id=${x} .users=${this.users}></tf-user>
|
||||||
|
</li>`
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -187,7 +187,7 @@ class TfTabNewsFeedElement extends LitElement {
|
|||||||
if (!this.hash.startsWith('#@') && !this.hash.startsWith('#%')) {
|
if (!this.hash.startsWith('#@') && !this.hash.startsWith('#%')) {
|
||||||
more = html`
|
more = html`
|
||||||
<p>
|
<p>
|
||||||
<button class="w3-button w3-dark-grey" @click=${this.load_more}>
|
<button class="w3-button w3-theme-d1" @click=${this.load_more}>
|
||||||
Load More
|
Load More
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
|
@ -12,6 +12,7 @@ class TfTabNewsElement extends LitElement {
|
|||||||
following: {type: Array},
|
following: {type: Array},
|
||||||
drafts: {type: Object},
|
drafts: {type: Object},
|
||||||
expanded: {type: Object},
|
expanded: {type: Object},
|
||||||
|
loading: {type: Boolean},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,10 +85,7 @@ class TfTabNewsElement extends LitElement {
|
|||||||
} else {
|
} else {
|
||||||
delete this.drafts[id];
|
delete this.drafts[id];
|
||||||
}
|
}
|
||||||
/* Only trigger a re-render if we're creating a new draft or discarding an old one. */
|
this.drafts = Object.assign({}, this.drafts);
|
||||||
if ((previous !== undefined) != (event.detail.draft !== undefined)) {
|
|
||||||
this.drafts = Object.assign({}, this.drafts);
|
|
||||||
}
|
|
||||||
tfrpc.rpc.localStorageSet('drafts', JSON.stringify(this.drafts));
|
tfrpc.rpc.localStorageSet('drafts', JSON.stringify(this.drafts));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,17 +114,31 @@ class TfTabNewsElement extends LitElement {
|
|||||||
.users=${this.users}
|
.users=${this.users}
|
||||||
></tf-profile>`
|
></tf-profile>`
|
||||||
: undefined;
|
: undefined;
|
||||||
|
let edit_profile;
|
||||||
|
if (
|
||||||
|
!this.loading &&
|
||||||
|
this.users[this.whoami]?.name === undefined &&
|
||||||
|
this.hash.substring(1) != this.whoami
|
||||||
|
) {
|
||||||
|
edit_profile = html` <div
|
||||||
|
class="w3-panel w3-padding w3-round w3-card-4 w3-theme-l3"
|
||||||
|
>
|
||||||
|
ℹ️ Follow your identity link ☝️ above to edit your profile and set your
|
||||||
|
name.
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
return html`
|
return html`
|
||||||
<p class="w3-bar">
|
<p class="w3-bar">
|
||||||
<button
|
<button
|
||||||
class="w3-bar-item w3-button w3-dark-grey"
|
class="w3-bar-item w3-button w3-theme-d1"
|
||||||
@click=${this.show_more}
|
@click=${this.show_more}
|
||||||
>
|
>
|
||||||
${this.new_messages_text()}
|
${this.new_messages_text()}
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div class="w3-bar">
|
||||||
Welcome, <tf-user id=${this.whoami} .users=${this.users}></tf-user>!
|
Welcome, <tf-user id=${this.whoami} .users=${this.users}></tf-user>!
|
||||||
|
${edit_profile}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<tf-compose
|
<tf-compose
|
||||||
|
@ -110,14 +110,14 @@ class TfTabQueryElement extends LitElement {
|
|||||||
<textarea
|
<textarea
|
||||||
id="search"
|
id="search"
|
||||||
rows="8"
|
rows="8"
|
||||||
class="w3-input w3-dark-grey"
|
class="w3-input w3-theme-d1"
|
||||||
style="flex: 1; resize: vertical"
|
style="flex: 1; resize: vertical"
|
||||||
@keydown=${this.search_keydown}
|
@keydown=${this.search_keydown}
|
||||||
>
|
>
|
||||||
${this.query}</textarea
|
${this.query}</textarea
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="w3-button w3-dark-grey"
|
class="w3-button w3-theme-d1"
|
||||||
@click=${(event) =>
|
@click=${(event) =>
|
||||||
self.search(self.renderRoot.getElementById('search').value)}
|
self.search(self.renderRoot.getElementById('search').value)}
|
||||||
>
|
>
|
||||||
|
@ -5,6 +5,7 @@ import {styles} from './tf-styles.js';
|
|||||||
class TfTabSearchElement extends LitElement {
|
class TfTabSearchElement extends LitElement {
|
||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
|
drafts: {type: Object},
|
||||||
whoami: {type: String},
|
whoami: {type: String},
|
||||||
users: {type: Object},
|
users: {type: Object},
|
||||||
following: {type: Array},
|
following: {type: Array},
|
||||||
@ -22,6 +23,10 @@ class TfTabSearchElement extends LitElement {
|
|||||||
this.users = {};
|
this.users = {};
|
||||||
this.following = [];
|
this.following = [];
|
||||||
this.expanded = {};
|
this.expanded = {};
|
||||||
|
this.drafts = {};
|
||||||
|
tfrpc.rpc.localStorageGet('drafts').then(function (d) {
|
||||||
|
self.drafts = JSON.parse(d || '{}');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async search(query) {
|
async search(query) {
|
||||||
@ -70,6 +75,18 @@ class TfTabSearchElement extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
draft(event) {
|
||||||
|
let id = event.detail.id || '';
|
||||||
|
let previous = this.drafts[id];
|
||||||
|
if (event.detail.draft !== undefined) {
|
||||||
|
this.drafts[id] = event.detail.draft;
|
||||||
|
} else {
|
||||||
|
delete this.drafts[id];
|
||||||
|
}
|
||||||
|
this.drafts = Object.assign({}, this.drafts);
|
||||||
|
tfrpc.rpc.localStorageSet('drafts', JSON.stringify(this.drafts));
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.query !== this.last_query) {
|
if (this.query !== this.last_query) {
|
||||||
this.last_query = this.query;
|
this.last_query = this.query;
|
||||||
@ -78,10 +95,10 @@ class TfTabSearchElement extends LitElement {
|
|||||||
let self = this;
|
let self = this;
|
||||||
return html`
|
return html`
|
||||||
<div style="display: flex; flex-direction: row; gap: 4px">
|
<div style="display: flex; flex-direction: row; gap: 4px">
|
||||||
<input type="text" class="w3-input w3-dark-grey" id="search" value=${this.query} style="flex: 1" @keydown=${this.search_keydown}></input>
|
<input type="text" class="w3-input w3-theme-d1" id="search" value=${this.query} style="flex: 1" @keydown=${this.search_keydown}></input>
|
||||||
<button class="w3-button w3-dark-grey" @click=${(event) => self.search(self.renderRoot.getElementById('search').value)}>Search</button>
|
<button class="w3-button w3-theme-d1" @click=${(event) => self.search(self.renderRoot.getElementById('search').value)}>Search</button>
|
||||||
</div>
|
</div>
|
||||||
<tf-news id="news" whoami=${this.whoami} .messages=${this.messages} .users=${this.users} .expanded=${this.expanded} @tf-expand=${this.on_expand}></tf-news>
|
<tf-news id="news" whoami=${this.whoami} .messages=${this.messages} .users=${this.users} .expanded=${this.expanded} .drafts=${this.drafts} @tf-expand=${this.on_expand} @tf-draft=${this.draft}></tf-news>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,11 @@ class TfUserElement extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
let image = html`<span
|
||||||
|
class="w3-theme-light w3-circle"
|
||||||
|
style="display: inline-block; width: 2em; height: 2em; text-align: center; line-height: 2em"
|
||||||
|
>?</span
|
||||||
|
>`;
|
||||||
let name = this.users?.[this.id]?.name;
|
let name = this.users?.[this.id]?.name;
|
||||||
name =
|
name =
|
||||||
name !== undefined
|
name !== undefined
|
||||||
@ -26,21 +31,20 @@ class TfUserElement extends LitElement {
|
|||||||
: html`<a target="_top" href=${'#' + this.id}>${this.id}</a>`;
|
: html`<a target="_top" href=${'#' + this.id}>${this.id}</a>`;
|
||||||
|
|
||||||
if (this.users[this.id]) {
|
if (this.users[this.id]) {
|
||||||
let image = this.users[this.id].image;
|
let image_link = this.users[this.id].image;
|
||||||
image = typeof image == 'string' ? image : image?.link;
|
image_link =
|
||||||
return html` <div style="display: inline-block; font-weight: bold">
|
typeof image_link == 'string' ? image_link : image_link?.link;
|
||||||
<img
|
if (image_link !== undefined) {
|
||||||
style="width: 2em; height: 2em; vertical-align: middle; border-radius: 50%"
|
image = html`<img
|
||||||
?hidden=${image === undefined}
|
class="w3-circle"
|
||||||
src="${image ? '/' + image + '/view' : undefined}"
|
style="width: 2em; height: 2em; vertical-align: middle; object-fit: cover"
|
||||||
/>
|
src="/${image_link}/view"
|
||||||
${name}
|
/>`;
|
||||||
</div>`;
|
}
|
||||||
} else {
|
|
||||||
return html` <div style="display: inline-block; font-weight: bold">
|
|
||||||
${name}
|
|
||||||
</div>`;
|
|
||||||
}
|
}
|
||||||
|
return html` <div style="display: inline-block; font-weight: bold">
|
||||||
|
${image} ${name}
|
||||||
|
</div>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import * as linkify from './commonmark-linkify.js';
|
|
||||||
import * as hashtagify from './commonmark-hashtag.js';
|
import * as hashtagify from './commonmark-hashtag.js';
|
||||||
|
|
||||||
|
const k_code_classes = 'w3-theme-l4 w3-theme-border w3-round';
|
||||||
|
|
||||||
function image(node, entering) {
|
function image(node, entering) {
|
||||||
if (
|
if (
|
||||||
node.firstChild?.type === 'text' &&
|
node.firstChild?.type === 'text' &&
|
||||||
@ -61,13 +62,32 @@ function image(node, entering) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function code(node) {
|
||||||
|
let attrs = this.attrs(node);
|
||||||
|
attrs.push(['class', k_code_classes]);
|
||||||
|
this.tag('code', attrs);
|
||||||
|
this.out(node.literal);
|
||||||
|
this.tag('/code');
|
||||||
|
}
|
||||||
|
|
||||||
|
function attrs(node) {
|
||||||
|
let result = commonmark.HtmlRenderer.prototype.attrs.bind(this)(node);
|
||||||
|
if (node.type == 'block_quote') {
|
||||||
|
result.push(['class', 'w3-theme-d1']);
|
||||||
|
} else if (node.type == 'code_block') {
|
||||||
|
result.push(['class', k_code_classes]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
export function markdown(md) {
|
export function markdown(md) {
|
||||||
let reader = new commonmark.Parser({safe: true});
|
let reader = new commonmark.Parser({safe: true});
|
||||||
let writer = new commonmark.HtmlRenderer();
|
let writer = new commonmark.HtmlRenderer();
|
||||||
writer.image = image;
|
writer.image = image;
|
||||||
|
writer.code = code;
|
||||||
|
writer.attrs = attrs;
|
||||||
let parsed = reader.parse(md || '');
|
let parsed = reader.parse(md || '');
|
||||||
parsed = hashtagify.transform(parsed);
|
parsed = hashtagify.transform(parsed);
|
||||||
parsed = linkify.transform(parsed);
|
|
||||||
let walker = parsed.walker();
|
let walker = parsed.walker();
|
||||||
let event, node;
|
let event, node;
|
||||||
while ((event = walker.next())) {
|
while ((event = walker.next())) {
|
||||||
|
@ -482,16 +482,7 @@ class TributeRange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getDocument() {
|
getDocument() {
|
||||||
let iframe;
|
return document;
|
||||||
if (this.tribute.current.collection) {
|
|
||||||
iframe = this.tribute.current.collection.iframe;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!iframe) {
|
|
||||||
return document
|
|
||||||
}
|
|
||||||
|
|
||||||
return iframe.contentWindow.document
|
|
||||||
}
|
}
|
||||||
|
|
||||||
positionMenuAtCaret(scrollTo) {
|
positionMenuAtCaret(scrollTo) {
|
||||||
@ -653,8 +644,8 @@ class TributeRange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getWindowSelection() {
|
getWindowSelection() {
|
||||||
if (this.tribute.collection.iframe) {
|
if (this.tribute.collection[0].iframe?.getSelection) {
|
||||||
return this.tribute.collection.iframe.contentWindow.getSelection()
|
return this.tribute.collection[0].iframe.getSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
return window.getSelection()
|
return window.getSelection()
|
||||||
|
4
apps/test.json
Normal file
4
apps/test.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"type": "tildefriends-app",
|
||||||
|
"emoji": "📦"
|
||||||
|
}
|
3
apps/test/app.js
Normal file
3
apps/test/app.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
app.setDocument(
|
||||||
|
'<p style="color: #fff">Maybe one day this app will run tests, but for now there is nothing to see here.</p>'
|
||||||
|
);
|
1
apps/test/hello.txt
Normal file
1
apps/test/hello.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Hello, world!
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "👋",
|
"emoji": "👋",
|
||||||
"previous": "&zFISmRDAv+SXFonfZ9/sHNhrmMe+poTU22gwZzuSkT4=.sha256"
|
"previous": "&7gFmLW5zSMhmxWWY1+jeRcHdullgujSqGJg94lVgr1k=.sha256"
|
||||||
}
|
}
|
||||||
|
78
apps/welcome/appimage.svg
Normal file
78
apps/welcome/appimage.svg
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="48px" height="48px" id="svg3832" version="1.1" inkscape:version="0.47 r22583" sodipodi:docname="appimage-assistant_alt3.svg">
|
||||||
|
<defs id="defs3834">
|
||||||
|
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3308-4-6-931-761-0" id="linearGradient2975" gradientUnits="userSpaceOnUse" x1="24.3125" y1="22.96875" x2="24.3125" y2="41.03125"/>
|
||||||
|
<linearGradient id="linearGradient3308-4-6-931-761-0">
|
||||||
|
<stop id="stop2919-2" style="stop-color:#ffffff;stop-opacity:1" offset="0"/>
|
||||||
|
<stop id="stop2921-76" style="stop-color:#ffffff;stop-opacity:0" offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4222" id="linearGradient2979" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0,0.3704967,-0.3617496,0,33.508315,6.1670925)" x1="7.6485429" y1="26.437023" x2="41.861729" y2="26.437023"/>
|
||||||
|
<linearGradient id="linearGradient4222">
|
||||||
|
<stop id="stop4224" style="stop-color:#ffffff;stop-opacity:1" offset="0"/>
|
||||||
|
<stop id="stop4226" style="stop-color:#ffffff;stop-opacity:0" offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3308-4-6-931-761" id="linearGradient2982" gradientUnits="userSpaceOnUse" gradientTransform="translate(0,0.9999987)" x1="23.99999" y1="4.999989" x2="23.99999" y2="43"/>
|
||||||
|
<linearGradient id="linearGradient3308-4-6-931-761">
|
||||||
|
<stop id="stop2919" style="stop-color:#ffffff;stop-opacity:1" offset="0"/>
|
||||||
|
<stop id="stop2921" style="stop-color:#ffffff;stop-opacity:0" offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient inkscape:collect="always" xlink:href="#linearGradient3575" id="radialGradient2985" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0,1.0262008,-1.6561124,9.4072203e-4,-56.097482,-45.332325)" cx="48.42384" cy="-48.027504" fx="48.42384" fy="-48.027504" r="38.212933"/>
|
||||||
|
<linearGradient id="linearGradient3575">
|
||||||
|
<stop id="stop3577" style="stop-color:#fafafa;stop-opacity:1" offset="0"/>
|
||||||
|
<stop id="stop3579" style="stop-color:#e6e6e6;stop-opacity:1" offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient inkscape:collect="always" xlink:href="#linearGradient3993" id="radialGradient2990" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0,2.0478765,-2.7410544,-8.6412258e-8,47.161382,-8.837436)" cx="9.3330879" cy="8.4497671" fx="9.3330879" fy="8.4497671" r="19.99999"/>
|
||||||
|
<linearGradient id="linearGradient3993">
|
||||||
|
<stop offset="0" style="stop-color:#a3c0d0;stop-opacity:1" id="stop3995"/>
|
||||||
|
<stop offset="1" style="stop-color:#427da1;stop-opacity:1" id="stop4001"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2508" id="linearGradient2992" gradientUnits="userSpaceOnUse" gradientTransform="translate(0,0.9674382)" x1="14.048676" y1="44.137306" x2="14.048676" y2="4.0000005"/>
|
||||||
|
<linearGradient id="linearGradient2508">
|
||||||
|
<stop offset="0" style="stop-color:#2e4a5a;stop-opacity:1" id="stop2510"/>
|
||||||
|
<stop offset="1" style="stop-color:#6e8796;stop-opacity:1" id="stop2512"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient cx="4.9929786" cy="43.5" r="2.5" fx="4.9929786" fy="43.5" id="radialGradient2873-966-168" xlink:href="#linearGradient3688-166-749" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.003784,0,0,1.4,27.98813,-17.4)"/>
|
||||||
|
<linearGradient id="linearGradient3688-166-749">
|
||||||
|
<stop id="stop2883" style="stop-color:#181818;stop-opacity:1" offset="0"/>
|
||||||
|
<stop id="stop2885" style="stop-color:#181818;stop-opacity:0" offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient cx="4.9929786" cy="43.5" r="2.5" fx="4.9929786" fy="43.5" id="radialGradient2875-742-326" xlink:href="#linearGradient3688-464-309" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.003784,0,0,1.4,-20.01187,-104.4)"/>
|
||||||
|
<linearGradient id="linearGradient3688-464-309">
|
||||||
|
<stop id="stop2889" style="stop-color:#181818;stop-opacity:1" offset="0"/>
|
||||||
|
<stop id="stop2891" style="stop-color:#181818;stop-opacity:0" offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient x1="25.058096" y1="47.027729" x2="25.058096" y2="39.999443" id="linearGradient2877-634-617" xlink:href="#linearGradient3702-501-757" gradientUnits="userSpaceOnUse"/>
|
||||||
|
<linearGradient id="linearGradient3702-501-757">
|
||||||
|
<stop id="stop2895" style="stop-color:#181818;stop-opacity:0" offset="0"/>
|
||||||
|
<stop id="stop2897" style="stop-color:#181818;stop-opacity:1" offset="0.5"/>
|
||||||
|
<stop id="stop2899" style="stop-color:#181818;stop-opacity:0" offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="7" inkscape:cx="24" inkscape:cy="24" inkscape:current-layer="layer1" showgrid="true" inkscape:grid-bbox="true" inkscape:document-units="px" inkscape:window-width="603" inkscape:window-height="484" inkscape:window-x="417" inkscape:window-y="162" inkscape:window-maximized="0"/>
|
||||||
|
<metadata id="metadata3837">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||||
|
<dc:title/>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer">
|
||||||
|
<g style="display:inline" id="g2036" transform="matrix(1.1,0,0,0.4444449,-2.4000022,25.11107)">
|
||||||
|
<g style="opacity:0.4" id="g3712" transform="matrix(1.052632,0,0,1.285713,-1.263158,-13.42854)">
|
||||||
|
<rect style="fill:url(#radialGradient2873-966-168);fill-opacity:1;stroke:none" id="rect2801" y="40" x="38" height="7" width="5"/>
|
||||||
|
<rect style="fill:url(#radialGradient2875-742-326);fill-opacity:1;stroke:none" id="rect3696" transform="scale(-1,-1)" y="-47" x="-10" height="7" width="5"/>
|
||||||
|
<rect style="fill:url(#linearGradient2877-634-617);fill-opacity:1;stroke:none" id="rect3700" y="40" x="10" height="7.0000005" width="28"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<rect style="fill:url(#radialGradient2990);fill-opacity:1;stroke:url(#linearGradient2992);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" id="rect5505" y="5.4674392" x="4.5" ry="2.2322156" rx="2.2322156" height="39" width="39"/>
|
||||||
|
<path style="opacity:0.05;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00178742;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path4294-1" d="m 21,6.9687498 a 2.0165107,2.0165107 0 0 0 -2.03125,2.03125 l 0,3.9687502 -1.15625,0 a 2.0165107,2.0165107 0 0 0 -1.5,3.375 l 5.0625,5.75 c -0.06312,0.110777 -0.178724,0.246032 -0.21875,0.34375 -0.195898,0.478256 -0.25,0.83653 -0.25,1.21875 l 0,0.125 L 20.8125,23.6875 C 20.534322,23.409323 20.213169,23.162739 19.71875,22.96875 19.47154,22.87176 19.185456,22.791748 18.75,22.8125 c -0.435456,0.02075 -1.054055,0.210302 -1.46875,0.625 L 15.75,24.96875 c -0.414689,0.414689 -0.604245,1.033294 -0.625,1.46875 -0.02075,0.435456 0.05925,0.721537 0.15625,0.96875 C 15.475241,27.900677 15.721817,28.221821 16,28.5 l 0.09375,0.09375 -0.125,0 c -0.382218,0 -0.740493,0.0541 -1.21875,0.25 -0.239128,0.09795 -0.538285,0.214988 -0.84375,0.53125 -0.305465,0.316262 -0.625,0.914788 -0.625,1.53125 l 0,2.1875 c 0,0.616465 0.319536,1.214989 0.625,1.53125 0.305464,0.316261 0.604622,0.433301 0.84375,0.53125 0.478256,0.195898 0.83653,0.25 1.21875,0.25 l 0.125,0 L 16,35.5 c -0.278175,0.278176 -0.52476,0.599329 -0.71875,1.09375 -0.09699,0.24721 -0.177003,0.533292 -0.15625,0.96875 0.02075,0.435458 0.210304,1.054058 0.625,1.46875 l 1.53125,1.53125 c 0.414691,0.414697 1.033292,0.604245 1.46875,0.625 0.435458,0.02076 0.721537,-0.05926 0.96875,-0.15625 0.494425,-0.19399 0.81557,-0.440568 1.09375,-0.71875 l 0.09375,-0.09375 0,0.125 c 0,0.38222 0.0541,0.740495 0.25,1.21875 0.09795,0.239127 0.214989,0.538285 0.53125,0.84375 0.316261,0.305465 0.914783,0.625 1.53125,0.625 l 2.1875,0 c 0.616466,0 1.214989,-0.319534 1.53125,-0.625 0.316261,-0.305466 0.433302,-0.604622 0.53125,-0.84375 0.195896,-0.478255 0.25,-0.836532 0.25,-1.21875 l 0,-0.125 0.09375,0.09375 c 0.278176,0.278175 0.599329,0.52476 1.09375,0.71875 0.24721,0.09699 0.533292,0.177003 0.96875,0.15625 0.435458,-0.02075 1.054058,-0.210304 1.46875,-0.625 L 32.875,39.03125 C 33.289697,38.616559 33.479245,37.997958 33.5,37.5625 33.52076,37.127042 33.44074,36.840963 33.34375,36.59375 33.14976,36.099325 32.903182,35.77818 32.625,35.5 l -0.09375,-0.09375 0.125,0 c 0.38222,0 0.740494,-0.0541 1.21875,-0.25 0.239128,-0.09795 0.538286,-0.214988 0.84375,-0.53125 0.305464,-0.316262 0.625,-0.914787 0.625,-1.53125 l 0,-2.1875 c 0,-0.61646 -0.319535,-1.214987 -0.625,-1.53125 -0.305465,-0.316263 -0.604621,-0.433301 -0.84375,-0.53125 -0.478257,-0.195898 -0.836532,-0.25 -1.21875,-0.25 l -0.125,0 L 32.625,28.5 c 0.278177,-0.278177 0.52476,-0.599329 0.71875,-1.09375 C 33.44074,27.15904 33.520753,26.872957 33.5,26.4375 33.47925,26.002043 33.289697,25.383443 32.875,24.96875 L 31.34375,23.4375 c -0.414688,-0.414694 -1.03329,-0.604245 -1.46875,-0.625 -0.43546,-0.02076 -0.721537,0.05925 -0.96875,0.15625 -0.494426,0.193991 -0.815572,0.44057 -1.09375,0.71875 l -0.09375,0.09375 0,-0.125 c 0,-0.382218 -0.0541,-0.740493 -0.25,-1.21875 -0.09112,-0.22245 -0.228127,-0.500183 -0.5,-0.78125 l 4.71875,-5.3125 a 2.0165107,2.0165107 0 0 0 -1.5,-3.375 l -1.15625,0 0,-3.9687502 A 2.0165107,2.0165107 0 0 0 27,6.9687498 l -6,0 z M 24.3125,31.25 c 0.427097,0 0.75,0.322904 0.75,0.75 0,0.427096 -0.322903,0.75 -0.75,0.75 -0.427094,0 -0.75,-0.322906 -0.75,-0.75 0,-0.427094 0.322906,-0.75 0.75,-0.75 z"/>
|
||||||
|
<path style="opacity:0.05;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00178742;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path4294" d="m 20.90625,8.0312498 a 0.96385067,0.96385067 0 0 0 -0.875,0.96875 l 0,5.0312502 -2.21875,0 A 0.96385067,0.96385067 0 0 0 17.09375,15.625 l 5.78125,6.53125 c -0.158814,0.0616 -0.341836,0.0951 -0.4375,0.1875 -0.169161,0.163386 -0.252971,0.323419 -0.3125,0.46875 -0.119058,0.290663 -0.15625,0.566746 -0.15625,0.84375 l 0,1.65625 C 21.718163,25.40233 21.485871,25.509772 21.25,25.625 l -1.1875,-1.1875 c -0.199651,-0.19965 -0.421433,-0.352095 -0.71875,-0.46875 -0.148659,-0.05833 -0.329673,-0.104846 -0.5625,-0.09375 -0.232827,0.0111 -0.53583,0.09833 -0.75,0.3125 L 16.5,25.71875 c -0.214168,0.214168 -0.301403,0.517173 -0.3125,0.75 -0.0111,0.232827 0.03542,0.41384 0.09375,0.5625 0.116655,0.297321 0.269096,0.519099 0.46875,0.71875 l 1.1875,1.1875 c -0.115228,0.235871 -0.222668,0.468163 -0.3125,0.71875 l -1.65625,0 c -0.277003,0 -0.553087,0.03719 -0.84375,0.15625 -0.145332,0.05953 -0.305363,0.143338 -0.46875,0.3125 -0.163387,0.169162 -0.3125,0.46403 -0.3125,0.78125 l 0,2.1875 c 0,0.317221 0.149114,0.612089 0.3125,0.78125 0.163386,0.169161 0.323419,0.252971 0.46875,0.3125 0.290663,0.119058 0.566746,0.15625 0.84375,0.15625 l 1.65625,0 c 0.08983,0.250587 0.197272,0.482879 0.3125,0.71875 L 16.75,36.25 c -0.199649,0.19965 -0.352095,0.421432 -0.46875,0.71875 -0.05833,0.148659 -0.104846,0.329672 -0.09375,0.5625 0.0111,0.232828 0.09833,0.535831 0.3125,0.75 l 1.53125,1.53125 c 0.214168,0.214172 0.517172,0.301403 0.75,0.3125 0.232828,0.0111 0.41384,-0.03542 0.5625,-0.09375 0.29732,-0.116655 0.519098,-0.269096 0.71875,-0.46875 L 21.25,38.375 c 0.235871,0.115228 0.468164,0.222668 0.71875,0.3125 l 0,1.65625 c 0,0.277003 0.03719,0.553087 0.15625,0.84375 0.05953,0.145331 0.143339,0.305364 0.3125,0.46875 0.169161,0.163386 0.464028,0.3125 0.78125,0.3125 l 2.1875,0 c 0.317221,0 0.612089,-0.149113 0.78125,-0.3125 0.169161,-0.163387 0.252971,-0.323419 0.3125,-0.46875 0.119057,-0.290663 0.15625,-0.566748 0.15625,-0.84375 l 0,-1.65625 c 0.250586,-0.08983 0.482879,-0.197272 0.71875,-0.3125 l 1.1875,1.1875 c 0.19965,0.199649 0.421432,0.352095 0.71875,0.46875 0.148659,0.05833 0.329672,0.104846 0.5625,0.09375 0.232828,-0.0111 0.535831,-0.09833 0.75,-0.3125 L 32.125,38.28125 c 0.214172,-0.214168 0.301403,-0.517172 0.3125,-0.75 0.0111,-0.232828 -0.03542,-0.41384 -0.09375,-0.5625 C 32.227095,36.67143 32.074654,36.449652 31.875,36.25 L 30.6875,35.0625 C 30.802728,34.82663 30.910168,34.594337 31,34.34375 l 1.65625,0 c 0.277004,0 0.553087,-0.03719 0.84375,-0.15625 0.145332,-0.05953 0.305364,-0.143339 0.46875,-0.3125 0.163386,-0.169161 0.3125,-0.46403 0.3125,-0.78125 l 0,-2.1875 c 0,-0.317219 -0.149114,-0.612088 -0.3125,-0.78125 C 33.805364,29.955838 33.645332,29.872029 33.5,29.8125 33.209336,29.693442 32.933253,29.65625 32.65625,29.65625 l -1.65625,0 C 30.91017,29.405663 30.802728,29.17337 30.6875,28.9375 L 31.875,27.75 c 0.19965,-0.19965 0.352095,-0.421432 0.46875,-0.71875 0.05833,-0.148659 0.104846,-0.329672 0.09375,-0.5625 -0.0111,-0.232828 -0.09833,-0.535831 -0.3125,-0.75 L 30.59375,24.1875 c -0.214167,-0.21417 -0.517171,-0.301403 -0.75,-0.3125 -0.232829,-0.0111 -0.41384,0.03542 -0.5625,0.09375 -0.29732,0.116656 -0.519099,0.269097 -0.71875,0.46875 L 27.375,25.625 c -0.235871,-0.115228 -0.468163,-0.222668 -0.71875,-0.3125 l 0,-1.65625 c 0,-0.277003 -0.03719,-0.553087 -0.15625,-0.84375 -0.05953,-0.145332 -0.143338,-0.305363 -0.3125,-0.46875 -0.169162,-0.163387 -0.46403,-0.3125 -0.78125,-0.3125 l -0.15625,0 5.65625,-6.40625 A 0.96385067,0.96385067 0 0 0 30.1875,14.03125 l -2.21875,0 0,-5.0312502 A 0.96385067,0.96385067 0 0 0 27,8.0312498 l -6,0 a 0.96385067,0.96385067 0 0 0 -0.09375,0 z M 24.3125,30.1875 c 1.002113,0 1.8125,0.810388 1.8125,1.8125 0,1.002112 -0.810387,1.8125 -1.8125,1.8125 C 23.31039,33.8125 22.5,33.002111 22.5,32 c 0,-1.002111 0.81039,-1.8125 1.8125,-1.8125 z"/>
|
||||||
|
<path style="fill:url(#radialGradient2985);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00178742;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path2317" d="M 21,8.9999996 21,15 17.8125,15 24,22 30.1875,15 27,15 l 0,-6.0000004 -6,0 z M 23.21875,23 c -0.172892,0 -0.28125,0.294922 -0.28125,0.65625 l 0,2.28125 C 22.24145,26.095996 21.585954,26.379869 21,26.75 l -1.625,-1.625 c -0.255498,-0.255497 -0.533998,-0.372253 -0.65625,-0.25 l -1.53125,1.53125 c -0.122254,0.122254 -0.0055,0.400753 0.25,0.65625 l 1.625,1.625 c -0.37013,0.585953 -0.654003,1.24145 -0.8125,1.9375 l -2.28125,0 c -0.361328,0 -0.65625,0.108357 -0.65625,0.28125 l 0,2.1875 c 0,0.172892 0.294922,0.28125 0.65625,0.28125 l 2.28125,0 c 0.158497,0.69605 0.44237,1.351546 0.8125,1.9375 l -1.625,1.625 c -0.255497,0.255498 -0.372254,0.533997 -0.25,0.65625 l 1.53125,1.53125 c 0.122252,0.122254 0.400752,0.0055 0.65625,-0.25 L 21,37.25 c 0.585954,0.37013 1.24145,0.654002 1.9375,0.8125 l 0,2.28125 C 22.9375,40.705077 23.045858,41 23.21875,41 l 2.1875,0 c 0.172893,0 0.28125,-0.294924 0.28125,-0.65625 l 0,-2.28125 c 0.69605,-0.158498 1.351546,-0.44237 1.9375,-0.8125 l 1.625,1.625 c 0.255498,0.255497 0.533997,0.372254 0.65625,0.25 l 1.53125,-1.53125 c 0.122254,-0.122252 0.0055,-0.400752 -0.25,-0.65625 l -1.625,-1.625 c 0.370129,-0.585954 0.654003,-1.24145 0.8125,-1.9375 l 2.28125,0 c 0.361329,0 0.65625,-0.108358 0.65625,-0.28125 l 0,-2.1875 c 0,-0.172893 -0.294921,-0.28125 -0.65625,-0.28125 l -2.28125,0 c -0.158497,-0.69605 -0.442371,-1.351547 -0.8125,-1.9375 l 1.625,-1.625 c 0.255497,-0.255497 0.372254,-0.533997 0.25,-0.65625 L 29.90625,24.875 C 29.783997,24.752745 29.505498,24.8695 29.25,25.125 l -1.625,1.625 c -0.585954,-0.370131 -1.24145,-0.654004 -1.9375,-0.8125 l 0,-2.28125 C 25.6875,23.294922 25.579143,23 25.40625,23 l -2.1875,0 z m 1.09375,6.21875 c 1.528616,0 2.78125,1.252635 2.78125,2.78125 0,1.528615 -1.252634,2.78125 -2.78125,2.78125 -1.528614,0 -2.78125,-1.252635 -2.78125,-2.78125 0,-1.528615 1.252636,-2.78125 2.78125,-2.78125 z"/>
|
||||||
|
<rect style="opacity:0.4;fill:none;stroke:url(#linearGradient2982);stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" id="rect6741" y="6.4999886" x="5.4999981" ry="1.365193" rx="1.365193" height="37.000011" width="36.999985"/>
|
||||||
|
<path style="fill:none;stroke:url(#linearGradient2979);stroke-width:0.99829447;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" id="path2777" d="M 28.926376,15.466668 24,21.177578 18.963089,15.5 21.5,15.5 l 0,-6.0000004 5,0 0,6.0000004 2.426376,-0.03333 z"/>
|
||||||
|
<path style="fill:none;stroke:url(#linearGradient2975);stroke-width:1;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path4243" d="m 23.4375,23.46875 c -0.01166,0.05381 -0.03125,0.100205 -0.03125,0.1875 l 0,2.28125 a 0.48185467,0.48185467 0 0 1 -0.375,0.46875 c -0.638467,0.145384 -1.238423,0.407111 -1.78125,0.75 a 0.48185467,0.48185467 0 0 1 -0.59375,-0.0625 l -1.625,-1.625 C 18.9779,25.4154 18.9477,25.40242 18.90625,25.375 l -1.21875,1.21875 c 0.02742,0.04145 0.0404,0.07165 0.09375,0.125 l 1.625,1.625 a 0.48185467,0.48185467 0 0 1 0.0625,0.59375 c -0.342888,0.542826 -0.604615,1.142782 -0.75,1.78125 a 0.48185467,0.48185467 0 0 1 -0.46875,0.375 l -2.28125,0 c -0.08729,0 -0.133695,0.01959 -0.1875,0.03125 l 0,1.75 c 0.05381,0.01166 0.100205,0.03125 0.1875,0.03125 l 2.28125,0 a 0.48185467,0.48185467 0 0 1 0.46875,0.375 c 0.145385,0.638468 0.407112,1.238423 0.75,1.78125 a 0.48185467,0.48185467 0 0 1 -0.0625,0.59375 l -1.625,1.625 c -0.05335,0.05335 -0.06633,0.08355 -0.09375,0.125 l 1.21875,1.21875 c 0.04145,-0.02742 0.07165,-0.0404 0.125,-0.09375 l 1.625,-1.625 A 0.48185467,0.48185467 0 0 1 21.25,36.84375 c 0.542827,0.342888 1.142781,0.604614 1.78125,0.75 a 0.48185467,0.48185467 0 0 1 0.375,0.46875 l 0,2.28125 c 0,0.08729 0.01959,0.133695 0.03125,0.1875 l 1.75,0 c 0.01166,-0.0538 0.03125,-0.100206 0.03125,-0.1875 l 0,-2.28125 a 0.48185467,0.48185467 0 0 1 0.375,-0.46875 c 0.638469,-0.145386 1.238423,-0.407112 1.78125,-0.75 a 0.48185467,0.48185467 0 0 1 0.59375,0.0625 l 1.625,1.625 c 0.05335,0.05335 0.08355,0.06633 0.125,0.09375 l 1.21875,-1.21875 c -0.02742,-0.04145 -0.0404,-0.07165 -0.09375,-0.125 l -1.625,-1.625 a 0.48185467,0.48185467 0 0 1 -0.0625,-0.59375 c 0.342888,-0.542828 0.604615,-1.142783 0.75,-1.78125 a 0.48185467,0.48185467 0 0 1 0.46875,-0.375 l 2.28125,0 c 0.08729,0 0.133695,-0.01959 0.1875,-0.03125 l 0,-1.75 c -0.0538,-0.01166 -0.100204,-0.03125 -0.1875,-0.03125 l -2.28125,0 a 0.48185467,0.48185467 0 0 1 -0.46875,-0.375 c -0.145385,-0.638467 -0.407113,-1.238424 -0.75,-1.78125 a 0.48185467,0.48185467 0 0 1 0.0625,-0.59375 l 1.625,-1.625 c 0.05335,-0.05335 0.06633,-0.08355 0.09375,-0.125 L 29.71875,25.375 c -0.04145,0.02742 -0.07165,0.0404 -0.125,0.09375 l -1.625,1.625 a 0.48185467,0.48185467 0 0 1 -0.59375,0.0625 c -0.542827,-0.342889 -1.142783,-0.604616 -1.78125,-0.75 a 0.48185467,0.48185467 0 0 1 -0.375,-0.46875 l 0,-2.28125 c 0,-0.0873 -0.01959,-0.133695 -0.03125,-0.1875 l -1.75,0 z m 0.875,5.28125 c 1.791829,0 3.25,1.458172 3.25,3.25 0,1.791828 -1.458171,3.25 -3.25,3.25 -1.791827,0 -3.25,-1.458172 -3.25,-3.25 0,-1.791828 1.458173,-3.25 3.25,-3.25 z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 19 KiB |
75
apps/welcome/f-droid.svg
Normal file
75
apps/welcome/f-droid.svg
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="48" height="48" viewBox="0 0 48.000001 48.000001" id="svg4230" version="1.1" inkscape:version="0.91 r13725" sodipodi:docname="fdroid-logo.svg">
|
||||||
|
<defs id="defs4232">
|
||||||
|
<linearGradient inkscape:collect="always" id="linearGradient5212">
|
||||||
|
<stop style="stop-color:#ffffff;stop-opacity:0.09803922" offset="0" id="stop5214"/>
|
||||||
|
<stop style="stop-color:#ffffff;stop-opacity:0" offset="1" id="stop5216"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient inkscape:collect="always" xlink:href="#linearGradient5212" id="radialGradient5220" cx="-98.23381" cy="3.4695871" fx="-98.23381" fy="3.4695871" r="22.671185" gradientTransform="matrix(0,1.9747624,-2.117225,3.9784049e-8,8.677247,1199.588)" gradientUnits="userSpaceOnUse"/>
|
||||||
|
<filter inkscape:collect="always" style="color-interpolation-filters:sRGB" id="filter4175" x="-0.023846937" width="1.0476939" y="-0.02415504" height="1.0483101">
|
||||||
|
<feGaussianBlur inkscape:collect="always" stdDeviation="0.45053152" id="feGaussianBlur4177"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="11.313708" inkscape:cx="6.4184057" inkscape:cy="25.737489" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" units="px" inkscape:window-width="1920" inkscape:window-height="1009" inkscape:window-x="0" inkscape:window-y="34" inkscape:window-maximized="1" gridtolerance="10000"/>
|
||||||
|
<metadata id="metadata4235">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||||
|
<dc:title/>
|
||||||
|
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/"/>
|
||||||
|
</cc:Work>
|
||||||
|
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
|
||||||
|
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||||
|
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||||
|
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||||
|
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||||
|
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||||
|
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||||
|
</cc:License>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(0,-1004.3622)">
|
||||||
|
<path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#263238;fill-opacity:0.4;fill-rule:evenodd;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4175);color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 2.613462,1006.3488 a 1.250125,1.250125 0 0 0 -1.01172,2.0293 l 3.60351,4.6641 c -0.12699,0.3331 -0.20312,0.6915 -0.20312,1.0703 l 0,4 0,2.8652 0,0.1348 c 0,1.662 1.338,3 3,3 l 32,0 c 1.662,0 3,-1.338 3,-3 l 0,-4 0,-2.8652 0,-0.1348 c 0,-0.3803 -0.0771,-0.74 -0.20508,-1.0742 l 3.60156,-4.6602 a 1.250125,1.250125 0 0 0 -1.04882,-2.0273 1.250125,1.250125 0 0 0 -0.92969,0.498 l -3.43164,4.4414 c -0.31022,-0.1079 -0.63841,-0.1777 -0.98633,-0.1777 l -32,0 c -0.34857,0 -0.67757,0.069 -0.98828,0.1777 l -3.4336,-4.4414 a 1.250125,1.250125 0 0 0 -0.96679,-0.5 z m 5.38867,18.7637 c -0.20775,0 -0.40983,0.021 -0.60547,0.061 -1.36951,0.2761 -2.39453,1.4698 -2.39453,2.9101 l 0,0.029 0,19.7793 0,0.029 0,0.1914 c 0,1.662 1.338,3 3,3 l 32,0 c 1.662,0 3,-1.338 3,-3 l 0,-20 0,-0.029 c 0,-1.4403 -1.02502,-2.634 -2.39453,-2.9101 -0.19565,-0.039 -0.39772,-0.061 -0.60547,-0.061 l -32,0 z" id="path4192" inkscape:connector-curvature="0"/>
|
||||||
|
<g id="g5012">
|
||||||
|
<g id="g4179" transform="matrix(-1,0,0,1,47.999779,0)">
|
||||||
|
<path style="fill:#8ab000;fill-opacity:1;fill-rule:evenodd;stroke:#769616;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 2.5889342,1006.8622 4.25,5.5" id="path4181" inkscape:connector-curvature="0" sodipodi:nodetypes="cc"/>
|
||||||
|
<path sodipodi:nodetypes="cccccc" inkscape:connector-curvature="0" id="path4183" d="m 2.6113281,1005.6094 c -0.4534623,0.012 -0.7616975,0.189 -0.9807462,0.4486 2.0269314,2.4089 2.368401,2.7916 5.1354735,6.2214 1.0195329,1.319 2.0816026,0.6373 1.0620696,-0.6817 l -4.25,-5.5 c -0.2289894,-0.3056 -0.5850813,-0.478 -0.9667969,-0.4883 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:0.29803923;fill-rule:evenodd;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"/>
|
||||||
|
<path sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" id="path4185" d="m 1.6220992,1006.0705 c -0.1238933,0.1479 -0.561176,0.8046 -0.02249,1.5562 l 4.25,5.5 c 1.0195329,1.319 1.1498748,-0.6123 1.1498748,-0.6123 0,0 -3.7344514,-4.51 -5.3773848,-6.4439 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#263238;fill-opacity:0.2;fill-rule:evenodd;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"/>
|
||||||
|
<path sodipodi:nodetypes="cscccc" inkscape:connector-curvature="0" id="path4187" d="m 2.3378905,1005.8443 c -0.438175,0 -0.959862,0.1416 -0.8242183,0.7986 0.103561,0.5016 4.6608262,6.0744 4.6608262,6.0744 1.0195329,1.319 2.4934721,0.6763 1.4739391,-0.6425 l -4.234375,-5.4727 c -0.2602394,-0.29 -0.6085188,-0.7436 -1.076172,-0.7578 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#8ab000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"/>
|
||||||
|
</g>
|
||||||
|
<g id="g4955">
|
||||||
|
<path sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path4945" d="m 2.5889342,1006.8622 4.25,5.5" style="fill:#8ab000;fill-opacity:1;fill-rule:evenodd;stroke:#769616;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
|
||||||
|
<path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:0.29803923;fill-rule:evenodd;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 2.6113281,1005.6094 c -0.4534623,0.012 -0.7616975,0.189 -0.9807462,0.4486 2.0269314,2.4089 2.368401,2.7916 5.1354735,6.2214 1.0195329,1.319 2.0816026,0.6373 1.0620696,-0.6817 l -4.25,-5.5 c -0.2289894,-0.3056 -0.5850813,-0.478 -0.9667969,-0.4883 z" id="path4947" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccc"/>
|
||||||
|
<path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#263238;fill-opacity:0.2;fill-rule:evenodd;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 1.6220992,1006.0705 c -0.1238933,0.1479 -0.561176,0.8046 -0.02249,1.5562 l 4.25,5.5 c 1.0195329,1.319 1.1498748,-0.6123 1.1498748,-0.6123 0,0 -3.7344514,-4.51 -5.3773848,-6.4439 z" id="path4951" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/>
|
||||||
|
<path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#8ab000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 2.3378905,1005.8443 c -0.438175,0 -0.959862,0.1416 -0.8242183,0.7986 0.103561,0.5016 4.6608262,6.0744 4.6608262,6.0744 1.0195329,1.319 2.4934721,0.6763 1.4739391,-0.6425 l -4.234375,-5.4727 c -0.2602394,-0.29 -0.6085188,-0.7436 -1.076172,-0.7578 z" id="path4925" inkscape:connector-curvature="0" sodipodi:nodetypes="cscccc"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(42,0)" id="g4967">
|
||||||
|
<rect style="opacity:1;fill:#aeea00;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="rect4144" width="38" height="13" x="-37" y="1010.3622" rx="3" ry="3"/>
|
||||||
|
<rect ry="3" rx="3" y="1013.3622" x="-37" height="10" width="38" id="rect4961" style="opacity:1;fill:#263238;fill-opacity:0.2;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
|
||||||
|
<rect ry="3" rx="3" y="1010.3622" x="-37" height="10" width="38" id="rect4963" style="opacity:1;fill:#ffffff;fill-opacity:0.29803923;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
|
||||||
|
<rect ry="2.5384617" rx="3" y="1011.3622" x="-37" height="11" width="38" id="rect4965" style="opacity:1;fill:#aeea00;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
|
||||||
|
</g>
|
||||||
|
<g id="g4979">
|
||||||
|
<rect style="opacity:1;fill:#1976d2;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="rect4146" width="38" height="26" x="5" y="1024.3622" rx="3" ry="3"/>
|
||||||
|
<rect ry="3" rx="3" y="1037.3622" x="5" height="13" width="38" id="rect4973" style="opacity:1;fill:#263238;fill-opacity:0.2;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
|
||||||
|
<rect ry="3" rx="3" y="1024.3622" x="5" height="13" width="38" id="rect4975" style="opacity:1;fill:#ffffff;fill-opacity:0.2;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
|
||||||
|
<rect ry="2.7692308" rx="3" y="1025.3622" x="5" height="24" width="38" id="rect4977" style="opacity:1;fill:#1976d2;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(0,1013.3622)" id="g4211">
|
||||||
|
<path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0d47a1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 24,17.75 c -2.880662,0 -5.319789,1.984685 -6.033203,4.650391 l 3.212891,0 C 21.734004,21.415044 22.774798,20.75 24,20.75 c 1.812692,0 3.25,1.437308 3.25,3.25 0,1.812693 -1.437308,3.25 -3.25,3.25 -1.307381,0 -2.411251,-0.75269 -2.929688,-1.849609 l -3.154296,0 C 18.558263,28.166146 21.04791,30.25 24,30.25 c 3.434013,0 6.25,-2.815987 6.25,-6.25 0,-3.434012 -2.815987,-6.25 -6.25,-6.25 z" id="path4161" inkscape:connector-curvature="0"/>
|
||||||
|
<circle style="opacity:1;fill:none;fill-opacity:0.40392157;stroke:#0d47a1;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="path4209" cx="24" cy="24" r="9.5500002"/>
|
||||||
|
</g>
|
||||||
|
<g id="g4989" transform="translate(0,0.50001738)">
|
||||||
|
<ellipse cy="1016.4872" cx="14.375" id="circle4985" style="opacity:1;fill:#263238;fill-opacity:0.2;stroke:none;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.69721117" rx="3.375" ry="3.875"/>
|
||||||
|
<circle style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.69721117" id="path4859" cx="14.375" cy="1016.9872" r="3.375"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(19.5,0.50001738)" id="g4171">
|
||||||
|
<ellipse ry="3.875" rx="3.375" style="opacity:1;fill:#263238;fill-opacity:0.2;stroke:none;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.69721117" id="ellipse4175" cx="14.375" cy="1016.4872"/>
|
||||||
|
<circle r="3.375" cy="1016.9872" cx="14.375" id="circle4177" style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.69721117"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path inkscape:connector-curvature="0" id="path5128" d="m 2.613462,1005.5987 a 1.250125,1.250125 0 0 0 -1.01172,2.0293 l 3.60351,4.6641 c -0.12699,0.3331 -0.20312,0.6915 -0.20312,1.0703 l 0,4 0,2.8652 0,0.1348 c 0,1.662 1.338,3 3,3 l 32,0 c 1.662,0 3,-1.338 3,-3 l 0,-4 0,-2.8652 0,-0.1348 c 0,-0.3803 -0.0771,-0.74 -0.20508,-1.0742 l 3.60156,-4.6602 a 1.250125,1.250125 0 0 0 -1.04882,-2.0273 1.250125,1.250125 0 0 0 -0.92969,0.498 l -3.43164,4.4414 c -0.31022,-0.1079 -0.63841,-0.1777 -0.98633,-0.1777 l -32,0 c -0.34857,0 -0.67757,0.069 -0.98828,0.1777 l -3.4336,-4.4414 a 1.250125,1.250125 0 0 0 -0.96679,-0.5 z m 5.38867,18.7637 c -0.20775,0 -0.40983,0.021 -0.60547,0.061 -1.36951,0.2761 -2.39453,1.4698 -2.39453,2.9101 l 0,0.029 0,19.7793 0,0.029 0,0.1914 c 0,1.662 1.338,3 3,3 l 32,0 c 1.662,0 3,-1.338 3,-3 l 0,-20 0,-0.029 c 0,-1.4403 -1.02502,-2.634 -2.39453,-2.9101 -0.19565,-0.039 -0.39772,-0.061 -0.60547,-0.061 l -32,0 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#radialGradient5220);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 21 KiB |
23
apps/welcome/googleplay.svg
Normal file
23
apps/welcome/googleplay.svg
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 511.999 511.999" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<path style="fill:#32BBFF;" d="M382.369,175.623C322.891,142.356,227.427,88.937,79.355,6.028
|
||||||
|
C69.372-0.565,57.886-1.429,47.962,1.93l254.05,254.05L382.369,175.623z"/>
|
||||||
|
<path style="fill:#32BBFF;" d="M47.962,1.93c-1.86,0.63-3.67,1.39-5.401,2.308C31.602,10.166,23.549,21.573,23.549,36v439.96
|
||||||
|
c0,14.427,8.052,25.834,19.012,31.761c1.728,0.917,3.537,1.68,5.395,2.314L302.012,255.98L47.962,1.93z"/>
|
||||||
|
<path style="fill:#32BBFF;" d="M302.012,255.98L47.956,510.035c9.927,3.384,21.413,2.586,31.399-4.103
|
||||||
|
c143.598-80.41,237.986-133.196,298.152-166.746c1.675-0.941,3.316-1.861,4.938-2.772L302.012,255.98z"/>
|
||||||
|
</g>
|
||||||
|
<path style="fill:#2C9FD9;" d="M23.549,255.98v219.98c0,14.427,8.052,25.834,19.012,31.761c1.728,0.917,3.537,1.68,5.395,2.314
|
||||||
|
L302.012,255.98H23.549z"/>
|
||||||
|
<path style="fill:#29CC5E;" d="M79.355,6.028C67.5-1.8,53.52-1.577,42.561,4.239l255.595,255.596l84.212-84.212
|
||||||
|
C322.891,142.356,227.427,88.937,79.355,6.028z"/>
|
||||||
|
<path style="fill:#D93F21;" d="M298.158,252.126L42.561,507.721c10.96,5.815,24.939,6.151,36.794-1.789
|
||||||
|
c143.598-80.41,237.986-133.196,298.152-166.746c1.675-0.941,3.316-1.861,4.938-2.772L298.158,252.126z"/>
|
||||||
|
<path style="fill:#FFD500;" d="M488.45,255.98c0-12.19-6.151-24.492-18.342-31.314c0,0-22.799-12.721-92.682-51.809l-83.123,83.123
|
||||||
|
l83.204,83.205c69.116-38.807,92.6-51.892,92.6-51.892C482.299,280.472,488.45,268.17,488.45,255.98z"/>
|
||||||
|
<path style="fill:#FFAA00;" d="M470.108,287.294c12.191-6.822,18.342-19.124,18.342-31.314H294.303l83.204,83.205
|
||||||
|
C446.624,300.379,470.108,287.294,470.108,287.294z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
@ -55,7 +55,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<a
|
<a
|
||||||
class="w3-button w3-black w3-padding-large"
|
class="w3-button w3-black w3-padding-large"
|
||||||
href="https://www.tildefriends.net/~cory/releases/"
|
href="https://dev.tildefriends.net/cory/tildefriends/releases"
|
||||||
><i class="fa fa-download"></i> Download</a
|
><i class="fa fa-download"></i> Download</a
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
@ -63,6 +63,33 @@
|
|||||||
href="https://www.tildefriends.net/~cory/apps/"
|
href="https://www.tildefriends.net/~cory/apps/"
|
||||||
><i class="fa fa-link"></i> Try It</a
|
><i class="fa fa-link"></i> Try It</a
|
||||||
>
|
>
|
||||||
|
<a
|
||||||
|
class="w3-button w3-black w3-padding-large"
|
||||||
|
href="https://dev.tildefriends.net/"
|
||||||
|
><i class="fa fa-mug-hot"></i> Development</a
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top"
|
||||||
|
href="https://f-droid.org/en/packages/com.unprompted.tildefriends.fdroid/"
|
||||||
|
><img src="f-droid.svg" style="height: 2em; margin: 0" /> Get it
|
||||||
|
on F-Droid</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top"
|
||||||
|
href="https://dev.tildefriends.net/releases/tildefriends-x86_64.AppImage"
|
||||||
|
>
|
||||||
|
<img src="appimage.svg" style="height: 2em; margin: 0" />
|
||||||
|
Get Linux 64-bit AppImage
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top"
|
||||||
|
href="https://play.google.com/store/apps/details?id=com.unprompted.tildefriends"
|
||||||
|
>
|
||||||
|
<img src="googleplay.svg" style="height: 2em; margin: 0" />
|
||||||
|
Get it on Google Play (Open Testing)
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w3-col l4 m6">
|
<div class="w3-col l4 m6">
|
||||||
<img src="tildefriends.png" class="w3-image w3-right w3-hide-small" />
|
<img src="tildefriends.png" class="w3-image w3-right w3-hide-small" />
|
||||||
@ -70,6 +97,55 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Getting Starting Section -->
|
||||||
|
<div class="w3-indigo w3-center">
|
||||||
|
<div class="w3-row-padding w3-padding-64">
|
||||||
|
<div class="w3-jumbo">
|
||||||
|
<i class="fa fa-rocket"></i> <b>Getting Started</b>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>First-time user checklist:</h2>
|
||||||
|
<ol type="1" style="text-align: left">
|
||||||
|
<li>
|
||||||
|
<a href="https://dev.tildefriends.net/cory/tildefriends/releases"
|
||||||
|
>Download</a
|
||||||
|
>
|
||||||
|
Tilde Friends or use
|
||||||
|
<a href="https://www.tildefriends.net/"
|
||||||
|
>https://www.tildefriends.net/</a
|
||||||
|
>.
|
||||||
|
</li>
|
||||||
|
<li>Create an account to identify yourself with that instance.</li>
|
||||||
|
<li>
|
||||||
|
Describe yourself in your profile in the <b>ssb</b> app. Give
|
||||||
|
yourself a name and an avatar if you like.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Connect to others.
|
||||||
|
<ul>
|
||||||
|
<li>Automatically discover peers on the same network.</li>
|
||||||
|
<li>
|
||||||
|
Manually connect to rooms and pubs, including
|
||||||
|
<a href="https://www.tildefriends.net/~cory/room/"
|
||||||
|
>tildefriends.net itself</a
|
||||||
|
>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Enable <b>Peer Exchange</b> in the <b>admin</b> to discover
|
||||||
|
internet peers.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Follow people to grow your network.</li>
|
||||||
|
<li>
|
||||||
|
Use the <b>edit</b> link at the top of any page to start modifying
|
||||||
|
and making apps.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- SSB Section -->
|
<!-- SSB Section -->
|
||||||
<div class="w3-light-grey">
|
<div class="w3-light-grey">
|
||||||
<div class="w3-row-padding w3-padding-64">
|
<div class="w3-row-padding w3-padding-64">
|
||||||
@ -147,8 +223,13 @@
|
|||||||
|
|
||||||
<!-- Technlology Section -->
|
<!-- Technlology Section -->
|
||||||
<div class="w3-container w3-padding-64 w3-light-grey w3-center">
|
<div class="w3-container w3-padding-64 w3-light-grey w3-center">
|
||||||
<h1 class="w3-jumbo"><b>Trusted Technology</b></h1>
|
<h1 class="w3-jumbo"><b>Boring Technology</b></h1>
|
||||||
<p>Tilde Friends is built using boring, trusted tech.</p>
|
<p>
|
||||||
|
Tilde Friends is built using boring, trusted tech. Unless a better
|
||||||
|
reason presents itself, it strives to use only simple and widely adopted
|
||||||
|
dependencies in order to keep it easy to build for all sorts of
|
||||||
|
platforms and maintainable for a very long time.
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Though of course for building Tilde Friends apps, you are free to use
|
Though of course for building Tilde Friends apps, you are free to use
|
||||||
whatever fits.
|
whatever fits.
|
||||||
@ -185,7 +266,7 @@
|
|||||||
<i class="fa fa-lock w3-text-purple w3-jumbo"></i>
|
<i class="fa fa-lock w3-text-purple w3-jumbo"></i>
|
||||||
<p>libsodium</p>
|
<p>libsodium</p>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.openssl.org/" class="w3-col s3">
|
<a href="https://github.com/openssl/openssl/releases" class="w3-col s3">
|
||||||
<i class="fa fa-shield-halved w3-text-green w3-jumbo"></i>
|
<i class="fa fa-shield-halved w3-text-green w3-jumbo"></i>
|
||||||
<p>OpenSSL</p>
|
<p>OpenSSL</p>
|
||||||
</a>
|
</a>
|
||||||
@ -199,7 +280,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w3-row" style="margin-top: 64px">
|
<div class="w3-row" style="margin-top: 64px">
|
||||||
<a href="https://codemirror.net/5/" class="w3-col s3">
|
<a href="https://codemirror.net/docs/changelog/" class="w3-col s3">
|
||||||
<i class="fa fa-keyboard w3-text-indigo w3-jumbo"></i>
|
<i class="fa fa-keyboard w3-text-indigo w3-jumbo"></i>
|
||||||
<p>CodeMirror</p>
|
<p>CodeMirror</p>
|
||||||
</a>
|
</a>
|
||||||
@ -211,6 +292,13 @@
|
|||||||
<i class="fa fa-fire w3-text-cyan w3-jumbo"></i>
|
<i class="fa fa-fire w3-text-cyan w3-jumbo"></i>
|
||||||
<p>Lit</p>
|
<p>Lit</p>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="https://github.com/c-ares/c-ares" class="w3-col s3">
|
||||||
|
<i class="fa fa-book-atlas w3-text-purple w3-jumbo"></i>
|
||||||
|
<p>c-ares</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w3-row" style="margin-top: 64px">
|
||||||
<a href="https://www.gnu.org/software/make/" class="w3-col s3">
|
<a href="https://www.gnu.org/software/make/" class="w3-col s3">
|
||||||
<i class="fa fa-hammer w3-text-teal w3-jumbo"></i>
|
<i class="fa fa-hammer w3-text-teal w3-jumbo"></i>
|
||||||
<p>GNU Make</p>
|
<p>GNU Make</p>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "📝",
|
"emoji": "📝",
|
||||||
"previous": "&DnfuAUGzzalSh9NgZXnzDc9Ru5aM0omfRJ4h27jYw4k=.sha256"
|
"previous": "&DaYqKHRBKhjFGaOzbKZ1+/pLspJeEkDJYTF2B50tH6k=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@ import * as utils from './utils.js';
|
|||||||
let g_hash;
|
let g_hash;
|
||||||
let g_collection_notifies = {};
|
let g_collection_notifies = {};
|
||||||
|
|
||||||
|
tfrpc.register(async function getActiveIdentity() {
|
||||||
|
return ssb.getActiveIdentity();
|
||||||
|
});
|
||||||
tfrpc.register(async function getOwnerIdentities() {
|
tfrpc.register(async function getOwnerIdentities() {
|
||||||
return ssb.getOwnerIdentities();
|
return ssb.getOwnerIdentities();
|
||||||
});
|
});
|
||||||
@ -54,6 +57,9 @@ core.register('message', async function message_handler(message) {
|
|||||||
await tfrpc.rpc.hash_changed(message.hash);
|
await tfrpc.rpc.hash_changed(message.hash);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
core.register('setActiveIdentity', async function setActiveIdentityHandler(id) {
|
||||||
|
await tfrpc.rpc.setActiveIdentity(id);
|
||||||
|
});
|
||||||
|
|
||||||
tfrpc.register(function set_hash(hash) {
|
tfrpc.register(function set_hash(hash) {
|
||||||
if (g_hash != hash) {
|
if (g_hash != hash) {
|
||||||
|
2
apps/wiki/commonmark.min.js
vendored
2
apps/wiki/commonmark.min.js
vendored
File diff suppressed because one or more lines are too long
@ -10,7 +10,6 @@
|
|||||||
window.litDisableBundleWarning = true;
|
window.litDisableBundleWarning = true;
|
||||||
</script>
|
</script>
|
||||||
<script src="tf-collection.js" type="module"></script>
|
<script src="tf-collection.js" type="module"></script>
|
||||||
<script src="tf-id-picker.js" type="module"></script>
|
|
||||||
<script src="tf-wiki-doc.js" type="module"></script>
|
<script src="tf-wiki-doc.js" type="module"></script>
|
||||||
<script src="tf-wiki-app.js" type="module"></script>
|
<script src="tf-wiki-app.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
|
42
apps/wiki/lit-all.min.js
vendored
42
apps/wiki/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,44 +0,0 @@
|
|||||||
import {LitElement, html} from './lit-all.min.js';
|
|
||||||
import * as tfrpc from '/static/tfrpc.js';
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Provide a list of IDs, and this lets the user pick one.
|
|
||||||
*/
|
|
||||||
class TfIdentityPickerElement extends LitElement {
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
ids: {type: Array},
|
|
||||||
selected: {type: String},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.ids = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
changed(event) {
|
|
||||||
this.selected = event.srcElement.value;
|
|
||||||
this.dispatchEvent(
|
|
||||||
new Event('change', {
|
|
||||||
srcElement: this,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return html`
|
|
||||||
<link rel="stylesheet" href="tildefriends.css" />
|
|
||||||
<select @change=${this.changed} style="max-width: 100%">
|
|
||||||
${(this.ids ?? []).map(
|
|
||||||
(id) =>
|
|
||||||
html`<option ?selected=${id == this.selected} value=${id}>
|
|
||||||
${id}
|
|
||||||
</option>`
|
|
||||||
)}
|
|
||||||
</select>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define('tf-id-picker', TfIdentityPickerElement);
|
|
@ -31,13 +31,16 @@ class TfCollectionsAppElement extends LitElement {
|
|||||||
tfrpc.register(function hash_changed(hash) {
|
tfrpc.register(function hash_changed(hash) {
|
||||||
self.notify_hash_changed(hash);
|
self.notify_hash_changed(hash);
|
||||||
});
|
});
|
||||||
|
tfrpc.register(function setActiveIdentity(id) {
|
||||||
|
self.whoami = id;
|
||||||
|
});
|
||||||
tfrpc.rpc.get_hash().then((hash) => self.notify_hash_changed(hash));
|
tfrpc.rpc.get_hash().then((hash) => self.notify_hash_changed(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
this.ids = await tfrpc.rpc.getIdentities();
|
this.ids = await tfrpc.rpc.getIdentities();
|
||||||
this.owner_ids = await tfrpc.rpc.getOwnerIdentities();
|
this.owner_ids = await tfrpc.rpc.getOwnerIdentities();
|
||||||
this.whoami = await tfrpc.rpc.localStorageGet('collections_whoami');
|
this.whoami = await tfrpc.rpc.getActiveIdentity();
|
||||||
let ids = [...new Set([...this.owner_ids, this.whoami])].sort();
|
let ids = [...new Set([...this.owner_ids, this.whoami])].sort();
|
||||||
this.following = Object.keys(await tfrpc.rpc.following(ids, 1)).sort();
|
this.following = Object.keys(await tfrpc.rpc.following(ids, 1)).sort();
|
||||||
|
|
||||||
@ -273,9 +276,6 @@ class TfCollectionsAppElement extends LitElement {
|
|||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div>
|
|
||||||
<tf-id-picker .ids=${this.ids} selected=${this.whoami} @change=${this.on_whoami_changed} ?hidden=${!this.ids?.length}></tf-id-picker>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
${keyed(
|
${keyed(
|
||||||
this.whoami,
|
this.whoami,
|
||||||
|
@ -50,7 +50,7 @@ function new_message() {
|
|||||||
return g_new_message_promise;
|
return g_new_message_promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssb.addEventListener('message', function (id) {
|
core.register('onMessage', function (id) {
|
||||||
let resolve = g_new_message_resolve;
|
let resolve = g_new_message_resolve;
|
||||||
g_new_message_promise = new Promise(function (resolve, reject) {
|
g_new_message_promise = new Promise(function (resolve, reject) {
|
||||||
g_new_message_resolve = resolve;
|
g_new_message_resolve = resolve;
|
||||||
@ -96,7 +96,7 @@ export async function collection(
|
|||||||
let rows = [];
|
let rows = [];
|
||||||
await ssb.sqlAsync(
|
await ssb.sqlAsync(
|
||||||
`
|
`
|
||||||
SELECT messages.id, author, content, timestamp
|
SELECT messages.id, author, json(content) AS content, timestamp
|
||||||
FROM messages
|
FROM messages
|
||||||
JOIN json_each(?1) AS id ON messages.author = id.value
|
JOIN json_each(?1) AS id ON messages.author = id.value
|
||||||
WHERE
|
WHERE
|
||||||
|
52
core/app.js
52
core/app.js
@ -1,4 +1,3 @@
|
|||||||
import * as auth from './auth.js';
|
|
||||||
import * as core from './core.js';
|
import * as core from './core.js';
|
||||||
|
|
||||||
let g_next_id = 1;
|
let g_next_id = 1;
|
||||||
@ -11,7 +10,7 @@ let gSessionIndex = 0;
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function makeSessionId() {
|
function makeSessionId() {
|
||||||
return (gSessionIndex++).toString();
|
return 'session_' + (gSessionIndex++).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,11 +83,10 @@ App.prototype.send = function (message) {
|
|||||||
* @param {*} response
|
* @param {*} response
|
||||||
* @param {*} client
|
* @param {*} client
|
||||||
*/
|
*/
|
||||||
function socket(request, response, client) {
|
async function socket(request, response, client) {
|
||||||
let process;
|
let process;
|
||||||
let options = {};
|
let options = {};
|
||||||
let credentials = auth.query(request.headers);
|
let credentials = await httpd.auth_query(request.headers);
|
||||||
let refresh = auth.makeRefresh(credentials);
|
|
||||||
|
|
||||||
response.onClose = async function () {
|
response.onClose = async function () {
|
||||||
if (process && process.task) {
|
if (process && process.task) {
|
||||||
@ -143,12 +141,21 @@ function socket(request, response, client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
response.send(
|
response.send(
|
||||||
JSON.stringify({
|
JSON.stringify(
|
||||||
action: 'session',
|
Object.assign(
|
||||||
credentials: credentials,
|
{
|
||||||
parentApp: parentApp,
|
action: 'session',
|
||||||
id: blobId,
|
credentials: credentials,
|
||||||
}),
|
parentApp: parentApp,
|
||||||
|
id: blobId,
|
||||||
|
},
|
||||||
|
await ssb.getIdentityInfo(
|
||||||
|
credentials?.session?.name,
|
||||||
|
packageOwner,
|
||||||
|
packageName
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
0x1
|
0x1
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -165,11 +172,7 @@ function socket(request, response, client) {
|
|||||||
0x1
|
0x1
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
process = await core.getSessionProcessBlob(
|
process = await core.getProcessBlob(blobId, sessionId, options);
|
||||||
blobId,
|
|
||||||
sessionId,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (process) {
|
if (process) {
|
||||||
@ -204,14 +207,14 @@ function socket(request, response, client) {
|
|||||||
if (process && process.timeout > 0) {
|
if (process && process.timeout > 0) {
|
||||||
setTimeout(ping, process.timeout);
|
setTimeout(ping, process.timeout);
|
||||||
}
|
}
|
||||||
} else if (message.action == 'enableStats') {
|
|
||||||
if (process) {
|
|
||||||
core.enableStats(process, message.enabled);
|
|
||||||
}
|
|
||||||
} else if (message.action == 'resetPermission') {
|
} else if (message.action == 'resetPermission') {
|
||||||
if (process) {
|
if (process) {
|
||||||
process.resetPermission(message.permission);
|
process.resetPermission(message.permission);
|
||||||
}
|
}
|
||||||
|
} else if (message.action == 'setActiveIdentity') {
|
||||||
|
process.setActiveIdentity(message.identity);
|
||||||
|
} else if (message.action == 'createIdentity') {
|
||||||
|
await process.createIdentity();
|
||||||
} else if (message.message == 'tfrpc') {
|
} else if (message.message == 'tfrpc') {
|
||||||
if (message.id && g_calls[message.id]) {
|
if (message.id && g_calls[message.id]) {
|
||||||
if (message.error !== undefined) {
|
if (message.error !== undefined) {
|
||||||
@ -241,14 +244,7 @@ function socket(request, response, client) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
response.upgrade(
|
response.upgrade(100, {});
|
||||||
100,
|
|
||||||
refresh
|
|
||||||
? {
|
|
||||||
'Set-Cookie': `session=${refresh.token}; path=/; Max-Age=${refresh.interval}; Secure; SameSite=Strict`,
|
|
||||||
}
|
|
||||||
: {}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export {socket, App};
|
export {socket, App};
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Tilde Friends Sign-in</title>
|
<title>Tilde Friends Sign-in</title>
|
||||||
<link type="text/css" rel="stylesheet" href="/static/style.css" />
|
<link type="text/css" rel="stylesheet" href="/static/style.css" />
|
||||||
<link type="image/png" rel="shortcut icon" href="/static/favicon.png" />
|
<link type="image/svg+xml" rel="icon" href="/static/tildefriends.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -19,8 +19,11 @@
|
|||||||
Object.assign(app, g_data);
|
Object.assign(app, g_data);
|
||||||
|
|
||||||
class TfAuthElement extends LitElement {
|
class TfAuthElement extends LitElement {
|
||||||
static get_properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
|
code_of_conduct: {type: String},
|
||||||
|
error: {type: String},
|
||||||
|
have_administrator: {type: Boolean},
|
||||||
name: {type: String},
|
name: {type: String},
|
||||||
tab: {type: String},
|
tab: {type: String},
|
||||||
};
|
};
|
||||||
@ -31,11 +34,6 @@
|
|||||||
this.tab = 'login';
|
this.tab = 'login';
|
||||||
}
|
}
|
||||||
|
|
||||||
tab_changed(name) {
|
|
||||||
this.tab = name;
|
|
||||||
this.requestUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let self = this;
|
let self = this;
|
||||||
return html`
|
return html`
|
||||||
@ -83,16 +81,16 @@
|
|||||||
<h1 ?hidden=${this.name === undefined}>Welcome, ${this.name}.</h1>
|
<h1 ?hidden=${this.name === undefined}>Welcome, ${this.name}.</h1>
|
||||||
|
|
||||||
<div style="display: flex; flex-direction: row; width: 100%">
|
<div style="display: flex; flex-direction: row; width: 100%">
|
||||||
<input type="radio" name="tab" id="login" value="Login" ?checked=${this.tab == 'login'} @change=${() => self.tab_changed('login')}></input>
|
<input type="radio" name="tab" id="login" value="Login" ?checked=${this.tab == 'login'} @change=${() => (self.tab = 'login')}></input>
|
||||||
<label for="login" id="login_label">Login</label>
|
<label for="login" id="login_label">Login</label>
|
||||||
|
|
||||||
<input type="radio" name="tab" id="register" value="Register" ?checked=${this.tab == 'register'} @change=${() => self.tab_changed('register')}></input>
|
<input type="radio" name="tab" id="register" value="Register" ?checked=${this.tab == 'register'} @change=${() => (self.tab = 'register')}></input>
|
||||||
<label for="register" id="register_label">Register</label>
|
<label for="register" id="register_label">Register</label>
|
||||||
|
|
||||||
<input type="radio" name="tab" id="guest" value="Guest" ?checked=${this.tab == 'guest'} @change=${() => self.tab_changed('guest')}></input>
|
<input type="radio" name="tab" id="guest" value="Guest" ?checked=${this.tab == 'guest'} @change=${() => (self.tab = 'guest')}></input>
|
||||||
<label for="guest" id="guest_label">Guest</label>
|
<label for="guest" id="guest_label">Guest</label>
|
||||||
|
|
||||||
<input type="radio" name="tab" id="change" value="Change Password" ?checked=${this.tab == 'change'} @change=${() => self.tab_changed('change')}></input>
|
<input type="radio" name="tab" id="change" value="Change Password" ?checked=${this.tab == 'change'} @change=${() => (self.tab = 'change')}></input>
|
||||||
<label for="change" id="change_label">Change Password</label>
|
<label for="change" id="change_label">Change Password</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
420
core/auth.js
420
core/auth.js
@ -1,420 +0,0 @@
|
|||||||
import * as core from './core.js';
|
|
||||||
import * as form from './form.js';
|
|
||||||
|
|
||||||
let gDatabase = new Database('auth');
|
|
||||||
|
|
||||||
const kRefreshInterval = 1 * 7 * 24 * 60 * 60 * 1000;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a Base64 value URL safe
|
|
||||||
* @param {string} value
|
|
||||||
* @returns TODOC
|
|
||||||
*/
|
|
||||||
function b64url(value) {
|
|
||||||
value = value.replaceAll('+', '-').replaceAll('/', '_');
|
|
||||||
let equals = value.indexOf('=');
|
|
||||||
|
|
||||||
if (equals !== -1) {
|
|
||||||
return value.substring(0, equals);
|
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODOC
|
|
||||||
* @param {string} value
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function unb64url(value) {
|
|
||||||
value = value.replaceAll('-', '+').replaceAll('_', '/');
|
|
||||||
let remainder = value.length % 4;
|
|
||||||
|
|
||||||
if (remainder == 3) {
|
|
||||||
return value + '=';
|
|
||||||
} else if (remainder == 2) {
|
|
||||||
return value + '==';
|
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a JSON Web Token
|
|
||||||
* @param {object} payload Object: {"name": "username"}
|
|
||||||
* @returns the JWT
|
|
||||||
*/
|
|
||||||
function makeJwt(payload) {
|
|
||||||
const ids = ssb.getIdentities(':auth');
|
|
||||||
let id;
|
|
||||||
|
|
||||||
if (ids?.length) {
|
|
||||||
id = ids[0];
|
|
||||||
} else {
|
|
||||||
id = ssb.createIdentity(':auth');
|
|
||||||
}
|
|
||||||
|
|
||||||
const final_payload = b64url(
|
|
||||||
base64Encode(
|
|
||||||
JSON.stringify(
|
|
||||||
Object.assign({}, payload, {
|
|
||||||
exp: new Date().valueOf() + kRefreshInterval,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const jwt = [
|
|
||||||
b64url(base64Encode(JSON.stringify({alg: 'HS256', typ: 'JWT'}))),
|
|
||||||
final_payload,
|
|
||||||
b64url(ssb.hmacsha256sign(final_payload, ':auth', id)),
|
|
||||||
].join('.');
|
|
||||||
return jwt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates a JWT ?
|
|
||||||
* @param {*} session TODOC
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function readSession(session) {
|
|
||||||
let jwt_parts = session?.split('.');
|
|
||||||
|
|
||||||
if (jwt_parts?.length === 3) {
|
|
||||||
let [header, payload, signature] = jwt_parts;
|
|
||||||
header = JSON.parse(utf8Decode(base64Decode(unb64url(header))));
|
|
||||||
|
|
||||||
if (header.typ === 'JWT' && header.alg === 'HS256') {
|
|
||||||
signature = unb64url(signature);
|
|
||||||
let id = ssb.getIdentities(':auth');
|
|
||||||
|
|
||||||
if (id?.length && ssb.hmacsha256verify(id[0], payload, signature)) {
|
|
||||||
const result = JSON.parse(utf8Decode(base64Decode(unb64url(payload))));
|
|
||||||
const now = new Date().valueOf();
|
|
||||||
|
|
||||||
if (now < result.exp) {
|
|
||||||
print(`JWT valid for another ${(result.exp - now) / 1000} seconds.`);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
print(`JWT expired by ${(now - result.exp) / 1000} seconds.`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print('JWT verification failed.');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print('Invalid JWT header.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check the provided password matches the hash
|
|
||||||
* @param {string} password
|
|
||||||
* @param {string} hash bcrypt hash
|
|
||||||
* @returns true if the password matches the hash
|
|
||||||
*/
|
|
||||||
function verifyPassword(password, hash) {
|
|
||||||
return bCrypt.hashpw(password, hash) === hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hashes a password
|
|
||||||
* @param {string} password
|
|
||||||
* @returns {string} TODOC
|
|
||||||
*/
|
|
||||||
function hashPassword(password) {
|
|
||||||
let salt = bCrypt.gensalt(12);
|
|
||||||
return bCrypt.hashpw(password, salt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there is an administrator on the instance
|
|
||||||
* @returns TODOC
|
|
||||||
*/
|
|
||||||
function noAdministrator() {
|
|
||||||
return (
|
|
||||||
!core.globalSettings ||
|
|
||||||
!core.globalSettings.permissions ||
|
|
||||||
!Object.keys(core.globalSettings.permissions).some(function (name) {
|
|
||||||
return (
|
|
||||||
core.globalSettings.permissions[name].indexOf('administration') != -1
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a user an administrator
|
|
||||||
* @param {string} name the user's name
|
|
||||||
*/
|
|
||||||
function makeAdministrator(name) {
|
|
||||||
if (!core.globalSettings.permissions) {
|
|
||||||
core.globalSettings.permissions = {};
|
|
||||||
}
|
|
||||||
if (!core.globalSettings.permissions[name]) {
|
|
||||||
core.globalSettings.permissions[name] = [];
|
|
||||||
}
|
|
||||||
if (core.globalSettings.permissions[name].indexOf('administration') == -1) {
|
|
||||||
core.globalSettings.permissions[name].push('administration');
|
|
||||||
}
|
|
||||||
|
|
||||||
core.setGlobalSettings(core.globalSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODOC
|
|
||||||
* @param {*} headers most likely an object
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function getCookies(headers) {
|
|
||||||
let cookies = {};
|
|
||||||
|
|
||||||
if (headers.cookie) {
|
|
||||||
let parts = headers.cookie.split(/,|;/);
|
|
||||||
for (let i in parts) {
|
|
||||||
let equals = parts[i].indexOf('=');
|
|
||||||
let name = parts[i].substring(0, equals).trim();
|
|
||||||
let value = parts[i].substring(equals + 1).trim();
|
|
||||||
cookies[name] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates a username
|
|
||||||
* @param {string} name
|
|
||||||
* @returns false | boolean[] ?
|
|
||||||
*/
|
|
||||||
function isNameValid(name) {
|
|
||||||
// TODO(tasiaiso): convert this into a regex
|
|
||||||
let c = name.charAt(0);
|
|
||||||
return (
|
|
||||||
((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) &&
|
|
||||||
name
|
|
||||||
.split()
|
|
||||||
.map(
|
|
||||||
(x) =>
|
|
||||||
x >= ('a' && x <= 'z') ||
|
|
||||||
x >= ('A' && x <= 'Z') ||
|
|
||||||
x >= ('0' && x <= '9')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request handler ?
|
|
||||||
* @param {*} request TODOC
|
|
||||||
* @param {*} response
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function handler(request, response) {
|
|
||||||
// TODO(tasiaiso): split this function
|
|
||||||
let session = getCookies(request.headers).session;
|
|
||||||
if (request.uri == '/login') {
|
|
||||||
let formData = form.decodeForm(request.query);
|
|
||||||
if (query(request.headers)?.permissions?.authenticated) {
|
|
||||||
if (formData.return) {
|
|
||||||
response.writeHead(303, {Location: formData.return});
|
|
||||||
} else {
|
|
||||||
response.writeHead(303, {
|
|
||||||
Location:
|
|
||||||
(request.client.tls ? 'https://' : 'http://') +
|
|
||||||
request.headers.host +
|
|
||||||
'/',
|
|
||||||
'Content-Length': '0',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
response.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sessionIsNew = false;
|
|
||||||
let loginError;
|
|
||||||
|
|
||||||
if (request.method == 'POST' || formData.submit) {
|
|
||||||
sessionIsNew = true;
|
|
||||||
formData = form.decodeForm(utf8Decode(request.body), formData);
|
|
||||||
if (formData.submit == 'Login') {
|
|
||||||
let account = gDatabase.get('user:' + formData.name);
|
|
||||||
account = account ? JSON.parse(account) : account;
|
|
||||||
if (formData.register == '1') {
|
|
||||||
if (
|
|
||||||
!account &&
|
|
||||||
isNameValid(formData.name) &&
|
|
||||||
formData.password == formData.confirm
|
|
||||||
) {
|
|
||||||
let users = new Set();
|
|
||||||
let users_original = gDatabase.get('users');
|
|
||||||
try {
|
|
||||||
users = new Set(JSON.parse(users_original));
|
|
||||||
} catch {}
|
|
||||||
if (!users.has(formData.name)) {
|
|
||||||
users.add(formData.name);
|
|
||||||
}
|
|
||||||
users = JSON.stringify([...users].sort());
|
|
||||||
if (users !== users_original) {
|
|
||||||
gDatabase.set('users', users);
|
|
||||||
}
|
|
||||||
session = makeJwt({name: formData.name});
|
|
||||||
account = {password: hashPassword(formData.password)};
|
|
||||||
gDatabase.set('user:' + formData.name, JSON.stringify(account));
|
|
||||||
if (noAdministrator()) {
|
|
||||||
makeAdministrator(formData.name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loginError = 'Error registering account.';
|
|
||||||
}
|
|
||||||
} else if (formData.change == '1') {
|
|
||||||
if (
|
|
||||||
account &&
|
|
||||||
isNameValid(formData.name) &&
|
|
||||||
formData.new_password == formData.confirm &&
|
|
||||||
verifyPassword(formData.password, account.password)
|
|
||||||
) {
|
|
||||||
session = makeJwt({name: formData.name});
|
|
||||||
account = {password: hashPassword(formData.new_password)};
|
|
||||||
gDatabase.set('user:' + formData.name, JSON.stringify(account));
|
|
||||||
} else {
|
|
||||||
loginError = 'Error changing password.';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
account &&
|
|
||||||
account.password &&
|
|
||||||
verifyPassword(formData.password, account.password)
|
|
||||||
) {
|
|
||||||
session = makeJwt({name: formData.name});
|
|
||||||
if (noAdministrator()) {
|
|
||||||
makeAdministrator(formData.name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loginError = 'Invalid username or password.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Proceed as Guest
|
|
||||||
session = makeJwt({name: 'guest'});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let cookie = `session=${session}; path=/; Max-Age=${kRefreshInterval}; ${request.client.tls ? 'Secure; ' : ''}SameSite=Strict; HttpOnly`;
|
|
||||||
let entry = readSession(session);
|
|
||||||
if (entry && formData.return) {
|
|
||||||
response.writeHead(303, {
|
|
||||||
Location: formData.return,
|
|
||||||
'Set-Cookie': cookie,
|
|
||||||
});
|
|
||||||
response.end();
|
|
||||||
} else {
|
|
||||||
File.readFile('core/auth.html')
|
|
||||||
.then(function (data) {
|
|
||||||
let html = utf8Decode(data);
|
|
||||||
let auth_data = {
|
|
||||||
session_is_new: sessionIsNew,
|
|
||||||
name: entry?.name,
|
|
||||||
error: loginError,
|
|
||||||
code_of_conduct: core.globalSettings.code_of_conduct,
|
|
||||||
have_administrator: !noAdministrator(),
|
|
||||||
};
|
|
||||||
html = utf8Encode(
|
|
||||||
html.replace('$AUTH_DATA', JSON.stringify(auth_data))
|
|
||||||
);
|
|
||||||
response.writeHead(200, {
|
|
||||||
'Content-Type': 'text/html; charset=utf-8',
|
|
||||||
'Set-Cookie': cookie,
|
|
||||||
'Content-Length': html.length,
|
|
||||||
});
|
|
||||||
response.end(html);
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
response.writeHead(404, {
|
|
||||||
'Content-Type': 'text/plain; charset=utf-8',
|
|
||||||
Connection: 'close',
|
|
||||||
});
|
|
||||||
response.end('404 File not found');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (request.uri == '/login/logout') {
|
|
||||||
response.writeHead(303, {
|
|
||||||
'Set-Cookie': `session=; path=/; ${request.client.tls ? 'Secure; ' : ''}SameSite=Strict; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly`,
|
|
||||||
Location: '/login' + (request.query ? '?' + request.query : ''),
|
|
||||||
});
|
|
||||||
response.end();
|
|
||||||
} else {
|
|
||||||
response.writeHead(200, {
|
|
||||||
'Content-Type': 'text/plain; charset=utf-8',
|
|
||||||
Connection: 'close',
|
|
||||||
});
|
|
||||||
response.end('Hello, ' + request.client.peerName + '.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a user's permissions based on it's session ?
|
|
||||||
* @param {*} session TODOC
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function getPermissions(session) {
|
|
||||||
let permissions;
|
|
||||||
let entry = readSession(session);
|
|
||||||
if (entry) {
|
|
||||||
permissions = getPermissionsForUser(entry.name);
|
|
||||||
permissions.authenticated = entry.name !== 'guest';
|
|
||||||
}
|
|
||||||
return permissions || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a user's permissions ?
|
|
||||||
* @param {string} userName TODOC
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function getPermissionsForUser(userName) {
|
|
||||||
let permissions = {};
|
|
||||||
if (
|
|
||||||
core.globalSettings &&
|
|
||||||
core.globalSettings.permissions &&
|
|
||||||
core.globalSettings.permissions[userName]
|
|
||||||
) {
|
|
||||||
for (let i in core.globalSettings.permissions[userName]) {
|
|
||||||
permissions[core.globalSettings.permissions[userName][i]] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODOC
|
|
||||||
* @param {*} headers
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function query(headers) {
|
|
||||||
let session = getCookies(headers).session;
|
|
||||||
let entry;
|
|
||||||
let autologin = tildefriends.args.autologin;
|
|
||||||
if ((entry = autologin ? {name: autologin} : readSession(session))) {
|
|
||||||
return {
|
|
||||||
session: entry,
|
|
||||||
permissions: autologin
|
|
||||||
? getPermissionsForUser(autologin)
|
|
||||||
: getPermissions(session),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refreshes a JWT ?
|
|
||||||
* @param {*} credentials TODOC
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function makeRefresh(credentials) {
|
|
||||||
if (credentials?.session?.name) {
|
|
||||||
return {
|
|
||||||
token: makeJwt({name: credentials.session.name}),
|
|
||||||
interval: kRefreshInterval,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {handler, query, makeRefresh};
|
|
256
core/client.js
256
core/client.js
@ -10,6 +10,7 @@ let gEditor;
|
|||||||
let gOriginalInput;
|
let gOriginalInput;
|
||||||
|
|
||||||
let kErrorColor = '#dc322f';
|
let kErrorColor = '#dc322f';
|
||||||
|
let kDisconnectColor = '#f00';
|
||||||
let kStatusColor = '#fff';
|
let kStatusColor = '#fff';
|
||||||
|
|
||||||
// Functions that server-side app code can call through the app object.
|
// Functions that server-side app code can call through the app object.
|
||||||
@ -56,6 +57,9 @@ class TfNavigationElement extends LitElement {
|
|||||||
spark_lines: {type: Object},
|
spark_lines: {type: Object},
|
||||||
version: {type: Object},
|
version: {type: Object},
|
||||||
show_version: {type: Boolean},
|
show_version: {type: Boolean},
|
||||||
|
identity: {type: String},
|
||||||
|
identities: {type: Array},
|
||||||
|
names: {type: Object},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +69,8 @@ class TfNavigationElement extends LitElement {
|
|||||||
this.show_permissions = false;
|
this.show_permissions = false;
|
||||||
this.status = {};
|
this.status = {};
|
||||||
this.spark_lines = {};
|
this.spark_lines = {};
|
||||||
|
this.identities = [];
|
||||||
|
this.names = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,10 +103,10 @@ class TfNavigationElement extends LitElement {
|
|||||||
get_spark_line(key, options) {
|
get_spark_line(key, options) {
|
||||||
if (!this.spark_lines[key]) {
|
if (!this.spark_lines[key]) {
|
||||||
let spark_line = document.createElement('tf-sparkline');
|
let spark_line = document.createElement('tf-sparkline');
|
||||||
spark_line.style.display = 'flex';
|
|
||||||
spark_line.style.flexDirection = 'row';
|
|
||||||
spark_line.style.flex = '0 50 5em';
|
|
||||||
spark_line.title = key;
|
spark_line.title = key;
|
||||||
|
spark_line.classList.add('w3-bar-item');
|
||||||
|
spark_line.classList.add('w3-hide-small');
|
||||||
|
spark_line.style.paddingRight = '0';
|
||||||
if (options) {
|
if (options) {
|
||||||
if (options.max) {
|
if (options.max) {
|
||||||
spark_line.max = options.max;
|
spark_line.max = options.max;
|
||||||
@ -112,17 +118,123 @@ class TfNavigationElement extends LitElement {
|
|||||||
return this.spark_lines[key];
|
return this.spark_lines[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
set_active_identity(id) {
|
||||||
* TODOC
|
send({action: 'setActiveIdentity', identity: id});
|
||||||
* @returns
|
this.renderRoot.getElementById('id_dropdown').classList.remove('w3-show');
|
||||||
*/
|
}
|
||||||
render_login() {
|
|
||||||
|
create_identity(event) {
|
||||||
|
if (confirm('Are you sure you want to create a new identity?')) {
|
||||||
|
send({action: 'createIdentity'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle_id_dropdown() {
|
||||||
|
this.renderRoot.getElementById('id_dropdown').classList.toggle('w3-show');
|
||||||
|
}
|
||||||
|
|
||||||
|
edit_profile() {
|
||||||
|
window.location.href = '/~core/ssb/#' + this.identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
window.location.href = `/login/logout?return=${encodeURIComponent(url() + hash())}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
render_identity() {
|
||||||
|
let self = this;
|
||||||
|
|
||||||
if (this?.credentials?.session?.name) {
|
if (this?.credentials?.session?.name) {
|
||||||
return html`<a id="login" href="/login/logout?return=${url() + hash()}"
|
if (this.identities?.length) {
|
||||||
>logout ${this.credentials.session.name}</a
|
return html`
|
||||||
>`;
|
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
||||||
|
<div class="w3-dropdown-click w3-right" style="max-width: 100%">
|
||||||
|
<button
|
||||||
|
class="w3-button w3-rest w3-cyan"
|
||||||
|
style="text-overflow: ellipsis; overflow: hidden; white-space: nowrap; max-width: 100%"
|
||||||
|
id="identity"
|
||||||
|
@click=${self.toggle_id_dropdown}
|
||||||
|
>
|
||||||
|
${self.names[this.identity]}▾
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
id="id_dropdown"
|
||||||
|
class="w3-dropdown-content w3-bar-block w3-card-4"
|
||||||
|
style="max-width: 100%; right: 0"
|
||||||
|
>
|
||||||
|
<div style="position: fixed; left: 0; right: 0; top: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.25); z-index: -100" @click=${self.toggle_id_dropdown}></div>
|
||||||
|
<button
|
||||||
|
class="w3-bar-item w3-button w3-border"
|
||||||
|
@click=${() => (window.location.href = '/~core/identity')}
|
||||||
|
>
|
||||||
|
Manage Identities...
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="w3-bar-item w3-button w3-border"
|
||||||
|
@click=${self.edit_profile}
|
||||||
|
>
|
||||||
|
Edit Profile...
|
||||||
|
</button>
|
||||||
|
${this.identities.map(
|
||||||
|
(x) => html`
|
||||||
|
<button
|
||||||
|
class="w3-bar-item w3-button ${x === self.identity
|
||||||
|
? 'w3-cyan'
|
||||||
|
: ''}"
|
||||||
|
@click=${() => self.set_active_identity(x)}
|
||||||
|
style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap"
|
||||||
|
>
|
||||||
|
${self.names[x]}${self.names[x] === x ? '' : html` - ${x}`}
|
||||||
|
</button>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
class="w3-bar-item w3-button w3-border"
|
||||||
|
id="logout"
|
||||||
|
@click=${self.logout}
|
||||||
|
>
|
||||||
|
Logout ${this.credentials.session.name}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else if (
|
||||||
|
this.credentials?.session?.name &&
|
||||||
|
this.credentials.session.name !== 'guest'
|
||||||
|
) {
|
||||||
|
return html`
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
||||||
|
<button
|
||||||
|
class="w3-bar-item w3-button w3-right w3-cyan"
|
||||||
|
id="logout"
|
||||||
|
@click=${self.logout}
|
||||||
|
>
|
||||||
|
Logout ${this.credentials.session.name}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
id="create_identity"
|
||||||
|
@click=${this.create_identity}
|
||||||
|
class="w3-button w3-mobile w3-red w3-right"
|
||||||
|
>
|
||||||
|
Create an Identity
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
return html`
|
||||||
|
<button
|
||||||
|
class="w3-bar-item w3-button w3-right w3-cyan"
|
||||||
|
id="logout"
|
||||||
|
@click=${self.logout}
|
||||||
|
>
|
||||||
|
Logout ${this.credentials.session.name}
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return html`<a id="login" href="/login?return=${url() + hash()}"
|
return html`<a
|
||||||
|
class="w3-bar-item w3-cyan w3-right"
|
||||||
|
id="login"
|
||||||
|
href="/login?return=${url() + hash()}"
|
||||||
>login</a
|
>login</a
|
||||||
>`;
|
>`;
|
||||||
}
|
}
|
||||||
@ -145,11 +257,17 @@ class TfNavigationElement extends LitElement {
|
|||||||
<div>This app has the following permissions:</div>
|
<div>This app has the following permissions:</div>
|
||||||
${Object.keys(this.permissions).map(
|
${Object.keys(this.permissions).map(
|
||||||
(key) => html`
|
(key) => html`
|
||||||
<div>
|
<div>
|
||||||
<span>${key}</span>: ${this.permissions[key] ? '✅ Allowed' : '❌ Denied'}
|
<span>${key}</span>:
|
||||||
<button @click=${() => this.reset_permission(key)} class='w3-button w3-red">Reset</button>
|
${this.permissions[key] ? '✅ Allowed' : '❌ Denied'}
|
||||||
</div>
|
<button
|
||||||
`
|
@click=${() => this.reset_permission(key)}
|
||||||
|
class="w3-button w3-red"
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
@click=${() => (this.show_permissions = false)}
|
@click=${() => (this.show_permissions = false)}
|
||||||
@ -163,6 +281,10 @@ class TfNavigationElement extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_error() {
|
||||||
|
this.status = {};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @returns
|
* @returns
|
||||||
@ -170,6 +292,7 @@ class TfNavigationElement extends LitElement {
|
|||||||
render() {
|
render() {
|
||||||
let self = this;
|
let self = this;
|
||||||
return html`
|
return html`
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
||||||
<style>
|
<style>
|
||||||
${k_global_style} .tooltip {
|
${k_global_style} .tooltip {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -185,17 +308,17 @@ class TfNavigationElement extends LitElement {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div
|
<div class="w3-black w3-bar">
|
||||||
style="margin: 4px; display: flex; flex-direction: row; flex-wrap: nowrap; gap: 3px; align-items: center"
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
|
class="w3-bar-item"
|
||||||
style="cursor: pointer"
|
style="cursor: pointer"
|
||||||
@click=${() => (this.show_version = !this.show_version)}
|
@click=${() => (this.show_version = !this.show_version)}
|
||||||
>😎</span
|
>😎</span
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
?hidden=${!this.show_version}
|
class="w3-bar-item"
|
||||||
style="flex: 0 0; white-space: nowrap"
|
style=${'white-space: nowrap' +
|
||||||
|
(this.show_version ? '' : '; display: none')}
|
||||||
title=${this.version?.name +
|
title=${this.version?.name +
|
||||||
' ' +
|
' ' +
|
||||||
Object.entries(this.version || {})
|
Object.entries(this.version || {})
|
||||||
@ -204,6 +327,7 @@ class TfNavigationElement extends LitElement {
|
|||||||
>${this.version?.number}</span
|
>${this.version?.number}</span
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
|
class="w3-bar-item"
|
||||||
accesskey="h"
|
accesskey="h"
|
||||||
@mouseover=${set_access_key_title}
|
@mouseover=${set_access_key_title}
|
||||||
data-tip="Open home app."
|
data-tip="Open home app."
|
||||||
@ -212,6 +336,7 @@ class TfNavigationElement extends LitElement {
|
|||||||
>TF</a
|
>TF</a
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
|
class="w3-bar-item"
|
||||||
accesskey="a"
|
accesskey="a"
|
||||||
@mouseover=${set_access_key_title}
|
@mouseover=${set_access_key_title}
|
||||||
data-tip="Open apps list."
|
data-tip="Open apps list."
|
||||||
@ -219,6 +344,7 @@ class TfNavigationElement extends LitElement {
|
|||||||
>apps</a
|
>apps</a
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
|
class="w3-bar-item"
|
||||||
accesskey="e"
|
accesskey="e"
|
||||||
@mouseover=${set_access_key_title}
|
@mouseover=${set_access_key_title}
|
||||||
data-tip="Toggle the app editor."
|
data-tip="Toggle the app editor."
|
||||||
@ -227,6 +353,7 @@ class TfNavigationElement extends LitElement {
|
|||||||
>edit</a
|
>edit</a
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
|
class="w3-bar-item"
|
||||||
accesskey="p"
|
accesskey="p"
|
||||||
@mouseover=${set_access_key_title}
|
@mouseover=${set_access_key_title}
|
||||||
data-tip="View and change permissions."
|
data-tip="View and change permissions."
|
||||||
@ -234,27 +361,34 @@ class TfNavigationElement extends LitElement {
|
|||||||
@click=${() => (self.show_permissions = !self.show_permissions)}
|
@click=${() => (self.show_permissions = !self.show_permissions)}
|
||||||
>🎛️</a
|
>🎛️</a
|
||||||
>
|
>
|
||||||
<span
|
|
||||||
style="display: inline-block; vertical-align: top; white-space: pre; color: ${this
|
|
||||||
.status.color ?? kErrorColor}"
|
|
||||||
>${this.status.message}</span
|
|
||||||
>
|
|
||||||
<span id="requests"></span>
|
|
||||||
${this.render_permissions()}
|
${this.render_permissions()}
|
||||||
<span
|
${this.status?.message && !this.status.is_error
|
||||||
style="flex: 1 1; display: flex; flex-direction: row; white-space: nowrap; margin: 0; padding: 0"
|
? html`
|
||||||
>${Object.keys(this.spark_lines)
|
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
||||||
.sort()
|
<div
|
||||||
.map((x) => this.spark_lines[x])
|
class="w3-bar-item"
|
||||||
.map((x) => [
|
style="color: ${this.status.color ?? kStatusColor}"
|
||||||
html`<span style="font-size: xx-small">${x.dataset.emoji}</span>`,
|
>
|
||||||
x,
|
${this.status.message}
|
||||||
])}</span
|
</div>
|
||||||
>
|
`
|
||||||
<span style="flex: 0 0; white-space: nowrap"
|
: undefined}
|
||||||
>${this.render_login()}</span
|
${Object.keys(this.spark_lines)
|
||||||
>
|
.sort()
|
||||||
|
.map((x) => this.spark_lines[x])}
|
||||||
|
${this.render_identity()}
|
||||||
</div>
|
</div>
|
||||||
|
${this.status?.is_error
|
||||||
|
? html`
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
||||||
|
<div class="w3-model w3-animate-top" style="position: absolute; left: 50%; transform: translate(-50%); z-index: 1">
|
||||||
|
<dijv class="w3-modal-content w3-card-4" style="display: block; padding: 1em">
|
||||||
|
<span id="close_error" @click=${self.clear_error} class="w3-button w3-display-topright">×</span>
|
||||||
|
<div style="color: ${this.status.color ?? kErrorColor}"><b>ERROR:</b><p id="error" style="white-space: pre">${this.status.message}</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: undefined}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -578,13 +712,13 @@ class TfSparkLineElement extends LitElement {
|
|||||||
) / 10.0;
|
) / 10.0;
|
||||||
return html`
|
return html`
|
||||||
<svg
|
<svg
|
||||||
style="max-width: 7.5em; max-height: 1.5em; margin: 0; padding: 0; background: #000"
|
style="max-width: 7.5em; margin: 0; padding: 0; background: #000; height: 1em"
|
||||||
viewBox="0 0 50 10"
|
viewBox="0 0 50 10"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
${this.lines.map((x) => this.render_line(x))}
|
${this.lines.map((x) => this.render_line(x))}
|
||||||
<text x="0" y="1em" style="font: 8px sans-serif; fill: #fff">
|
<text x="0" y="1em" style="font: 8px sans-serif; fill: #fff">
|
||||||
${max}
|
${this.dataset.emoji}${max}
|
||||||
</text>
|
</text>
|
||||||
</svg>
|
</svg>
|
||||||
`;
|
`;
|
||||||
@ -1000,9 +1134,9 @@ function api_postMessage(message) {
|
|||||||
function api_error(error) {
|
function api_error(error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
if (typeof error == 'string') {
|
if (typeof error == 'string') {
|
||||||
setStatusMessage('⚠️ ' + error, '#f00');
|
setStatusMessage('⚠️ ' + error, kErrorColor);
|
||||||
} else {
|
} else {
|
||||||
setStatusMessage('⚠️ ' + error.message + '\n' + error.stack, '#f00');
|
setStatusMessage('⚠️ ' + error.message + '\n' + error.stack, kErrorColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('error', error);
|
console.log('error', error);
|
||||||
@ -1041,7 +1175,7 @@ function api_requestPermission(permission, id) {
|
|||||||
|
|
||||||
let div = document.createElement('div');
|
let div = document.createElement('div');
|
||||||
div.appendChild(
|
div.appendChild(
|
||||||
document.createTextNode('This app is requesting the following permission:')
|
document.createTextNode('This app is requesting the following permission: ')
|
||||||
);
|
);
|
||||||
let span = document.createElement('span');
|
let span = document.createElement('span');
|
||||||
span.style = 'font-weight: bold';
|
span.style = 'font-weight: bold';
|
||||||
@ -1057,6 +1191,7 @@ function api_requestPermission(permission, id) {
|
|||||||
check.classList.add('w3-check');
|
check.classList.add('w3-check');
|
||||||
check.classList.add('w3-blue');
|
check.classList.add('w3-blue');
|
||||||
div.appendChild(check);
|
div.appendChild(check);
|
||||||
|
div.appendChild(document.createTextNode(' '));
|
||||||
let label = document.createElement('label');
|
let label = document.createElement('label');
|
||||||
label.htmlFor = check.id;
|
label.htmlFor = check.id;
|
||||||
label.appendChild(document.createTextNode('Remember this decision.'));
|
label.appendChild(document.createTextNode('Remember this decision.'));
|
||||||
@ -1119,11 +1254,19 @@ function api_setHash(hash) {
|
|||||||
function _receive_websocket_message(message) {
|
function _receive_websocket_message(message) {
|
||||||
if (message && message.action == 'session') {
|
if (message && message.action == 'session') {
|
||||||
setStatusMessage('🟢 Executing...', kStatusColor);
|
setStatusMessage('🟢 Executing...', kStatusColor);
|
||||||
document.getElementsByTagName('tf-navigation')[0].credentials =
|
let navigation = document.getElementsByTagName('tf-navigation')[0];
|
||||||
message.credentials;
|
navigation.credentials = message.credentials;
|
||||||
|
navigation.identities = message.identities;
|
||||||
|
navigation.identity = message.identity;
|
||||||
|
navigation.names = message.names;
|
||||||
} else if (message && message.action == 'permissions') {
|
} else if (message && message.action == 'permissions') {
|
||||||
document.getElementsByTagName('tf-navigation')[0].permissions =
|
let navigation = document.getElementsByTagName('tf-navigation')[0];
|
||||||
message.permissions ?? {};
|
navigation.permissions = message.permissions ?? {};
|
||||||
|
} else if (message && message.action == 'identities') {
|
||||||
|
let navigation = document.getElementsByTagName('tf-navigation')[0];
|
||||||
|
navigation.identities = message.identities;
|
||||||
|
navigation.identity = message.identity;
|
||||||
|
navigation.names = message.names;
|
||||||
} else if (message && message.action == 'ready') {
|
} else if (message && message.action == 'ready') {
|
||||||
setStatusMessage(null);
|
setStatusMessage(null);
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
@ -1133,7 +1276,6 @@ function _receive_websocket_message(message) {
|
|||||||
document.getElementById('viewPane').style.display = message.edit_only
|
document.getElementById('viewPane').style.display = message.edit_only
|
||||||
? 'none'
|
? 'none'
|
||||||
: 'flex';
|
: 'flex';
|
||||||
send({action: 'enableStats', enabled: true});
|
|
||||||
} else if (message && message.action == 'ping') {
|
} else if (message && message.action == 'ping') {
|
||||||
send({action: 'pong'});
|
send({action: 'pong'});
|
||||||
} else if (message && message.action == 'stats') {
|
} else if (message && message.action == 'stats') {
|
||||||
@ -1211,6 +1353,7 @@ function setStatusMessage(message, color) {
|
|||||||
document.getElementsByTagName('tf-navigation')[0].status = {
|
document.getElementsByTagName('tf-navigation')[0].status = {
|
||||||
message: message,
|
message: message,
|
||||||
color: color,
|
color: color,
|
||||||
|
is_error: color == kErrorColor,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1420,7 +1563,7 @@ function connectSocket(path) {
|
|||||||
};
|
};
|
||||||
setStatusMessage(
|
setStatusMessage(
|
||||||
'🔴 Closed: ' + (k_codes[event.code] || event.code),
|
'🔴 Closed: ' + (k_codes[event.code] || event.code),
|
||||||
kErrorColor
|
kDisconnectColor
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1641,10 +1784,11 @@ async function sourcePretty() {
|
|||||||
let prettier = (await import('/prettier/standalone.mjs')).default;
|
let prettier = (await import('/prettier/standalone.mjs')).default;
|
||||||
let babel = (await import('/prettier/babel.mjs')).default;
|
let babel = (await import('/prettier/babel.mjs')).default;
|
||||||
let estree = (await import('/prettier/estree.mjs')).default;
|
let estree = (await import('/prettier/estree.mjs')).default;
|
||||||
|
let prettier_html = (await import('/prettier/html.mjs')).default;
|
||||||
let source = gEditor.state.doc.toString();
|
let source = gEditor.state.doc.toString();
|
||||||
let formatted = await prettier.format(source, {
|
let formatted = await prettier.format(source, {
|
||||||
parser: 'babel',
|
parser: gCurrentFile?.toLowerCase()?.endsWith('.html') ? 'html' : 'babel',
|
||||||
plugins: [babel, estree],
|
plugins: [babel, estree, prettier_html],
|
||||||
trailingComma: 'es5',
|
trailingComma: 'es5',
|
||||||
useTabs: true,
|
useTabs: true,
|
||||||
semi: true,
|
semi: true,
|
||||||
@ -1679,8 +1823,8 @@ function toggleVisibleWhitespace() {
|
|||||||
.cm-highlightTab {
|
.cm-highlightTab {
|
||||||
background-image: unset !important;
|
background-image: unset !important;
|
||||||
}
|
}
|
||||||
.cm-highlightSpace:before {
|
.cm-highlightSpace {
|
||||||
content: unset !important;
|
background-image: unset !important;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
window.localStorage.setItem('visible_whitespace', '1');
|
window.localStorage.setItem('visible_whitespace', '1');
|
||||||
|
1125
core/core.js
1125
core/core.js
File diff suppressed because it is too large
Load Diff
BIN
core/favicon.png
BIN
core/favicon.png
Binary file not shown.
Before Width: | Height: | Size: 320 B |
@ -4,7 +4,7 @@
|
|||||||
<title>Tilde Friends</title>
|
<title>Tilde Friends</title>
|
||||||
<link type="text/css" rel="stylesheet" href="/static/style.css" />
|
<link type="text/css" rel="stylesheet" href="/static/style.css" />
|
||||||
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
||||||
<link type="image/png" rel="shortcut icon" href="/static/favicon.png" />
|
<link type="image/svg+xml" rel="icon" href="/static/tildefriends.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<script>
|
<script>
|
||||||
function set_access_key_title(event) {
|
function set_access_key_title(event) {
|
||||||
@ -25,6 +25,17 @@
|
|||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
<noscript>
|
||||||
|
<div class="w3-container">
|
||||||
|
<div class="w3-panel w3-red w3-padding w3-card-4">
|
||||||
|
<h1>TildeFriends requires JavaScript.</h1>
|
||||||
|
<p>
|
||||||
|
It looks like JavaScript is disabled or unsupported. This isn't
|
||||||
|
going to work.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</noscript>
|
||||||
<tf-navigation></tf-navigation>
|
<tf-navigation></tf-navigation>
|
||||||
<div id="content" class="hbox" style="flex: 1 0; overflow: auto">
|
<div id="content" class="hbox" style="flex: 1 0; overflow: auto">
|
||||||
<div
|
<div
|
||||||
|
@ -15,22 +15,6 @@ body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:link {
|
|
||||||
color: #268bd2;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:visited {
|
|
||||||
color: #6c71c4;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: #859900;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:active {
|
|
||||||
color: #2aa198;
|
|
||||||
}
|
|
||||||
|
|
||||||
#logo {
|
#logo {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
88
core/tildefriends.svg
Normal file
88
core/tildefriends.svg
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="65"
|
||||||
|
height="65"
|
||||||
|
viewBox="0 0 61 65"
|
||||||
|
fill="none"
|
||||||
|
version="1.1"
|
||||||
|
id="svg910"
|
||||||
|
sodipodi:docname="tildefriends.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||||
|
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">
|
||||||
|
<defs
|
||||||
|
id="defs914" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview912"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="18.369231"
|
||||||
|
inkscape:cx="32.472781"
|
||||||
|
inkscape:cy="32.5"
|
||||||
|
inkscape:window-width="2256"
|
||||||
|
inkscape:window-height="1447"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg910" />
|
||||||
|
<path
|
||||||
|
style="fill:#0af;stroke-width:.712717;fill-opacity:1"
|
||||||
|
d="M6 0h49a8 8 45 0 1 8 8v49a8 8 135 0 1-8 8H6a8 8 45 0 1-8-8V8a8 8 135 0 1 8-8Z"
|
||||||
|
id="path886" />
|
||||||
|
<g
|
||||||
|
aria-label="~"
|
||||||
|
id="text890"
|
||||||
|
style="font-size:40px;line-height:1.25;fill:#000000">
|
||||||
|
<path
|
||||||
|
d="m 1.6762187,36.689095 v -4.003907 q 2.0703125,-2.34375 5.4296875,-2.34375 1.171875,0 2.4609375,0.351563 1.2890623,0.332031 3.6718753,1.347656 1.347656,0.566406 2.011718,0.742188 0.683594,0.175781 1.367188,0.175781 1.269531,0 2.617187,-0.761719 1.367188,-0.761719 2.421875,-1.914062 v 4.140625 q -1.25,1.171875 -2.539062,1.699218 -1.269531,0.527344 -2.871094,0.527344 -1.171875,0 -2.246094,-0.273437 -1.054687,-0.273438 -3.378906,-1.308594 -2.3046873,-1.035156 -3.847656,-1.035156 -1.25,0 -2.3632813,0.546875 -1.09375,0.527343 -2.734375,2.109375 z"
|
||||||
|
style="font-family:Arial;-inkscape-font-specification:'Arial, Normal'"
|
||||||
|
id="path1704" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(16.213 5.975) scale(.72923)"
|
||||||
|
id="g896">
|
||||||
|
<circle
|
||||||
|
cx="36"
|
||||||
|
cy="36"
|
||||||
|
r="23"
|
||||||
|
fill="#fcea2b"
|
||||||
|
id="circle892" />
|
||||||
|
<path
|
||||||
|
fill="#3f3f3f"
|
||||||
|
d="M45.331 38.564c3.963 0 7.178-2.862 7.178-6.389 0-1.765.448-3.53-.852-4.685-1.299-1.156-4.345-1.704-6.326-1.704-2.357 0-5.143.143-6.451 1.704-.894 1.065-.727 3.253-.727 4.685 0 3.527 3.213 6.389 7.178 6.389zM25.738 38.564c3.963 0 7.179-2.862 7.179-6.389 0-1.765.447-3.53-.852-4.685-1.3-1.156-4.345-1.704-6.327-1.704-2.356 0-5.142.143-6.451 1.704-.893 1.065-.727 3.253-.727 4.685 0 3.527 3.213 6.389 7.178 6.389z"
|
||||||
|
id="path894" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
stroke="#000"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-miterlimit="10"
|
||||||
|
stroke-width="2"
|
||||||
|
transform="translate(16.213 5.975) scale(.72923)"
|
||||||
|
id="g908">
|
||||||
|
<circle
|
||||||
|
cx="35.887"
|
||||||
|
cy="36.056"
|
||||||
|
r="23"
|
||||||
|
id="circle898" />
|
||||||
|
<path
|
||||||
|
d="M45.702 44.862c-6.574 3.525-14.045 3.658-19.63 0M18.883 30.464s-.953 8.55 6.86 7.918c2.62-.212 7.817-.65 7.867-8.342.005-.698-.007-1.6-.81-2.63-1.065-1.367-3.572-1.971-9.945-1.422 0 0-3.446-.1-3.972 4.476z"
|
||||||
|
id="path900" />
|
||||||
|
<path
|
||||||
|
d="m18.953 29.931-.433-3.372 3.833-.527M52.741 30.464s.953 8.55-6.86 7.918c-2.62-.212-7.817-.65-7.868-8.342-.004-.698.008-1.6.811-2.63 1.065-1.367 3.572-1.971 9.945-1.422 0 0 3.446-.1 3.972 4.476z"
|
||||||
|
id="path902" />
|
||||||
|
<path
|
||||||
|
d="M31.505 26.416s4.124 2.534 8.657 0M33.536 31.318s2.202-3.751 4.536 0M52.664 29.933l.433-3.371-3.833-.528"
|
||||||
|
id="path904" />
|
||||||
|
<path
|
||||||
|
d="M33.955 30.027s1.795-3.75 3.699 0"
|
||||||
|
id="path906" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
66
default.nix
Normal file
66
default.nix
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# How to upgrade to a newer version
|
||||||
|
# - Comment `src.hash`
|
||||||
|
# - Change `version`
|
||||||
|
# - Run `$ nix build`
|
||||||
|
# This will fetch the source code
|
||||||
|
# Since `hash` is not provided, nix will stop building and throw an error:
|
||||||
|
#
|
||||||
|
# error: hash mismatch in fixed-output derivation '/nix/store/fghi3ljs6fhz8pwm3dh73j5fwjpq5wbz-source.drv':
|
||||||
|
# specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
||||||
|
# got: sha256-+uthA1w8CmZfW+WOK9wYGl2fUl/k10ufOc8W+Pwa9iQ=
|
||||||
|
# error: 1 dependencies of derivation '/nix/store/imcwsw5r74vkd8r0qa2k7cys2xfgraaz-tildefriends-0.0.18.drv' failed to build
|
||||||
|
#
|
||||||
|
# - Change `src.hash` to the new one, ie `sha256-+uthA1w8CmZfW+WOK9wYGl2fUl/k10ufOc8W+Pwa9iQ=`
|
||||||
|
# - Uncomment `src.hash`
|
||||||
|
# - Build again, this time it should work.
|
||||||
|
# - Check the release notes, if there's a new dependency or a change to `GNUMakefile`, this file might need to be changed too.
|
||||||
|
# For more details, contact tasiaiso @ https://tilde.club/~tasiaiso/
|
||||||
|
{
|
||||||
|
pkgs ? import <nixpkgs> {},
|
||||||
|
lib ? import <nixpkgs/lib>,
|
||||||
|
}:
|
||||||
|
pkgs.stdenv.mkDerivation rec {
|
||||||
|
pname = "tildefriends";
|
||||||
|
version = "0.0.24";
|
||||||
|
|
||||||
|
src = pkgs.fetchFromGitea {
|
||||||
|
domain = "dev.tildefriends.net";
|
||||||
|
owner = "cory";
|
||||||
|
repo = "tildefriends";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-XlmRr08UmScY//qxUEXHzagXHCFqARRYr3q8RK/jKFY=";
|
||||||
|
fetchSubmodules = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
glibc
|
||||||
|
gnumake
|
||||||
|
openssl
|
||||||
|
which
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
glibc
|
||||||
|
openssl
|
||||||
|
which
|
||||||
|
];
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
make -j $NIX_BUILD_CORES release
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp -r out/release/tildefriends $out/bin
|
||||||
|
'';
|
||||||
|
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
meta = with pkgs; {
|
||||||
|
homepage = "https://tildefriends.net";
|
||||||
|
description = "Make apps and friends from the comfort of your web browser.";
|
||||||
|
mainProgram = "tildefriends";
|
||||||
|
license = with lib.licenses; [mit];
|
||||||
|
platforms = lib.platforms.all;
|
||||||
|
};
|
||||||
|
}
|
1
deps/c-ares
vendored
Submodule
1
deps/c-ares
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit a57ff692eeab8d21c853dc1ddaf0164f517074c3
|
177
deps/c-ares_config/ares_build.h
vendored
Normal file
177
deps/c-ares_config/ares_build.h
vendored
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#ifndef __CARES_BUILD_H
|
||||||
|
#define __CARES_BUILD_H
|
||||||
|
/*
|
||||||
|
* Copyright (C) The c-ares project and its contributors
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CARES_STATICLIB
|
||||||
|
|
||||||
|
#ifdef CARES_HAVE_SYS_TYPES_H
|
||||||
|
# include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CARES_HAVE_SYS_SOCKET_H
|
||||||
|
# include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CARES_HAVE_SYS_SELECT_H
|
||||||
|
# include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#undef HAVE_REGISTERWAITFORSINGLEOBJECT
|
||||||
|
#define CARES_HAVE_WINSOCK2_H
|
||||||
|
#define CARES_HAVE_WINDOWS_H
|
||||||
|
#define CARES_HAVE_WS2TCPIP_H
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#define CARES_TYPEOF_ARES_SOCKLEN_T int
|
||||||
|
#define CARES_TYPEOF_ARES_SSIZE_T ssize_t
|
||||||
|
#else
|
||||||
|
#define CARES_TYPEOF_ARES_SOCKLEN_T socklen_t
|
||||||
|
#define CARES_TYPEOF_ARES_SSIZE_T ssize_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__HAIKU__)
|
||||||
|
#define GETSERVBYNAME_R_ARGS 6
|
||||||
|
#define GETSERVBYPORT_R_ARGS 6
|
||||||
|
#define HAVE_GETSERVBYNAME_R 1
|
||||||
|
#define HAVE_GETSERVBYPORT_R 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__HAIKU__)
|
||||||
|
#define HAVE_PIPE2 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__OpenBSD__) || defined(__HAIKU__)
|
||||||
|
#define GETSERVBYNAME_R_ARGS 4
|
||||||
|
#define GETSERVBYPORT_R_ARGS 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__HAIKU__)
|
||||||
|
#define HAVE_MALLOC_H 1
|
||||||
|
#define HAVE_EPOLL 1
|
||||||
|
#define HAVE_SYS_EPOLL_H 1
|
||||||
|
#define HAVE_SYS_RANDOM_H 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__WIN32)
|
||||||
|
#undef AC_APPLE_UNIVERSAL_BUILD
|
||||||
|
#undef ETC_INET
|
||||||
|
#define GETHOSTNAME_TYPE_ARG2 size_t
|
||||||
|
#define GETNAMEINFO_QUAL_ARG1
|
||||||
|
#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
|
||||||
|
#define GETNAMEINFO_TYPE_ARG2 socklen_t
|
||||||
|
#define GETNAMEINFO_TYPE_ARG46 socklen_t
|
||||||
|
#define GETNAMEINFO_TYPE_ARG7 int
|
||||||
|
#define HAVE_AF_INET6 1
|
||||||
|
#define HAVE_ARPA_INET_H 1
|
||||||
|
#define HAVE_ARPA_NAMESER_COMPAT_H 1
|
||||||
|
#define HAVE_ARPA_NAMESER_H 1
|
||||||
|
#define HAVE_ASSERT_H 1
|
||||||
|
#define HAVE_CLOCK_GETTIME_MONOTONIC 1
|
||||||
|
#define HAVE_CONNECT 1
|
||||||
|
#define HAVE_DLFCN_H 1
|
||||||
|
#define HAVE_ERRNO_H 1
|
||||||
|
#define HAVE_POLL_H 1
|
||||||
|
#define HAVE_POLL 1
|
||||||
|
#define HAVE_PIPE 1
|
||||||
|
#define HAVE_FCNTL 1
|
||||||
|
#define HAVE_FCNTL_H 1
|
||||||
|
#define HAVE_FCNTL_O_NONBLOCK 1
|
||||||
|
#define HAVE_FREEADDRINFO 1
|
||||||
|
#define HAVE_GETADDRINFO 1
|
||||||
|
#define HAVE_GETENV 1
|
||||||
|
#define HAVE_GETHOSTNAME 1
|
||||||
|
#define HAVE_GETNAMEINFO 1
|
||||||
|
#if !defined(__HAIKU__)
|
||||||
|
#define HAVE_GETRANDOM 1
|
||||||
|
#endif
|
||||||
|
#define HAVE_GETTIMEOFDAY 1
|
||||||
|
#define HAVE_IF_INDEXTONAME 1
|
||||||
|
#define HAVE_IF_NAMETOINDEX 1
|
||||||
|
#define HAVE_INET_NTOP 1
|
||||||
|
#define HAVE_INET_PTON 1
|
||||||
|
#define HAVE_INTTYPES_H 1
|
||||||
|
#define HAVE_IOCTL 1
|
||||||
|
#define HAVE_IOCTL_FIONBIO 1
|
||||||
|
#define HAVE_IOCTL_SIOCGIFADDR 1
|
||||||
|
#define HAVE_LIMITS_H 1
|
||||||
|
#define HAVE_LONGLONG 1
|
||||||
|
#define HAVE_MEMORY_H 1
|
||||||
|
#define HAVE_MSG_NOSIGNAL 1
|
||||||
|
#define HAVE_NETDB_H 1
|
||||||
|
#define HAVE_NETINET_IN_H 1
|
||||||
|
#define HAVE_NETINET_TCP_H 1
|
||||||
|
#define HAVE_NET_IF_H 1
|
||||||
|
#define HAVE_PF_INET6 1
|
||||||
|
#define HAVE_RECV 1
|
||||||
|
#define HAVE_RECVFROM 1
|
||||||
|
#define HAVE_SEND 1
|
||||||
|
#define HAVE_SETSOCKOPT 1
|
||||||
|
#define HAVE_SIGNAL_H 1
|
||||||
|
#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1
|
||||||
|
#define HAVE_SOCKET 1
|
||||||
|
#define HAVE_STDBOOL_H 1
|
||||||
|
#define HAVE_STDINT_H 1
|
||||||
|
#define HAVE_STDLIB_H 1
|
||||||
|
#define HAVE_STRCASECMP 1
|
||||||
|
#define HAVE_STRDUP 1
|
||||||
|
#define HAVE_STRINGS_H 1
|
||||||
|
#define HAVE_STRING_H 1
|
||||||
|
#define HAVE_STRNCASECMP 1
|
||||||
|
#define HAVE_STRUCT_ADDRINFO 1
|
||||||
|
#define HAVE_STRUCT_IN6_ADDR 1
|
||||||
|
#define HAVE_STRUCT_SOCKADDR_IN6 1
|
||||||
|
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||||
|
#define HAVE_STRUCT_TIMEVAL 1
|
||||||
|
#define HAVE_SYS_IOCTL_H 1
|
||||||
|
#define HAVE_SYS_PARAM_H 1
|
||||||
|
#define HAVE_SYS_SELECT_H 1
|
||||||
|
#define HAVE_SYS_SOCKET_H 1
|
||||||
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
#define HAVE_SYS_TIME_H 1
|
||||||
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
#define HAVE_SYS_UIO_H 1
|
||||||
|
#define HAVE_TIME_H 1
|
||||||
|
#define HAVE_IFADDRS_H 1
|
||||||
|
#define HAVE_UNISTD_H 1
|
||||||
|
#define HAVE_WRITEV 1
|
||||||
|
#if defined(__ANDROID__) || defined(__APPLE__) || defined(__OpenBSD__)
|
||||||
|
#define HAVE_ARC4RANDOM_BUF 1
|
||||||
|
#else
|
||||||
|
#undef HAVE_ARC4RANDOM_BUF
|
||||||
|
#endif
|
||||||
|
#define HAVE_GETIFADDRS 1
|
||||||
|
#define HAVE_STAT 1
|
||||||
|
#define CARES_RANDOM_FILE "/dev/urandom"
|
||||||
|
#define RECVFROM_QUAL_ARG5
|
||||||
|
#define RECVFROM_TYPE_ARG1 int
|
||||||
|
#define RECVFROM_TYPE_ARG2 void *
|
||||||
|
#define RECVFROM_TYPE_ARG2_IS_VOID 0
|
||||||
|
#define RECVFROM_TYPE_ARG3 size_t
|
||||||
|
#define RECVFROM_TYPE_ARG4 int
|
||||||
|
#define RECVFROM_TYPE_ARG5 struct sockaddr *
|
||||||
|
#define RECVFROM_TYPE_ARG5_IS_VOID 0
|
||||||
|
#define RECVFROM_TYPE_ARG6 socklen_t *
|
||||||
|
#define RECVFROM_TYPE_ARG6_IS_VOID 0
|
||||||
|
#define RECVFROM_TYPE_RETV ssize_t
|
||||||
|
#define RECV_TYPE_ARG1 int
|
||||||
|
#define RECV_TYPE_ARG2 void *
|
||||||
|
#define RECV_TYPE_ARG3 size_t
|
||||||
|
#define RECV_TYPE_ARG4 int
|
||||||
|
#define RECV_TYPE_RETV ssize_t
|
||||||
|
#define SEND_TYPE_ARG1 int
|
||||||
|
#define SEND_TYPE_ARG2 const void *
|
||||||
|
#define SEND_TYPE_ARG3 size_t
|
||||||
|
#define SEND_TYPE_ARG4 int
|
||||||
|
#define SEND_TYPE_RETV ssize_t
|
||||||
|
#undef USE_BLOCKING_SOCKETS
|
||||||
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
|
#define HAVE_PTHREAD_H 1
|
||||||
|
#define CARES_THREADS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __CARES_BUILD_H */
|
2
deps/codemirror/cm6.js
vendored
2
deps/codemirror/cm6.js
vendored
File diff suppressed because one or more lines are too long
452
deps/codemirror_src/package-lock.json
generated
vendored
452
deps/codemirror_src/package-lock.json
generated
vendored
@ -19,9 +19,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/autocomplete": {
|
"node_modules/@codemirror/autocomplete": {
|
||||||
"version": "6.15.0",
|
"version": "6.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.2.tgz",
|
||||||
"integrity": "sha512-G2Zm0mXznxz97JhaaOdoEG2cVupn4JjPaS4AcNvZzhOsnnG9YVN68VzfoUw6dYTsIxT6a/cmoFEN47KAWhXaOg==",
|
"integrity": "sha512-wJGylKtMFR/Ds6Gh01+OovXE/pncPiKZNNBKuC39pKnH+XK5d9+WsNqcrdxPjFPFTigRBqse0rfxw9UxrfyhPg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.0.0",
|
"@codemirror/language": "^6.0.0",
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
@ -36,32 +37,35 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/commands": {
|
"node_modules/@codemirror/commands": {
|
||||||
"version": "6.3.3",
|
"version": "6.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.7.1.tgz",
|
||||||
"integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==",
|
"integrity": "sha512-llTrboQYw5H4THfhN4U3qCnSZ1SOJ60ohhz+SzU0ADGtwlc533DtklQP0vSFaQuCPDn3BPpOd1GbbnUtwNjsrw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.0.0",
|
"@codemirror/language": "^6.0.0",
|
||||||
"@codemirror/state": "^6.4.0",
|
"@codemirror/state": "^6.4.0",
|
||||||
"@codemirror/view": "^6.0.0",
|
"@codemirror/view": "^6.27.0",
|
||||||
"@lezer/common": "^1.1.0"
|
"@lezer/common": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/lang-css": {
|
"node_modules/@codemirror/lang-css": {
|
||||||
"version": "6.2.1",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.0.tgz",
|
||||||
"integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==",
|
"integrity": "sha512-CyR4rUNG9OYcXDZwMPvJdtb6PHbBDKUc/6Na2BIwZ6dKab1JQqKa4di+RNRY9Myn7JB81vayKwJeQ7jEdmNVDA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.0.0",
|
"@codemirror/autocomplete": "^6.0.0",
|
||||||
"@codemirror/language": "^6.0.0",
|
"@codemirror/language": "^6.0.0",
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@lezer/common": "^1.0.2",
|
"@lezer/common": "^1.0.2",
|
||||||
"@lezer/css": "^1.0.0"
|
"@lezer/css": "^1.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/lang-html": {
|
"node_modules/@codemirror/lang-html": {
|
||||||
"version": "6.4.8",
|
"version": "6.4.9",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.8.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz",
|
||||||
"integrity": "sha512-tE2YK7wDlb9ZpAH6mpTPiYm6rhfdQKVDa5r9IwIFlwwgvVaKsCfuKKZoJGWsmMZIf3FQAuJ5CHMPLymOtg1hXw==",
|
"integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.0.0",
|
"@codemirror/autocomplete": "^6.0.0",
|
||||||
"@codemirror/lang-css": "^6.0.0",
|
"@codemirror/lang-css": "^6.0.0",
|
||||||
@ -78,6 +82,7 @@
|
|||||||
"version": "6.2.2",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
|
||||||
"integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
|
"integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.0.0",
|
"@codemirror/autocomplete": "^6.0.0",
|
||||||
"@codemirror/language": "^6.6.0",
|
"@codemirror/language": "^6.6.0",
|
||||||
@ -92,15 +97,17 @@
|
|||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
|
||||||
"integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==",
|
"integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.0.0",
|
"@codemirror/language": "^6.0.0",
|
||||||
"@lezer/json": "^1.0.0"
|
"@lezer/json": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/language": {
|
"node_modules/@codemirror/language": {
|
||||||
"version": "6.10.1",
|
"version": "6.10.3",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.3.tgz",
|
||||||
"integrity": "sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==",
|
"integrity": "sha512-kDqEU5sCP55Oabl6E7m5N+vZRoc0iWqgDVhEKifcHzPzjqCegcO4amfrYVL9PmPZpl4G0yjkpTpUO/Ui8CzO8A==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@codemirror/view": "^6.23.0",
|
"@codemirror/view": "^6.23.0",
|
||||||
@ -111,9 +118,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/lint": {
|
"node_modules/@codemirror/lint": {
|
||||||
"version": "6.5.0",
|
"version": "6.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.2.tgz",
|
||||||
"integrity": "sha512-+5YyicIaaAZKU8K43IQi8TBy6mF6giGeWAH7N96Z5LC30Wm5JMjqxOYIE9mxwMG1NbhT2mA3l9hA4uuKUM3E5g==",
|
"integrity": "sha512-PDFG5DjHxSEjOXk9TQYYVjZDqlZTFaDBfhQixHnQOEVDDNHUbEh/hstAjcQJaA6FQdZTD1hquXTK0rVBLADR1g==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@codemirror/view": "^6.0.0",
|
"@codemirror/view": "^6.0.0",
|
||||||
@ -121,9 +129,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/search": {
|
"node_modules/@codemirror/search": {
|
||||||
"version": "6.5.6",
|
"version": "6.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.7.tgz",
|
||||||
"integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==",
|
"integrity": "sha512-6+iLsXvITWKHYlkgHPCs/qiX4dNzn8N78YfhOFvPtPYCkuXqZq10rAfsUMhOq7O/1VjJqdXRflyExlfVcu/9VQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@codemirror/view": "^6.0.0",
|
"@codemirror/view": "^6.0.0",
|
||||||
@ -133,12 +142,14 @@
|
|||||||
"node_modules/@codemirror/state": {
|
"node_modules/@codemirror/state": {
|
||||||
"version": "6.4.1",
|
"version": "6.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
|
||||||
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
|
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/theme-one-dark": {
|
"node_modules/@codemirror/theme-one-dark": {
|
||||||
"version": "6.1.2",
|
"version": "6.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
|
||||||
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
|
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.0.0",
|
"@codemirror/language": "^6.0.0",
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
@ -147,9 +158,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/view": {
|
"node_modules/@codemirror/view": {
|
||||||
"version": "6.25.1",
|
"version": "6.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.25.1.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.34.2.tgz",
|
||||||
"integrity": "sha512-2LXLxsQnHDdfGzDvjzAwZh2ZviNJm7im6tGpa0IONIDnFd8RZ80D2SNi8PDi6YjKcMoMRK20v6OmKIdsrwsyoQ==",
|
"integrity": "sha512-d6n0WFvL970A9Z+l9N2dO+Hk9ev4hDYQzIx+B9tCyBP0W5wPEszi1rhuyFesNSkLZzXbQE5FPH7F/z/TMJfoPA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.4.0",
|
"@codemirror/state": "^6.4.0",
|
||||||
"style-mod": "^4.1.0",
|
"style-mod": "^4.1.0",
|
||||||
@ -161,6 +173,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||||
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/set-array": "^1.2.1",
|
"@jridgewell/set-array": "^1.2.1",
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||||
@ -175,6 +188,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
@ -184,6 +198,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
@ -193,36 +208,41 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||||
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/gen-mapping": "^0.3.5",
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
"@jridgewell/trace-mapping": "^0.3.25"
|
"@jridgewell/trace-mapping": "^0.3.25"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/sourcemap-codec": {
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
"version": "1.4.15",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
|
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
"version": "0.3.25",
|
"version": "0.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/resolve-uri": "^3.1.0",
|
"@jridgewell/resolve-uri": "^3.1.0",
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/common": {
|
"node_modules/@lezer/common": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
|
||||||
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ=="
|
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/css": {
|
"node_modules/@lezer/css": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.9",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.9.tgz",
|
||||||
"integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==",
|
"integrity": "sha512-TYwgljcDv+YrV0MZFFvYFQHCfGgbPMR6nuqLabBdmZoFH3EP1gvw8t0vae326Ne3PszQkbXfVBjCnf3ZVCr0bA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.2.0",
|
"@lezer/common": "^1.2.0",
|
||||||
"@lezer/highlight": "^1.0.0",
|
"@lezer/highlight": "^1.0.0",
|
||||||
@ -230,17 +250,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/highlight": {
|
"node_modules/@lezer/highlight": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
|
||||||
"integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==",
|
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.0.0"
|
"@lezer/common": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/html": {
|
"node_modules/@lezer/html": {
|
||||||
"version": "1.3.9",
|
"version": "1.3.10",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.9.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz",
|
||||||
"integrity": "sha512-MXxeCMPyrcemSLGaTQEZx0dBUH0i+RPl8RN5GwMAzo53nTsd/Unc/t5ZxACeQoyPUM5/GkPLRUs2WliOImzkRA==",
|
"integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.2.0",
|
"@lezer/common": "^1.2.0",
|
||||||
"@lezer/highlight": "^1.0.0",
|
"@lezer/highlight": "^1.0.0",
|
||||||
@ -248,9 +270,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/javascript": {
|
"node_modules/@lezer/javascript": {
|
||||||
"version": "1.4.13",
|
"version": "1.4.19",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.13.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.19.tgz",
|
||||||
"integrity": "sha512-5IBr8LIO3xJdJH1e9aj/ZNLE4LSbdsx25wFmGRAZsj2zSmwAYjx26JyU/BYOCpRQlu1jcv1z3vy4NB9+UkfRow==",
|
"integrity": "sha512-j44kbR1QL26l6dMunZ1uhKBFteVGLVCBGNUD2sUaMnic+rbTviVuoK0CD1l9FTW31EueWvFFswCKMH7Z+M3JRA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.2.0",
|
"@lezer/common": "^1.2.0",
|
||||||
"@lezer/highlight": "^1.1.3",
|
"@lezer/highlight": "^1.1.3",
|
||||||
@ -261,6 +284,7 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.2.tgz",
|
||||||
"integrity": "sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==",
|
"integrity": "sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.2.0",
|
"@lezer/common": "^1.2.0",
|
||||||
"@lezer/highlight": "^1.0.0",
|
"@lezer/highlight": "^1.0.0",
|
||||||
@ -268,22 +292,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/lr": {
|
"node_modules/@lezer/lr": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
|
||||||
"integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==",
|
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.0.0"
|
"@lezer/common": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/plugin-node-resolve": {
|
"node_modules/@rollup/plugin-node-resolve": {
|
||||||
"version": "15.2.3",
|
"version": "15.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz",
|
||||||
"integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==",
|
"integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rollup/pluginutils": "^5.0.1",
|
"@rollup/pluginutils": "^5.0.1",
|
||||||
"@types/resolve": "1.20.2",
|
"@types/resolve": "1.20.2",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"is-builtin-module": "^3.2.1",
|
|
||||||
"is-module": "^1.0.0",
|
"is-module": "^1.0.0",
|
||||||
"resolve": "^1.22.1"
|
"resolve": "^1.22.1"
|
||||||
},
|
},
|
||||||
@ -304,6 +329,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
|
||||||
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
|
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"serialize-javascript": "^6.0.1",
|
"serialize-javascript": "^6.0.1",
|
||||||
"smob": "^1.0.0",
|
"smob": "^1.0.0",
|
||||||
@ -322,13 +348,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/pluginutils": {
|
"node_modules/@rollup/pluginutils": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz",
|
||||||
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
|
"integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "^1.0.0",
|
"@types/estree": "^1.0.0",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"picomatch": "^2.3.1"
|
"picomatch": "^4.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@ -343,176 +370,257 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz",
|
||||||
"integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==",
|
"integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz",
|
||||||
"integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==",
|
"integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz",
|
||||||
"integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==",
|
"integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz",
|
||||||
"integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==",
|
"integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||||
|
"version": "4.24.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz",
|
||||||
|
"integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||||
|
"version": "4.24.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz",
|
||||||
|
"integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz",
|
||||||
"integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==",
|
"integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
|
"version": "4.24.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz",
|
||||||
|
"integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz",
|
||||||
"integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==",
|
"integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz",
|
||||||
"integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==",
|
"integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||||
|
"version": "4.24.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz",
|
||||||
|
"integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==",
|
||||||
|
"cpu": [
|
||||||
|
"ppc64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz",
|
||||||
"integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==",
|
"integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
|
"version": "4.24.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz",
|
||||||
|
"integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==",
|
||||||
|
"cpu": [
|
||||||
|
"s390x"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz",
|
||||||
"integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==",
|
"integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz",
|
||||||
"integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==",
|
"integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz",
|
||||||
"integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==",
|
"integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz",
|
||||||
"integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==",
|
"integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz",
|
||||||
"integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==",
|
"integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/resolve": {
|
"node_modules/@types/resolve": {
|
||||||
"version": "1.20.2",
|
"version": "1.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
|
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.11.3",
|
"version": "8.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||||
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
|
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@ -524,23 +632,14 @@
|
|||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
},
|
"license": "MIT"
|
||||||
"node_modules/builtin-modules": {
|
|
||||||
"version": "3.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
|
|
||||||
"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"node_modules/codemirror": {
|
"node_modules/codemirror": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
|
||||||
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
|
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.0.0",
|
"@codemirror/autocomplete": "^6.0.0",
|
||||||
"@codemirror/commands": "^6.0.0",
|
"@codemirror/commands": "^6.0.0",
|
||||||
@ -555,17 +654,20 @@
|
|||||||
"version": "2.20.3",
|
"version": "2.20.3",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/crelt": {
|
"node_modules/crelt": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
|
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/deepmerge": {
|
"node_modules/deepmerge": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -573,13 +675,15 @@
|
|||||||
"node_modules/estree-walker": {
|
"node_modules/estree-walker": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
@ -592,6 +696,7 @@
|
|||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||||
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
@ -600,6 +705,7 @@
|
|||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"function-bind": "^1.1.2"
|
"function-bind": "^1.1.2"
|
||||||
},
|
},
|
||||||
@ -607,26 +713,16 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-builtin-module": {
|
"node_modules/is-core-module": {
|
||||||
"version": "3.2.1",
|
"version": "2.15.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
|
||||||
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
|
"integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"builtin-modules": "^3.3.0"
|
"hasown": "^2.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">= 0.4"
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-core-module": {
|
|
||||||
"version": "2.13.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
|
|
||||||
"integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
|
|
||||||
"dependencies": {
|
|
||||||
"hasown": "^2.0.0"
|
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
@ -635,19 +731,22 @@
|
|||||||
"node_modules/is-module": {
|
"node_modules/is-module": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="
|
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/path-parse": {
|
"node_modules/path-parse": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.3.1",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.6"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
@ -658,6 +757,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "^5.1.0"
|
"safe-buffer": "^5.1.0"
|
||||||
}
|
}
|
||||||
@ -666,6 +766,7 @@
|
|||||||
"version": "1.22.8",
|
"version": "1.22.8",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
||||||
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
|
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-core-module": "^2.13.0",
|
"is-core-module": "^2.13.0",
|
||||||
"path-parse": "^1.0.7",
|
"path-parse": "^1.0.7",
|
||||||
@ -679,11 +780,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.13.0",
|
"version": "4.24.4",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz",
|
||||||
"integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==",
|
"integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.5"
|
"@types/estree": "1.0.6"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"rollup": "dist/bin/rollup"
|
"rollup": "dist/bin/rollup"
|
||||||
@ -693,19 +795,24 @@
|
|||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.13.0",
|
"@rollup/rollup-android-arm-eabi": "4.24.4",
|
||||||
"@rollup/rollup-android-arm64": "4.13.0",
|
"@rollup/rollup-android-arm64": "4.24.4",
|
||||||
"@rollup/rollup-darwin-arm64": "4.13.0",
|
"@rollup/rollup-darwin-arm64": "4.24.4",
|
||||||
"@rollup/rollup-darwin-x64": "4.13.0",
|
"@rollup/rollup-darwin-x64": "4.24.4",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.13.0",
|
"@rollup/rollup-freebsd-arm64": "4.24.4",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.13.0",
|
"@rollup/rollup-freebsd-x64": "4.24.4",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.13.0",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.24.4",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.13.0",
|
"@rollup/rollup-linux-arm-musleabihf": "4.24.4",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.13.0",
|
"@rollup/rollup-linux-arm64-gnu": "4.24.4",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.13.0",
|
"@rollup/rollup-linux-arm64-musl": "4.24.4",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.13.0",
|
"@rollup/rollup-linux-powerpc64le-gnu": "4.24.4",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.13.0",
|
"@rollup/rollup-linux-riscv64-gnu": "4.24.4",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.13.0",
|
"@rollup/rollup-linux-s390x-gnu": "4.24.4",
|
||||||
|
"@rollup/rollup-linux-x64-gnu": "4.24.4",
|
||||||
|
"@rollup/rollup-linux-x64-musl": "4.24.4",
|
||||||
|
"@rollup/rollup-win32-arm64-msvc": "4.24.4",
|
||||||
|
"@rollup/rollup-win32-ia32-msvc": "4.24.4",
|
||||||
|
"@rollup/rollup-win32-x64-msvc": "4.24.4",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -727,28 +834,32 @@
|
|||||||
"type": "consulting",
|
"type": "consulting",
|
||||||
"url": "https://feross.org/support"
|
"url": "https://feross.org/support"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/serialize-javascript": {
|
"node_modules/serialize-javascript": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"randombytes": "^2.1.0"
|
"randombytes": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/smob": {
|
"node_modules/smob": {
|
||||||
"version": "1.4.1",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
|
||||||
"integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==",
|
"integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -758,6 +869,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer-from": "^1.0.0",
|
"buffer-from": "^1.0.0",
|
||||||
"source-map": "^0.6.0"
|
"source-map": "^0.6.0"
|
||||||
@ -766,12 +878,14 @@
|
|||||||
"node_modules/style-mod": {
|
"node_modules/style-mod": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
||||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
|
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/supports-preserve-symlinks-flag": {
|
"node_modules/supports-preserve-symlinks-flag": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
},
|
},
|
||||||
@ -780,10 +894,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/terser": {
|
"node_modules/terser": {
|
||||||
"version": "5.29.1",
|
"version": "5.36.0",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz",
|
||||||
"integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==",
|
"integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/source-map": "^0.3.3",
|
"@jridgewell/source-map": "^0.3.3",
|
||||||
"acorn": "^8.8.2",
|
"acorn": "^8.8.2",
|
||||||
@ -800,7 +915,8 @@
|
|||||||
"node_modules/w3c-keyname": {
|
"node_modules/w3c-keyname": {
|
||||||
"version": "2.2.8",
|
"version": "2.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
|
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||||
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
deps/crypt_blowfish
vendored
Submodule
1
deps/crypt_blowfish
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 3354bb81eea489e972b0a7c63231514ab34f73a0
|
29
deps/crypt_blowfish/LINKS
vendored
29
deps/crypt_blowfish/LINKS
vendored
@ -1,29 +0,0 @@
|
|||||||
New versions of this package (crypt_blowfish):
|
|
||||||
|
|
||||||
http://www.openwall.com/crypt/
|
|
||||||
|
|
||||||
A paper on the algorithm that explains its design decisions:
|
|
||||||
|
|
||||||
http://www.usenix.org/events/usenix99/provos.html
|
|
||||||
|
|
||||||
Unix Seventh Edition Manual, Volume 2: the password scheme (1978):
|
|
||||||
|
|
||||||
http://plan9.bell-labs.com/7thEdMan/vol2/password
|
|
||||||
|
|
||||||
The Openwall GNU/*/Linux (Owl) tcb suite implementing the alternative
|
|
||||||
password shadowing scheme. This includes a PAM module which
|
|
||||||
supersedes pam_unix and uses the password hashing framework provided
|
|
||||||
with crypt_blowfish when setting new passwords.
|
|
||||||
|
|
||||||
http://www.openwall.com/tcb/
|
|
||||||
|
|
||||||
pam_passwdqc, a password strength checking and policy enforcement
|
|
||||||
module for PAM-aware password changing programs:
|
|
||||||
|
|
||||||
http://www.openwall.com/passwdqc/
|
|
||||||
|
|
||||||
John the Ripper password cracker:
|
|
||||||
|
|
||||||
http://www.openwall.com/john/
|
|
||||||
|
|
||||||
$Owl: Owl/packages/glibc/crypt_blowfish/LINKS,v 1.4 2005/11/16 13:09:47 solar Exp $
|
|
77
deps/crypt_blowfish/Makefile
vendored
77
deps/crypt_blowfish/Makefile
vendored
@ -1,77 +0,0 @@
|
|||||||
#
|
|
||||||
# Written and revised by Solar Designer <solar at openwall.com> in 2000-2011.
|
|
||||||
# No copyright is claimed, and the software is hereby placed in the public
|
|
||||||
# domain. In case this attempt to disclaim copyright and place the software
|
|
||||||
# in the public domain is deemed null and void, then the software is
|
|
||||||
# Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
|
||||||
# general public under the following terms:
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted.
|
|
||||||
#
|
|
||||||
# There's ABSOLUTELY NO WARRANTY, express or implied.
|
|
||||||
#
|
|
||||||
# See crypt_blowfish.c for more information.
|
|
||||||
#
|
|
||||||
|
|
||||||
CC = gcc
|
|
||||||
AS = $(CC)
|
|
||||||
LD = $(CC)
|
|
||||||
RM = rm -f
|
|
||||||
CFLAGS = -W -Wall -Wbad-function-cast -Wcast-align -Wcast-qual -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wundef -Wpointer-arith -O2 -fomit-frame-pointer -funroll-loops
|
|
||||||
ASFLAGS = -c
|
|
||||||
LDFLAGS = -s
|
|
||||||
|
|
||||||
BLOWFISH_OBJS = \
|
|
||||||
crypt_blowfish.o x86.o
|
|
||||||
|
|
||||||
CRYPT_OBJS = \
|
|
||||||
$(BLOWFISH_OBJS) crypt_gensalt.o wrapper.o
|
|
||||||
|
|
||||||
TEST_OBJS = \
|
|
||||||
$(BLOWFISH_OBJS) crypt_gensalt.o crypt_test.o
|
|
||||||
|
|
||||||
TEST_THREADS_OBJS = \
|
|
||||||
$(BLOWFISH_OBJS) crypt_gensalt.o crypt_test_threads.o
|
|
||||||
|
|
||||||
EXTRA_MANS = \
|
|
||||||
crypt_r.3 crypt_rn.3 crypt_ra.3 \
|
|
||||||
crypt_gensalt.3 crypt_gensalt_rn.3 crypt_gensalt_ra.3
|
|
||||||
|
|
||||||
all: $(CRYPT_OBJS) man
|
|
||||||
|
|
||||||
check: crypt_test
|
|
||||||
./crypt_test
|
|
||||||
|
|
||||||
crypt_test: $(TEST_OBJS)
|
|
||||||
$(LD) $(LDFLAGS) $(TEST_OBJS) -o $@
|
|
||||||
|
|
||||||
crypt_test.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h
|
|
||||||
$(CC) -c $(CFLAGS) wrapper.c -DTEST -o $@
|
|
||||||
|
|
||||||
check_threads: crypt_test_threads
|
|
||||||
./crypt_test_threads
|
|
||||||
|
|
||||||
crypt_test_threads: $(TEST_THREADS_OBJS)
|
|
||||||
$(LD) $(LDFLAGS) $(TEST_THREADS_OBJS) -lpthread -o $@
|
|
||||||
|
|
||||||
crypt_test_threads.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h
|
|
||||||
$(CC) -c $(CFLAGS) wrapper.c -DTEST -DTEST_THREADS=4 -o $@
|
|
||||||
|
|
||||||
man: $(EXTRA_MANS)
|
|
||||||
|
|
||||||
$(EXTRA_MANS):
|
|
||||||
echo '.so man3/crypt.3' > $@
|
|
||||||
|
|
||||||
crypt_blowfish.o: crypt_blowfish.h
|
|
||||||
crypt_gensalt.o: crypt_gensalt.h
|
|
||||||
wrapper.o: crypt.h ow-crypt.h crypt_blowfish.h crypt_gensalt.h
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) -c $(CFLAGS) $*.c
|
|
||||||
|
|
||||||
.S.o:
|
|
||||||
$(AS) $(ASFLAGS) $*.S
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) crypt_test crypt_test_threads *.o $(EXTRA_MANS) core
|
|
30
deps/crypt_blowfish/PERFORMANCE
vendored
30
deps/crypt_blowfish/PERFORMANCE
vendored
@ -1,30 +0,0 @@
|
|||||||
These numbers are for 32 iterations ("$2a$05"):
|
|
||||||
|
|
||||||
OpenBSD 3.0 bcrypt(*) crypt_blowfish 0.4.4
|
|
||||||
Pentium III, 840 MHz 99 c/s 121 c/s (+22%)
|
|
||||||
Alpha 21164PC, 533 MHz 55.5 c/s 76.9 c/s (+38%)
|
|
||||||
UltraSparc IIi, 400 MHz 49.9 c/s 52.5 c/s (+5%)
|
|
||||||
Pentium, 120 MHz 8.8 c/s 20.1 c/s (+128%)
|
|
||||||
PA-RISC 7100LC, 80 MHz 8.5 c/s 16.3 c/s (+92%)
|
|
||||||
|
|
||||||
(*) built with -fomit-frame-pointer -funroll-loops, which I don't
|
|
||||||
think happens for libcrypt.
|
|
||||||
|
|
||||||
Starting with version 1.1 released in June 2011, default builds of
|
|
||||||
crypt_blowfish invoke a quick self-test on every hash computation.
|
|
||||||
This has roughly a 4.8% performance impact at "$2a$05", but only a 0.6%
|
|
||||||
impact at a more typical setting of "$2a$08".
|
|
||||||
|
|
||||||
The large speedup for the original Pentium is due to the assembly
|
|
||||||
code and the weird optimizations this processor requires.
|
|
||||||
|
|
||||||
The numbers for password cracking are 2 to 10% higher than those for
|
|
||||||
crypt_blowfish as certain things may be done out of the loop and the
|
|
||||||
code doesn't need to be reentrant.
|
|
||||||
|
|
||||||
Recent versions of John the Ripper (1.6.25-dev and newer) achieve an
|
|
||||||
additional 15% speedup on the Pentium Pro family of processors (which
|
|
||||||
includes Pentium III) with a separate version of the assembly code and
|
|
||||||
run-time CPU detection.
|
|
||||||
|
|
||||||
$Owl: Owl/packages/glibc/crypt_blowfish/PERFORMANCE,v 1.6 2011/06/21 12:09:20 solar Exp $
|
|
68
deps/crypt_blowfish/README
vendored
68
deps/crypt_blowfish/README
vendored
@ -1,68 +0,0 @@
|
|||||||
This is an implementation of a password hashing method, provided via the
|
|
||||||
crypt(3) and a reentrant interface. It is fully compatible with
|
|
||||||
OpenBSD's bcrypt.c for prefix "$2b$", originally by Niels Provos and
|
|
||||||
David Mazieres. (Please refer to the included crypt(3) man page for
|
|
||||||
information on minor compatibility issues for other bcrypt prefixes.)
|
|
||||||
|
|
||||||
I've placed this code in the public domain, with fallback to a
|
|
||||||
permissive license. Please see the comment in crypt_blowfish.c for
|
|
||||||
more information.
|
|
||||||
|
|
||||||
You can use the provided routines in your own packages, or link them
|
|
||||||
into a C library. I've provided hooks for linking into GNU libc, but
|
|
||||||
it shouldn't be too hard to get this into another C library. Note
|
|
||||||
that simply adding this code into your libc is probably not enough to
|
|
||||||
make your system use the new password hashing algorithm. Changes to
|
|
||||||
passwd(1), PAM modules, or whatever else your system uses will likely
|
|
||||||
be needed as well. These are not a part of this package, but see
|
|
||||||
LINKS for a pointer to our tcb suite.
|
|
||||||
|
|
||||||
Instructions on using the routines in one of the two common ways are
|
|
||||||
given below. It is recommended that you test the routines on your
|
|
||||||
system before you start. Type "make check" or "make check_threads"
|
|
||||||
(if you have the POSIX threads library), then "make clean".
|
|
||||||
|
|
||||||
|
|
||||||
1. Using the routines in your programs.
|
|
||||||
|
|
||||||
The available interfaces are in ow-crypt.h, and this is the file you
|
|
||||||
should include. You won't need crypt.h. When linking, add all of the
|
|
||||||
C files and x86.S (you can compile and link it even on a non-x86, it
|
|
||||||
will produce no code in this case).
|
|
||||||
|
|
||||||
|
|
||||||
2. Building the routines into GNU C library.
|
|
||||||
|
|
||||||
For versions 2.13 and 2.14 (and likely other nearby ones), extract the
|
|
||||||
library sources as usual. Apply the patch for glibc 2.14 provided in
|
|
||||||
this package. Enter crypt/ and rename crypt.h to gnu-crypt.h within
|
|
||||||
that directory. Copy the C sources, header, and assembly (x86.S) files
|
|
||||||
from this package in there as well (but be sure you don't overwrite the
|
|
||||||
Makefile). Configure, build, and install the library as usual.
|
|
||||||
|
|
||||||
For versions 2.2 to 2.3.6 (and likely also for some newer ones),
|
|
||||||
extract the library sources and maybe its optional add-ons as usual.
|
|
||||||
Apply the patch for glibc 2.3.6 provided in this package. Enter
|
|
||||||
crypt/ and rename crypt.h to gnu-crypt.h within that directory. Copy
|
|
||||||
the C sources, header, and assembly (x86.S) files from this package in
|
|
||||||
there as well (but be sure you don't overwrite the Makefile).
|
|
||||||
Configure, build, and install the library as usual.
|
|
||||||
|
|
||||||
For versions 2.1 to 2.1.3, extract the library sources and the crypt
|
|
||||||
and linuxthreads add-ons as usual. Apply the patch for glibc 2.1.3
|
|
||||||
provided in this package. Enter crypt/sysdeps/unix/, and rename
|
|
||||||
crypt.h to gnu-crypt.h within that directory. Copy C sources, header,
|
|
||||||
and assembly (x86.S) files from this package in there as well (but be
|
|
||||||
sure you don't overwrite the Makefile). Configure, build, and install
|
|
||||||
the library as usual.
|
|
||||||
|
|
||||||
Programs that want to use the provided interfaces will need to include
|
|
||||||
crypt.h (but not ow-crypt.h directly). By default, prototypes for the
|
|
||||||
new routines aren't defined (but the extra functionality of crypt(3)
|
|
||||||
is indeed available). You need to define _OW_SOURCE to obtain the new
|
|
||||||
routines as well.
|
|
||||||
|
|
||||||
--
|
|
||||||
Solar Designer <solar at openwall.com>
|
|
||||||
|
|
||||||
$Owl: Owl/packages/glibc/crypt_blowfish/README,v 1.10 2014/07/07 15:19:04 solar Exp $
|
|
575
deps/crypt_blowfish/crypt.3
vendored
575
deps/crypt_blowfish/crypt.3
vendored
@ -1,575 +0,0 @@
|
|||||||
.\" Written and revised by Solar Designer <solar at openwall.com> in 2000-2011.
|
|
||||||
.\" No copyright is claimed, and this man page is hereby placed in the public
|
|
||||||
.\" domain. In case this attempt to disclaim copyright and place the man page
|
|
||||||
.\" in the public domain is deemed null and void, then the man page is
|
|
||||||
.\" Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
|
||||||
.\" general public under the following terms:
|
|
||||||
.\"
|
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
|
||||||
.\" modification, are permitted.
|
|
||||||
.\"
|
|
||||||
.\" There's ABSOLUTELY NO WARRANTY, express or implied.
|
|
||||||
.\"
|
|
||||||
.\" This manual page in its current form is intended for use on systems
|
|
||||||
.\" based on the GNU C Library with crypt_blowfish patched into libcrypt.
|
|
||||||
.\"
|
|
||||||
.TH CRYPT 3 "July 7, 2014" "Openwall Project" "Library functions"
|
|
||||||
.ad l
|
|
||||||
.\" No macros in NAME to keep makewhatis happy.
|
|
||||||
.SH NAME
|
|
||||||
\fBcrypt\fR, \fBcrypt_r\fR, \fBcrypt_rn\fR, \fBcrypt_ra\fR,
|
|
||||||
\fBcrypt_gensalt\fR, \fBcrypt_gensalt_rn\fR, \fBcrypt_gensalt_ra\fR
|
|
||||||
\- password hashing
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B #define _XOPEN_SOURCE
|
|
||||||
.br
|
|
||||||
.B #include <unistd.h>
|
|
||||||
.sp
|
|
||||||
.in +8
|
|
||||||
.ti -8
|
|
||||||
.BI "char *crypt(const char *" key ", const char *" setting );
|
|
||||||
.in -8
|
|
||||||
.sp
|
|
||||||
.B #define _GNU_SOURCE
|
|
||||||
.br
|
|
||||||
.B #include <crypt.h>
|
|
||||||
.sp
|
|
||||||
.in +8
|
|
||||||
.ti -8
|
|
||||||
.BI "char *crypt_r(const char *" key ", const char *" setting ", struct crypt_data *" data );
|
|
||||||
.in -8
|
|
||||||
.sp
|
|
||||||
.B #define _OW_SOURCE
|
|
||||||
.br
|
|
||||||
.B #include <crypt.h>
|
|
||||||
.sp
|
|
||||||
.in +8
|
|
||||||
.ti -8
|
|
||||||
.BI "char *crypt_rn(const char *" key ", const char *" setting ", void *" data ", int " size );
|
|
||||||
.ti -8
|
|
||||||
.BI "char *crypt_ra(const char *" key ", const char *" setting ", void **" data ", int *" size );
|
|
||||||
.ti -8
|
|
||||||
.BI "char *crypt_gensalt(const char *" prefix ", unsigned long " count ", const char *" input ", int " size );
|
|
||||||
.ti -8
|
|
||||||
.BI "char *crypt_gensalt_rn(const char *" prefix ", unsigned long " count ", const char *" input ", int " size ", char *" output ", int " output_size );
|
|
||||||
.ti -8
|
|
||||||
.BI "char *crypt_gensalt_ra(const char *" prefix ", unsigned long " count ", const char *" input ", int " size );
|
|
||||||
.ad b
|
|
||||||
.de crypt
|
|
||||||
.BR crypt ,
|
|
||||||
.BR crypt_r ,
|
|
||||||
.BR crypt_rn ", \\$1"
|
|
||||||
.ie "\\$2"" .B crypt_ra
|
|
||||||
.el .BR crypt_ra "\\$2"
|
|
||||||
..
|
|
||||||
.de crypt_gensalt
|
|
||||||
.BR crypt_gensalt ,
|
|
||||||
.BR crypt_gensalt_rn ", \\$1"
|
|
||||||
.ie "\\$2"" .B crypt_gensalt_ra
|
|
||||||
.el .BR crypt_gensalt_ra "\\$2"
|
|
||||||
..
|
|
||||||
.SH DESCRIPTION
|
|
||||||
The
|
|
||||||
.crypt and
|
|
||||||
functions calculate a cryptographic hash function of
|
|
||||||
.I key
|
|
||||||
with one of a number of supported methods as requested with
|
|
||||||
.IR setting ,
|
|
||||||
which is also used to pass a salt and possibly other parameters to
|
|
||||||
the chosen method.
|
|
||||||
The hashing methods are explained below.
|
|
||||||
.PP
|
|
||||||
Unlike
|
|
||||||
.BR crypt ,
|
|
||||||
the functions
|
|
||||||
.BR crypt_r ,
|
|
||||||
.BR crypt_rn " and"
|
|
||||||
.B crypt_ra
|
|
||||||
are reentrant.
|
|
||||||
They place their result and possibly their private data in a
|
|
||||||
.I data
|
|
||||||
area of
|
|
||||||
.I size
|
|
||||||
bytes as passed to them by an application and/or in memory they
|
|
||||||
allocate dynamically. Some hashing algorithms may use the data area to
|
|
||||||
cache precomputed intermediate values across calls. Thus, applications
|
|
||||||
must properly initialize the data area before its first use.
|
|
||||||
.B crypt_r
|
|
||||||
requires that only
|
|
||||||
.I data->initialized
|
|
||||||
be reset to zero;
|
|
||||||
.BR crypt_rn " and " crypt_ra
|
|
||||||
require that either the entire data area is zeroed or, in the case of
|
|
||||||
.BR crypt_ra ,
|
|
||||||
.I *data
|
|
||||||
is NULL. When called with a NULL
|
|
||||||
.I *data
|
|
||||||
or insufficient
|
|
||||||
.I *size
|
|
||||||
for the requested hashing algorithm,
|
|
||||||
.B crypt_ra
|
|
||||||
uses
|
|
||||||
.BR realloc (3)
|
|
||||||
to allocate the required amount of memory dynamically. Thus,
|
|
||||||
.B crypt_ra
|
|
||||||
has the additional requirement that
|
|
||||||
.IR *data ,
|
|
||||||
when non-NULL, must point to an area allocated either with a previous
|
|
||||||
call to
|
|
||||||
.B crypt_ra
|
|
||||||
or with a
|
|
||||||
.BR malloc (3)
|
|
||||||
family call.
|
|
||||||
The memory allocated by
|
|
||||||
.B crypt_ra
|
|
||||||
should be freed with
|
|
||||||
.BR free "(3)."
|
|
||||||
.PP
|
|
||||||
The
|
|
||||||
.crypt_gensalt and
|
|
||||||
functions compile a string for use as
|
|
||||||
.I setting
|
|
||||||
\- with the given
|
|
||||||
.I prefix
|
|
||||||
(used to choose a hashing method), the iteration
|
|
||||||
.I count
|
|
||||||
(if supported by the chosen method) and up to
|
|
||||||
.I size
|
|
||||||
cryptographically random
|
|
||||||
.I input
|
|
||||||
bytes for use as the actual salt.
|
|
||||||
If
|
|
||||||
.I count
|
|
||||||
is 0, a low default will be picked.
|
|
||||||
The random bytes may be obtained from
|
|
||||||
.BR /dev/urandom .
|
|
||||||
Unlike
|
|
||||||
.BR crypt_gensalt ,
|
|
||||||
the functions
|
|
||||||
.BR crypt_gensalt_rn " and " crypt_gensalt_ra
|
|
||||||
are reentrant.
|
|
||||||
.B crypt_gensalt_rn
|
|
||||||
places its result in the
|
|
||||||
.I output
|
|
||||||
buffer of
|
|
||||||
.I output_size
|
|
||||||
bytes.
|
|
||||||
.B crypt_gensalt_ra
|
|
||||||
allocates memory for its result dynamically. The memory should be
|
|
||||||
freed with
|
|
||||||
.BR free "(3)."
|
|
||||||
.SH RETURN VALUE
|
|
||||||
Upon successful completion, the functions
|
|
||||||
.crypt and
|
|
||||||
return a pointer to a string containing the setting that was actually used
|
|
||||||
and a printable encoding of the hash function value.
|
|
||||||
The entire string is directly usable as
|
|
||||||
.I setting
|
|
||||||
with other calls to
|
|
||||||
.crypt and
|
|
||||||
and as
|
|
||||||
.I prefix
|
|
||||||
with calls to
|
|
||||||
.crypt_gensalt and .
|
|
||||||
.PP
|
|
||||||
The behavior of
|
|
||||||
.B crypt
|
|
||||||
on errors isn't well standardized. Some implementations simply can't fail
|
|
||||||
(unless the process dies, in which case they obviously can't return),
|
|
||||||
others return NULL or a fixed string. Most implementations don't set
|
|
||||||
.IR errno ,
|
|
||||||
but some do. SUSv2 specifies only returning NULL and setting
|
|
||||||
.I errno
|
|
||||||
as a valid behavior, and defines only one possible error
|
|
||||||
.RB "(" ENOSYS ,
|
|
||||||
"The functionality is not supported on this implementation.")
|
|
||||||
Unfortunately, most existing applications aren't prepared to handle
|
|
||||||
NULL returns from
|
|
||||||
.BR crypt .
|
|
||||||
The description below corresponds to this implementation of
|
|
||||||
.BR crypt " and " crypt_r
|
|
||||||
only, and to
|
|
||||||
.BR crypt_rn " and " crypt_ra .
|
|
||||||
The behavior may change to match standards, other implementations or
|
|
||||||
existing applications.
|
|
||||||
.PP
|
|
||||||
.BR crypt " and " crypt_r
|
|
||||||
may only fail (and return) when passed an invalid or unsupported
|
|
||||||
.IR setting ,
|
|
||||||
in which case they return a pointer to a magic string that is
|
|
||||||
shorter than 13 characters and is guaranteed to differ from
|
|
||||||
.IR setting .
|
|
||||||
This behavior is safe for older applications which assume that
|
|
||||||
.B crypt
|
|
||||||
can't fail, when both setting new passwords and authenticating against
|
|
||||||
existing password hashes.
|
|
||||||
.BR crypt_rn " and " crypt_ra
|
|
||||||
return NULL to indicate failure. All four functions set
|
|
||||||
.I errno
|
|
||||||
when they fail.
|
|
||||||
.PP
|
|
||||||
The functions
|
|
||||||
.crypt_gensalt and
|
|
||||||
return a pointer to the compiled string for
|
|
||||||
.IR setting ,
|
|
||||||
or NULL on error in which case
|
|
||||||
.I errno
|
|
||||||
is set.
|
|
||||||
.SH ERRORS
|
|
||||||
.TP
|
|
||||||
.B EINVAL
|
|
||||||
.crypt "" :
|
|
||||||
.I setting
|
|
||||||
is invalid or not supported by this implementation;
|
|
||||||
.sp
|
|
||||||
.crypt_gensalt "" :
|
|
||||||
.I prefix
|
|
||||||
is invalid or not supported by this implementation;
|
|
||||||
.I count
|
|
||||||
is invalid for the requested
|
|
||||||
.IR prefix ;
|
|
||||||
the input
|
|
||||||
.I size
|
|
||||||
is insufficient for the smallest valid salt with the requested
|
|
||||||
.IR prefix ;
|
|
||||||
.I input
|
|
||||||
is NULL.
|
|
||||||
.TP
|
|
||||||
.B ERANGE
|
|
||||||
.BR crypt_rn :
|
|
||||||
the provided data area
|
|
||||||
.I size
|
|
||||||
is insufficient for the requested hashing algorithm;
|
|
||||||
.sp
|
|
||||||
.BR crypt_gensalt_rn :
|
|
||||||
.I output_size
|
|
||||||
is too small to hold the compiled
|
|
||||||
.I setting
|
|
||||||
string.
|
|
||||||
.TP
|
|
||||||
.B ENOMEM
|
|
||||||
.B crypt
|
|
||||||
(original glibc only):
|
|
||||||
failed to allocate memory for the output buffer (which subsequent calls
|
|
||||||
would re-use);
|
|
||||||
.sp
|
|
||||||
.BR crypt_ra :
|
|
||||||
.I *data
|
|
||||||
is NULL or
|
|
||||||
.I *size
|
|
||||||
is insufficient for the requested hashing algorithm and
|
|
||||||
.BR realloc (3)
|
|
||||||
failed;
|
|
||||||
.sp
|
|
||||||
.BR crypt_gensalt_ra :
|
|
||||||
failed to allocate memory for the compiled
|
|
||||||
.I setting
|
|
||||||
string.
|
|
||||||
.TP
|
|
||||||
.B ENOSYS
|
|
||||||
.B crypt
|
|
||||||
(SUSv2):
|
|
||||||
the functionality is not supported on this implementation;
|
|
||||||
.sp
|
|
||||||
.BR crypt ,
|
|
||||||
.B crypt_r
|
|
||||||
(glibc 2.0 to 2.0.1 only):
|
|
||||||
.de no-crypt-add-on
|
|
||||||
the crypt add-on is not compiled in and
|
|
||||||
.I setting
|
|
||||||
requests something other than the MD5-based algorithm.
|
|
||||||
..
|
|
||||||
.no-crypt-add-on
|
|
||||||
.TP
|
|
||||||
.B EOPNOTSUPP
|
|
||||||
.BR crypt ,
|
|
||||||
.B crypt_r
|
|
||||||
(glibc 2.0.2 to 2.1.3 only):
|
|
||||||
.no-crypt-add-on
|
|
||||||
.SH HASHING METHODS
|
|
||||||
The implemented hashing methods are intended specifically for processing
|
|
||||||
user passwords for storage and authentication;
|
|
||||||
they are at best inefficient for most other purposes.
|
|
||||||
.PP
|
|
||||||
It is important to understand that password hashing is not a replacement
|
|
||||||
for strong passwords.
|
|
||||||
It is always possible for an attacker with access to password hashes
|
|
||||||
to try guessing candidate passwords against the hashes.
|
|
||||||
There are, however, certain properties a password hashing method may have
|
|
||||||
which make these key search attacks somewhat harder.
|
|
||||||
.PP
|
|
||||||
All of the hashing methods use salts such that the same
|
|
||||||
.I key
|
|
||||||
may produce many possible hashes.
|
|
||||||
Proper use of salts may defeat a number of attacks, including:
|
|
||||||
.TP
|
|
||||||
1.
|
|
||||||
The ability to try candidate passwords against multiple hashes at the
|
|
||||||
price of one.
|
|
||||||
.TP
|
|
||||||
2.
|
|
||||||
The use of pre-hashed lists of candidate passwords.
|
|
||||||
.TP
|
|
||||||
3.
|
|
||||||
The ability to determine whether two users (or two accounts of one user)
|
|
||||||
have the same or different passwords without actually having to guess
|
|
||||||
one of the passwords.
|
|
||||||
.PP
|
|
||||||
The key search attacks depend on computing hashes of large numbers of
|
|
||||||
candidate passwords.
|
|
||||||
Thus, the computational cost of a good password hashing method must be
|
|
||||||
high \- but of course not too high to render it impractical.
|
|
||||||
.PP
|
|
||||||
All hashing methods implemented within the
|
|
||||||
.crypt and
|
|
||||||
interfaces use multiple iterations of an underlying cryptographic
|
|
||||||
primitive specifically in order to increase the cost of trying a
|
|
||||||
candidate password.
|
|
||||||
Unfortunately, due to hardware improvements, the hashing methods which
|
|
||||||
have a fixed cost become increasingly less secure over time.
|
|
||||||
.PP
|
|
||||||
In addition to salts, modern password hashing methods accept a variable
|
|
||||||
iteration
|
|
||||||
.IR count .
|
|
||||||
This makes it possible to adapt their cost to the hardware improvements
|
|
||||||
while still maintaining compatibility.
|
|
||||||
.PP
|
|
||||||
The following hashing methods are or may be implemented within the
|
|
||||||
described interfaces:
|
|
||||||
.PP
|
|
||||||
.de hash
|
|
||||||
.ad l
|
|
||||||
.TP
|
|
||||||
.I prefix
|
|
||||||
.ie "\\$1"" \{\
|
|
||||||
"" (empty string);
|
|
||||||
.br
|
|
||||||
a string matching ^[./0-9A-Za-z]{2} (see
|
|
||||||
.BR regex (7))
|
|
||||||
.\}
|
|
||||||
.el "\\$1"
|
|
||||||
.TP
|
|
||||||
.B Encoding syntax
|
|
||||||
\\$2
|
|
||||||
.TP
|
|
||||||
.B Maximum password length
|
|
||||||
\\$3 (uses \\$4-bit characters)
|
|
||||||
.TP
|
|
||||||
.B Effective key size
|
|
||||||
.ie "\\$5"" limited by the hash size only
|
|
||||||
.el up to \\$5 bits
|
|
||||||
.TP
|
|
||||||
.B Hash size
|
|
||||||
\\$6 bits
|
|
||||||
.TP
|
|
||||||
.B Salt size
|
|
||||||
\\$7 bits
|
|
||||||
.TP
|
|
||||||
.B Iteration count
|
|
||||||
\\$8
|
|
||||||
.ad b
|
|
||||||
..
|
|
||||||
.ti -2
|
|
||||||
.B Traditional DES-based
|
|
||||||
.br
|
|
||||||
This method is supported by almost all implementations of
|
|
||||||
.BR crypt .
|
|
||||||
Unfortunately, it no longer offers adequate security because of its many
|
|
||||||
limitations.
|
|
||||||
Thus, it should not be used for new passwords unless you absolutely have
|
|
||||||
to be able to migrate the password hashes to other systems.
|
|
||||||
.hash "" "[./0-9A-Za-z]{13}" 8 7 56 64 12 25
|
|
||||||
.PP
|
|
||||||
.ti -2
|
|
||||||
.B Extended BSDI-style DES-based
|
|
||||||
.br
|
|
||||||
This method is used on BSDI and is also available on at least NetBSD,
|
|
||||||
OpenBSD, and FreeBSD due to the use of David Burren's FreeSec library.
|
|
||||||
.hash _ "_[./0-9A-Za-z]{19}" unlimited 7 56 64 24 "1 to 2**24-1 (must be odd)"
|
|
||||||
.PP
|
|
||||||
.ti -2
|
|
||||||
.B FreeBSD-style MD5-based
|
|
||||||
.br
|
|
||||||
This is Poul-Henning Kamp's MD5-based password hashing method originally
|
|
||||||
developed for FreeBSD.
|
|
||||||
It is currently supported on many free Unix-like systems, on Solaris 10
|
|
||||||
and newer, and it is part of the official glibc.
|
|
||||||
Its main disadvantage is the fixed iteration count, which is already
|
|
||||||
too low for the currently available hardware.
|
|
||||||
.hash "$1$" "\e$1\e$[^$]{1,8}\e$[./0-9A-Za-z]{22}" unlimited 8 "" 128 "6 to 48" 1000
|
|
||||||
.PP
|
|
||||||
.ti -2
|
|
||||||
.BR "OpenBSD-style Blowfish-based" " (" bcrypt )
|
|
||||||
.br
|
|
||||||
.B bcrypt
|
|
||||||
was originally developed by Niels Provos and David Mazieres for OpenBSD
|
|
||||||
and is also supported on recent versions of FreeBSD and NetBSD,
|
|
||||||
on Solaris 10 and newer, and on several GNU/*/Linux distributions.
|
|
||||||
It is, however, not part of the official glibc.
|
|
||||||
.PP
|
|
||||||
While both
|
|
||||||
.B bcrypt
|
|
||||||
and the BSDI-style DES-based hashing offer a variable iteration count,
|
|
||||||
.B bcrypt
|
|
||||||
may scale to even faster hardware, doesn't allow for certain optimizations
|
|
||||||
specific to password cracking only, doesn't have the effective key size
|
|
||||||
limitation, and uses 8-bit characters in passwords.
|
|
||||||
.hash "$2b$" "\e$2[abxy]\e$[0-9]{2}\e$[./A-Za-z0-9]{53}" 72 8 "" 184 128 "2**4 to 2**99 (current implementations are limited to 2**31 iterations)"
|
|
||||||
.PP
|
|
||||||
With
|
|
||||||
.BR bcrypt ,
|
|
||||||
the
|
|
||||||
.I count
|
|
||||||
passed to
|
|
||||||
.crypt_gensalt and
|
|
||||||
is the base-2 logarithm of the actual iteration count.
|
|
||||||
.PP
|
|
||||||
.B bcrypt
|
|
||||||
hashes used the "$2a$" prefix since 1997.
|
|
||||||
However, in 2011 an implementation bug was discovered in crypt_blowfish
|
|
||||||
(versions up to 1.0.4 inclusive) affecting handling of password characters with
|
|
||||||
the 8th bit set.
|
|
||||||
Besides fixing the bug,
|
|
||||||
to provide for upgrade strategies for existing systems, two new prefixes were
|
|
||||||
introduced: "$2x$", which fully re-introduces the bug, and "$2y$", which
|
|
||||||
guarantees correct handling of both 7- and 8-bit characters.
|
|
||||||
OpenBSD 5.5 introduced the "$2b$" prefix for behavior that exactly matches
|
|
||||||
crypt_blowfish's "$2y$", and current crypt_blowfish supports it as well.
|
|
||||||
Unfortunately, the behavior of "$2a$" on password characters with the 8th bit
|
|
||||||
set has to be considered system-specific.
|
|
||||||
When generating new password hashes, the "$2b$" or "$2y$" prefix should be used.
|
|
||||||
(If such hashes ever need to be migrated to a system that does not yet support
|
|
||||||
these new prefixes, the prefix in migrated copies of the already-generated
|
|
||||||
hashes may be changed to "$2a$".)
|
|
||||||
.PP
|
|
||||||
.crypt_gensalt and
|
|
||||||
support the "$2b$", "$2y$", and "$2a$" prefixes (the latter for legacy programs
|
|
||||||
or configurations), but not "$2x$" (which must not be used for new hashes).
|
|
||||||
.crypt and
|
|
||||||
support all four of these prefixes.
|
|
||||||
.SH PORTABILITY NOTES
|
|
||||||
Programs using any of these functions on a glibc 2.x system must be
|
|
||||||
linked against
|
|
||||||
.BR libcrypt .
|
|
||||||
However, many Unix-like operating systems and older versions of the
|
|
||||||
GNU C Library include the
|
|
||||||
.BR crypt " function in " libc .
|
|
||||||
.PP
|
|
||||||
The
|
|
||||||
.BR crypt_r ,
|
|
||||||
.BR crypt_rn ,
|
|
||||||
.BR crypt_ra ,
|
|
||||||
.crypt_gensalt and
|
|
||||||
functions are very non-portable.
|
|
||||||
.PP
|
|
||||||
The set of supported hashing methods is implementation-dependent.
|
|
||||||
.SH CONFORMING TO
|
|
||||||
The
|
|
||||||
.B crypt
|
|
||||||
function conforms to SVID, X/OPEN, and is available on BSD 4.3.
|
|
||||||
The strings returned by
|
|
||||||
.B crypt
|
|
||||||
are not required to be portable among conformant systems.
|
|
||||||
.PP
|
|
||||||
.B crypt_r
|
|
||||||
is a GNU extension.
|
|
||||||
There's also a
|
|
||||||
.B crypt_r
|
|
||||||
function on HP-UX and MKS Toolkit, but the prototypes and semantics differ.
|
|
||||||
.PP
|
|
||||||
.B crypt_gensalt
|
|
||||||
is an Openwall extension.
|
|
||||||
There's also a
|
|
||||||
.B crypt_gensalt
|
|
||||||
function on Solaris 10 and newer, but the prototypes and semantics differ.
|
|
||||||
.PP
|
|
||||||
.BR crypt_rn ,
|
|
||||||
.BR crypt_ra ,
|
|
||||||
.BR crypt_gensalt_rn ,
|
|
||||||
and
|
|
||||||
.B crypt_gensalt_ra
|
|
||||||
are Openwall extensions.
|
|
||||||
.SH HISTORY
|
|
||||||
A rotor-based
|
|
||||||
.B crypt
|
|
||||||
function appeared in Version 6 AT&T UNIX.
|
|
||||||
The "traditional"
|
|
||||||
.B crypt
|
|
||||||
first appeared in Version 7 AT&T UNIX.
|
|
||||||
.PP
|
|
||||||
The
|
|
||||||
.B crypt_r
|
|
||||||
function was introduced during glibc 2.0 development.
|
|
||||||
.SH BUGS
|
|
||||||
The return values of
|
|
||||||
.BR crypt " and " crypt_gensalt
|
|
||||||
point to static buffers that are overwritten by subsequent calls.
|
|
||||||
These functions are not thread-safe.
|
|
||||||
.RB ( crypt
|
|
||||||
on recent versions of Solaris uses thread-specific data and actually is
|
|
||||||
thread-safe.)
|
|
||||||
.PP
|
|
||||||
The strings returned by certain other implementations of
|
|
||||||
.B crypt
|
|
||||||
on error may be stored in read-only locations or only initialized once,
|
|
||||||
which makes it unsafe to always attempt to zero out the buffer normally
|
|
||||||
pointed to by the
|
|
||||||
.B crypt
|
|
||||||
return value as it would otherwise be preferable for security reasons.
|
|
||||||
The problem could be avoided with the use of
|
|
||||||
.BR crypt_r ,
|
|
||||||
.BR crypt_rn ,
|
|
||||||
or
|
|
||||||
.B crypt_ra
|
|
||||||
where the application has full control over output buffers of these functions
|
|
||||||
(and often over some of their private data as well).
|
|
||||||
Unfortunately, the functions aren't (yet?) available on platforms where
|
|
||||||
.B crypt
|
|
||||||
has this undesired property.
|
|
||||||
.PP
|
|
||||||
Applications using the thread-safe
|
|
||||||
.B crypt_r
|
|
||||||
need to allocate address space for the large (over 128 KB)
|
|
||||||
.I struct crypt_data
|
|
||||||
structure. Each thread needs a separate instance of the structure. The
|
|
||||||
.B crypt_r
|
|
||||||
interface makes it impossible to implement a hashing algorithm which
|
|
||||||
would need to keep an even larger amount of private data, without breaking
|
|
||||||
binary compatibility.
|
|
||||||
.B crypt_ra
|
|
||||||
allows for dynamically increasing the allocation size as required by the
|
|
||||||
hashing algorithm that is actually used. Unfortunately,
|
|
||||||
.B crypt_ra
|
|
||||||
is even more non-portable than
|
|
||||||
.BR crypt_r .
|
|
||||||
.PP
|
|
||||||
Multi-threaded applications or library functions which are meant to be
|
|
||||||
thread-safe should use
|
|
||||||
.BR crypt_gensalt_rn " or " crypt_gensalt_ra
|
|
||||||
rather than
|
|
||||||
.BR crypt_gensalt .
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR login (1),
|
|
||||||
.BR passwd (1),
|
|
||||||
.BR crypto (3),
|
|
||||||
.BR encrypt (3),
|
|
||||||
.BR free (3),
|
|
||||||
.BR getpass (3),
|
|
||||||
.BR getpwent (3),
|
|
||||||
.BR malloc (3),
|
|
||||||
.BR realloc (3),
|
|
||||||
.BR shadow (3),
|
|
||||||
.BR passwd (5),
|
|
||||||
.BR shadow (5),
|
|
||||||
.BR regex (7),
|
|
||||||
.BR pam (8)
|
|
||||||
.sp
|
|
||||||
Niels Provos and David Mazieres. A Future-Adaptable Password Scheme.
|
|
||||||
Proceedings of the 1999 USENIX Annual Technical Conference, June 1999.
|
|
||||||
.br
|
|
||||||
http://www.usenix.org/events/usenix99/provos.html
|
|
||||||
.sp
|
|
||||||
Robert Morris and Ken Thompson. Password Security: A Case History.
|
|
||||||
Unix Seventh Edition Manual, Volume 2, April 1978.
|
|
||||||
.br
|
|
||||||
http://plan9.bell-labs.com/7thEdMan/vol2/password
|
|
24
deps/crypt_blowfish/crypt.h
vendored
24
deps/crypt_blowfish/crypt.h
vendored
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* Written by Solar Designer <solar at openwall.com> in 2000-2002.
|
|
||||||
* No copyright is claimed, and the software is hereby placed in the public
|
|
||||||
* domain. In case this attempt to disclaim copyright and place the software
|
|
||||||
* in the public domain is deemed null and void, then the software is
|
|
||||||
* Copyright (c) 2000-2002 Solar Designer and it is hereby released to the
|
|
||||||
* general public under the following terms:
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted.
|
|
||||||
*
|
|
||||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
|
||||||
*
|
|
||||||
* See crypt_blowfish.c for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <gnu-crypt.h>
|
|
||||||
|
|
||||||
#if defined(_OW_SOURCE) || defined(__USE_OW)
|
|
||||||
#define __SKIP_GNU
|
|
||||||
#undef __SKIP_OW
|
|
||||||
#include <ow-crypt.h>
|
|
||||||
#undef __SKIP_GNU
|
|
||||||
#endif
|
|
907
deps/crypt_blowfish/crypt_blowfish.c
vendored
907
deps/crypt_blowfish/crypt_blowfish.c
vendored
@ -1,907 +0,0 @@
|
|||||||
/*
|
|
||||||
* The crypt_blowfish homepage is:
|
|
||||||
*
|
|
||||||
* http://www.openwall.com/crypt/
|
|
||||||
*
|
|
||||||
* This code comes from John the Ripper password cracker, with reentrant
|
|
||||||
* and crypt(3) interfaces added, but optimizations specific to password
|
|
||||||
* cracking removed.
|
|
||||||
*
|
|
||||||
* Written by Solar Designer <solar at openwall.com> in 1998-2014.
|
|
||||||
* No copyright is claimed, and the software is hereby placed in the public
|
|
||||||
* domain. In case this attempt to disclaim copyright and place the software
|
|
||||||
* in the public domain is deemed null and void, then the software is
|
|
||||||
* Copyright (c) 1998-2014 Solar Designer and it is hereby released to the
|
|
||||||
* general public under the following terms:
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted.
|
|
||||||
*
|
|
||||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
|
||||||
*
|
|
||||||
* It is my intent that you should be able to use this on your system,
|
|
||||||
* as part of a software package, or anywhere else to improve security,
|
|
||||||
* ensure compatibility, or for any other purpose. I would appreciate
|
|
||||||
* it if you give credit where it is due and keep your modifications in
|
|
||||||
* the public domain as well, but I don't require that in order to let
|
|
||||||
* you place this code and any modifications you make under a license
|
|
||||||
* of your choice.
|
|
||||||
*
|
|
||||||
* This implementation is fully compatible with OpenBSD's bcrypt.c for prefix
|
|
||||||
* "$2b$", originally by Niels Provos <provos at citi.umich.edu>, and it uses
|
|
||||||
* some of his ideas. The password hashing algorithm was designed by David
|
|
||||||
* Mazieres <dm at lcs.mit.edu>. For information on the level of
|
|
||||||
* compatibility for bcrypt hash prefixes other than "$2b$", please refer to
|
|
||||||
* the comments in BF_set_key() below and to the included crypt(3) man page.
|
|
||||||
*
|
|
||||||
* There's a paper on the algorithm that explains its design decisions:
|
|
||||||
*
|
|
||||||
* http://www.usenix.org/events/usenix99/provos.html
|
|
||||||
*
|
|
||||||
* Some of the tricks in BF_ROUND might be inspired by Eric Young's
|
|
||||||
* Blowfish library (I can't be sure if I would think of something if I
|
|
||||||
* hadn't seen his code).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#ifndef __set_errno
|
|
||||||
#define __set_errno(val) errno = (val)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Just to make sure the prototypes match the actual definitions */
|
|
||||||
#include "crypt_blowfish.h"
|
|
||||||
|
|
||||||
#ifdef __i386__
|
|
||||||
#define BF_ASM 1
|
|
||||||
#define BF_SCALE 1
|
|
||||||
#elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__)
|
|
||||||
#define BF_ASM 0
|
|
||||||
#define BF_SCALE 1
|
|
||||||
#else
|
|
||||||
#define BF_ASM 0
|
|
||||||
#define BF_SCALE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef unsigned int BF_word;
|
|
||||||
typedef signed int BF_word_signed;
|
|
||||||
|
|
||||||
/* Number of Blowfish rounds, this is also hardcoded into a few places */
|
|
||||||
#define BF_N 16
|
|
||||||
|
|
||||||
typedef BF_word BF_key[BF_N + 2];
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
BF_word S[4][0x100];
|
|
||||||
BF_key P;
|
|
||||||
} BF_ctx;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Magic IV for 64 Blowfish encryptions that we do at the end.
|
|
||||||
* The string is "OrpheanBeholderScryDoubt" on big-endian.
|
|
||||||
*/
|
|
||||||
static BF_word BF_magic_w[6] = {
|
|
||||||
0x4F727068, 0x65616E42, 0x65686F6C,
|
|
||||||
0x64657253, 0x63727944, 0x6F756274
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* P-box and S-box tables initialized with digits of Pi.
|
|
||||||
*/
|
|
||||||
static BF_ctx BF_init_state = {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
|
|
||||||
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
|
||||||
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
|
||||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
|
||||||
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
|
|
||||||
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
|
||||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
|
|
||||||
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
|
||||||
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
|
||||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
|
||||||
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
|
|
||||||
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
|
||||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
|
|
||||||
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
|
||||||
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
|
||||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
|
||||||
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
|
|
||||||
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
|
||||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
|
|
||||||
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
|
||||||
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
|
||||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
|
||||||
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
|
|
||||||
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
|
||||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
|
|
||||||
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
|
||||||
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
|
||||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
|
||||||
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
|
|
||||||
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
|
||||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
|
|
||||||
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
|
||||||
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
|
||||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
|
||||||
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
|
|
||||||
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
|
||||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
|
|
||||||
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
|
||||||
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
|
||||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
|
||||||
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
|
|
||||||
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
|
||||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
|
|
||||||
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
|
||||||
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
|
||||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
|
||||||
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
|
|
||||||
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
|
||||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
|
|
||||||
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
|
||||||
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
|
||||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
|
||||||
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
|
|
||||||
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
|
||||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
|
|
||||||
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
|
||||||
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
|
||||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
|
||||||
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
|
|
||||||
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
|
||||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
|
|
||||||
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
|
||||||
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
|
||||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
|
|
||||||
}, {
|
|
||||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
|
|
||||||
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
|
||||||
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
|
||||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
|
||||||
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
|
|
||||||
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
|
||||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
|
|
||||||
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
|
||||||
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
|
||||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
|
||||||
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
|
|
||||||
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
|
||||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
|
|
||||||
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
|
||||||
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
|
||||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
|
||||||
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
|
|
||||||
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
|
||||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
|
|
||||||
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
|
||||||
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
|
||||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
|
||||||
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
|
|
||||||
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
|
||||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
|
|
||||||
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
|
||||||
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
|
||||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
|
||||||
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
|
|
||||||
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
|
||||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
|
|
||||||
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
|
||||||
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
|
||||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
|
||||||
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
|
|
||||||
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
|
||||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
|
|
||||||
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
|
||||||
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
|
||||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
|
||||||
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
|
|
||||||
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
|
||||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
|
|
||||||
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
|
||||||
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
|
||||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
|
||||||
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
|
|
||||||
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
|
||||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
|
|
||||||
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
|
||||||
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
|
||||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
|
||||||
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
|
|
||||||
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
|
||||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
|
|
||||||
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
|
||||||
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
|
||||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
|
||||||
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
|
|
||||||
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
|
||||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
|
|
||||||
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
|
||||||
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
|
||||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
|
|
||||||
}, {
|
|
||||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
|
||||||
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
|
||||||
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
|
||||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
|
||||||
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
|
|
||||||
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
|
||||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
|
|
||||||
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
|
||||||
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
|
||||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
|
||||||
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
|
|
||||||
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
|
||||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
|
|
||||||
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
|
||||||
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
|
||||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
|
||||||
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
|
|
||||||
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
|
||||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
|
|
||||||
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
|
||||||
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
|
||||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
|
||||||
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
|
|
||||||
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
|
||||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
|
|
||||||
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
|
||||||
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
|
||||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
|
||||||
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
|
|
||||||
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
|
||||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
|
|
||||||
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
|
||||||
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
|
||||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
|
||||||
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
|
|
||||||
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
|
||||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
|
|
||||||
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
|
||||||
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
|
||||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
|
||||||
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
|
|
||||||
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
|
||||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
|
|
||||||
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
|
||||||
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
|
||||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
|
||||||
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
|
|
||||||
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
|
||||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
|
|
||||||
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
|
||||||
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
|
||||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
|
||||||
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
|
|
||||||
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
|
||||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
|
|
||||||
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
|
||||||
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
|
||||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
|
||||||
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
|
|
||||||
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
|
||||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
|
||||||
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
|
||||||
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
|
||||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
|
|
||||||
}, {
|
|
||||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
|
|
||||||
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
|
||||||
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
|
||||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
|
||||||
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
|
|
||||||
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
|
||||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
|
|
||||||
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
|
||||||
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
|
||||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
|
||||||
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
|
|
||||||
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
|
||||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
|
|
||||||
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
|
||||||
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
|
||||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
|
||||||
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
|
|
||||||
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
|
||||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
|
|
||||||
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
|
||||||
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
|
||||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
|
||||||
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
|
|
||||||
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
|
||||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
|
|
||||||
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
|
||||||
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
|
||||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
|
||||||
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
|
|
||||||
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
|
||||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
|
|
||||||
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
|
||||||
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
|
||||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
|
||||||
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
|
|
||||||
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
|
||||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
|
|
||||||
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
|
||||||
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
|
||||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
|
||||||
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
|
|
||||||
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
|
||||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
|
|
||||||
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
|
||||||
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
|
||||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
|
||||||
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
|
|
||||||
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
|
||||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
|
|
||||||
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
|
||||||
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
|
||||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
|
||||||
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
|
|
||||||
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
|
||||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
|
|
||||||
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
|
||||||
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
|
||||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
|
||||||
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
|
|
||||||
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
|
||||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
|
|
||||||
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
|
||||||
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
|
||||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
|
|
||||||
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
|
|
||||||
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
|
||||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
|
|
||||||
0x9216d5d9, 0x8979fb1b
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned char BF_itoa64[64 + 1] =
|
|
||||||
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
||||||
|
|
||||||
static unsigned char BF_atoi64[0x60] = {
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
|
|
||||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
|
||||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
|
|
||||||
64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
|
|
||||||
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BF_safe_atoi64(dst, src) \
|
|
||||||
{ \
|
|
||||||
tmp = (unsigned char)(src); \
|
|
||||||
if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
|
|
||||||
tmp = BF_atoi64[tmp]; \
|
|
||||||
if (tmp > 63) return -1; \
|
|
||||||
(dst) = tmp; \
|
|
||||||
}
|
|
||||||
|
|
||||||
static int BF_decode(BF_word *dst, const char *src, int size)
|
|
||||||
{
|
|
||||||
unsigned char *dptr = (unsigned char *)dst;
|
|
||||||
unsigned char *end = dptr + size;
|
|
||||||
const unsigned char *sptr = (const unsigned char *)src;
|
|
||||||
unsigned int tmp, c1, c2, c3, c4;
|
|
||||||
|
|
||||||
do {
|
|
||||||
BF_safe_atoi64(c1, *sptr++);
|
|
||||||
BF_safe_atoi64(c2, *sptr++);
|
|
||||||
*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
|
|
||||||
if (dptr >= end) break;
|
|
||||||
|
|
||||||
BF_safe_atoi64(c3, *sptr++);
|
|
||||||
*dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
|
|
||||||
if (dptr >= end) break;
|
|
||||||
|
|
||||||
BF_safe_atoi64(c4, *sptr++);
|
|
||||||
*dptr++ = ((c3 & 0x03) << 6) | c4;
|
|
||||||
} while (dptr < end);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BF_encode(char *dst, const BF_word *src, int size)
|
|
||||||
{
|
|
||||||
const unsigned char *sptr = (const unsigned char *)src;
|
|
||||||
const unsigned char *end = sptr + size;
|
|
||||||
unsigned char *dptr = (unsigned char *)dst;
|
|
||||||
unsigned int c1, c2;
|
|
||||||
|
|
||||||
do {
|
|
||||||
c1 = *sptr++;
|
|
||||||
*dptr++ = BF_itoa64[c1 >> 2];
|
|
||||||
c1 = (c1 & 0x03) << 4;
|
|
||||||
if (sptr >= end) {
|
|
||||||
*dptr++ = BF_itoa64[c1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
c2 = *sptr++;
|
|
||||||
c1 |= c2 >> 4;
|
|
||||||
*dptr++ = BF_itoa64[c1];
|
|
||||||
c1 = (c2 & 0x0f) << 2;
|
|
||||||
if (sptr >= end) {
|
|
||||||
*dptr++ = BF_itoa64[c1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
c2 = *sptr++;
|
|
||||||
c1 |= c2 >> 6;
|
|
||||||
*dptr++ = BF_itoa64[c1];
|
|
||||||
*dptr++ = BF_itoa64[c2 & 0x3f];
|
|
||||||
} while (sptr < end);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BF_swap(BF_word *x, int count)
|
|
||||||
{
|
|
||||||
static int endianness_check = 1;
|
|
||||||
char *is_little_endian = (char *)&endianness_check;
|
|
||||||
BF_word tmp;
|
|
||||||
|
|
||||||
if (*is_little_endian)
|
|
||||||
do {
|
|
||||||
tmp = *x;
|
|
||||||
tmp = (tmp << 16) | (tmp >> 16);
|
|
||||||
*x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
|
|
||||||
} while (--count);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if BF_SCALE
|
|
||||||
/* Architectures which can shift addresses left by 2 bits with no extra cost */
|
|
||||||
#define BF_ROUND(L, R, N) \
|
|
||||||
tmp1 = L & 0xFF; \
|
|
||||||
tmp2 = L >> 8; \
|
|
||||||
tmp2 &= 0xFF; \
|
|
||||||
tmp3 = L >> 16; \
|
|
||||||
tmp3 &= 0xFF; \
|
|
||||||
tmp4 = L >> 24; \
|
|
||||||
tmp1 = data.ctx.S[3][tmp1]; \
|
|
||||||
tmp2 = data.ctx.S[2][tmp2]; \
|
|
||||||
tmp3 = data.ctx.S[1][tmp3]; \
|
|
||||||
tmp3 += data.ctx.S[0][tmp4]; \
|
|
||||||
tmp3 ^= tmp2; \
|
|
||||||
R ^= data.ctx.P[N + 1]; \
|
|
||||||
tmp3 += tmp1; \
|
|
||||||
R ^= tmp3;
|
|
||||||
#else
|
|
||||||
/* Architectures with no complicated addressing modes supported */
|
|
||||||
#define BF_INDEX(S, i) \
|
|
||||||
(*((BF_word *)(((unsigned char *)S) + (i))))
|
|
||||||
#define BF_ROUND(L, R, N) \
|
|
||||||
tmp1 = L & 0xFF; \
|
|
||||||
tmp1 <<= 2; \
|
|
||||||
tmp2 = L >> 6; \
|
|
||||||
tmp2 &= 0x3FC; \
|
|
||||||
tmp3 = L >> 14; \
|
|
||||||
tmp3 &= 0x3FC; \
|
|
||||||
tmp4 = L >> 22; \
|
|
||||||
tmp4 &= 0x3FC; \
|
|
||||||
tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
|
|
||||||
tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
|
|
||||||
tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
|
|
||||||
tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
|
|
||||||
tmp3 ^= tmp2; \
|
|
||||||
R ^= data.ctx.P[N + 1]; \
|
|
||||||
tmp3 += tmp1; \
|
|
||||||
R ^= tmp3;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Encrypt one block, BF_N is hardcoded here.
|
|
||||||
*/
|
|
||||||
#define BF_ENCRYPT \
|
|
||||||
L ^= data.ctx.P[0]; \
|
|
||||||
BF_ROUND(L, R, 0); \
|
|
||||||
BF_ROUND(R, L, 1); \
|
|
||||||
BF_ROUND(L, R, 2); \
|
|
||||||
BF_ROUND(R, L, 3); \
|
|
||||||
BF_ROUND(L, R, 4); \
|
|
||||||
BF_ROUND(R, L, 5); \
|
|
||||||
BF_ROUND(L, R, 6); \
|
|
||||||
BF_ROUND(R, L, 7); \
|
|
||||||
BF_ROUND(L, R, 8); \
|
|
||||||
BF_ROUND(R, L, 9); \
|
|
||||||
BF_ROUND(L, R, 10); \
|
|
||||||
BF_ROUND(R, L, 11); \
|
|
||||||
BF_ROUND(L, R, 12); \
|
|
||||||
BF_ROUND(R, L, 13); \
|
|
||||||
BF_ROUND(L, R, 14); \
|
|
||||||
BF_ROUND(R, L, 15); \
|
|
||||||
tmp4 = R; \
|
|
||||||
R = L; \
|
|
||||||
L = tmp4 ^ data.ctx.P[BF_N + 1];
|
|
||||||
|
|
||||||
#if BF_ASM
|
|
||||||
#define BF_body() \
|
|
||||||
_BF_body_r(&data.ctx);
|
|
||||||
#else
|
|
||||||
#define BF_body() \
|
|
||||||
L = R = 0; \
|
|
||||||
ptr = data.ctx.P; \
|
|
||||||
do { \
|
|
||||||
ptr += 2; \
|
|
||||||
BF_ENCRYPT; \
|
|
||||||
*(ptr - 2) = L; \
|
|
||||||
*(ptr - 1) = R; \
|
|
||||||
} while (ptr < &data.ctx.P[BF_N + 2]); \
|
|
||||||
\
|
|
||||||
ptr = data.ctx.S[0]; \
|
|
||||||
do { \
|
|
||||||
ptr += 2; \
|
|
||||||
BF_ENCRYPT; \
|
|
||||||
*(ptr - 2) = L; \
|
|
||||||
*(ptr - 1) = R; \
|
|
||||||
} while (ptr < &data.ctx.S[3][0xFF]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
|
|
||||||
unsigned char flags)
|
|
||||||
{
|
|
||||||
const char *ptr = key;
|
|
||||||
unsigned int bug, i, j;
|
|
||||||
BF_word safety, sign, diff, tmp[2];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* There was a sign extension bug in older revisions of this function. While
|
|
||||||
* we would have liked to simply fix the bug and move on, we have to provide
|
|
||||||
* a backwards compatibility feature (essentially the bug) for some systems and
|
|
||||||
* a safety measure for some others. The latter is needed because for certain
|
|
||||||
* multiple inputs to the buggy algorithm there exist easily found inputs to
|
|
||||||
* the correct algorithm that produce the same hash. Thus, we optionally
|
|
||||||
* deviate from the correct algorithm just enough to avoid such collisions.
|
|
||||||
* While the bug itself affected the majority of passwords containing
|
|
||||||
* characters with the 8th bit set (although only a percentage of those in a
|
|
||||||
* collision-producing way), the anti-collision safety measure affects
|
|
||||||
* only a subset of passwords containing the '\xff' character (not even all of
|
|
||||||
* those passwords, just some of them). This character is not found in valid
|
|
||||||
* UTF-8 sequences and is rarely used in popular 8-bit character encodings.
|
|
||||||
* Thus, the safety measure is unlikely to cause much annoyance, and is a
|
|
||||||
* reasonable tradeoff to use when authenticating against existing hashes that
|
|
||||||
* are not reliably known to have been computed with the correct algorithm.
|
|
||||||
*
|
|
||||||
* We use an approach that tries to minimize side-channel leaks of password
|
|
||||||
* information - that is, we mostly use fixed-cost bitwise operations instead
|
|
||||||
* of branches or table lookups. (One conditional branch based on password
|
|
||||||
* length remains. It is not part of the bug aftermath, though, and is
|
|
||||||
* difficult and possibly unreasonable to avoid given the use of C strings by
|
|
||||||
* the caller, which results in similar timing leaks anyway.)
|
|
||||||
*
|
|
||||||
* For actual implementation, we set an array index in the variable "bug"
|
|
||||||
* (0 means no bug, 1 means sign extension bug emulation) and a flag in the
|
|
||||||
* variable "safety" (bit 16 is set when the safety measure is requested).
|
|
||||||
* Valid combinations of settings are:
|
|
||||||
*
|
|
||||||
* Prefix "$2a$": bug = 0, safety = 0x10000
|
|
||||||
* Prefix "$2b$": bug = 0, safety = 0
|
|
||||||
* Prefix "$2x$": bug = 1, safety = 0
|
|
||||||
* Prefix "$2y$": bug = 0, safety = 0
|
|
||||||
*/
|
|
||||||
bug = (unsigned int)flags & 1;
|
|
||||||
safety = ((BF_word)flags & 2) << 15;
|
|
||||||
|
|
||||||
sign = diff = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < BF_N + 2; i++) {
|
|
||||||
tmp[0] = tmp[1] = 0;
|
|
||||||
for (j = 0; j < 4; j++) {
|
|
||||||
tmp[0] <<= 8;
|
|
||||||
tmp[0] |= (unsigned char)*ptr; /* correct */
|
|
||||||
tmp[1] <<= 8;
|
|
||||||
tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
|
|
||||||
/*
|
|
||||||
* Sign extension in the first char has no effect - nothing to overwrite yet,
|
|
||||||
* and those extra 24 bits will be fully shifted out of the 32-bit word. For
|
|
||||||
* chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
|
|
||||||
* extension in tmp[1] occurs. Once this flag is set, it remains set.
|
|
||||||
*/
|
|
||||||
if (j)
|
|
||||||
sign |= tmp[1] & 0x80;
|
|
||||||
if (!*ptr)
|
|
||||||
ptr = key;
|
|
||||||
else
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
|
|
||||||
|
|
||||||
expanded[i] = tmp[bug];
|
|
||||||
initial[i] = BF_init_state.P[i] ^ tmp[bug];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At this point, "diff" is zero iff the correct and buggy algorithms produced
|
|
||||||
* exactly the same result. If so and if "sign" is non-zero, which indicates
|
|
||||||
* that there was a non-benign sign extension, this means that we have a
|
|
||||||
* collision between the correctly computed hash for this password and a set of
|
|
||||||
* passwords that could be supplied to the buggy algorithm. Our safety measure
|
|
||||||
* is meant to protect from such many-buggy to one-correct collisions, by
|
|
||||||
* deviating from the correct algorithm in such cases. Let's check for this.
|
|
||||||
*/
|
|
||||||
diff |= diff >> 16; /* still zero iff exact match */
|
|
||||||
diff &= 0xffff; /* ditto */
|
|
||||||
diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
|
|
||||||
sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
|
|
||||||
sign &= ~diff & safety; /* action needed? */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we have determined that we need to deviate from the correct algorithm,
|
|
||||||
* flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but
|
|
||||||
* let's stick to it now. It came out of the approach we used above, and it's
|
|
||||||
* not any worse than any other choice we could make.)
|
|
||||||
*
|
|
||||||
* It is crucial that we don't do the same to the expanded key used in the main
|
|
||||||
* Eksblowfish loop. By doing it to only one of these two, we deviate from a
|
|
||||||
* state that could be directly specified by a password to the buggy algorithm
|
|
||||||
* (and to the fully correct one as well, but that's a side-effect).
|
|
||||||
*/
|
|
||||||
initial[0] ^= sign;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned char flags_by_subtype[26] =
|
|
||||||
{2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
|
|
||||||
|
|
||||||
static char *BF_crypt(const char *key, const char *setting,
|
|
||||||
char *output, int size,
|
|
||||||
BF_word min)
|
|
||||||
{
|
|
||||||
#if BF_ASM
|
|
||||||
extern void _BF_body_r(BF_ctx *ctx);
|
|
||||||
#endif
|
|
||||||
struct {
|
|
||||||
BF_ctx ctx;
|
|
||||||
BF_key expanded_key;
|
|
||||||
union {
|
|
||||||
BF_word salt[4];
|
|
||||||
BF_word output[6];
|
|
||||||
} binary;
|
|
||||||
} data;
|
|
||||||
BF_word L, R;
|
|
||||||
BF_word tmp1, tmp2, tmp3, tmp4;
|
|
||||||
BF_word *ptr;
|
|
||||||
BF_word count;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (size < 7 + 22 + 31 + 1) {
|
|
||||||
__set_errno(ERANGE);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setting[0] != '$' ||
|
|
||||||
setting[1] != '2' ||
|
|
||||||
setting[2] < 'a' || setting[2] > 'z' ||
|
|
||||||
!flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
|
|
||||||
setting[3] != '$' ||
|
|
||||||
setting[4] < '0' || setting[4] > '3' ||
|
|
||||||
setting[5] < '0' || setting[5] > '9' ||
|
|
||||||
(setting[4] == '3' && setting[5] > '1') ||
|
|
||||||
setting[6] != '$') {
|
|
||||||
__set_errno(EINVAL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
|
|
||||||
if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
|
|
||||||
__set_errno(EINVAL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
BF_swap(data.binary.salt, 4);
|
|
||||||
|
|
||||||
BF_set_key(key, data.expanded_key, data.ctx.P,
|
|
||||||
flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']);
|
|
||||||
|
|
||||||
memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
|
|
||||||
|
|
||||||
L = R = 0;
|
|
||||||
for (i = 0; i < BF_N + 2; i += 2) {
|
|
||||||
L ^= data.binary.salt[i & 2];
|
|
||||||
R ^= data.binary.salt[(i & 2) + 1];
|
|
||||||
BF_ENCRYPT;
|
|
||||||
data.ctx.P[i] = L;
|
|
||||||
data.ctx.P[i + 1] = R;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = data.ctx.S[0];
|
|
||||||
do {
|
|
||||||
ptr += 4;
|
|
||||||
L ^= data.binary.salt[(BF_N + 2) & 3];
|
|
||||||
R ^= data.binary.salt[(BF_N + 3) & 3];
|
|
||||||
BF_ENCRYPT;
|
|
||||||
*(ptr - 4) = L;
|
|
||||||
*(ptr - 3) = R;
|
|
||||||
|
|
||||||
L ^= data.binary.salt[(BF_N + 4) & 3];
|
|
||||||
R ^= data.binary.salt[(BF_N + 5) & 3];
|
|
||||||
BF_ENCRYPT;
|
|
||||||
*(ptr - 2) = L;
|
|
||||||
*(ptr - 1) = R;
|
|
||||||
} while (ptr < &data.ctx.S[3][0xFF]);
|
|
||||||
|
|
||||||
do {
|
|
||||||
int done;
|
|
||||||
|
|
||||||
for (i = 0; i < BF_N + 2; i += 2) {
|
|
||||||
data.ctx.P[i] ^= data.expanded_key[i];
|
|
||||||
data.ctx.P[i + 1] ^= data.expanded_key[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
done = 0;
|
|
||||||
do {
|
|
||||||
BF_body();
|
|
||||||
if (done)
|
|
||||||
break;
|
|
||||||
done = 1;
|
|
||||||
|
|
||||||
tmp1 = data.binary.salt[0];
|
|
||||||
tmp2 = data.binary.salt[1];
|
|
||||||
tmp3 = data.binary.salt[2];
|
|
||||||
tmp4 = data.binary.salt[3];
|
|
||||||
for (i = 0; i < BF_N; i += 4) {
|
|
||||||
data.ctx.P[i] ^= tmp1;
|
|
||||||
data.ctx.P[i + 1] ^= tmp2;
|
|
||||||
data.ctx.P[i + 2] ^= tmp3;
|
|
||||||
data.ctx.P[i + 3] ^= tmp4;
|
|
||||||
}
|
|
||||||
data.ctx.P[16] ^= tmp1;
|
|
||||||
data.ctx.P[17] ^= tmp2;
|
|
||||||
} while (1);
|
|
||||||
} while (--count);
|
|
||||||
|
|
||||||
for (i = 0; i < 6; i += 2) {
|
|
||||||
L = BF_magic_w[i];
|
|
||||||
R = BF_magic_w[i + 1];
|
|
||||||
|
|
||||||
count = 64;
|
|
||||||
do {
|
|
||||||
BF_ENCRYPT;
|
|
||||||
} while (--count);
|
|
||||||
|
|
||||||
data.binary.output[i] = L;
|
|
||||||
data.binary.output[i + 1] = R;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(output, setting, 7 + 22 - 1);
|
|
||||||
output[7 + 22 - 1] = BF_itoa64[(int)
|
|
||||||
BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
|
|
||||||
|
|
||||||
/* This has to be bug-compatible with the original implementation, so
|
|
||||||
* only encode 23 of the 24 bytes. :-) */
|
|
||||||
BF_swap(data.binary.output, 6);
|
|
||||||
BF_encode(&output[7 + 22], data.binary.output, 23);
|
|
||||||
output[7 + 22 + 31] = '\0';
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _crypt_output_magic(const char *setting, char *output, int size)
|
|
||||||
{
|
|
||||||
if (size < 3)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
output[0] = '*';
|
|
||||||
output[1] = '0';
|
|
||||||
output[2] = '\0';
|
|
||||||
|
|
||||||
if (setting[0] == '*' && setting[1] == '0')
|
|
||||||
output[1] = '1';
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Please preserve the runtime self-test. It serves two purposes at once:
|
|
||||||
*
|
|
||||||
* 1. We really can't afford the risk of producing incompatible hashes e.g.
|
|
||||||
* when there's something like gcc bug 26587 again, whereas an application or
|
|
||||||
* library integrating this code might not also integrate our external tests or
|
|
||||||
* it might not run them after every build. Even if it does, the miscompile
|
|
||||||
* might only occur on the production build, but not on a testing build (such
|
|
||||||
* as because of different optimization settings). It is painful to recover
|
|
||||||
* from incorrectly-computed hashes - merely fixing whatever broke is not
|
|
||||||
* enough. Thus, a proactive measure like this self-test is needed.
|
|
||||||
*
|
|
||||||
* 2. We don't want to leave sensitive data from our actual password hash
|
|
||||||
* computation on the stack or in registers. Previous revisions of the code
|
|
||||||
* would do explicit cleanups, but simply running the self-test after hash
|
|
||||||
* computation is more reliable.
|
|
||||||
*
|
|
||||||
* The performance cost of this quick self-test is around 0.6% at the "$2a$08"
|
|
||||||
* setting.
|
|
||||||
*/
|
|
||||||
char *_crypt_blowfish_rn(const char *key, const char *setting,
|
|
||||||
char *output, int size)
|
|
||||||
{
|
|
||||||
const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
|
|
||||||
const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu";
|
|
||||||
static const char * const test_hashes[2] =
|
|
||||||
{"i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */
|
|
||||||
"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55"}; /* 'x' */
|
|
||||||
const char *test_hash = test_hashes[0];
|
|
||||||
char *retval;
|
|
||||||
const char *p;
|
|
||||||
int save_errno, ok;
|
|
||||||
struct {
|
|
||||||
char s[7 + 22 + 1];
|
|
||||||
char o[7 + 22 + 31 + 1 + 1 + 1];
|
|
||||||
} buf;
|
|
||||||
|
|
||||||
/* Hash the supplied password */
|
|
||||||
_crypt_output_magic(setting, output, size);
|
|
||||||
retval = BF_crypt(key, setting, output, size, 16);
|
|
||||||
save_errno = errno;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do a quick self-test. It is important that we make both calls to BF_crypt()
|
|
||||||
* from the same scope such that they likely use the same stack locations,
|
|
||||||
* which makes the second call overwrite the first call's sensitive data on the
|
|
||||||
* stack and makes it more likely that any alignment related issues would be
|
|
||||||
* detected by the self-test.
|
|
||||||
*/
|
|
||||||
memcpy(buf.s, test_setting, sizeof(buf.s));
|
|
||||||
if (retval) {
|
|
||||||
unsigned int flags = flags_by_subtype[
|
|
||||||
(unsigned int)(unsigned char)setting[2] - 'a'];
|
|
||||||
test_hash = test_hashes[flags & 1];
|
|
||||||
buf.s[2] = setting[2];
|
|
||||||
}
|
|
||||||
memset(buf.o, 0x55, sizeof(buf.o));
|
|
||||||
buf.o[sizeof(buf.o) - 1] = 0;
|
|
||||||
p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1);
|
|
||||||
|
|
||||||
ok = (p == buf.o &&
|
|
||||||
!memcmp(p, buf.s, 7 + 22) &&
|
|
||||||
!memcmp(p + (7 + 22), test_hash, 31 + 1 + 1 + 1));
|
|
||||||
|
|
||||||
{
|
|
||||||
const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345";
|
|
||||||
BF_key ae, ai, ye, yi;
|
|
||||||
BF_set_key(k, ae, ai, 2); /* $2a$ */
|
|
||||||
BF_set_key(k, ye, yi, 4); /* $2y$ */
|
|
||||||
ai[0] ^= 0x10000; /* undo the safety (for comparison) */
|
|
||||||
ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 &&
|
|
||||||
!memcmp(ae, ye, sizeof(ae)) &&
|
|
||||||
!memcmp(ai, yi, sizeof(ai));
|
|
||||||
}
|
|
||||||
|
|
||||||
__set_errno(save_errno);
|
|
||||||
if (ok)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
/* Should not happen */
|
|
||||||
_crypt_output_magic(setting, output, size);
|
|
||||||
__set_errno(EINVAL); /* pretend we don't support this hash type */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
|
|
||||||
const char *input, int size, char *output, int output_size)
|
|
||||||
{
|
|
||||||
if (size < 16 || output_size < 7 + 22 + 1 ||
|
|
||||||
(count && (count < 4 || count > 31)) ||
|
|
||||||
prefix[0] != '$' || prefix[1] != '2' ||
|
|
||||||
(prefix[2] != 'a' && prefix[2] != 'b' && prefix[2] != 'y')) {
|
|
||||||
if (output_size > 0) output[0] = '\0';
|
|
||||||
__set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!count) count = 5;
|
|
||||||
|
|
||||||
output[0] = '$';
|
|
||||||
output[1] = '2';
|
|
||||||
output[2] = prefix[2];
|
|
||||||
output[3] = '$';
|
|
||||||
output[4] = '0' + count / 10;
|
|
||||||
output[5] = '0' + count % 10;
|
|
||||||
output[6] = '$';
|
|
||||||
|
|
||||||
BF_encode(&output[7], (const BF_word *)input, 16);
|
|
||||||
output[7 + 22] = '\0';
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
27
deps/crypt_blowfish/crypt_blowfish.h
vendored
27
deps/crypt_blowfish/crypt_blowfish.h
vendored
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
|
||||||
* No copyright is claimed, and the software is hereby placed in the public
|
|
||||||
* domain. In case this attempt to disclaim copyright and place the software
|
|
||||||
* in the public domain is deemed null and void, then the software is
|
|
||||||
* Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
|
||||||
* general public under the following terms:
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted.
|
|
||||||
*
|
|
||||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
|
||||||
*
|
|
||||||
* See crypt_blowfish.c for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _CRYPT_BLOWFISH_H
|
|
||||||
#define _CRYPT_BLOWFISH_H
|
|
||||||
|
|
||||||
extern int _crypt_output_magic(const char *setting, char *output, int size);
|
|
||||||
extern char *_crypt_blowfish_rn(const char *key, const char *setting,
|
|
||||||
char *output, int size);
|
|
||||||
extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
|
|
||||||
unsigned long count,
|
|
||||||
const char *input, int size, char *output, int output_size);
|
|
||||||
|
|
||||||
#endif
|
|
124
deps/crypt_blowfish/crypt_gensalt.c
vendored
124
deps/crypt_blowfish/crypt_gensalt.c
vendored
@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
|
||||||
* No copyright is claimed, and the software is hereby placed in the public
|
|
||||||
* domain. In case this attempt to disclaim copyright and place the software
|
|
||||||
* in the public domain is deemed null and void, then the software is
|
|
||||||
* Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
|
||||||
* general public under the following terms:
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted.
|
|
||||||
*
|
|
||||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
|
||||||
*
|
|
||||||
* See crypt_blowfish.c for more information.
|
|
||||||
*
|
|
||||||
* This file contains salt generation functions for the traditional and
|
|
||||||
* other common crypt(3) algorithms, except for bcrypt which is defined
|
|
||||||
* entirely in crypt_blowfish.c.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#ifndef __set_errno
|
|
||||||
#define __set_errno(val) errno = (val)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Just to make sure the prototypes match the actual definitions */
|
|
||||||
#include "crypt_gensalt.h"
|
|
||||||
|
|
||||||
unsigned char _crypt_itoa64[64 + 1] =
|
|
||||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
||||||
|
|
||||||
char *_crypt_gensalt_traditional_rn(const char *prefix, unsigned long count,
|
|
||||||
const char *input, int size, char *output, int output_size)
|
|
||||||
{
|
|
||||||
(void) prefix;
|
|
||||||
|
|
||||||
if (size < 2 || output_size < 2 + 1 || (count && count != 25)) {
|
|
||||||
if (output_size > 0) output[0] = '\0';
|
|
||||||
__set_errno((output_size < 2 + 1) ? ERANGE : EINVAL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
output[0] = _crypt_itoa64[(unsigned int)input[0] & 0x3f];
|
|
||||||
output[1] = _crypt_itoa64[(unsigned int)input[1] & 0x3f];
|
|
||||||
output[2] = '\0';
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *_crypt_gensalt_extended_rn(const char *prefix, unsigned long count,
|
|
||||||
const char *input, int size, char *output, int output_size)
|
|
||||||
{
|
|
||||||
unsigned long value;
|
|
||||||
|
|
||||||
(void) prefix;
|
|
||||||
|
|
||||||
/* Even iteration counts make it easier to detect weak DES keys from a look
|
|
||||||
* at the hash, so they should be avoided */
|
|
||||||
if (size < 3 || output_size < 1 + 4 + 4 + 1 ||
|
|
||||||
(count && (count > 0xffffff || !(count & 1)))) {
|
|
||||||
if (output_size > 0) output[0] = '\0';
|
|
||||||
__set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!count) count = 725;
|
|
||||||
|
|
||||||
output[0] = '_';
|
|
||||||
output[1] = _crypt_itoa64[count & 0x3f];
|
|
||||||
output[2] = _crypt_itoa64[(count >> 6) & 0x3f];
|
|
||||||
output[3] = _crypt_itoa64[(count >> 12) & 0x3f];
|
|
||||||
output[4] = _crypt_itoa64[(count >> 18) & 0x3f];
|
|
||||||
value = (unsigned long)(unsigned char)input[0] |
|
|
||||||
((unsigned long)(unsigned char)input[1] << 8) |
|
|
||||||
((unsigned long)(unsigned char)input[2] << 16);
|
|
||||||
output[5] = _crypt_itoa64[value & 0x3f];
|
|
||||||
output[6] = _crypt_itoa64[(value >> 6) & 0x3f];
|
|
||||||
output[7] = _crypt_itoa64[(value >> 12) & 0x3f];
|
|
||||||
output[8] = _crypt_itoa64[(value >> 18) & 0x3f];
|
|
||||||
output[9] = '\0';
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count,
|
|
||||||
const char *input, int size, char *output, int output_size)
|
|
||||||
{
|
|
||||||
unsigned long value;
|
|
||||||
|
|
||||||
(void) prefix;
|
|
||||||
|
|
||||||
if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000)) {
|
|
||||||
if (output_size > 0) output[0] = '\0';
|
|
||||||
__set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
output[0] = '$';
|
|
||||||
output[1] = '1';
|
|
||||||
output[2] = '$';
|
|
||||||
value = (unsigned long)(unsigned char)input[0] |
|
|
||||||
((unsigned long)(unsigned char)input[1] << 8) |
|
|
||||||
((unsigned long)(unsigned char)input[2] << 16);
|
|
||||||
output[3] = _crypt_itoa64[value & 0x3f];
|
|
||||||
output[4] = _crypt_itoa64[(value >> 6) & 0x3f];
|
|
||||||
output[5] = _crypt_itoa64[(value >> 12) & 0x3f];
|
|
||||||
output[6] = _crypt_itoa64[(value >> 18) & 0x3f];
|
|
||||||
output[7] = '\0';
|
|
||||||
|
|
||||||
if (size >= 6 && output_size >= 3 + 4 + 4 + 1) {
|
|
||||||
value = (unsigned long)(unsigned char)input[3] |
|
|
||||||
((unsigned long)(unsigned char)input[4] << 8) |
|
|
||||||
((unsigned long)(unsigned char)input[5] << 16);
|
|
||||||
output[7] = _crypt_itoa64[value & 0x3f];
|
|
||||||
output[8] = _crypt_itoa64[(value >> 6) & 0x3f];
|
|
||||||
output[9] = _crypt_itoa64[(value >> 12) & 0x3f];
|
|
||||||
output[10] = _crypt_itoa64[(value >> 18) & 0x3f];
|
|
||||||
output[11] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
30
deps/crypt_blowfish/crypt_gensalt.h
vendored
30
deps/crypt_blowfish/crypt_gensalt.h
vendored
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
|
||||||
* No copyright is claimed, and the software is hereby placed in the public
|
|
||||||
* domain. In case this attempt to disclaim copyright and place the software
|
|
||||||
* in the public domain is deemed null and void, then the software is
|
|
||||||
* Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
|
||||||
* general public under the following terms:
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted.
|
|
||||||
*
|
|
||||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
|
||||||
*
|
|
||||||
* See crypt_blowfish.c for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _CRYPT_GENSALT_H
|
|
||||||
#define _CRYPT_GENSALT_H
|
|
||||||
|
|
||||||
extern unsigned char _crypt_itoa64[];
|
|
||||||
extern char *_crypt_gensalt_traditional_rn(const char *prefix,
|
|
||||||
unsigned long count,
|
|
||||||
const char *input, int size, char *output, int output_size);
|
|
||||||
extern char *_crypt_gensalt_extended_rn(const char *prefix,
|
|
||||||
unsigned long count,
|
|
||||||
const char *input, int size, char *output, int output_size);
|
|
||||||
extern char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count,
|
|
||||||
const char *input, int size, char *output, int output_size);
|
|
||||||
|
|
||||||
#endif
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user