Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
e55548b105 | |||
cea3f7e33c |
@ -14,7 +14,7 @@ IndentWidth: 4
|
||||
MaxEmptyLinesToKeep: 1
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCBreakBeforeNestedBlockParam: false
|
||||
SortIncludes: true
|
||||
SortIncludes: false
|
||||
TabWidth: 4
|
||||
UseTab: Always
|
||||
...
|
||||
|
40
.fdroid.yml
Normal file
40
.fdroid.yml
Normal file
@ -0,0 +1,40 @@
|
||||
Categories:
|
||||
- Internet
|
||||
License: MIT
|
||||
|
||||
AutoName: tildefriends
|
||||
AuthorName: Cory McWilliams
|
||||
AuthorEmail: cory@tildefriends.net
|
||||
|
||||
RepoType: git
|
||||
Repo: https://dev.tildefriends.net/cory/tildefriends.git
|
||||
|
||||
Builds:
|
||||
- versionName: 0.0.21-wip
|
||||
versionCode: 22
|
||||
commit: 09b6a00731d45fa160b23a2c44be6def98d92d6a
|
||||
subdir: src/android
|
||||
submodules: true
|
||||
sudo:
|
||||
- apt-get update
|
||||
- apt-get install -y ant make zip
|
||||
androidupdate:
|
||||
- no
|
||||
scandelete:
|
||||
- deps/libuv/docs/src/static/diagrams.key/Index.zip
|
||||
- deps/openssl_src/cloudflare-quiche/*
|
||||
- deps/openssl_src/fuzz/*
|
||||
- deps/openssl_src/gost-engine/*
|
||||
- deps/openssl_src/test/*
|
||||
- deps/openssl_src/tlslite-ng/*
|
||||
prebuild:
|
||||
- sdkmanager "platforms;android-34" "build-tools;34.0.0"
|
||||
build:
|
||||
- mkdir bin/
|
||||
- ANDROID_SDK=$$SDK$$ ANDROID_NDK=$$NDK$$ ANDROID_NDK_ROOT=$$NDK$$ make -C ../../ -j`nproc` fdroid
|
||||
ndk: r26d
|
||||
|
||||
AutoUpdateMode: Version ^v[0-9\.]+$
|
||||
UpdateCheckMode: Tags
|
||||
CurrentVersion: 0.0.21-wip
|
||||
CurrentVersionCode: 22
|
@ -5,34 +5,11 @@ 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: sudo apt update && sudo apt install -y doxygen mingw-w64
|
||||
- run: make all -j`nproc` 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
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,7 +4,6 @@ db.*
|
||||
deps/ios_toolchain/
|
||||
deps/openssl/
|
||||
dist/
|
||||
.flatpak-builder
|
||||
.keys
|
||||
logs/
|
||||
**/node_modules
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -26,6 +26,3 @@
|
||||
[submodule "deps/c-ares"]
|
||||
path = deps/c-ares
|
||||
url = https://github.com/c-ares/c-ares.git
|
||||
[submodule "docs"]
|
||||
path = docs
|
||||
url = https://dev.tildefriends.net/cory/tildefriends.wiki.git
|
||||
|
428
GNUmakefile
428
GNUmakefile
@ -3,27 +3,13 @@
|
||||
MAKEFLAGS += --warn-undefined-variables
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
## == Tilde Friends build. ==
|
||||
##
|
||||
## This is a list of all supported build targets.
|
||||
##
|
||||
## Consider passing -j$(nproc) or adding it to your $MAKEFLAGS to build in
|
||||
## parallel (faster).
|
||||
##
|
||||
## Useful variables to override:
|
||||
## CC := Compiler.
|
||||
## AS := Assembler.
|
||||
## LD := Linker.
|
||||
## ANDROID_SDK := Path to the Android SDK.
|
||||
VERSION_CODE := 26
|
||||
VERSION_NUMBER := 0.0.22-wip
|
||||
VERSION_NAME := Look for the helpers.
|
||||
|
||||
VERSION_CODE := 31
|
||||
VERSION_NUMBER := 0.0.26-wip
|
||||
VERSION_NAME := This program kills fascists.
|
||||
|
||||
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3470200.zip
|
||||
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3460000.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
|
||||
BUILD_DIR ?= out
|
||||
@ -50,8 +36,7 @@ BUILD_TYPES := debug release
|
||||
CFLAGS += -Dstatic_assert=_Static_assert
|
||||
LDFLAGS += \
|
||||
-lbsd \
|
||||
-lnetwork \
|
||||
-Wno-stringop-overflow
|
||||
-lnetwork
|
||||
else ifeq ($(UNAME_S),OpenBSD)
|
||||
BUILD_TYPES := debug release
|
||||
CFLAGS += \
|
||||
@ -70,17 +55,16 @@ CFLAGS += \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-unknown-warning-option \
|
||||
-MMD \
|
||||
-MP \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-fno-exceptions \
|
||||
-g
|
||||
-g \
|
||||
-flto
|
||||
LDFLAGS += \
|
||||
-Wno-attributes \
|
||||
-Wno-aggressive-loop-optimizations \
|
||||
-flto=auto
|
||||
-flto=auto \
|
||||
-Wno-attributes
|
||||
|
||||
ANDROID_MIN_SDK_VERSION := 24
|
||||
ANDROID_TARGET_SDK_VERSION := 34
|
||||
@ -176,9 +160,6 @@ NONANDROID_RELEASE_TARGETS := $(filter-out $(ANDROID_ARM64_TARGETS),$(RELEASE_TA
|
||||
NONANDROID_TARGETS := $(filter-out $(ANDROID_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
|
||||
$(filter-out $(WINDOWS_TARGETS),$(ALL_TARGETS)): LDFLAGS += -rdynamic
|
||||
@ -188,13 +169,10 @@ $(ANDROID_TARGETS): CFLAGS += \
|
||||
-fdebug-compilation-dir . \
|
||||
-fomit-frame-pointer \
|
||||
-fno-asynchronous-unwind-tables \
|
||||
-funwind-tables \
|
||||
-Wno-unknown-warning-option
|
||||
-funwind-tables
|
||||
$(ANDROID_TARGETS): LDFLAGS += --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC
|
||||
$(DEBUG_TARGETS): CFLAGS += -DDEBUG -Og
|
||||
$(RELEASE_TARGETS): CFLAGS += \
|
||||
-DNDEBUG \
|
||||
-flto
|
||||
$(RELEASE_TARGETS): CFLAGS += -DNDEBUG
|
||||
$(NONANDROID_RELEASE_TARGETS): CFLAGS += -O3
|
||||
$(ANDROID_RELEASE_TARGETS): CFLAGS += -Oz
|
||||
$(WINDOWS_TARGETS): CC = x86_64-w64-mingw32-gcc-win32
|
||||
@ -238,15 +216,12 @@ $(ANDROID_X86_64_TARGETS): CFLAGS += -Ideps/openssl/android/x86_64/usr/local/inc
|
||||
$(ANDROID_X86_64_TARGETS): LDFLAGS += -Ldeps/openssl/android/x86_64/usr/local/lib
|
||||
$(NONMACOS_TARGETS): CFLAGS += -Wno-cast-function-type
|
||||
$(DEADSTRIP_TARGETS): LDFLAGS += -Wl,--gc-sections
|
||||
$(IOS_TARGETS): CFLAGS += -miphoneos-version-min=9.0 -Ideps/openssl/ios/ios64-xcrun/usr/local/include
|
||||
$(IOS_TARGETS): LDFLAGS += -miphoneos-version-min=9.0 -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib
|
||||
$(IOS_TARGETS): CFLAGS += -mios-version-min=9.0 -Ideps/openssl/ios/ios64-xcrun/usr/local/include
|
||||
$(IOS_TARGETS): LDFLAGS += -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib
|
||||
$(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include
|
||||
$(IOSSIM_TARGETS): LDFLAGS += -Ldeps/openssl/ios/iossimulator-xcrun/usr/local/lib
|
||||
|
||||
ifeq ($(UNAME_M),x86_64)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
all: appimage
|
||||
endif
|
||||
ifneq ($(UNAME_S),Haiku)
|
||||
out/debug/tildefriends: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common
|
||||
out/debug/tildefriends: LDFLAGS += -fsanitize=address -fsanitize=undefined
|
||||
@ -294,101 +269,98 @@ $(filter-out $(BUILD_DIR)/android% $(BUILD_DIR)/macos% $(BUILD_DIR)/ios%,$(APP_O
|
||||
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_platform.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_mapping.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_parse.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_write.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_name.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_record.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_multistring.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_data.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/ares_cancel.c \
|
||||
deps/c-ares/src/lib/ares_metrics.c \
|
||||
deps/c-ares/src/lib/ares_getnameinfo.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_txt_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_naptr_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_create_query.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_mx_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_srv_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_ptr_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_caa_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_expand_name.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_uri_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_a_reply.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/legacy/ares_getsock.c \
|
||||
deps/c-ares/src/lib/windows_port.c \
|
||||
deps/c-ares/src/lib/ares_qcache.c \
|
||||
deps/c-ares/src/lib/ares_update_servers.c \
|
||||
deps/c-ares/src/lib/ares_process.c \
|
||||
deps/c-ares/src/lib/ares_getenv.c \
|
||||
deps/c-ares/src/lib/ares_gethostbyname.c \
|
||||
deps/c-ares/src/lib/ares_send.c \
|
||||
deps/c-ares/src/lib/dsa/ares__slist.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable.c \
|
||||
deps/c-ares/src/lib/dsa/ares__llist.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable_szvp.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable_asvp.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable_vpvp.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable_strvp.c \
|
||||
deps/c-ares/src/lib/dsa/ares__array.c \
|
||||
deps/c-ares/src/lib/ares__socket.c \
|
||||
deps/c-ares/src/lib/event/ares_event_poll.c \
|
||||
deps/c-ares/src/lib/event/ares_event_thread.c \
|
||||
deps/c-ares/src/lib/event/ares_event_select.c \
|
||||
deps/c-ares/src/lib/event/ares_event_kqueue.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_wake_pipe.c \
|
||||
deps/c-ares/src/lib/event/ares_event_win32.c \
|
||||
deps/c-ares/src/lib/ares_search.c \
|
||||
deps/c-ares/src/lib/ares__parse_into_addrinfo.c \
|
||||
deps/c-ares/src/lib/ares__hosts_file.c \
|
||||
deps/c-ares/src/lib/ares_getaddrinfo.c \
|
||||
deps/c-ares/src/lib/ares__addrinfo2hostent.c \
|
||||
deps/c-ares/src/lib/ares_freeaddrinfo.c \
|
||||
deps/c-ares/src/lib/ares_strerror.c \
|
||||
deps/c-ares/src/lib/ares_version.c \
|
||||
deps/c-ares/src/lib/ares_gethostbyaddr.c \
|
||||
deps/c-ares/src/lib/ares__addrinfo_localhost.c \
|
||||
deps/c-ares/src/lib/ares_free_hostent.c \
|
||||
deps/c-ares/src/lib/ares__close_sockets.c \
|
||||
deps/c-ares/src/lib/ares_free_string.c \
|
||||
deps/c-ares/src/lib/ares_init.c \
|
||||
deps/c-ares/src/lib/ares_options.c \
|
||||
deps/c-ares/src/lib/str/ares_strcasecmp.c \
|
||||
deps/c-ares/src/lib/str/ares__buf.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/str/ares_str.c \
|
||||
deps/c-ares/src/lib/ares_sysconfig_mac.c \
|
||||
deps/c-ares/src/lib/ares__sortaddrinfo.c \
|
||||
deps/c-ares/src/lib/ares_sysconfig_files.c \
|
||||
deps/c-ares/src/lib/util/ares__iface_ips.c \
|
||||
deps/c-ares/src/lib/util/ares__timeval.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/util/ares__threads.c \
|
||||
deps/c-ares/src/lib/ares_query.c \
|
||||
deps/c-ares/src/lib/ares_cookie.c \
|
||||
deps/c-ares/src/lib/inet_net_pton.c \
|
||||
deps/c-ares/src/lib/inet_ntop.c \
|
||||
deps/c-ares/src/lib/ares_library_init.c \
|
||||
deps/c-ares/src/lib/ares_android.c \
|
||||
deps/c-ares/src/lib/ares_sysconfig_win.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 \
|
||||
@ -522,17 +494,10 @@ $(UV_OBJS): CFLAGS += \
|
||||
-Wno-incompatible-pointer-types \
|
||||
-Wno-maybe-uninitialized \
|
||||
-Wno-sign-compare \
|
||||
-Wno-unknown-attributes \
|
||||
-Wno-unused-but-set-parameter \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-unused-result \
|
||||
-Wno-unused-variable \
|
||||
-Wno-nonnull
|
||||
$(UV_OBJS): CFLAGS += -fno-lto
|
||||
$(filter out/win%,$(UV_OBJS)): \
|
||||
CFLAGS += \
|
||||
-Wno-cast-function-type \
|
||||
-Wno-missing-braces
|
||||
-Wno-unused-variable
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
$(UV_OBJS): CFLAGS += \
|
||||
-D_GNU_SOURCE
|
||||
@ -760,28 +725,11 @@ $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
||||
-framework UIKit \
|
||||
-framework WebKit
|
||||
|
||||
##
|
||||
## Common targets:
|
||||
##
|
||||
debug: ## Build a debug executable for the current platform.
|
||||
release: ## Build a release executable for the current platform.
|
||||
all: $(BUILD_TYPES) ## Build all targets that appear possible to build on this machine.
|
||||
unix: debug release ## Build all UNIX targets.
|
||||
win: windebug winrelease ## Build all Windows targets.
|
||||
unix: debug release
|
||||
win: windebug winrelease
|
||||
all: $(BUILD_TYPES)
|
||||
.PHONY: all win unix
|
||||
|
||||
##
|
||||
## Windows targets:
|
||||
##
|
||||
windebug: ## Build a debug win32 executable.
|
||||
winrelease: ## Build a release win32 executable.
|
||||
|
||||
##
|
||||
## MacOS targets:
|
||||
##
|
||||
macosdebug: ## Build a MacOS debug executable.
|
||||
macosrelease: ## Build a MacOS release executable.
|
||||
|
||||
ALL_APP_OBJS := \
|
||||
$(APP_OBJS) \
|
||||
$(ARES_OBJS) \
|
||||
@ -837,18 +785,7 @@ src/android/AndroidManifest.xml : $(firstword $(MAKEFILE_LIST))
|
||||
-e 's/android:targetSdkVersion="[[:digit:]]*"/android:targetSdkVersion="$(ANDROID_TARGET_SDK_VERSION)"/' \
|
||||
$@
|
||||
|
||||
##
|
||||
## Android targets:
|
||||
##
|
||||
androiddebug: ## Build a debug 64-bit ARM Android APK.
|
||||
androidrelease: ## Build a release 64-bit ARM Android APK.
|
||||
androiddebug-armv7a: ## Build a debug 32-bit ARM Android APK.
|
||||
androidrelease-armv7a: ## Build a release 32-bit ARM Android APK.
|
||||
androiddebug-x86: ## Build a debug x86 Android APK.
|
||||
androidrelease-x86: ## Build a release x86 Android APK.
|
||||
androiddebug-x86_64: ## Build a debug x86_64 Android APK.
|
||||
androidrelease-x86_64: ## Build a release x86_64 Android APK.
|
||||
|
||||
# Android support.
|
||||
out/res/layout_activity_main.xml.flat: src/android/res/layout/activity_main.xml
|
||||
@mkdir -p $(dir $@)
|
||||
@echo "[aapt2] $@"
|
||||
@ -899,7 +836,7 @@ PACKAGE_DIRS := \
|
||||
deps/prettier/ \
|
||||
deps/lit/
|
||||
|
||||
RAW_FILES := $(sort $(filter-out apps/blog% apps/issues% apps/welcome% apps/journal% %.map, $(shell find $(PACKAGE_DIRS) -type f -not -name '.*')))
|
||||
RAW_FILES := $(sort $(filter-out apps/blog% apps/issues% apps/welcome% apps/journal% %.map, $(shell find $(PACKAGE_DIRS) -type f)))
|
||||
|
||||
out/apk/TildeFriends-arm-debug.unsigned.apk: BUILD_TYPE := debug
|
||||
out/apk/TildeFriends-arm-release.unsigned.apk: BUILD_TYPE := release
|
||||
@ -955,7 +892,7 @@ out/TildeFriends.aab: out/apk/classes.dex $(filter-out %debug%, $(ANDROID_TARGET
|
||||
@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 ## Build an Android App Bundle.
|
||||
aab: out/TildeFriends.aab
|
||||
.PHONY: aab
|
||||
|
||||
out/TildeFriends.apks: out/TildeFriends.aab $(BUNDLETOOL)
|
||||
@ -1022,32 +959,20 @@ out/%.zopfli.apk: out/%.apk
|
||||
$(ANDROID_BUILD_TOOLS)/zipalign -f -z 4 $< $@.zopfli
|
||||
@$(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 $@ $@.zopfli
|
||||
|
||||
release-apk: out/TildeFriends-arm-release.zopfli.apk out/TildeFriends-x86-release.zopfli.apk ## Build an Android release APK.
|
||||
release-apk: out/TildeFriends-arm-release.zopfli.apk out/TildeFriends-x86-release.zopfli.apk
|
||||
.PHONY: release-apk
|
||||
|
||||
fdroid: out/apk/TildeFriends-release.fdroid.unsigned.apk ## Build Android APK for distribution on F-Droid.
|
||||
.PHONY: fdroid
|
||||
|
||||
apkgo: out/TildeFriends-arm-debug.apk ## Build, install, and run a debug Android 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 ## Build, install, and run a release Android APK.
|
||||
releaseapkgo: out/TildeFriends-arm-release.apk
|
||||
@adb install -r $<
|
||||
@adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity
|
||||
.PHONY: releaseapkgo
|
||||
|
||||
apklog: ## Display Android log output.
|
||||
@adb logcat *:S tildefriends
|
||||
.PHONY: apklog
|
||||
|
||||
##
|
||||
## iPhoneOS targets:
|
||||
##
|
||||
iosdebug: ## Build a debug iPhoneOS executable.
|
||||
iosrelease: ## Build a release iPhoneOS executable.
|
||||
|
||||
# iOS Support
|
||||
out/%.app/Info.plist: src/ios/Info.plist
|
||||
@mkdir -p $(dir $@)
|
||||
@cp -v $< $@
|
||||
@ -1061,7 +986,6 @@ out/data.zip: $(RAW_FILES)
|
||||
out/tildefriends-%.app/tildefriends: out/%/tildefriends out/tildefriends-%.app/Info.plist out/tildefriends-%.app/tildefriends.png out/data.zip
|
||||
@mkdir -p $(dir $@)
|
||||
@cp -v $< $@
|
||||
@cp -v out/data.zip $(@D)/
|
||||
ifeq ($(HAVE_LINUX_IOS),1)
|
||||
@zsign -q -k .keys/apple.p12 -f -m src/ios/embedded.mobileprovision $(realpath $(dir $@))
|
||||
endif
|
||||
@ -1084,23 +1008,43 @@ out/%/tildefriends.standalone.exe: out/%/tildefriends.exe out/data.zip
|
||||
@cat $< out/data.zip > $@
|
||||
@chmod +x $@
|
||||
|
||||
iossimdebug-app: out/tildefriends-iossimdebug.app/tildefriends ## Build a debug iOS Simulator .app directory.
|
||||
iossimrelease-app: out/tildefriends-iossimrelease.app/tildefriends ## Build a release iOS Simulator .app directory.
|
||||
iosdebug-app: out/tildefriends-iosdebug.app/tildefriends ## Build a debug iOS .app directory.
|
||||
iosrelease-app: out/tildefriends-iosrelease.app/tildefriends ## Build a release iOS .app directory.
|
||||
iossimdebug-app: out/tildefriends-iossimdebug.app/tildefriends
|
||||
iossimrelease-app: out/tildefriends-iossimrelease.app/tildefriends
|
||||
iosdebug-app: out/tildefriends-iosdebug.app/tildefriends
|
||||
iosrelease-app: out/tildefriends-iosrelease.app/tildefriends
|
||||
|
||||
iosdebug-ipa: out/tildefriends-debug.ipa ## Build a debug iOS .ipa.
|
||||
iosrelease-ipa: out/tildefriends-release.ipa ## Build a release iOS .ipa.
|
||||
iosdebug-ipa: out/tildefriends-debug.ipa
|
||||
iosrelease-ipa: out/tildefriends-release.ipa
|
||||
.PHONY: iossimdebug-app iossimrelease-app iosdebug-app iosrelease-app
|
||||
|
||||
ios%go: out/tildefriends-ios%.app/tildefriends
|
||||
ideviceinstaller -i $(realpath $(dir $<))
|
||||
|
||||
iossimdebuggo: out/tildefriends-iossimdebug.app/tildefriends ## Build, install, and run an iOS debug build.
|
||||
iossimdebuggo: out/tildefriends-iossimdebug.app/tildefriends
|
||||
xcrun simctl install booted out/tildefriends-iossimdebug.app/
|
||||
xcrun simctl launch booted com.unprompted.tildefriends
|
||||
.PHONY: iossimdebuggo
|
||||
|
||||
apklog:
|
||||
@adb logcat *:S tildefriends
|
||||
.PHONY: apklog
|
||||
|
||||
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"
|
||||
@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)
|
||||
@echo -n $(SQLITE_URL) > out/deps/sqlite.txt
|
||||
@echo "[fetch] prettier"
|
||||
@test -f deps/prettier/standalone.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/standalone.mjs
|
||||
@test -f deps/prettier/html.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/plugins/html.mjs
|
||||
@test -f deps/prettier/babel.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/plugins/babel.mjs
|
||||
@test -f deps/prettier/estree.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/plugins/estree.mjs
|
||||
.PHONY: fetchdeps
|
||||
|
||||
ANDROID_DEPS := deps/openssl/android/arm64-v8a/usr/local/lib/libssl.a
|
||||
$(ANDROID_DEPS):
|
||||
+@ANDROID_NDK_ROOT=$(ANDROID_NDK) tools/ssl-android
|
||||
@ -1120,62 +1064,14 @@ $(IOS_DEPS):
|
||||
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(IOS_DEPS)
|
||||
endif
|
||||
|
||||
##
|
||||
## Linux package targets:
|
||||
##
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
.PHONY: clean
|
||||
|
||||
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 ## Build an AppImage.
|
||||
.PHONY: appimage
|
||||
|
||||
flatpak: out/ ## Build a flatpak.
|
||||
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
|
||||
|
||||
##
|
||||
## Targets for release management:
|
||||
##
|
||||
|
||||
fetchdeps: ## Update various external sources that live in the tree that can't be pulled in as git submodules.
|
||||
@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 -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)
|
||||
@echo -n $(SQLITE_URL) > out/deps/sqlite.txt
|
||||
@echo "[fetch] prettier"
|
||||
@test -f deps/prettier/standalone.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/standalone.mjs
|
||||
@test -f deps/prettier/html.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/plugins/html.mjs
|
||||
@test -f deps/prettier/babel.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/plugins/babel.mjs
|
||||
@test -f deps/prettier/estree.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/plugins/estree.mjs
|
||||
.PHONY: fetchdeps
|
||||
|
||||
shots: ## Copy generated screenshots from `tildefriends test -t=auto` into place in the metadata/ directory.
|
||||
@echo [shots] $(wildcard out/screenshot*.png)
|
||||
@cp -f out/screenshot*.png metadata/en-US/images/phoneScreenshots/
|
||||
.PHONY: shots
|
||||
|
||||
tarball: ## Build an all-inclusive source tarball (.tar.xz).
|
||||
@echo [archive] out/tildefriends-$(VERSION_NUMBER).tar.xz
|
||||
dist: release-apk iosrelease-ipa aab $(if $(HAVE_WIN), out/winrelease/tildefriends.standalone.exe) out/TildeFriends-release.fdroid.apk
|
||||
@echo [archive] dist/tildefriends-$(VERSION_NUMBER).tar.xz
|
||||
@rm -rf out/tildefriends-$(VERSION_NUMBER)
|
||||
@mkdir -p out/tildefriends-$(VERSION_NUMBER)
|
||||
@mkdir -p dist/ out/tildefriends-$(VERSION_NUMBER)
|
||||
@git ls-files --recurse-submodules | tar -c -T- | tar -x -C out/tildefriends-$(VERSION_NUMBER)
|
||||
@tar \
|
||||
--exclude=apps/welcome* \
|
||||
@ -1192,16 +1088,9 @@ tarball: ## Build an all-inclusive source tarball (.tar.xz).
|
||||
--exclude=deps/sqlite/shell.c \
|
||||
--exclude=deps/zlib/contrib/vstudio \
|
||||
--exclude=deps/zlib/doc \
|
||||
-caf out/tildefriends-$(VERSION_NUMBER).tar.xz \
|
||||
-caf dist/tildefriends-$(VERSION_NUMBER).tar.xz \
|
||||
-C out/ \
|
||||
tildefriends-$(VERSION_NUMBER)
|
||||
.PHONY: tarball
|
||||
|
||||
dist: ## Build versions of all distributables for release.
|
||||
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"
|
||||
@cp out/TildeFriends-x86-release.zopfli.apk dist/TildeFriends-x86-$(VERSION_NUMBER).apk
|
||||
@echo "[cp] TildeFriends-arm-$(VERSION_NUMBER).apk"
|
||||
@ -1210,61 +1099,28 @@ dist: release-apk iosrelease-ipa aab $(if $(HAVE_WIN), out/winrelease/tildefrien
|
||||
@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
|
||||
|
||||
dist-test: dist ## Exercise some built distributable files, making sure they work as intended.
|
||||
dist-test: dist
|
||||
@tar -xf tildefriends-$(VERSION_NUMBER).tar.xz
|
||||
@$(MAKE) -C tildefriends-$(VERSION_NUMBER)/ debug release
|
||||
@docker build tildefriends-$(VERSION_NUMBER)/
|
||||
@rm -rf tildefriends-$(VERSION_NUMBER)
|
||||
.PHONY: dist-test
|
||||
|
||||
##
|
||||
## Targets for tidying up:
|
||||
##
|
||||
|
||||
format: ## Standardize formatting of C source.
|
||||
format:
|
||||
@clang-format -i $(wildcard src/*.c src/*.h src/*.m)
|
||||
.PHONY: format
|
||||
|
||||
prettier: ## Standardize formatting of JavaScript and Markdown source.
|
||||
prettier:
|
||||
@npm run prettier
|
||||
.PHONY: prettier
|
||||
|
||||
clean: ## Clean all generated files from the out/ directory.
|
||||
rm -rf $(BUILD_DIR)
|
||||
.PHONY: clean
|
||||
|
||||
##
|
||||
## Documentation:
|
||||
##
|
||||
help: ## Display this help message.
|
||||
@awk \
|
||||
-F: \
|
||||
-vG=$$(tput setaf 2) \
|
||||
-vO=$$(tput setaf 3) \
|
||||
-vB=$$(tput setaf 4) \
|
||||
-vM=$$(tput setaf 5) \
|
||||
-vC=$$(tput setaf 6) \
|
||||
-vR=$$(tput sgr0) ' \
|
||||
/^## ==.*==$$/ { sub(/^## ?/, ""); printf "%s%s%s\n", C, $$0, R } \
|
||||
/^##.*:=.*/ { sub(/^## ?/, ""); sub(/:=/, ":"); printf " %s%-20s%s %s%s%s\n", M, $$1, R, O, $$2, R } \
|
||||
/^##/ { sub(/^## ?/, ""); print $$0 } \
|
||||
/^[[:alnum:]-]+:.*##/ { \
|
||||
sub(/:.*##\s?/, ":"); \
|
||||
printf " %s%-20s%s %s%s%s\n", G, $$1, R, O, $$2, R \
|
||||
} \
|
||||
' < $(filter-out %.d,$(MAKEFILE_LIST))
|
||||
@echo "" # Blank line.
|
||||
.PHONY: help
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
docs: ## Build HTML docs.
|
||||
docs:
|
||||
@doxygen
|
||||
.PHONY: docs
|
||||
|
||||
fdroid: out/apk/TildeFriends-release.fdroid.unsigned.apk
|
||||
.PHONE: fdroid
|
||||
|
56
README.md
56
README.md
@ -14,53 +14,25 @@ Scuttlebutt, as well as a platform for writing and running web applications.
|
||||
3. Make creating and sharing web applications accessible to anyone with a
|
||||
browser.
|
||||
|
||||
## Getting the Source
|
||||
|
||||
Tilde Friends uses git submodules, so either:
|
||||
|
||||
```
|
||||
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.
|
||||
|
||||
## Building
|
||||
|
||||
Builds on Linux (x86_64 and aarch64), MacOS, OpenBSD, and Haiku. It's possible
|
||||
to build for Android, iOS, and Windows on Linux, if you have the right
|
||||
dependencies in the right places.
|
||||
Builds on Linux (x86_64 and aarch64), MacOS, OpenBSD, and Haiku. Builds for
|
||||
all of those host platforms plus mingw64, iOS, and android.
|
||||
|
||||
### Requirements
|
||||
|
||||
On Linux only, system OpenSSL libraries (`libssl-dev`, in debian-speak) are
|
||||
assumed to be available.
|
||||
|
||||
On MacOS, Xcode's command-line tools are expected to be available.
|
||||
|
||||
### Build Commands
|
||||
|
||||
Run `make` with no arguments to see available build targets and options. `make
|
||||
debug` is a good place to start.
|
||||
|
||||
To build in docker, `docker build .`.
|
||||
|
||||
`make format` and `make prettier` will normalize formatting to the coding
|
||||
standard.
|
||||
1. Requires openssl (`libssl-dev`, in debian-speak). All other dependencies
|
||||
are kept up to date in the tree.
|
||||
2. To build, run `make debug` or `make release`. An executable will be
|
||||
generated in a subdirectory of `out/`.
|
||||
3. It's possible to build for Android, iOS, and Windows on Linux, if you have
|
||||
the right dependencies in the right places. `make windebug winrelease
|
||||
iosdebug-ipa iosrelease-ipa release-apk`.
|
||||
4. To build in docker, `docker build .`.
|
||||
5. `make format` will normalize formatting to the coding standard.
|
||||
|
||||
## Running
|
||||
|
||||
By default, running the built `out/debug/tildefriends` executable will start a
|
||||
web server at <http://localhost:12345/>. It expects to be run with the
|
||||
repository root as the current working directory. `tildefriends -h` lists
|
||||
further options.
|
||||
By default, running the built `tildefriends` executable will start a web server
|
||||
at <http://localhost:12345/>. `tildefriends -h` lists further options.
|
||||
|
||||
The first user to create an account and log in will be granted administrative
|
||||
privileges. Further administration can be done at
|
||||
@ -69,7 +41,7 @@ privileges. Further administration can be done at
|
||||
## Documentation
|
||||
|
||||
Docs are a work in progress:
|
||||
<https://dev.tildefriends.net/cory/tildefriends/wiki>.
|
||||
<https://www.tildefriends.net/~cory/wiki/#test-wiki/tf-app-quick-reference>.
|
||||
|
||||
## License
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "🎛",
|
||||
"previous": "&R49FywYF8CXPhoSEydLbSCgvCddeyTiBwGuDU/gqY+M=.sha256"
|
||||
"previous": "&vrpS/vE7n588iYv1p8HafDxHB+YDHTrtUbJiu9nGA9I=.sha256"
|
||||
}
|
||||
|
@ -27,30 +27,23 @@ 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 () {
|
||||
const permission_template = (permission) => html` <code>${permission}</code>`;
|
||||
function input_template(key, description) {
|
||||
if (description.type === 'boolean') {
|
||||
return html`
|
||||
<li class="w3-row">
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${title_case(key)}</label>
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${key}</label>
|
||||
<div class="w3-quarter w3-padding">${description.description}</div>
|
||||
<div class="w3-quarter w3-padding w3-center"><input class="w3-check" type="checkbox" ?checked=${description.value} id=${'gs_' + key}></input></div>
|
||||
<button class="w3-quarter w3-button w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.firstChild.checked)}>Set</button>
|
||||
<input class="w3-quarter w3-check" type="checkbox" ?checked=${description.value} id=${'gs_' + key}></input>
|
||||
<button class="w3-quarter w3-button w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.checked)}>Set</button>
|
||||
</li>
|
||||
`;
|
||||
} else if (description.type === 'textarea') {
|
||||
return html`
|
||||
<li class="w3-row">
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold"
|
||||
>${title_case(key)}</label
|
||||
>${key}</label
|
||||
>
|
||||
<div class="w3-rest w3-padding">${description.description}</div>
|
||||
<textarea
|
||||
@ -75,7 +68,7 @@ ${description.value}</textarea
|
||||
} else {
|
||||
return html`
|
||||
<li class="w3-row">
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${title_case(key)}</label>
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${key}</label>
|
||||
<div class="w3-quarter w3-padding">${description.description}</div>
|
||||
<input class="w3-input w3-quarter" type="text" value="${description.value}" id=${'gs_' + key}></input>
|
||||
<button class="w3-button w3-quarter w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.value)}>Set</button>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "📜",
|
||||
"previous": "&BEf0nraBdHk/+PWqx6tOSu5rheWVaxaL7orAOz3285M=.sha256"
|
||||
"previous": "&miGORZ8BwjHg2YO0t4bms6SI28XWPYqnqOZ8u9zsbZc=.sha256"
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ function* treeify(prefix, o) {
|
||||
|
||||
function markdown(md) {
|
||||
let parsed = new commonmark.Parser().parse(md ?? '*undocumented*');
|
||||
return new commonmark.HtmlRenderer({safe: true}).render(parsed);
|
||||
return new commonmark.HtmlRenderer().render(parsed);
|
||||
}
|
||||
|
||||
function document(api) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "🪵",
|
||||
"previous": "&3jabNEk6W2uolzTvfXX6fcWF50N3501vtgZ6ZxFVJ1s=.sha256"
|
||||
"previous": "&TIrBnpN3iz3O9L9MCCteAcVJZjA83EKdcfu4SCM76VE=.sha256"
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ export async function get_blog_message(id) {
|
||||
}
|
||||
|
||||
export function markdown(md) {
|
||||
let reader = new commonmark.Parser();
|
||||
let writer = new commonmark.HtmlRenderer({safe: true});
|
||||
let reader = new commonmark.Parser({safe: true});
|
||||
let writer = new commonmark.HtmlRenderer();
|
||||
let parsed = reader.parse(md || '');
|
||||
let walker = parsed.walker();
|
||||
let event, node;
|
||||
|
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
44
apps/blog/lit-all.min.js
vendored
44
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,5 +1,4 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "💽",
|
||||
"previous": "&uQzkIe/Aj8yNhLKe3hEq+5fEJsGwIUx8NVBjJKwoV2U=.sha256"
|
||||
"emoji": "💽"
|
||||
}
|
||||
|
@ -51,19 +51,6 @@ async function key_list(db) {
|
||||
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) {
|
||||
if (message.event == 'hashChange') {
|
||||
let hash = message.hash.substring(1);
|
||||
@ -75,9 +62,9 @@ core.register('message', async function (message) {
|
||||
} else if (hash.length) {
|
||||
key_list(await database(hash.split(':').slice(1).join(':')));
|
||||
} else {
|
||||
load();
|
||||
database_list();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
load();
|
||||
database_list();
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "🪪",
|
||||
"previous": "&5kw/2PgcySwOYCmAkjHTR2xTkIx3i7UjQmtQ8MfgWw8=.sha256"
|
||||
"previous": "&de7q4A59auHP/34bXgeNH05JZoxsGr5TjwXPvehWH30=.sha256"
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
import * as tfrpc from '/tfrpc.js';
|
||||
|
||||
const is_admin = core.user?.credentials?.permissions?.administration;
|
||||
|
||||
tfrpc.register(async function get_private_key(id) {
|
||||
return bip39Words(await ssb.getPrivateKey(id));
|
||||
});
|
||||
@ -17,13 +15,9 @@ tfrpc.register(async function delete_id(id) {
|
||||
tfrpc.register(async function reload() {
|
||||
await main();
|
||||
});
|
||||
tfrpc.register(async function make_server(id) {
|
||||
return await ssb.swapWithServerIdentity(id);
|
||||
});
|
||||
|
||||
async function main() {
|
||||
let ids = await ssb.getIdentities();
|
||||
let server_id = await ssb.getServerIdentity();
|
||||
await app.setDocument(
|
||||
`
|
||||
<head>
|
||||
@ -104,16 +98,6 @@ async function main() {
|
||||
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>
|
||||
<header class="w3-theme w3-padding"><h1>SSB Identity Management</h1></header>
|
||||
<div class="w3-card-4 w3-margin">
|
||||
@ -132,15 +116,14 @@ async function main() {
|
||||
<div class="w3-card-4 w3-margin">
|
||||
<header class="w3-container w3-theme-l2"><h2>Identities</h2></header>
|
||||
<ul class="w3-ul">` +
|
||||
(ids ?? [])
|
||||
ids
|
||||
.map(
|
||||
(
|
||||
id
|
||||
) => `<li style="overflow: hidden; text-wrap: nowrap; text-overflow: ellipsis">
|
||||
<button onclick="handler.export_id(event)" data-id="${id}" class="w3-button w3-theme">Export Identity</button>
|
||||
<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>' : ''}
|
||||
${id}
|
||||
</li>`
|
||||
)
|
||||
.join('\n') +
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "🦟",
|
||||
"previous": "&O0huuEgL/UQC9bkUfhPOyZFo9eRiz+koOkba6QwCGNA=.sha256"
|
||||
"previous": "&cUqvSDUls3jn0haD85LPFAGdkc8wFuy347TtATNcJgg=.sha256"
|
||||
}
|
||||
|
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
44
apps/issues/lit-all.min.js
vendored
44
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
@ -1,11 +1,5 @@
|
||||
import * as linkify from './commonmark-linkify.js';
|
||||
|
||||
var reUnsafeProtocol = /^javascript:|vbscript:|file:|data:/i;
|
||||
var reSafeDataProtocol = /^data:image\/(?:png|gif|jpeg|webp)/i;
|
||||
var potentiallyUnsafe = function (url) {
|
||||
return reUnsafeProtocol.test(url) && !reSafeDataProtocol.test(url);
|
||||
};
|
||||
|
||||
function image(node, entering) {
|
||||
if (
|
||||
node.firstChild?.type === 'text' &&
|
||||
@ -67,8 +61,8 @@ function image(node, entering) {
|
||||
}
|
||||
|
||||
export function markdown(md) {
|
||||
var reader = new commonmark.Parser();
|
||||
var writer = new commonmark.HtmlRenderer({safe: true});
|
||||
var reader = new commonmark.Parser({safe: true});
|
||||
var writer = new commonmark.HtmlRenderer();
|
||||
writer.image = image;
|
||||
var parsed = reader.parse(md || '');
|
||||
parsed = linkify.transform(parsed);
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "📝",
|
||||
"previous": "&5LpOTEnor/rYFk3axyfmmehAoq9aEwNQRH4jwNhRQ7o=.sha256"
|
||||
"previous": "&b//KqE4Vx6kOSBRODK1p/8wjOLKZJ+CBB5IkaBt5YsM=.sha256"
|
||||
}
|
||||
|
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
44
apps/journal/lit-all.min.js
vendored
44
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
@ -18,8 +18,8 @@ class TfJournalEntryElement extends LitElement {
|
||||
}
|
||||
|
||||
markdown(md) {
|
||||
var reader = new commonmark.Parser();
|
||||
var writer = new commonmark.HtmlRenderer({safe: true});
|
||||
var reader = new commonmark.Parser({safe: true});
|
||||
var writer = new commonmark.HtmlRenderer();
|
||||
var parsed = reader.parse(md || '');
|
||||
return writer.render(parsed);
|
||||
}
|
||||
|
44
apps/sneaker/lit-all.min.js
vendored
44
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",
|
||||
"emoji": "🐌",
|
||||
"previous": "&0gBRfD+3EaZD2S82zAnXT3hgGuNTnUncOh5vGwZwbSw=.sha256"
|
||||
"previous": "&2xK//SIpjFb0+uT5I7MSAGJ3d1FKuI/rlzhcCQd3NME=.sha256"
|
||||
}
|
||||
|
@ -103,9 +103,6 @@ tfrpc.register(async function encrypt(id, recipients, content) {
|
||||
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());
|
||||
});
|
||||
|
@ -7,7 +7,7 @@ function textNode(text) {
|
||||
function linkNode(text, link) {
|
||||
const linkNode = new commonmark.Node('link', undefined);
|
||||
if (link.startsWith('#')) {
|
||||
linkNode.destination = `#${encodeURIComponent('#' + link)}`;
|
||||
linkNode.destination = `#q=${encodeURIComponent(link)}`;
|
||||
} else {
|
||||
linkNode.destination = link;
|
||||
}
|
||||
|
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
File diff suppressed because one or more lines are too long
44
apps/ssb/lit-all.min.js
vendored
44
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
@ -8,16 +8,10 @@ import * as tf_compose from './tf-compose.js';
|
||||
import * as tf_news from './tf-news.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_news from './tf-tab-news.js';
|
||||
import * as tf_tab_news_feed from './tf-tab-news-feed.js';
|
||||
import * as tf_tab_search from './tf-tab-search.js';
|
||||
import * as tf_tab_connections from './tf-tab-connections.js';
|
||||
import * as tf_tab_query from './tf-tab-query.js';
|
||||
import * as tf_tag from './tf-tag.js';
|
||||
import * as tf_styles from './tf-styles.js';
|
||||
|
||||
window.addEventListener('load', function () {
|
||||
let style = document.createElement('style');
|
||||
style.innerText = tf_styles.styles;
|
||||
document.body.appendChild(style);
|
||||
});
|
||||
|
@ -16,9 +16,7 @@ class TfElement extends LitElement {
|
||||
following: {type: Array},
|
||||
users: {type: Object},
|
||||
ids: {type: Array},
|
||||
channels: {type: Array},
|
||||
channels_unread: {type: Object},
|
||||
channels_latest: {type: Object},
|
||||
tags: {type: Array},
|
||||
};
|
||||
}
|
||||
|
||||
@ -35,9 +33,7 @@ class TfElement extends LitElement {
|
||||
this.following = [];
|
||||
this.users = {};
|
||||
this.loaded = false;
|
||||
this.channels = [];
|
||||
this.channels_unread = {};
|
||||
this.channels_latest = {};
|
||||
this.tags = [];
|
||||
tfrpc.rpc.getBroadcasts().then((b) => {
|
||||
self.broadcasts = b || [];
|
||||
});
|
||||
@ -68,76 +64,16 @@ class TfElement extends LitElement {
|
||||
let ids = (await tfrpc.rpc.getIdentities()) || [];
|
||||
this.whoami = whoami ?? (ids.length ? ids[0] : undefined);
|
||||
this.ids = ids;
|
||||
await this.load_channels();
|
||||
}
|
||||
|
||||
async load_channels() {
|
||||
let channels = await tfrpc.rpc.query(
|
||||
`
|
||||
SELECT
|
||||
content ->> 'channel' AS channel,
|
||||
content ->> 'subscribed' AS subscribed
|
||||
FROM
|
||||
messages
|
||||
WHERE
|
||||
author = ? AND
|
||||
content ->> 'type' = 'channel'
|
||||
ORDER BY sequence
|
||||
`,
|
||||
[this.whoami]
|
||||
);
|
||||
let channel_map = {};
|
||||
for (let row of channels) {
|
||||
if (row.subscribed) {
|
||||
channel_map[row.channel] = true;
|
||||
} else {
|
||||
delete channel_map[row.channel];
|
||||
}
|
||||
}
|
||||
this.channels = Object.keys(channel_map).sort();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this._keydown = this.keydown.bind(this);
|
||||
window.addEventListener('keydown', this._keydown);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
window.removeEventListener('keydown', this._keydown);
|
||||
}
|
||||
|
||||
keydown(event) {
|
||||
if (event.altKey && event.key == 'ArrowUp') {
|
||||
this.next_channel(1);
|
||||
event.preventDefault();
|
||||
} else if (event.altKey && event.key == 'ArrowDown') {
|
||||
this.next_channel(-1);
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
next_channel(delta) {
|
||||
let channel_names = ['', '@'].concat(this.channels);
|
||||
let index = channel_names.indexOf(this.hash.substring(1));
|
||||
if (index != -1) {
|
||||
index += delta;
|
||||
this.set_hash(
|
||||
'#' +
|
||||
encodeURIComponent(
|
||||
channel_names[(index + channel_names.length) % channel_names.length]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
set_hash(hash) {
|
||||
this.hash = decodeURIComponent(hash || '#');
|
||||
this.hash = hash || '#';
|
||||
if (this.hash.startsWith('#q=')) {
|
||||
this.tab = 'search';
|
||||
} else if (this.hash === '#connections') {
|
||||
this.tab = 'connections';
|
||||
} else if (this.hash === '#mentions') {
|
||||
this.tab = 'mentions';
|
||||
} else if (this.hash.startsWith('#sql=')) {
|
||||
this.tab = 'query';
|
||||
} else {
|
||||
@ -231,14 +167,6 @@ class TfElement extends LitElement {
|
||||
`,
|
||||
[JSON.stringify(this.following), id]
|
||||
);
|
||||
for (let message of messages) {
|
||||
if (message.author == this.whoami) {
|
||||
let content = JSON.parse(message.content);
|
||||
if (content?.type == 'channel') {
|
||||
this.load_channels();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (messages && messages.length) {
|
||||
this.unread = [...this.unread, ...messages];
|
||||
this.unread = this.unread.slice(this.unread.length - 1024);
|
||||
@ -267,36 +195,32 @@ class TfElement extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
async get_latest_private(following) {
|
||||
let latest = (await tfrpc.rpc.query('SELECT MAX(rowid) AS latest FROM messages'))[0].latest;
|
||||
const k_chunk_count = 256;
|
||||
while (latest - k_chunk_count >= 0) {
|
||||
let messages = await tfrpc.rpc.query(`
|
||||
SELECT messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||
FROM messages
|
||||
JOIN json_each(?1) AS following ON messages.author = following.value
|
||||
WHERE
|
||||
messages.rowid > ?2 AND
|
||||
messages.rowid <= ?3 AND
|
||||
json(messages.content) LIKE '"%'
|
||||
ORDER BY sequence DESC
|
||||
`,
|
||||
[
|
||||
JSON.stringify(following),
|
||||
latest - k_chunk_count,
|
||||
latest,
|
||||
]);
|
||||
messages = (await this.decrypt(messages)).filter(x => x.decrypted);
|
||||
if (messages.length) {
|
||||
return Math.max(...messages.map(x => x.rowid));
|
||||
}
|
||||
latest -= k_chunk_count;
|
||||
};
|
||||
return -1;
|
||||
async load_recent_tags() {
|
||||
let start = new Date();
|
||||
this.tags = await tfrpc.rpc.query(
|
||||
`
|
||||
WITH
|
||||
recent AS (SELECT id, json(content) AS content FROM messages
|
||||
WHERE messages.timestamp > ? AND json_extract(content, '$.type') = 'post'
|
||||
ORDER BY timestamp DESC LIMIT 1024),
|
||||
recent_channels AS (SELECT recent.id, '#' || json_extract(content, '$.channel') AS tag
|
||||
FROM recent
|
||||
WHERE json_extract(content, '$.channel') IS NOT NULL),
|
||||
recent_mentions AS (SELECT recent.id, json_extract(mention.value, '$.link') AS tag
|
||||
FROM recent, json_each(recent.content, '$.mentions') AS mention
|
||||
WHERE json_valid(mention.value) AND tag LIKE '#%'),
|
||||
combined AS (SELECT id, tag FROM recent_channels UNION ALL SELECT id, tag FROM recent_mentions),
|
||||
by_message AS (SELECT DISTINCT id, tag FROM combined)
|
||||
SELECT tag, COUNT(*) AS count FROM by_message GROUP BY tag ORDER BY count DESC LIMIT 10
|
||||
`,
|
||||
[new Date() - 7 * 24 * 60 * 60 * 1000]
|
||||
);
|
||||
console.log('tags took', (new Date() - start) / 1000.0, 'seconds');
|
||||
}
|
||||
|
||||
async load() {
|
||||
let whoami = this.whoami;
|
||||
let tags = this.load_recent_tags();
|
||||
let following = await tfrpc.rpc.following([whoami], 2);
|
||||
let users = {};
|
||||
let by_count = [];
|
||||
@ -309,31 +233,7 @@ class TfElement extends LitElement {
|
||||
};
|
||||
by_count.push({count: v.of, id: id});
|
||||
}
|
||||
let channels = tfrpc.rpc.query(
|
||||
`
|
||||
SELECT channels.value AS channel, MAX(messages.rowid) AS rowid FROM messages
|
||||
JOIN json_each(?1) AS channels ON messages.content ->> 'channel' = channels.value
|
||||
JOIN json_each(?2) AS following ON messages.author = following.value
|
||||
WHERE messages.content ->> 'type' = 'post' AND messages.content ->> 'root' IS NULL
|
||||
GROUP by channel
|
||||
UNION
|
||||
SELECT '' AS channel, MAX(messages.rowid) AS rowid FROM messages
|
||||
JOIN json_each(?2) AS following ON messages.author = following.value
|
||||
UNION
|
||||
SELECT '@' AS channel, MAX(messages.rowid) AS rowid FROM messages_fts(?3)
|
||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||
JOIN json_each(?2) AS following ON messages.author = following.value
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.channels),
|
||||
JSON.stringify(Object.keys(following)),
|
||||
'"' + this.whoami.replace('"', '""') + '"',
|
||||
]
|
||||
);
|
||||
let latest_private = this.get_latest_private(Object.keys(following));
|
||||
this.channels_unread = JSON.parse(
|
||||
(await tfrpc.rpc.databaseGet('unread')) ?? '{}'
|
||||
);
|
||||
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);
|
||||
console.log(
|
||||
@ -343,54 +243,14 @@ class TfElement extends LitElement {
|
||||
Object.keys(users).length,
|
||||
'users'
|
||||
);
|
||||
start_time = new Date();
|
||||
channels = await channels;
|
||||
console.log('channels took', (new Date() - start_time) / 1000.0);
|
||||
this.channels_latest = Object.fromEntries(
|
||||
channels.map((x) => [x.channel, x.rowid])
|
||||
);
|
||||
let self = this;
|
||||
latest_private.then(function(latest) {
|
||||
self.channels_latest = Object.assign({}, self.channels_latest, {'🔐': latest});
|
||||
console.log('private took', (new Date() - start_time) / 1000.0);
|
||||
});
|
||||
this.following = Object.keys(following);
|
||||
this.users = users;
|
||||
await tags;
|
||||
console.log(`load finished ${whoami} => ${this.whoami}`);
|
||||
this.whoami = whoami;
|
||||
this.loaded = whoami;
|
||||
}
|
||||
|
||||
channel_set_unread(event) {
|
||||
this.channels_unread[event.detail.channel ?? ''] = event.detail.unread;
|
||||
this.channels_unread = Object.assign({}, this.channels_unread);
|
||||
tfrpc.rpc.databaseSet('unread', JSON.stringify(this.channels_unread));
|
||||
}
|
||||
|
||||
async decrypt(messages) {
|
||||
let whoami = this.whoami;
|
||||
return Promise.all(messages.map(async function (message) {
|
||||
let content;
|
||||
try {
|
||||
content = JSON.parse(message?.content);
|
||||
} catch {}
|
||||
if (typeof content === 'string') {
|
||||
let decrypted;
|
||||
try {
|
||||
decrypted = await tfrpc.rpc.try_decrypt(whoami, content);
|
||||
} catch {}
|
||||
if (decrypted) {
|
||||
try {
|
||||
message.decrypted = JSON.parse(decrypted);
|
||||
} catch {
|
||||
message.decrypted = decrypted;
|
||||
}
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}));
|
||||
}
|
||||
|
||||
render_tab() {
|
||||
let following = this.following;
|
||||
let users = this.users;
|
||||
@ -405,10 +265,6 @@ class TfElement extends LitElement {
|
||||
.unread=${this.unread}
|
||||
@refresh=${() => (this.unread = [])}
|
||||
?loading=${this.loading}
|
||||
.channels=${this.channels}
|
||||
.channels_latest=${this.channels_latest}
|
||||
.channels_unread=${this.channels_unread}
|
||||
@channelsetunread=${this.channel_set_unread}
|
||||
></tf-tab-news>
|
||||
`;
|
||||
} else if (this.tab === 'connections') {
|
||||
@ -419,6 +275,14 @@ class TfElement extends LitElement {
|
||||
.broadcasts=${this.broadcasts}
|
||||
></tf-tab-connections>
|
||||
`;
|
||||
} else if (this.tab === 'mentions') {
|
||||
return html`
|
||||
<tf-tab-mentions
|
||||
.following=${this.following}
|
||||
whoami=${this.whoami}
|
||||
.users="${this.users}}"
|
||||
></tf-tab-mentions>
|
||||
`;
|
||||
} else if (this.tab === 'search') {
|
||||
return html`
|
||||
<tf-tab-search
|
||||
@ -450,15 +314,13 @@ class TfElement extends LitElement {
|
||||
await tfrpc.rpc.setHash('#');
|
||||
} else if (tab === 'connections') {
|
||||
await tfrpc.rpc.setHash('#connections');
|
||||
} else if (tab === 'mentions') {
|
||||
await tfrpc.rpc.setHash('#mentions');
|
||||
} else if (tab === 'query') {
|
||||
await tfrpc.rpc.setHash('#sql=');
|
||||
}
|
||||
}
|
||||
|
||||
refresh() {
|
||||
tfrpc.rpc.sync();
|
||||
}
|
||||
|
||||
render() {
|
||||
let self = this;
|
||||
|
||||
@ -472,21 +334,13 @@ class TfElement extends LitElement {
|
||||
const k_tabs = {
|
||||
'📰': 'news',
|
||||
'📡': 'connections',
|
||||
'@': 'mentions',
|
||||
'🔍': 'search',
|
||||
'👩💻': 'query',
|
||||
};
|
||||
|
||||
let tabs = html`
|
||||
<div
|
||||
class="w3-bar w3-theme-l1"
|
||||
style="position: sticky; top: 0; z-index: 10"
|
||||
>
|
||||
<button
|
||||
class="w3-bar-item w3-button w3-circle w3-ripple"
|
||||
@click=${this.refresh}
|
||||
>
|
||||
↻
|
||||
</button>
|
||||
<div class="w3-bar w3-theme-l1">
|
||||
${Object.entries(k_tabs).map(
|
||||
([k, v]) => html`
|
||||
<button
|
||||
@ -520,7 +374,13 @@ class TfElement extends LitElement {
|
||||
style="width: 100vw; min-height: 100vh; height: 100%"
|
||||
class="w3-theme-dark"
|
||||
>
|
||||
${tabs} ${contents}
|
||||
${tabs}
|
||||
<div style="padding: 8px">
|
||||
${this.tags.map(
|
||||
(x) => html`<tf-tag tag=${x.tag} count=${x.count}></tf-tag>`
|
||||
)}
|
||||
${contents}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ class TfComposeElement extends LitElement {
|
||||
apps: {type: Object},
|
||||
drafts: {type: Object},
|
||||
author: {type: String},
|
||||
channel: {type: String},
|
||||
};
|
||||
}
|
||||
|
||||
@ -181,13 +180,6 @@ class TfComposeElement extends LitElement {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
document.execCommand(
|
||||
'insertText',
|
||||
false,
|
||||
event.clipboardData.getData('text/plain')
|
||||
);
|
||||
}
|
||||
|
||||
async submit() {
|
||||
@ -197,7 +189,6 @@ class TfComposeElement extends LitElement {
|
||||
let message = {
|
||||
type: 'post',
|
||||
text: edit.innerText,
|
||||
channel: this.channel,
|
||||
};
|
||||
if (this.root || this.branch) {
|
||||
message.root = this.root;
|
||||
@ -537,9 +528,6 @@ class TfComposeElement extends LitElement {
|
||||
class="w3-card-4 w3-theme-d4 w3-padding-small"
|
||||
style="box-sizing: border-box"
|
||||
>
|
||||
${this.channel !== undefined
|
||||
? html`<p>To #${this.channel}:</p>`
|
||||
: undefined}
|
||||
${this.render_encrypt()}
|
||||
<div class="w3-container w3-padding-small">
|
||||
<div class="w3-half">
|
||||
|
@ -14,8 +14,6 @@ class TfMessageElement extends LitElement {
|
||||
format: {type: String},
|
||||
blog_data: {type: String},
|
||||
expanded: {type: Object},
|
||||
channel: {type: String},
|
||||
channel_unread: {type: Number},
|
||||
};
|
||||
}
|
||||
|
||||
@ -30,7 +28,6 @@ class TfMessageElement extends LitElement {
|
||||
this.drafts = {};
|
||||
this.format = 'message';
|
||||
this.expanded = {};
|
||||
this.channel_unread = -1;
|
||||
}
|
||||
|
||||
show_reply() {
|
||||
@ -76,23 +73,18 @@ class TfMessageElement extends LitElement {
|
||||
}
|
||||
}
|
||||
if (this.message?.votes?.length) {
|
||||
return html` <div class="w3-container">
|
||||
<div
|
||||
class="w3-button w3-bar w3-padding-small"
|
||||
@click=${this.show_reactions}
|
||||
>
|
||||
${(this.message.votes || []).map(
|
||||
(vote) => html`
|
||||
<span
|
||||
class="w3-bar-item w3-padding-small"
|
||||
title="${this.users[vote.author]?.name ??
|
||||
vote.author} ${new Date(vote.timestamp)}"
|
||||
>
|
||||
${normalize_expression(vote.content.vote.expression)}
|
||||
</span>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
return html`<div class="w3-button" @click=${this.show_reactions}>
|
||||
${(this.message.votes || []).map(
|
||||
(vote) => html`
|
||||
<span
|
||||
title="${this.users[vote.author]?.name ?? vote.author} ${new Date(
|
||||
vote.timestamp
|
||||
)}"
|
||||
>
|
||||
${normalize_expression(vote.content.vote.expression)}
|
||||
</span>
|
||||
`
|
||||
)}
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
@ -231,7 +223,7 @@ class TfMessageElement extends LitElement {
|
||||
>${mention.name}</a
|
||||
>`;
|
||||
} else if (mention.link?.startsWith('#')) {
|
||||
return html` <a href=${'#' + encodeURIComponent('#' + mention.link)}
|
||||
return html` <a href=${'#q=' + encodeURIComponent(mention.link)}
|
||||
>${mention.link}</a
|
||||
>`;
|
||||
} else if (
|
||||
@ -315,27 +307,12 @@ ${JSON.stringify(mention, null, 2)}</pre
|
||||
.users=${this.users}
|
||||
.drafts=${this.drafts}
|
||||
.expanded=${this.expanded}
|
||||
channel=${this.channel}
|
||||
channel_unread=${this.channel_unread}
|
||||
></tf-message>`
|
||||
)}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mark_unread() {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('channelsetunread', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: {
|
||||
channel: this.channel,
|
||||
unread: this.message.rowid,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
render_channels() {
|
||||
let content = this.message?.content;
|
||||
if (this?.messsage?.decrypted?.type == 'post') {
|
||||
@ -362,9 +339,7 @@ ${JSON.stringify(mention, null, 2)}</pre
|
||||
}
|
||||
let class_background = this.message?.decrypted
|
||||
? 'w3-pale-red'
|
||||
: this.message?.rowid >= this.channel_unread
|
||||
? 'w3-theme-d2'
|
||||
: 'w3-theme-d4';
|
||||
: 'w3-theme-d4';
|
||||
let self = this;
|
||||
let raw_button;
|
||||
switch (this.format) {
|
||||
@ -428,10 +403,9 @@ ${JSON.stringify(mention, null, 2)}</pre
|
||||
>
|
||||
<tf-user id=${self.message.author} .users=${self.users}></tf-user>
|
||||
<span style="padding-right: 8px"
|
||||
><a tfarget="_top" href=${'#' + encodeURIComponent(self.message.id)}
|
||||
>%</a
|
||||
>
|
||||
${new Date(self.message.timestamp).toLocaleString()}</span
|
||||
><a tfarget="_top" href=${'#' + self.message.id}>%</a> ${new Date(
|
||||
self.message.timestamp
|
||||
).toLocaleString()}</span
|
||||
>
|
||||
${raw_button} ${self.format == 'raw' ? self.render_raw() : inner}
|
||||
${self.render_votes()}
|
||||
@ -443,8 +417,6 @@ ${JSON.stringify(mention, null, 2)}</pre
|
||||
.users=${self.users}
|
||||
.drafts=${self.drafts}
|
||||
.expanded=${self.expanded}
|
||||
channel=${self.channel}
|
||||
channel_unread=${self.channel_unread}
|
||||
></tf-message>
|
||||
`
|
||||
)}
|
||||
@ -464,8 +436,6 @@ ${JSON.stringify(mention, null, 2)}</pre
|
||||
.users=${this.users}
|
||||
.drafts=${this.drafts}
|
||||
.expanded=${this.expanded}
|
||||
channel=${this.channel}
|
||||
channel_unread=${this.channel_unread}
|
||||
></tf-message>`
|
||||
)}
|
||||
</div>`;
|
||||
@ -474,9 +444,7 @@ ${JSON.stringify(mention, null, 2)}</pre
|
||||
class="w3-card-4 w3-theme-d4 w3-border-theme"
|
||||
style="margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
|
||||
>
|
||||
<a target="_top" href=${'#' + encodeURIComponent(this.message.id)}
|
||||
>${this.message.id}</a
|
||||
>
|
||||
<a target="_top" href=${'#' + this.message.id}>${this.message.id}</a>
|
||||
(placeholder)
|
||||
<div>${this.render_votes()}</div>
|
||||
${(this.message.child_messages || []).map(
|
||||
@ -487,8 +455,6 @@ ${JSON.stringify(mention, null, 2)}</pre
|
||||
.users=${this.users}
|
||||
.drafts=${this.drafts}
|
||||
.expanded=${this.expanded}
|
||||
channel=${this.channel}
|
||||
channel_unread=${this.channel_unread}
|
||||
></tf-message>
|
||||
`
|
||||
)}
|
||||
@ -629,11 +595,7 @@ ${JSON.stringify(content, null, 2)}</pre
|
||||
${is_encrypted}
|
||||
<span style="flex: 1"></span>
|
||||
<span style="padding-right: 8px"
|
||||
><a
|
||||
target="_top"
|
||||
href=${'#' + encodeURIComponent(self.message.id)}
|
||||
>%</a
|
||||
>
|
||||
><a target="_top" href=${'#' + self.message.id}>%</a>
|
||||
${new Date(this.message.timestamp).toLocaleString()}</span
|
||||
>
|
||||
<span>${raw_button}</span>
|
||||
@ -644,16 +606,6 @@ ${JSON.stringify(content, null, 2)}</pre
|
||||
<button class="w3-button w3-theme-d1" @click=${this.react}>
|
||||
React
|
||||
</button>
|
||||
${!content.root && this.message.rowid < this.channel_unread
|
||||
? html`
|
||||
<button
|
||||
class="w3-button w3-theme-d1"
|
||||
@click=${this.mark_unread}
|
||||
>
|
||||
Mark Unread
|
||||
</button>
|
||||
`
|
||||
: undefined}
|
||||
</p>
|
||||
${this.render_children()}
|
||||
</div>
|
||||
@ -686,11 +638,7 @@ ${JSON.stringify(content, null, 2)}</pre
|
||||
${is_encrypted}
|
||||
<span style="flex: 1"></span>
|
||||
<span style="padding-right: 8px"
|
||||
><a
|
||||
target="_top"
|
||||
href=${'#' + encodeURIComponent(self.message.id)}
|
||||
>%</a
|
||||
>
|
||||
><a target="_top" href=${'#' + self.message.id}>%</a>
|
||||
${new Date(this.message.timestamp).toLocaleString()}</span
|
||||
>
|
||||
<span>${raw_button}</span>
|
||||
@ -780,11 +728,7 @@ ${JSON.stringify(content, null, 2)}</pre
|
||||
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
||||
<span style="flex: 1"></span>
|
||||
<span style="padding-right: 8px"
|
||||
><a
|
||||
target="_top"
|
||||
href=${'#' + encodeURIComponent(self.message.id)}
|
||||
>%</a
|
||||
>
|
||||
><a target="_top" href=${'#' + self.message.id}>%</a>
|
||||
${new Date(this.message.timestamp).toLocaleString()}</span
|
||||
>
|
||||
<span>${raw_button}</span>
|
||||
@ -823,7 +767,7 @@ ${JSON.stringify(content, null, 2)}</pre
|
||||
return small_frame(html`
|
||||
<div>
|
||||
${content.subscribed ? 'subscribed to' : 'unsubscribed from'}
|
||||
<a href=${'#' + encodeURIComponent('#' + content.channel)}
|
||||
<a href=${'#q=' + encodeURIComponent('#' + content.channel)}
|
||||
>#${content.channel}</a
|
||||
>
|
||||
</div>
|
||||
|
@ -11,8 +11,6 @@ class TfNewsElement extends LitElement {
|
||||
following: {type: Array},
|
||||
drafts: {type: Object},
|
||||
expanded: {type: Object},
|
||||
channel: {type: String},
|
||||
channel_unread: {type: Number},
|
||||
};
|
||||
}
|
||||
|
||||
@ -27,7 +25,6 @@ class TfNewsElement extends LitElement {
|
||||
this.following = [];
|
||||
this.drafts = {};
|
||||
this.expanded = {};
|
||||
this.channel_unread = -1;
|
||||
}
|
||||
|
||||
process_messages(messages) {
|
||||
@ -36,13 +33,12 @@ class TfNewsElement extends LitElement {
|
||||
|
||||
console.log('processing', messages.length, 'messages');
|
||||
|
||||
function ensure_message(id, rowid) {
|
||||
function ensure_message(id) {
|
||||
let found = messages_by_id[id];
|
||||
if (found) {
|
||||
return found;
|
||||
} else {
|
||||
let added = {
|
||||
rowid: rowid,
|
||||
id: id,
|
||||
placeholder: true,
|
||||
content: '"placeholder"',
|
||||
@ -57,7 +53,7 @@ class TfNewsElement extends LitElement {
|
||||
|
||||
function link_message(message) {
|
||||
if (message.content.type === 'vote') {
|
||||
let parent = ensure_message(message.content.vote.link, message.rowid);
|
||||
let parent = ensure_message(message.content.vote.link);
|
||||
if (!parent.votes) {
|
||||
parent.votes = [];
|
||||
}
|
||||
@ -66,14 +62,14 @@ class TfNewsElement extends LitElement {
|
||||
} else if (message.content.type == 'post') {
|
||||
if (message.content.root) {
|
||||
if (typeof message.content.root === 'string') {
|
||||
let m = ensure_message(message.content.root, message.rowid);
|
||||
let m = ensure_message(message.content.root);
|
||||
if (!m.child_messages) {
|
||||
m.child_messages = [];
|
||||
}
|
||||
m.child_messages.push(message);
|
||||
message.parent_message = message.content.root;
|
||||
} else {
|
||||
let m = ensure_message(message.content.root[0], message.rowid);
|
||||
let m = ensure_message(message.content.root[0]);
|
||||
if (!m.child_messages) {
|
||||
m.child_messages = [];
|
||||
}
|
||||
@ -166,7 +162,6 @@ class TfNewsElement extends LitElement {
|
||||
} else {
|
||||
if (group.length > 0) {
|
||||
result.push({
|
||||
rowid: Math.max(...group.map((x) => x.rowid)),
|
||||
type: 'contact_group',
|
||||
messages: group,
|
||||
});
|
||||
@ -175,13 +170,6 @@ class TfNewsElement extends LitElement {
|
||||
result.push(message);
|
||||
}
|
||||
}
|
||||
if (group.length > 0) {
|
||||
result.push({
|
||||
rowid: Math.max(...group.map((x) => x.rowid)),
|
||||
type: 'contact_group',
|
||||
messages: group,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -190,39 +178,18 @@ class TfNewsElement extends LitElement {
|
||||
let final_messages = this.group_following(
|
||||
this.finalize_messages(messages_by_id)
|
||||
);
|
||||
let unread_rowid = -1;
|
||||
for (let message of final_messages) {
|
||||
if (message.rowid >= this.channel_unread) {
|
||||
unread_rowid = message.rowid;
|
||||
}
|
||||
}
|
||||
return html`
|
||||
<div>
|
||||
<div style="display: flex; flex-direction: column">
|
||||
${final_messages.map(
|
||||
(x) =>
|
||||
html`
|
||||
<tf-message
|
||||
.message=${x}
|
||||
whoami=${this.whoami}
|
||||
.users=${this.users}
|
||||
.drafts=${this.drafts}
|
||||
.expanded=${this.expanded}
|
||||
collapsed="true"
|
||||
channel=${this.channel}
|
||||
channel_unread=${this.channel_unread}
|
||||
></tf-message>
|
||||
${x.rowid == unread_rowid && x != final_messages[0]
|
||||
? html`<div style="display: flex; flex-direction: row">
|
||||
<div
|
||||
style="border-bottom: 1px solid #f00; flex: 1; align-self: center; height: 1px"
|
||||
></div>
|
||||
<div style="color: #f00; padding: 8px">unread</div>
|
||||
<div
|
||||
style="border-bottom: 1px solid #f00; flex: 1; align-self: center; height: 1px"
|
||||
></div>
|
||||
</div>`
|
||||
: undefined}
|
||||
`
|
||||
html`<tf-message
|
||||
.message=${x}
|
||||
whoami=${this.whoami}
|
||||
.users=${this.users}
|
||||
.drafts=${this.drafts}
|
||||
.expanded=${this.expanded}
|
||||
collapsed="true"
|
||||
></tf-message>`
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
|
@ -188,10 +188,6 @@ class TfProfileElement extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
copy_id() {
|
||||
navigator.clipboard.writeText(this.id);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (
|
||||
this.id == this.whoami &&
|
||||
@ -233,11 +229,7 @@ class TfProfileElement extends LitElement {
|
||||
</button>`;
|
||||
}
|
||||
edit = html`
|
||||
<button
|
||||
id="save_profile"
|
||||
class="w3-button w3-theme-d1"
|
||||
@click=${this.save_edits}
|
||||
>
|
||||
<button class="w3-button w3-theme-d1" @click=${this.save_edits}>
|
||||
Save Profile
|
||||
</button>
|
||||
<button class="w3-button w3-theme-d1" @click=${this.discard_edits}>
|
||||
@ -246,11 +238,7 @@ class TfProfileElement extends LitElement {
|
||||
${server_follow}
|
||||
`;
|
||||
} else {
|
||||
edit = html`<button
|
||||
id="edit_profile"
|
||||
class="w3-button w3-theme-d1"
|
||||
@click=${this.edit}
|
||||
>
|
||||
edit = html`<button class="w3-button w3-theme-d1" @click=${this.edit}>
|
||||
Edit Profile
|
||||
</button>`;
|
||||
}
|
||||
@ -297,10 +285,8 @@ class TfProfileElement extends LitElement {
|
||||
typeof profile.image == 'string' ? profile.image : profile.image?.link;
|
||||
image = this.editing?.image ?? image;
|
||||
let description = this.editing?.description ?? profile.description;
|
||||
return html`<div class="w3-container" style="box-sizing: border-box; border: 2px solid black; background-color: rgba(255, 255, 255, 0.2)">
|
||||
<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>
|
||||
return html`<div style="border: 2px solid black; background-color: rgba(255, 255, 255, 0.2); padding: 16px">
|
||||
<tf-user id=${this.id} .users=${this.users}></tf-user> (${tfutils.human_readable_size(this.size)})
|
||||
<div style="display: flex; flex-direction: row; gap: 1em">
|
||||
${edit_profile}
|
||||
<div style="flex: 1 0 50%">
|
||||
@ -314,11 +300,11 @@ class TfProfileElement extends LitElement {
|
||||
Blocking ${profile.blocking} identities.
|
||||
Blocked by ${profile.blocked} identities.
|
||||
</div>
|
||||
<p>
|
||||
<div>
|
||||
${edit}
|
||||
${follow}
|
||||
${block}
|
||||
</p>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
@ -27,12 +27,8 @@ class TfReactionsModalElement extends LitElement {
|
||||
? 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-modal-content w3-card-4 w3-theme-d1">
|
||||
<div class="w3-container w3-padding">
|
||||
<header class="w3-container">
|
||||
<h2>Reactions</h2>
|
||||
|
@ -286,29 +286,29 @@ hr{border:0;border-top:1px solid #eee;margin:20px 0}
|
||||
`;
|
||||
|
||||
// prettier-ignore
|
||||
const w3_2016_snorkel_blue = css`
|
||||
.w3-theme-l5 {color:#000 !important; background-color:#e9f5ff !important}
|
||||
.w3-theme-l4 {color:#000 !important; background-color:#b5dffd !important}
|
||||
.w3-theme-l3 {color:#000 !important; background-color:#6bc0fc !important}
|
||||
.w3-theme-l2 {color:#fff !important; background-color:#21a0fa !important}
|
||||
.w3-theme-l1 {color:#fff !important; background-color:#0479cc !important}
|
||||
.w3-theme-d1 {color:#fff !important; background-color:#024575 !important}
|
||||
.w3-theme-d2 {color:#fff !important; background-color:#023e68 !important}
|
||||
.w3-theme-d3 {color:#fff !important; background-color:#02365b !important}
|
||||
.w3-theme-d4 {color:#fff !important; background-color:#022e4e !important}
|
||||
.w3-theme-d5 {color:#fff !important; background-color:#012641 !important}
|
||||
const w3_2016_riverside = css`
|
||||
.w3-theme-l5 {color:#000 !important; background-color:#f4f6f9 !important}
|
||||
.w3-theme-l4 {color:#000 !important; background-color:#d9e1ec !important}
|
||||
.w3-theme-l3 {color:#000 !important; background-color:#b4c3d8 !important}
|
||||
.w3-theme-l2 {color:#fff !important; background-color:#8ea6c5 !important}
|
||||
.w3-theme-l1 {color:#fff !important; background-color:#6888b1 !important}
|
||||
.w3-theme-d1 {color:#fff !important; background-color:#456185 !important}
|
||||
.w3-theme-d2 {color:#fff !important; background-color:#3d5676 !important}
|
||||
.w3-theme-d3 {color:#fff !important; background-color:#354b68 !important}
|
||||
.w3-theme-d4 {color:#fff !important; background-color:#2e4059 !important}
|
||||
.w3-theme-d5 {color:#fff !important; background-color:#26364a !important}
|
||||
|
||||
.w3-theme-light {color:#000 !important; background-color:#e9f5ff !important}
|
||||
.w3-theme-dark {color:#fff !important; background-color:#012641 !important}
|
||||
.w3-theme-action {color:#fff !important; background-color:#012641 !important}
|
||||
.w3-theme-light {color:#000 !important; background-color:#f4f6f9 !important}
|
||||
.w3-theme-dark {color:#fff !important; background-color:#26364a !important}
|
||||
.w3-theme-action {color:#fff !important; background-color:#26364a !important}
|
||||
|
||||
.w3-theme {color:#fff !important; background-color:#034f84 !important}
|
||||
.w3-text-theme {color:#034f84 !important}
|
||||
.w3-border-theme {border-color:#034f84 !important}
|
||||
.w3-theme {color:#fff !important; background-color:#4c6a92 !important}
|
||||
.w3-text-theme {color:#4c6a92 !important}
|
||||
.w3-border-theme {border-color:#4c6a92 !important}
|
||||
|
||||
.w3-hover-theme:hover {color:#fff !important; background-color:#034f84 !important}
|
||||
.w3-hover-text-theme:hover {color:#034f84 !important}
|
||||
.w3-hover-border-theme:hover {border-color:#034f84 !important}
|
||||
.w3-hover-theme:hover {color:#fff !important; background-color:#4c6a92 !important}
|
||||
.w3-hover-text-theme:hover {color:#4c6a92 !important}
|
||||
.w3-hover-border-theme:hover {border-color:#4c6a92 !important}
|
||||
`;
|
||||
|
||||
export let styles = [tf, w3, w3_2016_snorkel_blue];
|
||||
export let styles = [tf, w3, w3_2016_riverside];
|
||||
|
@ -12,20 +12,11 @@ class TfTabConnectionsElement extends LitElement {
|
||||
stored_connections: {type: Array},
|
||||
users: {type: Object},
|
||||
server_identity: {type: String},
|
||||
connect_attempt: {type: Object},
|
||||
connect_message: {type: String},
|
||||
connect_success: {type: Boolean},
|
||||
};
|
||||
}
|
||||
|
||||
static styles = styles;
|
||||
|
||||
static k_broadcast_emojis = {
|
||||
discovery: '🏓',
|
||||
room: '🚪',
|
||||
peer_exchange: '🕸',
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
let self = this;
|
||||
@ -91,36 +82,19 @@ class TfTabConnectionsElement extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
render_message(connection) {
|
||||
return html`<div
|
||||
?hidden=${this.connect_message === undefined ||
|
||||
this.connect_attempt != connection}
|
||||
style="cursor: pointer"
|
||||
class=${'w3-panel ' + (this.connect_success ? 'w3-green' : 'w3-red')}
|
||||
@click=${() => (this.connect_attempt = undefined)}
|
||||
>
|
||||
<p>${this.connect_message}</p>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
render_broadcast(connection) {
|
||||
let self = this;
|
||||
return html`
|
||||
<li>
|
||||
<div class="w3-bar" style="overflow: hidden; overflow-wrap: nowrap">
|
||||
<button
|
||||
class="w3-bar-item w3-button w3-theme-d1"
|
||||
@click=${() => self.connect(connection)}
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
<div class="w3-bar-item">
|
||||
${TfTabConnectionsElement.k_broadcast_emojis[connection.origin]}
|
||||
<tf-user id=${connection.pubkey} .users=${this.users}></tf-user>
|
||||
${this.render_connection_summary(connection)}
|
||||
</div>
|
||||
<li class="w3-bar" style="overflow: hidden; overflow-wrap: nowrap">
|
||||
<button
|
||||
class="w3-bar-item w3-button w3-theme-d1"
|
||||
@click=${() => tfrpc.rpc.connect(connection)}
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
<div class="w3-bar-item">
|
||||
<tf-user id=${connection.pubkey} .users=${this.users}></tf-user>
|
||||
${this.render_connection_summary(connection)}
|
||||
</div>
|
||||
${this.render_message(connection)}
|
||||
</li>
|
||||
`;
|
||||
}
|
||||
@ -148,7 +122,6 @@ class TfTabConnectionsElement extends LitElement {
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
${connection.flags.one_shot ? '🔃' : undefined}
|
||||
<tf-user id=${connection.id} .users=${this.users}></tf-user>
|
||||
${connection.tunnel !== undefined
|
||||
? '🚇'
|
||||
@ -156,9 +129,7 @@ class TfTabConnectionsElement extends LitElement {
|
||||
<div>
|
||||
${requests.map(
|
||||
(x) => html`
|
||||
<span
|
||||
class=${'w3-tag w3-small ' +
|
||||
(x.active ? 'w3-theme-l3' : 'w3-theme-d3')}
|
||||
<span class="w3-tag w3-small"
|
||||
>${x.request_number > 0 ? '🟩' : '🟥'} ${x.name}
|
||||
<span
|
||||
class="w3-badge w3-white"
|
||||
@ -178,38 +149,16 @@ class TfTabConnectionsElement extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
connect(address) {
|
||||
let self = this;
|
||||
self.connect_attempt = address;
|
||||
self.connect_message = undefined;
|
||||
self.connect_success = false;
|
||||
tfrpc.rpc
|
||||
.connect(address)
|
||||
.then(function () {
|
||||
if (self.connect_attempt == address) {
|
||||
self.connect_message = 'Connected.';
|
||||
self.connect_success = true;
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
if (self.connect_attempt == address) {
|
||||
self.connect_message = 'Error: ' + error;
|
||||
self.connect_success = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
let self = this;
|
||||
return html`
|
||||
<div class="w3-container" style="box-sizing: border-box">
|
||||
<h2>New Connection</h2>
|
||||
<textarea class="w3-input w3-theme-d1" id="code"></textarea>
|
||||
${this.render_message(this.renderRoot.getElementById('code')?.value)}
|
||||
<button
|
||||
class="w3-button w3-theme-d1"
|
||||
@click=${() =>
|
||||
self.connect(self.renderRoot.getElementById('code')?.value)}
|
||||
tfrpc.rpc.connect(self.renderRoot.getElementById('code').value)}
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
@ -217,9 +166,6 @@ class TfTabConnectionsElement extends LitElement {
|
||||
<ul class="w3-ul w3-border">
|
||||
${this.broadcasts
|
||||
.filter((x) => x.address)
|
||||
.filter(
|
||||
(x) => self.connections.map((c) => c.id).indexOf(x.pubkey) == -1
|
||||
)
|
||||
.map((x) => self.render_broadcast(x))}
|
||||
</ul>
|
||||
<h2>Connections</h2>
|
||||
@ -236,26 +182,23 @@ class TfTabConnectionsElement extends LitElement {
|
||||
<ul class="w3-ul w3-border">
|
||||
${this.stored_connections.map(
|
||||
(x) => html`
|
||||
<li>
|
||||
<div class="w3-bar">
|
||||
<button
|
||||
class="w3-bar-item w3-button w3-theme-d1"
|
||||
@click=${() => self.forget_stored_connection(x)}
|
||||
>
|
||||
Forget
|
||||
</button>
|
||||
<button
|
||||
class="w3-bar-item w3-button w3-theme-d1"
|
||||
@click=${() => this.connect(x)}
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
<div class="w3-bar-item">
|
||||
<tf-user id=${x.pubkey} .users=${self.users}></tf-user>
|
||||
<div><small>${x.address}:${x.port}</small></div>
|
||||
</div>
|
||||
<li class="w3-bar">
|
||||
<button
|
||||
class="w3-bar-item w3-button w3-theme-d1"
|
||||
@click=${() => self.forget_stored_connection(x)}
|
||||
>
|
||||
Forget
|
||||
</button>
|
||||
<button
|
||||
class="w3-bar-item w3-button w3-theme-d1"
|
||||
@click=${() => tfrpc.rpc.connect(x)}
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
<div class="w3-bar-item">
|
||||
<tf-user id=${x.pubkey} .users=${self.users}></tf-user>
|
||||
<div><small>${x.address}:${x.port}</small></div>
|
||||
</div>
|
||||
${this.render_message(x)}
|
||||
</li>
|
||||
`
|
||||
)}
|
||||
|
78
apps/ssb/tf-tab-mentions.js
Normal file
78
apps/ssb/tf-tab-mentions.js
Normal file
@ -0,0 +1,78 @@
|
||||
import {LitElement, html, unsafeHTML} from './lit-all.min.js';
|
||||
import * as tfrpc from '/static/tfrpc.js';
|
||||
import {styles} from './tf-styles.js';
|
||||
|
||||
class TfTabMentionsElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
whoami: {type: String},
|
||||
users: {type: Object},
|
||||
following: {type: Array},
|
||||
expanded: {type: Object},
|
||||
messages: {type: Array},
|
||||
};
|
||||
}
|
||||
|
||||
static styles = styles;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
let self = this;
|
||||
this.whoami = null;
|
||||
this.users = {};
|
||||
this.following = [];
|
||||
this.expanded = {};
|
||||
this.messages = [];
|
||||
}
|
||||
|
||||
async load() {
|
||||
console.log('Loading...', this.whoami);
|
||||
let results = await tfrpc.rpc.query(
|
||||
`
|
||||
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages_fts(?)
|
||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE messages.author != ?
|
||||
ORDER BY timestamp DESC limit 20
|
||||
`,
|
||||
[
|
||||
'"' + this.whoami.replace('"', '""') + '"',
|
||||
JSON.stringify(this.following),
|
||||
this.whoami,
|
||||
]
|
||||
);
|
||||
console.log('Done.');
|
||||
this.messages = results;
|
||||
}
|
||||
|
||||
on_expand(event) {
|
||||
if (event.detail.expanded) {
|
||||
let expand = {};
|
||||
expand[event.detail.id] = true;
|
||||
this.expanded = Object.assign({}, this.expanded, expand);
|
||||
} else {
|
||||
delete this.expanded[event.detail.id];
|
||||
this.expanded = Object.assign({}, this.expanded);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let self = this;
|
||||
if (!this.loading) {
|
||||
this.loading = true;
|
||||
this.load();
|
||||
}
|
||||
return html`
|
||||
<tf-news
|
||||
id="news"
|
||||
whoami=${this.whoami}
|
||||
.messages=${this.messages}
|
||||
.users=${this.users}
|
||||
.expanded=${this.expanded}
|
||||
@tf-expand=${this.on_expand}
|
||||
></tf-news>
|
||||
`;
|
||||
}
|
||||
}
|
||||
customElements.define('tf-tab-mentions', TfTabMentionsElement);
|
@ -12,11 +12,6 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
messages: {type: Array},
|
||||
drafts: {type: Object},
|
||||
expanded: {type: Object},
|
||||
channels_unread: {type: Object},
|
||||
channels_latest: {type: Object},
|
||||
loading: {type: Number},
|
||||
time_range: {type: Array},
|
||||
time_loading: {type: Array},
|
||||
};
|
||||
}
|
||||
|
||||
@ -31,67 +26,30 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
this.following = [];
|
||||
this.drafts = {};
|
||||
this.expanded = {};
|
||||
this.channels_unread = {};
|
||||
this.channels_latest = {};
|
||||
this.start_time = new Date().valueOf();
|
||||
this.time_range = [0, 0];
|
||||
this.time_loading = undefined;
|
||||
this.loading = 0;
|
||||
this.start_time = new Date().valueOf() - 24 * 60 * 60 * 1000;
|
||||
}
|
||||
|
||||
channel() {
|
||||
return this.hash.startsWith('##')
|
||||
? this.hash.substring(2)
|
||||
: this.hash.substring(1);
|
||||
}
|
||||
|
||||
async fetch_messages(start_time, end_time) {
|
||||
this.time_loading = [start_time, end_time];
|
||||
let result;
|
||||
if (this.hash == '#@') {
|
||||
result = await tfrpc.rpc.query(
|
||||
async fetch_messages() {
|
||||
if (this.hash.startsWith('#@')) {
|
||||
let r = await tfrpc.rpc.query(
|
||||
`
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages_fts(?1)
|
||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||
JOIN json_each(?2) AS following ON messages.author = following.value
|
||||
WHERE
|
||||
messages.author != ?1 AND
|
||||
messages.timestamp >= ?3 AND
|
||||
messages.timestamp < ?4
|
||||
ORDER BY timestamp DESC limit 20
|
||||
`,
|
||||
[
|
||||
'"' + this.whoami.replace('"', '""') + '"',
|
||||
JSON.stringify(this.following),
|
||||
start_time,
|
||||
end_time,
|
||||
]
|
||||
);
|
||||
} else if (this.hash.startsWith('#@')) {
|
||||
result = await tfrpc.rpc.query(
|
||||
`
|
||||
WITH mine AS (SELECT rowid, id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||
WITH mine AS (SELECT id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||
FROM messages
|
||||
WHERE messages.author = ?
|
||||
ORDER BY sequence DESC)
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
ORDER BY sequence DESC
|
||||
LIMIT 20)
|
||||
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM mine
|
||||
JOIN messages_refs ON mine.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
WHERE
|
||||
mine.timestamp >= ?2 AND
|
||||
mine.timestamp < ?3
|
||||
UNION
|
||||
SELECT * FROM mine
|
||||
WHERE
|
||||
mine.timestamp >= ?2 AND
|
||||
mine.timestamp < ?3
|
||||
`,
|
||||
[this.hash.substring(1), start_time, end_time]
|
||||
[this.hash.substring(1)]
|
||||
);
|
||||
return r;
|
||||
} else if (this.hash.startsWith('#%')) {
|
||||
result = await tfrpc.rpc.query(
|
||||
return await tfrpc.rpc.query(
|
||||
`
|
||||
SELECT id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||
FROM messages
|
||||
@ -104,68 +62,6 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
`,
|
||||
[this.hash.substring(1)]
|
||||
);
|
||||
} else if (this.hash.startsWith('##')) {
|
||||
let promises = [];
|
||||
const k_following_limit = 256;
|
||||
for (let i = 0; i < this.following.length; i += k_following_limit) {
|
||||
promises.push(
|
||||
tfrpc.rpc.query(
|
||||
`
|
||||
WITH news AS (SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE
|
||||
messages.timestamp >= ? AND
|
||||
messages.timestamp < ? AND
|
||||
messages.content ->> 'channel' = ?
|
||||
ORDER BY messages.timestamp DESC)
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
UNION
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages_fts(?5)
|
||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||
JOIN json_each(?1) AS following ON messages.author = following.value
|
||||
JOIN json_tree(messages.content, '$.mentions') AS mention ON mention.value = '#' || ?4
|
||||
WHERE
|
||||
messages.timestamp >= ?2 AND
|
||||
messages.timestamp < ?3
|
||||
UNION
|
||||
SELECT news.* FROM news
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.following.slice(i, i + k_following_limit)),
|
||||
start_time,
|
||||
end_time,
|
||||
this.hash.substring(2),
|
||||
'"#' + this.hash.substring(2).replace('"', '""') + '"',
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
result = [].concat(...(await Promise.all(promises)));
|
||||
} else if (this.hash == '#🔐') {
|
||||
result = await tfrpc.rpc.query(
|
||||
`
|
||||
SELECT messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||
FROM messages
|
||||
JOIN json_each(?1) AS following ON messages.author = following.value
|
||||
WHERE
|
||||
messages.timestamp >= ?2 AND
|
||||
messages.timestamp < ?3 AND
|
||||
json(messages.content) LIKE '"%'
|
||||
ORDER BY sequence DESC
|
||||
`,
|
||||
[JSON.stringify(this.following), start_time, end_time]
|
||||
);
|
||||
result = (await this.decrypt(result)).filter(x => x.decrypted);
|
||||
} else {
|
||||
let promises = [];
|
||||
const k_following_limit = 256;
|
||||
@ -173,17 +69,17 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
promises.push(
|
||||
tfrpc.rpc.query(
|
||||
`
|
||||
WITH news AS (SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
WITH news AS (SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE messages.timestamp >= ? AND messages.timestamp < ?
|
||||
WHERE messages.timestamp > ? AND messages.timestamp < ?
|
||||
ORDER BY messages.timestamp DESC)
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
@ -192,58 +88,50 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.following.slice(i, i + k_following_limit)),
|
||||
start_time,
|
||||
end_time,
|
||||
this.start_time,
|
||||
/*
|
||||
** Don't show messages more than a day into the future to prevent
|
||||
** messages with far-future timestamps from staying at the top forever.
|
||||
*/
|
||||
new Date().valueOf() + 24 * 60 * 60 * 1000,
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
result = [].concat(...(await Promise.all(promises)));
|
||||
return [].concat(...(await Promise.all(promises)));
|
||||
}
|
||||
this.time_loading = undefined;
|
||||
return result;
|
||||
}
|
||||
|
||||
update_time_range_from_messages(messages) {
|
||||
this.time_range = [
|
||||
messages.reduce(
|
||||
(accumulator, current) => Math.min(accumulator, current.timestamp),
|
||||
this.time_range[0]
|
||||
),
|
||||
messages.reduce(
|
||||
(accumulator, current) => Math.max(accumulator, current.timestamp),
|
||||
this.time_range[1]
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
async load_more() {
|
||||
this.loading++;
|
||||
this.loading_canceled = false;
|
||||
try {
|
||||
let more = [];
|
||||
while (!more.length && !this.loading_canceled) {
|
||||
let last_start_time = this.start_time;
|
||||
this.start_time = last_start_time - 7 * 24 * 60 * 60 * 1000;
|
||||
more = await this.fetch_messages(this.start_time, last_start_time);
|
||||
this.update_time_range_from_messages(
|
||||
more.filter(
|
||||
(x) =>
|
||||
x.timestamp >= this.start_time && x.timestamp < last_start_time
|
||||
)
|
||||
);
|
||||
}
|
||||
this.messages = await this.decrypt([...more, ...this.messages]);
|
||||
} finally {
|
||||
this.loading--;
|
||||
}
|
||||
}
|
||||
|
||||
cancel_load() {
|
||||
this.loading_canceled = true;
|
||||
let last_start_time = this.start_time;
|
||||
this.start_time = last_start_time - 24 * 60 * 60 * 1000;
|
||||
let more = await tfrpc.rpc.query(
|
||||
`
|
||||
WITH news AS (SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE messages.timestamp > ?
|
||||
AND messages.timestamp <= ?
|
||||
ORDER BY messages.timestamp DESC)
|
||||
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
UNION
|
||||
SELECT news.* FROM news
|
||||
`,
|
||||
[JSON.stringify(this.following), this.start_time, last_start_time]
|
||||
);
|
||||
this.messages = await this.decrypt([...more, ...this.messages]);
|
||||
}
|
||||
|
||||
async decrypt(messages) {
|
||||
console.log('decrypt');
|
||||
let result = [];
|
||||
for (let message of messages) {
|
||||
let content;
|
||||
@ -268,89 +156,8 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
return result;
|
||||
}
|
||||
|
||||
async load_latest() {
|
||||
this.loading++;
|
||||
let now = new Date().valueOf();
|
||||
let end_time = now + 24 * 60 * 60 * 1000;
|
||||
let messages = [];
|
||||
try {
|
||||
messages = await this.fetch_messages(this.time_range[1], end_time);
|
||||
messages = await this.decrypt(messages);
|
||||
this.update_time_range_from_messages(
|
||||
messages.filter(
|
||||
(x) => x.timestamp >= this.time_range[1] && x.timestamp < end_time
|
||||
)
|
||||
);
|
||||
} finally {
|
||||
this.loading--;
|
||||
}
|
||||
this.messages = [...this.messages, ...messages];
|
||||
console.log('done loading latest messages.');
|
||||
}
|
||||
|
||||
async load_messages() {
|
||||
let self = this;
|
||||
this.loading++;
|
||||
let messages = [];
|
||||
try {
|
||||
this.messages = [];
|
||||
this._messages_hash = this.hash;
|
||||
this._messages_following = this.following;
|
||||
let now = new Date().valueOf();
|
||||
let start_time = now - 24 * 60 * 60 * 1000;
|
||||
this.start_time = start_time;
|
||||
this.time_range = [this.start_time, now + 24 * 60 * 60 * 1000];
|
||||
messages = await this.fetch_messages(
|
||||
this.time_range[0],
|
||||
this.time_range[1]
|
||||
);
|
||||
this.update_time_range_from_messages(
|
||||
messages.filter(
|
||||
(x) =>
|
||||
x.timestamp >= this.time_range[0] &&
|
||||
x.timestamp < this.time_range[1]
|
||||
)
|
||||
);
|
||||
messages = await this.decrypt(messages);
|
||||
if (!messages.length) {
|
||||
let more = [];
|
||||
while (!more.length && start_time >= 0) {
|
||||
let last_start_time = start_time;
|
||||
start_time = last_start_time - 7 * 24 * 60 * 60 * 1000;
|
||||
more = await this.fetch_messages(start_time, last_start_time);
|
||||
this.update_time_range_from_messages(
|
||||
more.filter(
|
||||
(x) => x.timestamp >= start_time && x.timestamp < last_start_time
|
||||
)
|
||||
);
|
||||
}
|
||||
messages = await this.decrypt([...more, ...this.messages]);
|
||||
}
|
||||
} finally {
|
||||
this.loading--;
|
||||
}
|
||||
this.messages = messages;
|
||||
this.time_loading = undefined;
|
||||
console.log(`loading messages done for ${self.whoami}`);
|
||||
}
|
||||
|
||||
mark_all_read() {
|
||||
let newest = this.messages.reduce(
|
||||
(accumulator, current) => Math.max(accumulator, current.rowid),
|
||||
this.channels_latest[this.channel()] ?? -1
|
||||
);
|
||||
if (newest >= 0) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('channelsetunread', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: {
|
||||
channel: this.channel(),
|
||||
unread: newest + 1,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
async add_messages(messages) {
|
||||
this.messages = await this.decrypt([...messages, ...this.messages]);
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -362,49 +169,31 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
console.log(
|
||||
`loading messages for ${this.whoami} (following ${this.following.length})`
|
||||
);
|
||||
this.load_messages();
|
||||
let self = this;
|
||||
this.messages = [];
|
||||
this._messages_hash = this.hash;
|
||||
this._messages_following = this.following;
|
||||
this.fetch_messages()
|
||||
.then(this.decrypt.bind(this))
|
||||
.then(function (messages) {
|
||||
self.messages = messages;
|
||||
console.log(`loading mesages done for ${self.whoami}`);
|
||||
})
|
||||
.catch(function (error) {
|
||||
alert(JSON.stringify(error, null, 2));
|
||||
});
|
||||
}
|
||||
let more;
|
||||
if (!this.hash.startsWith('#%')) {
|
||||
if (!this.hash.startsWith('#@') && !this.hash.startsWith('#%')) {
|
||||
more = html`
|
||||
<p>
|
||||
<button class="w3-button w3-theme-d1" @click=${this.mark_all_read}>
|
||||
Mark All Read
|
||||
</button>
|
||||
<button
|
||||
?disabled=${this.loading}
|
||||
class="w3-button w3-theme-d1"
|
||||
@click=${this.load_more}
|
||||
>
|
||||
<button class="w3-button w3-theme-d1" @click=${this.load_more}>
|
||||
Load More
|
||||
</button>
|
||||
<button
|
||||
class=${'w3-button w3-theme-d1' + (this.loading ? '' : ' w3-hide')}
|
||||
@click=${this.cancel_load}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<span
|
||||
>Showing
|
||||
${new Date(
|
||||
this.time_loading
|
||||
? Math.min(this.time_loading[0], this.time_range[0])
|
||||
: this.time_range[0]
|
||||
).toLocaleDateString()}
|
||||
-
|
||||
${new Date(
|
||||
this.time_loading
|
||||
? Math.max(this.time_loading[1], this.time_range[1])
|
||||
: this.time_range[1]
|
||||
).toLocaleDateString()}.</span
|
||||
>
|
||||
</p>
|
||||
`;
|
||||
}
|
||||
return html`
|
||||
<button class="w3-button w3-theme-d1" @click=${this.mark_all_read}>
|
||||
Mark All Read
|
||||
</button>
|
||||
<tf-news
|
||||
id="news"
|
||||
whoami=${this.whoami}
|
||||
@ -413,8 +202,6 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
.following=${this.following}
|
||||
.drafts=${this.drafts}
|
||||
.expanded=${this.expanded}
|
||||
channel=${this.channel()}
|
||||
channel_unread=${this.channels_unread?.[this.channel()]}
|
||||
></tf-news>
|
||||
${more}
|
||||
`;
|
||||
|
@ -13,9 +13,6 @@ class TfTabNewsElement extends LitElement {
|
||||
drafts: {type: Object},
|
||||
expanded: {type: Object},
|
||||
loading: {type: Boolean},
|
||||
channels: {type: Array},
|
||||
channels_unread: {type: Object},
|
||||
channels_latest: {type: Object},
|
||||
};
|
||||
}
|
||||
|
||||
@ -32,9 +29,6 @@ class TfTabNewsElement extends LitElement {
|
||||
this.cache = {};
|
||||
this.drafts = {};
|
||||
this.expanded = {};
|
||||
this.channels_unread = {};
|
||||
this.channels_latest = {};
|
||||
this.channels = [];
|
||||
tfrpc.rpc.localStorageGet('drafts').then(function (d) {
|
||||
self.drafts = JSON.parse(d || '{}');
|
||||
});
|
||||
@ -54,7 +48,10 @@ class TfTabNewsElement extends LitElement {
|
||||
let unread = this.unread;
|
||||
let news = this.shadowRoot?.getElementById('news');
|
||||
if (news) {
|
||||
news.load_latest();
|
||||
console.log('injecting messages', news.messages);
|
||||
news.add_messages(
|
||||
Object.values(Object.fromEntries(this.unread.map((x) => [x.id, x])))
|
||||
);
|
||||
this.dispatchEvent(new CustomEvent('refresh'));
|
||||
}
|
||||
}
|
||||
@ -109,57 +106,14 @@ class TfTabNewsElement extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
unread_status(channel) {
|
||||
if (
|
||||
this.channels_latest[channel] &&
|
||||
(this.channels_unread[channel] === undefined ||
|
||||
this.channels_unread[channel] < this.channels_latest[channel])
|
||||
) {
|
||||
return '🔵';
|
||||
}
|
||||
}
|
||||
|
||||
show_sidebar() {
|
||||
this.renderRoot.getElementById('sidebar').style.display = 'block';
|
||||
this.renderRoot.getElementById('sidebar_overlay').style.display = 'block';
|
||||
}
|
||||
|
||||
hide_sidebar() {
|
||||
this.renderRoot.getElementById('sidebar').style.display = 'none';
|
||||
this.renderRoot.getElementById('sidebar_overlay').style.display = 'none';
|
||||
}
|
||||
|
||||
async channel_toggle_subscribed() {
|
||||
let channel = this.hash.substring(2);
|
||||
let subscribed = this.channels.indexOf(channel) != -1;
|
||||
subscribed = !subscribed;
|
||||
|
||||
await tfrpc.rpc.appendMessage(this.whoami, {
|
||||
type: 'channel',
|
||||
channel: channel,
|
||||
subscribed: subscribed,
|
||||
});
|
||||
if (subscribed) {
|
||||
this.channels = [].concat([channel], this.channels).sort();
|
||||
} else {
|
||||
this.channels = this.channels.filter((x) => x != channel);
|
||||
}
|
||||
}
|
||||
|
||||
channel() {
|
||||
return this.hash.startsWith('##') ? this.hash.substring(2) : undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
let profile =
|
||||
this.hash.startsWith('#@') && this.hash != '#@'
|
||||
? html`<tf-profile
|
||||
class="tf-profile"
|
||||
id=${this.hash.substring(1)}
|
||||
whoami=${this.whoami}
|
||||
.users=${this.users}
|
||||
></tf-profile>`
|
||||
: undefined;
|
||||
let profile = this.hash.startsWith('#@')
|
||||
? html`<tf-profile
|
||||
id=${this.hash.substring(1)}
|
||||
whoami=${this.whoami}
|
||||
.users=${this.users}
|
||||
></tf-profile>`
|
||||
: undefined;
|
||||
let edit_profile;
|
||||
if (
|
||||
!this.loading &&
|
||||
@ -174,118 +128,39 @@ class TfTabNewsElement extends LitElement {
|
||||
</div>`;
|
||||
}
|
||||
return html`
|
||||
<div
|
||||
class="w3-sidebar w3-bar-block w3-theme-d1 w3-collapse w3-animate-left"
|
||||
style="width: 2in; left: 0; z-index: 5"
|
||||
id="sidebar"
|
||||
>
|
||||
<div
|
||||
class="w3-right w3-button w3-hide-large"
|
||||
@click=${this.hide_sidebar}
|
||||
<p class="w3-bar">
|
||||
<button
|
||||
class="w3-bar-item w3-button w3-theme-d1"
|
||||
@click=${this.show_more}
|
||||
>
|
||||
×
|
||||
</div>
|
||||
${this.hash.startsWith('##') &&
|
||||
this.channels.indexOf(this.hash.substring(2)) == -1
|
||||
? html`
|
||||
<div class="w3-bar-item w3-theme-d2">Viewing</div>
|
||||
<a
|
||||
href="#"
|
||||
class="w3-bar-item w3-button"
|
||||
style="font-weight: bold"
|
||||
>${this.hash.substring(2)}</a
|
||||
>
|
||||
`
|
||||
: undefined}
|
||||
<div class="w3-bar-item w3-theme-d2">Channels</div>
|
||||
<a
|
||||
href="#"
|
||||
class="w3-bar-item w3-button"
|
||||
style=${this.hash == '#' ? 'font-weight: bold' : undefined}
|
||||
>general ${this.unread_status('')}</a
|
||||
>
|
||||
<a
|
||||
href="#@"
|
||||
class="w3-bar-item w3-button"
|
||||
style=${this.hash == '#@' ? 'font-weight: bold' : undefined}
|
||||
>@mentions ${this.unread_status('@')}</a
|
||||
>
|
||||
<a
|
||||
href="#🔐"
|
||||
class="w3-bar-item w3-button"
|
||||
style=${this.hash == '#🔐' ? 'font-weight: bold' : undefined}
|
||||
>🔐private ${this.unread_status('🔐')}</a
|
||||
>
|
||||
${this.channels.map(
|
||||
(x) => html`
|
||||
<a
|
||||
href=${'#' + encodeURIComponent('#' + x)}
|
||||
class="w3-bar-item w3-button"
|
||||
style=${this.hash == '##' + x ? 'font-weight: bold' : undefined}
|
||||
>#${x} ${this.unread_status(x)}</a
|
||||
>
|
||||
`
|
||||
)}
|
||||
${this.new_messages_text()}
|
||||
</button>
|
||||
</p>
|
||||
<div class="w3-bar">
|
||||
Welcome, <tf-user id=${this.whoami} .users=${this.users}></tf-user>!
|
||||
${edit_profile}
|
||||
</div>
|
||||
<div
|
||||
class="w3-overlay"
|
||||
id="sidebar_overlay"
|
||||
@click=${this.hide_sidebar}
|
||||
></div>
|
||||
<div style="margin-left: 2in; padding: 8px" id="main" class="w3-main">
|
||||
<div
|
||||
id="show_sidebar"
|
||||
class="w3-left w3-button w3-hide-large"
|
||||
@click=${this.show_sidebar}
|
||||
>
|
||||
☰
|
||||
</div>
|
||||
<p>
|
||||
<button class="w3-button w3-theme-d1" @click=${this.show_more}>
|
||||
${this.new_messages_text()}
|
||||
</button>
|
||||
${this.hash.startsWith('##')
|
||||
? html`
|
||||
<button
|
||||
class="w3-button w3-theme-d1"
|
||||
@click=${this.channel_toggle_subscribed}
|
||||
>
|
||||
${this.channels.indexOf(this.hash.substring(2)) != -1
|
||||
? 'Unsubscribe from #'
|
||||
: 'Subscribe to #'}${this.hash.substring(2)}
|
||||
</button>
|
||||
`
|
||||
: undefined}
|
||||
</p>
|
||||
<div class="w3-bar">
|
||||
Welcome, <tf-user id=${this.whoami} .users=${this.users}></tf-user>!
|
||||
${edit_profile}
|
||||
</div>
|
||||
<div>
|
||||
<tf-compose
|
||||
id="tf-compose"
|
||||
whoami=${this.whoami}
|
||||
.users=${this.users}
|
||||
.drafts=${this.drafts}
|
||||
@tf-draft=${this.draft}
|
||||
.channel=${this.channel()}
|
||||
></tf-compose>
|
||||
</div>
|
||||
${profile}
|
||||
<tf-tab-news-feed
|
||||
id="news"
|
||||
<div>
|
||||
<tf-compose
|
||||
id="tf-compose"
|
||||
whoami=${this.whoami}
|
||||
.users=${this.users}
|
||||
.following=${this.following}
|
||||
hash=${this.hash}
|
||||
.drafts=${this.drafts}
|
||||
.expanded=${this.expanded}
|
||||
@tf-draft=${this.draft}
|
||||
@tf-expand=${this.on_expand}
|
||||
.channels_unread=${this.channels_unread}
|
||||
.channels_latest=${this.channels_latest}
|
||||
></tf-tab-news-feed>
|
||||
></tf-compose>
|
||||
</div>
|
||||
${profile}
|
||||
<tf-tab-news-feed
|
||||
id="news"
|
||||
whoami=${this.whoami}
|
||||
.users=${this.users}
|
||||
.following=${this.following}
|
||||
hash=${this.hash}
|
||||
.drafts=${this.drafts}
|
||||
.expanded=${this.expanded}
|
||||
@tf-draft=${this.draft}
|
||||
@tf-expand=${this.on_expand}
|
||||
></tf-tab-news-feed>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import {styles} from './tf-styles.js';
|
||||
class TfTabSearchElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
drafts: {type: Object},
|
||||
whoami: {type: String},
|
||||
users: {type: Object},
|
||||
following: {type: Array},
|
||||
@ -23,10 +22,6 @@ class TfTabSearchElement extends LitElement {
|
||||
this.users = {};
|
||||
this.following = [];
|
||||
this.expanded = {};
|
||||
this.drafts = {};
|
||||
tfrpc.rpc.localStorageGet('drafts').then(function (d) {
|
||||
self.drafts = JSON.parse(d || '{}');
|
||||
});
|
||||
}
|
||||
|
||||
async search(query) {
|
||||
@ -75,18 +70,6 @@ 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() {
|
||||
if (this.query !== this.last_query) {
|
||||
this.last_query = this.query;
|
||||
@ -98,7 +81,7 @@ class TfTabSearchElement extends LitElement {
|
||||
<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-theme-d1" @click=${(event) => self.search(self.renderRoot.getElementById('search').value)}>Search</button>
|
||||
</div>
|
||||
<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>
|
||||
<tf-news id="news" whoami=${this.whoami} .messages=${this.messages} .users=${this.users} .expanded=${this.expanded} @tf-expand=${this.on_expand}></tf-news>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class TfTagElement extends LitElement {
|
||||
render() {
|
||||
let number = this.count ? html` (${this.count})` : undefined;
|
||||
return html`<a
|
||||
href=${'#' + encodeURIComponent(this.tag)}
|
||||
href="#q=${this.tag}"
|
||||
style="display: inline-block; margin: 3px; border: 1px solid black; background-color: #444; padding: 4px; border-radius: 3px"
|
||||
>${this.tag}${number}</a
|
||||
>`;
|
||||
|
@ -37,7 +37,7 @@ class TfUserElement extends LitElement {
|
||||
if (image_link !== undefined) {
|
||||
image = html`<img
|
||||
class="w3-circle"
|
||||
style="width: 2em; height: 2em; vertical-align: middle; object-fit: cover"
|
||||
style="width: 2em; height: 2em; vertical-align: middle"
|
||||
src="/${image_link}/view"
|
||||
/>`;
|
||||
}
|
||||
|
@ -2,12 +2,6 @@ import * as hashtagify from './commonmark-hashtag.js';
|
||||
|
||||
const k_code_classes = 'w3-theme-l4 w3-theme-border w3-round';
|
||||
|
||||
var reUnsafeProtocol = /^javascript:|vbscript:|file:|data:/i;
|
||||
var reSafeDataProtocol = /^data:image\/(?:png|gif|jpeg|webp)/i;
|
||||
var potentiallyUnsafe = function (url) {
|
||||
return reUnsafeProtocol.test(url) && !reSafeDataProtocol.test(url);
|
||||
};
|
||||
|
||||
function image(node, entering) {
|
||||
if (
|
||||
node.firstChild?.type === 'text' &&
|
||||
@ -87,8 +81,8 @@ function attrs(node) {
|
||||
}
|
||||
|
||||
export function markdown(md) {
|
||||
let reader = new commonmark.Parser();
|
||||
let writer = new commonmark.HtmlRenderer({safe: true});
|
||||
let reader = new commonmark.Parser({safe: true});
|
||||
let writer = new commonmark.HtmlRenderer();
|
||||
writer.image = image;
|
||||
writer.code = code;
|
||||
writer.attrs = attrs;
|
||||
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "💾",
|
||||
"previous": "&mvGTlWKFR5QM/3nb4fJ2WQq0n/gNKvBmhGDkAvb8ki8=.sha256"
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
async function query(sql, args) {
|
||||
let rows = [];
|
||||
await ssb.sqlAsync(sql, args ?? [], function (row) {
|
||||
rows.push(row);
|
||||
});
|
||||
return rows;
|
||||
}
|
||||
|
||||
async function get_biggest() {
|
||||
return query(`
|
||||
select author, sum(length(content)) as size from messages group by author order by size desc limit 10;
|
||||
`);
|
||||
}
|
||||
|
||||
async function get_total() {
|
||||
return (
|
||||
await query(`
|
||||
select sum(length(content)) as size, count(distinct author) as count from messages;
|
||||
`)
|
||||
)[0];
|
||||
}
|
||||
|
||||
async function get_names(identities) {
|
||||
return query(
|
||||
`
|
||||
SELECT author, name FROM (
|
||||
SELECT
|
||||
messages.author,
|
||||
RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank,
|
||||
messages.content ->> 'name' AS name
|
||||
FROM messages
|
||||
JOIN json_each(?) AS identities ON identities.value = messages.author
|
||||
WHERE
|
||||
json_extract(messages.content, '$.type') = 'about' AND
|
||||
content ->> 'about' = messages.author AND name IS NOT NULL)
|
||||
WHERE author_rank = 1
|
||||
`,
|
||||
[JSON.stringify(identities)]
|
||||
);
|
||||
}
|
||||
|
||||
async function get_most_follows() {
|
||||
return query(`
|
||||
select author, count(*) as count
|
||||
from messages
|
||||
where content ->> 'type' = 'contact' and content ->> 'following' = true
|
||||
group by author
|
||||
order by count desc
|
||||
limit 10;
|
||||
`);
|
||||
}
|
||||
|
||||
function nice_size(bytes) {
|
||||
let value = bytes;
|
||||
let index = 0;
|
||||
let units = ['B', 'kB', 'MB', 'GB'];
|
||||
while (value > 1024 && index < units.length - 1) {
|
||||
value /= 1024;
|
||||
index++;
|
||||
}
|
||||
return `${Math.round(value * 10) / 10} ${units[index]}`;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await app.setDocument(
|
||||
'<p style="color: #fff">Finding the top 10 largest feeds...</p>'
|
||||
);
|
||||
let most_follows = await get_most_follows();
|
||||
let total = await get_total();
|
||||
let identities = await ssb.getAllIdentities();
|
||||
let following1 = await ssb.following(identities, 1);
|
||||
let following2 = await ssb.following(identities, 2);
|
||||
let biggest = await get_biggest();
|
||||
let names = await get_names(
|
||||
[].concat(
|
||||
biggest.map((x) => x.author),
|
||||
most_follows.map((x) => x.author)
|
||||
)
|
||||
);
|
||||
names = Object.fromEntries(names.map((x) => [x.author, x.name]));
|
||||
for (let item of biggest) {
|
||||
item.name = names[item.author];
|
||||
item.following =
|
||||
identities.indexOf(item.author) != -1
|
||||
? 0
|
||||
: following1[item.author] !== undefined
|
||||
? 1
|
||||
: following2[item.author] !== undefined
|
||||
? 2
|
||||
: undefined;
|
||||
}
|
||||
for (let item of most_follows) {
|
||||
item.name = names[item.author];
|
||||
}
|
||||
let html = `<body style="color: #000; background-color: #ddd">\n
|
||||
<h1>Storage Summary</h1>
|
||||
<h2>Top 10 Accounts by Size</h2>
|
||||
<ol>`;
|
||||
for (let item of biggest) {
|
||||
html += `<li>
|
||||
<span style="color: #888">${nice_size(item.size)}</span>
|
||||
<a target="_top" href="/~core/ssb/#${encodeURI(item.author)}">${item.name ?? item.author}</a>
|
||||
</li>
|
||||
\n`;
|
||||
}
|
||||
html += `
|
||||
</ol>
|
||||
<h2>Top 10 Accounts by Follows</h2>
|
||||
<ol>`;
|
||||
for (let item of most_follows) {
|
||||
html += `<li>
|
||||
<span style="color: #888">${item.count}</span>
|
||||
${following2[item.author] ? '✅' : '🚫'}
|
||||
<a target="_top" href="/~core/ssb/#${encodeURI(item.author)}">${item.name ?? item.author}</a>
|
||||
</li>
|
||||
\n`;
|
||||
}
|
||||
html += `
|
||||
</ol>
|
||||
<p>Total <span style="color: #888">${nice_size(total.size)}</span> in ${total.count} accounts.</p>
|
||||
`;
|
||||
await app.setDocument(html);
|
||||
}
|
||||
|
||||
main().catch(function (e) {
|
||||
print(e);
|
||||
});
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "📦"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
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 +0,0 @@
|
||||
Hello, world!
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "👋",
|
||||
"previous": "&7gFmLW5zSMhmxWWY1+jeRcHdullgujSqGJg94lVgr1k=.sha256"
|
||||
"previous": "&W5aJp2DgOW5rQ0AOIC9Ut3DpsahPrO6PjkJ1PQbNRdM=.sha256"
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 19 KiB |
@ -1,75 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 21 KiB |
@ -1,23 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.8 KiB |
@ -66,30 +66,8 @@
|
||||
<a
|
||||
class="w3-button w3-black w3-padding-large"
|
||||
href="https://dev.tildefriends.net/"
|
||||
><i class="fa fa-mug-hot"></i> Development</a
|
||||
><i class="fa fa-mug-hot"></i> Code</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 class="w3-col l4 m6">
|
||||
<img src="tildefriends.png" class="w3-image w3-right w3-hide-small" />
|
||||
@ -110,31 +88,36 @@
|
||||
<a href="https://dev.tildefriends.net/cory/tildefriends/releases"
|
||||
>Download</a
|
||||
>
|
||||
Tilde Friends or use
|
||||
Tilde Friends and run your own instance, 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>
|
||||
Create an account to identify yourself with that instance by
|
||||
username and password.
|
||||
</li>
|
||||
<li>
|
||||
Create an SSB identity in the <b>ssb</b> app. This will generate a
|
||||
keypair used to identify yourself to other users and sign your
|
||||
messages so that they can be verified as from you.
|
||||
</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>
|
||||
Connect to others. You will automatically discover peers on the
|
||||
same instance and same network if there are any. Or use
|
||||
<a href="https://github.com/staltz/ssb-room/blob/master/FAQ.md"
|
||||
>rooms</a
|
||||
>
|
||||
and pubs to reach more distant users.
|
||||
<a href="https://www.tildefriends.net/~cory/room/"
|
||||
>tildefriends.net itself</a
|
||||
>
|
||||
operates as a room, so you can connect and see who else is online
|
||||
and establish a connection.
|
||||
</li>
|
||||
<li>Follow people to grow your network.</li>
|
||||
<li>
|
||||
@ -223,13 +206,8 @@
|
||||
|
||||
<!-- Technlology Section -->
|
||||
<div class="w3-container w3-padding-64 w3-light-grey w3-center">
|
||||
<h1 class="w3-jumbo"><b>Boring Technology</b></h1>
|
||||
<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>
|
||||
<h1 class="w3-jumbo"><b>Trusted Technology</b></h1>
|
||||
<p>Tilde Friends is built using boring, trusted tech.</p>
|
||||
<p>
|
||||
Though of course for building Tilde Friends apps, you are free to use
|
||||
whatever fits.
|
||||
@ -266,7 +244,7 @@
|
||||
<i class="fa fa-lock w3-text-purple w3-jumbo"></i>
|
||||
<p>libsodium</p>
|
||||
</a>
|
||||
<a href="https://github.com/openssl/openssl/releases" class="w3-col s3">
|
||||
<a href="https://www.openssl.org/" class="w3-col s3">
|
||||
<i class="fa fa-shield-halved w3-text-green w3-jumbo"></i>
|
||||
<p>OpenSSL</p>
|
||||
</a>
|
||||
@ -292,13 +270,6 @@
|
||||
<i class="fa fa-fire w3-text-cyan w3-jumbo"></i>
|
||||
<p>Lit</p>
|
||||
</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">
|
||||
<i class="fa fa-hammer w3-text-teal w3-jumbo"></i>
|
||||
<p>GNU Make</p>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "📝",
|
||||
"previous": "&4UHlsfQJvSh7L3D86uFtr7KUKCMRVBBTFxRIMqIc5as=.sha256"
|
||||
"previous": "&DaYqKHRBKhjFGaOzbKZ1+/pLspJeEkDJYTF2B50tH6k=.sha256"
|
||||
}
|
||||
|
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
@ -2,8 +2,8 @@ import * as utils from './utils.js';
|
||||
import * as commonmark from './commonmark.min.js';
|
||||
|
||||
function markdown(md) {
|
||||
let reader = new commonmark.Parser();
|
||||
let writer = new commonmark.HtmlRenderer({safe: true});
|
||||
let reader = new commonmark.Parser({safe: true});
|
||||
let writer = new commonmark.HtmlRenderer();
|
||||
let parsed = reader.parse(md || '');
|
||||
let walker = parsed.walker();
|
||||
let event;
|
||||
|
44
apps/wiki/lit-all.min.js
vendored
44
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
@ -20,8 +20,8 @@ class TfWikiDocElement extends LitElement {
|
||||
}
|
||||
|
||||
markdown(md) {
|
||||
let reader = new commonmark.Parser();
|
||||
let writer = new commonmark.HtmlRenderer({safe: true});
|
||||
let reader = new commonmark.Parser({safe: true});
|
||||
let writer = new commonmark.HtmlRenderer();
|
||||
let parsed = reader.parse(md || '');
|
||||
let walker = parsed.walker();
|
||||
let event;
|
||||
|
@ -10,7 +10,7 @@ let gSessionIndex = 0;
|
||||
* @returns
|
||||
*/
|
||||
function makeSessionId() {
|
||||
return 'session_' + (gSessionIndex++).toString();
|
||||
return (gSessionIndex++).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,7 +172,11 @@ async function socket(request, response, client) {
|
||||
0x1
|
||||
);
|
||||
} else {
|
||||
process = await core.getProcessBlob(blobId, sessionId, options);
|
||||
process = await core.getSessionProcessBlob(
|
||||
blobId,
|
||||
sessionId,
|
||||
options
|
||||
);
|
||||
}
|
||||
}
|
||||
if (process) {
|
||||
|
@ -56,7 +56,7 @@ class TfNavigationElement extends LitElement {
|
||||
status: {type: Object},
|
||||
spark_lines: {type: Object},
|
||||
version: {type: Object},
|
||||
show_expanded: {type: Boolean},
|
||||
show_version: {type: Boolean},
|
||||
identity: {type: String},
|
||||
identities: {type: Array},
|
||||
names: {type: Object},
|
||||
@ -105,6 +105,7 @@ class TfNavigationElement extends LitElement {
|
||||
let spark_line = document.createElement('tf-sparkline');
|
||||
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.max) {
|
||||
@ -161,10 +162,6 @@ class TfNavigationElement extends LitElement {
|
||||
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')}
|
||||
@ -172,7 +169,6 @@ class TfNavigationElement extends LitElement {
|
||||
Manage Identities...
|
||||
</button>
|
||||
<button
|
||||
id="edit_profile"
|
||||
class="w3-bar-item w3-button w3-border"
|
||||
@click=${self.edit_profile}
|
||||
>
|
||||
@ -315,13 +311,13 @@ class TfNavigationElement extends LitElement {
|
||||
<span
|
||||
class="w3-bar-item"
|
||||
style="cursor: pointer"
|
||||
@click=${() => (this.show_expanded = !this.show_expanded)}
|
||||
@click=${() => (this.show_version = !this.show_version)}
|
||||
>😎</span
|
||||
>
|
||||
<span
|
||||
class="w3-bar-item"
|
||||
style=${'white-space: nowrap' +
|
||||
(this.show_expanded ? '' : '; display: none')}
|
||||
(this.show_version ? '' : '; display: none')}
|
||||
title=${this.version?.name +
|
||||
' ' +
|
||||
Object.entries(this.version || {})
|
||||
@ -376,11 +372,9 @@ class TfNavigationElement extends LitElement {
|
||||
</div>
|
||||
`
|
||||
: undefined}
|
||||
<span class=${this.show_expanded ? '' : 'w3-hide-small'}>
|
||||
${Object.keys(this.spark_lines)
|
||||
.sort()
|
||||
.map((x) => this.spark_lines[x])}
|
||||
</span>
|
||||
${Object.keys(this.spark_lines)
|
||||
.sort()
|
||||
.map((x) => this.spark_lines[x])}
|
||||
${this.render_identity()}
|
||||
</div>
|
||||
${this.status?.is_error
|
||||
@ -388,8 +382,8 @@ class TfNavigationElement extends LitElement {
|
||||
<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>
|
||||
<span @click=${self.clear_error} class="w3-button w3-display-topright">×</span>
|
||||
<div style="color: ${this.status.color ?? kErrorColor}"><b>ERROR:</b><p style="white-space: pre">${this.status.message}</p></div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
@ -1180,7 +1174,7 @@ function api_requestPermission(permission, id) {
|
||||
|
||||
let div = document.createElement('div');
|
||||
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');
|
||||
span.style = 'font-weight: bold';
|
||||
@ -1196,7 +1190,6 @@ function api_requestPermission(permission, id) {
|
||||
check.classList.add('w3-check');
|
||||
check.classList.add('w3-blue');
|
||||
div.appendChild(check);
|
||||
div.appendChild(document.createTextNode(' '));
|
||||
let label = document.createElement('label');
|
||||
label.htmlFor = check.id;
|
||||
label.appendChild(document.createTextNode('Remember this decision.'));
|
||||
@ -1789,11 +1782,10 @@ async function sourcePretty() {
|
||||
let prettier = (await import('/prettier/standalone.mjs')).default;
|
||||
let babel = (await import('/prettier/babel.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 formatted = await prettier.format(source, {
|
||||
parser: gCurrentFile?.toLowerCase()?.endsWith('.html') ? 'html' : 'babel',
|
||||
plugins: [babel, estree, prettier_html],
|
||||
parser: 'babel',
|
||||
plugins: [babel, estree],
|
||||
trailingComma: 'es5',
|
||||
useTabs: true,
|
||||
semi: true,
|
||||
@ -1828,8 +1820,8 @@ function toggleVisibleWhitespace() {
|
||||
.cm-highlightTab {
|
||||
background-image: unset !important;
|
||||
}
|
||||
.cm-highlightSpace {
|
||||
background-image: unset !important;
|
||||
.cm-highlightSpace:before {
|
||||
content: unset !important;
|
||||
}
|
||||
`;
|
||||
window.localStorage.setItem('visible_whitespace', '1');
|
||||
|
708
core/core.js
708
core/core.js
@ -4,6 +4,77 @@ import * as http from './http.js';
|
||||
|
||||
let gProcesses = {};
|
||||
let gStatsTimer = false;
|
||||
|
||||
const k_content_security_policy =
|
||||
'sandbox allow-downloads allow-top-navigation-by-user-activation';
|
||||
|
||||
const k_global_settings = {
|
||||
index: {
|
||||
type: 'string',
|
||||
default_value: '/~core/apps/',
|
||||
description: 'Default path.',
|
||||
},
|
||||
index_map: {
|
||||
type: 'textarea',
|
||||
default_value: undefined,
|
||||
description:
|
||||
'Mappings from hostname to redirect path, one per line, as in: "www.tildefriends.net=/~core/index/"',
|
||||
},
|
||||
room: {
|
||||
type: 'boolean',
|
||||
default_value: true,
|
||||
description: 'Whether this instance should behave as a room.',
|
||||
},
|
||||
room_name: {
|
||||
type: 'string',
|
||||
default_value: 'tilde friends tunnel',
|
||||
description: 'Name of the room.',
|
||||
},
|
||||
code_of_conduct: {
|
||||
type: 'textarea',
|
||||
default_value: undefined,
|
||||
description: 'Code of conduct presented at sign-in.',
|
||||
},
|
||||
http_redirect: {
|
||||
type: 'string',
|
||||
default_value: undefined,
|
||||
description:
|
||||
'If connecting by HTTP and HTTPS is configured, Location header prefix (ie, "https://example.com")',
|
||||
},
|
||||
fetch_hosts: {
|
||||
type: 'string',
|
||||
default_value: undefined,
|
||||
description:
|
||||
'Comma-separated list of host names to which HTTP fetch requests are allowed. None if empty.',
|
||||
},
|
||||
blob_fetch_age_seconds: {
|
||||
type: 'integer',
|
||||
default_value:
|
||||
platform() == 'android' || platform() == 'iphone'
|
||||
? 0.5 * 365 * 24 * 60 * 60
|
||||
: undefined,
|
||||
description:
|
||||
'Only blobs mentioned more recently than this age will be automatically fetched.',
|
||||
},
|
||||
blob_expire_age_seconds: {
|
||||
type: 'integer',
|
||||
default_value:
|
||||
platform() == 'android' || platform() == 'iphone'
|
||||
? 1.0 * 365 * 24 * 60 * 60
|
||||
: undefined,
|
||||
description: 'Blobs older than this will be automatically deleted.',
|
||||
},
|
||||
seeds_host: {
|
||||
type: 'string',
|
||||
default_value: '',
|
||||
description: 'Hostname for seed connections.',
|
||||
},
|
||||
};
|
||||
|
||||
let gGlobalSettings = {
|
||||
index: '/~core/apps/',
|
||||
};
|
||||
|
||||
let kPingInterval = 60 * 1000;
|
||||
|
||||
/**
|
||||
@ -175,6 +246,23 @@ function postMessageInternal(from, to, message) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODOC
|
||||
* @param {*} blobId
|
||||
* @param {*} session
|
||||
* @param {*} options
|
||||
* @returns
|
||||
*/
|
||||
async function getSessionProcessBlob(blobId, session, options) {
|
||||
let actualOptions = {timeout: kPingInterval};
|
||||
if (options) {
|
||||
for (let i in options) {
|
||||
actualOptions[i] = options[i];
|
||||
}
|
||||
}
|
||||
return getProcessBlob(blobId, 'session_' + session, actualOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODOC
|
||||
* @param {*} blobId
|
||||
@ -202,7 +290,7 @@ async function getProcessBlob(blobId, key, options) {
|
||||
}
|
||||
process.lastActive = Date.now();
|
||||
process.lastPing = null;
|
||||
process.timeout = kPingInterval;
|
||||
process.timeout = options.timeout;
|
||||
process.ready = new Promise(function (resolve, reject) {
|
||||
resolveReady = resolve;
|
||||
rejectReady = reject;
|
||||
@ -241,59 +329,59 @@ async function getProcessBlob(blobId, key, options) {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
permissionsGranted: async function () {
|
||||
permissionsGranted: function () {
|
||||
let user = process?.credentials?.session?.name;
|
||||
let settings = await loadSettings();
|
||||
if (
|
||||
user &&
|
||||
options?.packageOwner &&
|
||||
options?.packageName &&
|
||||
settings.userPermissions &&
|
||||
settings.userPermissions[user] &&
|
||||
settings.userPermissions[user][options.packageOwner]
|
||||
gGlobalSettings.userPermissions &&
|
||||
gGlobalSettings.userPermissions[user] &&
|
||||
gGlobalSettings.userPermissions[user][options.packageOwner]
|
||||
) {
|
||||
return settings.userPermissions[user][options.packageOwner][
|
||||
options.packageName
|
||||
];
|
||||
return gGlobalSettings.userPermissions[user][
|
||||
options.packageOwner
|
||||
][options.packageName];
|
||||
}
|
||||
},
|
||||
allPermissionsGranted: async function () {
|
||||
allPermissionsGranted: function () {
|
||||
let user = process?.credentials?.session?.name;
|
||||
let settings = await loadSettings();
|
||||
if (
|
||||
user &&
|
||||
options?.packageOwner &&
|
||||
options?.packageName &&
|
||||
settings.userPermissions &&
|
||||
settings.userPermissions[user]
|
||||
gGlobalSettings.userPermissions &&
|
||||
gGlobalSettings.userPermissions[user]
|
||||
) {
|
||||
return settings.userPermissions[user];
|
||||
return gGlobalSettings.userPermissions[user];
|
||||
}
|
||||
},
|
||||
permissionsForUser: async function (user) {
|
||||
let settings = await loadSettings();
|
||||
return settings?.permissions?.[user] ?? [];
|
||||
permissionsForUser: function (user) {
|
||||
return (
|
||||
(gGlobalSettings?.permissions
|
||||
? gGlobalSettings.permissions[user]
|
||||
: []) ?? []
|
||||
);
|
||||
},
|
||||
apps: (user) => getApps(user, process),
|
||||
getSockets: getSockets,
|
||||
permissionTest: async function (permission) {
|
||||
permissionTest: function (permission) {
|
||||
let user = process?.credentials?.session?.name;
|
||||
let settings = await loadSettings();
|
||||
if (!user || !options?.packageOwner || !options?.packageName) {
|
||||
return;
|
||||
} else if (
|
||||
settings.userPermissions &&
|
||||
settings.userPermissions[user] &&
|
||||
settings.userPermissions[user][options.packageOwner] &&
|
||||
settings.userPermissions[user][options.packageOwner][
|
||||
gGlobalSettings.userPermissions &&
|
||||
gGlobalSettings.userPermissions[user] &&
|
||||
gGlobalSettings.userPermissions[user][options.packageOwner] &&
|
||||
gGlobalSettings.userPermissions[user][options.packageOwner][
|
||||
options.packageName
|
||||
] &&
|
||||
settings.userPermissions[user][options.packageOwner][
|
||||
gGlobalSettings.userPermissions[user][options.packageOwner][
|
||||
options.packageName
|
||||
][permission] !== undefined
|
||||
) {
|
||||
if (
|
||||
settings.userPermissions[user][options.packageOwner][
|
||||
gGlobalSettings.userPermissions[user][options.packageOwner][
|
||||
options.packageName
|
||||
][permission]
|
||||
) {
|
||||
@ -304,9 +392,9 @@ async function getProcessBlob(blobId, key, options) {
|
||||
} else if (process.app) {
|
||||
return process.app
|
||||
.makeFunction(['requestPermission'])(permission)
|
||||
.then(async function (value) {
|
||||
.then(function (value) {
|
||||
if (value == 'allow') {
|
||||
await ssb.setUserPermission(
|
||||
storePermission(
|
||||
user,
|
||||
options.packageOwner,
|
||||
options.packageName,
|
||||
@ -318,7 +406,7 @@ async function getProcessBlob(blobId, key, options) {
|
||||
} else if (value == 'allow once') {
|
||||
return true;
|
||||
} else if (value == 'deny') {
|
||||
await ssb.setUserPermission(
|
||||
storePermission(
|
||||
user,
|
||||
options.packageOwner,
|
||||
options.packageName,
|
||||
@ -405,25 +493,22 @@ async function getProcessBlob(blobId, key, options) {
|
||||
}
|
||||
};
|
||||
if (process.credentials?.permissions?.administration) {
|
||||
imports.core.globalSettingsDescriptions = async function () {
|
||||
let settings = Object.assign({}, defaultGlobalSettings());
|
||||
for (let [key, value] of Object.entries(await loadSettings())) {
|
||||
imports.core.globalSettingsDescriptions = function () {
|
||||
let settings = Object.assign({}, k_global_settings);
|
||||
for (let [key, value] of Object.entries(gGlobalSettings)) {
|
||||
if (settings[key]) {
|
||||
settings[key].value = value;
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
imports.core.globalSettingsGet = async function (key) {
|
||||
let settings = await loadSettings();
|
||||
return settings?.[key];
|
||||
imports.core.globalSettingsGet = function (key) {
|
||||
return gGlobalSettings[key];
|
||||
};
|
||||
imports.core.globalSettingsSet = async function (key, value) {
|
||||
await imports.core.permissionTest('set_global_setting');
|
||||
imports.core.globalSettingsSet = function (key, value) {
|
||||
print('Setting', key, value);
|
||||
let settings = await loadSettings();
|
||||
settings[key] = value;
|
||||
await new Database('core').set('settings', JSON.stringify(settings));
|
||||
gGlobalSettings[key] = value;
|
||||
setGlobalSettings(gGlobalSettings);
|
||||
print('Done.');
|
||||
};
|
||||
imports.core.deleteUser = async function (user) {
|
||||
@ -590,24 +675,11 @@ async function getProcessBlob(blobId, key, options) {
|
||||
);
|
||||
}
|
||||
};
|
||||
imports.ssb.swapWithServerIdentity = function (id) {
|
||||
if (
|
||||
process.credentials &&
|
||||
process.credentials.session &&
|
||||
process.credentials.session.name
|
||||
) {
|
||||
return ssb.swapWithServerIdentity(
|
||||
process.credentials.session.name,
|
||||
id
|
||||
);
|
||||
}
|
||||
};
|
||||
imports.ssb.addEventListener = undefined;
|
||||
imports.ssb.removeEventListener = undefined;
|
||||
imports.ssb.getIdentityInfo = undefined;
|
||||
imports.fetch = async function (url, options) {
|
||||
let settings = await loadSettings();
|
||||
return http.fetch(url, options, settings?.fetch_hosts);
|
||||
imports.fetch = function (url, options) {
|
||||
return http.fetch(url, options, gGlobalSettings.fetch_hosts);
|
||||
};
|
||||
|
||||
if (
|
||||
@ -634,12 +706,12 @@ async function getProcessBlob(blobId, key, options) {
|
||||
Object.keys(db).map((x) => [x, db[x].bind(db)])
|
||||
);
|
||||
};
|
||||
imports.databases = async function () {
|
||||
imports.databases = function () {
|
||||
return [].concat(
|
||||
await databases.list(
|
||||
databases.list(
|
||||
':shared:' + process.credentials.session.name + ':%'
|
||||
),
|
||||
await databases.list(process.credentials.session.name + ':%')
|
||||
databases.list(process.credentials.session.name + ':%')
|
||||
);
|
||||
};
|
||||
}
|
||||
@ -658,22 +730,22 @@ async function getProcessBlob(blobId, key, options) {
|
||||
);
|
||||
};
|
||||
}
|
||||
process.sendPermissions = async function sendPermissions() {
|
||||
process.sendPermissions = function sendPermissions() {
|
||||
process.app.send({
|
||||
action: 'permissions',
|
||||
permissions: await imports.core.permissionsGranted(),
|
||||
permissions: imports.core.permissionsGranted(),
|
||||
});
|
||||
};
|
||||
process.resetPermission = async function resetPermission(permission) {
|
||||
process.resetPermission = function resetPermission(permission) {
|
||||
let user = process?.credentials?.session?.name;
|
||||
await ssb.setUserPermission(
|
||||
storePermission(
|
||||
user,
|
||||
options?.packageOwner,
|
||||
options?.packageName,
|
||||
permission,
|
||||
undefined
|
||||
);
|
||||
return process.sendPermissions();
|
||||
process.sendPermissions();
|
||||
};
|
||||
process.task.setImports(imports);
|
||||
process.task.activate();
|
||||
@ -706,7 +778,7 @@ async function getProcessBlob(blobId, key, options) {
|
||||
broadcastEvent('onSessionBegin', [getUser(process, process)]);
|
||||
if (process.app) {
|
||||
process.app.send({action: 'ready', version: version()});
|
||||
await process.sendPermissions();
|
||||
process.sendPermissions();
|
||||
}
|
||||
await process.task.execute({name: appSourceName, source: appSource});
|
||||
resolveReady(process);
|
||||
@ -730,6 +802,374 @@ async function getProcessBlob(blobId, key, options) {
|
||||
return process;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODOC
|
||||
* @param {*} settings
|
||||
* @returns
|
||||
*/
|
||||
async function setGlobalSettings(settings) {
|
||||
gGlobalSettings = settings;
|
||||
try {
|
||||
return await new Database('core').set('settings', JSON.stringify(settings));
|
||||
} catch (error) {
|
||||
print('Error storing settings:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODOC
|
||||
* @param {*} response
|
||||
* @param {*} data
|
||||
* @param {*} type
|
||||
* @param {*} headers
|
||||
* @param {*} status_code
|
||||
*/
|
||||
function sendData(response, data, type, headers, status_code) {
|
||||
if (data) {
|
||||
response.writeHead(
|
||||
status_code ?? 200,
|
||||
Object.assign(
|
||||
{
|
||||
'Content-Type':
|
||||
type ||
|
||||
httpd.mime_type_from_magic_bytes(data) ||
|
||||
'application/binary',
|
||||
'Content-Length': data.byteLength,
|
||||
},
|
||||
headers || {}
|
||||
)
|
||||
);
|
||||
response.end(data);
|
||||
} else {
|
||||
response.writeHead(
|
||||
status_code ?? 404,
|
||||
Object.assign(
|
||||
{
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
'Content-Length': 'File not found'.length,
|
||||
},
|
||||
headers || {}
|
||||
)
|
||||
);
|
||||
response.end('File not found');
|
||||
}
|
||||
}
|
||||
|
||||
let g_handler_index = 0;
|
||||
|
||||
/**
|
||||
* TODOC
|
||||
* @param {*} response
|
||||
* @param {*} handler_blob_id
|
||||
* @param {*} path
|
||||
* @param {*} query
|
||||
* @param {*} headers
|
||||
* @param {*} packageOwner
|
||||
* @param {*} packageName
|
||||
* @returns
|
||||
*/
|
||||
async function useAppHandler(
|
||||
response,
|
||||
handler_blob_id,
|
||||
path,
|
||||
query,
|
||||
headers,
|
||||
packageOwner,
|
||||
packageName
|
||||
) {
|
||||
print('useAppHandler', packageOwner, packageName);
|
||||
let do_resolve;
|
||||
let promise = new Promise(async function (resolve, reject) {
|
||||
do_resolve = resolve;
|
||||
});
|
||||
let process;
|
||||
let result;
|
||||
try {
|
||||
process = await getProcessBlob(
|
||||
handler_blob_id,
|
||||
'handler_' + g_handler_index++,
|
||||
{
|
||||
script: 'handler.js',
|
||||
imports: {
|
||||
request: {
|
||||
path: path,
|
||||
query: query,
|
||||
},
|
||||
respond: do_resolve,
|
||||
},
|
||||
credentials: await httpd.auth_query(headers),
|
||||
packageOwner: packageOwner,
|
||||
packageName: packageName,
|
||||
}
|
||||
);
|
||||
await process.ready;
|
||||
|
||||
result = await promise;
|
||||
} finally {
|
||||
if (process?.task) {
|
||||
await process.task.kill();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODOC
|
||||
* @param {*} request
|
||||
* @param {*} response
|
||||
* @param {*} blobId
|
||||
* @param {*} uri
|
||||
* @returns
|
||||
*/
|
||||
async function blobHandler(request, response, blobId, uri) {
|
||||
if (!uri) {
|
||||
response.writeHead(303, {
|
||||
Location:
|
||||
(request.client.tls ? 'https://' : 'http://') +
|
||||
(request.headers['x-forwarded-host'] ?? request.headers.host) +
|
||||
blobId +
|
||||
'/',
|
||||
'Content-Length': '0',
|
||||
});
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
|
||||
let process;
|
||||
if (uri == '/view') {
|
||||
let data;
|
||||
let match;
|
||||
let query = form.decodeForm(request.query);
|
||||
let headers = {
|
||||
'Content-Security-Policy': k_content_security_policy,
|
||||
};
|
||||
if (query.filename && query.filename.match(/^[A-Za-z0-9\.-]*$/)) {
|
||||
headers['Content-Disposition'] = `attachment; filename=${query.filename}`;
|
||||
}
|
||||
if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) {
|
||||
let id = await new Database(match[1]).get('path:' + match[2]);
|
||||
if (id) {
|
||||
if (request.headers['if-none-match'] === '"' + id + '"') {
|
||||
headers['Content-Length'] = '0';
|
||||
response.writeHead(304, headers);
|
||||
response.end();
|
||||
} else {
|
||||
data = await ssb.blobGet(id);
|
||||
if (match[3]) {
|
||||
let appObject = JSON.parse(data);
|
||||
data = appObject.files[match[3]];
|
||||
}
|
||||
sendData(
|
||||
response,
|
||||
data,
|
||||
undefined,
|
||||
Object.assign({etag: '"' + id + '"'}, headers)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (request.headers['if-none-match'] === '"' + blobId + '"') {
|
||||
headers['Content-Length'] = '0';
|
||||
response.writeHead(304, headers);
|
||||
response.end();
|
||||
} else {
|
||||
sendData(
|
||||
response,
|
||||
data,
|
||||
undefined,
|
||||
Object.assign({etag: '"' + blobId + '"'}, headers)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (request.headers['if-none-match'] === '"' + blobId + '"') {
|
||||
headers['Content-Length'] = '0';
|
||||
response.writeHead(304, headers);
|
||||
response.end();
|
||||
} else {
|
||||
data = await ssb.blobGet(blobId);
|
||||
sendData(
|
||||
response,
|
||||
data,
|
||||
undefined,
|
||||
Object.assign({etag: '"' + blobId + '"'}, headers)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (uri == '/save') {
|
||||
let match;
|
||||
if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) {
|
||||
let user = match[1];
|
||||
let appName = match[2];
|
||||
let credentials = await httpd.auth_query(request.headers);
|
||||
if (
|
||||
credentials &&
|
||||
credentials.session &&
|
||||
(credentials.session.name == user ||
|
||||
(credentials.permissions.administration && user == 'core'))
|
||||
) {
|
||||
let database = new Database(user);
|
||||
|
||||
let app_object = JSON.parse(utf8Decode(request.body));
|
||||
let previous_id = await database.get('path:' + appName);
|
||||
if (previous_id) {
|
||||
try {
|
||||
let previous_object = JSON.parse(
|
||||
utf8Decode(await ssb.blobGet(previous_id))
|
||||
);
|
||||
delete previous_object.previous;
|
||||
delete app_object.previous;
|
||||
if (JSON.stringify(previous_object) == JSON.stringify(app_object)) {
|
||||
response.writeHead(200, {
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
response.end('/' + previous_id);
|
||||
return;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
app_object.previous = previous_id;
|
||||
let newBlobId = await ssb.blobStore(JSON.stringify(app_object));
|
||||
|
||||
let apps = new Set();
|
||||
let apps_original = await database.get('apps');
|
||||
try {
|
||||
apps = new Set(JSON.parse(apps_original));
|
||||
} catch {}
|
||||
if (!apps.has(appName)) {
|
||||
apps.add(appName);
|
||||
}
|
||||
apps = JSON.stringify([...apps].sort());
|
||||
if (apps != apps_original) {
|
||||
await database.set('apps', apps);
|
||||
}
|
||||
await database.set('path:' + appName, newBlobId);
|
||||
response.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
|
||||
response.end('/' + newBlobId);
|
||||
} else {
|
||||
response.writeHead(401, {'Content-Type': 'text/plain; charset=utf-8'});
|
||||
response.end('401 Unauthorized');
|
||||
return;
|
||||
}
|
||||
} else if (blobId === '') {
|
||||
let newBlobId = await ssb.blobStore(request.body);
|
||||
response.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
|
||||
response.end('/' + newBlobId);
|
||||
} else {
|
||||
response.writeHead(400, {'Content-Type': 'text/plain; charset=utf-8'});
|
||||
response.end('Invalid name.');
|
||||
}
|
||||
} else if (uri == '/delete') {
|
||||
let match;
|
||||
if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) {
|
||||
let user = match[1];
|
||||
let appName = match[2];
|
||||
let credentials = await httpd.auth_query(request.headers);
|
||||
if (
|
||||
credentials &&
|
||||
credentials.session &&
|
||||
(credentials.session.name == user ||
|
||||
(credentials.permissions.administration && user == 'core'))
|
||||
) {
|
||||
let database = new Database(user);
|
||||
let apps = new Set();
|
||||
try {
|
||||
apps = new Set(JSON.parse(await database.get('apps')));
|
||||
} catch {}
|
||||
if (apps.delete(appName)) {
|
||||
await database.set('apps', JSON.stringify([...apps].sort()));
|
||||
}
|
||||
database.remove('path:' + appName);
|
||||
} else {
|
||||
response.writeHead(401, {'Content-Type': 'text/plain; charset=utf-8'});
|
||||
response.end('401 Unauthorized');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
response.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
|
||||
response.end('OK');
|
||||
} else {
|
||||
let data;
|
||||
let match;
|
||||
let id;
|
||||
let app_id = blobId;
|
||||
let packageOwner;
|
||||
let packageName;
|
||||
if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) {
|
||||
packageOwner = match[1];
|
||||
packageName = match[2];
|
||||
let db = new Database(match[1]);
|
||||
app_id = await db.get('path:' + match[2]);
|
||||
}
|
||||
|
||||
let app_object = JSON.parse(utf8Decode(await ssb.blobGet(app_id)));
|
||||
id = app_object?.files[uri.substring(1)];
|
||||
if (!id && app_object?.files['handler.js']) {
|
||||
let answer;
|
||||
try {
|
||||
answer = await useAppHandler(
|
||||
response,
|
||||
app_id,
|
||||
uri.substring(1),
|
||||
request.query ? form.decodeForm(request.query) : undefined,
|
||||
request.headers,
|
||||
packageOwner,
|
||||
packageName
|
||||
);
|
||||
} catch (error) {
|
||||
data = utf8Encode(
|
||||
`Internal Server Error\n\n${error?.message}\n${error?.stack}`
|
||||
);
|
||||
response.writeHead(500, {
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
'Content-Length': data.length,
|
||||
});
|
||||
response.end(data);
|
||||
return;
|
||||
}
|
||||
if (answer && typeof answer.data == 'string') {
|
||||
answer.data = utf8Encode(answer.data);
|
||||
}
|
||||
sendData(
|
||||
response,
|
||||
answer?.data,
|
||||
answer?.content_type,
|
||||
Object.assign(answer?.headers ?? {}, {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Security-Policy': k_content_security_policy,
|
||||
}),
|
||||
answer.status_code
|
||||
);
|
||||
} else if (id) {
|
||||
if (
|
||||
request.headers['if-none-match'] &&
|
||||
request.headers['if-none-match'] == '"' + id + '"'
|
||||
) {
|
||||
let headers = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Security-Policy': k_content_security_policy,
|
||||
'Content-Length': '0',
|
||||
};
|
||||
response.writeHead(304, headers);
|
||||
response.end();
|
||||
} else {
|
||||
let headers = {
|
||||
ETag: '"' + id + '"',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Security-Policy': k_content_security_policy,
|
||||
};
|
||||
data = await ssb.blobGet(id);
|
||||
let type =
|
||||
httpd.mime_type_from_extension(uri) ||
|
||||
httpd.mime_type_from_magic_bytes(data);
|
||||
sendData(response, data, type, headers);
|
||||
}
|
||||
} else {
|
||||
sendData(response, data, undefined, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssb.addEventListener('message', function () {
|
||||
broadcastEvent('onMessage', [...arguments]);
|
||||
});
|
||||
@ -755,12 +1195,12 @@ async function loadSettings() {
|
||||
} catch (error) {
|
||||
print('Settings not found in database:', error);
|
||||
}
|
||||
for (let [key, value] of Object.entries(defaultGlobalSettings())) {
|
||||
for (let [key, value] of Object.entries(k_global_settings)) {
|
||||
if (data[key] === undefined) {
|
||||
data[key] = value.default_value;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
gGlobalSettings = data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -781,82 +1221,34 @@ function sendStats() {
|
||||
}
|
||||
}
|
||||
|
||||
let g_handler_index = 0;
|
||||
|
||||
exports.callAppHandler = async function callAppHandler(
|
||||
response,
|
||||
app_blob_id,
|
||||
path,
|
||||
query,
|
||||
headers,
|
||||
package_owner,
|
||||
package_name
|
||||
) {
|
||||
let answer;
|
||||
try {
|
||||
let do_resolve;
|
||||
let promise = new Promise(async function (resolve, reject) {
|
||||
do_resolve = resolve;
|
||||
});
|
||||
let process;
|
||||
try {
|
||||
process = await getProcessBlob(
|
||||
app_blob_id,
|
||||
'handler_' + g_handler_index++,
|
||||
{
|
||||
script: 'handler.js',
|
||||
imports: {
|
||||
request: {
|
||||
path: path,
|
||||
query: query,
|
||||
},
|
||||
respond: do_resolve,
|
||||
},
|
||||
credentials: await httpd.auth_query(headers),
|
||||
packageOwner: package_owner,
|
||||
packageName: package_name,
|
||||
}
|
||||
);
|
||||
await process.ready;
|
||||
answer = await promise;
|
||||
} finally {
|
||||
if (process?.task) {
|
||||
await process.task.kill();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
let data = utf8Encode(
|
||||
`Internal Server Error\n\n${error?.message}\n${error?.stack}`
|
||||
);
|
||||
response.writeHead(500, {
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
'Content-Length': data.length,
|
||||
});
|
||||
response.end(data);
|
||||
return;
|
||||
}
|
||||
if (typeof answer?.data == 'string') {
|
||||
answer.data = utf8Encode(answer.data);
|
||||
}
|
||||
response.writeHead(answer?.status_code, {
|
||||
'Content-Type': answer?.content_type,
|
||||
'Content-Length': answer?.data?.length,
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Security-Policy':
|
||||
'sandbox allow-downloads allow-top-navigation-by-user-activation',
|
||||
});
|
||||
response.end(answer?.data);
|
||||
};
|
||||
|
||||
/**
|
||||
* TODOC
|
||||
*/
|
||||
loadSettings()
|
||||
.then(function (settings) {
|
||||
if (tildefriends.https_port && settings.http_redirect) {
|
||||
httpd.set_http_redirect(settings.http_redirect);
|
||||
.then(function () {
|
||||
if (tildefriends.https_port && gGlobalSettings.http_redirect) {
|
||||
httpd.set_http_redirect(gGlobalSettings.http_redirect);
|
||||
}
|
||||
httpd.all('/app/socket', app.socket);
|
||||
httpd.all('', function default_http_handler(request, response) {
|
||||
let match;
|
||||
if ((match = /^(\/~[^\/]+\/[^\/]+)(\/?.*)$/.exec(request.uri))) {
|
||||
return blobHandler(request, response, match[1], match[2]);
|
||||
} else if (
|
||||
(match = /^\/([&\%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(request.uri))
|
||||
) {
|
||||
return blobHandler(request, response, match[1], match[2]);
|
||||
} else if ((match = /^(.*)(\/(?:save|delete)?)$/.exec(request.uri))) {
|
||||
return blobHandler(request, response, match[1], match[2]);
|
||||
} else {
|
||||
let data = 'File not found.';
|
||||
response.writeHead(404, {
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
'Content-Length': data.length.toString(),
|
||||
});
|
||||
return response.end(data);
|
||||
}
|
||||
});
|
||||
let port = httpd.start(tildefriends.http_port);
|
||||
if (tildefriends.args.out_http_port_file) {
|
||||
print('Writing the port file.');
|
||||
@ -903,4 +1295,48 @@ loadSettings()
|
||||
exit(1);
|
||||
});
|
||||
|
||||
export {invoke, getProcessBlob};
|
||||
/**
|
||||
* TODOC
|
||||
* @param {*} user
|
||||
* @param {*} packageOwner
|
||||
* @param {*} packageName
|
||||
* @param {*} permission
|
||||
* @param {*} allow
|
||||
*/
|
||||
function storePermission(user, packageOwner, packageName, permission, allow) {
|
||||
if (!gGlobalSettings.userPermissions) {
|
||||
gGlobalSettings.userPermissions = {};
|
||||
}
|
||||
if (!gGlobalSettings.userPermissions[user]) {
|
||||
gGlobalSettings.userPermissions[user] = {};
|
||||
}
|
||||
if (!gGlobalSettings.userPermissions[user][packageOwner]) {
|
||||
gGlobalSettings.userPermissions[user][packageOwner] = {};
|
||||
}
|
||||
if (!gGlobalSettings.userPermissions[user][packageOwner][packageName]) {
|
||||
gGlobalSettings.userPermissions[user][packageOwner][packageName] = {};
|
||||
}
|
||||
if (
|
||||
gGlobalSettings.userPermissions[user][packageOwner][packageName][
|
||||
permission
|
||||
] !== allow
|
||||
) {
|
||||
if (allow === undefined) {
|
||||
delete gGlobalSettings.userPermissions[user][packageOwner][packageName][
|
||||
permission
|
||||
];
|
||||
} else {
|
||||
gGlobalSettings.userPermissions[user][packageOwner][packageName][
|
||||
permission
|
||||
] = allow;
|
||||
}
|
||||
setGlobalSettings(gGlobalSettings);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
gGlobalSettings as globalSettings,
|
||||
setGlobalSettings,
|
||||
invoke,
|
||||
getSessionProcessBlob,
|
||||
};
|
||||
|
@ -6,26 +6,6 @@
|
||||
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
||||
<link type="image/svg+xml" rel="icon" href="/static/tildefriends.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta
|
||||
name="title"
|
||||
content="Tilde Friends - Make friends and apps from your web browser."
|
||||
/>
|
||||
<meta
|
||||
name="description"
|
||||
content="Tilde Friends is a Secure Scuttlebutt client and a platform for building, running, and sharing web applications. "
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://metatags.io/" />
|
||||
<meta
|
||||
property="og:title"
|
||||
content="Tilde Friends - Make friends and apps from your web browser."
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Tilde Friends is a Secure Scuttlebutt client and a platform for building, running, and sharing web applications. "
|
||||
/>
|
||||
<meta property="og:image" content="/static/tildefriends.svg" />
|
||||
|
||||
<script>
|
||||
function set_access_key_title(event) {
|
||||
if (!event.srcElement.title) {
|
||||
|
@ -21,14 +21,14 @@
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation rec {
|
||||
pname = "tildefriends";
|
||||
version = "0.0.25";
|
||||
version = "0.0.21";
|
||||
|
||||
src = pkgs.fetchFromGitea {
|
||||
domain = "dev.tildefriends.net";
|
||||
owner = "cory";
|
||||
repo = "tildefriends";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-Rfk+CUhi+Ss0z70CCgmtVM/w4nCL1GX/MsD4sPYIa5s=";
|
||||
hash = "sha256-cBj9Hz0qT0Tqm7ivM8HPG9TNwC9iv0lTcE8XCNba8F4=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
|
2
deps/c-ares
vendored
2
deps/c-ares
vendored
@ -1 +1 @@
|
||||
Subproject commit b82840329a4081a1f1b125e6e6b760d4e1237b52
|
||||
Subproject commit caffa5ffb3826cf0926405793361bbad11db3268
|
13
deps/c-ares_config/ares_build.h
vendored
13
deps/c-ares_config/ares_build.h
vendored
@ -39,9 +39,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
|
||||
|
||||
@ -50,11 +47,13 @@
|
||||
#define GETSERVBYPORT_R_ARGS 4
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__HAIKU__)
|
||||
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__OpenBSD__)
|
||||
#define HAVE_MALLOC_H 1
|
||||
#if !defined(__HAIKU__)
|
||||
#define HAVE_SYS_RANDOM_H 1
|
||||
#define HAVE_EPOLL 1
|
||||
#define HAVE_SYS_EPOLL_H 1
|
||||
#define HAVE_SYS_RANDOM_H 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(__WIN32)
|
||||
@ -139,10 +138,8 @@
|
||||
#define HAVE_IFADDRS_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_WRITEV 1
|
||||
#if defined(__ANDROID__) || defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#if !defined(__HAIKU__)
|
||||
#define HAVE_ARC4RANDOM_BUF 1
|
||||
#else
|
||||
#undef HAVE_ARC4RANDOM_BUF
|
||||
#endif
|
||||
#define HAVE_GETIFADDRS 1
|
||||
#define HAVE_STAT 1
|
||||
|
2
deps/codemirror/cm6.js
vendored
2
deps/codemirror/cm6.js
vendored
File diff suppressed because one or more lines are too long
433
deps/codemirror_src/package-lock.json
generated
vendored
433
deps/codemirror_src/package-lock.json
generated
vendored
@ -19,10 +19,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/autocomplete": {
|
||||
"version": "6.18.3",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.3.tgz",
|
||||
"integrity": "sha512-1dNIOmiM0z4BIBwxmxEfA1yoxh1MF/6KPBbh20a5vphGV0ictKlgQsbJs6D6SkR6iJpGbpwRsa6PFMNlg9T9pQ==",
|
||||
"license": "MIT",
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.0.tgz",
|
||||
"integrity": "sha512-5DbOvBbY4qW5l57cjDsmmpDh3/TeK1vXfTHa+BUMrRzdWdcxKZ4U4V7vQaTtOpApNU4kLS4FQ6cINtLg245LXA==",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
@ -37,10 +36,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/commands": {
|
||||
"version": "6.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.7.1.tgz",
|
||||
"integrity": "sha512-llTrboQYw5H4THfhN4U3qCnSZ1SOJ60ohhz+SzU0ADGtwlc533DtklQP0vSFaQuCPDn3BPpOd1GbbnUtwNjsrw==",
|
||||
"license": "MIT",
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz",
|
||||
"integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
@ -49,23 +47,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-css": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz",
|
||||
"integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==",
|
||||
"license": "MIT",
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz",
|
||||
"integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.0.2",
|
||||
"@lezer/css": "^1.1.7"
|
||||
"@lezer/css": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-html": {
|
||||
"version": "6.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz",
|
||||
"integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/lang-css": "^6.0.0",
|
||||
@ -82,7 +78,6 @@
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
|
||||
"integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
@ -97,17 +92,15 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
|
||||
"integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/json": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/language": {
|
||||
"version": "6.10.6",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.6.tgz",
|
||||
"integrity": "sha512-KrsbdCnxEztLVbB5PycWXFxas4EOyk/fPAfruSOnDDppevQgid2XZ+KbJ9u+fDikP/e7MW7HPBTvTb8JlZK9vA==",
|
||||
"license": "MIT",
|
||||
"version": "6.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz",
|
||||
"integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.23.0",
|
||||
@ -118,21 +111,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lint": {
|
||||
"version": "6.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.4.tgz",
|
||||
"integrity": "sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==",
|
||||
"license": "MIT",
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.1.tgz",
|
||||
"integrity": "sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.35.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/search": {
|
||||
"version": "6.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz",
|
||||
"integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==",
|
||||
"license": "MIT",
|
||||
"version": "6.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz",
|
||||
"integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
@ -140,19 +131,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.0.tgz",
|
||||
"integrity": "sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@marijn/find-cluster-break": "^1.0.0"
|
||||
}
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
|
||||
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
|
||||
},
|
||||
"node_modules/@codemirror/theme-one-dark": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
|
||||
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
@ -161,12 +147,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.35.3",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.35.3.tgz",
|
||||
"integrity": "sha512-ScY7L8+EGdPl4QtoBiOzE4FELp7JmNUsBvgBcCakXWM2uiv/K89VAzU3BMDscf0DsACLvTKePbd5+cFDTcei6g==",
|
||||
"license": "MIT",
|
||||
"version": "6.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.30.0.tgz",
|
||||
"integrity": "sha512-96Nmn8OeLh6aONQprIeYk8hGVnEuYpWuxKSkdsODOx9hWPxyuyZGvmvxV/JmLsp+CubMO1PsLaN5TNNgrl0UrQ==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.5.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"style-mod": "^4.1.0",
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
@ -176,7 +161,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
@ -191,7 +175,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -201,7 +184,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -211,7 +193,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25"
|
||||
@ -221,31 +202,27 @@
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==",
|
||||
"license": "MIT"
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz",
|
||||
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ=="
|
||||
},
|
||||
"node_modules/@lezer/css": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.9.tgz",
|
||||
"integrity": "sha512-TYwgljcDv+YrV0MZFFvYFQHCfGgbPMR6nuqLabBdmZoFH3EP1gvw8t0vae326Ne3PszQkbXfVBjCnf3ZVCr0bA==",
|
||||
"license": "MIT",
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz",
|
||||
"integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@ -253,10 +230,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/highlight": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
|
||||
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
|
||||
"license": "MIT",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz",
|
||||
"integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
@ -265,7 +241,6 @@
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz",
|
||||
"integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@ -273,10 +248,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/javascript": {
|
||||
"version": "1.4.21",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.21.tgz",
|
||||
"integrity": "sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==",
|
||||
"license": "MIT",
|
||||
"version": "1.4.17",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.17.tgz",
|
||||
"integrity": "sha512-bYW4ctpyGK+JMumDApeUzuIezX01H76R1foD6LcRX224FWfyYit/HYxiPGDjXXe/wQWASjCvVGoukTH68+0HIA==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.1.3",
|
||||
@ -287,7 +261,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.2.tgz",
|
||||
"integrity": "sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@ -298,26 +271,19 @@
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
|
||||
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@marijn/find-cluster-break": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
|
||||
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rollup/plugin-node-resolve": {
|
||||
"version": "15.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz",
|
||||
"integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==",
|
||||
"license": "MIT",
|
||||
"version": "15.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz",
|
||||
"integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==",
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1",
|
||||
"@types/resolve": "1.20.2",
|
||||
"deepmerge": "^4.2.2",
|
||||
"is-builtin-module": "^3.2.1",
|
||||
"is-module": "^1.0.0",
|
||||
"resolve": "^1.22.1"
|
||||
},
|
||||
@ -338,7 +304,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
|
||||
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"serialize-javascript": "^6.0.1",
|
||||
"smob": "^1.0.0",
|
||||
@ -357,14 +322,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz",
|
||||
"integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==",
|
||||
"license": "MIT",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
|
||||
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"picomatch": "^4.0.2"
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
@ -379,270 +343,212 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz",
|
||||
"integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.20.0.tgz",
|
||||
"integrity": "sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz",
|
||||
"integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.20.0.tgz",
|
||||
"integrity": "sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz",
|
||||
"integrity": "sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.20.0.tgz",
|
||||
"integrity": "sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz",
|
||||
"integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.20.0.tgz",
|
||||
"integrity": "sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz",
|
||||
"integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz",
|
||||
"integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz",
|
||||
"integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.20.0.tgz",
|
||||
"integrity": "sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz",
|
||||
"integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.20.0.tgz",
|
||||
"integrity": "sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz",
|
||||
"integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.20.0.tgz",
|
||||
"integrity": "sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz",
|
||||
"integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.20.0.tgz",
|
||||
"integrity": "sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz",
|
||||
"integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz",
|
||||
"integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.20.0.tgz",
|
||||
"integrity": "sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz",
|
||||
"integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.20.0.tgz",
|
||||
"integrity": "sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz",
|
||||
"integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.20.0.tgz",
|
||||
"integrity": "sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz",
|
||||
"integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz",
|
||||
"integrity": "sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz",
|
||||
"integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.20.0.tgz",
|
||||
"integrity": "sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz",
|
||||
"integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.20.0.tgz",
|
||||
"integrity": "sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz",
|
||||
"integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.20.0.tgz",
|
||||
"integrity": "sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz",
|
||||
"integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.20.0.tgz",
|
||||
"integrity": "sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||
"license": "MIT"
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||
"version": "8.12.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@ -654,14 +560,23 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"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": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
|
||||
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/commands": "^6.0.0",
|
||||
@ -676,20 +591,17 @@
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -697,15 +609,13 @@
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
@ -718,7 +628,6 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
@ -727,7 +636,6 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
@ -735,11 +643,24 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/is-builtin-module": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
|
||||
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
|
||||
"dependencies": {
|
||||
"builtin-modules": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
|
||||
"integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
|
||||
"license": "MIT",
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz",
|
||||
"integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==",
|
||||
"dependencies": {
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
@ -753,22 +674,19 @@
|
||||
"node_modules/is-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"license": "MIT",
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
@ -779,7 +697,6 @@
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
@ -788,7 +705,6 @@
|
||||
"version": "1.22.8",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
||||
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.13.0",
|
||||
"path-parse": "^1.0.7",
|
||||
@ -802,12 +718,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.28.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.1.tgz",
|
||||
"integrity": "sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==",
|
||||
"license": "MIT",
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.20.0.tgz",
|
||||
"integrity": "sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.6"
|
||||
"@types/estree": "1.0.5"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
@ -817,25 +732,22 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.28.1",
|
||||
"@rollup/rollup-android-arm64": "4.28.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.28.1",
|
||||
"@rollup/rollup-darwin-x64": "4.28.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.28.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.28.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.28.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.28.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.28.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.28.1",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.28.1",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.28.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.28.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.28.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.28.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.28.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.28.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.28.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.28.1",
|
||||
"@rollup/rollup-android-arm-eabi": "4.20.0",
|
||||
"@rollup/rollup-android-arm64": "4.20.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.20.0",
|
||||
"@rollup/rollup-darwin-x64": "4.20.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.20.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.20.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.20.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.20.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.20.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.20.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.20.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.20.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.20.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.20.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.20.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.20.0",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
@ -857,15 +769,13 @@
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
]
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
@ -874,15 +784,13 @@
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
|
||||
"integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -892,7 +800,6 @@
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
@ -901,14 +808,12 @@
|
||||
"node_modules/style-mod": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
|
||||
},
|
||||
"node_modules/supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@ -917,11 +822,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.37.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
|
||||
"integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
|
||||
"version": "5.31.3",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz",
|
||||
"integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
@ -938,8 +842,7 @@
|
||||
"node_modules/w3c-keyname": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
deps/libbacktrace
vendored
2
deps/libbacktrace
vendored
@ -1 +1 @@
|
||||
Subproject commit d48f84034ce3e53e501d10593710d025cb1121db
|
||||
Subproject commit 86885d14049fab06ef8a33aac51664230ca09200
|
2
deps/libuv
vendored
2
deps/libuv
vendored
@ -1 +1 @@
|
||||
Subproject commit e1095c7a4373ce00cd8874d8e820de5afb25776e
|
||||
Subproject commit e9f29cb984231524e3931aa0ae2c5dae1a32884e
|
44
deps/lit/lit-all.min.js
vendored
44
deps/lit/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
2
deps/lit/lit-all.min.js.map
vendored
2
deps/lit/lit-all.min.js.map
vendored
File diff suppressed because one or more lines are too long
2
deps/openssl_src
vendored
2
deps/openssl_src
vendored
@ -1 +1 @@
|
||||
Subproject commit 98acb6b02839c609ef5b837794e08d906d965335
|
||||
Subproject commit db2ac4f6ebd8f3d7b2a60882992fbea1269114e2
|
23
deps/prettier/babel.mjs
vendored
23
deps/prettier/babel.mjs
vendored
File diff suppressed because one or more lines are too long
56
deps/prettier/estree.mjs
vendored
56
deps/prettier/estree.mjs
vendored
File diff suppressed because one or more lines are too long
33
deps/prettier/html.mjs
vendored
33
deps/prettier/html.mjs
vendored
File diff suppressed because one or more lines are too long
65
deps/prettier/standalone.mjs
vendored
65
deps/prettier/standalone.mjs
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
2
deps/speedscope/index.html
vendored
2
deps/speedscope/index.html
vendored
@ -1,2 +1,2 @@
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>speedscope</title><link href="source-code-pro.52b1676f.css" rel="stylesheet"><script></script><link rel="stylesheet" href="reset.8c46b7a1.css"><link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.bc503437.png"><link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.f74b3187.png"></head><body> <script src="speedscope.6f107512.js"></script>
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>speedscope</title><link href="https://fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet"><script></script><link rel="stylesheet" href="reset.8c46b7a1.css"><link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.bc503437.png"><link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.f74b3187.png"></head><body> <script src="speedscope.80eb88d2.js"></script>
|
||||
</body></html>
|
6
deps/speedscope/release.txt
vendored
6
deps/speedscope/release.txt
vendored
@ -1,3 +1,3 @@
|
||||
speedscope@1.21.0
|
||||
Sat Nov 16 22:13:27 PST 2024
|
||||
d36c3a54424063a8df7bc67a7b824a223d73861b
|
||||
speedscope@1.20.0
|
||||
Fri Jan 12 09:57:49 PST 2024
|
||||
68fd88ceaf93d89aa27f3f0a20a27c9cfdc015c5
|
||||
|
2
deps/speedscope/source-code-pro.52b1676f.css
vendored
2
deps/speedscope/source-code-pro.52b1676f.css
vendored
@ -1,2 +0,0 @@
|
||||
@font-face{font-family:Source Code Pro;font-weight:400;font-style:normal;font-stretch:normal;src:url(SourceCodePro-Regular.ttf.f546cbe0.woff2) format("woff2")}
|
||||
/*# sourceMappingURL=source-code-pro.52b1676f.css.map */
|
93
deps/speedscope/source-code-pro.LICENSE.md
vendored
93
deps/speedscope/source-code-pro.LICENSE.md
vendored
@ -1,93 +0,0 @@
|
||||
Copyright 2010-2019 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
File diff suppressed because one or more lines are too long
6049
deps/sqlite/shell.c
vendored
6049
deps/sqlite/shell.c
vendored
File diff suppressed because it is too large
Load Diff
8580
deps/sqlite/sqlite3.c
vendored
8580
deps/sqlite/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
202
deps/sqlite/sqlite3.h
vendored
202
deps/sqlite/sqlite3.h
vendored
@ -146,9 +146,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.47.2"
|
||||
#define SQLITE_VERSION_NUMBER 3047002
|
||||
#define SQLITE_SOURCE_ID "2024-12-07 20:39:59 2aabe05e2e8cae4847a802ee2daddc1d7413d8fc560254d93ee3e72c14685b6c"
|
||||
#define SQLITE_VERSION "3.46.0"
|
||||
#define SQLITE_VERSION_NUMBER 3046000
|
||||
#define SQLITE_SOURCE_ID "2024-05-23 13:25:27 96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -652,13 +652,6 @@ SQLITE_API int sqlite3_exec(
|
||||
** filesystem supports doing multiple write operations atomically when those
|
||||
** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
|
||||
** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
|
||||
**
|
||||
** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read
|
||||
** from the database file in amounts that are not a multiple of the
|
||||
** page size and that do not begin at a page boundary. Without this
|
||||
** property, SQLite is careful to only do full-page reads and write
|
||||
** on aligned pages, with the one exception that it will do a sub-page
|
||||
** read of the first page to access the database header.
|
||||
*/
|
||||
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
||||
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
||||
@ -675,7 +668,6 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
|
||||
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
|
||||
#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
|
||||
#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000
|
||||
|
||||
/*
|
||||
** CAPI3REF: File Locking Levels
|
||||
@ -780,8 +772,8 @@ struct sqlite3_file {
|
||||
** to xUnlock() is a no-op.
|
||||
** The xCheckReservedLock() method checks whether any database connection,
|
||||
** either in this process or in some other process, is holding a RESERVED,
|
||||
** PENDING, or EXCLUSIVE lock on the file. It returns, via its output
|
||||
** pointer parameter, true if such a lock exists and false otherwise.
|
||||
** PENDING, or EXCLUSIVE lock on the file. It returns true
|
||||
** if such a lock exists and false otherwise.
|
||||
**
|
||||
** The xFileControl() method is a generic interface that allows custom
|
||||
** VFS implementations to directly control an open file using the
|
||||
@ -822,7 +814,6 @@ struct sqlite3_file {
|
||||
** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
|
||||
** <li> [SQLITE_IOCAP_IMMUTABLE]
|
||||
** <li> [SQLITE_IOCAP_BATCH_ATOMIC]
|
||||
** <li> [SQLITE_IOCAP_SUBPAGE_READ]
|
||||
** </ul>
|
||||
**
|
||||
** The SQLITE_IOCAP_ATOMIC property means that all writes of
|
||||
@ -3579,8 +3570,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
**
|
||||
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
|
||||
** <dd>The database connection comes up in "extended result code mode".
|
||||
** In other words, the database behaves as if
|
||||
** [sqlite3_extended_result_codes(db,1)] were called on the database
|
||||
** In other words, the database behaves has if
|
||||
** [sqlite3_extended_result_codes(db,1)] where called on the database
|
||||
** connection as soon as the connection is created. In addition to setting
|
||||
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
|
||||
** to return an extended result code.</dd>
|
||||
@ -4231,17 +4222,13 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** and sqlite3_prepare16_v3() use UTF-16.
|
||||
**
|
||||
** ^If the nByte argument is negative, then zSql is read up to the
|
||||
** first zero terminator. ^If nByte is positive, then it is the maximum
|
||||
** number of bytes read from zSql. When nByte is positive, zSql is read
|
||||
** up to the first zero terminator or until the nByte bytes have been read,
|
||||
** whichever comes first. ^If nByte is zero, then no prepared
|
||||
** first zero terminator. ^If nByte is positive, then it is the
|
||||
** number of bytes read from zSql. ^If nByte is zero, then no prepared
|
||||
** statement is generated.
|
||||
** If the caller knows that the supplied string is nul-terminated, then
|
||||
** there is a small performance advantage to passing an nByte parameter that
|
||||
** is the number of bytes in the input string <i>including</i>
|
||||
** the nul-terminator.
|
||||
** Note that nByte measure the length of the input in bytes, not
|
||||
** characters, even for the UTF-16 interfaces.
|
||||
**
|
||||
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
|
||||
** past the end of the first SQL statement in zSql. These routines only
|
||||
@ -5612,7 +5599,7 @@ SQLITE_API int sqlite3_create_window_function(
|
||||
** This flag instructs SQLite to omit some corner-case optimizations that
|
||||
** might disrupt the operation of the [sqlite3_value_subtype()] function,
|
||||
** causing it to return zero rather than the correct subtype().
|
||||
** All SQL functions that invoke [sqlite3_value_subtype()] should have this
|
||||
** SQL functions that invokes [sqlite3_value_subtype()] should have this
|
||||
** property. If the SQLITE_SUBTYPE property is omitted, then the return
|
||||
** value from [sqlite3_value_subtype()] might sometimes be zero even though
|
||||
** a non-zero subtype was specified by the function argument expression.
|
||||
@ -5628,15 +5615,6 @@ SQLITE_API int sqlite3_create_window_function(
|
||||
** [sqlite3_result_subtype()] should avoid setting this property, as the
|
||||
** purpose of this property is to disable certain optimizations that are
|
||||
** incompatible with subtypes.
|
||||
**
|
||||
** [[SQLITE_SELFORDER1]] <dt>SQLITE_SELFORDER1</dt><dd>
|
||||
** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
|
||||
** that internally orders the values provided to the first argument. The
|
||||
** ordered-set aggregate SQL notation with a single ORDER BY term can be
|
||||
** used to invoke this function. If the ordered-set aggregate notation is
|
||||
** used on a function that lacks this flag, then an error is raised. Note
|
||||
** that the ordered-set aggregate syntax is only available if SQLite is
|
||||
** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
@ -5645,7 +5623,6 @@ SQLITE_API int sqlite3_create_window_function(
|
||||
#define SQLITE_SUBTYPE 0x000100000
|
||||
#define SQLITE_INNOCUOUS 0x000200000
|
||||
#define SQLITE_RESULT_SUBTYPE 0x001000000
|
||||
#define SQLITE_SELFORDER1 0x002000000
|
||||
|
||||
/*
|
||||
** CAPI3REF: Deprecated Functions
|
||||
@ -5843,7 +5820,7 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*);
|
||||
** one SQL function to another. Use the [sqlite3_result_subtype()]
|
||||
** routine to set the subtype for the return value of an SQL function.
|
||||
**
|
||||
** Every [application-defined SQL function] that invokes this interface
|
||||
** Every [application-defined SQL function] that invoke this interface
|
||||
** should include the [SQLITE_SUBTYPE] property in the text
|
||||
** encoding argument when the function is [sqlite3_create_function|registered].
|
||||
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
|
||||
@ -7450,11 +7427,9 @@ struct sqlite3_module {
|
||||
** will be returned by the strategy.
|
||||
**
|
||||
** The xBestIndex method may optionally populate the idxFlags field with a
|
||||
** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
|
||||
** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
|
||||
** output to show the idxNum has hex instead of as decimal. Another flag is
|
||||
** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
|
||||
** return at most one row.
|
||||
** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
|
||||
** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
|
||||
** assumes that the strategy may visit at most one row.
|
||||
**
|
||||
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
|
||||
** SQLite also assumes that if a call to the xUpdate() method is made as
|
||||
@ -7518,9 +7493,7 @@ struct sqlite3_index_info {
|
||||
** [sqlite3_index_info].idxFlags field to some combination of
|
||||
** these bits.
|
||||
*/
|
||||
#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */
|
||||
#define SQLITE_INDEX_SCAN_HEX 0x00000002 /* Display idxNum as hex */
|
||||
/* in EXPLAIN QUERY PLAN */
|
||||
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Constraint Operator Codes
|
||||
@ -8357,7 +8330,6 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_JSON_SELFCHECK 14
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_GETOPT 16
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
|
||||
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
|
||||
@ -8377,7 +8349,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
||||
#define SQLITE_TESTCTRL_TUNE 32
|
||||
#define SQLITE_TESTCTRL_LOGEST 33
|
||||
#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_USELONGDOUBLE 34
|
||||
#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
@ -9353,16 +9325,6 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
** APIs are not strictly speaking threadsafe. If they are invoked at the
|
||||
** same time as another thread is invoking sqlite3_backup_step() it is
|
||||
** possible that they return invalid values.
|
||||
**
|
||||
** <b>Alternatives To Using The Backup API</b>
|
||||
**
|
||||
** Other techniques for safely creating a consistent backup of an SQLite
|
||||
** database include:
|
||||
**
|
||||
** <ul>
|
||||
** <li> The [VACUUM INTO] command.
|
||||
** <li> The [sqlite3_rsync] utility program.
|
||||
** </ul>
|
||||
*/
|
||||
SQLITE_API sqlite3_backup *sqlite3_backup_init(
|
||||
sqlite3 *pDest, /* Destination database handle */
|
||||
@ -10562,14 +10524,6 @@ typedef struct sqlite3_snapshot {
|
||||
** If there is not already a read-transaction open on schema S when
|
||||
** this function is called, one is opened automatically.
|
||||
**
|
||||
** If a read-transaction is opened by this function, then it is guaranteed
|
||||
** that the returned snapshot object may not be invalidated by a database
|
||||
** writer or checkpointer until after the read-transaction is closed. This
|
||||
** is not guaranteed if a read-transaction is already open when this
|
||||
** function is called. In that case, any subsequent write or checkpoint
|
||||
** operation on the database may invalidate the returned snapshot handle,
|
||||
** even while the read-transaction remains open.
|
||||
**
|
||||
** The following must be true for this function to succeed. If any of
|
||||
** the following statements are false when sqlite3_snapshot_get() is
|
||||
** called, SQLITE_ERROR is returned. The final value of *P is undefined
|
||||
@ -10878,6 +10832,8 @@ SQLITE_API int sqlite3_deserialize(
|
||||
#if defined(__wasi__)
|
||||
# undef SQLITE_WASI
|
||||
# define SQLITE_WASI 1
|
||||
# undef SQLITE_OMIT_WAL
|
||||
# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
|
||||
# ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
# define SQLITE_OMIT_LOAD_EXTENSION
|
||||
# endif
|
||||
@ -13080,10 +13036,6 @@ struct Fts5PhraseIter {
|
||||
** (i.e. if it is a contentless table), then this API always iterates
|
||||
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
|
||||
**
|
||||
** In all cases, matches are visited in (column ASC, offset ASC) order.
|
||||
** i.e. all those in column 0, sorted by offset, followed by those in
|
||||
** column 1, etc.
|
||||
**
|
||||
** xPhraseNext()
|
||||
** See xPhraseFirst above.
|
||||
**
|
||||
@ -13150,32 +13102,9 @@ struct Fts5PhraseIter {
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option.
|
||||
**
|
||||
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
|
||||
** If parameter iCol is less than zero, or greater than or equal to the
|
||||
** number of columns in the table, SQLITE_RANGE is returned.
|
||||
**
|
||||
** Otherwise, this function attempts to retrieve the locale associated
|
||||
** with column iCol of the current row. Usually, there is no associated
|
||||
** locale, and output parameters (*pzLocale) and (*pnLocale) are set
|
||||
** to NULL and 0, respectively. However, if the fts5_locale() function
|
||||
** was used to associate a locale with the value when it was inserted
|
||||
** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
|
||||
** buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
|
||||
** is set to the size in bytes of the buffer, not including the
|
||||
** nul-terminator.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned. Or, if an error occurs, an
|
||||
** SQLite error code is returned. The final value of the output parameters
|
||||
** is undefined in this case.
|
||||
**
|
||||
** xTokenize_v2:
|
||||
** Tokenize text using the tokenizer belonging to the FTS5 table. This
|
||||
** API is the same as the xTokenize() API, except that it allows a tokenizer
|
||||
** locale to be specified.
|
||||
*/
|
||||
struct Fts5ExtensionApi {
|
||||
int iVersion; /* Currently always set to 4 */
|
||||
int iVersion; /* Currently always set to 3 */
|
||||
|
||||
void *(*xUserData)(Fts5Context*);
|
||||
|
||||
@ -13217,15 +13146,6 @@ struct Fts5ExtensionApi {
|
||||
const char **ppToken, int *pnToken
|
||||
);
|
||||
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
|
||||
|
||||
/* Below this point are iVersion>=4 only */
|
||||
int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
|
||||
int (*xTokenize_v2)(Fts5Context*,
|
||||
const char *pText, int nText, /* Text to tokenize */
|
||||
const char *pLocale, int nLocale, /* Locale to pass to tokenizer */
|
||||
void *pCtx, /* Context passed to xToken() */
|
||||
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -13246,7 +13166,7 @@ struct Fts5ExtensionApi {
|
||||
** A tokenizer instance is required to actually tokenize text.
|
||||
**
|
||||
** The first argument passed to this function is a copy of the (void*)
|
||||
** pointer provided by the application when the fts5_tokenizer_v2 object
|
||||
** pointer provided by the application when the fts5_tokenizer object
|
||||
** was registered with FTS5 (the third argument to xCreateTokenizer()).
|
||||
** The second and third arguments are an array of nul-terminated strings
|
||||
** containing the tokenizer arguments, if any, specified following the
|
||||
@ -13270,7 +13190,7 @@ struct Fts5ExtensionApi {
|
||||
** argument passed to this function is a pointer to an Fts5Tokenizer object
|
||||
** returned by an earlier call to xCreate().
|
||||
**
|
||||
** The third argument indicates the reason that FTS5 is requesting
|
||||
** The second argument indicates the reason that FTS5 is requesting
|
||||
** tokenization of the supplied text. This is always one of the following
|
||||
** four values:
|
||||
**
|
||||
@ -13294,13 +13214,6 @@ struct Fts5ExtensionApi {
|
||||
** on a columnsize=0 database.
|
||||
** </ul>
|
||||
**
|
||||
** The sixth and seventh arguments passed to xTokenize() - pLocale and
|
||||
** nLocale - are a pointer to a buffer containing the locale to use for
|
||||
** tokenization (e.g. "en_US") and its size in bytes, respectively. The
|
||||
** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
|
||||
** which case nLocale is always 0) to indicate that the tokenizer should
|
||||
** use its default locale.
|
||||
**
|
||||
** For each token in the input string, the supplied callback xToken() must
|
||||
** be invoked. The first argument to it should be a copy of the pointer
|
||||
** passed as the second argument to xTokenize(). The third and fourth
|
||||
@ -13324,30 +13237,6 @@ struct Fts5ExtensionApi {
|
||||
** may abandon the tokenization and return any error code other than
|
||||
** SQLITE_OK or SQLITE_DONE.
|
||||
**
|
||||
** If the tokenizer is registered using an fts5_tokenizer_v2 object,
|
||||
** then the xTokenize() method has two additional arguments - pLocale
|
||||
** and nLocale. These specify the locale that the tokenizer should use
|
||||
** for the current request. If pLocale and nLocale are both 0, then the
|
||||
** tokenizer should use its default locale. Otherwise, pLocale points to
|
||||
** an nLocale byte buffer containing the name of the locale to use as utf-8
|
||||
** text. pLocale is not nul-terminated.
|
||||
**
|
||||
** FTS5_TOKENIZER
|
||||
**
|
||||
** There is also an fts5_tokenizer object. This is an older, deprecated,
|
||||
** version of fts5_tokenizer_v2. It is similar except that:
|
||||
**
|
||||
** <ul>
|
||||
** <li> There is no "iVersion" field, and
|
||||
** <li> The xTokenize() method does not take a locale argument.
|
||||
** </ul>
|
||||
**
|
||||
** Legacy fts5_tokenizer tokenizers must be registered using the
|
||||
** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
|
||||
**
|
||||
** Tokenizer implementations registered using either API may be retrieved
|
||||
** using both xFindTokenizer() and xFindTokenizer_v2().
|
||||
**
|
||||
** SYNONYM SUPPORT
|
||||
**
|
||||
** Custom tokenizers may also support synonyms. Consider a case in which a
|
||||
@ -13456,33 +13345,6 @@ struct Fts5ExtensionApi {
|
||||
** inefficient.
|
||||
*/
|
||||
typedef struct Fts5Tokenizer Fts5Tokenizer;
|
||||
typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
|
||||
struct fts5_tokenizer_v2 {
|
||||
int iVersion; /* Currently always 2 */
|
||||
|
||||
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
|
||||
void (*xDelete)(Fts5Tokenizer*);
|
||||
int (*xTokenize)(Fts5Tokenizer*,
|
||||
void *pCtx,
|
||||
int flags, /* Mask of FTS5_TOKENIZE_* flags */
|
||||
const char *pText, int nText,
|
||||
const char *pLocale, int nLocale,
|
||||
int (*xToken)(
|
||||
void *pCtx, /* Copy of 2nd argument to xTokenize() */
|
||||
int tflags, /* Mask of FTS5_TOKEN_* flags */
|
||||
const char *pToken, /* Pointer to buffer containing token */
|
||||
int nToken, /* Size of token in bytes */
|
||||
int iStart, /* Byte offset of token within input text */
|
||||
int iEnd /* Byte offset of end of token within input text */
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
** New code should use the fts5_tokenizer_v2 type to define tokenizer
|
||||
** implementations. The following type is included for legacy applications
|
||||
** that still use it.
|
||||
*/
|
||||
typedef struct fts5_tokenizer fts5_tokenizer;
|
||||
struct fts5_tokenizer {
|
||||
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
|
||||
@ -13502,7 +13364,6 @@ struct fts5_tokenizer {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/* Flags that may be passed as the third argument to xTokenize() */
|
||||
#define FTS5_TOKENIZE_QUERY 0x0001
|
||||
#define FTS5_TOKENIZE_PREFIX 0x0002
|
||||
@ -13522,7 +13383,7 @@ struct fts5_tokenizer {
|
||||
*/
|
||||
typedef struct fts5_api fts5_api;
|
||||
struct fts5_api {
|
||||
int iVersion; /* Currently always set to 3 */
|
||||
int iVersion; /* Currently always set to 2 */
|
||||
|
||||
/* Create a new tokenizer */
|
||||
int (*xCreateTokenizer)(
|
||||
@ -13549,25 +13410,6 @@ struct fts5_api {
|
||||
fts5_extension_function xFunction,
|
||||
void (*xDestroy)(void*)
|
||||
);
|
||||
|
||||
/* APIs below this point are only available if iVersion>=3 */
|
||||
|
||||
/* Create a new tokenizer */
|
||||
int (*xCreateTokenizer_v2)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void *pUserData,
|
||||
fts5_tokenizer_v2 *pTokenizer,
|
||||
void (*xDestroy)(void*)
|
||||
);
|
||||
|
||||
/* Find an existing tokenizer */
|
||||
int (*xFindTokenizer_v2)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void **ppUserData,
|
||||
fts5_tokenizer_v2 **ppTokenizer
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user