Skip to content

Commit 05803d3

Browse files
Fixing line jump to top (#585)
* Fixing line jump to top * code clean
1 parent bd8e8bf commit 05803d3

File tree

4 files changed

+40
-2
lines changed

4 files changed

+40
-2
lines changed

writeopia/src/commonMain/kotlin/io/writeopia/sdk/model/story/Selection.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ package io.writeopia.sdk.model.story
77
* @property end the end of the cursor in the paragraph
88
* @property position the position of the paragraph (which line the cursor is)
99
*/
10-
data class Selection(val start: Int, val end: Int, val position: Int) {
10+
data class Selection(
11+
val start: Int,
12+
val end: Int,
13+
val position: Int,
14+
val fromEnd: Boolean = false
15+
) {
1116
fun key() = if (start == end) hashCode() else 0
1217

1318
fun sortedPositions(): Pair<Int, Int> = if (start < end) start to end else end to start
@@ -19,5 +24,8 @@ data class Selection(val start: Int, val end: Int, val position: Int) {
1924

2025
fun fromPosition(cursorPosition: Int, stepPosition: Int) =
2126
Selection(cursorPosition, cursorPosition, stepPosition)
27+
28+
fun fromLastLine(cursorPosition: Int, stepPosition: Int) =
29+
Selection(cursorPosition, cursorPosition, stepPosition, fromEnd = true)
2230
}
2331
}

writeopia_ui/src/commonMain/kotlin/io/writeopia/ui/drawer/content/TextDrawer.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ class TextDrawer(
119119
var textLayoutResult by remember {
120120
mutableStateOf<TextLayoutResult?>(null)
121121
}
122+
123+
// Recalculate selection for last-line positioning when layout becomes available
124+
LaunchedEffect(textLayoutResult, drawInfo.selection) {
125+
val selection = drawInfo.selection
126+
if (selection != null && selection.fromEnd && textLayoutResult != null) {
127+
val newRange = selection.toTextRange(step.text ?: "", textLayoutResult)
128+
if (inputText.selection != newRange) {
129+
inputText = inputText.copy(selection = newRange)
130+
}
131+
}
132+
}
133+
122134
val cursorLine by remember {
123135
derivedStateOf {
124136
textLayoutResult?.getLineForOffset(inputText.selection.end)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
11
package io.writeopia.ui.extensions
22

3+
import androidx.compose.ui.text.TextLayoutResult
34
import androidx.compose.ui.text.TextRange
45
import io.writeopia.sdk.model.story.Selection
56
import kotlin.math.min
67

78
fun Selection.toTextRange(text: String) =
89
TextRange(start = min(start, text.length), end = min(end, text.length))
10+
11+
fun Selection.toTextRange(text: String, textLayoutResult: TextLayoutResult?): TextRange =
12+
when {
13+
fromEnd && textLayoutResult != null && textLayoutResult.lineCount > 0 -> {
14+
val lastLineIndex = textLayoutResult.lineCount - 1
15+
val lastLineStart = textLayoutResult.getLineStart(lastLineIndex)
16+
val lastLineEnd = textLayoutResult.getLineEnd(lastLineIndex)
17+
val lastLineLength = lastLineEnd - lastLineStart
18+
val cursorPos = lastLineStart + min(start, lastLineLength)
19+
TextRange(cursorPos, cursorPos)
20+
}
21+
22+
// Fallback when no layout yet: position at end, will be corrected later
23+
fromEnd -> TextRange(text.length, text.length)
24+
25+
else -> TextRange(start = min(start, text.length), end = min(end, text.length))
26+
}

writeopia_ui/src/commonMain/kotlin/io/writeopia/ui/manager/WriteopiaStateManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ class WriteopiaStateManager(
12821282

12831283
_currentStory.value = storyState.copy(
12841284
focus = newPosition,
1285-
selection = Selection.fromPosition(cursor, newPosition),
1285+
selection = Selection.fromLastLine(cursor, newPosition),
12861286
stories = mutable
12871287
)
12881288
}

0 commit comments

Comments
 (0)