mirror of
https://github.com/amir1376/ab-download-manager.git
synced 2025-02-20 11:43:24 +08:00
add confirm exit dialog when there is active download/queue
This commit is contained in:
parent
054be24597
commit
3387a6d7c9
@ -48,7 +48,6 @@ import ir.amirab.util.compose.asStringSource
|
|||||||
import ir.amirab.util.compose.combineStringSources
|
import ir.amirab.util.compose.combineStringSources
|
||||||
import ir.amirab.util.flow.mapStateFlow
|
import ir.amirab.util.flow.mapStateFlow
|
||||||
import ir.amirab.util.osfileutil.FileUtils
|
import ir.amirab.util.osfileutil.FileUtils
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@ -732,10 +731,31 @@ class AppComponent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestClose() {
|
private val _showConfirmExitDialog = MutableStateFlow(false)
|
||||||
|
val showConfirmExitDialog = _showConfirmExitDialog.asStateFlow()
|
||||||
|
|
||||||
|
fun exitAppAsync() {
|
||||||
|
scope.launch { exitApp() }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun exitApp() {
|
||||||
|
downloadSystem.stopAnything()
|
||||||
exitProcess(0)
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun closeConfirmExit() {
|
||||||
|
_showConfirmExitDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun requestExitApp() {
|
||||||
|
val hasActiveDownloads = downloadSystem.downloadMonitor.activeDownloadCount.value > 0
|
||||||
|
if (hasActiveDownloads) {
|
||||||
|
_showConfirmExitDialog.value = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
exitApp()
|
||||||
|
}
|
||||||
|
|
||||||
fun openAbout() {
|
fun openAbout() {
|
||||||
showAboutPage.update { true }
|
showAboutPage.update { true }
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package com.abdownloadmanager.desktop
|
package com.abdownloadmanager.desktop
|
||||||
|
|
||||||
import com.abdownloadmanager.desktop.actions.exitAction
|
|
||||||
import com.abdownloadmanager.desktop.utils.IntegrationPortBroadcaster
|
import com.abdownloadmanager.desktop.utils.IntegrationPortBroadcaster
|
||||||
import com.abdownloadmanager.desktop.utils.singleInstance.Command
|
import com.abdownloadmanager.desktop.utils.singleInstance.Command
|
||||||
import com.abdownloadmanager.desktop.utils.singleInstance.MutableSingleInstanceServerHandler
|
import com.abdownloadmanager.desktop.utils.singleInstance.MutableSingleInstanceServerHandler
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
object Commands {
|
object Commands {
|
||||||
@ -26,7 +26,9 @@ object SingleInstanceServerInitializer:KoinComponent {
|
|||||||
appComponent.isReady()
|
appComponent.isReady()
|
||||||
}
|
}
|
||||||
mutableHandler.add(Commands.exit) {
|
mutableHandler.add(Commands.exit) {
|
||||||
exitAction()
|
runBlocking {
|
||||||
|
appComponent.exitApp()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,7 +13,6 @@ import ir.amirab.util.compose.action.simpleAction
|
|||||||
import com.abdownloadmanager.desktop.utils.getIcon
|
import com.abdownloadmanager.desktop.utils.getIcon
|
||||||
import com.abdownloadmanager.desktop.utils.getName
|
import com.abdownloadmanager.desktop.utils.getName
|
||||||
import com.abdownloadmanager.resources.Res
|
import com.abdownloadmanager.resources.Res
|
||||||
import com.abdownloadmanager.resources.*
|
|
||||||
import com.abdownloadmanager.utils.category.Category
|
import com.abdownloadmanager.utils.category.Category
|
||||||
import ir.amirab.downloader.downloaditem.DownloadCredentials
|
import ir.amirab.downloader.downloaditem.DownloadCredentials
|
||||||
import ir.amirab.downloader.queue.DownloadQueue
|
import ir.amirab.downloader.queue.DownloadQueue
|
||||||
@ -115,11 +114,12 @@ val stopAllAction = simpleAction(
|
|||||||
}.apply {
|
}.apply {
|
||||||
}
|
}
|
||||||
|
|
||||||
val exitAction = simpleAction(
|
// ui exit
|
||||||
|
val requestExitAction = simpleAction(
|
||||||
Res.string.exit.asStringSource(),
|
Res.string.exit.asStringSource(),
|
||||||
MyIcons.exit,
|
MyIcons.exit,
|
||||||
) {
|
) {
|
||||||
appComponent.requestClose()
|
scope.launch { appComponent.requestExitApp() }
|
||||||
}
|
}
|
||||||
|
|
||||||
val browserIntegrations = MenuItem.SubMenu(
|
val browserIntegrations = MenuItem.SubMenu(
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.abdownloadmanager.desktop.pages.confirmexit
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import com.abdownloadmanager.desktop.AppComponent
|
||||||
|
import com.abdownloadmanager.desktop.ui.widget.ConfirmDialog
|
||||||
|
import com.abdownloadmanager.desktop.ui.widget.ConfirmDialogType
|
||||||
|
import com.abdownloadmanager.resources.Res
|
||||||
|
import ir.amirab.util.compose.asStringSource
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ConfirmExit(appComponent: AppComponent) {
|
||||||
|
val showExitDialog by appComponent.showConfirmExitDialog.collectAsState()
|
||||||
|
if (showExitDialog) {
|
||||||
|
ConfirmDialog(
|
||||||
|
Res.string.confirm_exit.asStringSource(),
|
||||||
|
Res.string.confirm_exit_description.asStringSource(),
|
||||||
|
onCancel = appComponent::closeConfirmExit,
|
||||||
|
onConfirm = appComponent::exitAppAsync,
|
||||||
|
type = ConfirmDialogType.Warning,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -522,7 +522,7 @@ class HomeComponent(
|
|||||||
+newDownloadFromClipboardAction
|
+newDownloadFromClipboardAction
|
||||||
+batchDownloadAction
|
+batchDownloadAction
|
||||||
separator()
|
separator()
|
||||||
+exitAction
|
+requestExitAction
|
||||||
|
|
||||||
}
|
}
|
||||||
subMenu(Res.string.tasks.asStringSource()) {
|
subMenu(Res.string.tasks.asStringSource()) {
|
||||||
@ -897,7 +897,7 @@ class HomeComponent(
|
|||||||
"ctrl V" to newDownloadFromClipboardAction
|
"ctrl V" to newDownloadFromClipboardAction
|
||||||
"ctrl C" to downloadActions.copyDownloadLinkAction
|
"ctrl C" to downloadActions.copyDownloadLinkAction
|
||||||
"ctrl alt S" to gotoSettingsAction
|
"ctrl alt S" to gotoSettingsAction
|
||||||
"ctrl W" to exitAction
|
"ctrl W" to requestExitAction
|
||||||
"DELETE" to downloadActions.deleteAction
|
"DELETE" to downloadActions.deleteAction
|
||||||
"ctrl O" to downloadActions.openFileAction
|
"ctrl O" to downloadActions.openFileAction
|
||||||
"ctrl F" to downloadActions.openFolderAction
|
"ctrl F" to downloadActions.openFolderAction
|
||||||
|
@ -14,9 +14,6 @@ import com.abdownloadmanager.desktop.pages.singleDownloadPage.ShowDownloadDialog
|
|||||||
import com.abdownloadmanager.desktop.ui.icon.MyIcons
|
import com.abdownloadmanager.desktop.ui.icon.MyIcons
|
||||||
import com.abdownloadmanager.desktop.ui.theme.ABDownloaderTheme
|
import com.abdownloadmanager.desktop.ui.theme.ABDownloaderTheme
|
||||||
import com.abdownloadmanager.desktop.ui.widget.tray.ComposeTray
|
import com.abdownloadmanager.desktop.ui.widget.tray.ComposeTray
|
||||||
import com.abdownloadmanager.desktop.ui.widget.ProvideNotificationManager
|
|
||||||
import com.abdownloadmanager.desktop.ui.widget.ShowMessageDialogs
|
|
||||||
import com.abdownloadmanager.desktop.ui.widget.useNotification
|
|
||||||
import com.abdownloadmanager.desktop.utils.AppInfo
|
import com.abdownloadmanager.desktop.utils.AppInfo
|
||||||
import com.abdownloadmanager.desktop.utils.GlobalAppExceptionHandler
|
import com.abdownloadmanager.desktop.utils.GlobalAppExceptionHandler
|
||||||
import com.abdownloadmanager.desktop.utils.ProvideGlobalExceptionHandler
|
import com.abdownloadmanager.desktop.utils.ProvideGlobalExceptionHandler
|
||||||
@ -24,16 +21,15 @@ import ir.amirab.util.compose.action.buildMenu
|
|||||||
import com.abdownloadmanager.desktop.utils.isInDebugMode
|
import com.abdownloadmanager.desktop.utils.isInDebugMode
|
||||||
import com.abdownloadmanager.desktop.utils.mvi.HandleEffects
|
import com.abdownloadmanager.desktop.utils.mvi.HandleEffects
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
|
||||||
import androidx.compose.ui.unit.LayoutDirection
|
|
||||||
import androidx.compose.ui.window.*
|
import androidx.compose.ui.window.*
|
||||||
import com.abdownloadmanager.desktop.pages.batchdownload.BatchDownloadWindow
|
import com.abdownloadmanager.desktop.pages.batchdownload.BatchDownloadWindow
|
||||||
import com.abdownloadmanager.desktop.pages.category.ShowCategoryDialogs
|
import com.abdownloadmanager.desktop.pages.category.ShowCategoryDialogs
|
||||||
|
import com.abdownloadmanager.desktop.pages.confirmexit.ConfirmExit
|
||||||
import com.abdownloadmanager.desktop.pages.credits.translators.ShowTranslators
|
import com.abdownloadmanager.desktop.pages.credits.translators.ShowTranslators
|
||||||
import com.abdownloadmanager.desktop.pages.editdownload.EditDownloadWindow
|
import com.abdownloadmanager.desktop.pages.editdownload.EditDownloadWindow
|
||||||
import com.abdownloadmanager.desktop.pages.home.HomeWindow
|
import com.abdownloadmanager.desktop.pages.home.HomeWindow
|
||||||
import com.abdownloadmanager.desktop.pages.settings.ThemeManager
|
import com.abdownloadmanager.desktop.pages.settings.ThemeManager
|
||||||
import com.abdownloadmanager.desktop.ui.widget.ProvideLanguageManager
|
import com.abdownloadmanager.desktop.ui.widget.*
|
||||||
import com.abdownloadmanager.utils.compose.ProvideDebugInfo
|
import com.abdownloadmanager.utils.compose.ProvideDebugInfo
|
||||||
import ir.amirab.util.compose.localizationmanager.LanguageManager
|
import ir.amirab.util.compose.localizationmanager.LanguageManager
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@ -100,6 +96,7 @@ object Ui : KoinComponent {
|
|||||||
ShowMessageDialogs(appComponent)
|
ShowMessageDialogs(appComponent)
|
||||||
ShowOpenSourceLibraries(appComponent)
|
ShowOpenSourceLibraries(appComponent)
|
||||||
ShowTranslators(appComponent)
|
ShowTranslators(appComponent)
|
||||||
|
ConfirmExit(appComponent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +137,7 @@ private fun ApplicationScope.SystemTray(
|
|||||||
buildMenu {
|
buildMenu {
|
||||||
+showDownloadList
|
+showDownloadList
|
||||||
+gotoSettingsAction
|
+gotoSettingsAction
|
||||||
+exitAction
|
+requestExitAction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.abdownloadmanager.desktop.ui.widget
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.myColors
|
||||||
|
import com.abdownloadmanager.desktop.utils.div
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ActionContainer(
|
||||||
|
modifier: Modifier,
|
||||||
|
contentPadding: PaddingValues = PaddingValues(
|
||||||
|
horizontal = 16.dp,
|
||||||
|
vertical = 8.dp,
|
||||||
|
),
|
||||||
|
content: @Composable () -> Unit,
|
||||||
|
) {
|
||||||
|
Column(modifier) {
|
||||||
|
Spacer(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(1.dp)
|
||||||
|
.background(myColors.onBackground / 0.15f)
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(myColors.surface / 0.5f)
|
||||||
|
.padding(contentPadding),
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
package com.abdownloadmanager.desktop.ui.widget
|
||||||
|
|
||||||
|
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
||||||
|
import com.abdownloadmanager.desktop.ui.customwindow.WindowTitle
|
||||||
|
import com.abdownloadmanager.utils.compose.widget.MyIcon
|
||||||
|
import com.abdownloadmanager.desktop.ui.icon.MyIcons
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.myColors
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.myTextSizes
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.DpSize
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.WindowPosition
|
||||||
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.abdownloadmanager.resources.Res
|
||||||
|
import ir.amirab.util.compose.StringSource
|
||||||
|
import ir.amirab.util.compose.resources.myStringResource
|
||||||
|
import java.awt.Dimension
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
sealed class ConfirmDialogType {
|
||||||
|
data object Success : ConfirmDialogType()
|
||||||
|
data object Info : ConfirmDialogType()
|
||||||
|
data object Error : ConfirmDialogType()
|
||||||
|
data object Warning : ConfirmDialogType()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ConfirmDialog(
|
||||||
|
title: StringSource,
|
||||||
|
message: StringSource,
|
||||||
|
type: ConfirmDialogType,
|
||||||
|
onConfirm: () -> Unit,
|
||||||
|
onCancel: () -> Unit,
|
||||||
|
) {
|
||||||
|
val h = 180
|
||||||
|
val w = 400
|
||||||
|
val state = rememberWindowState(
|
||||||
|
size = DpSize(w.dp, h.dp),
|
||||||
|
position = WindowPosition.Aligned(Alignment.Center)
|
||||||
|
)
|
||||||
|
CustomWindow(
|
||||||
|
state,
|
||||||
|
onRequestMinimize = null,
|
||||||
|
onRequestToggleMaximize = null,
|
||||||
|
onCloseRequest = onCancel,
|
||||||
|
alwaysOnTop = true,
|
||||||
|
) {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
window.minimumSize = Dimension(w, h)
|
||||||
|
}
|
||||||
|
val typeName = type.toString()
|
||||||
|
WindowTitle(typeName)
|
||||||
|
Column {
|
||||||
|
Row(
|
||||||
|
Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(8.dp),
|
||||||
|
) {
|
||||||
|
val color = when (type) {
|
||||||
|
ConfirmDialogType.Error -> myColors.info
|
||||||
|
ConfirmDialogType.Info -> myColors.warning
|
||||||
|
ConfirmDialogType.Success -> myColors.success
|
||||||
|
ConfirmDialogType.Warning -> myColors.warning
|
||||||
|
}
|
||||||
|
MyIcon(
|
||||||
|
icon = MyIcons.info,
|
||||||
|
tint = color,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
.requiredSize(36.dp),
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
title.rememberString(),
|
||||||
|
fontSize = myTextSizes.xl,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
message.rememberString(),
|
||||||
|
fontSize = myTextSizes.base,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ActionContainer(
|
||||||
|
Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.End,
|
||||||
|
) {
|
||||||
|
ActionButton(
|
||||||
|
myStringResource(Res.string.ok),
|
||||||
|
onClick = onConfirm
|
||||||
|
)
|
||||||
|
Spacer(Modifier.width(8.dp))
|
||||||
|
ActionButton(
|
||||||
|
myStringResource(Res.string.cancel),
|
||||||
|
onClick = onCancel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -305,4 +305,6 @@ translators_contribute_title=Improve Translations
|
|||||||
translators_contribute_description=Want to help improve this project? If your language isn't listed or needs some tweaks, you can contribute your translations and make it better\!
|
translators_contribute_description=Want to help improve this project? If your language isn't listed or needs some tweaks, you can contribute your translations and make it better\!
|
||||||
contribute=Contribute
|
contribute=Contribute
|
||||||
meet_the_translators=Meet the Translators
|
meet_the_translators=Meet the Translators
|
||||||
localized_by_translators=Localized by Translators
|
localized_by_translators=Localized by Translators
|
||||||
|
confirm_exit=Confirm Exit
|
||||||
|
confirm_exit_description=Are you sure you want to exit AB Download Manager?\nActive downloads/queues will be stopped!
|
Loading…
x
Reference in New Issue
Block a user