Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/check-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,19 @@ jobs:

- name: Compile for Jvm
run: ./gradlew :composeApp:build --stacktrace

test:
runs-on: macos-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'

- name: Run tests
run: ./gradlew :composeApp:desktopTest --tests "com.sebastianneubauer.jsontreeviewer.ViewModelTest" --stacktrace
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.KeyboardArrowDown
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -106,7 +107,7 @@ private fun AppUi(
is Contract.State.InitialLoading -> InitialLoading(isHovering = isHovering)
is Contract.State.Loading -> Loading()
is Contract.State.Error -> Error(error = state.error, isHovering = isHovering)
is Contract.State.Content -> Content(json = state.json, stats = state.stats, onJsonParsingError = onJsonParsingError)
is Contract.State.Content -> Content(json = state.json, searchDirection = state.searchDirection, stats = state.stats, onJsonParsingError = onJsonParsingError)
}
}
}
Expand All @@ -115,6 +116,7 @@ private fun AppUi(
@Composable
private fun Content(
json: String,
searchDirection: Contract.SearchDirection?,
stats: Contract.Stats,
onJsonParsingError: (Throwable) -> Unit
) {
Expand All @@ -123,6 +125,14 @@ private fun Content(
val searchQuery by remember(searchState.query) { mutableStateOf(searchState.query.orEmpty()) }
var showSidebar by remember { mutableStateOf(false) }

LaunchedEffect(searchDirection) {
when(searchDirection) {
is Contract.SearchDirection.Next -> searchState.selectNext()
is Contract.SearchDirection.Previous -> searchState.selectPrevious()
null -> Unit
}
}

Column(
modifier = Modifier
.fillMaxSize()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ object Contract {
data object InitialLoading: State
data object Loading: State
data class Error(val error: ErrorType): State
data class Content(val json: String, val stats: Stats): State
data class Content(val json: String, val stats: Stats, val searchDirection: SearchDirection?): State
}

sealed class ErrorType {
Expand All @@ -17,6 +17,13 @@ object Contract {
data class JsonParserError(val message: String): ErrorType()
}

sealed interface SearchDirection {
val increment: Int

data class Next(override val increment: Int): SearchDirection
data class Previous(override val increment: Int): SearchDirection
}

data class Stats(
val filePath: String,
val fileName: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ViewModel(

State.Content(
json = json,
searchDirection = null,
stats = Contract.Stats(
filePath = validFile.path,
fileName = validFile.name,
Expand All @@ -63,34 +64,66 @@ class ViewModel(

fun onKeyEvent(event: KeyEvent): Boolean {
return if ((event.isCtrlPressed || event.isMetaPressed) && event.key == Key.V) {
val clipboardString = try {
Toolkit.getDefaultToolkit()
.systemClipboard
.getData(DataFlavor.stringFlavor) as String
} catch (e: Exception) {
null
}

viewModelState.value = if(clipboardString != null) {
State.Content(
json = clipboardString,
stats = Contract.Stats(
filePath = "from clipboard",
fileName = "n/a",
fileSize = "n/a",
fileReadTime = "n/a",
fileLines = clipboardString.lines().count().toString()
)
)
} else {
State.Error(error = Contract.ErrorType.CopyPasteError)
}
viewModelState.value = getStateFromClipboardData()
true
} else if(event.key == Key.DirectionDown || event.key == Key.Enter) {
val newState = getStateFromSearchDirectionEvent(isDownEvent = true)
viewModelState.value = newState
newState is State.Content
} else if(event.key == Key.DirectionUp) {
val newState = getStateFromSearchDirectionEvent(isDownEvent = false)
viewModelState.value = newState
newState is State.Content
} else {
false
}
}

private fun getStateFromClipboardData(): State {
val clipboardString = try {
Toolkit.getDefaultToolkit()
.systemClipboard
.getData(DataFlavor.stringFlavor) as String
} catch (e: Exception) {
null
}

return if(clipboardString != null) {
State.Content(
json = clipboardString,
searchDirection = null,
stats = Contract.Stats(
filePath = "from clipboard",
fileName = "n/a",
fileSize = "n/a",
fileReadTime = "n/a",
fileLines = clipboardString.lines().count().toString()
)
)
} else {
State.Error(error = Contract.ErrorType.CopyPasteError)
}
}

private fun getStateFromSearchDirectionEvent(isDownEvent: Boolean): State {
val currentState = viewModelState.value
return if(currentState is State.Content) {
val currentSearchDirection = currentState.searchDirection
val newSearchDirection = if(isDownEvent) {
when(currentSearchDirection) {
is Contract.SearchDirection.Next -> currentSearchDirection.copy(increment = currentSearchDirection.increment + 1)
else -> Contract.SearchDirection.Next(increment = 0)
}
} else {
when(currentSearchDirection) {
is Contract.SearchDirection.Previous -> currentSearchDirection.copy(increment = currentSearchDirection.increment + 1)
else -> Contract.SearchDirection.Previous(increment = 0)
}
}
currentState.copy(searchDirection = newSearchDirection)
} else currentState
}

fun showJsonParsingError(throwable: Throwable) {
viewModelState.value = State.Error(
error = Contract.ErrorType.JsonParserError(message = throwable.localizedMessage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class ViewModelTest {
assertEquals(
expected = State.Content(
json = json,
searchDirection = null,
stats = Contract.Stats(
filePath = file.path,
fileName = file.name,
Expand Down