37 Commits

Author SHA1 Message Date
697e2f2071 build: Nope, I don't understand nix.
Some checks failed
Build Tilde Friends / Build-All (push) Failing after 1m40s
2025-01-29 20:53:09 -05:00
f7fb112f21 build: I don't understand this nix error.
Some checks are pending
Build Tilde Friends / Build-All (push) Waiting to run
2025-01-29 20:32:35 -05:00
b2c0211190 build: nix?
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-29 20:28:26 -05:00
c59e0ea6e5 build: Let's release 0.0.27.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-29 19:58:31 -05:00
6c2fc1444d ssb: Fix some SQL syntax for private messages. They need more work.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 21m16s
2025-01-29 12:15:46 -05:00
94d969fe46 update: CodeMirror.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 21m19s
2025-01-28 22:23:52 -05:00
a7bc3d301c cleanup: format.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 21m16s
2025-01-28 22:00:48 -05:00
18bab849f7 ssb: prettier.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 20m17s
2025-01-27 21:02:15 -05:00
04878fcc30 ssb: Fix multiple bugs with follow status lying.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 20m10s
2025-01-27 20:28:44 -05:00
ffe1299548 ssb: More room for activities in the emoji picker dialog.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 20m27s
2025-01-27 12:45:54 -05:00
64bdbf5725 build: Never mind. flatpak tools don't want to work in docker.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 20m59s
2025-01-27 12:11:41 -05:00
b82deb557f build: https://github.com/flatpak/flatpak-builder/issues/237 ??
Some checks failed
Build Tilde Friends / Build-All (push) Failing after 24m37s
2025-01-26 21:43:18 -05:00
d529a48a11 build: flatpak maybe?
Some checks failed
Build Tilde Friends / Build-All (push) Failing after 24m34s
2025-01-26 21:14:55 -05:00
b711e4e6bd build: Can the CI worker build the flatpak? Let's find out.
Some checks failed
Build Tilde Friends / Build-All (push) Failing after 22m25s
2025-01-26 20:47:44 -05:00
186eecfbff build: I don't know why this works better, but it does.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-26 20:43:02 -05:00
d766c33f59 build: Stop using lto. Not worth the hassle.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 22m13s
2025-01-26 09:56:53 -05:00
2c9257f1a8 build: Trying to understand a build thing.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-26 09:33:45 -05:00
71ff604f90 ssb: Stop breaking up the news queries into chunks. It sometimes produced incorrect results, and it is not necessary if we're fast enough.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 20m50s
2025-01-25 20:13:05 -05:00
83e00763ea ssb: Be a bit more aggressive about loading latest messages. It bugs me when I don't see my own reactions in a channel or whatnot, and I think it has to do with the queried time ranges.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 21m2s
2025-01-25 18:00:06 -05:00
5b647e0937 buttfeed: Use markdown that works better in Manyverse.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 22m36s
2025-01-25 08:08:02 -05:00
e0444510f4 trace: Use our own sequential thread ids to be more compatible with different trace viewers.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 22m14s
2025-01-24 19:00:40 -05:00
82e876a892 ssb: Only re-populate the messages_stats table on first creation.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 21m38s
2025-01-24 18:06:31 -05:00
c728e05032 ssb: Add a lookup table of max sequence and timestamp per account.f
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 20m47s
2025-01-22 19:19:50 -05:00
c7a8ce7060 apps: display: grid.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-22 19:13:15 -05:00
762b4339fe ssb: Better 'Load More', too.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 20m53s
2025-01-22 18:28:55 -05:00
f824b8988e ssb: Correctness around tunnel.endpoints.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-22 18:03:05 -05:00
6280d6d167 apps: Mobile CSS tweaks.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 22m12s
2025-01-21 21:46:48 -05:00
4f18e744b4 ssb: Unbreak the channel query.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-21 21:31:16 -05:00
01d8f720e8 ssb: Treat timestamps of related messages separately from those of the primary queried messages.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 21m49s
2025-01-21 21:07:37 -05:00
18cf058af3 ssb: Experimenting with the news query strategy.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-21 20:53:23 -05:00
e2406df367 apps: Messing with CSS.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 21m3s
2025-01-20 20:45:35 -05:00
1fd669bdb3 update: npm.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-20 20:25:31 -05:00
f6add12c80 build: Update the change notes.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 22m43s
2025-01-20 17:57:15 -05:00
0f643bfe39 ssb: Complete using an invite, following the pub and posting a pub message. #99
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-20 17:47:30 -05:00
15be498e4b ssb: Don't show connections in various states of disconnectedness in the sidebar.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 22m24s
2025-01-20 16:57:22 -05:00
fba465dd62 ssb: Allow a concurrent connection if the other one is a connection in the process of closing.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-20 16:49:21 -05:00
19dbe354e7 core: Consolidate default global setting values in one place.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-01-20 14:23:41 -05:00
29 changed files with 833 additions and 484 deletions

View File

@ -17,7 +17,7 @@ MAKEFLAGS += --no-builtin-rules
## ANDROID_SDK := Path to the Android SDK. ## ANDROID_SDK := Path to the Android SDK.
VERSION_CODE := 32 VERSION_CODE := 32
VERSION_NUMBER := 0.0.27-wip VERSION_NUMBER := 0.0.27
VERSION_NAME := This program kills fascists. VERSION_NAME := This program kills fascists.
SQLITE_URL := https://www.sqlite.org/2025/sqlite-amalgamation-3480000.zip SQLITE_URL := https://www.sqlite.org/2025/sqlite-amalgamation-3480000.zip
@ -83,8 +83,7 @@ CFLAGS += \
-g -g
LDFLAGS += \ LDFLAGS += \
-Wno-attributes \ -Wno-attributes \
-Wno-aggressive-loop-optimizations \ -Wno-aggressive-loop-optimizations
-flto=auto
ANDROID_MIN_SDK_VERSION := 24 ANDROID_MIN_SDK_VERSION := 24
ANDROID_TARGET_SDK_VERSION := 34 ANDROID_TARGET_SDK_VERSION := 34
@ -211,8 +210,7 @@ $(ANDROID_TARGETS): LDFLAGS += --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt
$(DEBUG_TARGETS): CFLAGS += -DDEBUG -Og $(DEBUG_TARGETS): CFLAGS += -DDEBUG -Og
$(DEBUG_TARGETS): LDFLAGS += -Og $(DEBUG_TARGETS): LDFLAGS += -Og
$(RELEASE_TARGETS): CFLAGS += \ $(RELEASE_TARGETS): CFLAGS += \
-DNDEBUG \ -DNDEBUG
-flto
$(ANDROID_RELEASE_TARGETS): CFLAGS += -Oz $(ANDROID_RELEASE_TARGETS): CFLAGS += -Oz
$(ANDROID_RELEASE_TARGETS): LDFLAGS += -Oz $(ANDROID_RELEASE_TARGETS): LDFLAGS += -Oz
$(NONANDROID_RELEASE_TARGETS): CFLAGS += -Os $(NONANDROID_RELEASE_TARGETS): CFLAGS += -Os
@ -562,7 +560,6 @@ $(UV_OBJS): CFLAGS += \
-Wno-unused-result \ -Wno-unused-result \
-Wno-unused-variable \ -Wno-unused-variable \
-Wno-nonnull -Wno-nonnull
$(UV_OBJS): CFLAGS += -fno-lto
$(filter out/win%,$(UV_OBJS)): \ $(filter out/win%,$(UV_OBJS)): \
CFLAGS += \ CFLAGS += \
-Wno-cast-function-type \ -Wno-cast-function-type \
@ -1146,13 +1143,13 @@ $(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
ifeq ($(UNAME_S),Linux) ifeq ($(UNAME_S),Linux)
LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
$(LOCAL_DEPS): $(LOCAL_DEPS):
+@OPTIONS=-flto tools/ssl-local +@/usr/bin/env bash tools/ssl-local
$(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): | $(LOCAL_DEPS) $(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): | $(LOCAL_DEPS)
ifeq ($(HAVE_CROSS_AARCH64),1) ifeq ($(HAVE_CROSS_AARCH64),1)
LOCAL_DEPS := deps/openssl/$(UNAME_S)/aarch64/usr/local/lib/libssl.a LOCAL_DEPS := deps/openssl/$(UNAME_S)/aarch64/usr/local/lib/libssl.a
$(LOCAL_DEPS): $(LOCAL_DEPS):
+@OPTIONS="--cross-compile-prefix=aarch64-linux-gnu- -flto" BUILD_TARGET=aarch64 tools/ssl-local +@OPTIONS="--cross-compile-prefix=aarch64-linux-gnu-" BUILD_TARGET=aarch64 tools/ssl-local
$(filter $(BUILD_DIR)/armdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/armrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS) $(filter $(BUILD_DIR)/armdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/armrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS)
endif endif
@ -1175,7 +1172,7 @@ endif
ifeq ($(UNAME_S),Darwin) ifeq ($(UNAME_S),Darwin)
LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
$(LOCAL_DEPS): $(LOCAL_DEPS):
+@OPTIONS=-flto tools/ssl-local +@tools/ssl-local
$(filter $(BUILD_DIR)/macosdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/macosrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS) $(filter $(BUILD_DIR)/macosdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/macosrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS)
endif endif
@ -1220,7 +1217,8 @@ appimage: out/tildefriends-x86_64.AppImage ## Build an AppImage.
.PHONY: appimage .PHONY: appimage
flatpak: out/ ## Build a flatpak. 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 remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak-builder --user --disable-rofiles-fuse --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 flatpak build-bundle out/flatpak-repo out/tildefriends.flatpak com.unprompted.tildefriends
.PHONY: flatpak .PHONY: flatpak

View File

@ -1,5 +1,5 @@
{ {
"type": "tildefriends-app", "type": "tildefriends-app",
"emoji": "💻", "emoji": "💻",
"previous": "&icsPplXHgmpkbNWyo/WTvRdT/A8BXxW4lJixOtP4ueQ=.sha256" "previous": "&sFRTDn/RpxP1NJeECXHrXKwCRUJsEOEDVaCMPl50zpM=.sha256"
} }

View File

@ -19,10 +19,6 @@ async function fetch_info(apps) {
return result; return result;
} }
/**
*
*
*/
async function fetch_shared_apps() { async function fetch_shared_apps() {
let messages = {}; let messages = {};
@ -69,17 +65,17 @@ async function main() {
const stylesheet = ` const stylesheet = `
body { body {
color: whitesmoke; color: whitesmoke;
font-family: sans-serif; margin: 8px;
margin: 16px;
} }
.container {
.iconbox {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, 64px); grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
gap: 1em; }
justify-content: space-around;
background-color: #ffffff10; .iconbox::after {
border: 2px solid #073642; content: "";
border-radius: 8px; flex: auto;
} }
.app { .app {
@ -101,16 +97,28 @@ async function main() {
`; `;
const body = ` const body = `
<h1 style="text-shadow: #808080 0 0 10px;">Welcome to Tilde Friends.</h1> <h1>Welcome to Tilde Friends</h1>
<h2>your apps</h2> <div class="w3-card-4 w3-margin-top">
<div id="apps" class="container"></div> <header class="w3-container w3-light-blue">
<h2>Your Apps</h2>
</header>
<div id="apps" class="w3-indigo iconbox"></div>
</div>
<h2>shared apps</h2> <div class="w3-card-4 w3-margin-top">
<div id="shared_apps" class="container"></div> <header class="w3-container w3-light-blue">
<h2>Shared Apps</h2>
</header>
<div id="shared_apps" class="w3-indigo iconbox"></div>
</div>
<h2>core apps</h2> <div class="w3-card-4 w3-margin-top">
<div id="core_apps" class="container"></div> <header class="w3-container w3-light-blue">
<h2>Core Apps</h2>
</header>
<div id="core_apps" class="w3-indigo iconbox"></div>
</div>
`; `;
const script = ` const script = `
@ -126,9 +134,13 @@ async function main() {
// For each app in the provided list // For each app in the provided list
for (let app of Object.keys(apps).sort()) { for (let app of Object.keys(apps).sort()) {
// Create the item // Create the item
let div = list.appendChild(document.createElement('div')); let inline = document.createElement('div');
inline.style.display = 'inline-block';
inline.classList.add('w3-button');
list.appendChild(inline);
let div = document.createElement('div');
inline.appendChild(div);
div.classList.add('app'); div.classList.add('app');
// The app's icon // The app's icon
@ -161,12 +173,13 @@ async function main() {
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<link type="text/css" rel="stylesheet" href="w3.css"></link>
<style> <style>
${stylesheet} ${stylesheet}
</style> </style>
</head> </head>
<body> <body class="w3-darkgray">
${body} ${body}
</body> </body>

235
apps/apps/w3.css Normal file
View File

@ -0,0 +1,235 @@
/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */
html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}
audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
audio:not([controls]){display:none;height:0}[hidden],template{display:none}
a{background-color:transparent}a:active,a:hover{outline-width:0}
abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000}
small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}
code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold}
button,input{overflow:visible}button,select{text-transform:none}
button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}
button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}
button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}
fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
[type=checkbox],[type=radio]{padding:0}
[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
[type=search]::-webkit-search-decoration{-webkit-appearance:none}
::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
/* End extract */
html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}
.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace}
h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
hr{border:0;border-top:1px solid #eee;margin:20px 0}
.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit}
.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
.w3-dropdown-hover:hover .w3-dropdown-content{display:block}
.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1}
.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
.w3-main,#main{transition:margin-left .4s}
.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0}
.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
.w3-bar .w3-button{white-space:normal}
.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
.w3-responsive{display:block;overflow-x:auto}
.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px}
.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px}
.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
@media (max-width:1205px){.w3-auto{max-width:95%}}
@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}
.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}}
.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
.w3-display-position{position:absolute}
.w3-circle{border-radius:50%}
.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px}
.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important}
.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important}
.w3-left{float:left!important}.w3-right{float:right!important}
.w3-button:hover{color:#000!important;background-color:#ccc!important}
.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
.w3-hover-none:hover{box-shadow:none!important}
/* Colors */
.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important}
.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important}
.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important}
.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important}
.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important}
.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important}
.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important}
.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important}
.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important}
.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important}
.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important}
.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important}
.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important}
.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important}
.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important}
.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important}
.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important}
.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important}
.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important}
.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important}
.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important}
.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important}
.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important}
.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}

View File

@ -1,5 +1,5 @@
{ {
"type": "tildefriends-app", "type": "tildefriends-app",
"emoji": "🦀", "emoji": "🦀",
"previous": "&J6o2XRWWAirhnQbEa6Pi0QvAex6jTH1o23npX7x82aY=.sha256" "previous": "&m5ZrkzoyAjv7AY6AukzVoWIyUFUL97uuDDWCtxCloAU=.sha256"
} }

View File

@ -162,7 +162,7 @@ export async function picker(callback, anchor, author) {
<div class="w3-modal-content w3-card-4"> <div class="w3-modal-content w3-card-4">
<div <div
class="w3-content w3-theme-d1" class="w3-content w3-theme-d1"
style="display: flex; flex-direction: column; max-height: 50vh" style="display: flex; flex-direction: column; max-height: 80vh"
> >
<header class="w3-container" style="flex: 0 0"> <header class="w3-container" style="flex: 0 0">
<h1>Choose a Reaction</h1> <h1>Choose a Reaction</h1>

View File

@ -402,10 +402,9 @@ class TfElement extends LitElement {
async fetch_user_info(users) { async fetch_user_info(users) {
let info = await tfrpc.rpc.query( let info = await tfrpc.rpc.query(
` `
SELECT messages.author, MAX(messages.sequence) AS max_seq, MAX(timestamp) AS max_ts FROM messages SELECT messages_stats.author, messages_stats.max_sequence, messages_stats.max_timestamp AS max_ts FROM messages_stats
JOIN json_each(?) AS following JOIN json_each(?) AS following
ON messages.author = following.value ON messages_stats.author = following.value
GROUP BY messages.author
`, `,
[JSON.stringify(Object.keys(users))] [JSON.stringify(Object.keys(users))]
); );
@ -438,10 +437,11 @@ class TfElement extends LitElement {
(await tfrpc.rpc.databaseGet('unread')) ?? '{}' (await tfrpc.rpc.databaseGet('unread')) ?? '{}'
); );
this.following = Object.keys(following); this.following = Object.keys(following);
let about_start_time = new Date();
users = await this.fetch_about(following, users); users = await this.fetch_about(following, users);
console.log( console.log(
'about took', 'about took',
(new Date() - start_time) / 1000.0, (new Date() - about_start_time) / 1000.0,
'seconds for', 'seconds for',
Object.keys(users).length, Object.keys(users).length,
'users' 'users'

View File

@ -57,15 +57,14 @@ class TfTabNewsFeedElement extends LitElement {
JOIN json_each(?2) AS following ON messages.author = following.value JOIN json_each(?2) AS following ON messages.author = following.value
WHERE WHERE
messages.author != ?1 AND messages.author != ?1 AND
messages.timestamp >= ?3 AND (?3 IS NULL OR messages.timestamp >= ?3) AND messages.timestamp < ?4
messages.timestamp < ?4
ORDER BY timestamp DESC limit 20) ORDER BY timestamp DESC limit 20)
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature SELECT FALSE AS is_primary, messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM mentions FROM mentions
JOIN messages_refs ON mentions.id = messages_refs.ref JOIN messages_refs ON mentions.id = messages_refs.ref
JOIN messages ON messages_refs.message = messages.id JOIN messages ON messages_refs.message = messages.id
UNION UNION
SELECT * FROM mentions SELECT TRUE AS is_primary, * FROM mentions
`, `,
[ [
'"' + this.whoami.replace('"', '""') + '"', '"' + this.whoami.replace('"', '""') + '"',
@ -77,33 +76,29 @@ class TfTabNewsFeedElement extends LitElement {
} else if (this.hash.startsWith('#@')) { } else if (this.hash.startsWith('#@')) {
result = await tfrpc.rpc.query( result = await tfrpc.rpc.query(
` `
WITH mine AS (SELECT rowid, id, previous, author, sequence, timestamp, hash, json(content) AS content, signature WITH
FROM messages selected AS (SELECT rowid, id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
WHERE messages.author = ? FROM messages
ORDER BY sequence DESC) WHERE messages.author = ?1 AND (?2 IS NULL OR messages.timestamp >= 2) AND messages.timestamp < ?3
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
FROM mine )
JOIN messages_refs ON mine.id = messages_refs.ref SELECT FALSE AS is_primary, messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM selected
JOIN messages_refs ON selected.id = messages_refs.ref
JOIN messages ON messages_refs.message = messages.id JOIN messages ON messages_refs.message = messages.id
WHERE
messages.timestamp >= ?2 AND
messages.timestamp < ?3
UNION UNION
SELECT * FROM mine SELECT TRUE AS is_primary, * FROM selected
WHERE
mine.timestamp >= ?2 AND
mine.timestamp < ?3
`, `,
[this.hash.substring(1), start_time, end_time] [this.hash.substring(1), start_time, end_time]
); );
} else if (this.hash.startsWith('#%')) { } else if (this.hash.startsWith('#%')) {
result = await tfrpc.rpc.query( result = await tfrpc.rpc.query(
` `
SELECT id, previous, author, sequence, timestamp, hash, json(content) AS content, signature SELECT TRUE AS is_primary, id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
FROM messages FROM messages
WHERE messages.id = ?1 WHERE messages.id = ?1
UNION UNION
SELECT id, previous, author, sequence, timestamp, hash, json(content) AS content, signature SELECT FALSE AS is_primary, id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
FROM messages JOIN messages_refs FROM messages JOIN messages_refs
ON messages.id = messages_refs.message ON messages.id = messages_refs.message
WHERE messages_refs.ref = ?1 WHERE messages_refs.ref = ?1
@ -111,112 +106,98 @@ class TfTabNewsFeedElement extends LitElement {
[this.hash.substring(1)] [this.hash.substring(1)]
); );
} else if (this.hash.startsWith('##')) { } else if (this.hash.startsWith('##')) {
let promises = []; result = await tfrpc.rpc.query(
const k_following_limit = 256; `
for (let i = 0; i < this.following.length; i += k_following_limit) { WITH
promises.push( all_news AS (
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
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 JOIN json_each(?) AS following ON messages.author = following.value
FROM messages WHERE messages.content ->> 'channel' = ?4
JOIN json_each(?) AS following ON messages.author = following.value UNION
WHERE SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
messages.timestamp >= ? AND FROM messages_fts(?5)
messages.timestamp < ? AND JOIN messages ON messages.rowid = messages_fts.rowid
messages.content ->> 'channel' = ? JOIN json_each(?1) AS following ON messages.author = following.value
ORDER BY messages.timestamp DESC) JOIN json_tree(messages.content, '$.mentions') AS mention ON mention.value = '#' || ?4),
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature news AS (SELECT * FROM all_news
FROM news WHERE (?2 IS NULL OR all_news.timestamp >= ?2) AND all_news.timestamp < ?3
JOIN messages_refs ON news.id = messages_refs.ref ORDER BY all_news.timestamp DESC LIMIT 20)
JOIN messages ON messages_refs.message = messages.id SELECT FALSE AS is_primary, messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
UNION FROM news
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature JOIN messages_refs ON news.id = messages_refs.ref
FROM news JOIN messages ON messages_refs.message = messages.id
JOIN messages_refs ON news.id = messages_refs.message UNION
JOIN messages ON messages_refs.ref = messages.id SELECT FALSE AS is_primary, messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
UNION FROM news
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature JOIN messages_refs ON news.id = messages_refs.message
FROM messages_fts(?5) JOIN messages ON messages_refs.ref = messages.id
JOIN messages ON messages.rowid = messages_fts.rowid UNION
JOIN json_each(?1) AS following ON messages.author = following.value SELECT TRUE AS is_primary, news.* FROM news
JOIN json_tree(messages.content, '$.mentions') AS mention ON mention.value = '#' || ?4 `,
WHERE [
messages.timestamp >= ?2 AND JSON.stringify(this.following),
messages.timestamp < ?3 start_time,
UNION end_time,
SELECT news.* FROM news this.hash.substring(2),
`, '"#' + this.hash.substring(2).replace('"', '""') + '"',
[ ]
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 == '#🔐') { } else if (this.hash == '#🔐') {
result = await tfrpc.rpc.query( result = await tfrpc.rpc.query(
` `
SELECT messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature SELECT TRUE AS is_primary, messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
FROM messages FROM messages
JOIN json_each(?1) AS following ON messages.author = following.value JOIN json_each(?1) AS following ON messages.author = following.value
WHERE WHERE
messages.timestamp >= ?2 AND (?2 IS NULL OR (messages.timestamp >= ?2)) AND messages.timestamp < ?3 AND
messages.timestamp < ?3 AND json(messages.content) LIKE '"%'
json(messages.content) LIKE '"%' ORDER BY messages.sequence DESC LIMIT 20
ORDER BY sequence DESC
`, `,
[JSON.stringify(this.following), start_time, end_time] [JSON.stringify(this.following), start_time, end_time]
); );
result = (await this.decrypt(result)).filter((x) => x.decrypted); result = (await this.decrypt(result)).filter((x) => x.decrypted);
} else { } else {
let promises = []; result = await tfrpc.rpc.query(
const k_following_limit = 256; `
for (let i = 0; i < this.following.length; i += k_following_limit) { WITH
promises.push( all_news AS (
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
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 JOIN json_each(?) AS following ON messages.author = following.value
FROM messages WHERE timestamp >= 0 AND timestamp < ?3),
JOIN json_each(?) AS following ON messages.author = following.value news AS (
WHERE messages.timestamp >= ? AND messages.timestamp < ? SELECT * FROM all_news
ORDER BY messages.timestamp DESC) WHERE (?2 IS NULL OR all_news.timestamp >= ?2) AND all_news.timestamp < ?3
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature ORDER BY timestamp DESC LIMIT 20
FROM news )
JOIN messages_refs ON news.id = messages_refs.ref SELECT FALSE AS is_primary, messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
JOIN messages ON messages_refs.message = messages.id FROM news
UNION JOIN messages_refs ON news.id = messages_refs.ref
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature JOIN messages ON messages_refs.message = messages.id
FROM news UNION
JOIN messages_refs ON news.id = messages_refs.message SELECT FALSE AS is_primary, messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
JOIN messages ON messages_refs.ref = messages.id FROM news
UNION JOIN messages_refs ON news.id = messages_refs.message
SELECT news.* FROM news JOIN messages ON messages_refs.ref = messages.id
`, UNION
[ SELECT TRUE AS is_primary, news.* FROM news
JSON.stringify(this.following.slice(i, i + k_following_limit)), `,
start_time, [JSON.stringify(this.following), start_time, end_time]
end_time, );
]
)
);
}
result = [].concat(...(await Promise.all(promises)));
} }
this.time_loading = undefined; this.time_loading = undefined;
return result; return result;
} }
update_time_range_from_messages(messages) { update_time_range_from_messages(messages) {
let only_primary = messages.filter((x) => x.is_primary);
this.time_range = [ this.time_range = [
messages.reduce( only_primary.reduce(
(accumulator, current) => Math.min(accumulator, current.timestamp), (accumulator, current) => Math.min(accumulator, current.timestamp),
this.time_range[0] this.time_range[0]
), ),
messages.reduce( only_primary.reduce(
(accumulator, current) => Math.max(accumulator, current.timestamp), (accumulator, current) => Math.max(accumulator, current.timestamp),
this.time_range[1] this.time_range[1]
), ),
@ -228,17 +209,11 @@ class TfTabNewsFeedElement extends LitElement {
this.loading_canceled = false; this.loading_canceled = false;
try { try {
let more = []; let more = [];
while (!more.length && !this.loading_canceled) { let last_start_time = this.time_range[0];
let last_start_time = this.start_time; more = await this.fetch_messages(null, last_start_time);
this.start_time = last_start_time - 7 * 24 * 60 * 60 * 1000; this.update_time_range_from_messages(
more = await this.fetch_messages(this.start_time, last_start_time); more.filter((x) => x.timestamp < 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]); this.messages = await this.decrypt([...more, ...this.messages]);
} finally { } finally {
this.loading--; this.loading--;
@ -285,14 +260,11 @@ class TfTabNewsFeedElement extends LitElement {
let end_time = now + 24 * 60 * 60 * 1000; let end_time = now + 24 * 60 * 60 * 1000;
let messages = []; let messages = [];
try { try {
messages = await this.fetch_messages( messages = await this.fetch_messages(this.time_range[0], end_time);
this.time_range[1] - 24 * 60 * 60 * 1000,
end_time
);
messages = await this.decrypt(messages); messages = await this.decrypt(messages);
this.update_time_range_from_messages( this.update_time_range_from_messages(
messages.filter( messages.filter(
(x) => x.timestamp >= this.time_range[1] && x.timestamp < end_time (x) => x.timestamp >= this.time_range[0] && x.timestamp < end_time
) )
); );
} finally { } finally {
@ -313,6 +285,7 @@ class TfTabNewsFeedElement extends LitElement {
} }
async load_messages() { async load_messages() {
let start_time = new Date();
let self = this; let self = this;
this.loading++; this.loading++;
let messages = []; let messages = [];
@ -326,38 +299,19 @@ class TfTabNewsFeedElement extends LitElement {
let start_time = now - 24 * 60 * 60 * 1000; let start_time = now - 24 * 60 * 60 * 1000;
this.start_time = start_time; this.start_time = start_time;
this.time_range = [this.start_time, now + 24 * 60 * 60 * 1000]; this.time_range = [this.start_time, now + 24 * 60 * 60 * 1000];
messages = await this.fetch_messages( messages = await this.fetch_messages(null, this.time_range[1]);
this.time_range[0],
this.time_range[1]
);
this.update_time_range_from_messages( this.update_time_range_from_messages(
messages.filter( messages.filter((x) => x.timestamp < this.time_range[1])
(x) =>
x.timestamp >= this.time_range[0] &&
x.timestamp < this.time_range[1]
)
); );
messages = await this.decrypt(messages); 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 { } finally {
this.loading--; this.loading--;
} }
this.messages = this.merge_messages(this.messages, messages); this.messages = this.merge_messages(this.messages, messages);
this.time_loading = undefined; this.time_loading = undefined;
console.log(`loading messages done for ${self.whoami}`); console.log(
`loading messages done for ${self.whoami} in ${(new Date() - start_time) / 1000}s`
);
} }
mark_all_read() { mark_all_read() {

View File

@ -1,4 +1,11 @@
import {LitElement, cache, html, unsafeHTML, until} from './lit-all.min.js'; import {
LitElement,
cache,
keyed,
html,
unsafeHTML,
until,
} from './lit-all.min.js';
import * as tfrpc from '/static/tfrpc.js'; import * as tfrpc from '/static/tfrpc.js';
import {styles} from './tf-styles.js'; import {styles} from './tf-styles.js';
@ -216,16 +223,18 @@ class TfTabNewsElement extends LitElement {
)} )}
<h4 class="w3-bar-item w3-theme-d2">Connections</h4> <h4 class="w3-bar-item w3-theme-d2">Connections</h4>
${this.connections.map( ${this.connections
(x) => html` .filter((x) => x.id && !x.destroy_reason)
<tf-user .map(
class="w3-bar-item" (x) => html`
style="max-width: 100%" <tf-user
id=${x.id} class="w3-bar-item"
.users=${this.users} style="max-width: 100%"
></tf-user> id=${x.id}
` .users=${this.users}
)} ></tf-user>
`
)}
<h4 class="w3-bar-item w3-theme-d2">Suggested Follows</h4> <h4 class="w3-bar-item w3-theme-d2">Suggested Follows</h4>
${this.suggested_follows().map( ${this.suggested_follows().map(
(x) => html` (x) => html`
@ -249,12 +258,15 @@ class TfTabNewsElement extends LitElement {
render() { render() {
let profile = let profile =
this.hash.startsWith('#@') && this.hash != '#@' this.hash.startsWith('#@') && this.hash != '#@'
? html`<tf-profile ? keyed(
class="tf-profile" this.hash.substring(1),
id=${this.hash.substring(1)} html`<tf-profile
whoami=${this.whoami} class="tf-profile"
.users=${this.users} id=${this.hash.substring(1)}
></tf-profile>` whoami=${this.whoami}
.users=${this.users}
></tf-profile>`
)
: undefined; : undefined;
let edit_profile; let edit_profile;
if ( if (

View File

@ -20,7 +20,8 @@ class TfUserElement extends LitElement {
render() { render() {
let user = this.users[this.id]; let user = this.users[this.id];
let shape = !user || user.follow_depth >= 2 ? 'w3-circle' : 'w3-round'; let shape =
!user?.follow_depth || user.follow_depth >= 2 ? 'w3-circle' : 'w3-round';
let image = html`<span let image = html`<span
class=${'w3-theme-l4 ' + shape} class=${'w3-theme-l4 ' + shape}
style="display: inline-block; width: 2em; height: 2em; text-align: center; line-height: 2em" style="display: inline-block; width: 2em; height: 2em; text-align: center; line-height: 2em"

View File

@ -21,27 +21,26 @@
}: }:
pkgs.stdenv.mkDerivation rec { pkgs.stdenv.mkDerivation rec {
pname = "tildefriends"; pname = "tildefriends";
version = "0.0.26"; version = "0.0.27";
src = pkgs.fetchFromGitea { src = pkgs.fetchFromGitea {
domain = "dev.tildefriends.net"; domain = "dev.tildefriends.net";
owner = "cory"; owner = "cory";
repo = "tildefriends"; repo = "tildefriends";
rev = "v${version}"; rev = "v${version}";
hash = "sha256-XJ7M++risfsRn9GkS1zjTQpqqV5S09uyimeVzU9hGGg="; hash = "sha256-NhoTBWYsWc206f1+M9haxHSJU6ZSGoP5nPStymAIyRk=";
fetchSubmodules = true; fetchSubmodules = true;
}; };
nativeBuildInputs = with pkgs; [ nativeBuildInputs = with pkgs; [
bash
glibc glibc
gnumake gnumake
openssl
which which
]; ];
buildInputs = with pkgs; [ buildInputs = with pkgs; [
glibc glibc
openssl
which which
]; ];

File diff suppressed because one or more lines are too long

270
deps/codemirror_src/package-lock.json generated vendored
View File

@ -22,7 +22,6 @@
"version": "6.18.4", "version": "6.18.4",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz", "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz",
"integrity": "sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==", "integrity": "sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/language": "^6.0.0", "@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0", "@codemirror/state": "^6.0.0",
@ -34,7 +33,6 @@
"version": "6.8.0", "version": "6.8.0",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.0.tgz", "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.0.tgz",
"integrity": "sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ==", "integrity": "sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/language": "^6.0.0", "@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.4.0", "@codemirror/state": "^6.4.0",
@ -46,7 +44,6 @@
"version": "6.3.1", "version": "6.3.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz",
"integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.0.0", "@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0", "@codemirror/language": "^6.0.0",
@ -59,7 +56,6 @@
"version": "6.4.9", "version": "6.4.9",
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz", "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz",
"integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==", "integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.0.0", "@codemirror/autocomplete": "^6.0.0",
"@codemirror/lang-css": "^6.0.0", "@codemirror/lang-css": "^6.0.0",
@ -76,7 +72,6 @@
"version": "6.2.2", "version": "6.2.2",
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz", "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
"integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==", "integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.0.0", "@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.6.0", "@codemirror/language": "^6.6.0",
@ -91,7 +86,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz", "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
"integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==", "integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/language": "^6.0.0", "@codemirror/language": "^6.0.0",
"@lezer/json": "^1.0.0" "@lezer/json": "^1.0.0"
@ -101,7 +95,6 @@
"version": "6.10.8", "version": "6.10.8",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.8.tgz", "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.8.tgz",
"integrity": "sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw==", "integrity": "sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/state": "^6.0.0", "@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.23.0", "@codemirror/view": "^6.23.0",
@ -115,7 +108,6 @@
"version": "6.8.4", "version": "6.8.4",
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.4.tgz", "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.4.tgz",
"integrity": "sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==", "integrity": "sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/state": "^6.0.0", "@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.35.0", "@codemirror/view": "^6.35.0",
@ -126,7 +118,6 @@
"version": "6.5.8", "version": "6.5.8",
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz", "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz",
"integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==", "integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/state": "^6.0.0", "@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0", "@codemirror/view": "^6.0.0",
@ -137,7 +128,6 @@
"version": "6.5.1", "version": "6.5.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.1.tgz", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.1.tgz",
"integrity": "sha512-3rA9lcwciEB47ZevqvD8qgbzhM9qMb8vCcQCNmDfVRPQG4JT9mSb0Jg8H7YjKGGQcFnLN323fj9jdnG59Kx6bg==", "integrity": "sha512-3rA9lcwciEB47ZevqvD8qgbzhM9qMb8vCcQCNmDfVRPQG4JT9mSb0Jg8H7YjKGGQcFnLN323fj9jdnG59Kx6bg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@marijn/find-cluster-break": "^1.0.0" "@marijn/find-cluster-break": "^1.0.0"
} }
@ -146,7 +136,6 @@
"version": "6.1.2", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz", "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==", "integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/language": "^6.0.0", "@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0", "@codemirror/state": "^6.0.0",
@ -158,7 +147,6 @@
"version": "6.36.2", "version": "6.36.2",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.2.tgz", "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.2.tgz",
"integrity": "sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA==", "integrity": "sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/state": "^6.5.0", "@codemirror/state": "^6.5.0",
"style-mod": "^4.1.0", "style-mod": "^4.1.0",
@ -170,7 +158,6 @@
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/set-array": "^1.2.1", "@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/sourcemap-codec": "^1.4.10",
@ -185,7 +172,6 @@
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
} }
@ -195,7 +181,6 @@
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
} }
@ -205,7 +190,6 @@
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25" "@jridgewell/trace-mapping": "^0.3.25"
@ -215,15 +199,13 @@
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"dev": true, "dev": true
"license": "MIT"
}, },
"node_modules/@jridgewell/trace-mapping": { "node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25", "version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14" "@jridgewell/sourcemap-codec": "^1.4.14"
@ -232,14 +214,12 @@
"node_modules/@lezer/common": { "node_modules/@lezer/common": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==", "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
"license": "MIT"
}, },
"node_modules/@lezer/css": { "node_modules/@lezer/css": {
"version": "1.1.9", "version": "1.1.10",
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.9.tgz", "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.10.tgz",
"integrity": "sha512-TYwgljcDv+YrV0MZFFvYFQHCfGgbPMR6nuqLabBdmZoFH3EP1gvw8t0vae326Ne3PszQkbXfVBjCnf3ZVCr0bA==", "integrity": "sha512-V5/89eDapjeAkWPBpWEfQjZ1Hag3aYUUJOL8213X0dFRuXJ4BXa5NKl9USzOnaLod4AOpmVCkduir2oKwZYZtg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@lezer/common": "^1.2.0", "@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0", "@lezer/highlight": "^1.0.0",
@ -250,7 +230,6 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@lezer/common": "^1.0.0" "@lezer/common": "^1.0.0"
} }
@ -259,7 +238,6 @@
"version": "1.3.10", "version": "1.3.10",
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz", "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz",
"integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==", "integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==",
"license": "MIT",
"dependencies": { "dependencies": {
"@lezer/common": "^1.2.0", "@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0", "@lezer/highlight": "^1.0.0",
@ -270,7 +248,6 @@
"version": "1.4.21", "version": "1.4.21",
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.21.tgz", "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.21.tgz",
"integrity": "sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==", "integrity": "sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@lezer/common": "^1.2.0", "@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.1.3", "@lezer/highlight": "^1.1.3",
@ -281,7 +258,6 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz",
"integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@lezer/common": "^1.2.0", "@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0", "@lezer/highlight": "^1.0.0",
@ -292,7 +268,6 @@
"version": "1.4.2", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@lezer/common": "^1.0.0" "@lezer/common": "^1.0.0"
} }
@ -300,14 +275,12 @@
"node_modules/@marijn/find-cluster-break": { "node_modules/@marijn/find-cluster-break": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g=="
"license": "MIT"
}, },
"node_modules/@rollup/plugin-node-resolve": { "node_modules/@rollup/plugin-node-resolve": {
"version": "15.3.1", "version": "15.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz",
"integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@rollup/pluginutils": "^5.0.1", "@rollup/pluginutils": "^5.0.1",
"@types/resolve": "1.20.2", "@types/resolve": "1.20.2",
@ -332,7 +305,6 @@
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"serialize-javascript": "^6.0.1", "serialize-javascript": "^6.0.1",
"smob": "^1.0.0", "smob": "^1.0.0",
@ -354,7 +326,6 @@
"version": "5.1.4", "version": "5.1.4",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz",
"integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@types/estree": "^1.0.0", "@types/estree": "^1.0.0",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
@ -373,247 +344,228 @@
} }
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.1.tgz",
"integrity": "sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==", "integrity": "sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.1.tgz",
"integrity": "sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==", "integrity": "sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.1.tgz",
"integrity": "sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==", "integrity": "sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.1.tgz",
"integrity": "sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==", "integrity": "sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
] ]
}, },
"node_modules/@rollup/rollup-freebsd-arm64": { "node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.1.tgz",
"integrity": "sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==", "integrity": "sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
] ]
}, },
"node_modules/@rollup/rollup-freebsd-x64": { "node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.1.tgz",
"integrity": "sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==", "integrity": "sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.1.tgz",
"integrity": "sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==", "integrity": "sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.1.tgz",
"integrity": "sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==", "integrity": "sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.1.tgz",
"integrity": "sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==", "integrity": "sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.1.tgz",
"integrity": "sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==", "integrity": "sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-loongarch64-gnu": { "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.1.tgz",
"integrity": "sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==", "integrity": "sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.1.tgz",
"integrity": "sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==", "integrity": "sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.1.tgz",
"integrity": "sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==", "integrity": "sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.1.tgz",
"integrity": "sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==", "integrity": "sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.1.tgz",
"integrity": "sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==", "integrity": "sha512-WQFLZ9c42ECqEjwg/GHHsouij3pzLXkFdz0UxHa/0OM12LzvX7DzedlY0SIEly2v18YZLRhCRoHZDxbBSWoGYg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.1.tgz",
"integrity": "sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==", "integrity": "sha512-BLoiyHDOWoS3uccNSADMza6V6vCNiphi94tQlVIL5de+r6r/CCQuNnerf+1g2mnk2b6edp5dk0nhdZ7aEjOBsA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.1.tgz",
"integrity": "sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==", "integrity": "sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.1.tgz",
"integrity": "sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==", "integrity": "sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.30.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.1.tgz",
"integrity": "sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==", "integrity": "sha512-ar80GhdZb4DgmW3myIS9nRFYcpJRSME8iqWgzH2i44u+IdrzmiXVxeFnExQ5v4JYUSpg94bWjevMG8JHf1Da5Q==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@ -622,21 +574,18 @@
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
"license": "MIT"
}, },
"node_modules/@types/resolve": { "node_modules/@types/resolve": {
"version": "1.20.2", "version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
"license": "MIT"
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.14.0", "version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"dev": true, "dev": true,
"license": "MIT",
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@ -648,14 +597,12 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true, "dev": true
"license": "MIT"
}, },
"node_modules/codemirror": { "node_modules/codemirror": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.0.0", "@codemirror/autocomplete": "^6.0.0",
"@codemirror/commands": "^6.0.0", "@codemirror/commands": "^6.0.0",
@ -670,20 +617,17 @@
"version": "2.20.3", "version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true, "dev": true
"license": "MIT"
}, },
"node_modules/crelt": { "node_modules/crelt": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
"license": "MIT"
}, },
"node_modules/deepmerge": { "node_modules/deepmerge": {
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -691,15 +635,13 @@
"node_modules/estree-walker": { "node_modules/estree-walker": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
"license": "MIT"
}, },
"node_modules/fsevents": { "node_modules/fsevents": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
@ -712,7 +654,6 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@ -721,7 +662,6 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"function-bind": "^1.1.2" "function-bind": "^1.1.2"
}, },
@ -733,7 +673,6 @@
"version": "2.16.1", "version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"license": "MIT",
"dependencies": { "dependencies": {
"hasown": "^2.0.2" "hasown": "^2.0.2"
}, },
@ -747,20 +686,17 @@
"node_modules/is-module": { "node_modules/is-module": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="
"license": "MIT"
}, },
"node_modules/path-parse": { "node_modules/path-parse": {
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
"license": "MIT"
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"license": "MIT",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@ -773,7 +709,6 @@
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"safe-buffer": "^5.1.0" "safe-buffer": "^5.1.0"
} }
@ -782,7 +717,6 @@
"version": "1.22.10", "version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
"license": "MIT",
"dependencies": { "dependencies": {
"is-core-module": "^2.16.0", "is-core-module": "^2.16.0",
"path-parse": "^1.0.7", "path-parse": "^1.0.7",
@ -799,10 +733,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.30.1", "version": "4.32.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.1.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.1.tgz",
"integrity": "sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==", "integrity": "sha512-z+aeEsOeEa3mEbS1Tjl6sAZ8NE3+AalQz1RJGj81M+fizusbdDMoEJwdJNHfaB40Scr4qNu+welOfes7maKonA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@types/estree": "1.0.6" "@types/estree": "1.0.6"
}, },
@ -814,25 +747,25 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.30.1", "@rollup/rollup-android-arm-eabi": "4.32.1",
"@rollup/rollup-android-arm64": "4.30.1", "@rollup/rollup-android-arm64": "4.32.1",
"@rollup/rollup-darwin-arm64": "4.30.1", "@rollup/rollup-darwin-arm64": "4.32.1",
"@rollup/rollup-darwin-x64": "4.30.1", "@rollup/rollup-darwin-x64": "4.32.1",
"@rollup/rollup-freebsd-arm64": "4.30.1", "@rollup/rollup-freebsd-arm64": "4.32.1",
"@rollup/rollup-freebsd-x64": "4.30.1", "@rollup/rollup-freebsd-x64": "4.32.1",
"@rollup/rollup-linux-arm-gnueabihf": "4.30.1", "@rollup/rollup-linux-arm-gnueabihf": "4.32.1",
"@rollup/rollup-linux-arm-musleabihf": "4.30.1", "@rollup/rollup-linux-arm-musleabihf": "4.32.1",
"@rollup/rollup-linux-arm64-gnu": "4.30.1", "@rollup/rollup-linux-arm64-gnu": "4.32.1",
"@rollup/rollup-linux-arm64-musl": "4.30.1", "@rollup/rollup-linux-arm64-musl": "4.32.1",
"@rollup/rollup-linux-loongarch64-gnu": "4.30.1", "@rollup/rollup-linux-loongarch64-gnu": "4.32.1",
"@rollup/rollup-linux-powerpc64le-gnu": "4.30.1", "@rollup/rollup-linux-powerpc64le-gnu": "4.32.1",
"@rollup/rollup-linux-riscv64-gnu": "4.30.1", "@rollup/rollup-linux-riscv64-gnu": "4.32.1",
"@rollup/rollup-linux-s390x-gnu": "4.30.1", "@rollup/rollup-linux-s390x-gnu": "4.32.1",
"@rollup/rollup-linux-x64-gnu": "4.30.1", "@rollup/rollup-linux-x64-gnu": "4.32.1",
"@rollup/rollup-linux-x64-musl": "4.30.1", "@rollup/rollup-linux-x64-musl": "4.32.1",
"@rollup/rollup-win32-arm64-msvc": "4.30.1", "@rollup/rollup-win32-arm64-msvc": "4.32.1",
"@rollup/rollup-win32-ia32-msvc": "4.30.1", "@rollup/rollup-win32-ia32-msvc": "4.32.1",
"@rollup/rollup-win32-x64-msvc": "4.30.1", "@rollup/rollup-win32-x64-msvc": "4.32.1",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
@ -854,15 +787,13 @@
"type": "consulting", "type": "consulting",
"url": "https://feross.org/support" "url": "https://feross.org/support"
} }
], ]
"license": "MIT"
}, },
"node_modules/serialize-javascript": { "node_modules/serialize-javascript": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true, "dev": true,
"license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"randombytes": "^2.1.0" "randombytes": "^2.1.0"
} }
@ -871,15 +802,13 @@
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
"integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==",
"dev": true, "dev": true
"license": "MIT"
}, },
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true, "dev": true,
"license": "BSD-3-Clause",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -889,7 +818,6 @@
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"buffer-from": "^1.0.0", "buffer-from": "^1.0.0",
"source-map": "^0.6.0" "source-map": "^0.6.0"
@ -898,14 +826,12 @@
"node_modules/style-mod": { "node_modules/style-mod": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
"license": "MIT"
}, },
"node_modules/supports-preserve-symlinks-flag": { "node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
}, },
@ -918,7 +844,6 @@
"resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
"integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
"dev": true, "dev": true,
"license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"@jridgewell/source-map": "^0.3.3", "@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2", "acorn": "^8.8.2",
@ -935,8 +860,7 @@
"node_modules/w3c-keyname": { "node_modules/w3c-keyname": {
"version": "2.2.8", "version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
"license": "MIT"
} }
} }
} }

View File

@ -1,19 +1,20 @@
* Replying in a new thread.
* Drafts in the sidebar.
* Fix channel cycling shortcut.
* New databases go in ~/.local/share/tildefriends/.
* Cross-compile for aarch64.
* Load time optimizations.
* Show disconnect reasons in the UI.
* Improved unread status.
* Replication improvements.
* Show new messages as they arrive.
* Dynamic color scheme.
* Layout tweaks.
* Fix win32 crashes. * Fix win32 crashes.
* Loading screen. * Cross-compile for aarch64.
* Removed "server follow me." * Added CLI commands.
* Added various CLI commands. * SSB
* Updated dependencies: * Invites.
* Replying in a new thread.
* Drafts in the sidebar.
* Fix channel cycling shortcut.
* New databases go in ~/.local/share/tildefriends/.
* Disconnect reasons.
* Improved unread status.
* Improved replication.
* Show messages as they arrive.
* Loading screen.
* Faster load.
* Updated:
* CodeMirror * CodeMirror
* libuv 1.50.0
* speedscope 1.22.0
* sqlite 3.48.0 * sqlite 3.48.0

1
package-lock.json generated
View File

@ -14,7 +14,6 @@
"version": "3.4.2", "version": "3.4.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
"license": "MIT",
"bin": { "bin": {
"prettier": "bin/prettier.cjs" "prettier": "bin/prettier.cjs"
}, },

View File

@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unprompted.tildefriends" package="com.unprompted.tildefriends"
android:versionCode="32" android:versionCode="32"
android:versionName="0.0.27-wip"> android:versionName="0.0.27">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<application <application

View File

@ -1,6 +1,6 @@
id: com.unprompted.tildefriends id: com.unprompted.tildefriends
runtime: org.freedesktop.Platform runtime: org.freedesktop.Platform
runtime-version: '23.08' runtime-version: '24.08'
sdk: org.freedesktop.Sdk sdk: org.freedesktop.Sdk
command: tildefriends-run.sh command: tildefriends-run.sh
finish-args: finish-args:

View File

@ -1408,7 +1408,7 @@ static bool _tf_ssb_is_already_connected(tf_ssb_t* ssb, uint8_t* id, tf_ssb_conn
{ {
for (tf_ssb_connection_t* connection = ssb->connections; connection; connection = connection->next) for (tf_ssb_connection_t* connection = ssb->connections; connection; connection = connection->next)
{ {
if (!ignore_connection || connection != ignore_connection) if ((!ignore_connection || connection != ignore_connection) && !connection->is_closing)
{ {
if (memcmp(connection->serverpub, id, k_id_bin_len) == 0) if (memcmp(connection->serverpub, id, k_id_bin_len) == 0)
{ {

View File

@ -108,6 +108,24 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
" flags INTEGER," " flags INTEGER,"
" UNIQUE(author, sequence)" " UNIQUE(author, sequence)"
")"); ")");
if (!_tf_ssb_db_has_rows(db, "PRAGMA table_list('messages_stats')"))
{
_tf_ssb_db_exec(db,
"CREATE TABLE IF NOT EXISTS messages_stats ("
" author TEXT PRIMARY KEY,"
" max_sequence INTEGER,"
" max_timestamp READ"
")");
_tf_ssb_db_exec(
db, "INSERT OR REPLACE INTO messages_stats (author, max_sequence, max_timestamp) SELECT author, MAX(sequence), MAX(timestamp) FROM messages GROUP BY author");
}
_tf_ssb_db_exec(db,
"CREATE TRIGGER IF NOT EXISTS messages_ai_stats AFTER INSERT ON messages BEGIN INSERT INTO messages_stats(author, max_sequence, max_timestamp) VALUES (new.author, "
"new.sequence, new.timestamp) ON CONFLICT DO UPDATE SET max_sequence = MAX(max_sequence, excluded.max_sequence), max_timestamp = MAX(max_timestamp, "
"excluded.max_timestamp); END");
_tf_ssb_db_exec(db,
"CREATE TRIGGER IF NOT EXISTS messages_ad_stats AFTER DELETE ON messages BEGIN UPDATE messages_stats SET max_sequence = (SELECT MAX(messages.sequence) FROM messages WHERE "
"messages.author = old.author), max_timestamp = (SELECT MAX(messages.timestamp) FROM messages WHERE messages.author = old.author); END");
if (_tf_ssb_db_has_rows(db, "SELECT name FROM pragma_table_info('messages') WHERE name = 'content' AND type == 'TEXT'")) if (_tf_ssb_db_has_rows(db, "SELECT name FROM pragma_table_info('messages') WHERE name = 'content' AND type == 'TEXT'"))
{ {
@ -987,8 +1005,9 @@ int tf_ssb_sqlite_authorizer(void* user_data, int action_code, const char* arg0,
break; break;
case SQLITE_READ: case SQLITE_READ:
result = (strcmp(arg0, "blob_wants_view") == 0 || strcmp(arg0, "json_each") == 0 || strcmp(arg0, "json_tree") == 0 || strcmp(arg0, "messages") == 0 || result = (strcmp(arg0, "blob_wants_view") == 0 || strcmp(arg0, "json_each") == 0 || strcmp(arg0, "json_tree") == 0 || strcmp(arg0, "messages") == 0 ||
strcmp(arg0, "messages_fts") == 0 || strcmp(arg0, "messages_fts_idx") == 0 || strcmp(arg0, "messages_fts_config") == 0 || strcmp(arg0, "messages_refs") == 0 || strcmp(arg0, "messages_stats") == 0 || strcmp(arg0, "messages_fts") == 0 || strcmp(arg0, "messages_fts_idx") == 0 ||
strcmp(arg0, "messages_refs_message_idx") == 0 || strcmp(arg0, "messages_refs_ref_idx") == 0 || strcmp(arg0, "sqlite_master") == 0 || false) strcmp(arg0, "messages_fts_config") == 0 || strcmp(arg0, "messages_refs") == 0 || strcmp(arg0, "messages_refs_message_idx") == 0 ||
strcmp(arg0, "messages_refs_ref_idx") == 0 || strcmp(arg0, "sqlite_master") == 0 || false)
? SQLITE_OK ? SQLITE_OK
: SQLITE_DENY; : SQLITE_DENY;
break; break;
@ -2046,6 +2065,10 @@ bool tf_ssb_db_get_global_setting_bool(sqlite3* db, const char* name, bool* out_
{ {
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db)); tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
} }
if (!result)
{
*out_value = tf_util_get_default_global_setting_bool(name);
}
return result; return result;
} }
@ -2069,6 +2092,10 @@ bool tf_ssb_db_get_global_setting_int64(sqlite3* db, const char* name, int64_t*
{ {
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db)); tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
} }
if (!result)
{
*out_value = tf_util_get_default_global_setting_int(name);
}
return result; return result;
} }
@ -2092,6 +2119,10 @@ bool tf_ssb_db_get_global_setting_string(sqlite3* db, const char* name, char* ou
{ {
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db)); tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
} }
if (!result)
{
snprintf(out_value, size, "%s", tf_util_get_default_global_setting_string(name));
}
return result; return result;
} }

View File

@ -522,10 +522,11 @@ static void _tf_ssb_rpc_tunnel_endpoints(tf_ssb_connection_t* connection, uint8_
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
if (!tf_ssb_is_room(ssb)) if (!tf_ssb_is_room(ssb))
{ {
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "room.attendants"); tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "tunnel.endpoints");
return; return;
} }
tf_ssb_connection_add_request(connection, -request_number, "tunnel.endpoints", NULL, NULL, NULL, NULL);
tf_ssb_connection_set_endpoint(connection, true, request_number); tf_ssb_connection_set_endpoint(connection, true, request_number);
_tf_ssb_rpc_send_endpoints(ssb); _tf_ssb_rpc_send_endpoints(ssb);
} }
@ -1202,16 +1203,98 @@ static void _tf_ssb_rpc_ebt_replicate_server(
tf_ssb_connection_add_request(connection, -request_number, "ebt.replicate", _tf_ssb_rpc_ebt_replicate, NULL, NULL, NULL); tf_ssb_connection_add_request(connection, -request_number, "ebt.replicate", _tf_ssb_rpc_ebt_replicate, NULL, NULL, NULL);
} }
typedef struct _invite_use_t
{
tf_ssb_t* ssb;
char author[k_id_base64_len];
;
uint8_t private_key[512];
char previous_id[64];
int64_t previous_sequence;
char host[256];
int port;
char pub[k_id_base64_len];
} invite_use_t;
static void _tf_ssb_rpc_get_previous_work(tf_ssb_connection_t* connection, void* user_data)
{
invite_use_t* work = user_data;
tf_ssb_t* ssb = work->ssb;
tf_ssb_db_get_latest_message_by_author(ssb, work->author, &work->previous_sequence, work->previous_id, sizeof(work->previous_id));
}
static void _tf_ssb_invite_use_pub_message_store_callback(const char* id, bool verified, bool is_new, void* user_data)
{
invite_use_t* work = user_data;
tf_free(work);
}
static void _tf_ssb_invite_use_contact_message_store_callback(const char* id, bool verified, bool is_new, void* user_data)
{
/*
** 2. Post a pub message:
** { "type": "pub", "address": { "host": "one.butt.nz", "port": 8008, "key": "@VJM7w1W19ZsKmG2KnfaoKIM66BRoreEkzaVm/J//wl8=.ed25519" } }
*/
invite_use_t* work = user_data;
tf_ssb_t* ssb = work->ssb;
JSContext* context = tf_ssb_get_context(ssb);
JSValue content = JS_NewObject(context);
JS_SetPropertyStr(context, content, "type", JS_NewString(context, "pub"));
JSValue address = JS_NewObject(context);
JS_SetPropertyStr(context, address, "host", JS_NewString(context, work->host));
JS_SetPropertyStr(context, address, "port", JS_NewInt32(context, work->port));
JS_SetPropertyStr(context, address, "key", JS_NewString(context, work->pub));
JS_SetPropertyStr(context, content, "address", address);
JSValue message = tf_ssb_sign_message(ssb, work->author, work->private_key, content, id, work->previous_sequence + 1);
JSValue json = JS_JSONStringify(context, message, JS_NULL, JS_NULL);
JS_FreeValue(context, json);
tf_ssb_verify_strip_and_store_message(ssb, message, _tf_ssb_invite_use_pub_message_store_callback, work);
JS_FreeValue(context, message);
JS_FreeValue(context, content);
}
static void _tf_ssb_rpc_get_previous_after_work(tf_ssb_connection_t* connection, int status, void* user_data)
{
invite_use_t* work = user_data;
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
JSContext* context = tf_ssb_connection_get_context(connection);
JSValue content = JS_NewObject(context);
JS_SetPropertyStr(context, content, "type", JS_NewString(context, "contact"));
JS_SetPropertyStr(context, content, "contact", JS_NewString(context, work->pub));
JS_SetPropertyStr(context, content, "following", JS_TRUE);
JSValue message = tf_ssb_sign_message(ssb, work->author, work->private_key, content, work->previous_id, work->previous_sequence);
JSValue json = JS_JSONStringify(context, message, JS_NULL, JS_NULL);
JS_FreeValue(context, json);
tf_ssb_verify_strip_and_store_message(ssb, message, _tf_ssb_invite_use_contact_message_store_callback, work);
JS_FreeValue(context, message);
JS_FreeValue(context, content);
}
static void _tf_ssb_rpc_invite_use_callback( static void _tf_ssb_rpc_invite_use_callback(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
/* /*
** Follow the pub back: ** 1. Follow the pub back:
** { "type": "contact", "contact": "@VJM7w1W19ZsKmG2KnfaoKIM66BRoreEkzaVm/J//wl8=.ed25519", "following": true } ** { "type": "contact", "contact": "@VJM7w1W19ZsKmG2KnfaoKIM66BRoreEkzaVm/J//wl8=.ed25519", "following": true }
**
** Post a pub message:
** { "type": "pub", "address": { "host": "one.butt.nz", "port": 8008, "key": "@VJM7w1W19ZsKmG2KnfaoKIM66BRoreEkzaVm/J//wl8=.ed25519" } }
*/ */
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
invite_use_t* work = tf_malloc(sizeof(invite_use_t));
*work = (invite_use_t) {
.ssb = ssb,
.port = tf_ssb_connection_get_port(connection),
};
snprintf(work->host, sizeof(work->host), "%s", tf_ssb_connection_get_host(connection));
tf_ssb_whoami(ssb, work->author, sizeof(work->author));
tf_ssb_get_private_key(ssb, work->private_key, sizeof(work->private_key));
tf_ssb_connection_get_id(connection, work->pub, sizeof(work->pub));
tf_ssb_connection_run_work(connection, _tf_ssb_rpc_get_previous_work, _tf_ssb_rpc_get_previous_after_work, work);
} }
static void _tf_ssb_rpc_send_invite_use(tf_ssb_connection_t* connection) static void _tf_ssb_rpc_send_invite_use(tf_ssb_connection_t* connection)

View File

@ -1371,7 +1371,7 @@ void tf_ssb_test_invite(const tf_test_options_t* options)
tf_printf("waiting for messages\n"); tf_printf("waiting for messages\n");
tf_ssb_set_main_thread(ssb0, true); tf_ssb_set_main_thread(ssb0, true);
tf_ssb_set_main_thread(ssb1, true); tf_ssb_set_main_thread(ssb1, true);
while (count0 != 1 || count1 != 1) while (count0 != 3 || count1 != 3)
{ {
uv_run(&loop, UV_RUN_ONCE); uv_run(&loop, UV_RUN_ONCE);
} }

View File

@ -34,6 +34,7 @@ typedef struct _tf_trace_stack_t
typedef struct _tf_trace_thread_t typedef struct _tf_trace_thread_t
{ {
pthread_t id; pthread_t id;
int index;
tf_trace_stack_t* stack; tf_trace_stack_t* stack;
char name[64]; char name[64];
} tf_trace_thread_t; } tf_trace_thread_t;
@ -208,6 +209,7 @@ static tf_trace_thread_t* _tf_trace_get_thread(tf_trace_t* trace, pthread_t self
found = tf_malloc(sizeof(tf_trace_thread_t)); found = tf_malloc(sizeof(tf_trace_thread_t));
*found = (tf_trace_thread_t) { *found = (tf_trace_thread_t) {
.id = self, .id = self,
.index = trace->threads_count,
}; };
#if defined(__linux__) && !defined(__ANDROID__) #if defined(__linux__) && !defined(__ANDROID__)
pthread_getname_np(self, found->name, sizeof(found->name)); pthread_getname_np(self, found->name, sizeof(found->name));
@ -221,7 +223,7 @@ static tf_trace_thread_t* _tf_trace_get_thread(tf_trace_t* trace, pthread_t self
return found; return found;
} }
static void _tf_push_stack(tf_trace_t* trace, pthread_t self, const char* name, void* tag) static void _tf_push_stack(tf_trace_t* trace, pthread_t self, const char* name, void* tag, tf_trace_thread_t** out_thread)
{ {
tf_trace_thread_t* thread = _tf_trace_get_thread(trace, self); tf_trace_thread_t* thread = _tf_trace_get_thread(trace, self);
if (!thread->stack || thread->stack->count + 1 > tf_countof(thread->stack->names)) if (!thread->stack || thread->stack->count + 1 > tf_countof(thread->stack->names))
@ -239,9 +241,10 @@ static void _tf_push_stack(tf_trace_t* trace, pthread_t self, const char* name,
stack->names[stack->count] = name; stack->names[stack->count] = name;
stack->tags[stack->count] = tag; stack->tags[stack->count] = tag;
stack->count++; stack->count++;
*out_thread = thread;
} }
static const char* _tf_pop_stack(tf_trace_t* trace, pthread_t self, void* tag) static const char* _tf_pop_stack(tf_trace_t* trace, pthread_t self, void* tag, tf_trace_thread_t** out_thread)
{ {
tf_trace_thread_t* thread = _tf_trace_get_thread(trace, self); tf_trace_thread_t* thread = _tf_trace_get_thread(trace, self);
tf_trace_stack_t* stack = thread->stack; tf_trace_stack_t* stack = thread->stack;
@ -255,6 +258,7 @@ static const char* _tf_pop_stack(tf_trace_t* trace, pthread_t self, void* tag)
name = stack->names[stack->count - 1]; name = stack->names[stack->count - 1];
stack->count--; stack->count--;
} }
*out_thread = thread;
return name; return name;
} }
@ -265,11 +269,11 @@ static void _tf_trace_begin_tagged(tf_trace_t* trace, const char* name, void* ta
return; return;
} }
pthread_t self = pthread_self(); tf_trace_thread_t* thread = NULL;
_tf_push_stack(trace, self, name, tag); _tf_push_stack(trace, pthread_self(), name, tag, &thread);
char line[1024]; char line[1024];
int p = snprintf(line, sizeof(line), "{\"ph\": \"B\", \"pid\": %d, \"tid\": %" PRId64 ", \"ts\": %" PRId64 ", \"name\": \"", getpid(), (int64_t)self, _trace_ts()); int p = snprintf(line, sizeof(line), "{\"ph\": \"B\", \"pid\": %d, \"tid\": %d, \"ts\": %" PRId64 ", \"name\": \"", getpid(), thread->index, _trace_ts());
p += _tf_trace_escape_name(line + p, sizeof(line) - p - 4, name); p += _tf_trace_escape_name(line + p, sizeof(line) - p - 4, name);
p += snprintf(line + p, sizeof(line) - p, "\"},"); p += snprintf(line + p, sizeof(line) - p, "\"},");
p = tf_min(p, tf_countof(line)); p = tf_min(p, tf_countof(line));
@ -288,15 +292,15 @@ static void _tf_trace_end_tagged(tf_trace_t* trace, void* tag)
return; return;
} }
pthread_t self = pthread_self(); tf_trace_thread_t* thread = NULL;
const char* name = _tf_pop_stack(trace, self, tag); const char* name = _tf_pop_stack(trace, pthread_self(), tag, &thread);
if (!name) if (!name)
{ {
return; return;
} }
char line[1024]; char line[1024];
int p = snprintf(line, sizeof(line), "{\"ph\": \"E\", \"pid\": %d, \"tid\": %" PRId64 ", \"ts\": %" PRId64 ", \"name\": \"", getpid(), (int64_t)pthread_self(), _trace_ts()); int p = snprintf(line, sizeof(line), "{\"ph\": \"E\", \"pid\": %d, \"tid\": %d, \"ts\": %" PRId64 ", \"name\": \"", getpid(), thread->index, _trace_ts());
p += _tf_trace_escape_name(line + p, sizeof(line) - p - 4, name); p += _tf_trace_escape_name(line + p, sizeof(line) - p - 4, name);
p += snprintf(line + p, sizeof(line) - p, "\"},"); p += snprintf(line + p, sizeof(line) - p, "\"},");
p = tf_min(p, tf_countof(line)); p = tf_min(p, tf_countof(line));
@ -330,8 +334,8 @@ char* tf_trace_export(tf_trace_t* trace)
for (int i = 0; i < trace->threads_count; i++) for (int i = 0; i < trace->threads_count; i++)
{ {
tf_trace_thread_t* thread = trace->threads[i]; tf_trace_thread_t* thread = trace->threads[i];
size += snprintf(buffer + size, k_buffer_size - size, "{\"ph\":\"M\",\"pid\":%d,\"tid\":%" PRId64 ",\"name\":\"thread_name\",\"args\":{\"name\":\"%s\"}},\n", getpid(), size += snprintf(buffer + size, k_buffer_size - size, "{\"ph\":\"M\",\"pid\":%d,\"tid\":%d,\"name\":\"thread_name\",\"args\":{\"name\":\"%s\"}},\n", getpid(),
(uint64_t)thread->id, thread->name); thread->index, thread->name);
} }
uv_rwlock_rdunlock(&trace->threads_lock); uv_rwlock_rdunlock(&trace->threads_lock);
if (begin) if (begin)

View File

@ -20,6 +20,16 @@
#include <execinfo.h> #include <execinfo.h>
#endif #endif
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IPHONE)
#define TF_IS_MOBILE 1
#else
#define TF_IS_MOBILE 0
#endif
static JSValue _util_utf8_encode(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) static JSValue _util_utf8_encode(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{ {
size_t length = 0; size_t length = 0;
@ -304,73 +314,139 @@ static JSValue _util_parseHttpResponse(JSContext* context, JSValueConst this_val
return result; return result;
} }
#if defined(__APPLE__) typedef enum _value_kind_t
#include <TargetConditionals.h>
#endif
static bool _is_mobile()
{ {
#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IPHONE) k_kind_bool,
return true; k_kind_int,
#else k_kind_string,
return false; } value_kind_t;
#endif
static const char* k_kind_name[] = {
[k_kind_bool] = "bool",
[k_kind_int] = "int",
[k_kind_string] = "string",
};
typedef struct _setting_value_t
{
value_kind_t kind;
union
{
bool bool_value;
int int_value;
const char* string_value;
};
} setting_value_t;
typedef struct _setting_t
{
const char* name;
const char* type;
const char* description;
setting_value_t default_value;
} setting_t;
static const setting_t k_settings[] = {
{ .name = "code_of_conduct", .type = "textarea", .description = "Code of conduct presented at sign-in.", .default_value = { .kind = k_kind_string, .string_value = NULL } },
{ .name = "blob_fetch_age_seconds",
.type = "integer",
.description = "Only blobs mentioned more recently than this age will be automatically fetched.",
.default_value = { .kind = k_kind_int, .int_value = TF_IS_MOBILE ? (int)(0.5f * 365 * 24 * 60 * 60) : -1 } },
{ .name = "blob_expire_age_seconds",
.type = "integer",
.description = "Blobs older than this will be automatically deleted.",
.default_value = { .kind = k_kind_int, .int_value = TF_IS_MOBILE ? (int)(1.0f * 365 * 24 * 60 * 60) : -1 } },
{ .name = "fetch_hosts",
.type = "string",
.description = "Comma-separated list of host names to which HTTP fetch requests are allowed. None if empty.",
.default_value = { .kind = k_kind_string, .string_value = NULL } },
{ .name = "http_redirect",
.type = "string",
.description = "If connecting by HTTP and HTTPS is configured, Location header prefix (ie, \"http://example.com\")",
.default_value = { .kind = k_kind_string, .string_value = NULL } },
{ .name = "index", .type = "string", .description = "Default path.", .default_value = { .kind = k_kind_string, .string_value = "/~core/ssb/" } },
{ .name = "index_map",
.type = "textarea",
.description = "Mappings from hostname to redirect path, one per line, as in: \"www.tildefriends.net=/~core/index/\"",
.default_value = { .kind = k_kind_string, .string_value = NULL } },
{ .name = "peer_exchange",
.type = "boolean",
.description = "Enable discovery of, sharing of, and connecting to internet peer strangers, including announcing this instance.",
.default_value = { .kind = k_kind_bool, .bool_value = false } },
{ .name = "replicator", .type = "boolean", .description = "Enable message and blob replication.", .default_value = { .kind = k_kind_bool, .bool_value = true } },
{ .name = "room", .type = "boolean", .description = "Enable peers to tunnel through this instance as a room.", .default_value = { .kind = k_kind_bool, .bool_value = true } },
{ .name = "room_name", .type = "string", .description = "Name of the room.", .default_value = { .kind = k_kind_string, .string_value = "tilde friends tunnel" } },
{ .name = "seeds_host",
.type = "string",
.description = "Hostname for seed connections.",
.default_value = { .kind = k_kind_string, .string_value = "seeds.tildefriends.net" } },
{ .name = "account_registration", .type = "boolean", .description = "Allow registration of new accounts.", .default_value = { .kind = k_kind_bool, .bool_value = true } },
{ .name = "replication_hops",
.type = "integer",
.description = "Number of hops to replicate (1 = direct follows, 2 = follows of follows, etc.).",
.default_value = { .kind = k_kind_int, .int_value = 2 } },
{ .name = "delete_stale_feeds",
.type = "boolean",
.description = "Periodically delete feeds that aren't visible from local accounts or related follows.",
.default_value = { .kind = k_kind_bool, .bool_value = false } },
{ .name = "talk_to_strangers",
.type = "boolean",
.description = "Whether connections are accepted from accounts that aren't in the replication range or otherwise already known.",
.default_value = { .kind = k_kind_bool, .bool_value = true } },
};
static const setting_t* _util_get_setting(const char* name, value_kind_t kind)
{
for (int i = 0; i < tf_countof(k_settings); i++)
{
if (strcmp(k_settings[i].name, name) == 0 && k_settings[i].default_value.kind == kind)
{
return &k_settings[i];
}
}
tf_printf("Did not find global setting of type %s: %s.\n", k_kind_name[kind], name);
return NULL;
}
bool tf_util_get_default_global_setting_bool(const char* name)
{
const setting_t* setting = _util_get_setting(name, k_kind_bool);
return setting ? setting->default_value.bool_value : false;
}
int tf_util_get_default_global_setting_int(const char* name)
{
const setting_t* setting = _util_get_setting(name, k_kind_int);
return setting ? setting->default_value.int_value : 0;
}
const char* tf_util_get_default_global_setting_string(const char* name)
{
const setting_t* setting = _util_get_setting(name, k_kind_string);
return setting && setting->default_value.string_value ? setting->default_value.string_value : "";
} }
static JSValue _util_defaultGlobalSettings(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) static JSValue _util_defaultGlobalSettings(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{ {
typedef struct _setting_t
{
const char* name;
const char* type;
const char* description;
JSValue default_value;
} setting_t;
const setting_t k_settings[] = {
{ .name = "code_of_conduct", .type = "textarea", .description = "Code of conduct presented at sign-in." },
{ .name = "blob_fetch_age_seconds",
.type = "integer",
.description = "Only blobs mentioned more recently than this age will be automatically fetched.",
.default_value = _is_mobile() ? JS_NewInt32(context, (int)(0.5f * 365 * 24 * 60 * 60)) : JS_UNDEFINED },
{ .name = "blob_expire_age_seconds",
.type = "integer",
.description = "Blobs older than this will be automatically deleted.",
.default_value = _is_mobile() ? JS_NewInt32(context, (int)(1.0f * 365 * 24 * 60 * 60)) : JS_UNDEFINED },
{ .name = "fetch_hosts", .type = "string", .description = "Comma-separated list of host names to which HTTP fetch requests are allowed. None if empty." },
{ .name = "http_redirect", .type = "string", .description = "If connecting by HTTP and HTTPS is configured, Location header prefix (ie, \"http://example.com\")" },
{ .name = "index", .type = "string", .description = "Default path.", .default_value = JS_NewString(context, "/~core/ssb/") },
{ .name = "index_map", .type = "textarea", .description = "Mappings from hostname to redirect path, one per line, as in: \"www.tildefriends.net=/~core/index/\"" },
{ .name = "peer_exchange",
.type = "boolean",
.description = "Enable discovery of, sharing of, and connecting to internet peer strangers, including announcing this instance.",
.default_value = JS_FALSE },
{ .name = "replicator", .type = "boolean", .description = "Enable message and blob replication.", .default_value = JS_TRUE },
{ .name = "room", .type = "boolean", .description = "Enable peers to tunnel through this instance as a room.", .default_value = JS_TRUE },
{ .name = "room_name", .type = "string", .description = "Name of the room.", .default_value = JS_NewString(context, "tilde friends tunnel") },
{ .name = "seeds_host", .type = "string", .description = "Hostname for seed connections.", .default_value = JS_NewString(context, "seeds.tildefriends.net") },
{ .name = "account_registration", .type = "boolean", .description = "Allow registration of new accounts.", .default_value = JS_TRUE },
{ .name = "replication_hops",
.type = "integer",
.description = "Number of hops to replicate (1 = direct follows, 2 = follows of follows, etc.).",
.default_value = JS_NewInt32(context, 2) },
{ .name = "delete_stale_feeds",
.type = "boolean",
.description = "Periodically delete feeds that aren't visible from local accounts or related follows.",
.default_value = JS_FALSE },
{ .name = "talk_to_strangers",
.type = "boolean",
.description = "Whether connections are accepted from accounts that aren't in the replication range or otherwise already known.",
.default_value = JS_TRUE },
};
JSValue settings = JS_NewObject(context); JSValue settings = JS_NewObject(context);
for (int i = 0; i < tf_countof(k_settings); i++) for (int i = 0; i < tf_countof(k_settings); i++)
{ {
JSValue entry = JS_NewObject(context); JSValue entry = JS_NewObject(context);
JS_SetPropertyStr(context, entry, "type", JS_NewString(context, k_settings[i].type)); JS_SetPropertyStr(context, entry, "type", JS_NewString(context, k_settings[i].type));
JS_SetPropertyStr(context, entry, "description", JS_NewString(context, k_settings[i].description)); JS_SetPropertyStr(context, entry, "description", JS_NewString(context, k_settings[i].description));
JS_SetPropertyStr(context, entry, "default_value", k_settings[i].default_value); switch (k_settings[i].default_value.kind)
{
case k_kind_bool:
JS_SetPropertyStr(context, entry, "default_value", JS_NewBool(context, k_settings[i].default_value.bool_value));
break;
case k_kind_int:
JS_SetPropertyStr(context, entry, "default_value", JS_NewInt32(context, k_settings[i].default_value.int_value));
break;
case k_kind_string:
JS_SetPropertyStr(
context, entry, "default_value", k_settings[i].default_value.string_value ? JS_NewString(context, k_settings[i].default_value.string_value) : JS_UNDEFINED);
break;
}
JS_SetPropertyStr(context, settings, k_settings[i].name, entry); JS_SetPropertyStr(context, settings, k_settings[i].name, entry);
} }
return settings; return settings;

View File

@ -173,4 +173,25 @@ const char* tf_util_function_to_string(void* function);
*/ */
#define tf_countof(a) ((int)(sizeof((a)) / sizeof(*(a)))) #define tf_countof(a) ((int)(sizeof((a)) / sizeof(*(a))))
/**
** Get the default value of a global setting as a boolean.
** @param name The setting name.
** @return The default value.
*/
bool tf_util_get_default_global_setting_bool(const char* name);
/**
** Get the default value of a global setting as an integer.
** @param name The setting name.
** @return The default value.
*/
int tf_util_get_default_global_setting_int(const char* name);
/**
** Get teh default value of a global setting as a string.
** @param name The setting name.
** @return The default value.
*/
const char* tf_util_get_default_global_setting_string(const char* name);
/** @} */ /** @} */

View File

@ -1,2 +1,2 @@
#define VERSION_NUMBER "0.0.27-wip" #define VERSION_NUMBER "0.0.27"
#define VERSION_NAME "This program kills fascists." #define VERSION_NAME "This program kills fascists."

View File

@ -59,7 +59,7 @@ cutoff = state.get('last_update') or (time.time() - 2 * 7 * 24 * 60 * 60)
entries = [entry for entry in get_entries() if entry[0] > cutoff] entries = [entry for entry in get_entries() if entry[0] > cutoff]
if entries: if entries:
text = '\n'.join([f' * [{entry[1]}] [{entry[3]}]({entry[2]})' for entry in entries]) text = '\n'.join([f' * **{entry[1]}** [{entry[3]}]({entry[2]})' for entry in entries])
state['last_update'] = entries[0][0] state['last_update'] = entries[0][0]
if args.state_file: if args.state_file:
content = json.dumps({'type': 'post', 'text': text, 'mentions': []}) content = json.dumps({'type': 'post', 'text': text, 'mentions': []})

View File

@ -76,8 +76,7 @@ build_the_thing() {
-Oz -Oz
-DOPENSSL_SMALL_FOOTPRINT -DOPENSSL_SMALL_FOOTPRINT
-ffunction-sections -ffunction-sections
-fdata-sections -fdata-sections"
-flto"
pwd pwd
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \ echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \ ./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
BUILD_PLATFORM=$(uname -s) BUILD_PLATFORM=$(uname -s)
if [[ -z $BUILD_TARGET ]]; then if [[ -z $BUILD_TARGET ]]; then

View File

@ -59,7 +59,6 @@ build_the_thing() {
-Os -Os
-ffunction-sections -ffunction-sections
-fdata-sections -fdata-sections
-flto
-DOPENSSL_SMALL_FOOTPRINT" -DOPENSSL_SMALL_FOOTPRINT"
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \ echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \ ./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \