mirror of
https://github.com/gkd-kit/gkd.git
synced 2024-11-16 11:42:22 +08:00
perf: upload github file link
This commit is contained in:
parent
c07d29e876
commit
53a035bcd9
|
@ -44,6 +44,7 @@ import li.songe.gkd.service.fixRestartService
|
|||
import li.songe.gkd.service.updateLauncherAppId
|
||||
import li.songe.gkd.ui.component.BuildDialog
|
||||
import li.songe.gkd.ui.theme.AppTheme
|
||||
import li.songe.gkd.util.EditGithubCookieDlg
|
||||
import li.songe.gkd.util.LocalNavController
|
||||
import li.songe.gkd.util.UpgradeDialog
|
||||
import li.songe.gkd.util.appInfoCacheFlow
|
||||
|
@ -93,6 +94,8 @@ class MainActivity : ComponentActivity() {
|
|||
ShizukuErrorDialog(mainVm.shizukuErrorFlow)
|
||||
AuthDialog(mainVm.authReasonFlow)
|
||||
BuildDialog(mainVm.dialogFlow)
|
||||
mainVm.uploadOptions.ShowDialog()
|
||||
EditGithubCookieDlg(mainVm.showEditCookieDlgFlow)
|
||||
if (META.updateEnabled) {
|
||||
UpgradeDialog(mainVm.updateStatus)
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import li.songe.gkd.data.SubsItem
|
|||
import li.songe.gkd.db.DbSet
|
||||
import li.songe.gkd.permission.AuthReason
|
||||
import li.songe.gkd.ui.component.AlertDialogOptions
|
||||
import li.songe.gkd.ui.component.UploadOptions
|
||||
import li.songe.gkd.util.LOCAL_SUBS_ID
|
||||
import li.songe.gkd.util.UpdateStatus
|
||||
import li.songe.gkd.util.checkUpdate
|
||||
|
@ -43,6 +44,10 @@ class MainViewModel : ViewModel() {
|
|||
|
||||
val shizukuErrorFlow = MutableStateFlow(false)
|
||||
|
||||
val uploadOptions = UploadOptions(this)
|
||||
|
||||
val showEditCookieDlgFlow = MutableStateFlow(false)
|
||||
|
||||
init {
|
||||
viewModelScope.launchTry(Dispatchers.IO) {
|
||||
val subsItems = DbSet.subsItemDao.queryAll()
|
||||
|
|
|
@ -48,7 +48,6 @@ import androidx.compose.ui.text.style.TextDecoration
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -88,10 +87,8 @@ import li.songe.gkd.util.toast
|
|||
fun AboutPage() {
|
||||
val navController = LocalNavController.current
|
||||
val context = LocalContext.current as MainActivity
|
||||
val vm = viewModel<AboutVm>()
|
||||
val store by storeFlow.collectAsState()
|
||||
|
||||
vm.uploadOptions.ShowDialog()
|
||||
var showInfoDlg by remember { mutableStateOf(false) }
|
||||
if (showInfoDlg) {
|
||||
AlertDialog(
|
||||
|
@ -176,7 +173,9 @@ fun AboutPage() {
|
|||
modifier = Modifier
|
||||
.clickable(onClick = throttle {
|
||||
showShareLogDlg = false
|
||||
vm.uploadOptions.startTask(getFile = { buildLogFile() })
|
||||
context.mainVm.uploadOptions.startTask(
|
||||
getFile = { buildLogFile() }
|
||||
)
|
||||
})
|
||||
.then(modifier)
|
||||
)
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
package li.songe.gkd.ui
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import li.songe.gkd.ui.component.UploadOptions
|
||||
|
||||
class AboutVm : ViewModel() {
|
||||
val uploadOptions = UploadOptions(viewModelScope)
|
||||
}
|
|
@ -5,7 +5,6 @@ import android.content.Context
|
|||
import android.media.projection.MediaProjectionManager
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
|
@ -19,7 +18,6 @@ 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.automirrored.outlined.HelpOutline
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Icon
|
||||
|
@ -58,7 +56,6 @@ import com.ramcosta.composedestinations.generated.destinations.ActivityLogPageDe
|
|||
import com.ramcosta.composedestinations.generated.destinations.SnapshotPageDestination
|
||||
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.update
|
||||
import li.songe.gkd.MainActivity
|
||||
import li.songe.gkd.appScope
|
||||
import li.songe.gkd.debug.FloatingService
|
||||
|
@ -81,7 +78,6 @@ import li.songe.gkd.util.LocalNavController
|
|||
import li.songe.gkd.util.ProfileTransitions
|
||||
import li.songe.gkd.util.launchAsFn
|
||||
import li.songe.gkd.util.openUri
|
||||
import li.songe.gkd.util.privacyStoreFlow
|
||||
import li.songe.gkd.util.storeFlow
|
||||
import li.songe.gkd.util.throttle
|
||||
import li.songe.gkd.util.toast
|
||||
|
@ -155,62 +151,6 @@ fun AdvancedPage() {
|
|||
})
|
||||
}
|
||||
|
||||
var showEditCookieDlg by remember { mutableStateOf(false) }
|
||||
if (showEditCookieDlg) {
|
||||
val privacyStore by privacyStoreFlow.collectAsState()
|
||||
var value by remember {
|
||||
mutableStateOf(privacyStore.githubCookie ?: "")
|
||||
}
|
||||
AlertDialog(
|
||||
onDismissRequest = {
|
||||
if (value.isEmpty()) {
|
||||
showEditCookieDlg = false
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text(text = "Github Cookie")
|
||||
IconButton(onClick = throttle {
|
||||
context.openUri("https://gkd.li/?r=1")
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Outlined.HelpOutline,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
text = {
|
||||
OutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = {
|
||||
value = it.filter { c -> c != '\n' && c != '\r' }
|
||||
},
|
||||
placeholder = { Text(text = "请输入 Github Cookie") },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
maxLines = 10,
|
||||
)
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
showEditCookieDlg = false
|
||||
privacyStoreFlow.update { it.copy(githubCookie = value.trim()) }
|
||||
}) {
|
||||
Text(text = "确认")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showEditCookieDlg = false }) {
|
||||
Text(text = "取消")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
||||
Scaffold(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
|
@ -454,7 +394,7 @@ fun AdvancedPage() {
|
|||
},
|
||||
imageVector = Icons.Default.Edit,
|
||||
onClick = {
|
||||
showEditCookieDlg = true
|
||||
context.mainVm.showEditCookieDlgFlow.value = true
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -79,8 +79,6 @@ fun SnapshotPage() {
|
|||
val vm = viewModel<SnapshotVm>()
|
||||
val snapshots by vm.snapshotsState.collectAsState()
|
||||
|
||||
vm.uploadOptions.ShowDialog()
|
||||
|
||||
var selectedSnapshot by remember {
|
||||
mutableStateOf<Snapshot?>(null)
|
||||
}
|
||||
|
@ -246,8 +244,9 @@ fun SnapshotPage() {
|
|||
text = "生成链接(需科学上网)", modifier = Modifier
|
||||
.clickable(onClick = throttle {
|
||||
selectedSnapshot = null
|
||||
vm.uploadOptions.startTask(
|
||||
context.mainVm.uploadOptions.startTask(
|
||||
getFile = { SnapshotExt.getSnapshotZipFile(snapshotVal.id) },
|
||||
showHref = { IMPORT_SHORT_URL + it.id },
|
||||
onSuccessResult = vm.viewModelScope.launchAsFn<GithubPoliciesAsset>(
|
||||
Dispatchers.IO
|
||||
) {
|
||||
|
|
|
@ -5,15 +5,8 @@ import androidx.lifecycle.viewModelScope
|
|||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import li.songe.gkd.db.DbSet
|
||||
import li.songe.gkd.ui.component.UploadOptions
|
||||
import li.songe.gkd.util.IMPORT_SHORT_URL
|
||||
|
||||
class SnapshotVm : ViewModel() {
|
||||
val snapshotsState = DbSet.snapshotDao.query()
|
||||
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
val uploadOptions = UploadOptions(
|
||||
scope = viewModelScope,
|
||||
showHref = { IMPORT_SHORT_URL + it.id }
|
||||
)
|
||||
}
|
|
@ -6,13 +6,15 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.blankj.utilcode.util.ClipboardUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import li.songe.gkd.MainViewModel
|
||||
import li.songe.gkd.data.GithubPoliciesAsset
|
||||
import li.songe.gkd.util.GithubCookieException
|
||||
import li.songe.gkd.util.LoadStatus
|
||||
import li.songe.gkd.util.launchTry
|
||||
import li.songe.gkd.util.privacyStoreFlow
|
||||
|
@ -21,8 +23,7 @@ import li.songe.gkd.util.uploadFileToGithub
|
|||
import java.io.File
|
||||
|
||||
class UploadOptions(
|
||||
private val scope: CoroutineScope,
|
||||
private val showHref: (GithubPoliciesAsset) -> String = { it.shortHref }
|
||||
private val mainVm: MainViewModel,
|
||||
) {
|
||||
private val statusFlow = MutableStateFlow<LoadStatus<GithubPoliciesAsset>?>(null)
|
||||
private var job: Job? = null
|
||||
|
@ -30,7 +31,7 @@ class UploadOptions(
|
|||
cookie: String,
|
||||
getFile: suspend () -> File,
|
||||
onSuccessResult: ((GithubPoliciesAsset) -> Unit)?
|
||||
) = scope.launchTry(Dispatchers.IO) {
|
||||
) = mainVm.viewModelScope.launchTry(Dispatchers.IO) {
|
||||
statusFlow.value = LoadStatus.Loading()
|
||||
try {
|
||||
val policiesAsset = uploadFileToGithub(cookie, getFile()) {
|
||||
|
@ -47,18 +48,23 @@ class UploadOptions(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private var showHref: (GithubPoliciesAsset) -> String = { it.shortHref }
|
||||
fun startTask(
|
||||
getFile: suspend () -> File,
|
||||
showHref: (GithubPoliciesAsset) -> String = { it.shortHref },
|
||||
onSuccessResult: ((GithubPoliciesAsset) -> Unit)? = null
|
||||
) {
|
||||
val cookie = privacyStoreFlow.value.githubCookie
|
||||
if (cookie.isNullOrBlank()) {
|
||||
toast("请先设置 cookie 后再上传")
|
||||
mainVm.showEditCookieDlgFlow.value = true
|
||||
return
|
||||
}
|
||||
if (job != null || statusFlow.value is LoadStatus.Loading) {
|
||||
return
|
||||
}
|
||||
this.showHref = showHref
|
||||
job = buildTask(cookie, getFile, onSuccessResult)
|
||||
}
|
||||
|
||||
|
@ -123,6 +129,16 @@ class UploadOptions(
|
|||
})
|
||||
},
|
||||
onDismissRequest = { statusFlow.value = null },
|
||||
dismissButton = if (status.exception is GithubCookieException) ({
|
||||
TextButton(onClick = {
|
||||
statusFlow.value = null
|
||||
mainVm.showEditCookieDlgFlow.value = true
|
||||
}) {
|
||||
Text(text = "更换 Cookie")
|
||||
}
|
||||
}) else {
|
||||
null
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
statusFlow.value = null
|
||||
|
|
|
@ -1,5 +1,24 @@
|
|||
package li.songe.gkd.util
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.plugins.onUpload
|
||||
import io.ktor.client.request.forms.MultiPartFormDataContent
|
||||
|
@ -13,7 +32,10 @@ import io.ktor.client.statement.bodyAsText
|
|||
import io.ktor.http.Headers
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.HttpMessageBuilder
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.serialization.Serializable
|
||||
import li.songe.gkd.app
|
||||
import li.songe.gkd.data.GithubPoliciesAsset
|
||||
import java.io.File
|
||||
|
||||
|
@ -50,12 +72,14 @@ private data class Authenticity(
|
|||
val authenticityToken: String,
|
||||
)
|
||||
|
||||
data class GithubCookieException(override val message: String) : Exception(message)
|
||||
|
||||
private suspend fun getAuthenticity(cookie: String): Authenticity {
|
||||
val text = client.get(GITHUB_UPLOAD_URL) {
|
||||
setCommonHeaders(cookie)
|
||||
}.bodyAsText()
|
||||
if (!text.contains("data-login")) {
|
||||
error("用户未登录, 请更换 cookie")
|
||||
throw GithubCookieException("未检测到用户登录, 请更换 cookie")
|
||||
}
|
||||
val repositoryId =
|
||||
repositoryIdRegex.find(text)?.groupValues?.get(1) ?: error("repositoryId not found")
|
||||
|
@ -114,3 +138,62 @@ suspend fun uploadFileToGithub(
|
|||
return policiesResp.asset
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EditGithubCookieDlg(showEditCookieDlgFlow: MutableStateFlow<Boolean>) {
|
||||
val showEditCookieDlg by showEditCookieDlgFlow.collectAsState()
|
||||
if (showEditCookieDlg) {
|
||||
val privacyStore by privacyStoreFlow.collectAsState()
|
||||
var value by remember {
|
||||
mutableStateOf(privacyStore.githubCookie ?: "")
|
||||
}
|
||||
AlertDialog(
|
||||
onDismissRequest = {
|
||||
if (value.isEmpty()) {
|
||||
showEditCookieDlgFlow.value = false
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text(text = "Github Cookie")
|
||||
IconButton(onClick = throttle {
|
||||
app.openUri("https://gkd.li/?r=1")
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Outlined.HelpOutline,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
text = {
|
||||
OutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = {
|
||||
value = it.filter { c -> c != '\n' && c != '\r' }
|
||||
},
|
||||
placeholder = { Text(text = "请输入 Github Cookie") },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
maxLines = 10,
|
||||
)
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
showEditCookieDlgFlow.value = false
|
||||
privacyStoreFlow.update { it.copy(githubCookie = value.trim()) }
|
||||
}) {
|
||||
Text(text = "确认")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showEditCookieDlgFlow.value = false }) {
|
||||
Text(text = "取消")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user