mirror of
https://github.com/openflocon/Flocon.git
synced 2026-05-05 16:54:22 +00:00
Feature/system notification (#101)
* feature: System notification * feature: Type * fix: Settings --------- Co-authored-by: TEYSSANDIER Raphael <rteyssandier@sephora.fr>
This commit is contained in:
parent
8147d8852c
commit
0fe9d4e60b
22 changed files with 158 additions and 51 deletions
|
|
@ -1,8 +1,8 @@
|
|||
package io.github.openflocon.flocondesktop.app.di
|
||||
|
||||
import io.github.openflocon.flocondesktop.app.InitialSetupStateHolder
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayerHandler
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayerHandler
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayerImpl
|
||||
import org.koin.core.module.dsl.bind
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
package io.github.openflocon.flocondesktop.common.ui.feedback
|
||||
|
||||
interface FeedbackDisplayer {
|
||||
fun displayMessage(
|
||||
message: String,
|
||||
type: MessageType = MessageType.Success,
|
||||
)
|
||||
|
||||
enum class MessageType {
|
||||
Success,
|
||||
Error,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
package io.github.openflocon.flocondesktop.common.ui.feedback
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface FeedbackDisplayerHandler {
|
||||
val messagesToDisplay: Flow<MessageToDisplayUi>
|
||||
|
||||
data class MessageToDisplayUi(
|
||||
val message: String,
|
||||
val type: FeedbackDisplayer.MessageType,
|
||||
val id: String,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
package io.github.openflocon.flocondesktop.common.ui.feedback
|
||||
|
||||
import io.github.openflocon.domain.common.DispatcherProvider
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayerHandler
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayerHandler.MessageToDisplayUi
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayerHandler.NotificationToDisplayUi
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
|
|
@ -14,10 +18,11 @@ class FeedbackDisplayerImpl(
|
|||
FeedbackDisplayerHandler {
|
||||
private val scope = CoroutineScope(dispatcherProvider.ui + SupervisorJob())
|
||||
|
||||
private val _messagesToDisplay: Channel<FeedbackDisplayerHandler.MessageToDisplayUi> =
|
||||
Channel()
|
||||
override val messagesToDisplay: Flow<FeedbackDisplayerHandler.MessageToDisplayUi> =
|
||||
_messagesToDisplay.receiveAsFlow()
|
||||
private val _messagesToDisplay: Channel<MessageToDisplayUi> = Channel()
|
||||
override val messagesToDisplay: Flow<MessageToDisplayUi> = _messagesToDisplay.receiveAsFlow()
|
||||
|
||||
private val _notificationsToDisplay: Channel<NotificationToDisplayUi> = Channel()
|
||||
override val notificationsToDisplay: Flow<NotificationToDisplayUi> = _notificationsToDisplay.receiveAsFlow()
|
||||
|
||||
override fun displayMessage(
|
||||
message: String,
|
||||
|
|
@ -25,7 +30,7 @@ class FeedbackDisplayerImpl(
|
|||
) {
|
||||
scope.launch {
|
||||
_messagesToDisplay.send(
|
||||
FeedbackDisplayerHandler.MessageToDisplayUi(
|
||||
MessageToDisplayUi(
|
||||
message = message,
|
||||
type = type,
|
||||
id = System.currentTimeMillis().toString(),
|
||||
|
|
@ -33,4 +38,17 @@ class FeedbackDisplayerImpl(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun displayNotification(title: String, message: String, type: FeedbackDisplayer.NotificationType) {
|
||||
scope.launch {
|
||||
_notificationsToDisplay.send(
|
||||
NotificationToDisplayUi(
|
||||
title = title,
|
||||
message = message,
|
||||
type = type
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayerHandler
|
||||
import io.github.openflocon.library.designsystem.FloconTheme
|
||||
import org.koin.compose.koinInject
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import androidx.lifecycle.viewModelScope
|
|||
import io.github.openflocon.domain.analytics.usecase.ObserveCurrentDeviceAnalyticsContentUseCase
|
||||
import io.github.openflocon.domain.analytics.usecase.ResetCurrentDeviceSelectedAnalyticsUseCase
|
||||
import io.github.openflocon.domain.common.DispatcherProvider
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.analytics.delegate.AnalyticsSelectorDelegate
|
||||
import io.github.openflocon.flocondesktop.features.analytics.model.AnalyticsContentStateUiModel
|
||||
import io.github.openflocon.flocondesktop.features.analytics.model.AnalyticsRowUiModel
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import io.github.openflocon.domain.dashboard.usecase.ObserveCurrentDeviceDashboa
|
|||
import io.github.openflocon.domain.dashboard.usecase.SendCheckBoxUpdateDeviceDeviceUseCase
|
||||
import io.github.openflocon.domain.dashboard.usecase.SendClickEventToDeviceDeviceUseCase
|
||||
import io.github.openflocon.domain.dashboard.usecase.SubmitTextFieldToDeviceDeviceUseCase
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.dashboard.delegate.DashboardSelectorDelegate
|
||||
import io.github.openflocon.flocondesktop.features.dashboard.mapper.toUi
|
||||
import io.github.openflocon.flocondesktop.features.dashboard.model.DashboardViewState
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import io.github.openflocon.domain.common.DispatcherProvider
|
|||
import io.github.openflocon.domain.database.models.DatabaseExecuteSqlResponseDomainModel
|
||||
import io.github.openflocon.domain.database.usecase.ExecuteDatabaseQueryUseCase
|
||||
import io.github.openflocon.domain.database.usecase.ObserveLastSuccessQueriesUseCase
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.database.delegate.DatabaseSelectorDelegate
|
||||
import io.github.openflocon.flocondesktop.features.database.model.DatabaseRowUiModel
|
||||
import io.github.openflocon.flocondesktop.features.database.model.DatabaseScreenState
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import androidx.lifecycle.viewModelScope
|
|||
import io.github.openflocon.domain.common.DispatcherProvider
|
||||
import io.github.openflocon.domain.deeplink.usecase.ExecuteDeeplinkUseCase
|
||||
import io.github.openflocon.domain.deeplink.usecase.ObserveCurrentDeviceDeeplinkUseCase
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.deeplinks.mapper.mapToUi
|
||||
import io.github.openflocon.flocondesktop.features.deeplinks.model.DeeplinkPart
|
||||
import io.github.openflocon.flocondesktop.features.deeplinks.model.DeeplinkViewState
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import io.github.openflocon.domain.files.usecase.DeleteFileUseCase
|
|||
import io.github.openflocon.domain.files.usecase.DeleteFolderContentUseCase
|
||||
import io.github.openflocon.domain.files.usecase.ObserveFolderContentUseCase
|
||||
import io.github.openflocon.domain.files.usecase.RefreshFolderContentUseCase
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.files.mapper.buildContextualActions
|
||||
import io.github.openflocon.flocondesktop.features.files.mapper.toDomain
|
||||
import io.github.openflocon.flocondesktop.features.files.mapper.toUi
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import androidx.lifecycle.viewModelScope
|
|||
import io.github.openflocon.domain.common.DispatcherProvider
|
||||
import io.github.openflocon.domain.images.usecase.ObserveImagesUseCase
|
||||
import io.github.openflocon.domain.images.usecase.ResetCurrentDeviceImagesUseCase
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.images.model.ImagesStateUiModel
|
||||
import io.github.openflocon.flocondesktop.features.images.model.ImagesUiModel
|
||||
import io.github.openflocon.flocondesktop.features.network.mapper.formatTimestamp
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import io.github.openflocon.domain.network.usecase.mocks.GenerateNetworkMockFrom
|
|||
import io.github.openflocon.domain.network.usecase.mocks.GetNetworkMockByIdUseCase
|
||||
import io.github.openflocon.domain.network.usecase.mocks.ObserveNetworkMocksUseCase
|
||||
import io.github.openflocon.domain.network.usecase.mocks.UpdateNetworkMockIsEnabledUseCase
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.network.mapper.toDomain
|
||||
import io.github.openflocon.flocondesktop.features.network.mapper.toLineUi
|
||||
import io.github.openflocon.flocondesktop.features.network.mapper.toUi
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import io.github.openflocon.domain.network.usecase.ObserveHttpRequestsUseCase
|
|||
import io.github.openflocon.domain.network.usecase.RemoveHttpRequestUseCase
|
||||
import io.github.openflocon.domain.network.usecase.RemoveHttpRequestsBeforeUseCase
|
||||
import io.github.openflocon.domain.network.usecase.ResetCurrentDeviceHttpRequestsUseCase
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.network.delegate.HeaderDelegate
|
||||
import io.github.openflocon.flocondesktop.features.network.mapper.toDetailUi
|
||||
import io.github.openflocon.flocondesktop.features.network.mapper.toUi
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import io.github.openflocon.domain.common.DispatcherProvider
|
|||
import io.github.openflocon.domain.sharedpreference.models.SharedPreferenceRowDomainModel
|
||||
import io.github.openflocon.domain.sharedpreference.usecase.EditSharedPrefFieldUseCase
|
||||
import io.github.openflocon.domain.sharedpreference.usecase.ObserveCurrentDeviceSharedPreferenceValuesUseCase
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.sharedpreferences.delegate.SharedPrefSelectorDelegate
|
||||
import io.github.openflocon.flocondesktop.features.sharedpreferences.model.DeviceSharedPrefUiModel
|
||||
import io.github.openflocon.flocondesktop.features.sharedpreferences.model.SharedPreferencesRowUiModel
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import androidx.lifecycle.viewModelScope
|
|||
import io.github.openflocon.domain.common.DispatcherProvider
|
||||
import io.github.openflocon.domain.table.usecase.ObserveCurrentDeviceTableContentUseCase
|
||||
import io.github.openflocon.domain.table.usecase.ResetCurrentDeviceSelectedTableUseCase
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.flocondesktop.features.network.mapper.formatTimestamp
|
||||
import io.github.openflocon.flocondesktop.features.table.delegate.TableSelectorDelegate
|
||||
import io.github.openflocon.flocondesktop.features.table.model.DeviceTableUiModel
|
||||
|
|
|
|||
|
|
@ -165,25 +165,23 @@ private fun MainScreen(
|
|||
|
||||
SubScreen.Settings -> {
|
||||
SettingsScreen(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
||||
SubScreen.Deeplinks -> {
|
||||
DeeplinkScreen(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
||||
SubScreen.Analytics -> {
|
||||
AnalyticsScreen(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import io.github.openflocon.domain.common.DispatcherProvider
|
|||
import io.github.openflocon.domain.settings.repository.SettingsRepository
|
||||
import io.github.openflocon.domain.settings.usecase.TestAdbUseCase
|
||||
import io.github.openflocon.flocondesktop.app.InitialSetupStateHolder
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import io.github.openflocon.domain.common.Failure
|
|||
import io.github.openflocon.domain.common.Success
|
||||
import io.github.openflocon.flocondesktop.common.coroutines.closeable.CloseableDelegate
|
||||
import io.github.openflocon.flocondesktop.common.coroutines.closeable.CloseableScoped
|
||||
import io.github.openflocon.flocondesktop.common.ui.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.messages.usecase.HandleIncomingMessagesUseCase
|
||||
import io.github.openflocon.domain.messages.usecase.StartServerUseCase
|
||||
import kotlinx.coroutines.delay
|
||||
|
|
|
|||
|
|
@ -1,17 +1,27 @@
|
|||
package io.github.openflocon.flocondesktop
|
||||
|
||||
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
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.window.ApplicationScope
|
||||
import androidx.compose.ui.window.FrameWindowScope
|
||||
import androidx.compose.ui.window.MenuBar
|
||||
import androidx.compose.ui.window.Notification
|
||||
import androidx.compose.ui.window.Tray
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
import androidx.compose.ui.window.rememberTrayState
|
||||
import androidx.compose.ui.window.rememberWindowState
|
||||
import coil3.ImageLoader
|
||||
import coil3.compose.setSingletonImageLoaderFactory
|
||||
import coil3.network.ktor3.KtorNetworkFetcherFactory
|
||||
import flocondesktop.composeapp.generated.resources.Res
|
||||
import flocondesktop.composeapp.generated.resources.app_icon_small
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayer
|
||||
import io.github.openflocon.domain.feedback.FeedbackDisplayerHandler
|
||||
import io.github.openflocon.flocondesktop.about.AboutScreen
|
||||
import io.github.openflocon.flocondesktop.window.MIN_WINDOW_HEIGHT
|
||||
import io.github.openflocon.flocondesktop.window.MIN_WINDOW_WIDTH
|
||||
|
|
@ -20,14 +30,22 @@ import io.github.openflocon.flocondesktop.window.WindowStateSaver
|
|||
import io.github.openflocon.flocondesktop.window.size
|
||||
import io.github.openflocon.flocondesktop.window.windowPosition
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.koin.compose.koinInject
|
||||
import java.awt.Desktop
|
||||
import java.awt.Dimension
|
||||
|
||||
private const val ACTIVATE_TRAY_NOTIFICATION = false
|
||||
|
||||
fun main() {
|
||||
System.setProperty("apple.awt.application.name", "Flocon")
|
||||
|
||||
return application {
|
||||
var openAbout by remember { mutableStateOf(false) }
|
||||
val savedState = remember { WindowStateSaver.load() }
|
||||
val windowState = rememberWindowState(
|
||||
size = savedState.size(),
|
||||
position = savedState.windowPosition(),
|
||||
)
|
||||
|
||||
Desktop.getDesktop().setAboutHandler {
|
||||
openAbout = true
|
||||
|
|
@ -41,15 +59,6 @@ fun main() {
|
|||
}.build()
|
||||
}
|
||||
|
||||
val savedState = remember {
|
||||
WindowStateSaver.load()
|
||||
}
|
||||
|
||||
val windowState = rememberWindowState(
|
||||
size = savedState.size(),
|
||||
position = savedState.windowPosition(),
|
||||
)
|
||||
|
||||
Window(
|
||||
state = windowState,
|
||||
onCloseRequest = {
|
||||
|
|
@ -70,8 +79,12 @@ fun main() {
|
|||
icon = painterResource(Res.drawable.app_icon_small), // Remove black behind icon
|
||||
) {
|
||||
window.minimumSize = Dimension(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
|
||||
|
||||
App()
|
||||
if (ACTIVATE_TRAY_NOTIFICATION) {
|
||||
FloconTray()
|
||||
}
|
||||
// TODO later
|
||||
// FloconMenu()
|
||||
|
||||
if (openAbout) {
|
||||
AboutScreen(
|
||||
|
|
@ -81,3 +94,57 @@ fun main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FrameWindowScope.FloconMenu() {
|
||||
var openSettings by remember { mutableStateOf(false) }
|
||||
|
||||
MenuBar {
|
||||
Menu(
|
||||
text = "Settings"
|
||||
) {
|
||||
Item(
|
||||
text = "Open",
|
||||
onClick = {
|
||||
openSettings = true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Later
|
||||
// if (openSettings) {
|
||||
// SettingsScreen(
|
||||
// onCloseRequest = { openSettings = false }
|
||||
// )
|
||||
// }
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ApplicationScope.FloconTray() {
|
||||
val trayState = rememberTrayState()
|
||||
val feedbackDisplayerHandler = koinInject<FeedbackDisplayerHandler>()
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
feedbackDisplayerHandler.notificationsToDisplay
|
||||
.collect { notification ->
|
||||
trayState.sendNotification(
|
||||
Notification(
|
||||
title = notification.title,
|
||||
message = notification.message,
|
||||
type = when (notification.type) {
|
||||
FeedbackDisplayer.NotificationType.None -> Notification.Type.None
|
||||
FeedbackDisplayer.NotificationType.Info -> Notification.Type.Info
|
||||
FeedbackDisplayer.NotificationType.Warning -> Notification.Type.Warning
|
||||
FeedbackDisplayer.NotificationType.Error -> Notification.Type.Error
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Tray(
|
||||
state = trayState,
|
||||
icon = painterResource(Res.drawable.app_icon_small)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue