Compare commits
3 Commits
0ec862eaac
...
bc3fd57d7a
| Author | SHA1 | Date | |
|---|---|---|---|
| bc3fd57d7a | |||
| fa4ef3b082 | |||
| 0827718d68 |
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🎛",
|
"emoji": "🎛",
|
||||||
"previous": "&kmKNyb/uaXNb24gCinJtfS8iWx4cLUWdtl0y2DwEUas=.sha256"
|
"previous": "&bRhS1LQIH8WQjbBfQqdhjLv7tqDdHT7IEPyCmj39b+4=.sha256"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,20 @@ tfrpc.register(function global_settings_set(key, value) {
|
|||||||
return core.globalSettingsSet(key, value);
|
return core.globalSettingsSet(key, value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tfrpc.register(function addBlock(id) {
|
||||||
|
return ssb.addBlock(id);
|
||||||
|
});
|
||||||
|
tfrpc.register(function removeBlock(id) {
|
||||||
|
return ssb.removeBlock(id);
|
||||||
|
});
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
let data = {
|
let data = {
|
||||||
users: {},
|
users: {},
|
||||||
granted: await core.allPermissionsGranted(),
|
granted: await core.allPermissionsGranted(),
|
||||||
settings: await core.globalSettingsDescriptions(),
|
settings: await core.globalSettingsDescriptions(),
|
||||||
|
blocks: await ssb.getBlocks(),
|
||||||
};
|
};
|
||||||
for (let user of await core.users()) {
|
for (let user of await core.users()) {
|
||||||
data.users[user] = await core.permissionsForUser(user);
|
data.users[user] = await core.permissionsForUser(user);
|
||||||
|
|||||||
@@ -16,6 +16,14 @@ function delete_user(user) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function add_block() {
|
||||||
|
await tfrpc.rpc.addBlock(document.getElementById('add_block').value);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function remove_block(id) {
|
||||||
|
await tfrpc.rpc.removeBlock(id);
|
||||||
|
}
|
||||||
|
|
||||||
function global_settings_set(key, value) {
|
function global_settings_set(key, value) {
|
||||||
tfrpc.rpc
|
tfrpc.rpc
|
||||||
.global_settings_set(key, value)
|
.global_settings_set(key, value)
|
||||||
@@ -94,11 +102,32 @@ ${description.value}</textarea
|
|||||||
${user}: ${permissions.map((x) => permission_template(x))}
|
${user}: ${permissions.map((x) => permission_template(x))}
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
|
const block_template = (block) => html`
|
||||||
|
<li class="w3-card w3-margin">
|
||||||
|
<button
|
||||||
|
class="w3-button w3-theme-action"
|
||||||
|
@click=${(e) => remove_block(block.id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
<code>${block.id}</code>
|
||||||
|
${new Date(block.timestamp)}
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
const users_template = (users) =>
|
const users_template = (users) =>
|
||||||
html` <header class="w3-container w3-theme-l2"><h2>Users</h2></header>
|
html` <header class="w3-container w3-theme-l2"><h2>Users</h2></header>
|
||||||
<ul class="w3-ul">
|
<ul class="w3-ul">
|
||||||
${Object.entries(users).map((u) => user_template(u[0], u[1]))}
|
${Object.entries(users).map((u) => user_template(u[0], u[1]))}
|
||||||
</ul>`;
|
</ul>`;
|
||||||
|
const blocks_template = (blocks) =>
|
||||||
|
html` <header class="w3-container w3-theme-l2"><h2>Blocks</h2></header>
|
||||||
|
<div class="w3-row w3-margin">
|
||||||
|
<input type="text" class="w3-threequarter w3-input" id="add_block"></input>
|
||||||
|
<button class="w3-quarter w3-button w3-theme-action" @click=${add_block}>Add</button>
|
||||||
|
</div>
|
||||||
|
<ul class="w3-ul">
|
||||||
|
${blocks.map((b) => block_template(b))}
|
||||||
|
</ul>`;
|
||||||
const page_template = (data) =>
|
const page_template = (data) =>
|
||||||
html`<div style="padding: 0; margin: 0; width: 100%; max-width: 100%">
|
html`<div style="padding: 0; margin: 0; width: 100%; max-width: 100%">
|
||||||
<header class="w3-container w3-theme-l2"><h2>Global Settings</h2></header>
|
<header class="w3-container w3-theme-l2"><h2>Global Settings</h2></header>
|
||||||
@@ -109,7 +138,7 @@ ${description.value}</textarea
|
|||||||
.map((x) => html`${input_template(x, data.settings[x])}`)}
|
.map((x) => html`${input_template(x, data.settings[x])}`)}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
${users_template(data.users)}
|
${users_template(data.users)} ${blocks_template(data.blocks)}
|
||||||
</div> `;
|
</div> `;
|
||||||
render(page_template(g_data), document.body);
|
render(page_template(g_data), document.body);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🦀",
|
"emoji": "🦀",
|
||||||
"previous": "&g0o5rMFQcyi3GwyWGrSQcQPPABae0yrUpVehztef3XE=.sha256"
|
"previous": "&E7oElXjP2g+Xb8dhrRyTVdv8EJArjJRvgmfl1prtciw=.sha256"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,6 +196,26 @@ class TfMessageElement extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flag(event) {
|
||||||
|
let reason = prompt(
|
||||||
|
'What is the reason for reporting this content (spam, nsfw, ...)?',
|
||||||
|
'offensive'
|
||||||
|
);
|
||||||
|
if (reason !== undefined) {
|
||||||
|
tfrpc.rpc
|
||||||
|
.appendMessage(this.whoami, {
|
||||||
|
type: 'flag',
|
||||||
|
flag: {
|
||||||
|
link: this.message.id,
|
||||||
|
reason: reason.length ? reason : undefined,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
alert(error?.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
show_image(link) {
|
show_image(link) {
|
||||||
let div = document.createElement('div');
|
let div = document.createElement('div');
|
||||||
div.style.left = 0;
|
div.style.left = 0;
|
||||||
@@ -505,6 +525,12 @@ class TfMessageElement extends LitElement {
|
|||||||
>
|
>
|
||||||
👍 React
|
👍 React
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="w3-button w3-bar-item w3-border-bottom"
|
||||||
|
@click=${this.flag}
|
||||||
|
>
|
||||||
|
⚠️ Flag
|
||||||
|
</button>
|
||||||
${formats.map(
|
${formats.map(
|
||||||
([format, name]) => html`
|
([format, name]) => html`
|
||||||
<button
|
<button
|
||||||
@@ -575,9 +601,11 @@ class TfMessageElement extends LitElement {
|
|||||||
let self = this;
|
let self = this;
|
||||||
return this.render_frame(html`
|
return this.render_frame(html`
|
||||||
${self.render_header()}
|
${self.render_header()}
|
||||||
${self.format == 'raw'
|
<div class="w3-container">
|
||||||
? html`<div class="w3-container">${self.render_raw()}</div>`
|
${self.format == 'raw'
|
||||||
: inner}
|
? html`${self.render_raw()}`
|
||||||
|
: self.render_flagged(inner)}
|
||||||
|
</div>
|
||||||
${self.render_votes()}
|
${self.render_votes()}
|
||||||
${(self.message.child_messages || []).map(
|
${(self.message.child_messages || []).map(
|
||||||
(x) => html`
|
(x) => html`
|
||||||
@@ -703,6 +731,38 @@ class TfMessageElement extends LitElement {
|
|||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render_flagged(inner) {
|
||||||
|
if (this.message.flags) {
|
||||||
|
return html`
|
||||||
|
<div
|
||||||
|
class="w3-panel w3-round-xlarge w3-theme-l4 w3"
|
||||||
|
style="cursor: pointer"
|
||||||
|
@click=${(x) => this.toggle_expanded(':cw')}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
${this.message.flags
|
||||||
|
? html`<p>
|
||||||
|
Caution: This message has been flagged
|
||||||
|
${this.message.flags.length}
|
||||||
|
time${this.message.flags.length == 1 ? '' : 's'}.
|
||||||
|
</p>`
|
||||||
|
: undefined}
|
||||||
|
</p>
|
||||||
|
<p class="w3-small">
|
||||||
|
${inner !== undefined
|
||||||
|
? this.is_expanded(':cw')
|
||||||
|
? 'Show less'
|
||||||
|
: 'Show more'
|
||||||
|
: undefined}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
${this.is_expanded(':cw') ? inner : undefined}
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
return inner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_render() {
|
_render() {
|
||||||
let content = this.message?.content;
|
let content = this.message?.content;
|
||||||
if (this.message?.decrypted?.type == 'post') {
|
if (this.message?.decrypted?.type == 'post') {
|
||||||
@@ -850,6 +910,7 @@ class TfMessageElement extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="w3-container">${this.render_flagged(undefined)}</div>
|
||||||
<div>${this.render_votes()}</div>
|
<div>${this.render_votes()}</div>
|
||||||
${(this.message.child_messages || []).map(
|
${(this.message.child_messages || []).map(
|
||||||
(x) => html`
|
(x) => html`
|
||||||
@@ -965,7 +1026,19 @@ class TfMessageElement extends LitElement {
|
|||||||
style="cursor: pointer"
|
style="cursor: pointer"
|
||||||
@click=${(x) => this.toggle_expanded(':cw')}
|
@click=${(x) => this.toggle_expanded(':cw')}
|
||||||
>
|
>
|
||||||
<p>${content.contentWarning}</p>
|
<p>
|
||||||
|
${this.message.flags
|
||||||
|
? html`<p>
|
||||||
|
Caution: This message has been flagged
|
||||||
|
${this.message.flags.length}
|
||||||
|
time${this.message.flags.length == 1 ? '' : 's'}.
|
||||||
|
</p>`
|
||||||
|
: undefined}
|
||||||
|
${content.contentWarning
|
||||||
|
? html`<p>${content.contentWarning}</p>`
|
||||||
|
: undefined}
|
||||||
|
</p>
|
||||||
|
|
||||||
<p class="w3-small">
|
<p class="w3-small">
|
||||||
${this.is_expanded(':cw') ? 'Show less' : 'Show more'}
|
${this.is_expanded(':cw') ? 'Show less' : 'Show more'}
|
||||||
</p>
|
</p>
|
||||||
@@ -976,11 +1049,12 @@ class TfMessageElement extends LitElement {
|
|||||||
<div @click=${this.body_click}>${body}</div>
|
<div @click=${this.body_click}>${body}</div>
|
||||||
${this.render_mentions()}
|
${this.render_mentions()}
|
||||||
`;
|
`;
|
||||||
let payload = content.contentWarning
|
let payload =
|
||||||
? self.expanded[(this.message.id || '') + ':cw']
|
this.message.flags || content.contentWarning
|
||||||
? html` ${content_warning} ${content_html} `
|
? self.expanded[(this.message.id || '') + ':cw']
|
||||||
: content_warning
|
? html` ${content_warning} ${content_html} `
|
||||||
: content_html;
|
: content_warning
|
||||||
|
: content_html;
|
||||||
return this.render_frame(html`
|
return this.render_frame(html`
|
||||||
${this.render_header()}
|
${this.render_header()}
|
||||||
<div class="w3-container">${payload}</div>
|
<div class="w3-container">${payload}</div>
|
||||||
|
|||||||
@@ -515,6 +515,7 @@ async function getProcessBlob(blobId, key, options) {
|
|||||||
await imports.core.permissionTest('modify_blocks', `Unblock ${id}.`);
|
await imports.core.permissionTest('modify_blocks', `Unblock ${id}.`);
|
||||||
await ssb_internal.removeBlock(id);
|
await ssb_internal.removeBlock(id);
|
||||||
};
|
};
|
||||||
|
imports.ssb.getBlocks = ssb_internal.getBlocks.bind(ssb_internal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
12
src/ssb.db.c
12
src/ssb.db.c
@@ -2936,3 +2936,15 @@ bool tf_ssb_db_is_blocked(sqlite3* db, const char* id)
|
|||||||
}
|
}
|
||||||
return is_blocked;
|
return is_blocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tf_ssb_db_get_blocks(sqlite3* db, void (*callback)(const char* id, double timestamp, void* user_data), void* user_data)
|
||||||
|
{
|
||||||
|
sqlite3_stmt* statement = NULL;
|
||||||
|
if (sqlite3_prepare_v2(db, "SELECT id, timestamp FROM blocks ORDER BY timestamp", -1, &statement, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
while (sqlite3_step(statement) == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
callback((const char*)sqlite3_column_text(statement, 0), sqlite3_column_double(statement, 1), user_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -639,4 +639,12 @@ void tf_ssb_db_remove_block(sqlite3* db, const char* id);
|
|||||||
*/
|
*/
|
||||||
bool tf_ssb_db_is_blocked(sqlite3* db, const char* id);
|
bool tf_ssb_db_is_blocked(sqlite3* db, const char* id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Get block list.
|
||||||
|
** @param db The database.
|
||||||
|
** @param callback Called for each entry.
|
||||||
|
** @param user_data User data to be passed to the callback.
|
||||||
|
*/
|
||||||
|
void tf_ssb_db_get_blocks(sqlite3* db, void (*callback)(const char* id, double timestamp, void* user_data), void* user_data);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
63
src/ssb.js.c
63
src/ssb.js.c
@@ -2232,6 +2232,68 @@ static JSValue _tf_ssb_remove_block(JSContext* context, JSValueConst this_val, i
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _block_t
|
||||||
|
{
|
||||||
|
char id[k_id_base64_len];
|
||||||
|
double timestamp;
|
||||||
|
} block_t;
|
||||||
|
|
||||||
|
typedef struct _get_blocks_t
|
||||||
|
{
|
||||||
|
block_t* blocks;
|
||||||
|
int count;
|
||||||
|
JSValue promise[2];
|
||||||
|
} get_blocks_t;
|
||||||
|
|
||||||
|
static void _get_blocks_callback(const char* id, double timestamp, void* user_data)
|
||||||
|
{
|
||||||
|
get_blocks_t* work = user_data;
|
||||||
|
work->blocks = tf_resize_vec(work->blocks, sizeof(block_t) * (work->count + 1));
|
||||||
|
work->blocks[work->count] = (block_t) { .timestamp = timestamp };
|
||||||
|
tf_string_set(work->blocks[work->count].id, sizeof(work->blocks[work->count].id), id);
|
||||||
|
work->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tf_ssb_get_blocks_work(tf_ssb_t* ssb, void* user_data)
|
||||||
|
{
|
||||||
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
|
tf_ssb_db_get_blocks(db, _get_blocks_callback, user_data);
|
||||||
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tf_ssb_get_blocks_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
||||||
|
{
|
||||||
|
get_blocks_t* work = user_data;
|
||||||
|
JSContext* context = tf_ssb_get_context(ssb);
|
||||||
|
|
||||||
|
JSValue result = JS_NewArray(context);
|
||||||
|
for (int i = 0; i < work->count; i++)
|
||||||
|
{
|
||||||
|
JSValue entry = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, entry, "id", JS_NewString(context, work->blocks[i].id));
|
||||||
|
JS_SetPropertyStr(context, entry, "timestamp", JS_NewFloat64(context, work->blocks[i].timestamp));
|
||||||
|
JS_SetPropertyUint32(context, result, i, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValue error = JS_Call(context, work->promise[0], JS_UNDEFINED, 1, &result);
|
||||||
|
JS_FreeValue(context, result);
|
||||||
|
tf_util_report_error(context, error);
|
||||||
|
JS_FreeValue(context, error);
|
||||||
|
JS_FreeValue(context, work->promise[0]);
|
||||||
|
JS_FreeValue(context, work->promise[1]);
|
||||||
|
tf_free(work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue _tf_ssb_get_blocks(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
|
{
|
||||||
|
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
|
||||||
|
get_blocks_t* work = tf_malloc(sizeof(get_blocks_t));
|
||||||
|
*work = (get_blocks_t) { 0 };
|
||||||
|
JSValue result = JS_NewPromiseCapability(context, work->promise);
|
||||||
|
tf_ssb_run_work(ssb, _tf_ssb_get_blocks_work, _tf_ssb_get_blocks_after_work, work);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void tf_ssb_register(JSContext* context, tf_ssb_t* ssb)
|
void tf_ssb_register(JSContext* context, tf_ssb_t* ssb)
|
||||||
{
|
{
|
||||||
JS_NewClassID(&_tf_ssb_classId);
|
JS_NewClassID(&_tf_ssb_classId);
|
||||||
@@ -2289,6 +2351,7 @@ void tf_ssb_register(JSContext* context, tf_ssb_t* ssb)
|
|||||||
JS_SetPropertyStr(context, object_internal, "removeEventListener", JS_NewCFunction(context, _tf_ssb_remove_event_listener, "removeEventListener", 2));
|
JS_SetPropertyStr(context, object_internal, "removeEventListener", JS_NewCFunction(context, _tf_ssb_remove_event_listener, "removeEventListener", 2));
|
||||||
JS_SetPropertyStr(context, object_internal, "addBlock", JS_NewCFunction(context, _tf_ssb_add_block, "addBlock", 1));
|
JS_SetPropertyStr(context, object_internal, "addBlock", JS_NewCFunction(context, _tf_ssb_add_block, "addBlock", 1));
|
||||||
JS_SetPropertyStr(context, object_internal, "removeBlock", JS_NewCFunction(context, _tf_ssb_remove_block, "removeBlock", 1));
|
JS_SetPropertyStr(context, object_internal, "removeBlock", JS_NewCFunction(context, _tf_ssb_remove_block, "removeBlock", 1));
|
||||||
|
JS_SetPropertyStr(context, object_internal, "getBlocks", JS_NewCFunction(context, _tf_ssb_get_blocks, "getBlocks", 0));
|
||||||
|
|
||||||
JS_FreeValue(context, global);
|
JS_FreeValue(context, global);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user