Skip to content

Commit

Permalink
Merge branch 'main' into 2fpf
Browse files Browse the repository at this point in the history
  • Loading branch information
tschudin authored Dec 12, 2023
2 parents c87900b + 3ac1ce3 commit 0c71fc0
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 87 deletions.
85 changes: 50 additions & 35 deletions android/tinySSB/app/src/main/assets/web/tremola.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@

<div id="new_contact-overlay" class="qr-overlay" style="display: none; text-align: center">
<div style='margin-bottom: 15px;'>&nbsp;<br>Scan tinySSB QR code<br>of a trustworthy person:</div>
<button class="passive buttontext" onclick="qr_scan_start();" style="border: 0pt; height: 60pt; width: 120px; background-image: url('img/qr-code-scan.svg');">&nbsp;</button><br>&nbsp;<hr>
<button class="passive buttontext" onclick="qr_scan_start(QR_SCAN_TARGET.ADD_CONTACT);" style="border: 0pt; height: 60pt; width: 120px; background-image: url('img/qr-code-scan.svg');">&nbsp;</button><br>&nbsp;<hr>
<br>or enter their SSB identity as text:<br>&nbsp;
<div style="display: flex;">
<textarea rows="2" id="contact_id" placeholder="Tap here to type" style="width: calc(100% - 50px); vertical-align: middle;"></textarea>
Expand Down Expand Up @@ -294,10 +294,23 @@

<div id='edit-overlay' class='qr-overlay'>
<div id="edit_title" style='margin-bottom: 25px;'>Edit X:</div>
<input type="text" id="edit_text" onkeypress="edit_checkEnter(event)" minlength="1" size="64" style="width: calc(100% - 10px); height: 30px;">&nbsp;
<input type="text" id="edit_text" onkeypress="onEnter(event)" minlength="1" size="64" style="width: calc(100% - 10px); height: 30px;">&nbsp;
<div style='text-align: right;'><button class="passive buttontext" onclick="edit_confirmed();" style="background-image: url('img/checked.svg'); margin-right: 5px; border: 0pt; height: 30px; width: 30px;">&nbsp;</button></div>
</div>

<div id='import-id-overlay' class='qr-overlay'>
<div style='font-size: larger; text-align: center'><b>Import new ID</b></div>
<div style='margin-left: 10px; margin-right: 10px;margin-bottom: 15px;'><p align=“justify“><b>Caution: </b>Ensure you avoid utilizing the same identity simultaneously on multiple devices, as this could result in concurrent actions, thus rendering your log invalid.</p></div>
<div style='text-align: center'><b>Import via QR Code</b></div>
<br>
<div style='display: flex; justify-content: center;'><button class="passive buttontext" onclick="qr_scan_start(QR_SCAN_TARGET.IMPORT_ID);" style="border: 0pt; height: 60pt; width: 120px; background-image: url('img/qr-code-scan.svg');margin: auto;">&nbsp;</button></div>
<br>
<div style='text-align: center; margin-left: 10px; margin-right: 10px;margin-bottom: 15px;'><b>Import via copied secret key</b></div>
<textarea placeholder='{"curve": "ed25519", "secret": "YOUR SECRECT KEY"}' id="import-id-input" rows="3" onkeypress="onEnter(event)"></textarea>
<button class="passive buttontext" style="background-image: url('img/checked.svg');border: 0pt; height: 40px; width: 40px;" onclick="btn_import_id()" ></button>
<div></div>
</div>

<div id="snackbar">the msg</div>

<div id='about-overlay' class='qr-overlay' style="overflow: scroll; font-size: medium; height: 75%;">
Expand Down Expand Up @@ -388,30 +401,6 @@
</div>
</div>

</div>

<div id='div:footer' class=neutral style="height: 56px; align-content: center; border: 3px inset #ebf4fa /*var(--light)*/; border-radius: 2px; margin: 3px; width: calc(100% - 12px);">

<table width=100% cellpadding="2pt"><tr>
<td width=33%><button id='btn:chats' class="w100 flat active buttontext" onclick="btnBridge(this);" style="background-image: url('img/chat.svg');">&nbsp;<!-- font size=+3>&#x1F4E8;</font><br><font size=small>Chats</font --></button>
<td width=33%><button id='btn:kanban' class="w100 flat passive buttontext" onclick="btnBridge(this);" style="background-image: url('img/kanban.svg');">&nbsp;<!-- font size=+3>&#x1F5E3;</font><br><font size=small>Board</font --></button>
<td width=33%><button id='btn:contacts' class="w100 flat passive buttontext" onclick="btnBridge(this);" style="background-image: url('img/contacts.svg');">&nbsp;<!-- font size=+3>&#x1F465;</font><br><font size=small>Contacts</font --></button>
</table>

</div>

<table id="div:textarea" class="neutral" style="height: 56px; width: calc(100% - 6pt); display: none; border: 3px inset #ebf4fa /*var(--light)*/; margin: 3pt;" width=100%>
<tr><td width=95%><textarea id='draft' rows=3 placeholder='Tap here to type'></textarea>
<!-- td width=5% height=100%><button id='btn:attach' class="flat passive buttontext"><font size=+2>&#x1F4CE;</font><br><font size=small>Attach</font></button></td -->
<td width=8% height=100%><button id='btn:attach' class="flat white buttontext" onclick="btnBridge(this);" style="background-image: url('img/record.svg'); fill: #fff; width: 50px; height: 50px; margin-bottom: 4px;"></button>
<td width=5% height=100%><button id='btn:preview' class="flat passive buttontext" onclick="showPreview();" style="background-image: url('img/send-button.svg'); width: 50px; height: 50px; margin-bottom: 4px;">&nbsp;<!-- font size=+2>&#x1F440;</font><br><font size=small>Preview</font --></button>
</table>

<div id='div:confirm-members' class=neutral style="height: 36px; align-content: center; border: 3px inset #ebf4fa /*var(--light)*/; border-radius: 2pt; margin: 3px; margin-top: 20px; display: none; flex-direction: row; justify-content: center; align-items: center;">
<!-- button class="flat passive buttontext" style="background-image: url('img/cancel.svg'); width: 50%; height: 50px; margin: 5px;" onclick="onBackPressed();">&nbsp;</--button -->
<button class="flat passive buttontext" style="background-image: url('img/checked.svg'); width: 100%; height: 30px; margin: 3px;" onclick="members_confirmed();">&nbsp;</button>
</div>

<div id="div:settings" style="display: none; height: calc(100% - 45px);"><div style="height: 100%; overflow: scroll; margin: 6px;">
<div style="text-align: center;"><em>Configurations</em></div>
<hr>
Expand All @@ -436,15 +425,15 @@
<hr>

<div class="settings">
<div class="settingsText">Connect to Pub via Websocket</div>
<div style="float: right;"><label class="switch">
<input id="websocket" type="checkbox" onchange="toggle_changed(this);">
<span class="slider round"></span></label></div>
<div class="settingsText">Connect to Pub via Websocket</div>
<div style="float: right;"><label class="switch">
<input id="websocket" type="checkbox" onchange="toggle_changed(this);">
<span class="slider round"></span></label></div>
</div>
<div id="container:settings_ws_url" class="websocket_url_settings" style="display:none;">
<div class="settingsText" style="margin-right: 10px;font-size: 16px;margin-bottom: 5px;">URL: </div>
<input type="text" id="settings_urlInput" onkeypress="enter_setWebsocketUrl(event)" placeholder="Websocket-Url (ws://...)" required style="height:30px; width: 70%">
<button id="btn:url" class ="flat passive buttontext" onclick="btn_setWebsocketUrl()" style="background-image: url('img/checked.svg'); width:35px; height:35px; margin-left: 5px;"></button>
<div class="settingsText" style="margin-right: 10px;font-size: 16px;margin-bottom: 5px;">URL: </div>
<input type="text" id="settings_urlInput" onkeypress="onEnter(event)" placeholder="Websocket-Url (ws://...)" required style="height:30px; width: 70%">
<button id="btn:url" class ="flat passive buttontext" onclick="btn_setWebsocketUrl()" style="background-image: url('img/checked.svg'); width:35px; height:35px; margin-left: 5px;"></button>
</div>
<hr>

Expand Down Expand Up @@ -508,15 +497,41 @@
Reset UI + Re-stream (but keep ID)</button><hr>
<p><button class="w100 button active item" style="height: 2.5em;" onclick="settings_clear_other_feeds()">
Delete all logs except your own (but keep ID)</button><hr>
<p><button class="w100 button active item" style="height: 2.5em;">
<del>Import new secret key (also erases DB)</del></button><hr>
<p><button class="w100 button active item" style="height: 2.5em;" onclick="menu_import_id()">
Import new secret key (also erases DB)</button><hr>
<p><button class="w100 button active item" style="height: 3em;" onclick="backend('exportSecret');">
Export secret key</button><hr>
<p>&nbsp;<br>&nbsp;<br>&nbsp;<br><button class="w100 button active item" style="height: 2.5em;" onclick="settings_wipe();">
<span style="color: #e85132 /* var(--red) */;font-weight: 900;">WIPE EVERYTHING IMMEDIATELY</span></button><hr>
&nbsp;
</div></div>

</div>

<div id='div:footer' class=neutral style="height: 56px; align-content: center; border: 3px inset #ebf4fa /*var(--light)*/; border-radius: 2px; margin: 3px; width: calc(100% - 12px);">

<table width=100% cellpadding="2pt"><tr>
<td width=33%><button id='btn:chats' class="w100 flat active buttontext" onclick="btnBridge(this);" style="background-image: url('img/chat.svg');">&nbsp;<!-- font size=+3>&#x1F4E8;</font><br><font size=small>Chats</font --></button>
<td width=33%><button id='btn:kanban' class="w100 flat passive buttontext" onclick="btnBridge(this);" style="background-image: url('img/kanban.svg');">&nbsp;<!-- font size=+3>&#x1F5E3;</font><br><font size=small>Board</font --></button>
<td width=33%><button id='btn:contacts' class="w100 flat passive buttontext" onclick="btnBridge(this);" style="background-image: url('img/contacts.svg');">&nbsp;<!-- font size=+3>&#x1F465;</font><br><font size=small>Contacts</font --></button>
</table>

</div>

<table id="div:textarea" class="neutral" style="height: 56px; width: calc(100% - 6pt); display: none; border: 3px inset #ebf4fa /*var(--light)*/; margin: 3pt;" width=100%>
<tr><td width=95%><textarea id='draft' rows=3 placeholder='Tap here to type'></textarea>
<!-- td width=5% height=100%><button id='btn:attach' class="flat passive buttontext"><font size=+2>&#x1F4CE;</font><br><font size=small>Attach</font></button></td -->
<td width=8% height=100%><button id='btn:attach' class="flat white buttontext" onclick="btnBridge(this);" style="background-image: url('img/record.svg'); fill: #fff; width: 50px; height: 50px; margin-bottom: 4px;"></button>
<td width=5% height=100%><button id='btn:preview' class="flat passive buttontext" onclick="showPreview();" style="background-image: url('img/send-button.svg'); width: 50px; height: 50px; margin-bottom: 4px;">&nbsp;<!-- font size=+2>&#x1F440;</font><br><font size=small>Preview</font --></button>
</table>

<div id='div:confirm-members' class=neutral style="height: 36px; align-content: center; border: 3px inset #ebf4fa /*var(--light)*/; border-radius: 2pt; margin: 3px; margin-top: 20px; display: none; flex-direction: row; justify-content: center; align-items: center;">
<!-- button class="flat passive buttontext" style="background-image: url('img/cancel.svg'); width: 50%; height: 50px; margin: 5px;" onclick="onBackPressed();">&nbsp;</--button -->
<button class="flat passive buttontext" style="background-image: url('img/checked.svg'); width: 100%; height: 30px; margin: 3px;" onclick="members_confirmed();">&nbsp;</button>
</div>



</div>
</body>
</html>
48 changes: 44 additions & 4 deletions android/tinySSB/app/src/main/assets/web/tremola.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}

Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1089,7 +1129,7 @@ function b2f_new_voice(voice_b64) {
}

function b2f_showSecret(json) {
setScenario(prev_scenario);
//setScenario(prev_scenario);
generateQR(json)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ function btn_setWebsocketUrl() {
}

function enter_setWebsocketUrl(ev) {
console.log(ev.target)
if (ev.key == "Enter") {
btn_setWebsocketUrl()
}
Expand Down
71 changes: 48 additions & 23 deletions android/tinySSB/app/src/main/assets/web/tremola_ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -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']
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -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:<br>(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:<br>(only you can see this alias)", "");
}




function qr_scan_failure() {
launch_snackbar("QR scan failed")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,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}');")
Expand All @@ -105,10 +94,24 @@ 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.reset()

if (act.websocket != null)
act.websocket!!.stop()
if (act.ble != null)
Expand Down
Loading

0 comments on commit 0c71fc0

Please sign in to comment.