diff --git a/apps/ssb/tf-app.js b/apps/ssb/tf-app.js index ee30ffa9..bc1bf2fe 100644 --- a/apps/ssb/tf-app.js +++ b/apps/ssb/tf-app.js @@ -245,13 +245,16 @@ class TfElement extends LitElement { if (confirm("Are you sure you want to create a new identity?")) { await tfrpc.rpc.createIdentity(); this.ids = (await tfrpc.rpc.getIdentities()) || []; + if (this.ids && !this.whoami) { + this.whoami = this.ids[0]; + } } } render_id_picker() { return html` - + `; } @@ -293,7 +296,7 @@ class TfElement extends LitElement { let users = this.users; if (this.tab === 'news') { return html` - this.unread = []}> + this.unread = []}> `; } else if (this.tab === 'connections') { return html` @@ -325,7 +328,6 @@ class TfElement extends LitElement { let self = this; if (!this.loading && this.whoami && this.loaded !== this.whoami) { - console.log(`starting loading ${this.whoami} ${this.loaded}`); this.loading = true; this.load().finally(function() { self.loading = false; @@ -355,4 +357,4 @@ class TfElement extends LitElement { } } -customElements.define('tf-app', TfElement); \ No newline at end of file +customElements.define('tf-app', TfElement); diff --git a/apps/ssb/tf-compose.js b/apps/ssb/tf-compose.js index 7276d3d1..cd100dad 100644 --- a/apps/ssb/tf-compose.js +++ b/apps/ssb/tf-compose.js @@ -372,7 +372,7 @@ class TfComposeElement extends LitElement { ${Object.values(draft.mentions || {}).map(x => self.render_mention(x))} ${this.render_content_warning()} ${this.render_attach_app()} - + ${this.render_attach_app_button()} @@ -381,4 +381,4 @@ class TfComposeElement extends LitElement { } } -customElements.define('tf-compose', TfComposeElement); \ No newline at end of file +customElements.define('tf-compose', TfComposeElement); diff --git a/apps/ssb/tf-id-picker.js b/apps/ssb/tf-id-picker.js index 900eeb6c..1b9516cb 100644 --- a/apps/ssb/tf-id-picker.js +++ b/apps/ssb/tf-id-picker.js @@ -14,7 +14,6 @@ class TfIdentityPickerElement extends LitElement { constructor() { super(); - let self = this; this.ids = []; } @@ -34,4 +33,4 @@ class TfIdentityPickerElement extends LitElement { } } -customElements.define('tf-id-picker', TfIdentityPickerElement); \ No newline at end of file +customElements.define('tf-id-picker', TfIdentityPickerElement); diff --git a/apps/ssb/tf-tab-news.js b/apps/ssb/tf-tab-news.js index 6f4eab78..84f509bc 100644 --- a/apps/ssb/tf-tab-news.js +++ b/apps/ssb/tf-tab-news.js @@ -109,11 +109,11 @@ class TfTabNewsElement extends LitElement {
🏠Home
Welcome, !
-
+
${profile} `; } } -customElements.define('tf-tab-news', TfTabNewsElement); \ No newline at end of file +customElements.define('tf-tab-news', TfTabNewsElement); diff --git a/core/client.js b/core/client.js index db8bd117..fa662318 100644 --- a/core/client.js +++ b/core/client.js @@ -96,9 +96,9 @@ class TfNavigationElement extends LitElement { render_login() { if (this?.credentials?.session?.name) { - return html`logout ${this.credentials.session.name}`; + return html`logout ${this.credentials.session.name}`; } else { - return html`login`; + return html`login`; } } @@ -704,11 +704,13 @@ function api_requestPermission(permission, id) { const k_options = [ { + id: 'allow', text: '✅ Allow', grant: ['allow once', 'allow'], }, { + id: 'deny', text: '❌ Deny', grant: ['deny once', 'deny'], }, @@ -719,6 +721,7 @@ function api_requestPermission(permission, id) { for (let option of k_options) { let button = document.createElement('button'); button.innerText = option.text; + button.id = option.id; button.onclick = function() { resolve(option.grant[check.checked ? 1 : 0]); document.body.removeChild(outer); diff --git a/src/main.c b/src/main.c index f89624bf..ec210e12 100644 --- a/src/main.c +++ b/src/main.c @@ -353,16 +353,13 @@ static int _tf_run_task(const tf_run_args_t* args, int index) } tf_task_set_db_path(task, db_path); tf_task_activate(task); - if (args->ssb_port) + if (args->zip) { - if (args->zip) - { - tf_ssb_import_from_zip(tf_task_get_ssb(task), args->zip, "core", "apps"); - } - else - { - tf_ssb_import(tf_task_get_ssb(task), "core", "apps"); - } + tf_ssb_import_from_zip(tf_task_get_ssb(task), args->zip, "core", "apps"); + } + else + { + tf_ssb_import(tf_task_get_ssb(task), "core", "apps"); } if (tf_task_execute(task, args->script)) { diff --git a/src/ssb.c b/src/ssb.c index 486517ec..d0e20933 100644 --- a/src/ssb.c +++ b/src/ssb.c @@ -239,6 +239,7 @@ typedef struct _tf_ssb_t void* hitch_user_data; tf_ssb_store_queue_t store_queue; + int ref_count; } tf_ssb_t; typedef struct _tf_ssb_connection_message_request_t @@ -2278,7 +2279,8 @@ void tf_ssb_destroy(tf_ssb_t* ssb) ssb->broadcast_timer.data || ssb->broadcast_cleanup_timer.data || ssb->trace_timer.data || - ssb->server.data) + ssb->server.data || + ssb->ref_count) { uv_run(ssb->loop, UV_RUN_ONCE); } @@ -2341,7 +2343,11 @@ void tf_ssb_destroy(tf_ssb_t* ssb) } if (ssb->loop == &ssb->own_loop) { - uv_loop_close(ssb->loop); + int r = uv_loop_close(ssb->loop); + if (r != 0) + { + tf_printf("uv_loop_close: %s\n", uv_strerror(r)); + } } if (ssb->own_context) { @@ -3568,3 +3574,13 @@ tf_ssb_store_queue_t* tf_ssb_get_store_queue(tf_ssb_t* ssb) { return &ssb->store_queue; } + +void tf_ssb_ref(tf_ssb_t* ssb) +{ + ssb->ref_count++; +} + +void tf_ssb_unref(tf_ssb_t* ssb) +{ + ssb->ref_count--; +} diff --git a/src/ssb.h b/src/ssb.h index b0ab3013..670c2d5a 100644 --- a/src/ssb.h +++ b/src/ssb.h @@ -200,3 +200,6 @@ uint64_t tf_ssb_get_average_thread_time(tf_ssb_t* ssb); void tf_ssb_set_hitch_callback(tf_ssb_t* ssb, void (*callback)(const char* name, uint64_t duration_ns, void* user_data), void* user_data); tf_ssb_store_queue_t* tf_ssb_get_store_queue(tf_ssb_t* ssb); + +void tf_ssb_ref(tf_ssb_t* ssb); +void tf_ssb_unref(tf_ssb_t* ssb); diff --git a/src/ssb.rpc.c b/src/ssb.rpc.c index d3724d17..e7549c24 100644 --- a/src/ssb.rpc.c +++ b/src/ssb.rpc.c @@ -1209,6 +1209,7 @@ static void _tf_ssb_rpc_delete_blobs_after_work(uv_work_t* work, int status) { delete_blobs_work_t* delete = work->data; tf_ssb_record_thread_time(delete->ssb, (int64_t)delete->thread_id, delete->end_time - delete->start_time); + tf_ssb_unref(delete->ssb); tf_free(delete); } @@ -1238,6 +1239,7 @@ static void _tf_ssb_rpc_start_delete_blobs(tf_ssb_t* ssb, int delay_ms) *timer = (uv_timer_t) { .data = ssb }; uv_timer_init(tf_ssb_get_loop(ssb), timer); uv_timer_start(timer, _tf_ssb_rpc_start_delete_timer, delay_ms, 0); + tf_ssb_ref(ssb); } void tf_ssb_rpc_register(tf_ssb_t* ssb) diff --git a/tools/autotest.py b/tools/autotest.py new file mode 100644 index 00000000..66786ecf --- /dev/null +++ b/tools/autotest.py @@ -0,0 +1,58 @@ +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions +from selenium.webdriver.support.ui import WebDriverWait + +import os +import subprocess +import time + +for path in ('out/selenium.sqlite', 'out/selenium.sqlite-shm', 'out/selenium.sqlite-wal'): + try: + os.unlink(path) + except: + pass +tf = subprocess.Popen(['out/debug/tildefriends', 'run', '-d', 'out/selenium.sqlite', '-b', '0', '-p', '8888']) + +try: + options = webdriver.FirefoxOptions() + #options.add_argument('--headless') + driver = webdriver.Firefox(options = options) + driver.get('http://localhost:8888') + driver.find_element(By.TAG_NAME, 'tf-navigation').shadow_root.find_element(By.LINK_TEXT, 'login').click() + driver.find_element(By.ID, 'register').click() + driver.find_element(By.ID, 'name').send_keys('test_user') + driver.find_element(By.ID, 'password').send_keys('test_password') + driver.find_element(By.ID, 'confirm').send_keys('test_password') + driver.find_element(By.ID, 'loginButton').click() + + driver.switch_to.frame(driver.find_element(By.ID, 'document')) + WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.LINK_TEXT, 'ssb'))) + driver.find_element(By.LINK_TEXT, 'ssb').click() + driver.switch_to.default_content() + + WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.ID, 'document'))) + driver.switch_to.frame(driver.find_element(By.ID, 'document')) + WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.TAG_NAME, 'tf-app'))) + tf_app = driver.find_element(By.TAG_NAME, 'tf-app').shadow_root + WebDriverWait(driver, 30).until(expected_conditions.element_to_be_clickable(tf_app.find_element(By.ID, 'create_identity'))) + tf_app.find_element(By.ID, 'create_identity').click() + alert = WebDriverWait(driver, 30).until(expected_conditions.alert_is_present()) + alert.accept() + + driver.implicitly_wait(3) + #tf_app = driver.find_element(By.TAG_NAME, 'tf-app').shadow_root + #WebDriverWait(driver, 30).until(expected_conditions.visibility_of(tf_app.find_element(By.ID, 'tf-tab-news'))) + tf_tab_news = tf_app.find_element(By.ID, 'tf-tab-news').shadow_root + tf_tab_news.find_element(By.ID, 'tf-compose').shadow_root.find_element(By.ID, 'edit').send_keys('Hello, world!') + tf_tab_news.find_element(By.ID, 'tf-compose').shadow_root.find_element(By.ID, 'submit').click() + + driver.switch_to.default_content() + driver.find_element(By.ID, 'allow').click() + + print('SUCCESS.') +finally: + driver.close() + driver.quit() + +tf.terminate()