diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarTextContextMenu.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarTextContextMenu.kt new file mode 100644 index 0000000000000000000000000000000000000000..db17bba0ae49e6b36d4a91c8169f167d51231c3e --- /dev/null +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarTextContextMenu.kt @@ -0,0 +1,55 @@ +/* + * Briar Desktop + * Copyright (C) 2023 The Briar Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package org.briarproject.briar.desktop.ui + +import androidx.compose.foundation.ContextMenuArea +import androidx.compose.foundation.ContextMenuItem +import androidx.compose.foundation.ContextMenuState +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.text.TextContextMenu +import androidx.compose.foundation.text.TextContextMenu.TextManager +import androidx.compose.runtime.Composable +import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n + +@OptIn(ExperimentalFoundationApi::class) +object BriarTextContextMenu : TextContextMenu { + @Composable + override fun Area(textManager: TextManager, state: ContextMenuState, content: @Composable () -> Unit) { + val items = { + listOfNotNull( + textManager.cut?.let { + ContextMenuItem(i18n("cut"), it) + }, + textManager.copy?.let { + // don't show copy option if no text is selected + if (textManager.selectedText.isEmpty()) null + else ContextMenuItem(i18n("copy"), it) + }, + textManager.paste?.let { + ContextMenuItem(i18n("paste"), it) + }, + textManager.selectAll?.let { + ContextMenuItem(i18n("select_all"), it) + }, + ) + } + + ContextMenuArea(items, state, content = content) + } +} diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt index c7b63caf06925e6d4ca6ba6f6f66ab0b7dce005b..c9fe9daf2a696da2a7f9469f427a3cc414658813 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt @@ -1,6 +1,6 @@ /* * Briar Desktop - * Copyright (C) 2021-2022 The Briar Project + * Copyright (C) 2021-2023 The Briar Project * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -18,9 +18,11 @@ package org.briarproject.briar.desktop.ui +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.text.LocalTextContextMenu import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect @@ -34,8 +36,6 @@ import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.toAwtImage import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.platform.LocalLocalization -import androidx.compose.ui.platform.PlatformLocalization import androidx.compose.ui.res.painterResource import androidx.compose.ui.window.FrameWindowScope import androidx.compose.ui.window.Window @@ -117,14 +117,9 @@ constructor( } } + @OptIn(ExperimentalFoundationApi::class) @Composable override fun start(onClose: () -> Unit) { - val platformLocalization = object : PlatformLocalization { - override val copy = i18n("copy") - override val cut = i18n("cut") - override val paste = i18n("paste") - override val selectAll = i18n("select_all") - } val focusState = remember { WindowFocusState() } Window( @@ -167,11 +162,19 @@ constructor( val messageCounterListener: MessageCounterListener = { (type, total, groups, inc) -> if (inc && total > 0 && !focusState.focused) { val callback: NotificationProvider.() -> Unit = when (type) { - PrivateMessage -> { { notifyPrivateMessages(total, groups) } } - Forum -> { { notifyForumPosts(total, groups) } } + PrivateMessage -> { + { notifyPrivateMessages(total, groups) } + } + + Forum -> { + { notifyForumPosts(total, groups) } + } } val (lastNotification, setLastNotification) = when (type) { - PrivateMessage -> lastNotificationPrivateMessage to { v: Long -> lastNotificationPrivateMessage = v } + PrivateMessage -> lastNotificationPrivateMessage to { v: Long -> + lastNotificationPrivateMessage = v + } + Forum -> lastNotificationForum to { v: Long -> lastNotificationForum = v } } @@ -209,7 +212,7 @@ constructor( LocalViewModelProvider provides viewModelProvider, LocalAvatarManager provides avatarManager, LocalConfiguration provides configuration, - LocalLocalization provides platformLocalization, + LocalTextContextMenu provides BriarTextContextMenu, ) { // invalidate whole application window in case the theme or language setting is changed configuration.invalidateScreen.react {