Vadik Sirekanyan 2 лет назад
Родитель
Сommit
3abcbd72ad

+ 13 - 0
app/src/main/java/org/sirekanyan/outline/MainActivity.kt

@@ -15,6 +15,7 @@ import org.sirekanyan.outline.api.OutlineApi
 import org.sirekanyan.outline.db.rememberApiUrlDao
 import org.sirekanyan.outline.ui.AddServerContent
 import org.sirekanyan.outline.ui.DeleteKeyContent
+import org.sirekanyan.outline.ui.DeleteServerContent
 import org.sirekanyan.outline.ui.EditKeyContent
 import org.sirekanyan.outline.ui.theme.OutlineTheme
 
@@ -55,6 +56,18 @@ class MainActivity : ComponentActivity() {
                                     }
                                 )
                             }
+                            is DeleteServerDialog -> {
+                                val (apiUrl, serverName) = dialog
+                                DeleteServerContent(
+                                    serverName = serverName,
+                                    onDismiss = { state.dialog = null },
+                                    onConfirm = {
+                                        dao.deleteUrl(apiUrl)
+                                        state.page = HelloPage
+                                        state.openDrawer()
+                                    }
+                                )
+                            }
                         }
                     }
                 }

+ 14 - 25
app/src/main/java/org/sirekanyan/outline/MainContent.kt

@@ -11,18 +11,12 @@ import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.systemBars
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
-import androidx.compose.material.icons.filled.Menu
+import androidx.compose.material.icons.filled.Delete
 import androidx.compose.material3.CircularProgressIndicator
-import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
-import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.ModalNavigationDrawer
 import androidx.compose.material3.Text
 import androidx.compose.material3.TextButton
-import androidx.compose.material3.TopAppBar
-import androidx.compose.material3.TopAppBarDefaults
-import androidx.compose.material3.surfaceColorAtElevation
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
@@ -57,9 +51,10 @@ fun MainContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
                         Text("Add server")
                     }
                 }
-                MainTopAppBar(stringResource(R.string.app_name)) {
-                    state.openDrawer()
-                }
+                MainTopAppBar(
+                    title = stringResource(R.string.app_name),
+                    onMenuClick = state::openDrawer,
+                )
             }
             is SelectedPage -> {
                 when (val keys = page.keys) {
@@ -89,9 +84,15 @@ fun MainContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
                 val server by produceState(state.servers.getCachedServer(apiUrl), apiUrl) {
                     value = state.servers.getServer(apiUrl)
                 }
-                MainTopAppBar(server.name) {
-                    state.openDrawer()
-                }
+                MainTopAppBar(
+                    title = server.name,
+                    onMenuClick = state::openDrawer,
+                    items = listOf(
+                        MenuItem("Delete", Icons.Default.Delete) {
+                            state.dialog = DeleteServerDialog(page.apiUrl, server.name)
+                        },
+                    ),
+                )
             }
         }
         AddKeyButton(
@@ -121,15 +122,3 @@ fun MainContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
         }
     }
 }
-
-@Composable
-@OptIn(ExperimentalMaterial3Api::class)
-private fun MainTopAppBar(title: String, onMenuClick: () -> Unit) {
-    TopAppBar(
-        title = { Text(title) },
-        navigationIcon = { IconButton({ onMenuClick() }) { Icon(Icons.Default.Menu, null) } },
-        colors = TopAppBarDefaults.topAppBarColors(
-            MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp).copy(alpha = 0.98f),
-        ),
-    )
-}

+ 2 - 0
app/src/main/java/org/sirekanyan/outline/MainState.kt

@@ -110,3 +110,5 @@ data object AddServerDialog : Dialog()
 data class EditKeyDialog(val apiUrl: String, val key: Key) : Dialog()
 
 data class DeleteKeyDialog(val apiUrl: String, val key: Key) : Dialog()
+
+data class DeleteServerDialog(val apiUrl: String, val serverName: String) : Dialog()

+ 63 - 0
app/src/main/java/org/sirekanyan/outline/MainTopAppBar.kt

@@ -0,0 +1,63 @@
+package org.sirekanyan.outline
+
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Menu
+import androidx.compose.material.icons.outlined.MoreVert
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.material3.surfaceColorAtElevation
+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 androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.dp
+
+data class MenuItem(val text: String, val icon: ImageVector, val onClick: () -> Unit)
+
+@Composable
+@OptIn(ExperimentalMaterial3Api::class)
+fun MainTopAppBar(
+    title: String,
+    onMenuClick: () -> Unit,
+    items: List<MenuItem> = listOf(),
+) {
+    TopAppBar(
+        title = { Text(title) },
+        navigationIcon = { IconButton({ onMenuClick() }) { Icon(Icons.Default.Menu, null) } },
+        actions = { MainMenu(items) },
+        colors = TopAppBarDefaults.topAppBarColors(
+            MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp).copy(alpha = 0.98f),
+        ),
+    )
+}
+
+@Composable
+private fun MainMenu(items: List<MenuItem>) {
+    if (items.isNotEmpty()) {
+        var isMenuVisible by remember { mutableStateOf(false) }
+        IconButton({ isMenuVisible = !isMenuVisible }) {
+            Icon(Icons.Outlined.MoreVert, null)
+        }
+        items.forEach { (text, icon, onClick) ->
+            DropdownMenu(isMenuVisible, { isMenuVisible = false }) {
+                DropdownMenuItem(
+                    text = { Text(text) },
+                    trailingIcon = { Icon(icon, null) },
+                    onClick = {
+                        isMenuVisible = false
+                        onClick()
+                    },
+                )
+            }
+        }
+    }
+}

+ 19 - 1
app/src/main/java/org/sirekanyan/outline/ui/DeleteKeyContent.kt → app/src/main/java/org/sirekanyan/outline/ui/ConfirmationAlertDialog.kt

@@ -12,10 +12,28 @@ import org.sirekanyan.outline.api.model.Key
 
 @Composable
 fun DeleteKeyContent(key: Key, onDismiss: () -> Unit, onConfirm: () -> Unit) {
+    ConfirmationAlertDialog(
+        text = "Are you sure you want to delete the key named \"${key.accessKey.nameOrDefault}\"?",
+        onDismiss = onDismiss,
+        onConfirm = onConfirm,
+    )
+}
+
+@Composable
+fun DeleteServerContent(serverName: String, onDismiss: () -> Unit, onConfirm: () -> Unit) {
+    ConfirmationAlertDialog(
+        text = "Are you sure you want to delete the server named \"$serverName\"?",
+        onDismiss = onDismiss,
+        onConfirm = onConfirm,
+    )
+}
+
+@Composable
+private fun ConfirmationAlertDialog(text: String, onDismiss: () -> Unit, onConfirm: () -> Unit) {
     AlertDialog(
         icon = { Icon(Icons.Default.Delete, null) },
         title = { Text("Confirmation") },
-        text = { Text("Are you sure you want to delete the key named \"${key.accessKey.nameOrDefault}\"?") },
+        text = { Text(text) },
         onDismissRequest = onDismiss,
         dismissButton = { TextButton(onDismiss) { Text("Cancel") } },
         confirmButton = {