Skip to content

Commit

Permalink
perf: upload dialog, move log to AdvancedPage
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Aug 7, 2024
1 parent eebcf24 commit ab8afce
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 341 deletions.
95 changes: 93 additions & 2 deletions app/src/main/kotlin/li/songe/gkd/ui/AdvancedPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Upload
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalTextStyle
Expand All @@ -46,6 +49,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.core.content.ContextCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewModelScope
Expand Down Expand Up @@ -82,12 +86,16 @@ import li.songe.gkd.util.LocalLauncher
import li.songe.gkd.util.LocalNavController
import li.songe.gkd.util.ProfileTransitions
import li.songe.gkd.util.appInfoCacheFlow
import li.songe.gkd.util.buildLogFile
import li.songe.gkd.util.json
import li.songe.gkd.util.launchAsFn
import li.songe.gkd.util.launchTry
import li.songe.gkd.util.openApp
import li.songe.gkd.util.openUri
import li.songe.gkd.util.saveFileToDownloads
import li.songe.gkd.util.shareFile
import li.songe.gkd.util.storeFlow
import li.songe.gkd.util.throttle
import li.songe.gkd.util.toast
import rikka.shizuku.Shizuku

Expand All @@ -103,10 +111,62 @@ fun AdvancedPage() {
val snapshotCount by vm.snapshotCountFlow.collectAsState()

ShizukuErrorDialog(vm.shizukuErrorFlow)
vm.uploadOptions.ShowDialog()

var showPortDlg by remember {
mutableStateOf(false)
}
var showShareLogDlg by remember {
mutableStateOf(false)
}
if (showShareLogDlg) {
Dialog(onDismissRequest = { showShareLogDlg = false }) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
val modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
Text(
text = "分享到其他应用", modifier = Modifier
.clickable(onClick = throttle {
showShareLogDlg = false
vm.viewModelScope.launchTry(Dispatchers.IO) {
val logZipFile = buildLogFile()
context.shareFile(logZipFile, "分享日志文件")
}
})
.then(modifier)
)
Text(
text = "保存到下载", modifier = Modifier
.clickable(onClick = throttle {
showShareLogDlg = false
vm.viewModelScope.launchTry(Dispatchers.IO) {
val logZipFile = buildLogFile()
context.saveFileToDownloads(logZipFile)
}
})
.then(modifier)
)
Text(
text = "生成链接(需科学上网)",
modifier = Modifier
.clickable(onClick = throttle {
showShareLogDlg = false
vm.viewModelScope.launchTry(Dispatchers.IO) {
val logZipFile = buildLogFile()
vm.uploadOptions.startTask(logZipFile)
}
})
.then(modifier)
)
}
}
}

val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(
Expand Down Expand Up @@ -324,7 +384,7 @@ fun AdvancedPage() {
}

TextSwitch(
name = "隐藏快照状态栏",
name = "隐藏状态栏",
desc = "当保存快照时,隐藏截图里的顶部状态栏高度区域",
checked = store.hideSnapshotStatusBar
) {
Expand All @@ -334,7 +394,7 @@ fun AdvancedPage() {
}

TextSwitch(
name = "保存快照提示",
name = "保存提示",
desc = "保存快照时是否提示\"正在保存快照\"",
checked = store.showSaveSnapshotToast
) {
Expand All @@ -343,6 +403,37 @@ fun AdvancedPage() {
)
}

Text(
text = "日志",
modifier = Modifier.titleItemPadding(),
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.primary,
)

TextSwitch(name = "保存日志",
desc = "保存7天日志,帮助定位BUG",
checked = store.log2FileSwitch,
onCheckedChange = {
storeFlow.value = store.copy(
log2FileSwitch = it
)
if (!it) {
context.mainVm.viewModelScope.launchTry(Dispatchers.IO) {
val logFiles = LogUtils.getLogFiles()
if (logFiles.isNotEmpty()) {
logFiles.forEach { f ->
f.delete()
}
toast("已删除全部日志")
}
}
}
})

SettingItem(title = "导出日志", imageVector = Icons.Default.Upload, onClick = {
showShareLogDlg = true
})

Text(
text = "其它",
modifier = Modifier.titleItemPadding(),
Expand Down
6 changes: 4 additions & 2 deletions app/src/main/kotlin/li/songe/gkd/ui/AdvancedVm.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package li.songe.gkd.ui

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.component.UploadOptions
import javax.inject.Inject

@HiltViewModel
class AdvancedVm @Inject constructor(stateHandle: SavedStateHandle) : ViewModel() {
class AdvancedVm @Inject constructor() : ViewModel() {
val snapshotCountFlow =
DbSet.snapshotDao.count().stateIn(viewModelScope, SharingStarted.Eagerly, 0)

val shizukuErrorFlow = MutableStateFlow(false)

val uploadOptions = UploadOptions(viewModelScope)
}
75 changes: 4 additions & 71 deletions app/src/main/kotlin/li/songe/gkd/ui/SnapshotPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Card
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
Expand All @@ -49,7 +46,6 @@ import com.blankj.utilcode.util.UriUtils
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph
import com.ramcosta.composedestinations.navigation.navigate
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import li.songe.gkd.MainActivity
Expand All @@ -63,7 +59,6 @@ import li.songe.gkd.ui.component.waitResult
import li.songe.gkd.ui.destinations.ImagePreviewPageDestination
import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.util.IMPORT_BASE_URL
import li.songe.gkd.util.LoadStatus
import li.songe.gkd.util.LocalNavController
import li.songe.gkd.util.LocalPickContentLauncher
import li.songe.gkd.util.ProfileTransitions
Expand All @@ -86,7 +81,8 @@ fun SnapshotPage() {

val vm = hiltViewModel<SnapshotVm>()
val snapshots by vm.snapshotsState.collectAsState()
val uploadStatus by vm.uploadStatusFlow.collectAsState()

vm.uploadOptions.ShowDialog()

var selectedSnapshot by remember {
mutableStateOf<Snapshot?>(null)
Expand Down Expand Up @@ -253,9 +249,9 @@ fun SnapshotPage() {
} else {
Text(
text = "生成链接(需科学上网)", modifier = Modifier
.clickable(onClick = {
.clickable(onClick = vm.viewModelScope.launchAsFn(Dispatchers.IO) {
selectedSnapshot = null
vm.uploadZip(snapshotVal)
vm.uploadOptions.startTask(SnapshotExt.getSnapshotZipFile(snapshotVal.id))
})
.then(modifier)
)
Expand Down Expand Up @@ -323,69 +319,6 @@ fun SnapshotPage() {
}
}
}

when (val uploadStatusVal = uploadStatus) {
is LoadStatus.Failure -> {
AlertDialog(
title = { Text(text = "上传失败") },
text = {
Text(text = uploadStatusVal.exception.let {
it.message ?: it.toString()
})
},
onDismissRequest = { vm.uploadStatusFlow.value = null },
confirmButton = {
TextButton(onClick = {
vm.uploadStatusFlow.value = null
}) {
Text(text = "关闭")
}
},
)
}

is LoadStatus.Loading -> {
AlertDialog(
title = { Text(text = "上传文件中") },
text = {
LinearProgressIndicator(
progress = { uploadStatusVal.progress },
)
},
onDismissRequest = { },
confirmButton = {
TextButton(onClick = {
vm.uploadJob?.cancel(CancellationException("终止上传"))
vm.uploadJob = null
}) {
Text(text = "终止上传")
}
},
)
}

is LoadStatus.Success -> {
AlertDialog(title = { Text(text = "上传完成") }, text = {
Text(text = IMPORT_BASE_URL + uploadStatusVal.result.id)
}, onDismissRequest = {}, dismissButton = {
TextButton(onClick = {
vm.uploadStatusFlow.value = null
}) {
Text(text = "关闭")
}
}, confirmButton = {
TextButton(onClick = {
ClipboardUtils.copyText(IMPORT_BASE_URL + uploadStatusVal.result.id)
toast("复制成功")
vm.uploadStatusFlow.value = null
}) {
Text(text = "复制")
}
})
}

else -> {}
}
}


55 changes: 2 additions & 53 deletions app/src/main/kotlin/li/songe/gkd/ui/SnapshotVm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,10 @@ package li.songe.gkd.ui
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import io.ktor.client.call.body
import io.ktor.client.plugins.onUpload
import io.ktor.client.request.forms.formData
import io.ktor.client.request.forms.submitFormWithBinaryData
import io.ktor.client.statement.bodyAsText
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.data.GithubPoliciesAsset
import li.songe.gkd.data.RpcError
import li.songe.gkd.data.Snapshot
import li.songe.gkd.db.DbSet
import li.songe.gkd.debug.SnapshotExt.getSnapshotZipFile
import li.songe.gkd.util.FILE_UPLOAD_URL
import li.songe.gkd.util.LoadStatus
import li.songe.gkd.util.client
import li.songe.gkd.util.launchTry
import li.songe.gkd.ui.component.UploadOptions
import javax.inject.Inject


Expand All @@ -32,40 +15,6 @@ class SnapshotVm @Inject constructor() : ViewModel() {
val snapshotsState = DbSet.snapshotDao.query()
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())

val uploadStatusFlow = MutableStateFlow<LoadStatus<GithubPoliciesAsset>?>(null)
var uploadJob: Job? = null

fun uploadZip(snapshot: Snapshot) {
uploadJob = viewModelScope.launchTry(Dispatchers.IO) {
val zipFile = getSnapshotZipFile(snapshot.id)
uploadStatusFlow.value = LoadStatus.Loading()
try {
val response =
client.submitFormWithBinaryData(url = FILE_UPLOAD_URL, formData = formData {
append("\"file\"", zipFile.readBytes(), Headers.build {
append(HttpHeaders.ContentType, "application/x-zip-compressed")
append(HttpHeaders.ContentDisposition, "filename=\"file.zip\"")
})
}) {
onUpload { bytesSentTotal, contentLength ->
if (uploadStatusFlow.value is LoadStatus.Loading) {
uploadStatusFlow.value =
LoadStatus.Loading(bytesSentTotal / contentLength.toFloat())
}
}
}
if (response.headers["X_RPC_OK"] == "true") {
val policiesAsset = response.body<GithubPoliciesAsset>()
uploadStatusFlow.value = LoadStatus.Success(policiesAsset)
DbSet.snapshotDao.update(snapshot.copy(githubAssetId = policiesAsset.id))
} else if (response.headers["X_RPC_OK"] == "false") {
uploadStatusFlow.value = LoadStatus.Failure(response.body<RpcError>())
} else {
uploadStatusFlow.value = LoadStatus.Failure(Exception(response.bodyAsText()))
}
} catch (e: Exception) {
uploadStatusFlow.value = LoadStatus.Failure(e)
}
}
}
val uploadOptions = UploadOptions(viewModelScope)
}
Loading

0 comments on commit ab8afce

Please sign in to comment.