diff --git a/src/main/kotlin/org/briarproject/briar/desktop/navigation/BriarSidebar.kt b/src/main/kotlin/org/briarproject/briar/desktop/navigation/BriarSidebar.kt index 0643899d7a09600241a7e6151ffcf4c6aed4dd7a..7f550bb33b869d605b9e9795e314198f9f1a2930 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/navigation/BriarSidebar.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/navigation/BriarSidebar.kt @@ -33,6 +33,7 @@ import androidx.compose.material.icons.filled.ChromeReaderMode import androidx.compose.material.icons.filled.Contacts import androidx.compose.material.icons.filled.Forum import androidx.compose.material.icons.filled.Group +import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.WifiTethering import androidx.compose.runtime.Composable @@ -44,6 +45,7 @@ import org.briarproject.bramble.api.identity.LocalAuthor import org.briarproject.briar.desktop.contact.ProfileCircle import org.briarproject.briar.desktop.theme.sidebarSurface import org.briarproject.briar.desktop.ui.UiMode +import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n import org.briarproject.briar.desktop.utils.getDesktopFeatureFlags val SIDEBAR_WIDTH = 56.dp @@ -53,6 +55,7 @@ fun BriarSidebar( account: LocalAuthor?, uiMode: UiMode, setUiMode: (UiMode) -> Unit, + showAbout: () -> Unit, ) { val displayButton = @Composable { selectedMode: UiMode, mode: UiMode, icon: ImageVector -> BriarSidebarButton( @@ -94,6 +97,12 @@ fun BriarSidebar( for ((mode, icon) in items) { displayButton(uiMode, mode, icon) } + BriarSidebarButton( + selected = false, + onClick = showAbout, + icon = Icons.Filled.Info, + contentDescription = i18n("access.about_briar_desktop") + ) } } } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/ui/AboutDialog.kt b/src/main/kotlin/org/briarproject/briar/desktop/ui/AboutDialog.kt new file mode 100644 index 0000000000000000000000000000000000000000..3f35d9dbe97d678b97eb3b2458b8ddab9f5005a9 --- /dev/null +++ b/src/main/kotlin/org/briarproject/briar/desktop/ui/AboutDialog.kt @@ -0,0 +1,113 @@ +package org.briarproject.briar.desktop.ui + +import androidx.compose.foundation.VerticalScrollbar +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.rememberScrollbarAdapter +import androidx.compose.material.Divider +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.TextField +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.max +import org.briarproject.briar.desktop.BuildData +import org.briarproject.briar.desktop.utils.PreviewUtils.preview +import java.time.Instant +import java.time.ZoneId +import java.time.format.DateTimeFormatter + +fun main() = preview( + "visible" to true, +) { + if (getBooleanParameter("visible")) { + AboutDialog( + onClose = { setBooleanParameter("visible", false) }, + ) + } +} + +@Composable +fun AboutDialog( + onClose: () -> Unit, +) { + // sizes of the two columns + val colSizes = listOf(0.3f, 0.7f) + + // format date + val buildTime = Instant.ofEpochMilli(BuildData.GIT_TIME).atZone(ZoneId.systemDefault()).toLocalDateTime() + + // rows displayed in table + val lines = buildList { + add(Pair("Copyright", "The Briar Project")) + add(Pair("License", "GNU Affero General Public License v3")) + add(Pair("Version", BuildData.VERSION)) + add(Pair("Git branch", BuildData.GIT_BRANCH)) + add(Pair("Git hash", BuildData.GIT_HASH)) + add(Pair("Commit time", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(buildTime))) + } + + BriarDialog(onClose = onClose) { + val box = this + Column( + modifier = Modifier.requiredSize( + box.maxWidth.times(0.8f), box.maxHeight.times(0.8f) + ).padding(16.dp) + ) { + Row(modifier = Modifier.padding(bottom = 8.dp), verticalAlignment = Alignment.CenterVertically) { + val minSize = 20.dp + BriarLogo(modifier = Modifier.heightIn(minSize, max(minSize, box.maxHeight.times(0.1f)))) + Text("Briar Desktop", style = MaterialTheme.typography.h4, modifier = Modifier.padding(start = 16.dp)) + } + val scrollState = rememberLazyListState() + Box { + LazyColumn(state = scrollState) { + item { + Divider(modifier = Modifier.fillMaxWidth().height(1.dp)) + } + items(lines) { (key, value) -> + // this is required for Divider between Boxes to have appropriate size + Row(Modifier.fillMaxWidth().height(IntrinsicSize.Min)) { + Box(modifier = Modifier.weight(colSizes[0]).fillMaxHeight()) { + Text( + text = key, + modifier = Modifier.padding(horizontal = 8.dp).padding(end = 8.dp) + .align(Alignment.CenterStart) + ) + } + Divider(modifier = Modifier.fillMaxHeight().width(1.dp)) + Box(modifier = Modifier.weight(colSizes[1]).fillMaxHeight()) { + TextField( + value = value, + onValueChange = {}, + readOnly = true, + singleLine = true, + modifier = Modifier.fillMaxWidth() + ) + } + } + Divider(modifier = Modifier.fillMaxWidth().height(1.dp)) + } + } + VerticalScrollbar( + adapter = rememberScrollbarAdapter(scrollState), + modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight() + ) + } + } + } +} diff --git a/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarDialog.kt b/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarDialog.kt new file mode 100644 index 0000000000000000000000000000000000000000..2618c41312e62c7f40197f6b7f9887ee90f8dff6 --- /dev/null +++ b/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarDialog.kt @@ -0,0 +1,45 @@ +package org.briarproject.briar.desktop.ui + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.BoxWithConstraintsScope +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class) +@Composable +fun BriarDialog( + onClose: () -> Unit, + content: @Composable BoxWithConstraintsScope.() -> Unit, +) { + BoxWithConstraints(Modifier.fillMaxSize()) { + Box( + modifier = Modifier.requiredSize(maxWidth, maxHeight) + .background(MaterialTheme.colors.onSurface.copy(alpha = 0.4f)) + .clickable( + // prevent visual indication + interactionSource = remember { MutableInteractionSource() }, + indication = null + ) { + onClose() + } + ) + + Surface(modifier = Modifier.align(Alignment.Center), shape = RoundedCornerShape(8.dp)) { + content() + } + } +} diff --git a/src/main/kotlin/org/briarproject/briar/desktop/ui/MainScreen.kt b/src/main/kotlin/org/briarproject/briar/desktop/ui/MainScreen.kt index 25b2f3c61267d54d2cf8e57390706eb31bc2998e..5dcf2d21213806d55fa28d86dadaf3d64b10b777 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/ui/MainScreen.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/ui/MainScreen.kt @@ -20,6 +20,10 @@ package org.briarproject.briar.desktop.ui import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import org.briarproject.briar.desktop.conversation.PrivateMessageScreen import org.briarproject.briar.desktop.navigation.BriarSidebar import org.briarproject.briar.desktop.navigation.SidebarViewModel @@ -38,11 +42,14 @@ fun MainScreen( settingsViewModel: SettingsViewModel, viewModel: SidebarViewModel = viewModel(), ) { + var showAbout by remember { mutableStateOf(false) } + Row { BriarSidebar( viewModel.account.value, viewModel.uiMode.value, viewModel::setUiMode, + { showAbout = true }, ) VerticalDivider() when (viewModel.uiMode.value) { @@ -52,4 +59,8 @@ fun MainScreen( else -> UiPlaceholder() } } + + if (showAbout) { + AboutDialog(onClose = { showAbout = false }) + } } diff --git a/src/main/resources/strings/BriarDesktop.properties b/src/main/resources/strings/BriarDesktop.properties index 5c4135d1272fae16cdac0940002978367af8f50e..c236a5ddea38973fa75371ff669c95ce6913de4a 100644 --- a/src/main/resources/strings/BriarDesktop.properties +++ b/src/main/resources/strings/BriarDesktop.properties @@ -13,6 +13,7 @@ access.message.send=Send message access.message.sent=Message sent access.logo=Briar logo access.swap=Icon showing errors between two contacts +access.about_briar_desktop=About Briar Desktop # Contacts contacts.none_selected.title=No contact selected