Compare commits
40 Commits
7ef4d814ef
...
v0.0.27.1
Author | SHA1 | Date | |
---|---|---|---|
8d529327a4 | |||
697e2f2071 | |||
f7fb112f21 | |||
b2c0211190 | |||
c59e0ea6e5 | |||
6c2fc1444d | |||
94d969fe46 | |||
a7bc3d301c | |||
18bab849f7 | |||
04878fcc30 | |||
ffe1299548 | |||
64bdbf5725 | |||
b82deb557f | |||
d529a48a11 | |||
b711e4e6bd | |||
186eecfbff | |||
d766c33f59 | |||
2c9257f1a8 | |||
71ff604f90 | |||
83e00763ea | |||
5b647e0937 | |||
e0444510f4 | |||
82e876a892 | |||
c728e05032 | |||
c7a8ce7060 | |||
762b4339fe | |||
f824b8988e | |||
6280d6d167 | |||
4f18e744b4 | |||
01d8f720e8 | |||
18cf058af3 | |||
e2406df367 | |||
1fd669bdb3 | |||
f6add12c80 | |||
0f643bfe39 | |||
15be498e4b | |||
fba465dd62 | |||
19dbe354e7 | |||
fca5d37b7e | |||
aa04ad2dc2 |
21
GNUmakefile
21
GNUmakefile
@ -17,7 +17,7 @@ MAKEFLAGS += --no-builtin-rules
|
||||
## ANDROID_SDK := Path to the Android SDK.
|
||||
|
||||
VERSION_CODE := 32
|
||||
VERSION_NUMBER := 0.0.27-wip
|
||||
VERSION_NUMBER := 0.0.27
|
||||
VERSION_NAME := This program kills fascists.
|
||||
|
||||
SQLITE_URL := https://www.sqlite.org/2025/sqlite-amalgamation-3480000.zip
|
||||
@ -35,6 +35,7 @@ BUNDLETOOL = out/bundletool.jar
|
||||
|
||||
HAVE_WIN := 0
|
||||
HAVE_CROSS_AARCH64 := 0
|
||||
USE_SYSTEM_SSL := 0
|
||||
|
||||
export SOURCE_DATE_EPOCH=1
|
||||
export TZ=UTC
|
||||
@ -83,8 +84,7 @@ CFLAGS += \
|
||||
-g
|
||||
LDFLAGS += \
|
||||
-Wno-attributes \
|
||||
-Wno-aggressive-loop-optimizations \
|
||||
-flto=auto
|
||||
-Wno-aggressive-loop-optimizations
|
||||
|
||||
ANDROID_MIN_SDK_VERSION := 24
|
||||
ANDROID_TARGET_SDK_VERSION := 34
|
||||
@ -211,8 +211,7 @@ $(ANDROID_TARGETS): LDFLAGS += --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt
|
||||
$(DEBUG_TARGETS): CFLAGS += -DDEBUG -Og
|
||||
$(DEBUG_TARGETS): LDFLAGS += -Og
|
||||
$(RELEASE_TARGETS): CFLAGS += \
|
||||
-DNDEBUG \
|
||||
-flto
|
||||
-DNDEBUG
|
||||
$(ANDROID_RELEASE_TARGETS): CFLAGS += -Oz
|
||||
$(ANDROID_RELEASE_TARGETS): LDFLAGS += -Oz
|
||||
$(NONANDROID_RELEASE_TARGETS): CFLAGS += -Os
|
||||
@ -562,7 +561,6 @@ $(UV_OBJS): CFLAGS += \
|
||||
-Wno-unused-result \
|
||||
-Wno-unused-variable \
|
||||
-Wno-nonnull
|
||||
$(UV_OBJS): CFLAGS += -fno-lto
|
||||
$(filter out/win%,$(UV_OBJS)): \
|
||||
CFLAGS += \
|
||||
-Wno-cast-function-type \
|
||||
@ -1146,13 +1144,13 @@ $(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
||||
$(LOCAL_DEPS):
|
||||
+@OPTIONS=-flto tools/ssl-local
|
||||
$(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
||||
+@/usr/bin/env bash tools/ssl-local
|
||||
$(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): $(if $(USE_SYSTEM_SSL), , | $(LOCAL_DEPS))
|
||||
|
||||
ifeq ($(HAVE_CROSS_AARCH64),1)
|
||||
LOCAL_DEPS := deps/openssl/$(UNAME_S)/aarch64/usr/local/lib/libssl.a
|
||||
$(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)
|
||||
endif
|
||||
|
||||
@ -1175,7 +1173,7 @@ endif
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
||||
$(LOCAL_DEPS):
|
||||
+@OPTIONS=-flto tools/ssl-local
|
||||
+@tools/ssl-local
|
||||
$(filter $(BUILD_DIR)/macosdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/macosrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
||||
endif
|
||||
|
||||
@ -1220,7 +1218,8 @@ appimage: out/tildefriends-x86_64.AppImage ## Build an AppImage.
|
||||
.PHONY: appimage
|
||||
|
||||
flatpak: out/ ## Build a flatpak.
|
||||
flatpak-builder --force-clean --user --install-deps-from=flathub --install --repo=out/flatpak-repo out/flatpak src/com.unprompted.tildefriends.yml
|
||||
flatpak 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
|
||||
.PHONY: flatpak
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "💻",
|
||||
"previous": "&icsPplXHgmpkbNWyo/WTvRdT/A8BXxW4lJixOtP4ueQ=.sha256"
|
||||
"previous": "&sFRTDn/RpxP1NJeECXHrXKwCRUJsEOEDVaCMPl50zpM=.sha256"
|
||||
}
|
||||
|
@ -19,10 +19,6 @@ async function fetch_info(apps) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
async function fetch_shared_apps() {
|
||||
let messages = {};
|
||||
|
||||
@ -69,17 +65,17 @@ async function main() {
|
||||
const stylesheet = `
|
||||
body {
|
||||
color: whitesmoke;
|
||||
font-family: sans-serif;
|
||||
margin: 16px;
|
||||
margin: 8px;
|
||||
}
|
||||
.container {
|
||||
|
||||
.iconbox {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, 64px);
|
||||
gap: 1em;
|
||||
justify-content: space-around;
|
||||
background-color: #ffffff10;
|
||||
border: 2px solid #073642;
|
||||
border-radius: 8px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
|
||||
}
|
||||
|
||||
.iconbox::after {
|
||||
content: "";
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.app {
|
||||
@ -101,16 +97,28 @@ async function main() {
|
||||
`;
|
||||
|
||||
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 id="apps" class="container"></div>
|
||||
<div class="w3-card-4 w3-margin-top">
|
||||
<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 id="shared_apps" class="container"></div>
|
||||
<div class="w3-card-4 w3-margin-top">
|
||||
<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 id="core_apps" class="container"></div>
|
||||
<div class="w3-card-4 w3-margin-top">
|
||||
<header class="w3-container w3-light-blue">
|
||||
<h2>Core Apps</h2>
|
||||
</header>
|
||||
<div id="core_apps" class="w3-indigo iconbox"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const script = `
|
||||
@ -126,9 +134,13 @@ async function main() {
|
||||
|
||||
// For each app in the provided list
|
||||
for (let app of Object.keys(apps).sort()) {
|
||||
|
||||
// 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');
|
||||
|
||||
// The app's icon
|
||||
@ -161,12 +173,13 @@ async function main() {
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link type="text/css" rel="stylesheet" href="w3.css"></link>
|
||||
<style>
|
||||
${stylesheet}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body class="w3-darkgray">
|
||||
${body}
|
||||
</body>
|
||||
|
||||
|
235
apps/apps/w3.css
Normal file
235
apps/apps/w3.css
Normal file
@ -0,0 +1,235 @@
|
||||
/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */
|
||||
html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
|
||||
/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */
|
||||
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
|
||||
article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}
|
||||
audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
|
||||
audio:not([controls]){display:none;height:0}[hidden],template{display:none}
|
||||
a{background-color:transparent}a:active,a:hover{outline-width:0}
|
||||
abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
|
||||
b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000}
|
||||
small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||||
sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}
|
||||
code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
|
||||
button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold}
|
||||
button,input{overflow:visible}button,select{text-transform:none}
|
||||
button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}
|
||||
button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}
|
||||
button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}
|
||||
fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
|
||||
legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
|
||||
[type=checkbox],[type=radio]{padding:0}
|
||||
[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
|
||||
[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
|
||||
[type=search]::-webkit-search-decoration{-webkit-appearance:none}
|
||||
::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
|
||||
/* End extract */
|
||||
html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
|
||||
h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}
|
||||
.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace}
|
||||
h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
|
||||
hr{border:0;border-top:1px solid #eee;margin:20px 0}
|
||||
.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit}
|
||||
.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
|
||||
.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
|
||||
.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
|
||||
.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
|
||||
.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
|
||||
.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
|
||||
.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
|
||||
.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
|
||||
.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
||||
.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
|
||||
.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
|
||||
.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
|
||||
.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
|
||||
.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
|
||||
.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
|
||||
.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
|
||||
.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
|
||||
.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
|
||||
.w3-dropdown-hover:hover .w3-dropdown-content{display:block}
|
||||
.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
|
||||
.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
|
||||
.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1}
|
||||
.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
|
||||
.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
|
||||
.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
|
||||
.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
|
||||
.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
|
||||
.w3-main,#main{transition:margin-left .4s}
|
||||
.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
|
||||
.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
|
||||
.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
|
||||
.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0}
|
||||
.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
|
||||
.w3-bar .w3-button{white-space:normal}
|
||||
.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
|
||||
.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
|
||||
.w3-responsive{display:block;overflow-x:auto}
|
||||
.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
|
||||
.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
|
||||
.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
|
||||
.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
|
||||
.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
|
||||
.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
|
||||
@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
|
||||
.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
|
||||
.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
|
||||
@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
|
||||
.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
|
||||
.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
|
||||
.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px}
|
||||
.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px}
|
||||
.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
|
||||
.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
|
||||
.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
|
||||
@media (max-width:1205px){.w3-auto{max-width:95%}}
|
||||
@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
|
||||
.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}
|
||||
.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
|
||||
.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
|
||||
@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
|
||||
@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
|
||||
@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
|
||||
@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}}
|
||||
.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
|
||||
.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
|
||||
.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
|
||||
.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
|
||||
.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
|
||||
.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
|
||||
.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
|
||||
.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
|
||||
.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
|
||||
.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
|
||||
.w3-display-position{position:absolute}
|
||||
.w3-circle{border-radius:50%}
|
||||
.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
|
||||
.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
|
||||
.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px}
|
||||
.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
|
||||
.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
|
||||
.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
|
||||
.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
|
||||
.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
|
||||
.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
|
||||
.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
|
||||
.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
|
||||
.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
|
||||
.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
|
||||
.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
|
||||
.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
|
||||
.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
|
||||
.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
|
||||
.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
|
||||
.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
|
||||
.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
|
||||
.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
|
||||
.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
|
||||
.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
|
||||
.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
|
||||
.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
|
||||
.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
|
||||
.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
|
||||
.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
|
||||
.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
|
||||
.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
|
||||
.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
|
||||
.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
|
||||
.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
|
||||
.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
|
||||
.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
|
||||
.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
|
||||
.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
|
||||
.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important}
|
||||
.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important}
|
||||
.w3-left{float:left!important}.w3-right{float:right!important}
|
||||
.w3-button:hover{color:#000!important;background-color:#ccc!important}
|
||||
.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
|
||||
.w3-hover-none:hover{box-shadow:none!important}
|
||||
/* Colors */
|
||||
.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
|
||||
.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
|
||||
.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
|
||||
.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
|
||||
.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
|
||||
.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
|
||||
.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
|
||||
.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
|
||||
.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
|
||||
.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
|
||||
.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
|
||||
.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
|
||||
.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
|
||||
.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
|
||||
.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
|
||||
.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
|
||||
.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
|
||||
.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
|
||||
.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
|
||||
.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
|
||||
.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
|
||||
.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
|
||||
.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
|
||||
.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important}
|
||||
.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
|
||||
.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
|
||||
.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
|
||||
.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
|
||||
.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
|
||||
.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
|
||||
.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
|
||||
.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
|
||||
.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
|
||||
.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
|
||||
.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
|
||||
.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
|
||||
.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important}
|
||||
.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
|
||||
.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
|
||||
.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
|
||||
.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
|
||||
.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
|
||||
.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
|
||||
.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
|
||||
.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
|
||||
.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
|
||||
.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
|
||||
.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
|
||||
.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
|
||||
.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
|
||||
.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
|
||||
.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
|
||||
.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
|
||||
.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
|
||||
.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
|
||||
.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
|
||||
.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important}
|
||||
.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important}
|
||||
.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
|
||||
.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important}
|
||||
.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important}
|
||||
.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important}
|
||||
.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important}
|
||||
.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
|
||||
.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important}
|
||||
.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important}
|
||||
.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important}
|
||||
.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important}
|
||||
.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important}
|
||||
.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important}
|
||||
.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important}
|
||||
.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important}
|
||||
.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important}
|
||||
.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
|
||||
.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important}
|
||||
.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important}
|
||||
.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
|
||||
.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
|
||||
.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
|
||||
.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important}
|
||||
.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important}
|
||||
.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important}
|
||||
.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important}
|
||||
.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "🦀",
|
||||
"previous": "&J6o2XRWWAirhnQbEa6Pi0QvAex6jTH1o23npX7x82aY=.sha256"
|
||||
"previous": "&m5ZrkzoyAjv7AY6AukzVoWIyUFUL97uuDDWCtxCloAU=.sha256"
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ export async function picker(callback, anchor, author) {
|
||||
<div class="w3-modal-content w3-card-4">
|
||||
<div
|
||||
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">
|
||||
<h1>Choose a Reaction</h1>
|
||||
|
@ -402,10 +402,9 @@ class TfElement extends LitElement {
|
||||
async fetch_user_info(users) {
|
||||
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
|
||||
ON messages.author = following.value
|
||||
GROUP BY messages.author
|
||||
ON messages_stats.author = following.value
|
||||
`,
|
||||
[JSON.stringify(Object.keys(users))]
|
||||
);
|
||||
@ -438,10 +437,11 @@ class TfElement extends LitElement {
|
||||
(await tfrpc.rpc.databaseGet('unread')) ?? '{}'
|
||||
);
|
||||
this.following = Object.keys(following);
|
||||
let about_start_time = new Date();
|
||||
users = await this.fetch_about(following, users);
|
||||
console.log(
|
||||
'about took',
|
||||
(new Date() - start_time) / 1000.0,
|
||||
(new Date() - about_start_time) / 1000.0,
|
||||
'seconds for',
|
||||
Object.keys(users).length,
|
||||
'users'
|
||||
|
@ -57,15 +57,14 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
JOIN json_each(?2) AS following ON messages.author = following.value
|
||||
WHERE
|
||||
messages.author != ?1 AND
|
||||
messages.timestamp >= ?3 AND
|
||||
messages.timestamp < ?4
|
||||
(?3 IS NULL OR messages.timestamp >= ?3) AND messages.timestamp < ?4
|
||||
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
|
||||
JOIN messages_refs ON mentions.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT * FROM mentions
|
||||
SELECT TRUE AS is_primary, * FROM mentions
|
||||
`,
|
||||
[
|
||||
'"' + this.whoami.replace('"', '""') + '"',
|
||||
@ -77,33 +76,29 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
} else if (this.hash.startsWith('#@')) {
|
||||
result = await tfrpc.rpc.query(
|
||||
`
|
||||
WITH mine AS (SELECT rowid, id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||
FROM messages
|
||||
WHERE messages.author = ?
|
||||
ORDER BY sequence DESC)
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM mine
|
||||
JOIN messages_refs ON mine.id = messages_refs.ref
|
||||
WITH
|
||||
selected AS (SELECT rowid, id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||
FROM messages
|
||||
WHERE messages.author = ?1 AND (?2 IS NULL OR messages.timestamp >= 2) AND messages.timestamp < ?3
|
||||
ORDER BY sequence DESC LIMIT 20
|
||||
)
|
||||
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
|
||||
WHERE
|
||||
messages.timestamp >= ?2 AND
|
||||
messages.timestamp < ?3
|
||||
UNION
|
||||
SELECT * FROM mine
|
||||
WHERE
|
||||
mine.timestamp >= ?2 AND
|
||||
mine.timestamp < ?3
|
||||
SELECT TRUE AS is_primary, * FROM selected
|
||||
`,
|
||||
[this.hash.substring(1), start_time, end_time]
|
||||
);
|
||||
} else if (this.hash.startsWith('#%')) {
|
||||
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
|
||||
WHERE messages.id = ?1
|
||||
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
|
||||
ON messages.id = messages_refs.message
|
||||
WHERE messages_refs.ref = ?1
|
||||
@ -111,112 +106,98 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
[this.hash.substring(1)]
|
||||
);
|
||||
} else if (this.hash.startsWith('##')) {
|
||||
let promises = [];
|
||||
const k_following_limit = 256;
|
||||
for (let i = 0; i < this.following.length; i += k_following_limit) {
|
||||
promises.push(
|
||||
tfrpc.rpc.query(
|
||||
`
|
||||
WITH news AS (SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE
|
||||
messages.timestamp >= ? AND
|
||||
messages.timestamp < ? AND
|
||||
messages.content ->> 'channel' = ?
|
||||
ORDER BY messages.timestamp DESC)
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
UNION
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages_fts(?5)
|
||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||
JOIN json_each(?1) AS following ON messages.author = following.value
|
||||
JOIN json_tree(messages.content, '$.mentions') AS mention ON mention.value = '#' || ?4
|
||||
WHERE
|
||||
messages.timestamp >= ?2 AND
|
||||
messages.timestamp < ?3
|
||||
UNION
|
||||
SELECT news.* FROM news
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.following.slice(i, i + k_following_limit)),
|
||||
start_time,
|
||||
end_time,
|
||||
this.hash.substring(2),
|
||||
'"#' + this.hash.substring(2).replace('"', '""') + '"',
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
result = [].concat(...(await Promise.all(promises)));
|
||||
result = await tfrpc.rpc.query(
|
||||
`
|
||||
WITH
|
||||
all_news AS (
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE messages.content ->> 'channel' = ?4
|
||||
UNION
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages_fts(?5)
|
||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||
JOIN json_each(?1) AS following ON messages.author = following.value
|
||||
JOIN json_tree(messages.content, '$.mentions') AS mention ON mention.value = '#' || ?4),
|
||||
news AS (SELECT * FROM all_news
|
||||
WHERE (?2 IS NULL OR all_news.timestamp >= ?2) AND all_news.timestamp < ?3
|
||||
ORDER BY all_news.timestamp DESC LIMIT 20)
|
||||
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 news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
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 news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
UNION
|
||||
SELECT TRUE AS is_primary, news.* FROM news
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.following),
|
||||
start_time,
|
||||
end_time,
|
||||
this.hash.substring(2),
|
||||
'"#' + this.hash.substring(2).replace('"', '""') + '"',
|
||||
]
|
||||
);
|
||||
} else if (this.hash == '#🔐') {
|
||||
result = await tfrpc.rpc.query(
|
||||
`
|
||||
SELECT messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||
FROM messages
|
||||
JOIN json_each(?1) AS following ON messages.author = following.value
|
||||
WHERE
|
||||
messages.timestamp >= ?2 AND
|
||||
messages.timestamp < ?3 AND
|
||||
json(messages.content) LIKE '"%'
|
||||
ORDER BY sequence DESC
|
||||
SELECT TRUE AS is_primary, messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||
FROM messages
|
||||
JOIN json_each(?1) AS following ON messages.author = following.value
|
||||
WHERE
|
||||
(?2 IS NULL OR (messages.timestamp >= ?2)) AND messages.timestamp < ?3 AND
|
||||
json(messages.content) LIKE '"%'
|
||||
ORDER BY messages.sequence DESC LIMIT 20
|
||||
`,
|
||||
[JSON.stringify(this.following), start_time, end_time]
|
||||
);
|
||||
result = (await this.decrypt(result)).filter((x) => x.decrypted);
|
||||
} else {
|
||||
let promises = [];
|
||||
const k_following_limit = 256;
|
||||
for (let i = 0; i < this.following.length; i += k_following_limit) {
|
||||
promises.push(
|
||||
tfrpc.rpc.query(
|
||||
`
|
||||
WITH news AS (SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE messages.timestamp >= ? AND messages.timestamp < ?
|
||||
ORDER BY messages.timestamp DESC)
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
UNION
|
||||
SELECT news.* FROM news
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.following.slice(i, i + k_following_limit)),
|
||||
start_time,
|
||||
end_time,
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
result = [].concat(...(await Promise.all(promises)));
|
||||
result = await tfrpc.rpc.query(
|
||||
`
|
||||
WITH
|
||||
all_news AS (
|
||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE timestamp >= 0 AND timestamp < ?3),
|
||||
news AS (
|
||||
SELECT * FROM all_news
|
||||
WHERE (?2 IS NULL OR all_news.timestamp >= ?2) AND all_news.timestamp < ?3
|
||||
ORDER BY timestamp DESC LIMIT 20
|
||||
)
|
||||
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 news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
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 news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
UNION
|
||||
SELECT TRUE AS is_primary, news.* FROM news
|
||||
`,
|
||||
[JSON.stringify(this.following), start_time, end_time]
|
||||
);
|
||||
}
|
||||
this.time_loading = undefined;
|
||||
return result;
|
||||
}
|
||||
|
||||
update_time_range_from_messages(messages) {
|
||||
let only_primary = messages.filter((x) => x.is_primary);
|
||||
this.time_range = [
|
||||
messages.reduce(
|
||||
only_primary.reduce(
|
||||
(accumulator, current) => Math.min(accumulator, current.timestamp),
|
||||
this.time_range[0]
|
||||
),
|
||||
messages.reduce(
|
||||
only_primary.reduce(
|
||||
(accumulator, current) => Math.max(accumulator, current.timestamp),
|
||||
this.time_range[1]
|
||||
),
|
||||
@ -228,17 +209,11 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
this.loading_canceled = false;
|
||||
try {
|
||||
let more = [];
|
||||
while (!more.length && !this.loading_canceled) {
|
||||
let last_start_time = this.start_time;
|
||||
this.start_time = last_start_time - 7 * 24 * 60 * 60 * 1000;
|
||||
more = await this.fetch_messages(this.start_time, last_start_time);
|
||||
this.update_time_range_from_messages(
|
||||
more.filter(
|
||||
(x) =>
|
||||
x.timestamp >= this.start_time && x.timestamp < last_start_time
|
||||
)
|
||||
);
|
||||
}
|
||||
let last_start_time = this.time_range[0];
|
||||
more = await this.fetch_messages(null, last_start_time);
|
||||
this.update_time_range_from_messages(
|
||||
more.filter((x) => x.timestamp < last_start_time)
|
||||
);
|
||||
this.messages = await this.decrypt([...more, ...this.messages]);
|
||||
} finally {
|
||||
this.loading--;
|
||||
@ -285,14 +260,11 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
let end_time = now + 24 * 60 * 60 * 1000;
|
||||
let messages = [];
|
||||
try {
|
||||
messages = await this.fetch_messages(
|
||||
this.time_range[1] - 24 * 60 * 60 * 1000,
|
||||
end_time
|
||||
);
|
||||
messages = await this.fetch_messages(this.time_range[0], end_time);
|
||||
messages = await this.decrypt(messages);
|
||||
this.update_time_range_from_messages(
|
||||
messages.filter(
|
||||
(x) => x.timestamp >= this.time_range[1] && x.timestamp < end_time
|
||||
(x) => x.timestamp >= this.time_range[0] && x.timestamp < end_time
|
||||
)
|
||||
);
|
||||
} finally {
|
||||
@ -313,6 +285,7 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
}
|
||||
|
||||
async load_messages() {
|
||||
let start_time = new Date();
|
||||
let self = this;
|
||||
this.loading++;
|
||||
let messages = [];
|
||||
@ -326,38 +299,19 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
let start_time = now - 24 * 60 * 60 * 1000;
|
||||
this.start_time = start_time;
|
||||
this.time_range = [this.start_time, now + 24 * 60 * 60 * 1000];
|
||||
messages = await this.fetch_messages(
|
||||
this.time_range[0],
|
||||
this.time_range[1]
|
||||
);
|
||||
messages = await this.fetch_messages(null, this.time_range[1]);
|
||||
this.update_time_range_from_messages(
|
||||
messages.filter(
|
||||
(x) =>
|
||||
x.timestamp >= this.time_range[0] &&
|
||||
x.timestamp < this.time_range[1]
|
||||
)
|
||||
messages.filter((x) => x.timestamp < this.time_range[1])
|
||||
);
|
||||
messages = await this.decrypt(messages);
|
||||
if (!messages.length) {
|
||||
let more = [];
|
||||
while (!more.length && start_time >= 0) {
|
||||
let last_start_time = start_time;
|
||||
start_time = last_start_time - 7 * 24 * 60 * 60 * 1000;
|
||||
more = await this.fetch_messages(start_time, last_start_time);
|
||||
this.update_time_range_from_messages(
|
||||
more.filter(
|
||||
(x) => x.timestamp >= start_time && x.timestamp < last_start_time
|
||||
)
|
||||
);
|
||||
}
|
||||
messages = await this.decrypt([...more, ...this.messages]);
|
||||
}
|
||||
} finally {
|
||||
this.loading--;
|
||||
}
|
||||
this.messages = this.merge_messages(this.messages, messages);
|
||||
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() {
|
||||
|
@ -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 {styles} from './tf-styles.js';
|
||||
|
||||
@ -216,16 +223,18 @@ class TfTabNewsElement extends LitElement {
|
||||
)}
|
||||
|
||||
<h4 class="w3-bar-item w3-theme-d2">Connections</h4>
|
||||
${this.connections.map(
|
||||
(x) => html`
|
||||
<tf-user
|
||||
class="w3-bar-item"
|
||||
style="max-width: 100%"
|
||||
id=${x.id}
|
||||
.users=${this.users}
|
||||
></tf-user>
|
||||
`
|
||||
)}
|
||||
${this.connections
|
||||
.filter((x) => x.id && !x.destroy_reason)
|
||||
.map(
|
||||
(x) => html`
|
||||
<tf-user
|
||||
class="w3-bar-item"
|
||||
style="max-width: 100%"
|
||||
id=${x.id}
|
||||
.users=${this.users}
|
||||
></tf-user>
|
||||
`
|
||||
)}
|
||||
<h4 class="w3-bar-item w3-theme-d2">Suggested Follows</h4>
|
||||
${this.suggested_follows().map(
|
||||
(x) => html`
|
||||
@ -249,12 +258,15 @@ class TfTabNewsElement extends LitElement {
|
||||
render() {
|
||||
let profile =
|
||||
this.hash.startsWith('#@') && this.hash != '#@'
|
||||
? html`<tf-profile
|
||||
class="tf-profile"
|
||||
id=${this.hash.substring(1)}
|
||||
whoami=${this.whoami}
|
||||
.users=${this.users}
|
||||
></tf-profile>`
|
||||
? keyed(
|
||||
this.hash.substring(1),
|
||||
html`<tf-profile
|
||||
class="tf-profile"
|
||||
id=${this.hash.substring(1)}
|
||||
whoami=${this.whoami}
|
||||
.users=${this.users}
|
||||
></tf-profile>`
|
||||
)
|
||||
: undefined;
|
||||
let edit_profile;
|
||||
if (
|
||||
|
@ -20,7 +20,8 @@ class TfUserElement extends LitElement {
|
||||
|
||||
render() {
|
||||
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
|
||||
class=${'w3-theme-l4 ' + shape}
|
||||
style="display: inline-block; width: 2em; height: 2em; text-align: center; line-height: 2em"
|
||||
|
@ -21,14 +21,14 @@
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation rec {
|
||||
pname = "tildefriends";
|
||||
version = "0.0.26";
|
||||
version = "0.0.27";
|
||||
|
||||
src = pkgs.fetchFromGitea {
|
||||
domain = "dev.tildefriends.net";
|
||||
owner = "cory";
|
||||
repo = "tildefriends";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-XJ7M++risfsRn9GkS1zjTQpqqV5S09uyimeVzU9hGGg=";
|
||||
hash = "sha256-NhoTBWYsWc206f1+M9haxHSJU6ZSGoP5nPStymAIyRk=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
@ -46,7 +46,7 @@ pkgs.stdenv.mkDerivation rec {
|
||||
];
|
||||
|
||||
buildPhase = ''
|
||||
make -j $NIX_BUILD_CORES release
|
||||
make -j $NIX_BUILD_CORES release USE_SYSTEM_SSL=1
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
|
2
deps/codemirror/cm6.js
vendored
2
deps/codemirror/cm6.js
vendored
File diff suppressed because one or more lines are too long
270
deps/codemirror_src/package-lock.json
generated
vendored
270
deps/codemirror_src/package-lock.json
generated
vendored
@ -22,7 +22,6 @@
|
||||
"version": "6.18.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz",
|
||||
"integrity": "sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
@ -34,7 +33,6 @@
|
||||
"version": "6.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.0.tgz",
|
||||
"integrity": "sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
@ -46,7 +44,6 @@
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz",
|
||||
"integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
@ -59,7 +56,6 @@
|
||||
"version": "6.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz",
|
||||
"integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/lang-css": "^6.0.0",
|
||||
@ -76,7 +72,6 @@
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
|
||||
"integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
@ -91,7 +86,6 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
|
||||
"integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/json": "^1.0.0"
|
||||
@ -101,7 +95,6 @@
|
||||
"version": "6.10.8",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.8.tgz",
|
||||
"integrity": "sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.23.0",
|
||||
@ -115,7 +108,6 @@
|
||||
"version": "6.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.4.tgz",
|
||||
"integrity": "sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.35.0",
|
||||
@ -126,7 +118,6 @@
|
||||
"version": "6.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz",
|
||||
"integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
@ -137,7 +128,6 @@
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.1.tgz",
|
||||
"integrity": "sha512-3rA9lcwciEB47ZevqvD8qgbzhM9qMb8vCcQCNmDfVRPQG4JT9mSb0Jg8H7YjKGGQcFnLN323fj9jdnG59Kx6bg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@marijn/find-cluster-break": "^1.0.0"
|
||||
}
|
||||
@ -146,7 +136,6 @@
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
|
||||
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
@ -158,7 +147,6 @@
|
||||
"version": "6.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.2.tgz",
|
||||
"integrity": "sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.5.0",
|
||||
"style-mod": "^4.1.0",
|
||||
@ -170,7 +158,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
||||
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
@ -185,7 +172,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -195,7 +181,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -205,7 +190,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25"
|
||||
@ -215,15 +199,13 @@
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
@ -232,14 +214,12 @@
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
|
||||
},
|
||||
"node_modules/@lezer/css": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.9.tgz",
|
||||
"integrity": "sha512-TYwgljcDv+YrV0MZFFvYFQHCfGgbPMR6nuqLabBdmZoFH3EP1gvw8t0vae326Ne3PszQkbXfVBjCnf3ZVCr0bA==",
|
||||
"license": "MIT",
|
||||
"version": "1.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.10.tgz",
|
||||
"integrity": "sha512-V5/89eDapjeAkWPBpWEfQjZ1Hag3aYUUJOL8213X0dFRuXJ4BXa5NKl9USzOnaLod4AOpmVCkduir2oKwZYZtg==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@ -250,7 +230,6 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
|
||||
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
@ -259,7 +238,6 @@
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz",
|
||||
"integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@ -270,7 +248,6 @@
|
||||
"version": "1.4.21",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.21.tgz",
|
||||
"integrity": "sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.1.3",
|
||||
@ -281,7 +258,6 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz",
|
||||
"integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@ -292,7 +268,6 @@
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
|
||||
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
@ -300,14 +275,12 @@
|
||||
"node_modules/@marijn/find-cluster-break": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
|
||||
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g=="
|
||||
},
|
||||
"node_modules/@rollup/plugin-node-resolve": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz",
|
||||
"integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1",
|
||||
"@types/resolve": "1.20.2",
|
||||
@ -332,7 +305,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
|
||||
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"serialize-javascript": "^6.0.1",
|
||||
"smob": "^1.0.0",
|
||||
@ -354,7 +326,6 @@
|
||||
"version": "5.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz",
|
||||
"integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
@ -373,247 +344,228 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.30.1.tgz",
|
||||
"integrity": "sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.1.tgz",
|
||||
"integrity": "sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.30.1.tgz",
|
||||
"integrity": "sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.1.tgz",
|
||||
"integrity": "sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.30.1.tgz",
|
||||
"integrity": "sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.1.tgz",
|
||||
"integrity": "sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.30.1.tgz",
|
||||
"integrity": "sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.1.tgz",
|
||||
"integrity": "sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.30.1.tgz",
|
||||
"integrity": "sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.1.tgz",
|
||||
"integrity": "sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.30.1.tgz",
|
||||
"integrity": "sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.1.tgz",
|
||||
"integrity": "sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.30.1.tgz",
|
||||
"integrity": "sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.1.tgz",
|
||||
"integrity": "sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.30.1.tgz",
|
||||
"integrity": "sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.1.tgz",
|
||||
"integrity": "sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.30.1.tgz",
|
||||
"integrity": "sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.1.tgz",
|
||||
"integrity": "sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.30.1.tgz",
|
||||
"integrity": "sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.1.tgz",
|
||||
"integrity": "sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.30.1.tgz",
|
||||
"integrity": "sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.1.tgz",
|
||||
"integrity": "sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.30.1.tgz",
|
||||
"integrity": "sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.1.tgz",
|
||||
"integrity": "sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.30.1.tgz",
|
||||
"integrity": "sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.1.tgz",
|
||||
"integrity": "sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.30.1.tgz",
|
||||
"integrity": "sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.1.tgz",
|
||||
"integrity": "sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.30.1.tgz",
|
||||
"integrity": "sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.1.tgz",
|
||||
"integrity": "sha512-WQFLZ9c42ECqEjwg/GHHsouij3pzLXkFdz0UxHa/0OM12LzvX7DzedlY0SIEly2v18YZLRhCRoHZDxbBSWoGYg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.30.1.tgz",
|
||||
"integrity": "sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.1.tgz",
|
||||
"integrity": "sha512-BLoiyHDOWoS3uccNSADMza6V6vCNiphi94tQlVIL5de+r6r/CCQuNnerf+1g2mnk2b6edp5dk0nhdZ7aEjOBsA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.30.1.tgz",
|
||||
"integrity": "sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.1.tgz",
|
||||
"integrity": "sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.30.1.tgz",
|
||||
"integrity": "sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.1.tgz",
|
||||
"integrity": "sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.30.1.tgz",
|
||||
"integrity": "sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.1.tgz",
|
||||
"integrity": "sha512-ar80GhdZb4DgmW3myIS9nRFYcpJRSME8iqWgzH2i44u+IdrzmiXVxeFnExQ5v4JYUSpg94bWjevMG8JHf1Da5Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
@ -622,21 +574,18 @@
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@ -648,14 +597,12 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/codemirror": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
|
||||
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/commands": "^6.0.0",
|
||||
@ -670,20 +617,17 @@
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -691,15 +635,13 @@
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
@ -712,7 +654,6 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
@ -721,7 +662,6 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
@ -733,7 +673,6 @@
|
||||
"version": "2.16.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
@ -747,20 +686,17 @@
|
||||
"node_modules/is-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -773,7 +709,6 @@
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
@ -782,7 +717,6 @@
|
||||
"version": "1.22.10",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.16.0",
|
||||
"path-parse": "^1.0.7",
|
||||
@ -799,10 +733,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.30.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.1.tgz",
|
||||
"integrity": "sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==",
|
||||
"license": "MIT",
|
||||
"version": "4.32.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.1.tgz",
|
||||
"integrity": "sha512-z+aeEsOeEa3mEbS1Tjl6sAZ8NE3+AalQz1RJGj81M+fizusbdDMoEJwdJNHfaB40Scr4qNu+welOfes7maKonA==",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.6"
|
||||
},
|
||||
@ -814,25 +747,25 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.30.1",
|
||||
"@rollup/rollup-android-arm64": "4.30.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.30.1",
|
||||
"@rollup/rollup-darwin-x64": "4.30.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.30.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.30.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.30.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.30.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.30.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.30.1",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.30.1",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.30.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.30.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.30.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.30.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.30.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.30.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.30.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.30.1",
|
||||
"@rollup/rollup-android-arm-eabi": "4.32.1",
|
||||
"@rollup/rollup-android-arm64": "4.32.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.32.1",
|
||||
"@rollup/rollup-darwin-x64": "4.32.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.32.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.32.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.32.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.32.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.32.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.32.1",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.32.1",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.32.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.32.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.32.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.32.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.32.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.32.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.32.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.32.1",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
@ -854,15 +787,13 @@
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
]
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
@ -871,15 +802,13 @@
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
|
||||
"integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -889,7 +818,6 @@
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
@ -898,14 +826,12 @@
|
||||
"node_modules/style-mod": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
|
||||
},
|
||||
"node_modules/supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@ -918,7 +844,6 @@
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
|
||||
"integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
@ -935,8 +860,7 @@
|
||||
"node_modules/w3c-keyname": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
* Loading screen.
|
||||
* Removed "server follow me."
|
||||
* Added various CLI commands.
|
||||
* Updated dependencies:
|
||||
* Cross-compile for aarch64.
|
||||
* Added CLI commands.
|
||||
* SSB
|
||||
* 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
|
||||
* libuv 1.50.0
|
||||
* speedscope 1.22.0
|
||||
* sqlite 3.48.0
|
||||
|
1
package-lock.json
generated
1
package-lock.json
generated
@ -14,7 +14,6 @@
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
|
||||
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
|
@ -2,7 +2,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.unprompted.tildefriends"
|
||||
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.INTERNET"/>
|
||||
<application
|
||||
|
@ -1,6 +1,6 @@
|
||||
id: com.unprompted.tildefriends
|
||||
runtime: org.freedesktop.Platform
|
||||
runtime-version: '23.08'
|
||||
runtime-version: '24.08'
|
||||
sdk: org.freedesktop.Sdk
|
||||
command: tildefriends-run.sh
|
||||
finish-args:
|
||||
|
77
src/ssb.c
77
src/ssb.c
@ -245,6 +245,7 @@ typedef struct _tf_ssb_t
|
||||
bool is_room;
|
||||
bool is_replicator;
|
||||
bool is_peer_exchange;
|
||||
bool talk_to_strangers;
|
||||
char* room_name;
|
||||
char seeds_host[256];
|
||||
time_t last_seed_check;
|
||||
@ -278,6 +279,8 @@ typedef struct _tf_ssb_connection_t
|
||||
uv_timer_t linger_timer;
|
||||
uv_timer_t activity_timer;
|
||||
bool is_closing;
|
||||
bool is_pending_stranger_check;
|
||||
bool is_stranger;
|
||||
|
||||
tf_ssb_connection_t* tunnel_connection;
|
||||
int32_t tunnel_request_number;
|
||||
@ -374,6 +377,8 @@ static void _tf_ssb_start_update_settings(tf_ssb_t* ssb);
|
||||
static void _tf_ssb_update_settings(tf_ssb_t* ssb);
|
||||
static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t size);
|
||||
static void _tf_ssb_connection_dispatch_scheduled(tf_ssb_connection_t* connection);
|
||||
static bool _tf_ssb_connection_read_start(tf_ssb_connection_t* connection);
|
||||
static bool _tf_ssb_connection_read_stop(tf_ssb_connection_t* connection);
|
||||
|
||||
static const char* _tf_ssb_connection_state_to_string(tf_ssb_state_t state)
|
||||
{
|
||||
@ -1403,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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -1418,6 +1423,52 @@ static bool _tf_ssb_is_already_connected(tf_ssb_t* ssb, uint8_t* id, tf_ssb_conn
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _tf_ssb_connection_is_account_a_stranger_work(tf_ssb_connection_t* connection, void* user_data)
|
||||
{
|
||||
tf_ssb_t* ssb = connection->ssb;
|
||||
char id[k_id_base64_len] = { 0 };
|
||||
tf_ssb_id_bin_to_str(id, sizeof(id), connection->serverpub);
|
||||
if (tf_ssb_db_get_latest_message_by_author(ssb, id, NULL, NULL, 0))
|
||||
{
|
||||
connection->is_stranger = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t replication_hops = 2;
|
||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||
tf_ssb_db_get_global_setting_int64(db, "replication_hops", &replication_hops);
|
||||
tf_ssb_release_db_reader(ssb, db);
|
||||
|
||||
const char** identities = tf_ssb_db_get_all_visible_identities(ssb, replication_hops);
|
||||
for (int i = 0; identities[i]; i++)
|
||||
{
|
||||
if (strcmp(id, identities[i]) == 0)
|
||||
{
|
||||
connection->is_stranger = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
tf_free((void*)identities);
|
||||
}
|
||||
}
|
||||
|
||||
static void _tf_ssb_connection_is_account_a_stranger_after_work(tf_ssb_connection_t* connection, int status, void* user_data)
|
||||
{
|
||||
connection->is_pending_stranger_check = false;
|
||||
if (connection->is_stranger && !connection->ssb->talk_to_strangers)
|
||||
{
|
||||
tf_ssb_connection_close(connection, "Account is a stranger");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connection->tcp.data)
|
||||
{
|
||||
_tf_ssb_connection_read_start(connection);
|
||||
}
|
||||
_tf_ssb_notify_connections_changed(connection->ssb, k_tf_ssb_change_connect, connection);
|
||||
}
|
||||
}
|
||||
|
||||
static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* connection, const uint8_t* message, size_t len)
|
||||
{
|
||||
uint8_t nonce[crypto_secretbox_NONCEBYTES] = { 0 };
|
||||
@ -1598,7 +1649,14 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne
|
||||
{
|
||||
uv_timer_stop(&connection->handshake_timer);
|
||||
}
|
||||
_tf_ssb_notify_connections_changed(connection->ssb, k_tf_ssb_change_connect, connection);
|
||||
|
||||
connection->is_pending_stranger_check = true;
|
||||
connection->is_stranger = true;
|
||||
if (connection->tcp.data)
|
||||
{
|
||||
_tf_ssb_connection_read_stop(connection);
|
||||
}
|
||||
tf_ssb_connection_run_work(connection, _tf_ssb_connection_is_account_a_stranger_work, _tf_ssb_connection_is_account_a_stranger_after_work, NULL);
|
||||
}
|
||||
|
||||
static bool _tf_ssb_connection_recv_pop(tf_ssb_connection_t* connection, uint8_t* buffer, size_t size)
|
||||
@ -2197,6 +2255,8 @@ static bool _tf_ssb_connection_read_start(tf_ssb_connection_t* connection)
|
||||
tf_ssb_connection_close(connection, reason);
|
||||
return false;
|
||||
}
|
||||
/* Process anything that might have already been queued before we stopped reading. */
|
||||
uv_async_send(&connection->async);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2795,10 +2855,13 @@ static void _tf_ssb_connection_finalizer(JSRuntime* runtime, JSValue value)
|
||||
static void _tf_ssb_connection_process_message_async(uv_async_t* async)
|
||||
{
|
||||
tf_ssb_connection_t* connection = async->data;
|
||||
/* The receive may initiate a close, so this order is important. */
|
||||
if (_tf_ssb_connection_box_stream_recv(connection) && !connection->is_closing)
|
||||
if (!connection->is_pending_stranger_check)
|
||||
{
|
||||
uv_async_send(&connection->async);
|
||||
/* The receive may initiate a close, so this order is important. */
|
||||
if (_tf_ssb_connection_box_stream_recv(connection) && !connection->is_closing)
|
||||
{
|
||||
uv_async_send(&connection->async);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4324,6 +4387,7 @@ typedef struct _update_settings_t
|
||||
bool is_room;
|
||||
bool is_replicator;
|
||||
bool is_peer_exchange;
|
||||
bool talk_to_strangers;
|
||||
char seeds_host[256];
|
||||
char room_name[1024];
|
||||
} update_settings_t;
|
||||
@ -4335,9 +4399,11 @@ static void _tf_ssb_update_settings_work(tf_ssb_t* ssb, void* user_data)
|
||||
update->is_room = true;
|
||||
update->is_replicator = true;
|
||||
update->is_peer_exchange = true;
|
||||
update->talk_to_strangers = true;
|
||||
tf_ssb_db_get_global_setting_bool(db, "room", &update->is_room);
|
||||
tf_ssb_db_get_global_setting_bool(db, "replicator", &update->is_replicator);
|
||||
tf_ssb_db_get_global_setting_bool(db, "peer_exchange", &update->is_peer_exchange);
|
||||
tf_ssb_db_get_global_setting_bool(db, "talk_to_strangers", &update->talk_to_strangers);
|
||||
tf_ssb_db_get_global_setting_string(db, "room_name", update->room_name, sizeof(update->room_name));
|
||||
tf_ssb_db_get_global_setting_string(db, "seeds_host", update->seeds_host, sizeof(update->seeds_host));
|
||||
tf_ssb_release_db_reader(ssb, db);
|
||||
@ -4350,6 +4416,7 @@ static void _tf_ssb_update_settings_after_work(tf_ssb_t* ssb, int result, void*
|
||||
tf_ssb_set_room_name(ssb, update->room_name);
|
||||
tf_ssb_set_is_peer_exchange(ssb, update->is_peer_exchange);
|
||||
tf_ssb_set_is_replicator(ssb, update->is_replicator);
|
||||
ssb->talk_to_strangers = update->talk_to_strangers;
|
||||
snprintf(ssb->seeds_host, sizeof(ssb->seeds_host), "%s", update->seeds_host);
|
||||
_tf_ssb_start_update_settings(ssb);
|
||||
tf_free(update);
|
||||
|
69
src/ssb.db.c
69
src/ssb.db.c
@ -108,6 +108,24 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
||||
" flags INTEGER,"
|
||||
" 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'"))
|
||||
{
|
||||
@ -987,8 +1005,9 @@ int tf_ssb_sqlite_authorizer(void* user_data, int action_code, const char* arg0,
|
||||
break;
|
||||
case SQLITE_READ:
|
||||
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_refs_message_idx") == 0 || strcmp(arg0, "messages_refs_ref_idx") == 0 || strcmp(arg0, "sqlite_master") == 0 || false)
|
||||
strcmp(arg0, "messages_stats") == 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_refs_message_idx") == 0 ||
|
||||
strcmp(arg0, "messages_refs_ref_idx") == 0 || strcmp(arg0, "sqlite_master") == 0 || false)
|
||||
? SQLITE_OK
|
||||
: SQLITE_DENY;
|
||||
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));
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
*out_value = tf_util_get_default_global_setting_bool(name);
|
||||
}
|
||||
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));
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
*out_value = tf_util_get_default_global_setting_int(name);
|
||||
}
|
||||
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));
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
snprintf(out_value, size, "%s", tf_util_get_default_global_setting_string(name));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2148,6 +2179,33 @@ const char* tf_ssb_db_get_profile_name(sqlite3* db, const char* id)
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _tf_ssb_db_invite_cleanup(sqlite3* db)
|
||||
{
|
||||
sqlite3_stmt* statement;
|
||||
if (sqlite3_prepare(db, "DELETE FROM invites WHERE use_count = 0 OR expires < ?", -1, &statement, NULL) == SQLITE_OK)
|
||||
{
|
||||
if (sqlite3_bind_int64(statement, 1, (int64_t)time(NULL)) == SQLITE_OK)
|
||||
{
|
||||
if (sqlite3_step(statement) == SQLITE_DONE)
|
||||
{
|
||||
if (sqlite3_changes(db))
|
||||
{
|
||||
tf_printf("Cleaned up %d used/expired invites.\n", sqlite3_changes(db));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_printf("Invite cleanup failed: %s\n", sqlite3_errmsg(db));
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
||||
}
|
||||
}
|
||||
|
||||
bool tf_ssb_db_generate_invite(sqlite3* db, const char* id, const char* host, int port, int use_count, int expires_seconds, char* out_invite, size_t size)
|
||||
{
|
||||
if (use_count < -1 || use_count == 0)
|
||||
@ -2180,6 +2238,8 @@ bool tf_ssb_db_generate_invite(sqlite3* db, const char* id, const char* host, in
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
|
||||
_tf_ssb_db_invite_cleanup(db);
|
||||
|
||||
snprintf(out_invite, size, "%s:%d:%s~%s", host, port, id, seed_b64);
|
||||
return inserted;
|
||||
}
|
||||
@ -2188,7 +2248,7 @@ bool tf_ssb_db_use_invite(sqlite3* db, const char* id)
|
||||
{
|
||||
bool used = false;
|
||||
sqlite3_stmt* statement;
|
||||
if (sqlite3_prepare(db, "UPDATE invites SET use_count = use_count - 1 WHERE invite_public_key = ? AND expires > ? AND (use_count > 0 OR use_count = -1)", -1, &statement,
|
||||
if (sqlite3_prepare(db, "UPDATE invites SET use_count = use_count - 1 WHERE invite_public_key = ? AND expires >= ? AND (use_count > 0 OR use_count = -1)", -1, &statement,
|
||||
NULL) == SQLITE_OK)
|
||||
{
|
||||
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, (int64_t)time(NULL)) == SQLITE_OK)
|
||||
@ -2197,5 +2257,8 @@ bool tf_ssb_db_use_invite(sqlite3* db, const char* id)
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
|
||||
_tf_ssb_db_invite_cleanup(db);
|
||||
|
||||
return used;
|
||||
}
|
||||
|
11
src/ssb.db.h
11
src/ssb.db.h
@ -524,6 +524,17 @@ bool tf_ssb_db_generate_invite(sqlite3* db, const char* id, const char* host, in
|
||||
*/
|
||||
bool tf_ssb_db_use_invite(sqlite3* db, const char* id);
|
||||
|
||||
/**
|
||||
** Determine if an account is familiar, meaning it is local or within the given
|
||||
** follow depth of the local accounts or we have already replicated data for
|
||||
** it.
|
||||
** @param db The database.
|
||||
** @param id The identity.
|
||||
** @param depth The follow depth.
|
||||
** @return true if the account is familiar.
|
||||
*/
|
||||
bool tf_ssb_db_is_account_familiar(sqlite3* db, const char* id, int depth);
|
||||
|
||||
/**
|
||||
** An SQLite authorizer callback. See https://www.sqlite.org/c3ref/set_authorizer.html for use.
|
||||
** @param user_data User data registered with the authorizer.
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
||||
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(
|
||||
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 }
|
||||
**
|
||||
** 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)
|
||||
|
@ -1371,7 +1371,7 @@ void tf_ssb_test_invite(const tf_test_options_t* options)
|
||||
tf_printf("waiting for messages\n");
|
||||
tf_ssb_set_main_thread(ssb0, true);
|
||||
tf_ssb_set_main_thread(ssb1, true);
|
||||
while (count0 != 1 || count1 != 1)
|
||||
while (count0 != 3 || count1 != 3)
|
||||
{
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
}
|
||||
|
24
src/trace.c
24
src/trace.c
@ -34,6 +34,7 @@ typedef struct _tf_trace_stack_t
|
||||
typedef struct _tf_trace_thread_t
|
||||
{
|
||||
pthread_t id;
|
||||
int index;
|
||||
tf_trace_stack_t* stack;
|
||||
char name[64];
|
||||
} 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_trace_thread_t) {
|
||||
.id = self,
|
||||
.index = trace->threads_count,
|
||||
};
|
||||
#if defined(__linux__) && !defined(__ANDROID__)
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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->tags[stack->count] = tag;
|
||||
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_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];
|
||||
stack->count--;
|
||||
}
|
||||
*out_thread = thread;
|
||||
return name;
|
||||
}
|
||||
|
||||
@ -265,11 +269,11 @@ static void _tf_trace_begin_tagged(tf_trace_t* trace, const char* name, void* ta
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_t self = pthread_self();
|
||||
_tf_push_stack(trace, self, name, tag);
|
||||
tf_trace_thread_t* thread = NULL;
|
||||
_tf_push_stack(trace, pthread_self(), name, tag, &thread);
|
||||
|
||||
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 += snprintf(line + p, sizeof(line) - p, "\"},");
|
||||
p = tf_min(p, tf_countof(line));
|
||||
@ -288,15 +292,15 @@ static void _tf_trace_end_tagged(tf_trace_t* trace, void* tag)
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_t self = pthread_self();
|
||||
const char* name = _tf_pop_stack(trace, self, tag);
|
||||
tf_trace_thread_t* thread = NULL;
|
||||
const char* name = _tf_pop_stack(trace, pthread_self(), tag, &thread);
|
||||
if (!name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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 += snprintf(line + p, sizeof(line) - p, "\"},");
|
||||
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++)
|
||||
{
|
||||
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(),
|
||||
(uint64_t)thread->id, thread->name);
|
||||
size += snprintf(buffer + size, k_buffer_size - size, "{\"ph\":\"M\",\"pid\":%d,\"tid\":%d,\"name\":\"thread_name\",\"args\":{\"name\":\"%s\"}},\n", getpid(),
|
||||
thread->index, thread->name);
|
||||
}
|
||||
uv_rwlock_rdunlock(&trace->threads_lock);
|
||||
if (begin)
|
||||
|
184
src/util.js.c
184
src/util.js.c
@ -20,6 +20,16 @@
|
||||
#include <execinfo.h>
|
||||
#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)
|
||||
{
|
||||
size_t length = 0;
|
||||
@ -304,69 +314,139 @@ static JSValue _util_parseHttpResponse(JSContext* context, JSValueConst this_val
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
static bool _is_mobile()
|
||||
typedef enum _value_kind_t
|
||||
{
|
||||
#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IPHONE)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
k_kind_bool,
|
||||
k_kind_int,
|
||||
k_kind_string,
|
||||
} value_kind_t;
|
||||
|
||||
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)
|
||||
{
|
||||
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 },
|
||||
};
|
||||
|
||||
JSValue settings = JS_NewObject(context);
|
||||
for (int i = 0; i < tf_countof(k_settings); i++)
|
||||
{
|
||||
JSValue entry = JS_NewObject(context);
|
||||
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, "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);
|
||||
}
|
||||
return settings;
|
||||
|
@ -173,4 +173,25 @@ const char* tf_util_function_to_string(void* function);
|
||||
*/
|
||||
#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);
|
||||
|
||||
/** @} */
|
||||
|
@ -1,2 +1,2 @@
|
||||
#define VERSION_NUMBER "0.0.27-wip"
|
||||
#define VERSION_NUMBER "0.0.27"
|
||||
#define VERSION_NAME "This program kills fascists."
|
||||
|
@ -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]
|
||||
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]
|
||||
if args.state_file:
|
||||
content = json.dumps({'type': 'post', 'text': text, 'mentions': []})
|
||||
|
@ -76,8 +76,7 @@ build_the_thing() {
|
||||
-Oz
|
||||
-DOPENSSL_SMALL_FOOTPRINT
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-flto"
|
||||
-fdata-sections"
|
||||
pwd
|
||||
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
|
||||
./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BUILD_PLATFORM=$(uname -s)
|
||||
if [[ -z $BUILD_TARGET ]]; then
|
||||
|
@ -59,7 +59,6 @@ build_the_thing() {
|
||||
-Os
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-flto
|
||||
-DOPENSSL_SMALL_FOOTPRINT"
|
||||
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
|
||||
./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \
|
||||
|
Reference in New Issue
Block a user