diff --git a/android/tinySSB/app/src/main/assets/web/tremola.html b/android/tinySSB/app/src/main/assets/web/tremola.html index 7208764..f494e4d 100644 --- a/android/tinySSB/app/src/main/assets/web/tremola.html +++ b/android/tinySSB/app/src/main/assets/web/tremola.html @@ -114,7 +114,7 @@ - -
- - -
- - -
- -
- - - - - - + + +
+ + +
+ + +
+ +
+ + + + + + + + diff --git a/android/tinySSB/app/src/main/assets/web/tremola.js b/android/tinySSB/app/src/main/assets/web/tremola.js index 89d229c..43c895e 100644 --- a/android/tinySSB/app/src/main/assets/web/tremola.js +++ b/android/tinySSB/app/src/main/assets/web/tremola.js @@ -88,9 +88,20 @@ function menu_edit(target, title, text) { edit_target = target; } -function edit_checkEnter(ev) { +function onEnter(ev) { + if (ev.key == "Enter") { - edit_confirmed() + switch(ev.target.id) { + case 'edit_text': + edit_confirmed() + break + case 'settings_urlInput': + btn_setWebsocketUrl() + break + case 'import-id-input': + btn_import_id() + break + } } } @@ -218,8 +229,21 @@ function menu_forget_conv() { } function menu_import_id() { - // backend('secret: XXX'); closeOverlay(); + document.getElementById('import-id-overlay').style.display = 'initial' + document.getElementById('overlay-bg').style.display = 'initial' +} + +function btn_import_id() { + var str = document.getElementById('import-id-input').value + if(str == "") + return + var r = import_id(str) + if(r) { + launch_snackbar("Successfully imported, restarting...") + } else { + launch_snackbar("wrong format") + } } function menu_process_msgs() { @@ -745,6 +769,22 @@ function fid2display(fid) { return a; } +function import_id(json_str) { + var json + try { + json = JSON.parse(json_str) + } catch (e) { + return false // argument is not a valid json string + } + if (Object.keys(json).length != 2 || !('curve' in json) || !('secret' in json)) { + return false // wrong format + } + + backend("importSecret " + json['secret']) + return true +} + + // --- Interface to Kotlin side and local (browser) storage function backend(cmdStr) { // send this to Kotlin (or simulate in case of browser-only testing) @@ -1089,7 +1129,7 @@ function b2f_new_voice(voice_b64) { } function b2f_showSecret(json) { - setScenario(prev_scenario); + //setScenario(prev_scenario); generateQR(json) } diff --git a/android/tinySSB/app/src/main/assets/web/tremola_settings.js b/android/tinySSB/app/src/main/assets/web/tremola_settings.js index a40ed6a..91fc78f 100644 --- a/android/tinySSB/app/src/main/assets/web/tremola_settings.js +++ b/android/tinySSB/app/src/main/assets/web/tremola_settings.js @@ -93,6 +93,7 @@ function btn_setWebsocketUrl() { } function enter_setWebsocketUrl(ev) { + console.log(ev.target) if (ev.key == "Enter") { btn_setWebsocketUrl() } diff --git a/android/tinySSB/app/src/main/assets/web/tremola_ui.js b/android/tinySSB/app/src/main/assets/web/tremola_ui.js index bec609c..f776cda 100644 --- a/android/tinySSB/app/src/main/assets/web/tremola_ui.js +++ b/android/tinySSB/app/src/main/assets/web/tremola_ui.js @@ -20,7 +20,7 @@ var scenarioDisplay = { 'posts': ['div:back', 'core', 'lst:posts', 'div:textarea'], 'connex': ['div:qr', 'core', 'the:connex', 'div:footer', 'plus'], 'members': ['div:back', 'core', 'lst:members', 'div:confirm-members'], - 'settings': ['div:back', 'div:settings'], + 'settings': ['div:back', 'div:settings', 'core'], 'kanban': ['div:qr', 'core', 'lst:kanban', 'div:footer', 'plus'], 'board': ['div:back', 'core', 'div:board'] } @@ -77,6 +77,13 @@ var scenarioMenu = { ['Debug', 'ui_debug']] } +const QR_SCAN_TARGET = { + ADD_CONTACT: 0, + IMPORT_ID: 1 +} + +var curr_qr_scan_target = QR_SCAN_TARGET.ADD_CONTACT + function onBackPressed() { if (overlayIsActive) { closeOverlay(); @@ -235,6 +242,7 @@ function closeOverlay() { document.getElementById('attach-menu').style.display = 'none'; document.getElementById('div:modal_img').style.display = 'none'; document.getElementById('connection-overlay').style.display = 'none'; + document.getElementById('import-id-overlay').style.display = 'none'; // kanban overlays document.getElementById('div:menu_history').style.display = 'none'; @@ -331,38 +339,55 @@ function generateQR(s) { overlayIsActive = true; } -function qr_scan_start() { + +function qr_scan_start(target) { // test if Android is defined ... + curr_qr_scan_target = target backend("qrscan.init"); closeOverlay(); } function qr_scan_success(s) { closeOverlay(); - var t = "did:ssb:ed25519:"; - if (s.substring(0, t.length) == t) { - s = '@' + s.substring(t.length) + '.ed25519'; - } - var b = ''; - try { - b = atob(s.substr(1, s.length - 9)); - // FIXME we should also test whether it is a valid ed25519 public key ... - } catch (err) { - } - if (b.length != 32) { - launch_snackbar("unknown format or invalid identity"); - return; - } - new_contact_id = s; - // console.log("tremola:", tremola) - if (new_contact_id in tremola.contacts) { - launch_snackbar("This contact already exists"); - return; + switch (curr_qr_scan_target) { + case QR_SCAN_TARGET.ADD_CONTACT: + var t = "did:ssb:ed25519:"; + if (s.substring(0, t.length) == t) { + s = '@' + s.substring(t.length) + '.ed25519'; + } + var b = ''; + try { + b = atob(s.substr(1, s.length - 9)); + // FIXME we should also test whether it is a valid ed25519 public key ... + } catch (err) { + } + if (b.length != 32) { + launch_snackbar("unknown format or invalid identity"); + return; + } + new_contact_id = s; + // console.log("tremola:", tremola) + if (new_contact_id in tremola.contacts) { + launch_snackbar("This contact already exists"); + return; + } + // FIXME: do sanity tests + menu_edit('new_contact_alias', "Assign alias to new contact:
(only you can see this alias)", ""); + break + case QR_SCAN_TARGET.IMPORT_ID: + r = import_id(s) + if (r) { + launch_snackbar("Successfully imported, restarting...") + } else { + launch_snackbar("wrong format") + } + break } - // FIXME: do sanity tests - menu_edit('new_contact_alias', "Assign alias to new contact:
(only you can see this alias)", ""); } + + + function qr_scan_failure() { launch_snackbar("QR scan failed") } diff --git a/android/tinySSB/app/src/main/java/nz/scuttlebutt/tremolavossbol/WebAppInterface.kt b/android/tinySSB/app/src/main/java/nz/scuttlebutt/tremolavossbol/WebAppInterface.kt index 5a7a04b..77bf076 100644 --- a/android/tinySSB/app/src/main/java/nz/scuttlebutt/tremolavossbol/WebAppInterface.kt +++ b/android/tinySSB/app/src/main/java/nz/scuttlebutt/tremolavossbol/WebAppInterface.kt @@ -82,17 +82,6 @@ class WebAppInterface(val act: MainActivity, val webView: WebView) { intentIntegrator.initiateScan() return } - "secret:" -> { - if (importIdentity(args[1])) { - /* - tremolaState.logDAO.wipe() - tremolaState.contactDAO.wipe() - tremolaState.pubDAO.wipe() - */ - act.finishAffinity() - } - return - } "exportSecret" -> { val json = act.idStore.identity.toExportString()!! eval("b2f_showSecret('${json}');") @@ -102,10 +91,25 @@ class WebAppInterface(val act: MainActivity, val webView: WebView) { Toast.makeText(act, "secret key was also\ncopied to clipboard", Toast.LENGTH_LONG).show() } + "importSecret" -> { + act.idStore.setNewIdentity(Base64.decode(args[1], Base64.NO_WRAP)) + act.tinyRepo.repo_reset() + + // restart App + if (act.websocket != null) + act.websocket!!.stop() + if (act.ble != null) + act.ble!!.stopBluetooth() + val ctx = act.applicationContext + ctx.startActivity(Intent.makeRestartActivityTask(act.applicationContext.packageManager.getLaunchIntentForPackage(ctx.packageName)!!.component)) + Runtime.getRuntime().exit(0) + } "wipe" -> { act.settings!!.resetToDefault() act.idStore.setNewIdentity(null) // creates new identity act.tinyRepo.repo_reset() + + // restart App if (act.websocket != null) act.websocket!!.stop() if (act.ble != null)