diff --git a/android/app/src/main/java/dev/dettmer/simplenotes/ui/editor/NoteEditorScreen.kt b/android/app/src/main/java/dev/dettmer/simplenotes/ui/editor/NoteEditorScreen.kt index dfe1cf5..3a4b966 100644 --- a/android/app/src/main/java/dev/dettmer/simplenotes/ui/editor/NoteEditorScreen.kt +++ b/android/app/src/main/java/dev/dettmer/simplenotes/ui/editor/NoteEditorScreen.kt @@ -338,6 +338,7 @@ private fun LazyItemScope.DraggableChecklistItem( onDelete: (String) -> Unit, onAddNewItemAfter: (String) -> Unit, onFocusHandled: () -> Unit, + onHeightChanged: () -> Unit, // ๐Ÿ†• v1.8.1 (IMPL_05) ) { val isDragging = dragDropState.draggingItemIndex == visualIndex val elevation by animateDpAsState( @@ -363,6 +364,7 @@ private fun LazyItemScope.DraggableChecklistItem( isDragging = isDragging, isAnyItemDragging = dragDropState.draggingItemIndex != null, dragModifier = Modifier.dragContainer(dragDropState, visualIndex), + onHeightChanged = onHeightChanged, // ๐Ÿ†• v1.8.1 (IMPL_05) modifier = Modifier .then(if (!isDragging) Modifier.animateItem() else Modifier) .offset { @@ -404,6 +406,9 @@ private fun ChecklistEditor( onMove = onMove ) + // ๐Ÿ†• v1.8.1 (IMPL_05): Auto-Scroll bei Zeilenumbruch + var scrollToItemIndex by remember { mutableStateOf(null) } + // ๐Ÿ†• v1.8.0 (IMPL_017 + IMPL_020): Separator nur bei MANUAL und UNCHECKED_FIRST anzeigen val uncheckedCount = items.count { !it.isChecked } val checkedCount = items.count { it.isChecked } @@ -418,6 +423,21 @@ private fun ChecklistEditor( dragDropState.separatorVisualIndex = separatorVisualIndex } + // ๐Ÿ†• v1.8.1 (IMPL_05): Auto-Scroll wenn ein Item durch Zeilenumbruch wรคchst + LaunchedEffect(scrollToItemIndex) { + scrollToItemIndex?.let { index -> + delay(50) // Warten bis Layout-Pass abgeschlossen + val lastVisibleIndex = listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0 + if (index >= lastVisibleIndex - 1) { + listState.animateScrollToItem( + index = minOf(index + 1, items.size + if (showSeparator) 1 else 0), + scrollOffset = 0 + ) + } + scrollToItemIndex = null + } + } + LazyColumn( state = listState, modifier = Modifier.weight(1f), @@ -438,7 +458,8 @@ private fun ChecklistEditor( onCheckedChange = onCheckedChange, onDelete = onDelete, onAddNewItemAfter = onAddNewItemAfter, - onFocusHandled = onFocusHandled + onFocusHandled = onFocusHandled, + onHeightChanged = { scrollToItemIndex = index } // ๐Ÿ†• v1.8.1 (IMPL_05) ) } @@ -466,7 +487,8 @@ private fun ChecklistEditor( onCheckedChange = onCheckedChange, onDelete = onDelete, onAddNewItemAfter = onAddNewItemAfter, - onFocusHandled = onFocusHandled + onFocusHandled = onFocusHandled, + onHeightChanged = { scrollToItemIndex = visualIndex } // ๐Ÿ†• v1.8.1 (IMPL_05) ) } } diff --git a/android/app/src/main/java/dev/dettmer/simplenotes/ui/editor/components/ChecklistItemRow.kt b/android/app/src/main/java/dev/dettmer/simplenotes/ui/editor/components/ChecklistItemRow.kt index 1c86102..575f976 100644 --- a/android/app/src/main/java/dev/dettmer/simplenotes/ui/editor/components/ChecklistItemRow.kt +++ b/android/app/src/main/java/dev/dettmer/simplenotes/ui/editor/components/ChecklistItemRow.kt @@ -25,6 +25,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -70,6 +71,7 @@ fun ChecklistItemRow( isDragging: Boolean = false, // ๐Ÿ†• v1.8.0: IMPL_023 - Drag state isAnyItemDragging: Boolean = false, // ๐Ÿ†• v1.8.0: IMPL_023 - Hide gradient during any drag dragModifier: Modifier = Modifier, // ๐Ÿ†• v1.8.0: IMPL_023 - Drag modifier for handle + onHeightChanged: (() -> Unit)? = null, // ๐Ÿ†• v1.8.1: IMPL_05 - Auto-scroll callback modifier: Modifier = Modifier ) { val focusRequester = remember { FocusRequester() } @@ -91,6 +93,9 @@ fun ChecklistItemRow( // ๐Ÿ†• v1.8.0: ScrollState fรผr dynamischen Gradient val scrollState = rememberScrollState() + // ๐Ÿ†• v1.8.1: IMPL_05 - Letzte Zeilenanzahl tracken fรผr Auto-Scroll + var lastLineCount by remember { mutableIntStateOf(0) } + // ๐Ÿ†• v1.8.1: Gradient-Sichtbarkeit direkt berechnet (kein derivedStateOf) // derivedStateOf mit remember{} fรคngt showGradient als stale val โ€” nie aktualisiert. val showGradient = hasOverflow && collapsedHeightDp != null && !isFocused && !isAnyItemDragging @@ -216,8 +221,9 @@ fun ChecklistItemRow( cursorBrush = SolidColor(MaterialTheme.colorScheme.primary), onTextLayout = { textLayoutResult -> // ๐Ÿ†• v1.8.1: lineCount ist jetzt akkurat (maxLines=MAX_VALUE deckelt nicht) + val lineCount = textLayoutResult.lineCount if (!isAnyItemDragging) { - val overflow = textLayoutResult.lineCount > COLLAPSED_MAX_LINES + val overflow = lineCount > COLLAPSED_MAX_LINES hasOverflow = overflow // Hรถhe der ersten 5 Zeilen berechnen (einmalig) if (overflow && collapsedHeightDp == null) { @@ -230,6 +236,11 @@ fun ChecklistItemRow( collapsedHeightDp = null } } + // ๐Ÿ†• v1.8.1 (IMPL_05): Hรถhenรคnderung bei Zeilenumbruch melden + if (isFocused && lineCount > lastLineCount && lastLineCount > 0) { + onHeightChanged?.invoke() + } + lastLineCount = lineCount }, decorationBox = { innerTextField -> Box {