diff options
| author | Adam Soltys <[email protected]> | 2026-08-28 21:00:11 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-28 21:00:11 -0700 |
| commit | f13acc1bf4ffa3d0e2733dc53041bbc61659a5af (patch) | |
| tree | 2a67050e4800848dabe7fba7a7b9912e51b4025a | |
| parent | 339e9badc0f06c098f2236af90501572bde1defa (diff) | |
| download | coinosv3-f13acc1bf4ffa3d0e2733dc53041bbc61659a5af.tar.gz coinosv3-f13acc1bf4ffa3d0e2733dc53041bbc61659a5af.zip | |
The profile editor learns to take a photo, not just a URL: an Upload button feeds the same signed nostr.build path the onboarding picker uses and fills the picture field with the result
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
| -rw-r--r-- | src/app.js | 3 | ||||
| -rw-r--r-- | src/features/messages.js | 18 | ||||
| -rw-r--r-- | src/i18n.js | 1 |
3 files changed, 22 insertions, 0 deletions
@@ -4439,6 +4439,9 @@ const ctx = { setAccount: (a, dir) => setAccountSel(a, dir), // Open (or create) a wallet from a mnemonic — used by nostr login. openMnemonic: async (mnemonic, passphrase, opts) => enterWallet(mnemonic, passphrase, opts), + // Upload an image (avatar) and get back its URL — the same signed + // nostr.build path the onboarding picker uses. + uploadImage: (file) => onbUpload(file), // A nostr login that lands mid-wizard: a restored wallet has been through // onboarding elsewhere, so the wizard ends without tour or prompts; a fresh // one falls through to the wallet + tour on the next render. diff --git a/src/features/messages.js b/src/features/messages.js index be1abf5..eea4fbf 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -1723,6 +1723,24 @@ export function messagesFeature(ctx) { field(t('profDisplayName'), 'name'), field(t('profAbout'), 'about', '', true), field(t('profPicture'), 'picture', 'https://…'), + // or skip the URL entirely: pick a photo, we upload and fill it + h('div', { class: 'row gap6' }, + h('button', { + class: 'btn-sm', type: 'button', disabled: !!ui.profUploading, + onClick: () => document.getElementById('prof-pic-file')?.click(), + }, ui.profUploading ? h('span', { class: 'spinner sm' }) : t('profUploadPic')), + h('input', { + id: 'prof-pic-file', type: 'file', accept: 'image/*', style: 'display:none', + onChange: async (e) => { + const f = e.target.files && e.target.files[0]; + e.target.value = ''; + if (!f || !ctx.uploadImage) return; + ui.profUploading = true; render(); + try { if (ui.profEdit) ui.profEdit.picture = await ctx.uploadImage(f); } + catch (err) { toast(err.message); } + ui.profUploading = false; render(); + }, + })), h('button', { class: 'btn-primary btn-block', disabled: ui.profSaving, onClick: saveProfile }, ui.profSaving ? h('span', { class: 'spinner sm' }) : t('save')), logoutBtn()) diff --git a/src/i18n.js b/src/i18n.js index 42ad2e0..ec151f6 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -85,6 +85,7 @@ const STR = { enterPassword: 'Enter your password', enterPasswordDesc: 'Unlock your saved accounts to continue.', profUsername: 'Username', + profUploadPic: 'Upload photo', profDisplayName: 'Display name', profUnameInvalid: 'Usernames can only use letters, numbers, dots, dashes and underscores.', lockSaveDesc: 'The accounts already saved on this device are protected by a password. Enter it to save this account with them and lock.', |
