From 584ac9718cf3ef02ab90e7dbe0e38314d9f73ba3 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Tue, 4 Aug 2026 22:03:37 +0200 Subject: [PATCH 1/2] add confirmation dialog before deleting a folder --- .../gitnote/ui/screen/setup/SetupNav.kt | 51 +++++++++++++++++-- .../gitnote/ui/viewmodel/SetupViewModel.kt | 33 ++++++++---- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/SetupNav.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/SetupNav.kt index 96c6b21a..f607f274 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/SetupNav.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/SetupNav.kt @@ -3,6 +3,7 @@ package io.github.wiiznokes.gitnote.ui.screen.setup import androidx.compose.animation.ContentTransform import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.lifecycle.viewmodel.compose.viewModel import dev.olshevski.navigation.reimagined.AnimatedNavHost @@ -14,6 +15,7 @@ import dev.olshevski.navigation.reimagined.navigate import dev.olshevski.navigation.reimagined.pop import dev.olshevski.navigation.reimagined.popUpTo import dev.olshevski.navigation.reimagined.rememberNavController +import io.github.wiiznokes.gitnote.ui.component.RequestConfirmationDialog import io.github.wiiznokes.gitnote.ui.destination.NewRepoMethod import io.github.wiiznokes.gitnote.ui.destination.SetupDestination import io.github.wiiznokes.gitnote.ui.model.StorageConfiguration @@ -84,6 +86,35 @@ fun SetupNav( key = path ) + val requestConfirmationDialogExpanded = remember { + mutableStateOf(false) + } + + var pendingStorageConfig: StorageConfiguration? = remember { + null + } + + RequestConfirmationDialog( + expanded = requestConfirmationDialogExpanded, + text = "WARNING: Are you sure you want to continue? The directory will be deleted.", + onConfirmation = { + pendingStorageConfig?.let { storageConfig -> + when (setupDestination.newRepoMethod) { + NewRepoMethod.Create -> vm.createLocalRepo( + storageConfig, + onSetupSuccess + ) + + NewRepoMethod.Open -> vm.openRepo(storageConfig, onSetupSuccess) + NewRepoMethod.Clone -> { + navController.navigate( + SetupDestination.Remote(storageConfig) + ) + } + } + } + } + ) FileExplorerScreen( currentDir = fileExplorerVm.currentDir, @@ -102,14 +133,24 @@ fun SetupNav( ) when (setupDestination.newRepoMethod) { - NewRepoMethod.Create -> vm.createLocalRepo( - storageConfig, - onSetupSuccess - ) + NewRepoMethod.Create -> { + if (vm.isFolderWillBeDeleted(storageConfig)) { + requestConfirmationDialogExpanded.value = true + pendingStorageConfig = storageConfig + } else { + vm.createLocalRepo( + storageConfig, + onSetupSuccess + ) + } + } NewRepoMethod.Open -> vm.openRepo(storageConfig, onSetupSuccess) NewRepoMethod.Clone -> { - if (useUrlForRootFolder || vm.checkPathForClone(storageConfig.repoPath()).isSuccess) { + if (vm.isFolderWillBeDeleted(storageConfig)) { + requestConfirmationDialogExpanded.value = true + pendingStorageConfig = storageConfig + } else { navController.navigate( SetupDestination.Remote(storageConfig) ) diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/viewmodel/SetupViewModel.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/viewmodel/SetupViewModel.kt index ca55c6cc..06979014 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/viewmodel/SetupViewModel.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/viewmodel/SetupViewModel.kt @@ -107,6 +107,30 @@ class SetupViewModel(val authFlow: SharedFlow) : ViewModel(), SetupViewM } } + fun isFolderWillBeDeleted(storageConfig: StorageConfiguration): Boolean { + return when (storageConfig) { + StorageConfiguration.App -> false + is StorageConfiguration.Device -> { + if (storageConfig.useUrlForRootFolder) { + return false + } + + val folder = NodeFs.Folder.fromPath(storageConfig.path) + + if (!folder.exist()) { + return false + } + + + if (folder.isEmptyDirectory().isSuccess) { + return false + } + + true + } + } + } + fun createLocalRepo(storageConfig: StorageConfiguration, onSuccess: () -> Unit) { CoroutineScope(Dispatchers.IO).launch { @@ -158,15 +182,6 @@ class SetupViewModel(val authFlow: SharedFlow) : ViewModel(), SetupViewM } - - fun checkPathForClone(repoPath: String): Result { - val result = NodeFs.Folder.fromPath(repoPath).isEmptyDirectory() - result.onFailure { - uiHelper.makeToast(it.message) - } - return result - } - override fun launch(f: suspend () -> Unit) { viewModelScope.launch { f() } } From e43e11404612e7fffd8a8cf7feb730d21e05d484 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Tue, 4 Aug 2026 22:03:44 +0200 Subject: [PATCH 2/2] fmt --- .../java/io/github/wiiznokes/gitnote/MyApp.kt | 1 + .../gitnote/helper/NetworkPermissionHelper.kt | 43 ++++++++++--------- .../gitnote/manager/MimeTypeManager.kt | 3 +- .../wiiznokes/gitnote/provider/GitHub.kt | 4 +- .../ui/destination/RemoteDestination.kt | 2 +- .../gitnote/ui/screen/app/grid/GridScreen.kt | 2 - .../gitnote/ui/screen/app/grid/TopGrid.kt | 10 ++++- .../ui/screen/app/grid/markdownHelper.kt | 10 ++++- .../gitnote/ui/screen/settings/LogsScreen.kt | 2 + .../ui/screen/setup/remote/EnterUrlScreen.kt | 7 ++- .../ui/screen/setup/remote/RemoteNav.kt | 1 - .../gitnote/ui/viewmodel/GridViewModel.kt | 1 - 12 files changed, 50 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/MyApp.kt b/app/src/main/java/io/github/wiiznokes/gitnote/MyApp.kt index 877ddc53..e8ffa3da 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/MyApp.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/MyApp.kt @@ -6,6 +6,7 @@ import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch const val TAG = "MyApp (Application)" + class MyApp : Application() { companion object { diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/helper/NetworkPermissionHelper.kt b/app/src/main/java/io/github/wiiznokes/gitnote/helper/NetworkPermissionHelper.kt index 5a1b6f1b..5981be3c 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/helper/NetworkPermissionHelper.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/helper/NetworkPermissionHelper.kt @@ -4,10 +4,10 @@ import android.Manifest import android.content.Context import android.os.Build import androidx.core.content.PermissionChecker -import java.net.InetAddress -import java.net.URI import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import java.net.InetAddress +import java.net.URI class NetworkPermissionHelper { companion object { @@ -19,30 +19,31 @@ class NetworkPermissionHelper { ) == PermissionChecker.PERMISSION_GRANTED } - suspend fun requiresLocalNetworkPermission(urlString: String): Boolean = withContext(Dispatchers.IO) { - try { - val host = if (urlString.contains("://")) { - URI(urlString).host - } else { - val afterAt = urlString.substringAfter('@', urlString) - afterAt.substringBefore(':') - } + suspend fun requiresLocalNetworkPermission(urlString: String): Boolean = + withContext(Dispatchers.IO) { + try { + val host = if (urlString.contains("://")) { + URI(urlString).host + } else { + val afterAt = urlString.substringAfter('@', urlString) + afterAt.substringBefore(':') + } - if (host == null) return@withContext false + if (host == null) return@withContext false - if (host.endsWith(".local", ignoreCase = true)) { - return@withContext true - } + if (host.endsWith(".local", ignoreCase = true)) { + return@withContext true + } - val addresses = InetAddress.getAllByName(host) + val addresses = InetAddress.getAllByName(host) - addresses.any { address -> - address.isSiteLocalAddress || - address.isLinkLocalAddress + addresses.any { address -> + address.isSiteLocalAddress || + address.isLinkLocalAddress + } + } catch (_: Exception) { + false } - } catch (_: Exception) { - false } - } } } diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/manager/MimeTypeManager.kt b/app/src/main/java/io/github/wiiznokes/gitnote/manager/MimeTypeManager.kt index ef210282..723ceeb5 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/manager/MimeTypeManager.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/manager/MimeTypeManager.kt @@ -9,7 +9,8 @@ enum class ExtensionType { Markdown; } -fun extensionType(extension: String): ExtensionType? = extensionTypeFromNumber(extensionTypeLib(extension)) +fun extensionType(extension: String): ExtensionType? = + extensionTypeFromNumber(extensionTypeLib(extension)) private fun extensionTypeFromNumber(num: Int): ExtensionType? = when (num) { diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/provider/GitHub.kt b/app/src/main/java/io/github/wiiznokes/gitnote/provider/GitHub.kt index bb15b725..ecbc04df 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/provider/GitHub.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/provider/GitHub.kt @@ -9,9 +9,7 @@ import java.util.Locale import java.util.TimeZone -class GithubProvider( - -) : Provider { +class GithubProvider : Provider { override val createRepoLink: String = "https://github.com/new" diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/destination/RemoteDestination.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/destination/RemoteDestination.kt index 5ae02cdc..67bc056b 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/destination/RemoteDestination.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/destination/RemoteDestination.kt @@ -49,5 +49,5 @@ sealed interface RemoteDestination : Parcelable { ) : RemoteDestination @Parcelize - data object Logs: RemoteDestination + data object Logs : RemoteDestination } diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/GridScreen.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/GridScreen.kt index d0f720bc..c7fba17e 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/GridScreen.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/GridScreen.kt @@ -23,8 +23,6 @@ import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.pullrefresh.PullRefreshIndicator import androidx.compose.material.pullrefresh.pullRefresh diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/TopGrid.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/TopGrid.kt index 36261076..7e76e026 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/TopGrid.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/TopGrid.kt @@ -43,7 +43,6 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.TooltipAnchorPosition import androidx.compose.material3.TooltipBox -import androidx.compose.material3.TooltipDefaults import androidx.compose.material3.TooltipDefaults.rememberTooltipPositionProvider import androidx.compose.material3.rememberDrawerState import androidx.compose.material3.rememberTooltipState @@ -438,7 +437,11 @@ private fun SyncStateIcon( } val tooltipState = rememberTooltipState(isPersistent = true) - var visible by remember(state) { if (state is Ok) mutableStateOf(!state.isConsumed) else mutableStateOf(true) } + var visible by remember(state) { + if (state is Ok) mutableStateOf(!state.isConsumed) else mutableStateOf( + true + ) + } if (state is Ok) { LaunchedEffect(visible) { @@ -482,16 +485,19 @@ private fun SyncStateIcon( contentDescription = "Sync Error", modifier = modifier ) + is Ok -> Icon( imageVector = Icons.Default.CloudDone, contentDescription = "Sync Done", modifier = modifier, ) + Pull -> Icon( imageVector = Icons.Default.CloudDownload, contentDescription = "Pulling", modifier = modifier, ) + Push -> Icon( imageVector = Icons.Default.CloudUpload, contentDescription = "Pushing", diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/markdownHelper.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/markdownHelper.kt index 1c494eb5..04d192ac 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/markdownHelper.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/app/grid/markdownHelper.kt @@ -68,6 +68,7 @@ fun MarkdownCustom( ) } } + @Composable fun MarkdownCustomInner( content: String, @@ -82,7 +83,13 @@ fun MarkdownCustomInner( annotator: MarkdownAnnotator = markdownAnnotator(), extendedSpans: MarkdownExtendedSpans = markdownExtendedSpans(), inlineContent: MarkdownInlineContent = markdownInlineContent(), - components: MarkdownComponents = markdownComponents(checkbox = { MarkdownCheckBox(it.content, it.node, it.typography.text) }), + components: MarkdownComponents = markdownComponents(checkbox = { + MarkdownCheckBox( + it.content, + it.node, + it.typography.text + ) + }), animations: MarkdownAnimations = markdownAnimations(), referenceLinkHandler: ReferenceLinkHandler = ReferenceLinkHandlerImpl(), lookupLinks: Boolean = true, @@ -114,7 +121,6 @@ fun MarkdownCustomInner( ) - private fun TextStyle.scaled(scale: Float): TextStyle = copy( fontSize = fontSize.scale(scale), lineHeight = lineHeight.scale(scale), diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/settings/LogsScreen.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/settings/LogsScreen.kt index 117fbbf6..2d6698d4 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/settings/LogsScreen.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/settings/LogsScreen.kt @@ -64,10 +64,12 @@ private fun getTextStyleFromInt(id: Int): TextStyle { fontSize = 8.sp, lineHeight = 10.sp ) + 0 -> MaterialTheme.typography.bodySmall.copy( fontSize = 10.sp, lineHeight = 12.sp ) + 1 -> MaterialTheme.typography.bodySmall 2 -> MaterialTheme.typography.bodyMedium 3 -> MaterialTheme.typography.bodyLarge diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/remote/EnterUrlScreen.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/remote/EnterUrlScreen.kt index e471b59a..2f34781e 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/remote/EnterUrlScreen.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/remote/EnterUrlScreen.kt @@ -24,7 +24,6 @@ import androidx.compose.ui.tooling.preview.Preview import io.github.wiiznokes.gitnote.MyApp import io.github.wiiznokes.gitnote.R import io.github.wiiznokes.gitnote.helper.NetworkPermissionHelper -import kotlinx.coroutines.launch import io.github.wiiznokes.gitnote.manager.getUrlInfoLib import io.github.wiiznokes.gitnote.provider.GithubProvider import io.github.wiiznokes.gitnote.provider.Provider @@ -32,6 +31,7 @@ import io.github.wiiznokes.gitnote.ui.component.AppPage import io.github.wiiznokes.gitnote.ui.component.SetupButton import io.github.wiiznokes.gitnote.ui.component.SetupLine import io.github.wiiznokes.gitnote.ui.component.SetupPage +import kotlinx.coroutines.launch fun isUrlSsh(url: String): Boolean { @@ -134,7 +134,10 @@ fun EnterUrlScreen( onClick = { val urlText = url.value.text scope.launch { - if (NetworkPermissionHelper.requiresLocalNetworkPermission(urlText) && !NetworkPermissionHelper.isPermissionGranted(context)) { + if (NetworkPermissionHelper.requiresLocalNetworkPermission(urlText) && !NetworkPermissionHelper.isPermissionGranted( + context + ) + ) { pendingUrl.value = urlText nearbyPermissionLauncher.launch(android.Manifest.permission.ACCESS_LOCAL_NETWORK) } else { diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/remote/RemoteNav.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/remote/RemoteNav.kt index 5475816e..90c8b913 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/remote/RemoteNav.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/screen/setup/remote/RemoteNav.kt @@ -22,7 +22,6 @@ import io.github.wiiznokes.gitnote.ui.destination.RemoteDestination.PickRepo import io.github.wiiznokes.gitnote.ui.destination.RemoteDestination.SelectGenerateNewSshKeys import io.github.wiiznokes.gitnote.ui.destination.RemoteDestination.SelectProvider import io.github.wiiznokes.gitnote.ui.destination.RemoteDestination.SelectSetupAutomatically -import io.github.wiiznokes.gitnote.ui.destination.SettingsDestination import io.github.wiiznokes.gitnote.ui.model.StorageConfiguration import io.github.wiiznokes.gitnote.ui.screen.settings.LogsScreen import io.github.wiiznokes.gitnote.ui.utils.slide diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/ui/viewmodel/GridViewModel.kt b/app/src/main/java/io/github/wiiznokes/gitnote/ui/viewmodel/GridViewModel.kt index 8a5dc22e..4adb018b 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/ui/viewmodel/GridViewModel.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/ui/viewmodel/GridViewModel.kt @@ -17,7 +17,6 @@ import io.github.wiiznokes.gitnote.data.room.RepoDatabase import io.github.wiiznokes.gitnote.helper.NameValidation import io.github.wiiznokes.gitnote.manager.StorageManager import io.github.wiiznokes.gitnote.ui.model.FileExtension -import io.github.wiiznokes.gitnote.ui.model.NoteViewType import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi