package com.peachpasswords.ui.vault import androidx.activity.compose.BackHandler import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material.icons.outlined.Add import androidx.compose.material.icons.outlined.Close import androidx.compose.material.icons.outlined.DeleteOutline import androidx.compose.material.icons.outlined.Search import androidx.compose.material3.Icon import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.runtime.collectAsState import androidx.hilt.navigation.compose.hiltViewModel import com.peachpasswords.haptics.PeachHaptics import com.peachpasswords.ui.components.PeachEmptyOrEndState import com.peachpasswords.ui.PeachNav import com.peachpasswords.ui.components.SecureFlagEffect import com.peachpasswords.ui.theme.PeachSpacing import com.peachpasswords.ui.theme.PeachRadius import com.peachpasswords.vault.VaultEntry import com.peachpasswords.ui.theme.LocalPeachAccent import com.peachpasswords.ui.theme.peachColors import com.peachpasswords.ui.theme.PeachType import com.peachpasswords.ui.theme.ShellBackground /** * E2 — full-screen editor for NOTE-type entries. Editable inline title, a B/I/U * formatting toolbar, a full-width Inter body, and an 800ms-debounced auto-save * with a "saved." pulse. FLAG_SECURE blocks screenshots while open (same as * EntryDetail). * * The body opens rendered (see NoteHtml.kt) and switches to the editor on tap, * because a note written in the browser is HTML and Compose has no text field * that can edit styled text without dropping the styles. Formatting typed here * is saved back as the browser's own tag vocabulary. */ @Composable fun NotesModeScreen( onBack: () -> Unit, onNavigate: (PeachNav) -> Unit, vm: NotesModeViewModel = hiltViewModel(), ) { val entry by vm.entry.collectAsState() val notes by vm.notes.collectAsState() val activeNoteId by vm.activeNoteId.collectAsState() val isMultiSelect by vm.isMultiSelectMode.collectAsState() val selectedIds by vm.selectedIds.collectAsState() val savedPulse by vm.savedPulse.collectAsState() val accent = LocalPeachAccent.current SecureFlagEffect() // "saved." indicator fades in on each save pulse, holds, then fades out. var showSaved by remember { mutableStateOf(false) } LaunchedEffect(savedPulse) { if (savedPulse == 0L) return@LaunchedEffect showSaved = true kotlinx.coroutines.delay(1300) showSaved = false } val savedAlpha by animateFloatAsState( targetValue = if (showSaved) 1f else 0f, animationSpec = tween(300), label = "saved-fade", ) if (activeNoteId == null) { NotesToc( notes = notes, onBack = onBack, onOpenNote = vm::openNote, onNewNote = vm::createNote, isMultiSelect = isMultiSelect, selectedIds = selectedIds, onEnterMultiSelect = vm::enterMultiSelect, onToggleSelected = vm::toggleSelected, onDeleteSelected = vm::batchDelete, onCancelMultiSelect = vm::exitMultiSelect, onNavigate = onNavigate, onLock = vm::lock, ) return } val e = entry val stored = e?.notes.orEmpty() var title by remember(e?.id) { mutableStateOf(e?.title ?: "") } var body by remember(e?.id) { mutableStateOf(TextFieldValue(noteEditorText(stored))) } // A note stays plain text until the user asks for formatting, so typing // "- eggs" into a shopping list never turns it into a