Jelajahi Sumber

Added server name to toolbar

Vadik Sirekanyan 2 tahun lalu
induk
melakukan
cfea2a542f

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

@@ -36,7 +36,7 @@ class MainActivity : ComponentActivity() {
                         }
                         Surface {
                             when (dialog) {
-                                is AddServerDialog -> AddServerContent(api, dao, state)
+                                is AddServerDialog -> AddServerContent(dao, state)
                                 is EditKeyDialog -> EditKeyContent(api, state, dialog)
                             }
                         }

+ 15 - 6
app/src/main/java/org/sirekanyan/outline/MainContent.kt

@@ -25,6 +25,8 @@ 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
+import androidx.compose.runtime.produceState
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
@@ -44,7 +46,7 @@ import org.sirekanyan.outline.ui.KeyBottomSheet
 
 @Composable
 fun MainContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
-    ModalNavigationDrawer({ DrawerContent(api, dao, state) }, drawerState = state.drawer) {
+    ModalNavigationDrawer({ DrawerContent(dao, state) }, drawerState = state.drawer) {
         val insets = WindowInsets.systemBars.asPaddingValues() + PaddingValues(top = 64.dp)
         when (val page = state.page) {
             is HelloPage -> {
@@ -55,6 +57,9 @@ fun MainContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
                         Text("Add server")
                     }
                 }
+                MainTopAppBar(stringResource(R.string.app_name)) {
+                    state.openDrawer()
+                }
             }
             is SelectedPage -> {
                 when (val keys = page.keys) {
@@ -80,11 +85,15 @@ fun MainContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
                 LaunchedEffect(page.selected) {
                     state.refreshCurrentKeys(showLoading = true)
                 }
+                val apiUrl = page.selected
+                val serverName by produceState(state.servers.getDefaultName(apiUrl), apiUrl) {
+                    value = state.servers.getName(apiUrl)
+                }
+                MainTopAppBar(serverName) {
+                    state.openDrawer()
+                }
             }
         }
-        MainTopAppBar {
-            state.openDrawer()
-        }
         AddKeyButton(
             isVisible = state.isFabVisible,
             isLoading = state.isFabLoading,
@@ -122,9 +131,9 @@ fun MainContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
 
 @Composable
 @OptIn(ExperimentalMaterial3Api::class)
-private fun MainTopAppBar(onMenuClick: () -> Unit) {
+private fun MainTopAppBar(title: String, onMenuClick: () -> Unit) {
     TopAppBar(
-        title = { Text(stringResource(R.string.app_name)) },
+        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

@@ -23,6 +23,7 @@ import org.sirekanyan.outline.feature.keys.KeysErrorState
 import org.sirekanyan.outline.feature.keys.KeysLoadingState
 import org.sirekanyan.outline.feature.keys.KeysState
 import org.sirekanyan.outline.feature.keys.KeysSuccessState
+import org.sirekanyan.outline.repository.ServerNameRepository
 import java.net.ConnectException
 import java.net.UnknownHostException
 
@@ -52,6 +53,7 @@ fun rememberMainState(api: OutlineApi): MainState {
 
 class MainState(val scope: CoroutineScope, private val api: OutlineApi) {
 
+    val servers = ServerNameRepository(api)
     val drawer = DrawerState(DrawerValue.Closed)
     var page by mutableStateOf<Page>(HelloPage)
     var dialog by mutableStateOf<Dialog?>(null)

+ 31 - 0
app/src/main/java/org/sirekanyan/outline/repository/ServerNameRepository.kt

@@ -0,0 +1,31 @@
+package org.sirekanyan.outline.repository
+
+import android.net.Uri
+import android.util.Log
+import org.sirekanyan.outline.api.OutlineApi
+import java.util.concurrent.ConcurrentHashMap
+
+class ServerNameRepository(private val api: OutlineApi) {
+
+    private val cache: MutableMap<String, String> = ConcurrentHashMap()
+
+    fun getDefaultName(apiUrl: String): String =
+        cache[apiUrl] ?: Uri.parse(apiUrl).host.orEmpty()
+
+    suspend fun fetchName(apiUrl: String): String =
+        api.getServerName(apiUrl).also { fetched ->
+            cache[apiUrl] = fetched
+        }
+
+    suspend fun getName(apiUrl: String): String {
+        if (!cache.containsKey(apiUrl)) {
+            try {
+                return fetchName(apiUrl)
+            } catch (exception: Exception) {
+                Log.d("OUTLINE", "Cannot fetch server name", exception)
+            }
+        }
+        return getDefaultName(apiUrl)
+    }
+
+}

+ 2 - 3
app/src/main/java/org/sirekanyan/outline/ui/AddServerContent.kt

@@ -21,18 +21,17 @@ import androidx.compose.ui.unit.dp
 import kotlinx.coroutines.launch
 import org.sirekanyan.outline.MainState
 import org.sirekanyan.outline.SelectedPage
-import org.sirekanyan.outline.api.OutlineApi
 import org.sirekanyan.outline.db.ApiUrlDao
 
 @Composable
-fun AddServerContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
+fun AddServerContent(dao: ApiUrlDao, state: MainState) {
     var draft by remember { mutableStateOf("") }
     var error by remember(draft) { mutableStateOf("") }
     var isLoading by remember { mutableStateOf(false) }
     suspend fun onAddClick() {
         try {
             isLoading = true
-            api.getServerName(draft)
+            state.servers.fetchName(draft)
             dao.insertUrl(draft)
             state.dialog = null
             state.page = SelectedPage(draft)

+ 3 - 10
app/src/main/java/org/sirekanyan/outline/ui/DrawerContent.kt

@@ -1,7 +1,5 @@
 package org.sirekanyan.outline.ui
 
-import android.net.Uri
-import android.util.Log
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
@@ -23,11 +21,10 @@ import org.sirekanyan.outline.AddServerDialog
 import org.sirekanyan.outline.MainState
 import org.sirekanyan.outline.R
 import org.sirekanyan.outline.SelectedPage
-import org.sirekanyan.outline.api.OutlineApi
 import org.sirekanyan.outline.db.ApiUrlDao
 
 @Composable
-fun DrawerContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
+fun DrawerContent(dao: ApiUrlDao, state: MainState) {
     ModalDrawerSheet {
         Text(
             text = stringResource(R.string.app_name),
@@ -37,12 +34,8 @@ fun DrawerContent(api: OutlineApi, dao: ApiUrlDao, state: MainState) {
         val apiUrls by remember { dao.observeUrls() }.collectAsState(listOf())
         apiUrls.forEach { apiUrl ->
             val selected = state.selected == apiUrl
-            val serverName by produceState(Uri.parse(apiUrl).host.orEmpty()) {
-                try {
-                    value = api.getServerName(apiUrl)
-                } catch (exception: Exception) {
-                    Log.d("OUTLINE", "Cannot fetch server name", exception)
-                }
+            val serverName by produceState(state.servers.getDefaultName(apiUrl), state.drawer.isOpen) {
+                value = state.servers.getName(apiUrl)
             }
             NavigationDrawerItem(
                 icon = { Icon(Icons.Default.Done, null) },