@@ -291,13 +312,17 @@ const props = withDefaults(defineProps
(), {
const emit = defineEmits()
const { loginWithNostr, isLoading: authLoading } = useAuth()
-const { loginWithExtension } = useAccounts()
+const { loginWithExtension, loginWithPrivateKey } = useAccounts()
const mode = ref<'login' | 'register' | 'forgot'>(props.defaultMode)
const errorMessage = ref(null)
const isLoading = computed(() => authLoading.value || sovereignGenerating.value)
-// Amber login state
+// nsec login (tap to reveal field)
+const showNsecField = ref(false)
+const nsecInput = ref('')
+
+// Amber login state (hidden for now)
const amberPhase = ref<'idle' | 'waiting-pubkey' | 'waiting-signature' | 'completing'>('idle')
const amberPubkey = ref(null)
const amberUnsignedEvent = ref(null)
@@ -322,6 +347,8 @@ watch(() => props.isOpen, (open) => {
sovereignDismissed.value = false
generatedKeys.value = null
errorMessage.value = null
+ showNsecField.value = false
+ nsecInput.value = ''
cancelAmber()
}
})
@@ -471,6 +498,33 @@ async function handleNostrLogin() {
}
}
+function cancelNsecField() {
+ showNsecField.value = false
+ nsecInput.value = ''
+ errorMessage.value = null
+}
+
+/**
+ * Sign in with pasted nsec. Adds account, sets active, then creates backend session.
+ */
+async function handleNsecSubmit() {
+ const nsec = nsecInput.value.trim()
+ if (!nsec) return
+ errorMessage.value = null
+ try {
+ await loginWithPrivateKey(nsec)
+ const account = accountManager.active
+ if (!account) throw new Error('Account not set')
+ await loginWithNostr(account.pubkey, 'nsec', {}, undefined)
+ nsecInput.value = ''
+ showNsecField.value = false
+ emit('success')
+ closeModal()
+ } catch (err: any) {
+ errorMessage.value = err.message || 'Invalid nsec or sign-in failed.'
+ }
+}
+
/**
* Clean up Amber flow state, timers, and event listeners.
*/
@@ -809,6 +863,42 @@ declare global {
color: rgba(255, 255, 255, 0.3);
}
+/* nsec login field block */
+.nsec-field-block {
+ padding: 0.5rem 0;
+}
+.nsec-hint {
+ font-size: 0.8125rem;
+ color: rgba(255, 255, 255, 0.5);
+ margin-bottom: 0.5rem;
+ line-height: 1.4;
+}
+.nsec-field-block .auth-input {
+ margin-bottom: 0.5rem;
+}
+.nsec-actions {
+ display: flex;
+ gap: 0.5rem;
+ align-items: center;
+ margin-top: 0.5rem;
+}
+.nsec-cancel-btn {
+ padding: 0.5rem 1rem;
+ font-size: 0.875rem;
+ font-weight: 500;
+ color: rgba(255, 255, 255, 0.6);
+ background: transparent;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 12px;
+ cursor: pointer;
+ transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
+}
+.nsec-cancel-btn:hover {
+ color: rgba(255, 255, 255, 0.9);
+ border-color: rgba(255, 255, 255, 0.2);
+ background: rgba(255, 255, 255, 0.05);
+}
+
/* Modal Transitions */
.modal-fade-enter-active,
.modal-fade-leave-active {