Compare commits
10 Commits
abde709e54
...
v0.0.30
Author | SHA1 | Date | |
---|---|---|---|
ddfa84f040 | |||
6b3a6ec7c1 | |||
4d037c02bf | |||
deaeab10d8 | |||
2a5375b1e7 | |||
e7a03e3283 | |||
efb3a12dcc | |||
3830d695d7 | |||
f36620927b | |||
5423cbd628 |
@@ -18,7 +18,7 @@ MAKEFLAGS += --no-builtin-rules
|
|||||||
|
|
||||||
VERSION_CODE := 35
|
VERSION_CODE := 35
|
||||||
VERSION_CODE_IOS := 12
|
VERSION_CODE_IOS := 12
|
||||||
VERSION_NUMBER := 0.0.30-wip
|
VERSION_NUMBER := 0.0.30
|
||||||
VERSION_NAME := This program kills fascists.
|
VERSION_NAME := This program kills fascists.
|
||||||
|
|
||||||
IPHONEOS_VERSION_MIN=14.0
|
IPHONEOS_VERSION_MIN=14.0
|
||||||
@@ -718,12 +718,12 @@ $(SQLITE_OBJS): CFLAGS += \
|
|||||||
-DSQLITE_MAX_COMPOUND_SELECT=300 \
|
-DSQLITE_MAX_COMPOUND_SELECT=300 \
|
||||||
-DSQLITE_MAX_EXPR_DEPTH=40 \
|
-DSQLITE_MAX_EXPR_DEPTH=40 \
|
||||||
-DSQLITE_MAX_FUNCTION_ARG=8 \
|
-DSQLITE_MAX_FUNCTION_ARG=8 \
|
||||||
-DSQLITE_MAX_LENGTH=5242880 \
|
-DSQLITE_MAX_LENGTH=10485760 \
|
||||||
-DSQLITE_MAX_LIKE_PATTERN_LENGTH=50 \
|
-DSQLITE_MAX_LIKE_PATTERN_LENGTH=50 \
|
||||||
-DSQLITE_MAX_SQL_LENGTH=100000 \
|
-DSQLITE_MAX_SQL_LENGTH=100000 \
|
||||||
-DSQLITE_MAX_TRIGGER_DEPTH=10 \
|
-DSQLITE_MAX_TRIGGER_DEPTH=10 \
|
||||||
-DSQLITE_MAX_VARIABLE_NUMBER=100 \
|
-DSQLITE_MAX_VARIABLE_NUMBER=100 \
|
||||||
-DSQLITE_MAX_VDBE_OP=25000 \
|
-DSQLITE_MAX_VDBE_OP=50000 \
|
||||||
-DSQLITE_OMIT_DEPRECATED \
|
-DSQLITE_OMIT_DEPRECATED \
|
||||||
-DSQLITE_OMIT_DESERIALIZE \
|
-DSQLITE_OMIT_DESERIALIZE \
|
||||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🦀",
|
"emoji": "🦀",
|
||||||
"previous": "&jko2iokTaY2t/pD9m4ekMr0wsLjov3LVl9ShysXEjkE=.sha256"
|
"previous": "&Zv/eOewtUPxYuALmYV8v+JDKwH4+aN8zCTYFwB7oYEw=.sha256"
|
||||||
}
|
}
|
||||||
|
@@ -41,18 +41,21 @@ class TfReactionsModalElement extends LitElement {
|
|||||||
>
|
>
|
||||||
</header>
|
</header>
|
||||||
<ul class="w3-theme-dark w3-container w3-ul">
|
<ul class="w3-theme-dark w3-container w3-ul">
|
||||||
${this.votes.map(
|
${this.votes
|
||||||
|
.sort((x, y) => y.timestamp - x.timestamp)
|
||||||
|
.map(
|
||||||
(x) => html`
|
(x) => html`
|
||||||
<li class="w3-bar">
|
<li style="display: flex; flex-direction: row; gap: 4px">
|
||||||
<span class="w3-bar-item"
|
<span style="flex-basis: 3em"
|
||||||
>${x?.content?.vote?.expression}</span
|
>${x?.content?.vote?.expression}</span
|
||||||
>
|
>
|
||||||
<tf-user
|
<tf-user
|
||||||
class="w3-bar-item"
|
style="flex: 1 1"
|
||||||
id=${x.author}
|
id=${x.author}
|
||||||
.users=${this.users}
|
.users=${this.users}
|
||||||
></tf-user>
|
></tf-user>
|
||||||
<span class="w3-bar-item w3-right"
|
<span
|
||||||
|
style="flex-shrink: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis"
|
||||||
>${new Date(x?.timestamp).toLocaleString()}</span
|
>${new Date(x?.timestamp).toLocaleString()}</span
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
@@ -179,11 +179,10 @@ class TfTabNewsFeedElement extends LitElement {
|
|||||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||||
JOIN json_each(?1) AS following ON messages.author = following.value
|
JOIN json_each(?1) AS following ON messages.author = following.value
|
||||||
JOIN json_tree(messages.content, '$.mentions') AS mention ON mention.value = '#' || ?4
|
JOIN json_tree(messages.content, '$.mentions') AS mention ON mention.value = '#' || ?4
|
||||||
),
|
)
|
||||||
news AS (SELECT * FROM all_news
|
SELECT TRUE AS is_primary, all_news.* FROM all_news
|
||||||
WHERE (?2 IS NULL OR all_news.timestamp >= ?2) AND all_news.timestamp < ?3
|
WHERE (?2 IS NULL OR all_news.timestamp >= ?2) AND all_news.timestamp < ?3
|
||||||
ORDER BY all_news.timestamp DESC LIMIT 20)
|
ORDER BY all_news.timestamp DESC LIMIT 20
|
||||||
SELECT TRUE AS is_primary, news.* FROM news
|
|
||||||
`,
|
`,
|
||||||
[
|
[
|
||||||
JSON.stringify(this.following),
|
JSON.stringify(this.following),
|
||||||
|
2
deps/codemirror/cm6.js
vendored
2
deps/codemirror/cm6.js
vendored
File diff suppressed because one or more lines are too long
6
deps/codemirror_src/package-lock.json
generated
vendored
6
deps/codemirror_src/package-lock.json
generated
vendored
@@ -245,9 +245,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/javascript": {
|
"node_modules/@lezer/javascript": {
|
||||||
"version": "1.4.21",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.21.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.1.tgz",
|
||||||
"integrity": "sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==",
|
"integrity": "sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.2.0",
|
"@lezer/common": "^1.2.0",
|
||||||
"@lezer/highlight": "^1.1.3",
|
"@lezer/highlight": "^1.1.3",
|
||||||
|
12
metadata/en-US/changelogs/35.txt
Normal file
12
metadata/en-US/changelogs/35.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
* Faster loads.
|
||||||
|
* Replication fixes.
|
||||||
|
* Shutdown fixes.
|
||||||
|
* Consolidated message actions into a % menu.
|
||||||
|
* Fixed and tested handling of user permissions.
|
||||||
|
* Add a very work in progress "web" app.
|
||||||
|
* Updates:
|
||||||
|
* CodeMirror
|
||||||
|
* Lit 3.3.0
|
||||||
|
* OpenSSL 3.5.0
|
||||||
|
* c-ares 1.34.5
|
||||||
|
* libbacktrace
|
@@ -2,7 +2,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.unprompted.tildefriends"
|
package="com.unprompted.tildefriends"
|
||||||
android:versionCode="35"
|
android:versionCode="35"
|
||||||
android:versionName="0.0.30-wip">
|
android:versionName="0.0.30">
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<application
|
<application
|
||||||
|
@@ -1486,17 +1486,9 @@ static void _httpd_endpoint_delete(tf_http_request_t* request)
|
|||||||
static void _httpd_endpoint_root_callback(const char* path, void* user_data)
|
static void _httpd_endpoint_root_callback(const char* path, void* user_data)
|
||||||
{
|
{
|
||||||
tf_http_request_t* request = user_data;
|
tf_http_request_t* request = user_data;
|
||||||
const char* host = tf_http_request_get_header(request, "x-forwarded-host");
|
|
||||||
if (!host)
|
|
||||||
{
|
|
||||||
host = tf_http_request_get_header(request, "host");
|
|
||||||
}
|
|
||||||
|
|
||||||
char url[1024];
|
|
||||||
snprintf(url, sizeof(url), "%s%s%s", request->is_tls ? "https://" : "http://", host, path ? path : "/~core/apps/");
|
|
||||||
const char* headers[] = {
|
const char* headers[] = {
|
||||||
"Location",
|
"Location",
|
||||||
url,
|
path ? path : "/~core/apps/",
|
||||||
};
|
};
|
||||||
tf_http_respond(request, 303, headers, tf_countof(headers) / 2, NULL, 0);
|
tf_http_respond(request, 303, headers, tf_countof(headers) / 2, NULL, 0);
|
||||||
tf_http_request_unref(request);
|
tf_http_request_unref(request);
|
||||||
|
15
src/ssb.db.c
15
src/ssb.db.c
@@ -196,9 +196,8 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
|||||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_timestamp_index ON messages (timestamp)");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_timestamp_index ON messages (timestamp)");
|
||||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_type_timestamp_index ON messages (content ->> 'type', timestamp)");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_type_timestamp_index ON messages (content ->> 'type', timestamp)");
|
||||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_size_by_author_index ON messages (author, length(content))");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_size_by_author_index ON messages (author, length(content))");
|
||||||
_tf_ssb_db_exec(db,
|
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_root_timestamp_index ");
|
||||||
"CREATE INDEX IF NOT EXISTS messages_type_author_channel_root_timestamp_index ON messages (author, timestamp, content ->> 'type', content ->> 'channel', content ->> "
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_channel_author_timestamp_root_index ON messages (content ->> 'channel', author, timestamp, content ->> 'root')");
|
||||||
"'root')");
|
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_index");
|
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_index");
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_author_id_index");
|
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_author_id_index");
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_by_author_index");
|
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_by_author_index");
|
||||||
@@ -287,7 +286,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
|||||||
tf_printf("Populating messages_refs...\n");
|
tf_printf("Populating messages_refs...\n");
|
||||||
_tf_ssb_db_exec(db,
|
_tf_ssb_db_exec(db,
|
||||||
"INSERT INTO messages_refs(message, ref) "
|
"INSERT INTO messages_refs(message, ref) "
|
||||||
"SELECT messages.id, j.value FROM messages, json_tree(messages.content) as j WHERE "
|
"SELECT messages.id, j.value FROM messages, json_tree(messages.content) AS j WHERE "
|
||||||
"j.value LIKE '&%.sha256' OR "
|
"j.value LIKE '&%.sha256' OR "
|
||||||
"j.value LIKE '%%%.sha256' OR "
|
"j.value LIKE '%%%.sha256' OR "
|
||||||
"j.value LIKE '@%.ed25519' "
|
"j.value LIKE '@%.ed25519' "
|
||||||
@@ -300,7 +299,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
|||||||
_tf_ssb_db_exec(db,
|
_tf_ssb_db_exec(db,
|
||||||
"CREATE TRIGGER IF NOT EXISTS messages_ai_refs AFTER INSERT ON messages BEGIN "
|
"CREATE TRIGGER IF NOT EXISTS messages_ai_refs AFTER INSERT ON messages BEGIN "
|
||||||
"INSERT INTO messages_refs(message, ref) "
|
"INSERT INTO messages_refs(message, ref) "
|
||||||
"SELECT DISTINCT new.id, j.value FROM json_tree(new.content) as j WHERE "
|
"SELECT DISTINCT new.id, j.value FROM json_tree(new.content) AS j WHERE "
|
||||||
"j.value LIKE '&%.sha256' OR "
|
"j.value LIKE '&%.sha256' OR "
|
||||||
"j.value LIKE '%%%.sha256' OR "
|
"j.value LIKE '%%%.sha256' OR "
|
||||||
"j.value LIKE '@%.ed25519' "
|
"j.value LIKE '@%.ed25519' "
|
||||||
@@ -325,7 +324,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
|||||||
tf_printf("Populating blobs_refs...\n");
|
tf_printf("Populating blobs_refs...\n");
|
||||||
_tf_ssb_db_exec(db,
|
_tf_ssb_db_exec(db,
|
||||||
"INSERT INTO blobs_refs(blob, ref) "
|
"INSERT INTO blobs_refs(blob, ref) "
|
||||||
"SELECT blobs.id, j.value FROM blobs, json_tree(blobs.content) as j WHERE "
|
"SELECT blobs.id, j.value FROM blobs, json_tree(blobs.content) AS j WHERE "
|
||||||
"json_valid(blobs.content) AND j.value LIKE '&%.sha256' "
|
"json_valid(blobs.content) AND j.value LIKE '&%.sha256' "
|
||||||
"ON CONFLICT DO NOTHING");
|
"ON CONFLICT DO NOTHING");
|
||||||
_tf_ssb_db_exec(db, "COMMIT TRANSACTION");
|
_tf_ssb_db_exec(db, "COMMIT TRANSACTION");
|
||||||
@@ -335,7 +334,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
|||||||
_tf_ssb_db_exec(db,
|
_tf_ssb_db_exec(db,
|
||||||
"CREATE TRIGGER IF NOT EXISTS blobs_ai_refs AFTER INSERT ON blobs BEGIN "
|
"CREATE TRIGGER IF NOT EXISTS blobs_ai_refs AFTER INSERT ON blobs BEGIN "
|
||||||
"INSERT INTO blobs_refs(blob, ref) "
|
"INSERT INTO blobs_refs(blob, ref) "
|
||||||
"SELECT DISTINCT new.id, j.value FROM json_tree(new.content) as j WHERE "
|
"SELECT DISTINCT new.id, j.value FROM json_tree(new.content) AS j WHERE "
|
||||||
"json_valid(new.content) AND j.value LIKE '&%.sha256' "
|
"json_valid(new.content) AND j.value LIKE '&%.sha256' "
|
||||||
"ON CONFLICT DO NOTHING; END");
|
"ON CONFLICT DO NOTHING; END");
|
||||||
_tf_ssb_db_exec(db, "DROP TRIGGER IF EXISTS blobs_ad_refs");
|
_tf_ssb_db_exec(db, "DROP TRIGGER IF EXISTS blobs_ad_refs");
|
||||||
@@ -950,7 +949,7 @@ bool tf_ssb_db_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char*
|
|||||||
result = r == SQLITE_DONE;
|
result = r == SQLITE_DONE;
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
tf_printf("Blob store failed: %s.\n", sqlite3_errmsg(db));
|
tf_printf("Blob store failed (%s: %zd): %s / %s.\n", id, size, sqlite3_errstr(r), sqlite3_errmsg(db));
|
||||||
}
|
}
|
||||||
rows = sqlite3_changes(db);
|
rows = sqlite3_changes(db);
|
||||||
}
|
}
|
||||||
|
@@ -165,7 +165,8 @@ static bool _tf_ssb_register_app(tf_ssb_t* ssb, const char* user, const char* ap
|
|||||||
bool result = false;
|
bool result = false;
|
||||||
sqlite3_stmt* statement;
|
sqlite3_stmt* statement;
|
||||||
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
|
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
|
||||||
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES (?1, 'path:' || ?2, ?3)", -1, &statement, NULL) == SQLITE_OK)
|
if (sqlite3_prepare(db, "INSERT INTO properties (id, key, value) VALUES (?1, 'path:' || ?2, ?3) ON CONFLICT DO UPDATE SET value = excluded.value WHERE value != excluded.value",
|
||||||
|
-1, &statement, NULL) == SQLITE_OK)
|
||||||
{
|
{
|
||||||
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, app, -1, NULL) == SQLITE_OK &&
|
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, app, -1, NULL) == SQLITE_OK &&
|
||||||
sqlite3_bind_text(statement, 3, id, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_DONE)
|
sqlite3_bind_text(statement, 3, id, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_DONE)
|
||||||
|
@@ -119,6 +119,7 @@ typedef struct _tf_task_t
|
|||||||
bool _trusted;
|
bool _trusted;
|
||||||
bool _one_proc;
|
bool _one_proc;
|
||||||
bool _killed;
|
bool _killed;
|
||||||
|
bool _shutting_down;
|
||||||
char _scriptName[256];
|
char _scriptName[256];
|
||||||
int _global_exception_count;
|
int _global_exception_count;
|
||||||
|
|
||||||
@@ -1818,6 +1819,8 @@ JSValue tf_taskstub_kill(tf_taskstub_t* stub);
|
|||||||
|
|
||||||
void tf_task_destroy(tf_task_t* task)
|
void tf_task_destroy(tf_task_t* task)
|
||||||
{
|
{
|
||||||
|
task->_shutting_down = true;
|
||||||
|
|
||||||
while (task->_children)
|
while (task->_children)
|
||||||
{
|
{
|
||||||
for (task_child_node_t* node = task->_children; node; node = node->next)
|
for (task_child_node_t* node = task->_children; node; node = node->next)
|
||||||
@@ -2162,6 +2165,11 @@ void tf_task_set_android_service_callbacks(tf_android_start_service_t* start_ser
|
|||||||
s_android_stop_service = stop_service;
|
s_android_stop_service = stop_service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tf_task_is_shutting_down(tf_task_t* task)
|
||||||
|
{
|
||||||
|
return task && task->_shutting_down;
|
||||||
|
}
|
||||||
|
|
||||||
tf_android_start_service_t* tf_task_get_android_start_service()
|
tf_android_start_service_t* tf_task_get_android_start_service()
|
||||||
{
|
{
|
||||||
return s_android_start_service;
|
return s_android_start_service;
|
||||||
|
@@ -364,4 +364,11 @@ tf_android_stop_service_t* tf_task_get_android_stop_service();
|
|||||||
*/
|
*/
|
||||||
void tf_task_check_jobs(tf_task_t* task);
|
void tf_task_check_jobs(tf_task_t* task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Check whether tf_task_destroy has been called already.
|
||||||
|
** @param task The task.
|
||||||
|
** @return true if the task is in the process of shutting down.
|
||||||
|
*/
|
||||||
|
bool tf_task_is_shutting_down(tf_task_t* task);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@@ -125,6 +125,11 @@ static void _tf_taskstub_packetstream_close(void* user_data)
|
|||||||
static JSValue _taskstub_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
static JSValue _taskstub_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
{
|
{
|
||||||
tf_task_t* parent = tf_task_get(context);
|
tf_task_t* parent = tf_task_get(context);
|
||||||
|
if (parent && tf_task_is_shutting_down(parent))
|
||||||
|
{
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
tf_taskstub_t* stub = tf_malloc(sizeof(tf_taskstub_t));
|
tf_taskstub_t* stub = tf_malloc(sizeof(tf_taskstub_t));
|
||||||
memset(stub, 0, sizeof(*stub));
|
memset(stub, 0, sizeof(*stub));
|
||||||
stub->_stream = tf_packetstream_create();
|
stub->_stream = tf_packetstream_create();
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
#define VERSION_NUMBER "0.0.30-wip"
|
#define VERSION_NUMBER "0.0.30"
|
||||||
#define VERSION_NAME "This program kills fascists."
|
#define VERSION_NAME "This program kills fascists."
|
||||||
|
Reference in New Issue
Block a user