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
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.github.wiiznokes.gitnote.MyApp
import io.github.wiiznokes.gitnote.R
import io.github.wiiznokes.gitnote.data.removeFirstAndLastSlash
import io.github.wiiznokes.gitnote.ui.model.FileExtension
import io.github.wiiznokes.gitnote.util.toResult
import io.github.wiiznokes.gitnote.utils.toResult
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
Expand All @@ -28,7 +27,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import io.github.wiiznokes.gitnote.ui.util.conditional
import io.github.wiiznokes.gitnote.ui.utils.conditional

@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import io.github.wiiznokes.gitnote.ui.destination.SettingsDestination
import io.github.wiiznokes.gitnote.ui.screen.app.edit.EditScreen
import io.github.wiiznokes.gitnote.ui.screen.app.grid.GridScreen
import io.github.wiiznokes.gitnote.ui.screen.settings.SettingsNav
import io.github.wiiznokes.gitnote.ui.util.crossFade
import io.github.wiiznokes.gitnote.ui.util.slide
import io.github.wiiznokes.gitnote.ui.utils.crossFade
import io.github.wiiznokes.gitnote.ui.utils.slide


private const val TAG = "AppScreen"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import dev.olshevski.navigation.reimagined.NavTransitionSpec
import dev.olshevski.navigation.reimagined.pop
import dev.olshevski.navigation.reimagined.rememberNavController
import io.github.wiiznokes.gitnote.ui.destination.SettingsDestination
import io.github.wiiznokes.gitnote.ui.util.slide
import io.github.wiiznokes.gitnote.ui.utils.slide
import io.github.wiiznokes.gitnote.ui.viewmodel.SettingsViewModel


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import io.github.wiiznokes.gitnote.ui.destination.SetupDestination
import io.github.wiiznokes.gitnote.ui.destination.NewRepoMethod
import io.github.wiiznokes.gitnote.ui.model.StorageConfiguration
import io.github.wiiznokes.gitnote.ui.screen.setup.remote.RemoteScreen
import io.github.wiiznokes.gitnote.ui.util.crossFade
import io.github.wiiznokes.gitnote.ui.util.slide
import io.github.wiiznokes.gitnote.ui.utils.crossFade
import io.github.wiiznokes.gitnote.ui.utils.slide
import io.github.wiiznokes.gitnote.ui.viewmodel.SetupViewModel
import io.github.wiiznokes.gitnote.ui.viewmodel.viewModelFactory
import kotlinx.coroutines.flow.SharedFlow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import io.github.wiiznokes.gitnote.ui.component.NextButton
import io.github.wiiznokes.gitnote.ui.component.SetupPage
import io.github.wiiznokes.gitnote.ui.model.StorageConfiguration
import io.github.wiiznokes.gitnote.ui.viewmodel.SetupViewModel
import io.github.wiiznokes.gitnote.util.contains
import io.github.wiiznokes.gitnote.utils.contains


sealed class Selected {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import io.github.wiiznokes.gitnote.ui.destination.RemoteDestination.SelectGenera
import io.github.wiiznokes.gitnote.ui.destination.RemoteDestination.SelectProvider
import io.github.wiiznokes.gitnote.ui.destination.RemoteDestination.SelectSetupAutomatically
import io.github.wiiznokes.gitnote.ui.model.StorageConfiguration
import io.github.wiiznokes.gitnote.ui.util.slide
import io.github.wiiznokes.gitnote.ui.utils.slide
import io.github.wiiznokes.gitnote.ui.viewmodel.SetupViewModel


Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.github.wiiznokes.gitnote.ui.util
package io.github.wiiznokes.gitnote.ui.utils

import io.github.wiiznokes.gitnote.data.room.Note
import java.util.Vector
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.github.wiiznokes.gitnote.ui.util
package io.github.wiiznokes.gitnote.ui.utils

import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.github.wiiznokes.gitnote.ui.util
package io.github.wiiznokes.gitnote.ui.utils

import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
Expand All @@ -8,8 +8,6 @@ import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.transform

@Composable
fun Modifier.conditional(
Expand All @@ -35,13 +33,3 @@ fun slide(backWard: Boolean = false) = slideInHorizontally(
}
)

/**
* This is similar to the map function, but the flow that was
* mapped is also included in the result:
* flow1.mapAndCombine(f(flow1) -> flow3)
* will return: flow(1, 3)
*/
inline fun <T, R> Flow<T>.mapAndCombine(crossinline transform: suspend (value: T) -> R): Flow<Pair<T, R>> =
transform { value ->
return@transform emit(Pair(value, transform(value)))
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import io.github.wiiznokes.gitnote.ui.model.SortOrder.Descending
import io.github.wiiznokes.gitnote.ui.model.SortType.AlphaNumeric
import io.github.wiiznokes.gitnote.ui.model.SortType.Modification
import io.github.wiiznokes.gitnote.ui.screen.app.DrawerFolderModel
import io.github.wiiznokes.gitnote.ui.util.fuzzySort
import io.github.wiiznokes.gitnote.ui.util.mapAndCombine
import io.github.wiiznokes.gitnote.ui.utils.fuzzySort
import io.github.wiiznokes.gitnote.utils.mapAndCombine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import io.github.wiiznokes.gitnote.ui.destination.EditParams
import io.github.wiiznokes.gitnote.ui.model.EditType
import io.github.wiiznokes.gitnote.ui.model.FileExtension
import io.github.wiiznokes.gitnote.ui.viewmodel.viewModelFactory
import io.github.wiiznokes.gitnote.utils.endsWith
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -60,7 +61,12 @@ open class TextVM() : ViewModel() {
private val _content = mutableStateOf(TextFieldValue())
val content: State<TextFieldValue> get() = _content

private val history = mutableListOf<TextFieldValue>()
private data class HistoryItem(
val v: TextFieldValue,
val flagDoNotRemove: Boolean = false,
)

private val history = mutableListOf<HistoryItem>()

private val _historyManager: MutableStateFlow<History> =
MutableStateFlow(History(index = 0, size = 1))
Expand Down Expand Up @@ -89,7 +95,7 @@ open class TextVM() : ViewModel() {
)

_content.value = textFieldValue.copy()
history.add(textFieldValue)
history.add(HistoryItem(textFieldValue))

Log.d(TAG, "init: $previousNote, $editType")
}
Expand All @@ -112,11 +118,17 @@ open class TextVM() : ViewModel() {
)

_content.value = textFieldValue.copy()
history.add(textFieldValue)
history.add(HistoryItem(textFieldValue))

Log.d(TAG, "init saved: $previousNote, $editType")
}

enum class IsSimilarResult {
Yes,
No,
FlagDoNotRemove
}

// https://medium.com/androiddevelopers/effective-state-management-for-textfield-in-compose-d6e5b070fbe5
// even if we are not doing anything async, sometime, when we long press enter for example,
// the value v will not be the last one set by `content.value`. This will instead by an internal copy
Expand All @@ -129,12 +141,11 @@ open class TextVM() : ViewModel() {
// todo: report this to google
open fun onValueChange(v: TextFieldValue) {

// don't bloat history with different selection
if (content.value.text == v.text) {
if (history.size == 1 && content.value.text == v.text) {
_content.value = v.copy()
history[0] = HistoryItem(v.copy())
return
}

_content.value = v.copy()

val historyManager = historyManager.value
Expand All @@ -145,42 +156,72 @@ open class TextVM() : ViewModel() {
i--
}

fun isSimilar(v1: TextFieldValue, v2: TextFieldValue): Boolean {
fun isSimilar(v1: HistoryItem, v2: HistoryItem, firstPass: Boolean): IsSimilarResult {

if (v1.text.endsWith(".")) {
return false
if (v2.flagDoNotRemove) {
return IsSimilarResult.No
}

if (!v1.text.endsWith(". ") && v1.text.endsWith(" ")) {
return false
if (firstPass) {
if ((v2.v.selection.start - v1.v.selection.start).absoluteValue > 1
|| (v2.v.selection.end - v1.v.selection.end).absoluteValue > 1
) {
return IsSimilarResult.FlagDoNotRemove
}

if (v2.v.text.endsWith(".", startIndex = v2.v.selection.max)) {
return IsSimilarResult.No
}

if (!v2.v.text.endsWith(
". ",
startIndex = v2.v.selection.max
) && v2.v.text.endsWith(" ", startIndex = v2.v.selection.max)
) {
return IsSimilarResult.No
}

if (v2.v.text.endsWith("-", startIndex = v2.v.selection.max)) {
return IsSimilarResult.No
}
}

if (v1.text.endsWith("\n")) {
return false
if (v2.v.text.endsWith("\n", startIndex = v2.v.selection.max)) {
return IsSimilarResult.No
}
if (v1.text.endsWith("-")) {
return false
if ((v2.v.text.length - v1.v.text.length).absoluteValue >= 10) {
return IsSimilarResult.No
}

if ((v1.text.length - v2.text.length).absoluteValue >= 10)
return false

return true
return IsSimilarResult.Yes
}

history.add(v)
history.add(HistoryItem(v.copy()))

fun cleanHistory() {

// we don't want to remove the last and first index of the history
// [_,a,ab] -> the size is 3, "a" will be removed
if (history.size < 3) return

val secondLast = history.size - 2
var last = history.size - 1
val secondLast = last - 1

if (isSimilar(history[last], history[secondLast])) {
if (isSimilar(history[secondLast - 1], history[secondLast])) {
history.removeAt(secondLast)
when (isSimilar(history[secondLast], history[last], true)) {
IsSimilarResult.Yes -> {
if (isSimilar(
history[secondLast - 1],
history[secondLast],
false
) == IsSimilarResult.Yes
) {
history.removeAt(secondLast)
}
}

IsSimilarResult.No -> {}
IsSimilarResult.FlagDoNotRemove -> {
history[last] = history[last].copy(flagDoNotRemove = true)
}
}
}
Expand Down Expand Up @@ -208,7 +249,7 @@ open class TextVM() : ViewModel() {
)
)
}
_content.value = history[historyManager.index - 1].copy()
_content.value = history[historyManager.index - 1].v.copy()
}

fun redo() {
Expand All @@ -221,7 +262,7 @@ open class TextVM() : ViewModel() {
)
)
}
_content.value = history[historyManager.index + 1].copy()
_content.value = history[historyManager.index + 1].v.copy()
}

fun setReadOnlyMode(value: Boolean) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.github.wiiznokes.gitnote.util
package io.github.wiiznokes.gitnote.utils

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.Result.Companion.failure
Expand Down Expand Up @@ -58,4 +60,32 @@ fun <T> MutableList<T>.remove(predicate: (T) -> Boolean): Result<Int> {
}

fun <T> Iterable<T>.contains(predicate: (T) -> Boolean): Boolean =
firstOrNull(predicate) != null
firstOrNull(predicate) != null

fun String.endsWith(
suffix: String,
ignoreCase: Boolean = false,
startIndex: Int = this.length
): Boolean {
if (startIndex < 0 || startIndex > this.length) return false
if (startIndex < suffix.length) return false

return regionMatches(
startIndex - suffix.length,
suffix,
0,
suffix.length,
ignoreCase = ignoreCase
)
}

/**
* This is similar to the map function, but the flow that was
* mapped is also included in the result:
* flow1.mapAndCombine(f(flow1) -> flow3)
* will return: flow(1, 3)
*/
inline fun <T, R> Flow<T>.mapAndCombine(crossinline transform: suspend (value: T) -> R): Flow<Pair<T, R>> =
transform { value ->
return@transform emit(Pair(value, transform(value)))
}
Loading