Skip to content

Commit

Permalink
Merge branch 'feature/bigtext' into 'main'
Browse files Browse the repository at this point in the history
BigText

See merge request products/hello-http!23
  • Loading branch information
Sunny Chung committed Nov 9, 2024
2 parents a71b1ba + 654cc10 commit ef9b2b7
Show file tree
Hide file tree
Showing 115 changed files with 14,797 additions and 493 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/run-debug-test.yaml
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() }}
9 changes: 7 additions & 2 deletions .github/workflows/run-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,14 @@ jobs:
with:
name: ux-test-result_${{ matrix.os }}
path: ux-and-transport-test/build/reports/tests/test
if: ${{ !cancelled() }}
if: ${{ always() }}
- uses: actions/upload-artifact@v3
with:
name: unit-test-result_${{ matrix.os }}
path: build/reports/tests
if: ${{ !cancelled() }}
if: ${{ always() }}
- uses: actions/upload-artifact@v3
with:
name: ux-test-error_${{ matrix.os }}
path: ux-and-transport-test/test-error.png
if: ${{ always() }}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Added

- Prettify button in JSON request editor. This includes GraphQL and gRPC.
- Mouse hovering variable placeholders in Body Editor to show a tooltip for its value (if exists)

### Removed
- Text fields and response body viewer now do not trim content over 4 MB (but other limits still apply)

## [1.6.0] - 2024-07-22

Expand Down
12 changes: 12 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ kotlin {

// implementation("org.apache.logging.log4j:log4j-api:2.23.1")
// implementation("org.apache.logging.log4j:log4j-core:2.23.1")

// incremental parser
implementation("io.github.tree-sitter:ktreesitter:0.23.0")
implementation("io.github.sunny-chung:ktreesitter-json:0.23.0.1")
implementation("io.github.sunny-chung:ktreesitter-graphql:1.0.0.0")
}

resources.srcDir("$buildDir/resources")
Expand Down Expand Up @@ -152,11 +157,18 @@ tasks.getByName("jvmMainClasses") {

tasks.withType<Test> {
useJUnitPlatform()
jvmArgs("-Xmx6144m")
testLogging {
events = setOf(TestLogEvent.STARTED, TestLogEvent.FAILED, TestLogEvent.PASSED, TestLogEvent.SKIPPED)
showStandardStreams = true
exceptionFormat = TestExceptionFormat.FULL
}
if (project.hasProperty("isCI") && project.property("isCI").toString().toBoolean()) {
filter {
excludeTestsMatching("com.sunnychung.application.multiplatform.hellohttp.test.bigtext.**")
excludeTestsMatching("com.sunnychung.**.ChunkedLatestFlowTest") // The latencies of `delay()` are unstable on GitHub macOS runners
}
}
}

compose.desktop {
Expand Down
43 changes: 43 additions & 0 deletions doc/bigtext/implementation/LayoutQueries.md
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.
41 changes: 41 additions & 0 deletions doc/bigtext/implementation/LineQueries.md
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
```
126 changes: 126 additions & 0 deletions doc/bigtext/implementation/TransformReplace.md
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.
71 changes: 71 additions & 0 deletions doc/bigtext/usage/ValueMutationCallback.md
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()
)
```

2 changes: 1 addition & 1 deletion gradle.properties
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
Loading

0 comments on commit ef9b2b7

Please sign in to comment.