Skip to content

Commit

Permalink
fix ip reader, fix extract
Browse files Browse the repository at this point in the history
  • Loading branch information
storytellerF committed Dec 25, 2024
1 parent 7b1940f commit 7fca344
Show file tree
Hide file tree
Showing 25 changed files with 287 additions and 218 deletions.
9 changes: 5 additions & 4 deletions backend/src/main/kotlin/com/storyteller_f/tables/Reactions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,23 @@ suspend fun getReaction(uid: PrimaryKey, objectId: PrimaryKey, emojiText: String
}
}

suspend fun getSingleReaction(uid: PrimaryKey, emoji: String): Result<SingleReactionInfo?> {
suspend fun getSingleReaction(uid: PrimaryKey, emoji: String, objectId: PrimaryKey): Result<SingleReactionInfo?> {
return DatabaseFactory.first({
SingleReactionInfo(id, emoji, objectId, objectType, createdTime, uid)
}, {
Reaction.wrapRow(it)
}) {
Reactions.selectAll().where {
(Reactions.emoji eq emoji) and (Reactions.uid eq uid)
(Reactions.objectId eq objectId) and (Reactions.uid eq uid) and (Reactions.emoji eq emoji)
}
}
}

suspend fun deleteReaction(
uid: PrimaryKey,
emoji: String
): Result<Boolean> = getSingleReaction(uid, emoji).mapResult {
emoji: String,
objectId: PrimaryKey
): Result<Boolean> = getSingleReaction(uid, emoji, objectId).mapResult {
if (it == null) {
Result.success(true)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ suspend fun HttpClient.getRoomTopics(
) = serviceCatching {
get("rooms/$roomId/topics") {
url {
if (isAlreadyLogin()) {
parameters.append("fillHasCommented", "true")
}
appendPagingQueryParams(size, nextTopicId)
}
}.body<ServerResponse<TopicInfo>>()
Expand Down Expand Up @@ -171,20 +174,15 @@ private fun URLBuilder.appendPagingQueryParams(size: Int, nextId: PrimaryKey?) {
}
}

private fun URLBuilder.appendPagingQueryParams(size: Int, nextId: String?) {
parameters.append("size", size.toString())
if (nextId != null) {
parameters.append("nextPageToken", nextId)
}
}

suspend fun HttpClient.getWorldTopics(nextTopicId: PrimaryKey?, size: Int, fillHasCommented: Boolean) =
suspend fun HttpClient.getWorldTopics(nextTopicId: PrimaryKey?, size: Int) =
serviceCatching {
get(
"topics/recommend"
) {
url {
parameters.append("fillHasCommented", fillHasCommented.toString())
if (isAlreadyLogin()) {
parameters.append("fillHasCommented", "true")
}
appendPagingQueryParams(size, nextTopicId)
}
}.body<ServerResponse<TopicInfo>>()
Expand Down Expand Up @@ -213,6 +211,9 @@ suspend fun HttpClient.getTopicTopics(topicId: PrimaryKey, nextTopicId: PrimaryK
serviceCatching {
get("topics/$topicId/topics") {
url {
if (isAlreadyLogin()) {
parameters.append("fillHasCommented", "true")
}
appendPagingQueryParams(size, nextTopicId)
}
}.body<ServerResponse<TopicInfo>>()
Expand Down Expand Up @@ -331,10 +332,10 @@ suspend fun HttpClient.addReaction(topicId: PrimaryKey, emoji: String) = service
}.body<ReactionInfo>()
}

suspend fun HttpClient.deleteReaction(emoji: String) = serviceCatching {
suspend fun HttpClient.deleteReaction(emoji: String, objectId: PrimaryKey) = serviceCatching {
post("reactions/delete") {
contentType(ContentType.Application.Json)
setBody(NewReaction(emoji))
setBody(DeleteReaction(emoji, objectId))
}.body<Boolean>()
}

Expand Down Expand Up @@ -379,7 +380,7 @@ suspend fun HttpClient.upload(
formData {
append("description", "amedia")
append("file", stream, Headers.build {
append(HttpHeaders.ContentType, ContentType.defaultForFileExtension(extension).contentType)
append(HttpHeaders.ContentType, ContentType.defaultForFileExtension(extension))
append(HttpHeaders.ContentDisposition, "filename=\"$name\"")
})
},
Expand Down
22 changes: 16 additions & 6 deletions composeApp/src/commonMain/kotlin/com/storyteller_f/a/app/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import com.storyteller_f.a.client_lib.LoginViewModel
import com.storyteller_f.a.client_lib.addRequestHeaders
import com.storyteller_f.a.client_lib.defaultClientConfigure
import com.storyteller_f.a.client_lib.getClient
import com.storyteller_f.shared.model.TopicInfo
import com.storyteller_f.shared.obj.RoomFrame
import com.storyteller_f.shared.type.ObjectType
import com.storyteller_f.shared.type.PrimaryKey
Expand Down Expand Up @@ -232,19 +233,28 @@ val wsClient by lazy {
}) {
if (it is RoomFrame.NewTopicInfo) {
val info = processEncryptedTopic(listOf(it.topicInfo)).first()
getOrCreateCollection("topics${info.parentId}").save(
MutableDocument(
info.id.toString(),
Json.encodeToString(info)
)
)
updateDocumentInParent(info)
Napier.v(tag = "pagination") {
"save document $info"
}
}
}
}

fun updateDocumentInParent(info: TopicInfo) {
val collectionName = "topics${info.parentId}"
updateDocument(collectionName, info)
}

fun updateDocument(collectionName: String, info: TopicInfo) {
getOrCreateCollection(collectionName).save(
MutableDocument(
info.id.toString(),
Json.encodeToString(info)
)
)
}

fun HttpClientConfig<*>.setupRequest() {
defaultRequest {
url(BuildKonfig.SERVER_URL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fun CommunityIcon(
val radius = 8.dp
val shape = RoundedCornerShape(radius)
if (model != null) {
AsyncImage(model, contentDescription = null, Modifier.size(iconSize).clip(shape).clickable {
AsyncImage(globalLoader(model), contentDescription = null, Modifier.size(iconSize).clip(shape).clickable {
updateDialog(true)
})
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ private fun EmojiCell(
val hasReacted = info.hasReacted
Pill(info.count.toString(), emoji = emoji, selected = hasReacted == true) {
emoji.let { string ->
if (hasReacted == true) {
if (hasReacted) {
scope.launch {
globalDialogState.use {
client.deleteReaction(string)
client.deleteReaction(string, topicInfo.id)
bus.emit(OnTopicChanged(topicInfo.copy(reactionCount = reactionCount - 1)))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
import coil3.compose.LocalPlatformContext
import coil3.network.ktor3.KtorNetworkFetcherFactory
import coil3.request.ImageRequest
import coil3.request.crossfade
import com.storyteller_f.a.app.LocalAppNav
import com.storyteller_f.a.app.client
import com.storyteller_f.a.app.user.UserDialog
import com.storyteller_f.a.client_lib.LoginViewModel
import com.storyteller_f.shared.model.UserInfo
Expand All @@ -38,7 +43,7 @@ fun UserIcon(userInfo: UserInfo?, showDialog: Boolean = true, size: Dp = 40.dp)
val url = userInfo?.avatar?.url
if (url != null) {
AsyncImage(
url,
globalLoader(url),
contentDescription = "${userInfo.nickname}'s avatar",
modifier = Modifier.size(size).clip(CircleShape).clickable(showDialog, onClick = onClick)
)
Expand All @@ -57,3 +62,9 @@ fun UserIcon(userInfo: UserInfo?, showDialog: Boolean = true, size: Dp = 40.dp)
showMyDialog = false
}
}

@Composable
fun globalLoader(url: String) =
ImageRequest.Builder(LocalPlatformContext.current).data(url).crossfade(true).fetcherFactory(
KtorNetworkFetcherFactory(client)
).build()
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import androidx.compose.runtime.Composable
import com.storyteller_f.a.app.common.viewModel
import com.storyteller_f.a.app.search.SearchScope
import com.storyteller_f.shared.model.RoomInfo
import com.storyteller_f.shared.model.TopicInfo
import com.storyteller_f.shared.obj.JoinStatusSearch
import com.storyteller_f.shared.type.DEFAULT_PRIMARY_KEY
import com.storyteller_f.shared.type.ObjectType
import com.storyteller_f.shared.type.PrimaryKey

Expand Down Expand Up @@ -135,6 +137,12 @@ fun createTopicViewModel(topicId: PrimaryKey) =
TopicViewModel(topicId)
}

@Composable
fun createTopicViewModelFromInfo(topicInfo: TopicInfo) =
viewModel(keys = listOf("topic", topicInfo.id)) {
TopicViewModel(topicInfo)
}

@Composable
fun createTopicsInTopicViewModel(topicId: PrimaryKey) =
viewModel(keys = listOf("topic-topics", topicId)) {
Expand Down Expand Up @@ -202,8 +210,8 @@ fun createUserViewModel(userId: PrimaryKey) =
}

@Composable
fun createWorldViewModel() = viewModel {
WorldViewModel()
fun createWorldViewModel() = viewModel(keys = listOf("world")) {
TopicsViewModel(DEFAULT_PRIMARY_KEY, null)
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,19 @@ import com.storyteller_f.a.app.client
import com.storyteller_f.a.app.common.*
import com.storyteller_f.a.app.compontents.DialogSaveState
import com.storyteller_f.a.app.topic.processEncryptedTopic
import com.storyteller_f.a.app.updateDocument
import com.storyteller_f.a.app.updateDocumentInParent
import com.storyteller_f.a.client_lib.*
import com.storyteller_f.shared.model.*
import com.storyteller_f.shared.obj.JoinStatusSearch
import com.storyteller_f.shared.obj.ServerResponse
import com.storyteller_f.shared.type.ObjectType
import com.storyteller_f.shared.type.PrimaryKey
import com.storyteller_f.shared.type.toPrimaryKey
import com.storyteller_f.shared.type.toPrimaryKeyOrNull
import com.storyteller_f.shared.type.*
import com.storyteller_f.shared.utils.extractMarkdownHeadline
import io.github.aakira.napier.Napier
import io.ktor.client.*
import kotbase.Expression
import kotbase.MutableDocument
import kotbase.ktx.all
import kotbase.ktx.orderBy
import kotbase.ktx.select
import kotbase.ktx.where
import kotbase.ktx.*
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

data class OnCommunityJoined(val newInfo: CommunityInfo)
Expand Down Expand Up @@ -105,7 +100,7 @@ data class OnRoomJoined(val newInfo: RoomInfo)
data class OnRoomExited(val newInfo: RoomInfo)

@OptIn(ExperimentalPagingApi::class)
class TopicsViewModel(id: PrimaryKey, val type: ObjectType) : PagingViewModel<PrimaryKey, TopicInfo>({
class TopicsViewModel(id: PrimaryKey, val type: ObjectType? = null) : PagingViewModel<PrimaryKey, TopicInfo>({
CustomQueryPagingSource(
select = select(all()),
collectionName = "topics$id",
Expand All @@ -127,25 +122,49 @@ class TopicsViewModel(id: PrimaryKey, val type: ObjectType) : PagingViewModel<Pr
}
)
}, TopicsRemoteMediator("topics$id") { loadKey ->
val info = when (type) {
ObjectType.ROOM -> client.getRoomTopics(id, loadKey, 20)
ObjectType.COMMUNITY -> client.getCommunityTopics(id, loadKey, 20)
val info = when {
id == DEFAULT_PRIMARY_KEY -> client.getWorldTopics(loadKey, 10)
type == ObjectType.ROOM -> client.getRoomTopics(id, loadKey, 20)
type == ObjectType.COMMUNITY -> client.getCommunityTopics(id, loadKey, 20)
else -> client.getTopicTopics(id, loadKey, 20)
}.getOrThrow()
info.copy(processEncryptedTopic(info.data))
})
info.copy(processEncryptedTopic(info.data).map {
extractHeadlineIfPlain(it)
})
}) {
init {
viewModelScope.launch {
bus.collect { value ->
if (value is OnTopicChanged) {
val topicInfo = value.topicInfo
updateDocumentInParent(extractHeadlineIfPlain(topicInfo))
// 尝试更新到推荐
if (select(all()).from(getOrCreateCollection("topics$id"))
.where(Expression.property("id").equalTo(topicInfo.id)).execute().next() != null
) {
updateDocument("topics0", topicInfo)
}
}
}
}
}
}

private fun extractHeadlineIfPlain(it: TopicInfo): TopicInfo {
val content = it.content
return if (content is TopicContent.Plain) {
it.copy(content = TopicContent.Extracted(extractMarkdownHeadline(content.plain)))
} else {
it
}
}

@OptIn(ExperimentalPagingApi::class)
class TopicsRemoteMediator(
private val collectionName: String,
val networkService: suspend (PrimaryKey?) -> ServerResponse<TopicInfo>
) :
RemoteMediator<PrimaryKey, TopicInfo>() {
private val scope = database.defaultScope
private val collection
get() = scope.getCollection(collectionName) ?: database.createCollection(
collectionName
)

override suspend fun load(
loadType: LoadType,
Expand Down Expand Up @@ -175,17 +194,7 @@ class TopicsRemoteMediator(
database.deleteCollection(collectionName)
}
response.data.forEach {
val rawId = it.id.toString(2)
collection.save(
MutableDocument(
if (rawId.length == 64) {
rawId
} else {
"0$rawId"
},
Json.encodeToString(it)
)
)
updateDocument(collectionName, it)
}
Napier.v(tag = "pagination") {
"mediator success $loadKey"
Expand Down Expand Up @@ -287,9 +296,12 @@ class UserViewModel(private val requestInfo: suspend HttpClient.() -> Result<Use
class WorldViewModel : PagingViewModel<PrimaryKey, TopicInfo>({
SimplePagingSource {
serviceCatching {
client.getWorldTopics(it, 10, LoginViewModel.currentIsAlreadySignUp).getOrThrow()
client.getWorldTopics(it, 10).getOrThrow()
}.map {
APagingData(it.data, it.pagination?.nextPageToken?.toPrimaryKeyOrNull())
val data = it.data.map { info ->
extractHeadlineIfPlain(info)
}
APagingData(data, it.pagination?.nextPageToken?.toPrimaryKeyOrNull())
}
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import coil3.compose.AsyncImage
import com.storyteller_f.a.app.LocalAppNav
import com.storyteller_f.a.app.common.StateView
import com.storyteller_f.a.app.compontents.CommunityIcon
import com.storyteller_f.a.app.compontents.globalLoader
import com.storyteller_f.a.app.compontents.rememberCommonDialogController
import com.storyteller_f.a.app.model.createCommunityViewModel
import com.storyteller_f.a.app.model.createJoinedRoomsViewModel
Expand Down Expand Up @@ -122,7 +123,7 @@ fun RoomIcon(
val shape = RoundedCornerShape(radius)
if (iconUrl != null) {
AsyncImage(
iconUrl,
globalLoader(iconUrl),
contentDescription = "${roomInfo.name}'s icon",
modifier = Modifier.size(size).clip(shape).clickable(enableClick) {
updateShowDialog(true)
Expand Down
Loading

0 comments on commit 7fca344

Please sign in to comment.