-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/bigtext' into 'main'
BigText See merge request products/hello-http!23
- Loading branch information
Showing
115 changed files
with
14,797 additions
and
493 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
name: Debug Verification Tests | ||
on: | ||
push: | ||
branches: | ||
- '**' | ||
jobs: | ||
test: | ||
strategy: | ||
matrix: | ||
# macos-12 for Intel Mac, macos-14 for Apple Chips Mac | ||
os: [ubuntu-20.04, windows-2019, windows-2022, macos-12, macos-14] | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-java@v3 | ||
with: | ||
distribution: 'corretto' | ||
java-version: '17' | ||
- run: | | ||
export GRADLE_OPTS='-Xmx64m -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx3072m -XX:+HeapDumpOnOutOfMemoryError"' | ||
./gradlew jvmTest --tests 'com.sunnychung.application.multiplatform.hellohttp.test.util.ChunkedLatestFlowTest' | ||
shell: bash # let Windows use bash | ||
- uses: actions/upload-artifact@v3 | ||
with: | ||
name: ux-test-result_${{ matrix.os }} | ||
path: ux-and-transport-test/build/reports/tests/test | ||
if: ${{ always() }} | ||
- uses: actions/upload-artifact@v3 | ||
with: | ||
name: unit-test-result_${{ matrix.os }} | ||
path: build/reports/tests | ||
if: ${{ always() }} | ||
- uses: actions/upload-artifact@v3 | ||
with: | ||
name: ux-test-error_${{ matrix.os }} | ||
path: ux-and-transport-test/test-error.png | ||
if: ${{ always() }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Layout Queries | ||
|
||
## Definition of Row Index | ||
|
||
- 0: The first row to the user. Start from the beginning of the string. | ||
- 1: The 2nd row to the user. Start from the 1st (index = 0) row break. | ||
- 2: The 3rd row to the user. Start from the 2nd (index = 1) row break. | ||
- 3: The 4th row to the user. Start from the 3rd (index = 2) row break. | ||
|
||
### Example (Test case `BigTextImplLayoutTest#insertTriggersRelayout1`) | ||
|
||
For a string `"abcd\nABCDEFGHIJ<BCDEFGHIJ<xyz\nabcd"` and chunk size is `10`, mapping is as follows: | ||
|
||
| Char Index | Row Index | Line Index | | ||
|------------|-----------|------------| | ||
| 0 | 0 | 0 | | ||
| 5 | 1 | 1 | | ||
| 15 | 2 | 1 | | ||
| 25 | 3 | 1 | | ||
| 30 | 4 | 2 | | ||
|
||
|
||
## `findLineIndexByRowIndex` | ||
|
||
### Locate the interested node | ||
|
||
#### Example | ||
|
||
Assume we want to locate the node containing row index 3. | ||
|
||
Case 1: The node contains the 3rd row break. | ||
|
||
Case 2: The node is the last node, contains the 2nd row break and "is end with force row break". | ||
|
||
#### General algorithm | ||
|
||
Assume we want to locate the node containing row index `x`. | ||
|
||
Case 1: The node contains the `x`-th row break. | ||
|
||
Case 2: The node is the last node, contains the `(x - 1)`-th row break and "is end with force row break". | ||
|
||
Case 3: The node is the first node and `x` is 0. `x` is ahead of all row breaks. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Line Queries | ||
|
||
## Find Line Index and Column Index | ||
|
||
Example: | ||
|
||
```mermaid | ||
block-beta | ||
columns 20 | ||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ||
a c1["#92;n"] b c d c5["#92;n"] e f c8["#92;n"] g h i j k l c15["#92;n"] c16["#92;n"] m n c19["#92;n"] | ||
``` | ||
|
||
Line break indices are: | ||
```mermaid | ||
block-beta | ||
columns 6 | ||
0 1 2 3 4 5 | ||
l0["1"] l1["5"] 8 15 16 19 | ||
``` | ||
|
||
```mermaid | ||
block-beta | ||
columns 20 | ||
H0["0"] H1["1"] H2["2"] H3["3"] H4["4"] H5["5"] H6["6"] H7["7"] H8["8"] H9["9"] H10["10"] H11["11"] H12["12"] H13["13"] H14["14"] H15["15"] H16["16"] H17["17"] H18["18"] H19["19"] | ||
a c1["#92;n"] b c d c5["#92;n"] e f c8["#92;n"] g h i j k l c15["#92;n"] c16["#92;n"] m n c19["#92;n"] | ||
space:20 | ||
space:20 | ||
space:7 L0 L1 L2 L3 L4 L5 space:7 | ||
space:7 l0["1"] l1["5"] 8 15 16 19 | ||
a-->L0 | ||
c1-->L0 | ||
b-->L1 | ||
c-->L1 | ||
d-->L1 | ||
c5-->L1 | ||
e-->L2 | ||
f-->L2 | ||
c8-->L2 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
# Transform Replaces | ||
|
||
## Block-offset transforms | ||
|
||
- Transformed positions are never mapped from original positions | ||
- New transform inserts to the same position of existing block-offset transforms would append the new text to the end of it | ||
|
||
### `simpleBlockTransformReplaces` first test case | ||
|
||
```mermaid | ||
block-beta | ||
columns 20 | ||
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | ||
O40["<"] O41["r"] O42["o"] O43["w"] O44[" "] O45["b"] O46["r"] O47["e"] O48["a"] O49["k"] O50["<"] O51[" "] O52["s"] O53["h"] O54["o"] O55["u"] O56["l"] O57["d"] O58[" "] O59["h"] | ||
space:20 | ||
T40["<"] T41["r"] T42["o"] T43["w"] T44[" "] T45["-"] T46["+"] T47["-"] T48["+"] T49["-"] T50["h"] T51["o"] T52["u"] T53["l"] T54["d"] T55[" "] T56["h"] T57["<"] T58["a"] T59["p"] | ||
space:20 | ||
o40["<"] o41["r"] o42["o"] o43["w"] o44[" "] o45["b"] o46["r"] o47["e"] o48["a"] o49["k"] o50["<"] o51[" "] o52["s"] o53["h"] o54["o"] o55["u"] o56["l"] o57["d"] o58[" "] o59["h"] | ||
style O45 fill:#d00 | ||
style O46 fill:#d00 | ||
style O47 fill:#d00 | ||
style O48 fill:#d00 | ||
style O49 fill:#d00 | ||
style O50 fill:#d00 | ||
style O51 fill:#d00 | ||
style O52 fill:#d00 | ||
style T45 fill:#060 | ||
style T46 fill:#060 | ||
style T47 fill:#060 | ||
style T48 fill:#060 | ||
style T49 fill:#060 | ||
style o45 fill:#d00 | ||
style o46 fill:#d00 | ||
style o47 fill:#d00 | ||
style o48 fill:#d00 | ||
style o49 fill:#d00 | ||
style o50 fill:#d00 | ||
style o51 fill:#d00 | ||
style o52 fill:#d00 | ||
O43-->T43 | ||
O44-->T44 | ||
O53-->T50 | ||
O54-->T51 | ||
O45 --> T50 | ||
O46 --> T50 | ||
O47 -.-> T50 | ||
O48 -.-> T50 | ||
O49 -.-> T50 | ||
O50 -.-> T50 | ||
O51 -.-> T50 | ||
O52 -.-> T50 | ||
T43 --> o43 | ||
T44 --> o44 | ||
T50 --> o53 | ||
T51 --> o54 | ||
T45 --> o45 | ||
T46 --> o45 | ||
T47 --> o45 | ||
T48 --> o45 | ||
T49 --> o45 | ||
``` | ||
|
||
## Incremental-offset transforms | ||
|
||
- Transformed positions are mapped 1-to-1 from original positions, until the earliest end of either one | ||
- New transform inserts to the same position of existing incremental-offset transforms would append the new text to the start of it | ||
|
||
### `mixedTransformReplaces` first test case | ||
|
||
```mermaid | ||
block-beta | ||
columns 20 | ||
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | ||
O30["<"] O31["B"] O32["C"] O33["D"] O34["E"] O35["F"] O36["G"] O37["H"] O38["I"] O39["J"] O40["<"] O41["r"] O42["o"] O43["w"] O44[" "] O45["b"] O46["r"] O47["e"] O48["a"] O49["k"] | ||
space:20 | ||
space:20 | ||
T30["<"] T31["B"] T32["l"] T33["o"] T34["n"] T35["g"] T36[" "] T37["r"] T38["e"] T39["p"] T40["l"] T41["a"] T42["c"] T43["e"] T44["m"] T45["e"] T46["n"] T47["t"] T48["H"] T49["I"] | ||
space:20 | ||
o30["<"] o31["B"] o32["C"] o33["D"] o34["E"] o35["F"] o36["G"] o37["H"] o38["I"] o39["J"] o40["<"] o41["r"] o42["o"] o43["w"] o44[" "] o45["b"] o46["r"] o47["e"] o48["a"] o49["k"] | ||
style O32 fill:#d00 | ||
style O33 fill:#d00 | ||
style O34 fill:#d00 | ||
style O35 fill:#d00 | ||
style O36 fill:#d00 | ||
style T32 fill:#060 | ||
style T33 fill:#060 | ||
style T34 fill:#060 | ||
style T35 fill:#060 | ||
style T36 fill:#060 | ||
style T37 fill:#060 | ||
style T38 fill:#060 | ||
style T39 fill:#060 | ||
style T40 fill:#060 | ||
style T41 fill:#060 | ||
style T42 fill:#060 | ||
style T43 fill:#060 | ||
style T44 fill:#060 | ||
style T45 fill:#060 | ||
style T46 fill:#060 | ||
style T47 fill:#060 | ||
O30-->T30 | ||
O31-->T31 | ||
O37-->T48 | ||
O38-->T49 | ||
O32 -.-> T32 | ||
O33 -.-> T33 | ||
O34 -.-> T34 | ||
O35 -.-> T35 | ||
O36 -.-> T36 | ||
``` | ||
|
||
## Transform inserts | ||
|
||
Transform inserts behaves the same as block-offset transform replaces without deletions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Text Value Mutation Callback | ||
|
||
## Method 1: Receive via Flow | ||
|
||
Listen to changes via reactive `Flow`. Convert `BigText` back to `String` on every event. Use a `debounce` operator to reduce number of conversions. | ||
|
||
### Advantage | ||
- Clear control of expensive operations | ||
|
||
### Disadvantage | ||
- Need to maintain a unique cache key per text instance. | ||
- The expensive `BigText#fullString` is invoked frequently (but the interval is controllable). | ||
- Result is not immediately obtained, which may be a trouble in state synchronization. | ||
|
||
```kotlin | ||
val bigTextFieldState = rememberBigTextFieldState(cacheKey, textValue.text) | ||
val scrollState = rememberScrollState() | ||
|
||
bigTextFieldState.valueChangesFlow | ||
.debounce(1.seconds().toMilliseconds()) | ||
.onEach { | ||
onTextChange?.let { onTextChange -> | ||
onTextChange(it.bigText.fullString()) | ||
} | ||
bigTextValueId = it.changeId | ||
} | ||
.launchIn(CoroutineScope(Dispatchers.Main)) | ||
|
||
BigMonospaceTextField( | ||
textFieldState = bigTextFieldState, | ||
visualTransformation = visualTransformationToUse, | ||
fontSize = LocalFont.current.codeEditorBodyFontSize, | ||
scrollState = scrollState, | ||
modifier = Modifier.fillMaxSize() | ||
) | ||
``` | ||
## Method 2: Wrap BigText as CharSequence | ||
|
||
### Advantage | ||
- Able to keep the declarative code pattern | ||
- The actual value is immediately available when it is needed | ||
- The expensive `BigText#fullString` is never invoked if it is not needed | ||
|
||
### Disadvantage | ||
- Need to change the usage of String type in models and composables to CharSequence (or BigText). | ||
- The expensive `BigText#fullString` may be invoked (via `BigTextAsCharSequence#toString`) out of control. | ||
- Lots of code changes to an existing code base, hence a significant risk to existing projects. | ||
- Memory usage can be higher, as BigText uses more memory than String in linear to number of changes. | ||
|
||
```kotlin | ||
val bigTextValue = BigText.wrap(newText) | ||
val scrollState = rememberScrollState() | ||
val bigTextViewState = remember(bigTextValue) { BigTextViewState() } | ||
|
||
BigMonospaceTextField( | ||
text = bigTextValue, | ||
onTextChange = { | ||
onTextChange?.let { onTextChange -> | ||
onTextChange(it.bigText.asCharSequence()) | ||
} | ||
bigTextValueId = it.changeId | ||
}, | ||
viewState = bigTextViewState, | ||
visualTransformation = visualTransformationToUse, | ||
fontSize = LocalFont.current.codeEditorBodyFontSize, | ||
scrollState = scrollState, | ||
onTextLayout = { layoutResult = it }, | ||
modifier = Modifier.fillMaxSize() | ||
) | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
kotlin.code.style=official | ||
kotlin.version=1.8.0 | ||
agp.version=7.3.0 | ||
compose.version=1.6.2 | ||
compose.version=1.6.11 |
Oops, something went wrong.