feat: 贴页面错误提示

This commit is contained in:
HuanCheng65 2023-07-17 13:31:17 +08:00
parent 2f1ab3b038
commit 67052d4a91
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
9 changed files with 3778 additions and 3647 deletions

View File

@ -4,4 +4,8 @@ import com.huanchengfly.tieba.post.api.Error.ERROR_NETWORK
class NoConnectivityException( class NoConnectivityException(
msg: String = "No internet!" msg: String = "No internet!"
) : TiebaLocalException(ERROR_NETWORK, msg) ) : TiebaLocalException(ERROR_NETWORK, msg) {
override fun toString(): String {
return "NoConnectivityException(message=$message)"
}
}

View File

@ -4,7 +4,11 @@ import com.huanchengfly.tieba.post.api.models.CommonResponse
class TiebaApiException( class TiebaApiException(
private val commonResponse: CommonResponse private val commonResponse: CommonResponse
) : TiebaException(commonResponse.errorMsg?.takeIf { it.isNotEmpty() } ?: "未知错误") { ) : TiebaException(commonResponse.errorMsg.takeIf { it.isNotEmpty() } ?: "未知错误") {
override val code: Int override val code: Int
get() = commonResponse.errorCode ?: -1 get() = commonResponse.errorCode
override fun toString(): String {
return "TiebaApiException(code=$code, message=$message, commonResponse=$commonResponse)"
}
} }

View File

@ -4,4 +4,13 @@ import java.io.IOException
abstract class TiebaException(message: String) : IOException(message) { abstract class TiebaException(message: String) : IOException(message) {
abstract val code: Int abstract val code: Int
override fun toString(): String {
return "TiebaException(code=$code, message=$message)"
}
}
object TiebaUnknownException : TiebaException("未知错误") {
override val code: Int
get() = -1
} }

View File

@ -3,4 +3,8 @@ package com.huanchengfly.tieba.post.api.retrofit.exception
open class TiebaLocalException( open class TiebaLocalException(
override val code: Int, override val code: Int,
msg: String msg: String
) : TiebaException(msg) ) : TiebaException(msg) {
override fun toString(): String {
return "TiebaLocalException(code=$code, message=$message)"
}
}

View File

@ -4,4 +4,8 @@ import com.huanchengfly.tieba.post.api.Error.ERROR_NOT_LOGGED_IN
class TiebaNotLoggedInException( class TiebaNotLoggedInException(
msg: String = "Not logged in!" msg: String = "Not logged in!"
) : TiebaLocalException(ERROR_NOT_LOGGED_IN, msg) ) : TiebaLocalException(ERROR_NOT_LOGGED_IN, msg) {
override fun toString(): String {
return "TiebaNotLoggedInException(message=$message)"
}
}

View File

@ -120,6 +120,7 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.BackNavigationIcon
import com.huanchengfly.tieba.post.ui.widgets.compose.Button import com.huanchengfly.tieba.post.ui.widgets.compose.Button
import com.huanchengfly.tieba.post.ui.widgets.compose.Card import com.huanchengfly.tieba.post.ui.widgets.compose.Card
import com.huanchengfly.tieba.post.ui.widgets.compose.ConfirmDialog import com.huanchengfly.tieba.post.ui.widgets.compose.ConfirmDialog
import com.huanchengfly.tieba.post.ui.widgets.compose.ErrorScreen
import com.huanchengfly.tieba.post.ui.widgets.compose.HorizontalDivider import com.huanchengfly.tieba.post.ui.widgets.compose.HorizontalDivider
import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad
import com.huanchengfly.tieba.post.ui.widgets.compose.ListMenuItem import com.huanchengfly.tieba.post.ui.widgets.compose.ListMenuItem
@ -457,6 +458,14 @@ fun ThreadPage(
prop1 = ThreadUiState::isLoadingMore, prop1 = ThreadUiState::isLoadingMore,
initial = false initial = false
) )
val isError by viewModel.uiState.collectPartialAsState(
prop1 = ThreadUiState::isError,
initial = false
)
val error by viewModel.uiState.collectPartialAsState(
prop1 = ThreadUiState::error,
initial = null
)
val hasMore by viewModel.uiState.collectPartialAsState( val hasMore by viewModel.uiState.collectPartialAsState(
prop1 = ThreadUiState::hasMore, prop1 = ThreadUiState::hasMore,
initial = true initial = true
@ -469,10 +478,6 @@ fun ThreadPage(
prop1 = ThreadUiState::hasPrevious, prop1 = ThreadUiState::hasPrevious,
initial = true initial = true
) )
val currentPageMin by viewModel.uiState.collectPartialAsState(
prop1 = ThreadUiState::currentPageMin,
initial = 0
)
val currentPageMax by viewModel.uiState.collectPartialAsState( val currentPageMax by viewModel.uiState.collectPartialAsState(
prop1 = ThreadUiState::currentPageMax, prop1 = ThreadUiState::currentPageMax,
initial = 0 initial = 0
@ -707,8 +712,14 @@ fun ThreadPage(
ProvideNavigator(navigator = navigator) { ProvideNavigator(navigator = navigator) {
StateScreen( StateScreen(
isEmpty = isEmpty, isEmpty = isEmpty,
isError = false, isError = isError,
isLoading = isRefreshing, isLoading = isRefreshing,
errorScreen = {
error?.let {
val (e) = it
ErrorScreen(error = e)
}
},
onReload = { onReload = {
viewModel.send( viewModel.send(
ThreadUiIntent.Load( ThreadUiIntent.Load(

View File

@ -11,6 +11,7 @@ import com.huanchengfly.tieba.post.api.models.protos.SimpleForum
import com.huanchengfly.tieba.post.api.models.protos.ThreadInfo import com.huanchengfly.tieba.post.api.models.protos.ThreadInfo
import com.huanchengfly.tieba.post.api.models.protos.User import com.huanchengfly.tieba.post.api.models.protos.User
import com.huanchengfly.tieba.post.api.renders import com.huanchengfly.tieba.post.api.renders
import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaUnknownException
import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorCode import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorCode
import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorMessage import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorMessage
import com.huanchengfly.tieba.post.api.updateAgreeStatus import com.huanchengfly.tieba.post.api.updateAgreeStatus
@ -108,7 +109,7 @@ class ThreadViewModel @Inject constructor() :
fun ThreadUiIntent.Init.producePartialChange(): Flow<ThreadPartialChange.Init> = fun ThreadUiIntent.Init.producePartialChange(): Flow<ThreadPartialChange.Init> =
flowOf<ThreadPartialChange.Init>( flowOf<ThreadPartialChange.Init>(
ThreadPartialChange.Init.Success( ThreadPartialChange.Init.Success(
threadInfo?.title ?: "", threadInfo?.title.orEmpty(),
threadInfo?.author, threadInfo?.author,
threadInfo, threadInfo,
threadInfo?.firstPostContent?.renders ?: emptyList(), threadInfo?.firstPostContent?.renders ?: emptyList(),
@ -116,18 +117,14 @@ class ThreadViewModel @Inject constructor() :
seeLz, seeLz,
sortType, sortType,
) )
).catch { ).catch { emit(ThreadPartialChange.Init.Failure(it)) }
emit(
ThreadPartialChange.Init.Failure(
it.getErrorCode(),
it.getErrorMessage()
)
)
}
fun ThreadUiIntent.Load.producePartialChange(): Flow<ThreadPartialChange.Load> = fun ThreadUiIntent.Load.producePartialChange(): Flow<ThreadPartialChange.Load> =
PbPageRepository PbPageRepository
.pbPage(threadId, page, postId, forumId, seeLz, sortType, from = from) .pbPage(
threadId, page, postId, forumId, seeLz, sortType,
from = from.takeIf { it == ThreadPageFrom.FROM_STORE }.orEmpty()
)
.map { response -> .map { response ->
if ( if (
response.data_?.page != null response.data_?.page != null
@ -170,17 +167,10 @@ class ThreadViewModel @Inject constructor() :
seeLz, seeLz,
sortType, sortType,
) )
} else ThreadPartialChange.Load.Failure(-1, "未知错误") } else ThreadPartialChange.Load.Failure(TiebaUnknownException)
} }
.onStart { emit(ThreadPartialChange.Load.Start) } .onStart { emit(ThreadPartialChange.Load.Start) }
.catch { .catch { emit(ThreadPartialChange.Load.Failure(it)) }
emit(
ThreadPartialChange.Load.Failure(
it.getErrorCode(),
it.getErrorMessage()
)
)
}
fun ThreadUiIntent.LoadFirstPage.producePartialChange(): Flow<ThreadPartialChange.LoadFirstPage> = fun ThreadUiIntent.LoadFirstPage.producePartialChange(): Flow<ThreadPartialChange.LoadFirstPage> =
PbPageRepository PbPageRepository
@ -220,17 +210,10 @@ class ThreadViewModel @Inject constructor() :
seeLz, seeLz,
sortType, sortType,
) )
} else ThreadPartialChange.LoadFirstPage.Failure(-1, "未知错误") } else ThreadPartialChange.LoadFirstPage.Failure(TiebaUnknownException)
} }
.onStart { emit(ThreadPartialChange.LoadFirstPage.Start) } .onStart { emit(ThreadPartialChange.LoadFirstPage.Start) }
.catch { .catch { emit(ThreadPartialChange.LoadFirstPage.Failure(it)) }
emit(
ThreadPartialChange.LoadFirstPage.Failure(
it.getErrorCode(),
it.getErrorMessage()
)
)
}
fun ThreadUiIntent.LoadMore.producePartialChange(): Flow<ThreadPartialChange.LoadMore> = fun ThreadUiIntent.LoadMore.producePartialChange(): Flow<ThreadPartialChange.LoadMore> =
PbPageRepository PbPageRepository
@ -488,6 +471,8 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
override fun reduce(oldState: ThreadUiState): ThreadUiState = when (this) { override fun reduce(oldState: ThreadUiState): ThreadUiState = when (this) {
is Success -> oldState.copy( is Success -> oldState.copy(
isRefreshing = true, isRefreshing = true,
isError = false,
error = null,
title = title, title = title,
author = if (author != null) wrapImmutable(author) else null, author = if (author != null) wrapImmutable(author) else null,
threadInfo = threadInfo?.wrapImmutable(), threadInfo = threadInfo?.wrapImmutable(),
@ -506,7 +491,10 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
sortType = sortType, sortType = sortType,
) )
is Failure -> oldState is Failure -> oldState.copy(
isError = true,
error = error.wrapImmutable()
)
} }
data class Success( data class Success(
@ -520,8 +508,7 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
) : Init() ) : Init()
data class Failure( data class Failure(
val errorCode: Int, val error: Throwable
val errorMessage: String
) : Init() ) : Init()
} }
@ -531,6 +518,8 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
is Success -> oldState.copy( is Success -> oldState.copy(
isRefreshing = false, isRefreshing = false,
isError = false,
error = null,
title = title, title = title,
author = wrapImmutable(author), author = wrapImmutable(author),
user = wrapImmutable(user), user = wrapImmutable(user),
@ -553,7 +542,11 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
sortType = sortType, sortType = sortType,
) )
is Failure -> oldState.copy(isRefreshing = false) is Failure -> oldState.copy(
isRefreshing = false,
isError = true,
error = error.wrapImmutable()
)
} }
object Start : Load() object Start : Load()
@ -580,8 +573,7 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
) : Load() ) : Load()
data class Failure( data class Failure(
val errorCode: Int, val error: Throwable,
val errorMessage: String
) : Load() ) : Load()
} }
@ -590,6 +582,8 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
is Start -> oldState.copy(isRefreshing = true) is Start -> oldState.copy(isRefreshing = true)
is Success -> oldState.copy( is Success -> oldState.copy(
isRefreshing = false, isRefreshing = false,
isError = false,
error = null,
title = title, title = title,
author = wrapImmutable(author), author = wrapImmutable(author),
data = data.toImmutableList(), data = data.toImmutableList(),
@ -607,7 +601,11 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
sortType = sortType, sortType = sortType,
) )
is Failure -> oldState.copy(isRefreshing = false) is Failure -> oldState.copy(
isRefreshing = false,
isError = true,
error = error.wrapImmutable(),
)
} }
object Start : LoadFirstPage() object Start : LoadFirstPage()
@ -630,8 +628,7 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
) : LoadFirstPage() ) : LoadFirstPage()
data class Failure( data class Failure(
val errorCode: Int, val error: Throwable
val errorMessage: String
) : LoadFirstPage() ) : LoadFirstPage()
} }
@ -866,6 +863,8 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
data class ThreadUiState( data class ThreadUiState(
val isRefreshing: Boolean = false, val isRefreshing: Boolean = false,
val isLoadingMore: Boolean = false, val isLoadingMore: Boolean = false,
val isError: Boolean = false,
val error: ImmutableHolder<Throwable>? = null,
val hasMore: Boolean = true, val hasMore: Boolean = true,
val nextPagePostId: Long = 0, val nextPagePostId: Long = 0,

File diff suppressed because it is too large Load Diff

View File

@ -653,7 +653,7 @@
<string name="no_internet_connectivity">无互联网连接</string> <string name="no_internet_connectivity">无互联网连接</string>
<string name="connectivity_timeout">连接超时</string> <string name="connectivity_timeout">连接超时</string>
<string name="title_no_internet_connectivity">网络找不到了</string> <string name="title_no_internet_connectivity">网络找不到了</string>
<string name="title_api_error">服务器有一些自己的想法</string> <string name="title_api_error">啊哦,出错了</string>
<string name="title_unknown_error">发生了一个奇怪的错误…</string> <string name="title_unknown_error">发生了一个奇怪的错误…</string>
<string name="message_no_internet_connectivity">%s。请检查你的网络连接是否正常</string> <string name="message_no_internet_connectivity">%s。请检查你的网络连接是否正常</string>
<string name="message_unknown_error">哦我的老伙计,我向你保证这真的是一个奇怪的错误……</string> <string name="message_unknown_error">哦我的老伙计,我向你保证这真的是一个奇怪的错误……</string>