2023-02-27 05:39:07 +00:00
|
|
|
import Combine
|
2023-01-17 10:36:01 +00:00
|
|
|
import Env
|
2022-12-20 19:33:45 +00:00
|
|
|
import Models
|
2023-02-12 17:24:09 +00:00
|
|
|
import NaturalLanguage
|
2022-12-20 19:33:45 +00:00
|
|
|
import Network
|
2023-01-17 10:36:01 +00:00
|
|
|
import SwiftUI
|
2022-12-20 19:33:45 +00:00
|
|
|
|
2023-02-08 17:47:09 +00:00
|
|
|
import DesignSystem
|
|
|
|
|
2022-12-20 19:33:45 +00:00
|
|
|
@MainActor
|
|
|
|
public class StatusRowViewModel: ObservableObject {
|
|
|
|
let status: Status
|
2022-12-24 12:41:25 +00:00
|
|
|
let isFocused: Bool
|
2023-01-06 11:14:05 +00:00
|
|
|
let isRemote: Bool
|
2023-01-17 06:54:59 +00:00
|
|
|
let showActions: Bool
|
2023-02-18 06:26:48 +00:00
|
|
|
|
2023-01-24 05:35:43 +00:00
|
|
|
@Published var favoritesCount: Int
|
|
|
|
@Published var isFavorited: Bool
|
2022-12-21 11:39:29 +00:00
|
|
|
@Published var isReblogged: Bool
|
2023-01-03 17:22:08 +00:00
|
|
|
@Published var isPinned: Bool
|
2023-01-09 18:26:56 +00:00
|
|
|
@Published var isBookmarked: Bool
|
2022-12-21 11:39:29 +00:00
|
|
|
@Published var reblogsCount: Int
|
|
|
|
@Published var repliesCount: Int
|
2023-01-17 14:14:50 +00:00
|
|
|
@Published var embeddedStatus: Status?
|
2022-12-28 09:45:05 +00:00
|
|
|
@Published var displaySpoiler: Bool = false
|
2023-01-27 12:38:24 +00:00
|
|
|
@Published var isEmbedLoading: Bool = false
|
2023-01-03 11:24:15 +00:00
|
|
|
@Published var isFiltered: Bool = false
|
2023-01-22 05:38:30 +00:00
|
|
|
|
2023-02-12 12:22:36 +00:00
|
|
|
@Published var translation: StatusTranslation?
|
2023-01-21 08:58:38 +00:00
|
|
|
@Published var isLoadingTranslation: Bool = false
|
2023-02-08 05:24:09 +00:00
|
|
|
@Published var showDeleteAlert: Bool = false
|
2023-02-04 16:17:38 +00:00
|
|
|
|
2023-02-23 06:32:00 +00:00
|
|
|
private var actionsAccountsFetched: Bool = false
|
2023-02-05 09:07:45 +00:00
|
|
|
@Published var favoriters: [Account] = []
|
|
|
|
@Published var rebloggers: [Account] = []
|
2023-02-18 06:26:48 +00:00
|
|
|
|
2023-02-13 05:48:29 +00:00
|
|
|
@Published var isLoadingRemoteContent: Bool = false
|
|
|
|
@Published var localStatusId: String?
|
|
|
|
@Published var localStatus: Status?
|
2023-02-08 17:47:09 +00:00
|
|
|
|
2023-02-26 16:32:09 +00:00
|
|
|
// used by the button to expand a collapsed post
|
|
|
|
@Published var isCollapsed: Bool = true {
|
|
|
|
didSet {
|
|
|
|
recalcCollapse()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// number of lines to show, nil means show the whole post
|
|
|
|
@Published var lineLimit: Int? = nil
|
|
|
|
// post length determining if the post should be collapsed
|
|
|
|
let collapseThresholdLength : Int = 750
|
|
|
|
// number of text lines to show on a collpased post
|
|
|
|
let collapsedLines: Int = 8
|
|
|
|
// user preference, set in init
|
|
|
|
var collapseLongPosts: Bool = false
|
|
|
|
|
|
|
|
private func recalcCollapse() {
|
|
|
|
let hasContentWarning = !status.spoilerText.asRawText.isEmpty
|
|
|
|
let showCollapseButton = collapseLongPosts && isCollapsed && !hasContentWarning
|
|
|
|
&& (status.reblog?.content ?? status.content).asRawText.unicodeScalars.count > collapseThresholdLength
|
|
|
|
let newlineLimit = showCollapseButton && isCollapsed ? collapsedLines : nil
|
|
|
|
if newlineLimit != lineLimit {
|
|
|
|
lineLimit = newlineLimit
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-08 17:47:09 +00:00
|
|
|
private let theme = Theme.shared
|
2023-02-26 08:38:26 +00:00
|
|
|
private let userMentionned: Bool
|
2023-02-12 15:29:41 +00:00
|
|
|
|
2023-02-16 07:52:11 +00:00
|
|
|
private var seen = false
|
2023-02-04 16:17:38 +00:00
|
|
|
|
2023-01-03 11:24:15 +00:00
|
|
|
var filter: Filtered? {
|
2023-01-03 14:15:08 +00:00
|
|
|
status.reblog?.filtered?.first ?? status.filtered?.first
|
2023-01-03 11:24:15 +00:00
|
|
|
}
|
2023-02-21 06:23:42 +00:00
|
|
|
|
2023-02-19 19:12:31 +00:00
|
|
|
var isThread: Bool {
|
|
|
|
status.reblog?.inReplyToId != nil || status.reblog?.inReplyToAccountId != nil ||
|
2023-02-26 05:45:57 +00:00
|
|
|
status.inReplyToId != nil || status.inReplyToAccountId != nil
|
2023-02-19 19:12:31 +00:00
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-02-08 17:47:09 +00:00
|
|
|
var highlightRowColor: Color {
|
|
|
|
if status.visibility == .direct {
|
|
|
|
return theme.tintColor.opacity(0.15)
|
2023-02-26 08:38:26 +00:00
|
|
|
} else if userMentionned {
|
2023-02-08 17:47:09 +00:00
|
|
|
return theme.secondaryBackgroundColor
|
|
|
|
} else {
|
|
|
|
return theme.primaryBackgroundColor
|
|
|
|
}
|
2023-02-02 05:39:03 +00:00
|
|
|
}
|
|
|
|
|
2023-02-15 07:46:14 +00:00
|
|
|
let client: Client
|
|
|
|
let routerPath: RouterPath
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2022-12-24 12:41:25 +00:00
|
|
|
public init(status: Status,
|
2023-02-15 07:46:14 +00:00
|
|
|
client: Client,
|
|
|
|
routerPath: RouterPath,
|
2023-01-05 17:54:18 +00:00
|
|
|
isFocused: Bool = false,
|
2023-01-17 06:54:59 +00:00
|
|
|
isRemote: Bool = false,
|
2023-01-17 10:36:01 +00:00
|
|
|
showActions: Bool = true)
|
|
|
|
{
|
2022-12-20 19:33:45 +00:00
|
|
|
self.status = status
|
2023-02-15 07:46:14 +00:00
|
|
|
self.client = client
|
|
|
|
self.routerPath = routerPath
|
2022-12-24 12:41:25 +00:00
|
|
|
self.isFocused = isFocused
|
2023-01-06 11:14:05 +00:00
|
|
|
self.isRemote = isRemote
|
2023-01-17 06:54:59 +00:00
|
|
|
self.showActions = showActions
|
2022-12-23 14:53:02 +00:00
|
|
|
if let reblog = status.reblog {
|
2023-01-24 05:56:28 +00:00
|
|
|
isFavorited = reblog.favourited == true
|
2023-01-17 10:36:01 +00:00
|
|
|
isReblogged = reblog.reblogged == true
|
|
|
|
isPinned = reblog.pinned == true
|
|
|
|
isBookmarked = reblog.bookmarked == true
|
2022-12-23 14:53:02 +00:00
|
|
|
} else {
|
2023-01-24 05:56:28 +00:00
|
|
|
isFavorited = status.favourited == true
|
2023-01-17 10:36:01 +00:00
|
|
|
isReblogged = status.reblogged == true
|
|
|
|
isPinned = status.pinned == true
|
|
|
|
isBookmarked = status.bookmarked == true
|
2022-12-23 14:53:02 +00:00
|
|
|
}
|
2023-01-24 05:56:28 +00:00
|
|
|
favoritesCount = status.reblog?.favouritesCount ?? status.favouritesCount
|
2023-01-17 10:36:01 +00:00
|
|
|
reblogsCount = status.reblog?.reblogsCount ?? status.reblogsCount
|
|
|
|
repliesCount = status.reblog?.repliesCount ?? status.repliesCount
|
2023-02-16 07:52:11 +00:00
|
|
|
if UserPreferences.shared.autoExpandSpoilers {
|
|
|
|
displaySpoiler = false
|
|
|
|
} else {
|
|
|
|
displaySpoiler = !(status.reblog?.spoilerText.asRawText ?? status.spoilerText.asRawText).isEmpty
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-02-26 08:38:26 +00:00
|
|
|
|
|
|
|
if status.mentions.first(where: { $0.id == CurrentAccount.shared.account?.id }) != nil {
|
|
|
|
userMentionned = true
|
|
|
|
} else {
|
|
|
|
userMentionned = false
|
|
|
|
}
|
|
|
|
|
2023-01-17 10:36:01 +00:00
|
|
|
isFiltered = filter != nil
|
2023-02-26 05:45:57 +00:00
|
|
|
|
2023-02-23 06:23:18 +00:00
|
|
|
if let url = embededStatusURL(),
|
2023-02-26 05:45:57 +00:00
|
|
|
let embed = StatusEmbedCache.shared.get(url: url)
|
|
|
|
{
|
2023-02-23 06:23:18 +00:00
|
|
|
isEmbedLoading = false
|
|
|
|
embeddedStatus = embed
|
|
|
|
}
|
2023-02-26 16:32:09 +00:00
|
|
|
|
|
|
|
collapseLongPosts = UserPreferences.shared.collapseLongPosts
|
|
|
|
recalcCollapse()
|
2022-12-20 19:33:45 +00:00
|
|
|
}
|
2023-02-26 05:45:57 +00:00
|
|
|
|
2023-02-01 17:56:06 +00:00
|
|
|
func markSeen() {
|
|
|
|
// called in on appear so we can cache that the status has been seen.
|
2023-02-04 16:17:38 +00:00
|
|
|
if UserPreferences.shared.suppressDupeReblogs && !seen {
|
2023-02-16 07:52:11 +00:00
|
|
|
DispatchQueue.global().async { [weak self] in
|
|
|
|
guard let self else { return }
|
|
|
|
ReblogCache.shared.cache(self.status, seen: true)
|
|
|
|
Task { @MainActor in
|
|
|
|
self.seen = true
|
|
|
|
}
|
|
|
|
}
|
2023-02-01 17:56:06 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-02-15 07:46:14 +00:00
|
|
|
func navigateToDetail() {
|
2023-01-17 18:41:46 +00:00
|
|
|
guard !isFocused else { return }
|
2023-01-18 12:36:00 +00:00
|
|
|
if isRemote, let url = URL(string: status.reblog?.url ?? status.url ?? "") {
|
2023-01-17 14:14:50 +00:00
|
|
|
routerPath.navigate(to: .remoteStatusDetail(url: url))
|
2023-01-06 11:14:05 +00:00
|
|
|
} else {
|
2023-02-10 17:25:38 +00:00
|
|
|
routerPath.navigate(to: .statusDetailWithStatus(status: status.reblogAsAsStatus ?? status))
|
2023-01-06 11:14:05 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-30 06:27:06 +00:00
|
|
|
|
2023-02-15 07:46:14 +00:00
|
|
|
func navigateToAccountDetail(account: Account) {
|
2023-01-29 10:17:43 +00:00
|
|
|
if isRemote, let url = account.url {
|
|
|
|
withAnimation {
|
|
|
|
isLoadingRemoteContent = true
|
|
|
|
}
|
|
|
|
Task {
|
|
|
|
await routerPath.navigateToAccountFrom(url: url)
|
|
|
|
isLoadingRemoteContent = false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
routerPath.navigate(to: .accountDetailWithAccount(account: account))
|
|
|
|
}
|
|
|
|
}
|
2023-01-30 06:27:06 +00:00
|
|
|
|
2023-02-15 07:46:14 +00:00
|
|
|
func navigateToMention(mention: Mention) {
|
2023-01-29 10:17:43 +00:00
|
|
|
if isRemote {
|
|
|
|
withAnimation {
|
|
|
|
isLoadingRemoteContent = true
|
|
|
|
}
|
|
|
|
Task {
|
|
|
|
await routerPath.navigateToAccountFrom(url: mention.url)
|
|
|
|
isLoadingRemoteContent = false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
routerPath.navigate(to: .accountDetail(id: mention.id))
|
|
|
|
}
|
|
|
|
}
|
2023-02-26 05:45:57 +00:00
|
|
|
|
2023-02-23 06:23:18 +00:00
|
|
|
private func embededStatusURL() -> URL? {
|
|
|
|
let content = status.reblog?.content ?? status.content
|
|
|
|
if !content.statusesURLs.isEmpty,
|
|
|
|
let url = content.statusesURLs.first,
|
2023-02-26 05:45:57 +00:00
|
|
|
client.hasConnection(with: url)
|
|
|
|
{
|
2023-02-23 06:23:18 +00:00
|
|
|
return url
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-01-17 14:14:50 +00:00
|
|
|
func loadEmbeddedStatus() async {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard embeddedStatus == nil,
|
2023-02-26 05:45:57 +00:00
|
|
|
let url = embededStatusURL()
|
|
|
|
else {
|
2023-01-28 10:09:35 +00:00
|
|
|
if isEmbedLoading {
|
|
|
|
isEmbedLoading = false
|
|
|
|
}
|
2022-12-30 18:31:17 +00:00
|
|
|
return
|
|
|
|
}
|
2023-02-26 05:45:57 +00:00
|
|
|
|
2023-02-23 06:23:18 +00:00
|
|
|
if let embed = StatusEmbedCache.shared.get(url: url) {
|
|
|
|
isEmbedLoading = false
|
|
|
|
embeddedStatus = embed
|
|
|
|
return
|
|
|
|
}
|
2023-02-26 05:45:57 +00:00
|
|
|
|
2022-12-27 06:51:44 +00:00
|
|
|
do {
|
2023-01-27 12:38:24 +00:00
|
|
|
isEmbedLoading = true
|
2022-12-31 05:37:13 +00:00
|
|
|
var embed: Status?
|
2022-12-30 15:55:13 +00:00
|
|
|
if url.absoluteString.contains(client.server), let id = Int(url.lastPathComponent) {
|
2022-12-31 05:37:13 +00:00
|
|
|
embed = try await client.get(endpoint: Statuses.status(id: String(id)))
|
2022-12-30 15:55:13 +00:00
|
|
|
} else {
|
|
|
|
let results: SearchResults = try await client.get(endpoint: Search.search(query: url.absoluteString,
|
|
|
|
type: "statuses",
|
2022-12-31 08:10:27 +00:00
|
|
|
offset: 0,
|
|
|
|
following: nil),
|
2023-01-17 10:36:01 +00:00
|
|
|
forceVersion: .v2)
|
2022-12-31 05:37:13 +00:00
|
|
|
embed = results.statuses.first
|
2022-12-30 15:55:13 +00:00
|
|
|
}
|
2023-02-23 06:23:18 +00:00
|
|
|
if let embed {
|
|
|
|
StatusEmbedCache.shared.set(url: url, status: embed)
|
|
|
|
}
|
2022-12-30 18:31:17 +00:00
|
|
|
withAnimation {
|
2023-01-17 14:14:50 +00:00
|
|
|
embeddedStatus = embed
|
2022-12-30 18:31:17 +00:00
|
|
|
isEmbedLoading = false
|
|
|
|
}
|
|
|
|
} catch {
|
|
|
|
isEmbedLoading = false
|
|
|
|
}
|
2022-12-27 06:51:44 +00:00
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-01-24 05:35:43 +00:00
|
|
|
func favorite() async {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard client.isAuth else { return }
|
2023-01-24 05:35:43 +00:00
|
|
|
isFavorited = true
|
|
|
|
favoritesCount += 1
|
2022-12-20 19:33:45 +00:00
|
|
|
do {
|
2023-02-13 05:48:29 +00:00
|
|
|
let status: Status = try await client.post(endpoint: Statuses.favorite(id: localStatusId ?? status.reblog?.id ?? status.id))
|
2022-12-20 19:33:45 +00:00
|
|
|
updateFromStatus(status: status)
|
|
|
|
} catch {
|
2023-01-24 05:35:43 +00:00
|
|
|
isFavorited = false
|
|
|
|
favoritesCount -= 1
|
2022-12-20 19:33:45 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-01-24 05:35:43 +00:00
|
|
|
func unFavorite() async {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard client.isAuth else { return }
|
2023-01-24 05:35:43 +00:00
|
|
|
isFavorited = false
|
|
|
|
favoritesCount -= 1
|
2022-12-20 19:33:45 +00:00
|
|
|
do {
|
2023-02-13 05:48:29 +00:00
|
|
|
let status: Status = try await client.post(endpoint: Statuses.unfavorite(id: localStatusId ?? status.reblog?.id ?? status.id))
|
2022-12-20 19:33:45 +00:00
|
|
|
updateFromStatus(status: status)
|
|
|
|
} catch {
|
2023-01-24 05:35:43 +00:00
|
|
|
isFavorited = true
|
|
|
|
favoritesCount += 1
|
2022-12-20 19:33:45 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2022-12-21 11:39:29 +00:00
|
|
|
func reblog() async {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard client.isAuth else { return }
|
2022-12-21 11:39:29 +00:00
|
|
|
isReblogged = true
|
|
|
|
reblogsCount += 1
|
|
|
|
do {
|
2023-02-13 05:48:29 +00:00
|
|
|
let status: Status = try await client.post(endpoint: Statuses.reblog(id: localStatusId ?? status.reblog?.id ?? status.id))
|
2022-12-21 11:39:29 +00:00
|
|
|
updateFromStatus(status: status)
|
|
|
|
} catch {
|
|
|
|
isReblogged = false
|
|
|
|
reblogsCount -= 1
|
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2022-12-21 11:39:29 +00:00
|
|
|
func unReblog() async {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard client.isAuth else { return }
|
2022-12-21 11:39:29 +00:00
|
|
|
isReblogged = false
|
|
|
|
reblogsCount -= 1
|
|
|
|
do {
|
2023-02-13 05:48:29 +00:00
|
|
|
let status: Status = try await client.post(endpoint: Statuses.unreblog(id: localStatusId ?? status.reblog?.id ?? status.id))
|
2022-12-21 11:39:29 +00:00
|
|
|
updateFromStatus(status: status)
|
|
|
|
} catch {
|
|
|
|
isReblogged = true
|
|
|
|
reblogsCount += 1
|
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-01-03 17:22:08 +00:00
|
|
|
func pin() async {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard client.isAuth else { return }
|
2023-01-03 17:22:08 +00:00
|
|
|
isPinned = true
|
|
|
|
do {
|
|
|
|
let status: Status = try await client.post(endpoint: Statuses.pin(id: status.reblog?.id ?? status.id))
|
|
|
|
updateFromStatus(status: status)
|
|
|
|
} catch {
|
|
|
|
isPinned = false
|
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-01-03 17:22:08 +00:00
|
|
|
func unPin() async {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard client.isAuth else { return }
|
2023-01-03 17:22:08 +00:00
|
|
|
isPinned = false
|
|
|
|
do {
|
|
|
|
let status: Status = try await client.post(endpoint: Statuses.unpin(id: status.reblog?.id ?? status.id))
|
|
|
|
updateFromStatus(status: status)
|
|
|
|
} catch {
|
|
|
|
isPinned = true
|
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-01-09 18:26:56 +00:00
|
|
|
func bookmark() async {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard client.isAuth else { return }
|
2023-01-09 18:26:56 +00:00
|
|
|
isBookmarked = true
|
|
|
|
do {
|
2023-02-13 05:48:29 +00:00
|
|
|
let status: Status = try await client.post(endpoint: Statuses.bookmark(id: localStatusId ?? status.reblog?.id ?? status.id))
|
2023-01-09 18:26:56 +00:00
|
|
|
updateFromStatus(status: status)
|
|
|
|
} catch {
|
|
|
|
isBookmarked = false
|
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-01-09 18:26:56 +00:00
|
|
|
func unbookmark() async {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard client.isAuth else { return }
|
2023-01-09 18:26:56 +00:00
|
|
|
isBookmarked = false
|
|
|
|
do {
|
2023-02-13 05:48:29 +00:00
|
|
|
let status: Status = try await client.post(endpoint: Statuses.unbookmark(id: localStatusId ?? status.reblog?.id ?? status.id))
|
2023-01-09 18:26:56 +00:00
|
|
|
updateFromStatus(status: status)
|
|
|
|
} catch {
|
|
|
|
isBookmarked = true
|
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2022-12-25 11:46:42 +00:00
|
|
|
func delete() async {
|
|
|
|
do {
|
|
|
|
_ = try await client.delete(endpoint: Statuses.status(id: status.id))
|
2023-01-17 10:36:01 +00:00
|
|
|
} catch {}
|
2022-12-25 11:46:42 +00:00
|
|
|
}
|
2023-02-12 15:29:41 +00:00
|
|
|
|
2023-02-05 09:07:45 +00:00
|
|
|
func fetchActionsAccounts() async {
|
2023-02-23 06:32:00 +00:00
|
|
|
guard !actionsAccountsFetched else { return }
|
2023-02-05 09:07:45 +00:00
|
|
|
do {
|
|
|
|
favoriters = try await client.get(endpoint: Statuses.favoritedBy(id: status.id, maxId: nil))
|
|
|
|
rebloggers = try await client.get(endpoint: Statuses.rebloggedBy(id: status.id, maxId: nil))
|
2023-02-23 06:32:00 +00:00
|
|
|
actionsAccountsFetched = true
|
2023-02-12 15:29:41 +00:00
|
|
|
} catch {}
|
2023-02-05 09:07:45 +00:00
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2022-12-20 19:33:45 +00:00
|
|
|
private func updateFromStatus(status: Status) {
|
2022-12-23 14:53:02 +00:00
|
|
|
if let reblog = status.reblog {
|
2023-01-24 05:56:28 +00:00
|
|
|
isFavorited = reblog.favourited == true
|
2022-12-23 14:53:02 +00:00
|
|
|
isReblogged = reblog.reblogged == true
|
2023-01-03 17:22:08 +00:00
|
|
|
isPinned = reblog.pinned == true
|
2023-01-09 18:26:56 +00:00
|
|
|
isBookmarked = reblog.bookmarked == true
|
2022-12-23 14:53:02 +00:00
|
|
|
} else {
|
2023-01-24 05:56:28 +00:00
|
|
|
isFavorited = status.favourited == true
|
2022-12-23 14:53:02 +00:00
|
|
|
isReblogged = status.reblogged == true
|
2023-01-03 17:22:08 +00:00
|
|
|
isPinned = status.pinned == true
|
2023-01-09 18:26:56 +00:00
|
|
|
isBookmarked = status.bookmarked == true
|
2022-12-23 14:53:02 +00:00
|
|
|
}
|
2023-01-24 05:56:28 +00:00
|
|
|
favoritesCount = status.reblog?.favouritesCount ?? status.favouritesCount
|
2022-12-21 11:39:29 +00:00
|
|
|
reblogsCount = status.reblog?.reblogsCount ?? status.reblogsCount
|
|
|
|
repliesCount = status.reblog?.repliesCount ?? status.repliesCount
|
2022-12-20 19:33:45 +00:00
|
|
|
}
|
2023-02-12 17:24:09 +00:00
|
|
|
|
|
|
|
func getStatusLang() -> String? {
|
2023-02-17 18:11:01 +00:00
|
|
|
status.reblog?.language ?? status.language
|
2023-02-12 17:24:09 +00:00
|
|
|
}
|
|
|
|
|
2023-01-21 08:58:38 +00:00
|
|
|
func translate(userLang: String) async {
|
|
|
|
do {
|
|
|
|
withAnimation {
|
|
|
|
isLoadingTranslation = true
|
|
|
|
}
|
2023-02-12 12:22:36 +00:00
|
|
|
// We first use instance translation API if available.
|
|
|
|
let translation: StatusTranslation = try await client.post(endpoint: Statuses.translate(id: status.reblog?.id ?? status.id,
|
|
|
|
lang: userLang))
|
2023-01-21 08:58:38 +00:00
|
|
|
withAnimation {
|
|
|
|
self.translation = translation
|
2023-01-22 09:24:19 +00:00
|
|
|
isLoadingTranslation = false
|
2023-01-21 08:58:38 +00:00
|
|
|
}
|
2023-02-12 12:22:36 +00:00
|
|
|
} catch {
|
|
|
|
// If not or fail we use Ice Cubes own DeepL client.
|
|
|
|
let deepLClient = DeepLClient()
|
|
|
|
let translation = try? await deepLClient.request(target: userLang,
|
|
|
|
source: status.language,
|
|
|
|
text: status.reblog?.content.asRawText ?? status.content.asRawText)
|
|
|
|
withAnimation {
|
|
|
|
self.translation = translation
|
|
|
|
isLoadingTranslation = false
|
|
|
|
}
|
|
|
|
}
|
2023-01-21 08:58:38 +00:00
|
|
|
}
|
2023-02-18 06:26:48 +00:00
|
|
|
|
2023-02-13 05:48:29 +00:00
|
|
|
func fetchRemoteStatus() async -> Bool {
|
2023-02-15 07:46:14 +00:00
|
|
|
guard isRemote, let remoteStatusURL = URL(string: status.reblog?.url ?? status.url ?? "") else { return false }
|
2023-02-13 05:48:29 +00:00
|
|
|
isLoadingRemoteContent = true
|
|
|
|
let results: SearchResults? = try? await client.get(endpoint: Search.search(query: remoteStatusURL.absoluteString,
|
|
|
|
type: "statuses",
|
|
|
|
offset: nil,
|
|
|
|
following: nil),
|
|
|
|
forceVersion: .v2)
|
|
|
|
if let status = results?.statuses.first {
|
2023-02-18 06:26:48 +00:00
|
|
|
localStatusId = status.id
|
|
|
|
localStatus = status
|
2023-02-13 05:48:29 +00:00
|
|
|
isLoadingRemoteContent = false
|
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
isLoadingRemoteContent = false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2022-12-20 19:33:45 +00:00
|
|
|
}
|