feat-user_settings): add ability to import and delete an identity, formatting
This commit is contained in:
		@@ -1,4 +1 @@
 | 
				
			|||||||
{
 | 
					{"type": "tildefriends-app", "emoji": "⚙️"}
 | 
				
			||||||
  "type": "tildefriends-app",
 | 
					 | 
				
			||||||
  "emoji": "⚙️"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,13 +9,19 @@ tfrpc.register(async function createID(id) {
 | 
				
			|||||||
tfrpc.register(async function getPrivateKey(id) {
 | 
					tfrpc.register(async function getPrivateKey(id) {
 | 
				
			||||||
	return bip39Words(await ssb.getPrivateKey(id));
 | 
						return bip39Words(await ssb.getPrivateKey(id));
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					tfrpc.register(async function addID(id) {
 | 
				
			||||||
 | 
						return await ssb.addIdentity(bip39Bytes(id));
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					tfrpc.register(async function deleteID(id) {
 | 
				
			||||||
 | 
						return await ssb.deleteIdentity(id);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
tfrpc.register(async function getThemes() {
 | 
					tfrpc.register(async function getThemes() {
 | 
				
			||||||
	// TODO
 | 
						// TODO
 | 
				
			||||||
	return ['solarized', 'gruvbox', 'light'];
 | 
						return ['solarized', 'gruvbox', 'light'];
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
tfrpc.register(async function setTheme() {
 | 
					tfrpc.register(async function setTheme() {
 | 
				
			||||||
	// TODO
 | 
						// TODO
 | 
				
			||||||
	console.warn("setTheme called - not implemented")
 | 
						console.warn('setTheme called - not implemented');
 | 
				
			||||||
	return null;
 | 
						return null;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
tfrpc.register(async function reload() {
 | 
					tfrpc.register(async function reload() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	<h3>Manage your identities</h3>
 | 
						<h3>Manage your identities</h3>
 | 
				
			||||||
	<tf-identity-manager></tf-identity-manager>
 | 
						<tf-identity-manager></tf-identity-manager>
 | 
				
			||||||
	
 | 
					
 | 
				
			||||||
	<h3>Change my password</h3>
 | 
						<h3>Change my password</h3>
 | 
				
			||||||
	<tf-password-form></tf-password-form>
 | 
						<tf-password-form></tf-password-form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
/* */
 | 
					 | 
				
			||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
/* */
 | 
					 | 
				
			||||||
@@ -22,7 +22,7 @@ class TfDeleteAccountButtonElement extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	render() {
 | 
						render() {
 | 
				
			||||||
		return html`
 | 
							return html`
 | 
				
			||||||
			<link rel="stylesheet" href="/static/tildefriends-v1.css"/>
 | 
								<link rel="stylesheet" href="/static/tildefriends-v1.css" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<span>This action is irreversible !</span>
 | 
								<span>This action is irreversible !</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,7 @@ class TfIdentityManagerElement extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	async createIdentity() {
 | 
						async createIdentity() {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			let id = await tfrpc.rpc.createID();
 | 
								const id = await tfrpc.rpc.createID();
 | 
				
			||||||
			alert('Successfully created: ' + id);
 | 
								alert('Successfully created: ' + id);
 | 
				
			||||||
			await tfrpc.rpc.reload();
 | 
								await tfrpc.rpc.reload();
 | 
				
			||||||
		} catch (err) {
 | 
							} catch (err) {
 | 
				
			||||||
@@ -28,13 +28,50 @@ class TfIdentityManagerElement extends LitElement {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						async importIdentity() {
 | 
				
			||||||
 | 
							const words = this.renderRoot?.querySelector('#import-id-textarea').value;
 | 
				
			||||||
 | 
							if (!words) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								const newID = await tfrpc.rpc.addID(words);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (newID) alert('Successfully imported a new identity');
 | 
				
			||||||
 | 
								else alert('This identity already exists or is invalid.');
 | 
				
			||||||
 | 
								await tfrpc.rpc.reload();
 | 
				
			||||||
 | 
							} catch (err) {
 | 
				
			||||||
 | 
								alert('Error importing identity: ' + err);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	async exportIdentity(id) {
 | 
						async exportIdentity(id) {
 | 
				
			||||||
		alert('Your private key is:\n' + (await tfrpc.rpc.getPrivateKey(id)));
 | 
							alert(
 | 
				
			||||||
 | 
								'Your private key is:\n' +
 | 
				
			||||||
 | 
									(await tfrpc.rpc.getPrivateKey(id)) +
 | 
				
			||||||
 | 
									'\nDo not share it with anyone!'
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						async deleteIdentity(id) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								if (
 | 
				
			||||||
 | 
									prompt(
 | 
				
			||||||
 | 
										'Are you sure you want to delete "' +
 | 
				
			||||||
 | 
											id +
 | 
				
			||||||
 | 
											'"?  It cannot be recovered without the exported phrase.\\n\\nEnter the word "DELETE" to confirm you wish to delete it.'
 | 
				
			||||||
 | 
									) === 'DELETE'
 | 
				
			||||||
 | 
								) {
 | 
				
			||||||
 | 
									if (await tfrpc.rpc.deleteID(id)) {
 | 
				
			||||||
 | 
										alert('Successfully deleted ID: ' + id);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									await tfrpc.rpc.reload();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								alert('Error deleting ID: ' + e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	render() {
 | 
						render() {
 | 
				
			||||||
		return html`
 | 
							return html` <link rel="stylesheet" href="/static/tildefriends-v1.css" />
 | 
				
			||||||
			<link rel="stylesheet" href="/static/tildefriends-v1.css"/>
 | 
					 | 
				
			||||||
			<style>
 | 
								<style>
 | 
				
			||||||
				.id-span {
 | 
									.id-span {
 | 
				
			||||||
					font-family: monospace;
 | 
										font-family: monospace;
 | 
				
			||||||
@@ -43,29 +80,39 @@ class TfIdentityManagerElement extends LitElement {
 | 
				
			|||||||
			</style>
 | 
								</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<h4>Create a new identity</h4>
 | 
								<h4>Create a new identity</h4>
 | 
				
			||||||
			<button id="create-id" class="green" @click=${this.createIdentity}>Create Identity</button>
 | 
								<button id="create-id" class="green" @click=${this.createIdentity}>
 | 
				
			||||||
 | 
									Create Identity
 | 
				
			||||||
 | 
								</button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<h4>Import an SSB Identity from 12 BIP39 English Words</h4>
 | 
								<h4>Import an SSB Identity from 12 BIP39 English Words</h4>
 | 
				
			||||||
			<textarea id="add-id" style="width: 100%" rows="4"></textarea>
 | 
								<textarea id="import-id-textarea" style="width: 100%" rows="4"></textarea>
 | 
				
			||||||
			<button class="green">[Not implemented] Import Identity</button>
 | 
								<button class="green" @click=${this.importIdentity}>
 | 
				
			||||||
 | 
									Import Identity
 | 
				
			||||||
 | 
								</button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<h4>Warning !</h4>
 | 
								<h4>Warning !</h4>
 | 
				
			||||||
			<strong>Anybody that has access to your private key can gain total access over your account.</strong>
 | 
								<strong
 | 
				
			||||||
			<br><br>
 | 
									>Anybody that knows your private key can gain total access over your
 | 
				
			||||||
 | 
									account.</strong
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								<br /><br />
 | 
				
			||||||
			Tilde Friends' contributors will never ask you for your private key !
 | 
								Tilde Friends' contributors will never ask you for your private key !
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<ul>
 | 
								<ul>
 | 
				
			||||||
			${this.ids.map(
 | 
									${this.ids.map(
 | 
				
			||||||
				(id) =>
 | 
										(id) =>
 | 
				
			||||||
					html`
 | 
											html` <li>
 | 
				
			||||||
				<li>
 | 
												<button class="blue" @click=${() => this.exportIdentity(id)}>
 | 
				
			||||||
					<button class="blue" @click=${() => this.exportIdentity(id)}>Export Identity</button>
 | 
													Export Identity
 | 
				
			||||||
					<button class="red">[Not implemented] Delete Identity</button>
 | 
												</button>
 | 
				
			||||||
					<span class="id-span">${id}</span>
 | 
												<button class="red" @click=${() => this.deleteIdentity(id)}>
 | 
				
			||||||
				</li>`
 | 
													Delete Identity
 | 
				
			||||||
			)}
 | 
												</button>
 | 
				
			||||||
 | 
												<span class="id-span">${id}</span>
 | 
				
			||||||
 | 
											</li>`
 | 
				
			||||||
 | 
									)}
 | 
				
			||||||
			</ul>`;
 | 
								</ul>`;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
customElements.define('tf-identity-manager', TfIdentityManagerElement);
 | 
					customElements.define('tf-identity-manager', TfIdentityManagerElement);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ class TfPasswordFormElement extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	render() {
 | 
						render() {
 | 
				
			||||||
		return html`
 | 
							return html`
 | 
				
			||||||
			<link rel="stylesheet" href="/static/tildefriends-v1.css"/>
 | 
								<link rel="stylesheet" href="/static/tildefriends-v1.css" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<style>
 | 
								<style>
 | 
				
			||||||
				.grid {
 | 
									.grid {
 | 
				
			||||||
@@ -48,21 +48,35 @@ class TfPasswordFormElement extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			<div class="grid">
 | 
								<div class="grid">
 | 
				
			||||||
				<label for="current">Current password:</label>
 | 
									<label for="current">Current password:</label>
 | 
				
			||||||
				<input type="password" id="current" name="current" autocomplete="current-password" />
 | 
									<input
 | 
				
			||||||
 | 
										type="password"
 | 
				
			||||||
 | 
										id="current"
 | 
				
			||||||
 | 
										name="current"
 | 
				
			||||||
 | 
										autocomplete="current-password"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				<label for="new">Enter new password:</label>
 | 
									<label for="new">Enter new password:</label>
 | 
				
			||||||
				<input type="password" id="new" name="new" autocomplete="new-password" />
 | 
									<input
 | 
				
			||||||
 | 
										type="password"
 | 
				
			||||||
 | 
										id="new"
 | 
				
			||||||
 | 
										name="new"
 | 
				
			||||||
 | 
										autocomplete="new-password"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				<label for="repeat">Repeat new password:</label>
 | 
									<label for="repeat">Repeat new password:</label>
 | 
				
			||||||
				<input type="password" id="repeat" name="repeat" autocomplete="new-password" />
 | 
									<input
 | 
				
			||||||
 | 
										type="password"
 | 
				
			||||||
 | 
										id="repeat"
 | 
				
			||||||
 | 
										name="repeat"
 | 
				
			||||||
 | 
										autocomplete="new-password"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<button @click=${this.submitPassword} class="red">
 | 
								<button @click=${this.submitPassword} class="red">
 | 
				
			||||||
				[Not implemented] Change my password
 | 
									[Not implemented] Change my password
 | 
				
			||||||
			</button>
 | 
								</button>
 | 
				
			||||||
 | 
					 | 
				
			||||||
		`;
 | 
							`;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
customElements.define('tf-password-form', TfPasswordFormElement);
 | 
					customElements.define('tf-password-form', TfPasswordFormElement);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,12 +26,18 @@ class TfThemePickerElement extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	render() {
 | 
						render() {
 | 
				
			||||||
		return html`
 | 
							return html`
 | 
				
			||||||
			<link rel="stylesheet" href="/static/tildefriends-v1.css"/>
 | 
								<link rel="stylesheet" href="/static/tildefriends-v1.css" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<label for="theme">[Not implemented] Choose your theme:</label>
 | 
								<label for="theme">[Not implemented] Choose your theme:</label>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<select name="theme" ?hidden=${!this.themes?.length} @change=${this.changed}>
 | 
								<select
 | 
				
			||||||
				${(this.themes ?? []).map((id) => html`<option value=${id}>${id}</option>`)}
 | 
									name="theme"
 | 
				
			||||||
 | 
									?hidden=${!this.themes?.length}
 | 
				
			||||||
 | 
									@change=${this.changed}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									${(this.themes ?? []).map(
 | 
				
			||||||
 | 
										(id) => html`<option value=${id}>${id}</option>`
 | 
				
			||||||
 | 
									)}
 | 
				
			||||||
			</select>
 | 
								</select>
 | 
				
			||||||
		`;
 | 
							`;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,8 +18,8 @@ body {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
button,
 | 
					button,
 | 
				
			||||||
.button,
 | 
					.button,
 | 
				
			||||||
input[type=button],
 | 
					input[type='button'],
 | 
				
			||||||
input[type=submit],
 | 
					input[type='submit'],
 | 
				
			||||||
select {
 | 
					select {
 | 
				
			||||||
	border: none;
 | 
						border: none;
 | 
				
			||||||
	border-radius: 8px;
 | 
						border-radius: 8px;
 | 
				
			||||||
@@ -75,7 +75,8 @@ table {
 | 
				
			|||||||
	width: 100%;
 | 
						width: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
td, th {
 | 
					td,
 | 
				
			||||||
 | 
					th {
 | 
				
			||||||
	border: 1px solid #ffffff40;
 | 
						border: 1px solid #ffffff40;
 | 
				
			||||||
	text-align: left;
 | 
						text-align: left;
 | 
				
			||||||
	padding: 8px;
 | 
						padding: 8px;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user