Skip to content

Commit b662f1e

Browse files
authored
Merge pull request #9 from kaleidot725/fix_perfomance_bug
Fix perfomance bug
2 parents 6944545 + c34e9c3 commit b662f1e

File tree

6 files changed

+46
-63
lines changed

6 files changed

+46
-63
lines changed

.github/workflows/pull_request_check.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
java-version: '17'
1616
- uses: actions/setup-ruby@v1
1717
with:
18-
ruby-version: '3.0'
18+
ruby-version: '3'
1919
- name: Install danger
2020
run: |
2121
gem install danger danger-junit danger-android_lint danger-checkstyle_format

.idea/misc.xml

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Dangerfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@ warn("Big PR") if git.lines_of_code > 500
33

44
# Notify ktlint warning
55
checkstyle_format.base_path = Dir.pwd
6-
checkstyle_format.report 'app/build/reports/ktlint/ktlintMainSourceSetCheck/ktlintMainSourceSetCheck.xml'
76
checkstyle_format.report 'texteditor/build/reports/ktlint/ktlintMainSourceSetCheck/ktlintMainSourceSetCheck.xml'
87

texteditor/src/main/java/jp/kaleidot725/texteditor/controller/EditorController.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package jp.kaleidot725.texteditor.controller
22

3+
import android.util.Log
34
import androidx.compose.runtime.Composable
45
import androidx.compose.runtime.mutableStateOf
56
import androidx.compose.runtime.remember
@@ -44,6 +45,10 @@ internal class EditorController(
4445

4546
fun splitNewLine(targetIndex: Int, textFieldValue: TextFieldValue) {
4647
lock.withLock {
48+
if (_fields.count { it.isSelected } > 1) {
49+
Log.v("TEST", "NEWLINE ERROR")
50+
}
51+
4752
if (targetIndex < 0 || fields.count() <= targetIndex) {
4853
throw InvalidParameterException("targetIndex out of range($targetIndex)")
4954
}
@@ -228,9 +233,9 @@ internal class EditorController(
228233
}
229234

230235
private fun clearSelectedIndicesInternal() {
231-
_selectedIndices
232-
.filter { _fields.getOrNull(it) != null }
233-
.forEach { index -> _fields[index] = _fields[index].copy(isSelected = false) }
236+
val copyFields = _fields.toList().map { it.copy(isSelected = false) }
237+
_fields.clear()
238+
_fields.addAll(copyFields)
234239
_selectedIndices.clear()
235240
}
236241

@@ -266,9 +271,8 @@ internal class EditorController(
266271
targetIndex
267272
)
268273
} else {
269-
val isSelected = true
270274
val copyTarget = target.copy(
271-
isSelected = isSelected,
275+
isSelected = true,
272276
value = target.value.copy(selection = selection)
273277
)
274278
this.clearSelectedIndicesInternal()

texteditor/src/main/java/jp/kaleidot725/texteditor/view/TextEditor.kt

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package jp.kaleidot725.texteditor.view
22

3-
import android.util.Log
43
import androidx.compose.foundation.clickable
54
import androidx.compose.foundation.interaction.MutableInteractionSource
65
import androidx.compose.foundation.layout.Box
@@ -20,6 +19,7 @@ import androidx.compose.ui.Modifier
2019
import androidx.compose.ui.focus.FocusRequester
2120
import jp.kaleidot725.texteditor.controller.rememberTextEditorController
2221
import jp.kaleidot725.texteditor.state.TextEditorState
22+
import java.util.Date
2323

2424
typealias DecorationBoxComposable = @Composable (
2525
index: Int,
@@ -37,37 +37,13 @@ fun TextEditor(
3737
) {
3838
val textEditorState by rememberUpdatedState(newValue = textEditorState)
3939
val editableController by rememberTextEditorController(textEditorState, onChanged = { onChanged(it) })
40-
var lastEvent by remember { mutableStateOf(null as Event?) }
40+
var lastScrollEvent by remember { mutableStateOf(null as ScrollEvent?) }
4141
val lazyColumnState = rememberLazyListState()
4242
val focusRequesters by remember { mutableStateOf(mutableMapOf<Int, FocusRequester>()) }
43-
4443
editableController.syncState(textEditorState)
4544

46-
LaunchedEffect(lastEvent) {
47-
when (val event = lastEvent) {
48-
is Event.AddNewLine -> {
49-
lazyColumnState.animateScrollToItem(event.index)
50-
}
51-
is Event.DeleteNewLine -> {
52-
lazyColumnState.animateScrollToItem(event.index)
53-
}
54-
is Event.Down -> {
55-
lazyColumnState.animateScrollToItem(event.index)
56-
}
57-
is Event.Up -> {
58-
lazyColumnState.animateScrollToItem(event.index)
59-
}
60-
else -> {}
61-
}
62-
}
63-
64-
LaunchedEffect(textEditorState.selectedIndices) {
65-
val targetIndex = textEditorState.selectedIndices.firstOrNull() ?: return@LaunchedEffect
66-
try {
67-
focusRequesters[targetIndex]?.requestFocus()
68-
} catch (e: Exception) {
69-
Log.d("TextEditor", "Warning $e")
70-
}
45+
LaunchedEffect(lastScrollEvent) {
46+
lastScrollEvent?.index?.let { lazyColumnState.scrollToItem(it) }
7147
}
7248

7349
LazyColumn(
@@ -118,28 +94,34 @@ fun TextEditor(
11894
editableController.updateField(targetIndex = index, textFieldValue = newText)
11995
},
12096
onContainNewLine = { newText ->
97+
if (lastScrollEvent != null && lastScrollEvent?.isConsumed != true) return@TextField
12198
editableController.splitNewLine(targetIndex = index, textFieldValue = newText)
122-
lastEvent = Event.AddNewLine(index + 1)
99+
lastScrollEvent = ScrollEvent(index + 1)
123100
},
124101
onAddNewLine = { newText ->
102+
if (lastScrollEvent != null && lastScrollEvent?.isConsumed != true) return@TextField
125103
editableController.splitAtCursor(targetIndex = index, textFieldValue = newText)
126-
lastEvent = Event.AddNewLine(index + 1)
104+
lastScrollEvent = ScrollEvent(index + 1)
127105
},
128106
onDeleteNewLine = {
107+
if (lastScrollEvent != null && lastScrollEvent?.isConsumed != true) return@TextField
129108
editableController.deleteField(targetIndex = index)
130-
if (index != 0) lastEvent = Event.DeleteNewLine(index - 1)
109+
if (index != 0) lastScrollEvent = ScrollEvent(index - 1)
131110
},
132111
onFocus = {
133112
editableController.selectField(index)
134113
},
135114
onUpFocus = {
115+
if (lastScrollEvent != null && lastScrollEvent?.isConsumed != true) return@TextField
136116
editableController.selectPreviousField()
137-
if (index != 0) lastEvent = Event.DeleteNewLine(index - 1)
117+
if (index != 0) lastScrollEvent = ScrollEvent(index - 1)
138118
},
139119
onDownFocus = {
120+
if (lastScrollEvent != null && lastScrollEvent?.isConsumed != true) return@TextField
140121
editableController.selectNextField()
141-
lastEvent = Event.AddNewLine(index + 1)
142-
}
122+
if (index != textEditorState.fields.lastIndex) lastScrollEvent = ScrollEvent(index + 1)
123+
},
124+
scrollEvent = if (lastScrollEvent?.index == index) lastScrollEvent else null
143125
)
144126
}
145127
}
@@ -148,9 +130,11 @@ fun TextEditor(
148130
}
149131
}
150132

151-
sealed class Event(val time: Long, val index: Int = -1) {
152-
class Up(index: Int) : Event(System.currentTimeMillis(), index)
153-
class Down(index: Int) : Event(System.currentTimeMillis(), index)
154-
class AddNewLine(index: Int) : Event(System.currentTimeMillis(), index)
155-
class DeleteNewLine(index: Int) : Event(System.currentTimeMillis(), index)
133+
data class ScrollEvent(val index: Int = -1, val time: Long = Date().time) {
134+
var isConsumed: Boolean = false
135+
private set
136+
137+
fun consume() {
138+
isConsumed = true
139+
}
156140
}

texteditor/src/main/java/jp/kaleidot725/texteditor/view/TextField.kt

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import android.view.KeyEvent.KEYCODE_DEL
44
import android.view.KeyEvent.KEYCODE_DPAD_DOWN
55
import android.view.KeyEvent.KEYCODE_DPAD_UP
66
import android.view.KeyEvent.KEYCODE_ENTER
7-
import androidx.compose.foundation.layout.Box
87
import androidx.compose.foundation.layout.fillMaxWidth
98
import androidx.compose.foundation.layout.wrapContentHeight
109
import androidx.compose.foundation.text.BasicTextField
@@ -37,18 +36,28 @@ internal fun TextField(
3736
onFocus: () -> Unit,
3837
onUpFocus: () -> Unit,
3938
onDownFocus: () -> Unit,
40-
modifier: Modifier = Modifier
39+
modifier: Modifier = Modifier,
40+
scrollEvent: ScrollEvent? = null
4141
) {
4242
val currentTextField by rememberUpdatedState(newValue = textFieldState.value)
4343

4444
LaunchedEffect(textFieldState.isSelected) {
4545
if (textFieldState.isSelected) {
46+
scrollEvent?.consume()
4647
focusRequester.requestFocus()
4748
}
4849
}
4950

50-
Box(
51+
BasicTextField(
52+
value = textFieldState.value,
53+
enabled = enabled,
54+
onValueChange = {
55+
if (currentTextField == it) return@BasicTextField
56+
if (it.text.contains('\n')) onContainNewLine(it) else onUpdateText(it)
57+
},
5158
modifier = modifier
59+
.fillMaxWidth()
60+
.wrapContentHeight()
5261
.focusTarget()
5362
.focusRequester(focusRequester)
5463
.onFocusChanged { if (it.isFocused) onFocus() }
@@ -70,19 +79,7 @@ internal fun TextField(
7079

7180
false
7281
}
73-
) {
74-
BasicTextField(
75-
value = textFieldState.value,
76-
enabled = enabled,
77-
onValueChange = {
78-
if (currentTextField == it) return@BasicTextField
79-
if (it.text.contains('\n')) onContainNewLine(it) else onUpdateText(it)
80-
},
81-
modifier = Modifier
82-
.fillMaxWidth()
83-
.wrapContentHeight()
84-
)
85-
}
82+
)
8683
}
8784

8885
private fun onPreviewDelKeyEvent(

0 commit comments

Comments
 (0)