From fb64343a9f89086c7207ba4c2aea7326cd878a6e Mon Sep 17 00:00:00 2001 From: Shuming Liu Date: Tue, 8 Sep 2026 11:25:03 +0800 Subject: [PATCH] add delete function --- .../cn/learningpad/oraltrainer/sdk/UserApi.kt | 16 +++ .../oraltrainer/sample/ui/MineScreen.kt | 103 +++++++++++++++++- 2 files changed, 113 insertions(+), 6 deletions(-) diff --git a/android/oral-trainer-sdk/src/main/java/cn/learningpad/oraltrainer/sdk/UserApi.kt b/android/oral-trainer-sdk/src/main/java/cn/learningpad/oraltrainer/sdk/UserApi.kt index 9694645..a991b06 100644 --- a/android/oral-trainer-sdk/src/main/java/cn/learningpad/oraltrainer/sdk/UserApi.kt +++ b/android/oral-trainer-sdk/src/main/java/cn/learningpad/oraltrainer/sdk/UserApi.kt @@ -165,6 +165,22 @@ class UserApi internal constructor( onComplete: (Result>) -> Unit, ): CancellableRequest = submitObject(onComplete, token) { parseDubShares(getBlocking(it, "api/v1/me/dub-shares")) } + fun deleteResult( + token: String, + attemptId: String, + onComplete: (Result) -> Unit, + ): CancellableRequest = submitUnit(onComplete, token) { + request("api/v1/me/results/$attemptId", token, method = "DELETE") + } + + fun deleteDubShare( + token: String, + shareId: String, + onComplete: (Result) -> Unit, + ): CancellableRequest = submitUnit(onComplete, token) { + request("api/v1/me/dub-shares/$shareId", token, method = "DELETE") + } + fun dubShareDetail( shareId: String, onComplete: (Result) -> Unit, diff --git a/android/sample-app/src/main/java/cn/learningpad/oraltrainer/sample/ui/MineScreen.kt b/android/sample-app/src/main/java/cn/learningpad/oraltrainer/sample/ui/MineScreen.kt index 02fe48e..4647ff9 100644 --- a/android/sample-app/src/main/java/cn/learningpad/oraltrainer/sample/ui/MineScreen.kt +++ b/android/sample-app/src/main/java/cn/learningpad/oraltrainer/sample/ui/MineScreen.kt @@ -3,12 +3,14 @@ package cn.learningpad.oraltrainer.sample.ui import android.app.Activity import android.graphics.Color import android.graphics.Typeface +import android.view.Gravity import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.LinearLayout import android.widget.ScrollView import android.widget.TextView +import android.widget.Toast import cn.learningpad.oraltrainer.sample.MineScreenActions import cn.learningpad.oraltrainer.sample.SampleBindings import cn.learningpad.oraltrainer.sample.SampleTheme @@ -25,6 +27,8 @@ internal class MineScreen( ) : UiStyled { override val uiContext get() = activity + private val deletingHistoryIds = mutableSetOf() + fun createSection(): View { bindings.myContentList = LinearLayout(activity).apply { orientation = LinearLayout.VERTICAL @@ -79,10 +83,13 @@ internal class MineScreen( filtered.forEach { row -> val passedLabel = if (row.passed) "通过" else "未通过" list.addView( - widgets.infoCard( - "第 ${row.sentenceIndex + 1} 句" + "\n" + + historyCard( + text = "第 ${row.sentenceIndex + 1} 句" + "\n" + "得分 ${row.overallScore.toInt()} · $passedLabel", - ), + id = row.attemptId, + ) { + deleteResult(userApi, token, row.attemptId) + }, ) } }, @@ -99,10 +106,13 @@ internal class MineScreen( } filtered.forEach { row -> list.addView( - widgets.infoCard( - "${row.title}" + "\n" + + historyCard( + text = "${row.title}" + "\n" + "${row.segmentCount} 句 · 平均 ${row.averageScore.toInt()} 分", - ), + id = row.shareId, + ) { + deleteDubShare(userApi, token, row.shareId) + }, ) } }, @@ -115,6 +125,87 @@ internal class MineScreen( } } + private fun deleteResult(userApi: UserApi, token: String, attemptId: String) { + userApi.deleteResult(token, attemptId) { result -> + result.fold( + onSuccess = { + Toast.makeText(activity, "测试记录已删除", Toast.LENGTH_SHORT).show() + refreshContent(userApi, token) + }, + onFailure = { + deletingHistoryIds.remove(attemptId) + Toast.makeText(activity, "删除失败:${it.message}", Toast.LENGTH_SHORT).show() + refreshContent(userApi, token) + }, + ) + } + } + + private fun deleteDubShare(userApi: UserApi, token: String, shareId: String) { + userApi.deleteDubShare(token, shareId) { result -> + result.fold( + onSuccess = { + Toast.makeText(activity, "配音分享已删除", Toast.LENGTH_SHORT).show() + refreshContent(userApi, token) + }, + onFailure = { + deletingHistoryIds.remove(shareId) + Toast.makeText(activity, "删除失败:${it.message}", Toast.LENGTH_SHORT).show() + refreshContent(userApi, token) + }, + ) + } + } + + private fun historyCard( + text: String, + id: String, + onDelete: () -> Unit, + ): View { + val isDeleting = id in deletingHistoryIds + return LinearLayout(activity).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER_VERTICAL + background = rounded(SampleTheme.selected, 8f) + setPadding(12.dp, 10.dp, 10.dp, 10.dp) + layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + ).withMargins(0, 0, 0, 8.dp) + + addView(TextView(activity).apply { + this.text = text + setTextColor(SampleTheme.textDark) + textSize = 13f + layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f) + }) + addView(Button(activity).apply { + setText(if (isDeleting) "删除中..." else "删除") + isAllCaps = false + isEnabled = !isDeleting + setTextColor(Color.WHITE) + textSize = 12f + typeface = Typeface.DEFAULT_BOLD + minWidth = 0 + minHeight = 0 + minimumWidth = 0 + minimumHeight = 0 + setPadding(10.dp, 0, 10.dp, 0) + background = rounded(SampleTheme.danger, 8f) + layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + 32.dp, + ).withMargins(8.dp, 0, 0, 0) + setOnClickListener { + if (!deletingHistoryIds.add(id)) return@setOnClickListener + setText("删除中...") + isEnabled = false + onDelete() + } + }) + } + } + private fun courseHeading(title: String): TextView = TextView(activity).apply { text = "当前课程:$title"