Revoke a single license by product key (v1.0.2).

Send license.key to the admin revoke API and track revoking state per key.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-07-01 16:44:18 +08:00
parent bf6f347a44
commit 9799bca5e3
5 changed files with 13 additions and 13 deletions
+2 -2
View File
@@ -12,8 +12,8 @@ android {
applicationId = "ru.mailib.ttrpg.licensemanager" applicationId = "ru.mailib.ttrpg.licensemanager"
minSdk = 26 minSdk = 26
targetSdk = 35 targetSdk = 35
versionCode = 2 versionCode = 3
versionName = "1.0.1" versionName = "1.0.2"
} }
buildTypes { buildTypes {
@@ -32,7 +32,7 @@ data class ProductKeyResponse(
) )
data class RevokeLicenseRequest( data class RevokeLicenseRequest(
val sub: String, val key: String,
) )
data class RevokeLicenseResponse( data class RevokeLicenseResponse(
@@ -59,8 +59,8 @@ class LicenseRepository(
createApi(settings).createProductKey(request) createApi(settings).createProductKey(request)
} }
suspend fun revokeLicense(settings: AppSettings, sub: String): Result<Unit> = runCatching { suspend fun revokeLicense(settings: AppSettings, key: String): Result<Unit> = runCatching {
createApi(settings).revokeLicense(RevokeLicenseRequest(sub)) createApi(settings).revokeLicense(RevokeLicenseRequest(key))
} }
private fun createApi(settings: AppSettings): LicenseApi { private fun createApi(settings: AppSettings): LicenseApi {
@@ -22,7 +22,7 @@ import java.time.ZoneOffset
data class LicenseListUiState( data class LicenseListUiState(
val licenses: List<LicenseEntry> = emptyList(), val licenses: List<LicenseEntry> = emptyList(),
val isLoading: Boolean = false, val isLoading: Boolean = false,
val revokingSub: String? = null, val revokingKey: String? = null,
val error: String? = null, val error: String? = null,
) )
@@ -76,18 +76,18 @@ class LicenseViewModel(application: Application) : AndroidViewModel(application)
} }
} }
fun revokeLicense(sub: String) { fun revokeLicense(key: String) {
viewModelScope.launch { viewModelScope.launch {
_listState.update { it.copy(revokingSub = sub, error = null) } _listState.update { it.copy(revokingKey = key, error = null) }
licenseRepository.revokeLicense(currentSettings(), sub) licenseRepository.revokeLicense(currentSettings(), key)
.onSuccess { .onSuccess {
loadLicenses() loadLicenses()
_listState.update { it.copy(revokingSub = null) } _listState.update { it.copy(revokingKey = null) }
} }
.onFailure { e -> .onFailure { e ->
_listState.update { _listState.update {
it.copy( it.copy(
revokingSub = null, revokingKey = null,
error = e.message ?: "Не удалось отозвать лицензию", error = e.message ?: "Не удалось отозвать лицензию",
) )
} }
@@ -63,7 +63,7 @@ fun LicenseListScreen(viewModel: LicenseViewModel) {
confirmButton = { confirmButton = {
TextButton( TextButton(
onClick = { onClick = {
viewModel.revokeLicense(license.sub) viewModel.revokeLicense(license.key)
confirmRevoke = null confirmRevoke = null
}, },
) { ) {
@@ -116,7 +116,7 @@ fun LicenseListScreen(viewModel: LicenseViewModel) {
items(state.licenses, key = { it.key }) { license -> items(state.licenses, key = { it.key }) { license ->
LicenseCard( LicenseCard(
license = license, license = license,
isRevoking = state.revokingSub == license.sub, isRevoking = state.revokingKey == license.key,
onRevoke = { confirmRevoke = license }, onRevoke = { confirmRevoke = license },
) )
} }