浏览代码

Replaced string with api url

Vadik Sirekanyan 2 年之前
父节点
当前提交
aac7da090e

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

@@ -62,7 +62,7 @@ class MainActivity : ComponentActivity() {
                                     serverName = serverName,
                                     onDismiss = { state.dialog = null },
                                     onConfirm = {
-                                        dao.deleteUrl(apiUrl)
+                                        dao.deleteUrl(apiUrl.id)
                                         state.page = HelloPage
                                         state.openDrawer()
                                     }

+ 5 - 4
app/src/main/java/org/sirekanyan/outline/MainState.kt

@@ -18,6 +18,7 @@ import kotlinx.coroutines.launch
 import kotlinx.coroutines.plus
 import org.sirekanyan.outline.api.OutlineApi
 import org.sirekanyan.outline.api.model.Key
+import org.sirekanyan.outline.db.model.ApiUrl
 import org.sirekanyan.outline.ext.logError
 import org.sirekanyan.outline.feature.keys.KeysErrorState
 import org.sirekanyan.outline.feature.keys.KeysLoadingState
@@ -99,7 +100,7 @@ sealed class Page
 
 data object HelloPage : Page()
 
-data class SelectedPage(val apiUrl: String) : Page() {
+data class SelectedPage(val apiUrl: ApiUrl) : Page() {
     var keys by mutableStateOf<KeysState>(KeysLoadingState)
 }
 
@@ -107,8 +108,8 @@ sealed class Dialog
 
 data object AddServerDialog : Dialog()
 
-data class EditKeyDialog(val apiUrl: String, val key: Key) : Dialog()
+data class EditKeyDialog(val apiUrl: ApiUrl, val key: Key) : Dialog()
 
-data class DeleteKeyDialog(val apiUrl: String, val key: Key) : Dialog()
+data class DeleteKeyDialog(val apiUrl: ApiUrl, val key: Key) : Dialog()
 
-data class DeleteServerDialog(val apiUrl: String, val serverName: String) : Dialog()
+data class DeleteServerDialog(val apiUrl: ApiUrl, val serverName: String) : Dialog()

+ 27 - 17
app/src/main/java/org/sirekanyan/outline/api/OutlineApi.kt

@@ -4,12 +4,12 @@ import io.ktor.client.HttpClient
 import io.ktor.client.call.body
 import io.ktor.client.engine.okhttp.OkHttp
 import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
-import io.ktor.client.request.delete
-import io.ktor.client.request.get
-import io.ktor.client.request.post
-import io.ktor.client.request.put
+import io.ktor.client.request.HttpRequestBuilder
+import io.ktor.client.request.request
 import io.ktor.client.request.setBody
+import io.ktor.client.statement.HttpResponse
 import io.ktor.http.ContentType
+import io.ktor.http.HttpMethod
 import io.ktor.http.contentType
 import io.ktor.serialization.kotlinx.json.json
 import kotlinx.serialization.json.Json
@@ -20,6 +20,7 @@ import org.sirekanyan.outline.api.model.RenameRequest
 import org.sirekanyan.outline.api.model.Server
 import org.sirekanyan.outline.api.model.ServerNameResponse
 import org.sirekanyan.outline.api.model.TransferMetricsResponse
+import org.sirekanyan.outline.db.model.ApiUrl
 import org.sirekanyan.outline.ext.logDebug
 import java.security.SecureRandom
 import javax.net.ssl.SSLContext
@@ -44,42 +45,51 @@ class OutlineApi {
         }
     }
 
-    suspend fun getServer(apiUrl: String): Server {
-        val name = httpClient.get("$apiUrl/server").body<ServerNameResponse>().name
+    private suspend fun request(
+        httpMethod: HttpMethod,
+        apiUrl: ApiUrl,
+        path: String,
+        block: HttpRequestBuilder.() -> Unit = {},
+    ): HttpResponse {
+        return httpClient.request(apiUrl.id + '/' + path) { method = httpMethod; block() }
+    }
+
+    suspend fun getServer(apiUrl: ApiUrl): Server {
+        val name = request(HttpMethod.Get, apiUrl, "server").body<ServerNameResponse>().name
         val transferMetrics = getTransferMetrics(apiUrl)?.bytesTransferredByUserId
         return Server(name, transferMetrics?.values?.sum())
     }
 
-    suspend fun getKeys(apiUrl: String): List<Key> {
+    suspend fun getKeys(apiUrl: ApiUrl): List<Key> {
         val accessKeys = getAccessKeys(apiUrl).accessKeys
         val transferMetrics = getTransferMetrics(apiUrl)?.bytesTransferredByUserId
         return accessKeys.map { accessKey -> Key(accessKey, transferMetrics?.get(accessKey.id)) }
     }
 
-    private suspend fun getAccessKeys(apiUrl: String): AccessKeysResponse =
-        httpClient.get("$apiUrl/access-keys").body()
+    private suspend fun getAccessKeys(apiUrl: ApiUrl): AccessKeysResponse =
+        request(HttpMethod.Get, apiUrl, "access-keys").body()
 
-    private suspend fun getTransferMetrics(apiUrl: String): TransferMetricsResponse? =
+    private suspend fun getTransferMetrics(apiUrl: ApiUrl): TransferMetricsResponse? =
         try {
-            httpClient.get("$apiUrl/metrics/transfer").body()
+            request(HttpMethod.Get, apiUrl, "metrics/transfer").body()
         } catch (exception: Exception) {
             logDebug("Cannot fetch transfer metrics", exception)
             null
         }
 
-    suspend fun createAccessKey(apiUrl: String) {
-        httpClient.post("$apiUrl/access-keys")
+    suspend fun createAccessKey(apiUrl: ApiUrl) {
+        request(HttpMethod.Post, apiUrl, "access-keys")
     }
 
-    suspend fun renameAccessKey(apiUrl: String, id: String, name: String) {
-        httpClient.put("$apiUrl/access-keys/$id/name") {
+    suspend fun renameAccessKey(apiUrl: ApiUrl, id: String, name: String) {
+        request(HttpMethod.Put, apiUrl, "access-keys/$id/name") {
             contentType(ContentType.Application.Json)
             setBody(RenameRequest(name))
         }
     }
 
-    suspend fun deleteAccessKey(apiUrl: String, id: String) {
-        httpClient.delete("$apiUrl/access-keys/$id")
+    suspend fun deleteAccessKey(apiUrl: ApiUrl, id: String) {
+        request(HttpMethod.Delete, apiUrl, "access-keys/$id")
     }
 
 }

+ 7 - 6
app/src/main/java/org/sirekanyan/outline/repository/ServerRepository.kt

@@ -3,6 +3,7 @@ package org.sirekanyan.outline.repository
 import android.net.Uri
 import org.sirekanyan.outline.api.OutlineApi
 import org.sirekanyan.outline.api.model.Server
+import org.sirekanyan.outline.db.model.ApiUrl
 import org.sirekanyan.outline.ext.logDebug
 import java.util.concurrent.ConcurrentHashMap
 
@@ -10,16 +11,16 @@ class ServerRepository(private val api: OutlineApi) {
 
     private val cache: MutableMap<String, Server> = ConcurrentHashMap()
 
-    fun getCachedServer(apiUrl: String): Server =
-        cache[apiUrl] ?: Server(Uri.parse(apiUrl).host.orEmpty(), traffic = null)
+    fun getCachedServer(apiUrl: ApiUrl): Server =
+        cache[apiUrl.id] ?: Server(Uri.parse(apiUrl.id).host.orEmpty(), traffic = null)
 
-    suspend fun fetchServer(apiUrl: String): Server =
+    suspend fun fetchServer(apiUrl: ApiUrl): Server =
         api.getServer(apiUrl).also { fetched ->
-            cache[apiUrl] = fetched
+            cache[apiUrl.id] = fetched
         }
 
-    suspend fun getServer(apiUrl: String): Server {
-        if (!cache.containsKey(apiUrl)) {
+    suspend fun getServer(apiUrl: ApiUrl): Server {
+        if (!cache.containsKey(apiUrl.id)) {
             try {
                 return fetchServer(apiUrl)
             } catch (exception: Exception) {

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

@@ -44,10 +44,11 @@ fun AddServerContent(dao: ApiUrlDao, state: MainState) {
         }
         try {
             isLoading = true
-            state.servers.fetchServer(draft)
-            dao.insertUrl(ApiUrl(draft, insecure))
+            val apiUrl = ApiUrl(draft, insecure)
+            state.servers.fetchServer(apiUrl)
+            dao.insertUrl(apiUrl)
             state.dialog = null
-            state.page = SelectedPage(draft)
+            state.page = SelectedPage(apiUrl)
             state.closeDrawer(animated = false)
         } catch (exception: Exception) {
             exception.printStackTrace()

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

@@ -37,7 +37,6 @@ import org.sirekanyan.outline.MainState
 import org.sirekanyan.outline.R
 import org.sirekanyan.outline.SelectedPage
 import org.sirekanyan.outline.db.ApiUrlDao
-import org.sirekanyan.outline.db.model.ApiUrl
 import org.sirekanyan.outline.isPlayFlavor
 import org.sirekanyan.outline.text.formatTraffic
 import org.sirekanyan.outline.ui.icons.IconOpenInNew
@@ -66,8 +65,8 @@ private fun DrawerSheetContent(dao: ApiUrlDao, state: MainState, insets: Padding
             style = MaterialTheme.typography.titleSmall,
         )
         val apiUrls by remember { dao.observeUrls() }.collectAsState(listOf())
-        apiUrls.map(ApiUrl::id).forEach { apiUrl ->
-            val isSelected = state.selectedPage?.apiUrl == apiUrl
+        apiUrls.forEach { apiUrl ->
+            val isSelected = state.selectedPage?.apiUrl?.id == apiUrl.id
             val server by produceState(state.servers.getCachedServer(apiUrl), state.drawer.isOpen) {
                 value = state.servers.getServer(apiUrl)
             }