Compare commits
12 Commits
66234b14bc
...
v0.0.30
Author | SHA1 | Date | |
---|---|---|---|
ddfa84f040 | |||
6b3a6ec7c1 | |||
4d037c02bf | |||
deaeab10d8 | |||
2a5375b1e7 | |||
e7a03e3283 | |||
efb3a12dcc | |||
3830d695d7 | |||
f36620927b | |||
5423cbd628 | |||
abde709e54 | |||
27f2d319ab |
@ -18,7 +18,7 @@ MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
VERSION_CODE := 35
|
||||
VERSION_CODE_IOS := 12
|
||||
VERSION_NUMBER := 0.0.30-wip
|
||||
VERSION_NUMBER := 0.0.30
|
||||
VERSION_NAME := This program kills fascists.
|
||||
|
||||
IPHONEOS_VERSION_MIN=14.0
|
||||
@ -718,12 +718,12 @@ $(SQLITE_OBJS): CFLAGS += \
|
||||
-DSQLITE_MAX_COMPOUND_SELECT=300 \
|
||||
-DSQLITE_MAX_EXPR_DEPTH=40 \
|
||||
-DSQLITE_MAX_FUNCTION_ARG=8 \
|
||||
-DSQLITE_MAX_LENGTH=5242880 \
|
||||
-DSQLITE_MAX_LENGTH=10485760 \
|
||||
-DSQLITE_MAX_LIKE_PATTERN_LENGTH=50 \
|
||||
-DSQLITE_MAX_SQL_LENGTH=100000 \
|
||||
-DSQLITE_MAX_TRIGGER_DEPTH=10 \
|
||||
-DSQLITE_MAX_VARIABLE_NUMBER=100 \
|
||||
-DSQLITE_MAX_VDBE_OP=25000 \
|
||||
-DSQLITE_MAX_VDBE_OP=50000 \
|
||||
-DSQLITE_OMIT_DEPRECATED \
|
||||
-DSQLITE_OMIT_DESERIALIZE \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "🦀",
|
||||
"previous": "&jko2iokTaY2t/pD9m4ekMr0wsLjov3LVl9ShysXEjkE=.sha256"
|
||||
"previous": "&Zv/eOewtUPxYuALmYV8v+JDKwH4+aN8zCTYFwB7oYEw=.sha256"
|
||||
}
|
||||
|
@ -318,10 +318,9 @@ class TfMessageElement extends LitElement {
|
||||
>
|
||||
+ ${this.total_child_messages(this.message) + ' More'}
|
||||
</button>
|
||||
`;
|
||||
`;
|
||||
} else {
|
||||
return html`
|
||||
<div class="w3-container w3-margin-bottom">
|
||||
return html` <div class="w3-container w3-margin-bottom">
|
||||
${repeat(
|
||||
this.message.child_messages || [],
|
||||
(x) => x.id,
|
||||
@ -342,8 +341,8 @@ class TfMessageElement extends LitElement {
|
||||
style="box-sizing: border-box"
|
||||
@click=${() => self.set_expanded(false)}
|
||||
>
|
||||
Collapse</button
|
||||
>`;
|
||||
Collapse
|
||||
</button>`;
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
@ -553,12 +552,8 @@ class TfMessageElement extends LitElement {
|
||||
`
|
||||
: undefined;
|
||||
return html`
|
||||
<div class="w3-section w3-container">
|
||||
${reply}
|
||||
</div>
|
||||
<footer>
|
||||
${this.render_children()}
|
||||
</footer>
|
||||
<div class="w3-section w3-container">${reply}</div>
|
||||
<footer>${this.render_children()}</footer>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -41,23 +41,26 @@ class TfReactionsModalElement extends LitElement {
|
||||
>
|
||||
</header>
|
||||
<ul class="w3-theme-dark w3-container w3-ul">
|
||||
${this.votes.map(
|
||||
(x) => html`
|
||||
<li class="w3-bar">
|
||||
<span class="w3-bar-item"
|
||||
>${x?.content?.vote?.expression}</span
|
||||
>
|
||||
<tf-user
|
||||
class="w3-bar-item"
|
||||
id=${x.author}
|
||||
.users=${this.users}
|
||||
></tf-user>
|
||||
<span class="w3-bar-item w3-right"
|
||||
>${new Date(x?.timestamp).toLocaleString()}</span
|
||||
>
|
||||
</li>
|
||||
`
|
||||
)}
|
||||
${this.votes
|
||||
.sort((x, y) => y.timestamp - x.timestamp)
|
||||
.map(
|
||||
(x) => html`
|
||||
<li style="display: flex; flex-direction: row; gap: 4px">
|
||||
<span style="flex-basis: 3em"
|
||||
>${x?.content?.vote?.expression}</span
|
||||
>
|
||||
<tf-user
|
||||
style="flex: 1 1"
|
||||
id=${x.author}
|
||||
.users=${this.users}
|
||||
></tf-user>
|
||||
<span
|
||||
style="flex-shrink: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis"
|
||||
>${new Date(x?.timestamp).toLocaleString()}</span
|
||||
>
|
||||
</li>
|
||||
`
|
||||
)}
|
||||
</ul>
|
||||
<footer class="w3-container w3-padding">
|
||||
<button class="w3-button" @click=${this.clear}>Close</button>
|
||||
|
@ -179,11 +179,10 @@ class TfTabNewsFeedElement extends LitElement {
|
||||
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 TRUE AS is_primary, news.* FROM 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
|
||||
ORDER BY all_news.timestamp DESC LIMIT 20
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.following),
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "💾",
|
||||
"previous": "&mvGTlWKFR5QM/3nb4fJ2WQq0n/gNKvBmhGDkAvb8ki8=.sha256"
|
||||
"previous": "&tzZFIe7Y54O4sx1QtAPdemkXh+p5qHXSG/dlS7NP6OQ=.sha256"
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ async function query(sql, args) {
|
||||
|
||||
async function get_biggest() {
|
||||
return query(`
|
||||
select author, sum(length(content)) as size from messages group by author order by size desc limit 10;
|
||||
select author, size from messages_stats group by author order by size desc limit 10;
|
||||
`);
|
||||
}
|
||||
|
||||
@ -62,15 +62,14 @@ function nice_size(bytes) {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await app.setDocument(
|
||||
'<p style="color: #fff">Finding the top 10 largest feeds...</p>'
|
||||
);
|
||||
let most_follows = await get_most_follows();
|
||||
await app.setDocument('<p style="color: #fff">Analyzing feeds...</p>');
|
||||
let most_follows = get_most_follows();
|
||||
let total = await get_total();
|
||||
let identities = await ssb.getAllIdentities();
|
||||
let following1 = await ssb.following(identities, 1);
|
||||
let following2 = await ssb.following(identities, 2);
|
||||
let biggest = await get_biggest();
|
||||
most_follows = await most_follows;
|
||||
let names = await get_names(
|
||||
[].concat(
|
||||
biggest.map((x) => x.author),
|
||||
@ -94,7 +93,7 @@ async function main() {
|
||||
}
|
||||
let html = `<body style="color: #000; background-color: #ddd">\n
|
||||
<h1>Storage Summary</h1>
|
||||
<h2>Top 10 Accounts by Size</h2>
|
||||
<h2>Top Accounts by Size</h2>
|
||||
<ol>`;
|
||||
for (let item of biggest) {
|
||||
html += `<li>
|
||||
@ -105,7 +104,7 @@ async function main() {
|
||||
}
|
||||
html += `
|
||||
</ol>
|
||||
<h2>Top 10 Accounts by Follows</h2>
|
||||
<h2>Top Accounts by Follows</h2>
|
||||
<ol>`;
|
||||
for (let item of most_follows) {
|
||||
html += `<li>
|
||||
|
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": {
|
||||
"version": "1.4.21",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.21.tgz",
|
||||
"integrity": "sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==",
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.1.tgz",
|
||||
"integrity": "sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@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"
|
||||
package="com.unprompted.tildefriends"
|
||||
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.INTERNET"/>
|
||||
<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)
|
||||
{
|
||||
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[] = {
|
||||
"Location",
|
||||
url,
|
||||
path ? path : "/~core/apps/",
|
||||
};
|
||||
tf_http_respond(request, 303, headers, tf_countof(headers) / 2, NULL, 0);
|
||||
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_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_type_author_channel_root_timestamp_index ON messages (author, timestamp, content ->> 'type', content ->> 'channel', content ->> "
|
||||
"'root')");
|
||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_root_timestamp_index ");
|
||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_channel_author_timestamp_root_index ON messages (content ->> 'channel', author, timestamp, content ->> '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_author_id_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_ssb_db_exec(db,
|
||||
"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 '@%.ed25519' "
|
||||
@ -300,7 +299,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
||||
_tf_ssb_db_exec(db,
|
||||
"CREATE TRIGGER IF NOT EXISTS messages_ai_refs AFTER INSERT ON messages BEGIN "
|
||||
"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 '@%.ed25519' "
|
||||
@ -325,7 +324,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
||||
tf_printf("Populating blobs_refs...\n");
|
||||
_tf_ssb_db_exec(db,
|
||||
"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' "
|
||||
"ON CONFLICT DO NOTHING");
|
||||
_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,
|
||||
"CREATE TRIGGER IF NOT EXISTS blobs_ai_refs AFTER INSERT ON blobs BEGIN "
|
||||
"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' "
|
||||
"ON CONFLICT DO NOTHING; END");
|
||||
_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;
|
||||
if (!result)
|
||||
{
|
||||
tf_printf("Blob store failed: %s.", 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);
|
||||
}
|
||||
|
@ -165,7 +165,8 @@ static bool _tf_ssb_register_app(tf_ssb_t* ssb, const char* user, const char* ap
|
||||
bool result = false;
|
||||
sqlite3_stmt* statement;
|
||||
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 &&
|
||||
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 _one_proc;
|
||||
bool _killed;
|
||||
bool _shutting_down;
|
||||
char _scriptName[256];
|
||||
int _global_exception_count;
|
||||
|
||||
@ -1818,6 +1819,8 @@ JSValue tf_taskstub_kill(tf_taskstub_t* stub);
|
||||
|
||||
void tf_task_destroy(tf_task_t* task)
|
||||
{
|
||||
task->_shutting_down = true;
|
||||
|
||||
while (task->_children)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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);
|
||||
|
||||
/**
|
||||
** 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)
|
||||
{
|
||||
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));
|
||||
memset(stub, 0, sizeof(*stub));
|
||||
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."
|
||||
|
Reference in New Issue
Block a user