/* Copyright 2021 Tusky Contributors * * This file is a part of Tusky. * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Tusky; if not, * see . */ @file:OptIn(ExperimentalStdlibApi::class) package com.keylesspalace.tusky.components.timeline import android.util.Log import com.keylesspalace.tusky.db.TimelineAccountEntity import com.keylesspalace.tusky.db.TimelineStatusEntity import com.keylesspalace.tusky.db.TimelineStatusWithAccount import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Card import com.keylesspalace.tusky.entity.Emoji import com.keylesspalace.tusky.entity.HashTag import com.keylesspalace.tusky.entity.Poll import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.TimelineAccount import com.keylesspalace.tusky.viewdata.StatusViewData import com.keylesspalace.tusky.viewdata.TranslationViewData import com.squareup.moshi.Moshi import com.squareup.moshi.adapter import java.util.Date private const val TAG = "TimelineTypeMappers" data class Placeholder( val id: String, val loading: Boolean ) fun TimelineAccount.toEntity(accountId: Long, moshi: Moshi): TimelineAccountEntity { return TimelineAccountEntity( serverId = id, timelineUserId = accountId, localUsername = localUsername, username = username, displayName = name, url = url, avatar = avatar, emojis = moshi.adapter>().toJson(emojis), bot = bot ) } fun TimelineAccountEntity.toAccount(moshi: Moshi): TimelineAccount { return TimelineAccount( id = serverId, localUsername = localUsername, username = username, displayName = displayName, note = "", url = url, avatar = avatar, bot = bot, emojis = moshi.adapter?>().fromJson(emojis).orEmpty() ) } fun Placeholder.toEntity(timelineUserId: Long): TimelineStatusEntity { return TimelineStatusEntity( serverId = this.id, url = null, timelineUserId = timelineUserId, authorServerId = null, inReplyToId = null, inReplyToAccountId = null, content = null, createdAt = 0L, editedAt = 0L, emojis = null, reblogsCount = 0, favouritesCount = 0, reblogged = false, favourited = false, bookmarked = false, sensitive = false, spoilerText = "", visibility = Status.Visibility.UNKNOWN, attachments = null, mentions = null, tags = null, application = null, reblogServerId = null, reblogAccountId = null, poll = null, muted = false, expanded = loading, contentCollapsed = false, contentShowing = false, pinned = false, card = null, repliesCount = 0, language = null, filtered = emptyList() ) } fun Status.toEntity( timelineUserId: Long, moshi: Moshi, expanded: Boolean, contentShowing: Boolean, contentCollapsed: Boolean ): TimelineStatusEntity { return TimelineStatusEntity( serverId = this.id, url = actionableStatus.url, timelineUserId = timelineUserId, authorServerId = actionableStatus.account.id, inReplyToId = actionableStatus.inReplyToId, inReplyToAccountId = actionableStatus.inReplyToAccountId, content = actionableStatus.content, createdAt = actionableStatus.createdAt.time, editedAt = actionableStatus.editedAt?.time, emojis = actionableStatus.emojis.let { moshi.adapter>().toJson(it) }, reblogsCount = actionableStatus.reblogsCount, favouritesCount = actionableStatus.favouritesCount, reblogged = actionableStatus.reblogged, favourited = actionableStatus.favourited, bookmarked = actionableStatus.bookmarked, sensitive = actionableStatus.sensitive, spoilerText = actionableStatus.spoilerText, visibility = actionableStatus.visibility, attachments = actionableStatus.attachments.let { moshi.adapter>().toJson(it) }, mentions = actionableStatus.mentions.let { moshi.adapter>().toJson(it) }, tags = actionableStatus.tags.let { moshi.adapter?>().toJson(it) }, application = actionableStatus.application.let { moshi.adapter().toJson(it) }, reblogServerId = reblog?.id, reblogAccountId = reblog?.let { this.account.id }, poll = actionableStatus.poll.let { moshi.adapter().toJson(it) }, muted = actionableStatus.muted, expanded = expanded, contentShowing = contentShowing, contentCollapsed = contentCollapsed, pinned = actionableStatus.pinned, card = actionableStatus.card?.let { moshi.adapter().toJson(it) }, repliesCount = actionableStatus.repliesCount, language = actionableStatus.language, filtered = actionableStatus.filtered ) } fun TimelineStatusWithAccount.toViewData(moshi: Moshi, isDetailed: Boolean = false, translation: TranslationViewData? = null): StatusViewData { if (this.account == null) { Log.d(TAG, "Constructing Placeholder(${this.status.serverId}, ${this.status.expanded})") return StatusViewData.Placeholder(this.status.serverId, this.status.expanded) } val attachments: List = status.attachments?.let { moshi.adapter?>().fromJson(it) }.orEmpty() val mentions: List = status.mentions?.let { moshi.adapter?>().fromJson(it) }.orEmpty() val tags: List? = status.tags?.let { moshi.adapter?>().fromJson(it) } val application = status.application?.let { moshi.adapter().fromJson(it) } val emojis: List = status.emojis?.let { moshi.adapter?>().fromJson(it) }.orEmpty() val poll: Poll? = status.poll?.let { moshi.adapter().fromJson(it) } val card: Card? = status.card?.let { moshi.adapter().fromJson(it) } val reblog = status.reblogServerId?.let { id -> Status( id = id, url = status.url, account = account.toAccount(moshi), inReplyToId = status.inReplyToId, inReplyToAccountId = status.inReplyToAccountId, reblog = null, content = status.content.orEmpty(), createdAt = Date(status.createdAt), editedAt = status.editedAt?.let { Date(it) }, emojis = emojis, reblogsCount = status.reblogsCount, favouritesCount = status.favouritesCount, reblogged = status.reblogged, favourited = status.favourited, bookmarked = status.bookmarked, sensitive = status.sensitive, spoilerText = status.spoilerText, visibility = status.visibility, attachments = attachments, mentions = mentions, tags = tags, application = application, pinned = false, muted = status.muted ?: false, poll = poll, card = card, repliesCount = status.repliesCount, language = status.language, filtered = status.filtered.orEmpty(), ) } val status = if (reblog != null) { Status( id = status.serverId, // no url for reblogs url = null, account = this.reblogAccount!!.toAccount(moshi), inReplyToId = null, inReplyToAccountId = null, reblog = reblog, content = "", // lie but whatever? createdAt = Date(status.createdAt), editedAt = null, emojis = emptyList(), reblogsCount = 0, favouritesCount = 0, reblogged = false, favourited = false, bookmarked = false, sensitive = false, spoilerText = "", visibility = status.visibility, attachments = emptyList(), mentions = emptyList(), tags = emptyList(), application = null, pinned = status.pinned, muted = status.muted ?: false, poll = null, card = null, repliesCount = status.repliesCount, language = status.language, filtered = status.filtered.orEmpty() ) } else { Status( id = status.serverId, url = status.url, account = account.toAccount(moshi), inReplyToId = status.inReplyToId, inReplyToAccountId = status.inReplyToAccountId, reblog = null, content = translation?.data?.content ?: status.content.orEmpty(), createdAt = Date(status.createdAt), editedAt = status.editedAt?.let { Date(it) }, emojis = emojis, reblogsCount = status.reblogsCount, favouritesCount = status.favouritesCount, reblogged = status.reblogged, favourited = status.favourited, bookmarked = status.bookmarked, sensitive = status.sensitive, spoilerText = status.spoilerText, visibility = status.visibility, attachments = attachments, mentions = mentions, tags = tags, application = application, pinned = status.pinned, muted = status.muted ?: false, poll = poll, card = card, repliesCount = status.repliesCount, language = status.language, filtered = status.filtered.orEmpty() ) } return StatusViewData.Concrete( status = status, isExpanded = this.status.expanded, isShowingContent = this.status.contentShowing, isCollapsed = this.status.contentCollapsed, isDetailed = isDetailed, translation = translation, ) }