Add information about last seen status.
This commit is contained in:
parent
34b3efa211
commit
da3db13bc4
|
@ -97,12 +97,12 @@
|
|||
F897978F29684BCB00B22335 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F897978E29684BCB00B22335 /* LoadingView.swift */; };
|
||||
F8984E4D296B648000A2610F /* UIImage+Blurhash.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8984E4C296B648000A2610F /* UIImage+Blurhash.swift */; };
|
||||
F898DE702972868A004B4A6A /* String+Empty.swift in Sources */ = {isa = PBXBuildFile; fileRef = F898DE6F2972868A004B4A6A /* String+Empty.swift */; };
|
||||
F898DE7229728CB2004B4A6A /* CommentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F898DE7129728CB2004B4A6A /* CommentViewModel.swift */; };
|
||||
F898DE7229728CB2004B4A6A /* CommentModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F898DE7129728CB2004B4A6A /* CommentModel.swift */; };
|
||||
F8996DEB2971D29D0043EEC6 /* View+Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8996DEA2971D29D0043EEC6 /* View+Transition.swift */; };
|
||||
F89992C7296D3DF8005994BF /* MastodonKit in Frameworks */ = {isa = PBXBuildFile; productRef = F89992C6296D3DF8005994BF /* MastodonKit */; };
|
||||
F89992C9296D6DC7005994BF /* CommentBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89992C8296D6DC7005994BF /* CommentBody.swift */; };
|
||||
F89992CC296D9231005994BF /* StatusViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89992CB296D9231005994BF /* StatusViewModel.swift */; };
|
||||
F89992CE296D92E7005994BF /* AttachmentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89992CD296D92E7005994BF /* AttachmentViewModel.swift */; };
|
||||
F89992CC296D9231005994BF /* StatusModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89992CB296D9231005994BF /* StatusModel.swift */; };
|
||||
F89992CE296D92E7005994BF /* AttachmentModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89992CD296D92E7005994BF /* AttachmentModel.swift */; };
|
||||
F89A46DC296EAACE0062125F /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89A46DB296EAACE0062125F /* SettingsView.swift */; };
|
||||
F89A46DE296EABA20062125F /* StatusPlaceholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89A46DD296EABA20062125F /* StatusPlaceholder.swift */; };
|
||||
F89CEB802984198600A1376F /* AttachmentData+HighestImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89CEB7F2984198600A1376F /* AttachmentData+HighestImage.swift */; };
|
||||
|
@ -117,6 +117,8 @@
|
|||
F8B1E6512973FB7E00EE0D10 /* ToastrService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B1E6502973FB7E00EE0D10 /* ToastrService.swift */; };
|
||||
F8C14392296AF0B3001FE31D /* String+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C14391296AF0B3001FE31D /* String+Exif.swift */; };
|
||||
F8C14394296AF21B001FE31D /* Double+Round.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C14393296AF21B001FE31D /* Double+Round.swift */; };
|
||||
F8C5E55F2988E92600ADF6A7 /* AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C5E55E2988E92600ADF6A7 /* AccountModel.swift */; };
|
||||
F8C5E56229892CC300ADF6A7 /* FirstAppear.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C5E56129892CC300ADF6A7 /* FirstAppear.swift */; };
|
||||
F8C7EDBF298169EE002843BC /* TagsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C7EDBE298169EE002843BC /* TagsService.swift */; };
|
||||
F8CC95CE2970761D00C9C2AC /* TintColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CC95CD2970761D00C9C2AC /* TintColor.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -210,11 +212,11 @@
|
|||
F897978E29684BCB00B22335 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = "<group>"; };
|
||||
F8984E4C296B648000A2610F /* UIImage+Blurhash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Blurhash.swift"; sourceTree = "<group>"; };
|
||||
F898DE6F2972868A004B4A6A /* String+Empty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Empty.swift"; sourceTree = "<group>"; };
|
||||
F898DE7129728CB2004B4A6A /* CommentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentViewModel.swift; sourceTree = "<group>"; };
|
||||
F898DE7129728CB2004B4A6A /* CommentModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentModel.swift; sourceTree = "<group>"; };
|
||||
F8996DEA2971D29D0043EEC6 /* View+Transition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Transition.swift"; sourceTree = "<group>"; };
|
||||
F89992C8296D6DC7005994BF /* CommentBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentBody.swift; sourceTree = "<group>"; };
|
||||
F89992CB296D9231005994BF /* StatusViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusViewModel.swift; sourceTree = "<group>"; };
|
||||
F89992CD296D92E7005994BF /* AttachmentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentViewModel.swift; sourceTree = "<group>"; };
|
||||
F89992CB296D9231005994BF /* StatusModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusModel.swift; sourceTree = "<group>"; };
|
||||
F89992CD296D92E7005994BF /* AttachmentModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentModel.swift; sourceTree = "<group>"; };
|
||||
F89A46DB296EAACE0062125F /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
F89A46DD296EABA20062125F /* StatusPlaceholder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusPlaceholder.swift; sourceTree = "<group>"; };
|
||||
F89CEB7F2984198600A1376F /* AttachmentData+HighestImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttachmentData+HighestImage.swift"; sourceTree = "<group>"; };
|
||||
|
@ -228,7 +230,10 @@
|
|||
F8B1E6502973FB7E00EE0D10 /* ToastrService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastrService.swift; sourceTree = "<group>"; };
|
||||
F8C14391296AF0B3001FE31D /* String+Exif.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Exif.swift"; sourceTree = "<group>"; };
|
||||
F8C14393296AF21B001FE31D /* Double+Round.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Double+Round.swift"; sourceTree = "<group>"; };
|
||||
F8C5E55E2988E92600ADF6A7 /* AccountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountModel.swift; sourceTree = "<group>"; };
|
||||
F8C5E56129892CC300ADF6A7 /* FirstAppear.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstAppear.swift; sourceTree = "<group>"; };
|
||||
F8C7EDBE298169EE002843BC /* TagsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagsService.swift; sourceTree = "<group>"; };
|
||||
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-001.xcdatamodel"; sourceTree = "<group>"; };
|
||||
F8CC95CD2970761D00C9C2AC /* TintColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TintColor.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -316,6 +321,10 @@
|
|||
F8341F95295C640C009C8EE6 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F89992CB296D9231005994BF /* StatusModel.swift */,
|
||||
F89992CD296D92E7005994BF /* AttachmentModel.swift */,
|
||||
F898DE7129728CB2004B4A6A /* CommentModel.swift */,
|
||||
F8C5E55E2988E92600ADF6A7 /* AccountModel.swift */,
|
||||
F88FAD2C295F4AD7009B20C9 /* ApplicationState.swift */,
|
||||
F866F6AD29606367002E8F88 /* ApplicationViewMode.swift */,
|
||||
F8CC95CD2970761D00C9C2AC /* TintColor.swift */,
|
||||
|
@ -417,12 +426,12 @@
|
|||
children = (
|
||||
F866F6A829604FFF002E8F88 /* Info.plist */,
|
||||
F802884D297AEEAA000BDD51 /* Errors */,
|
||||
F89992CA296D9211005994BF /* ViewModels */,
|
||||
F86B721F296C498B00EE59EC /* Styles */,
|
||||
F88ABD9029686F00004EF61E /* Cache */,
|
||||
F897978B2968367E00B22335 /* Haptics */,
|
||||
F8210DE82966E4D8001D9973 /* Modifiers */,
|
||||
F88FAD30295F5010009B20C9 /* Services */,
|
||||
F8C5E56029892C8A00ADF6A7 /* ViewModifiers */,
|
||||
F83901A2295D863B00456AE2 /* Widgets */,
|
||||
F8341F96295C6427009C8EE6 /* CoreData */,
|
||||
F8341F95295C640C009C8EE6 /* Models */,
|
||||
|
@ -485,16 +494,6 @@
|
|||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F89992CA296D9211005994BF /* ViewModels */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F89992CB296D9231005994BF /* StatusViewModel.swift */,
|
||||
F89992CD296D92E7005994BF /* AttachmentViewModel.swift */,
|
||||
F898DE7129728CB2004B4A6A /* CommentViewModel.swift */,
|
||||
);
|
||||
path = ViewModels;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F89D6C4029717FC0001DA3D4 /* SettingsView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -525,6 +524,14 @@
|
|||
path = StatusView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F8C5E56029892C8A00ADF6A7 /* ViewModifiers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F8C5E56129892CC300ADF6A7 /* FirstAppear.swift */,
|
||||
);
|
||||
path = ViewModifiers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
|
@ -646,10 +653,11 @@
|
|||
F89D6C4429718092001DA3D4 /* AccentsSection.swift in Sources */,
|
||||
F88E4D42297E69FD0057491A /* StatusesView.swift in Sources */,
|
||||
F85D497929640B9D00751DF7 /* ImagesCarousel.swift in Sources */,
|
||||
F8C5E55F2988E92600ADF6A7 /* AccountModel.swift in Sources */,
|
||||
F89D6C3F29716E41001DA3D4 /* Theme.swift in Sources */,
|
||||
F88E4D5A297ECEE60057491A /* SearchService.swift in Sources */,
|
||||
F8CC95CE2970761D00C9C2AC /* TintColor.swift in Sources */,
|
||||
F89992CC296D9231005994BF /* StatusViewModel.swift in Sources */,
|
||||
F89992CC296D9231005994BF /* StatusModel.swift in Sources */,
|
||||
F80048052961850500E6868A /* StatusData+CoreDataClass.swift in Sources */,
|
||||
F86B7221296C49A300EE59EC /* EmptyButtonStyle.swift in Sources */,
|
||||
F80048042961850500E6868A /* AttachmentData+CoreDataProperties.swift in Sources */,
|
||||
|
@ -658,7 +666,7 @@
|
|||
F83901A6295D8EC000456AE2 /* LabelIcon.swift in Sources */,
|
||||
F8B1E6512973FB7E00EE0D10 /* ToastrService.swift in Sources */,
|
||||
F88E4D48297E90CD0057491A /* TrendStatusesView.swift in Sources */,
|
||||
F89992CE296D92E7005994BF /* AttachmentViewModel.swift in Sources */,
|
||||
F89992CE296D92E7005994BF /* AttachmentModel.swift in Sources */,
|
||||
F800480A2961EA1900E6868A /* AttachmentDataHandler.swift in Sources */,
|
||||
F80048032961850500E6868A /* AttachmentData+CoreDataClass.swift in Sources */,
|
||||
F897978D2968369600B22335 /* HapticService.swift in Sources */,
|
||||
|
@ -670,7 +678,7 @@
|
|||
F86B721E296C458700EE59EC /* BlurredImage.swift in Sources */,
|
||||
F88C2478295C37BB0006098B /* Vernissage.xcdatamodeld in Sources */,
|
||||
F88E4D52297EA6DA0057491A /* String+Markdown.swift in Sources */,
|
||||
F898DE7229728CB2004B4A6A /* CommentViewModel.swift in Sources */,
|
||||
F898DE7229728CB2004B4A6A /* CommentModel.swift in Sources */,
|
||||
F89A46DE296EABA20062125F /* StatusPlaceholder.swift in Sources */,
|
||||
F88C2482295C3A4F0006098B /* StatusView.swift in Sources */,
|
||||
F866F6A329604161002E8F88 /* AccountDataHandler.swift in Sources */,
|
||||
|
@ -704,6 +712,7 @@
|
|||
F88FAD2D295F4AD7009B20C9 /* ApplicationState.swift in Sources */,
|
||||
F88E4D54297EA7EE0057491A /* MarkdownFormattedText.swift in Sources */,
|
||||
F866F6A1296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift in Sources */,
|
||||
F8C5E56229892CC300ADF6A7 /* FirstAppear.swift in Sources */,
|
||||
F8C14394296AF21B001FE31D /* Double+Round.swift in Sources */,
|
||||
F83CBEFB298298A1002972C8 /* ImageCarouselPicture.swift in Sources */,
|
||||
F89A46DC296EAACE0062125F /* SettingsView.swift in Sources */,
|
||||
|
@ -1014,9 +1023,10 @@
|
|||
F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */,
|
||||
F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */,
|
||||
);
|
||||
currentVersion = F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */;
|
||||
currentVersion = F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */;
|
||||
path = Vernissage.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
versionGroupType = wrapper.xcdatamodel;
|
||||
|
|
|
@ -34,7 +34,7 @@ extension AccountData {
|
|||
@NSManaged public var url: URL?
|
||||
@NSManaged public var username: String
|
||||
@NSManaged public var statuses: Set<StatusData>?
|
||||
|
||||
@NSManaged public var lastSeenStatusId: String?
|
||||
}
|
||||
|
||||
// MARK: Generated accessors for statuses
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class AccountModel: ObservableObject {
|
||||
public let accessToken: String?
|
||||
public let refreshToken: String?
|
||||
public let acct: String
|
||||
public let avatar: URL?
|
||||
public let avatarData: Data?
|
||||
public let clientId: String
|
||||
public let clientSecret: String
|
||||
public let clientVapidKey: String
|
||||
public let createdAt: String
|
||||
public let displayName: String?
|
||||
public let followersCount: Int32
|
||||
public let followingCount: Int32
|
||||
public let header: URL?
|
||||
public let id: String
|
||||
public let locked: Bool
|
||||
public let note: String?
|
||||
public let serverUrl: URL
|
||||
public let statusesCount: Int32
|
||||
public let url: URL?
|
||||
public let username: String
|
||||
public let lastSeenStatusId: String?
|
||||
|
||||
init(accountData: AccountData) {
|
||||
self.accessToken = accountData.accessToken
|
||||
self.refreshToken = accountData.refreshToken
|
||||
self.acct = accountData.acct
|
||||
self.avatar = accountData.avatar
|
||||
self.avatarData = accountData.avatarData
|
||||
self.clientId = accountData.clientId
|
||||
self.clientSecret = accountData.clientSecret
|
||||
self.clientVapidKey = accountData.clientVapidKey
|
||||
self.createdAt = accountData.createdAt
|
||||
self.displayName = accountData.displayName
|
||||
self.followersCount = accountData.followersCount
|
||||
self.followingCount = accountData.followingCount
|
||||
self.header = accountData.header
|
||||
self.id = accountData.id
|
||||
self.locked = accountData.locked
|
||||
self.note = accountData.note
|
||||
self.serverUrl = accountData.serverUrl
|
||||
self.statusesCount = accountData.statusesCount
|
||||
self.url = accountData.url
|
||||
self.username = accountData.username
|
||||
self.lastSeenStatusId = accountData.lastSeenStatusId
|
||||
}
|
||||
}
|
|
@ -12,7 +12,9 @@ public class ApplicationState: ObservableObject {
|
|||
public static let shared = ApplicationState()
|
||||
private init() { }
|
||||
|
||||
@Published var accountData: AccountData?
|
||||
@Published var account: AccountModel?
|
||||
|
||||
@Published var lastSeenStatusId: String?
|
||||
@Published var tintColor = TintColor.accentColor2
|
||||
@Published var theme = Theme.system
|
||||
@Published var avatarShape = AvatarShape.circle
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class AttachmentViewModel: ObservableObject {
|
||||
public class AttachmentModel: ObservableObject {
|
||||
public let id: String
|
||||
public let type: MediaAttachment.MediaAttachmentType
|
||||
public let url: URL
|
||||
|
@ -117,8 +117,8 @@ public class AttachmentViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
extension [AttachmentViewModel] {
|
||||
func getHighestImage() -> AttachmentViewModel? {
|
||||
extension [AttachmentModel] {
|
||||
func getHighestImage() -> AttachmentModel? {
|
||||
var attachment = self.first
|
||||
var imgHeight = 0.0
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public struct CommentViewModel {
|
||||
var status: StatusViewModel
|
||||
public struct CommentModel {
|
||||
var status: StatusModel
|
||||
var showDivider: Bool
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class StatusViewModel: ObservableObject {
|
||||
public class StatusModel: ObservableObject {
|
||||
|
||||
public let id: EntityId
|
||||
public let content: Html
|
||||
|
@ -38,7 +38,7 @@ public class StatusViewModel: ObservableObject {
|
|||
|
||||
public let reblogStatus: Status?
|
||||
|
||||
@Published public var mediaAttachments: [AttachmentViewModel]
|
||||
@Published public var mediaAttachments: [AttachmentModel]
|
||||
|
||||
public init(
|
||||
id: EntityId,
|
||||
|
@ -62,7 +62,7 @@ public class StatusViewModel: ObservableObject {
|
|||
muted: Bool = false,
|
||||
spoilerText: String? = nil,
|
||||
visibility: Status.Visibility = Status.Visibility.pub,
|
||||
mediaAttachments: [AttachmentViewModel] = [],
|
||||
mediaAttachments: [AttachmentModel] = [],
|
||||
card: PreviewCard? = nil,
|
||||
mentions: [Mention] = [],
|
||||
tags: [Tag] = [],
|
||||
|
@ -126,9 +126,9 @@ public class StatusViewModel: ObservableObject {
|
|||
self.application = orginalStatus.application
|
||||
self.place = orginalStatus.place
|
||||
|
||||
var mediaAttachments: [AttachmentViewModel] = []
|
||||
var mediaAttachments: [AttachmentModel] = []
|
||||
for item in orginalStatus.mediaAttachments {
|
||||
mediaAttachments.append(AttachmentViewModel(attachment: item))
|
||||
mediaAttachments.append(AttachmentModel(attachment: item))
|
||||
}
|
||||
|
||||
self.mediaAttachments = mediaAttachments
|
||||
|
@ -141,7 +141,7 @@ public class StatusViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
public extension StatusViewModel {
|
||||
public extension StatusModel {
|
||||
func getImageWidth() -> Int32? {
|
||||
let highestImage = self.mediaAttachments.getHighestImage()
|
||||
if let width = (highestImage?.meta as? ImageMetadata)?.original?.width {
|
||||
|
@ -162,13 +162,13 @@ public extension StatusViewModel {
|
|||
}
|
||||
|
||||
public extension [Status] {
|
||||
func toStatusViewModel() -> [StatusViewModel] {
|
||||
func toStatusViewModel() -> [StatusModel] {
|
||||
self
|
||||
.sorted(by: { lhs, rhs in
|
||||
lhs.id < rhs.id
|
||||
})
|
||||
.map { status in
|
||||
StatusViewModel(status: status)
|
||||
StatusModel(status: status)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,8 +11,8 @@ public class AccountService {
|
|||
public static let shared = AccountService()
|
||||
private init() { }
|
||||
|
||||
public func account(withId accountId: String, for accountData: AccountData?) async throws -> Account? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func account(withId accountId: String, for account: AccountModel?) async throws -> Account? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,8 @@ public class AccountService {
|
|||
return try await client.account(for: accountId)
|
||||
}
|
||||
|
||||
public func relationships(withId accountId: String, for accountData: AccountData?) async throws -> Relationship? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func relationships(withId accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -30,14 +30,14 @@ public class AccountService {
|
|||
}
|
||||
|
||||
public func statuses(createdBy accountId: String,
|
||||
for accountData: AccountData?,
|
||||
for account: AccountModel?,
|
||||
onlyMedia: Bool = true,
|
||||
excludeReplies: Bool = true,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,8 @@ public class AccountService {
|
|||
limit: limit)
|
||||
}
|
||||
|
||||
public func follow(account accountId: String, for accountData: AccountData?) async throws -> Relationship? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func follow(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -60,8 +60,8 @@ public class AccountService {
|
|||
return try await client.follow(for: accountId)
|
||||
}
|
||||
|
||||
public func unfollow(account accountId: String, for accountData: AccountData?) async throws -> Relationship? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func unfollow(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,8 @@ public class AccountService {
|
|||
return try await client.unfollow(for: accountId)
|
||||
}
|
||||
|
||||
public func mute(account accountId: String, for accountData: AccountData?) async throws -> Relationship? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func mute(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -78,8 +78,8 @@ public class AccountService {
|
|||
return try await client.mute(for: accountId)
|
||||
}
|
||||
|
||||
public func unmute(account accountId: String, for accountData: AccountData?) async throws -> Relationship? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func unmute(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -87,8 +87,8 @@ public class AccountService {
|
|||
return try await client.unmute(for: accountId)
|
||||
}
|
||||
|
||||
public func block(account accountId: String, for accountData: AccountData?) async throws -> Relationship? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func block(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -96,8 +96,8 @@ public class AccountService {
|
|||
return try await client.block(for: accountId)
|
||||
}
|
||||
|
||||
public func unblock(account accountId: String, for accountData: AccountData?) async throws -> Relationship? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func unblock(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,8 @@ public class AccountService {
|
|||
return try await client.unblock(for: accountId)
|
||||
}
|
||||
|
||||
public func followers(account accountId: String, for accountData: AccountData?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func followers(account accountId: String, for account: AccountModel?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
@ -114,8 +114,8 @@ public class AccountService {
|
|||
return try await client.followers(for: accountId, page: page)
|
||||
}
|
||||
|
||||
public func following(account accountId: String, for accountData: AccountData?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func following(account accountId: String, for account: AccountModel?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
@ -123,12 +123,12 @@ public class AccountService {
|
|||
return try await client.following(for: accountId, page: page)
|
||||
}
|
||||
|
||||
public func favourites(for accountData: AccountData?,
|
||||
public func favourites(for account: AccountModel?,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
@ -136,12 +136,12 @@ public class AccountService {
|
|||
return try await client.favourites(maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
|
||||
}
|
||||
|
||||
public func bookmarks(for accountData: AccountData?,
|
||||
public func bookmarks(for account: AccountModel?,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ public class AuthorizationService {
|
|||
}
|
||||
|
||||
/// Sign in to the Pixelfed server.
|
||||
public func sign(in serverAddress: String, session: AuthorizationSession, _ result: @escaping (AccountData?) -> Void) async throws {
|
||||
public func sign(in serverAddress: String, session: AuthorizationSession, _ result: @escaping (AccountData) -> Void) async throws {
|
||||
|
||||
guard let baseUrl = URL(string: serverAddress) else {
|
||||
throw AuthorisationError.badServerUrl
|
||||
|
|
|
@ -13,35 +13,56 @@ public class HomeTimelineService {
|
|||
public static let shared = HomeTimelineService()
|
||||
private init() { }
|
||||
|
||||
public func loadOnBottom(for accountData: AccountData) async throws -> Int {
|
||||
public func loadOnBottom(for account: AccountModel) async throws -> Int {
|
||||
// Load data from API and operate on CoreData on background context.
|
||||
let backgroundContext = CoreDataHandler.shared.newBackgroundContext()
|
||||
|
||||
// Get maximimum downloaded stauts id.
|
||||
let oldestStatus = StatusDataHandler.shared.getMinimumStatus(accountId: accountData.id, viewContext: backgroundContext)
|
||||
let oldestStatus = StatusDataHandler.shared.getMinimumStatus(accountId: account.id, viewContext: backgroundContext)
|
||||
|
||||
guard let oldestStatus = oldestStatus else {
|
||||
return 0
|
||||
}
|
||||
|
||||
let newStatuses = try await self.load(for: accountData, on: backgroundContext, maxId: oldestStatus.id)
|
||||
// Load data on bottom of the list.
|
||||
let newStatuses = try await self.load(for: account, on: backgroundContext, maxId: oldestStatus.id)
|
||||
|
||||
// Save data into database.
|
||||
try backgroundContext.save()
|
||||
|
||||
// Return amount of newly downloaded statuses.
|
||||
return newStatuses.count
|
||||
}
|
||||
|
||||
public func loadOnTop(for accountData: AccountData) async throws {
|
||||
public func loadOnTop(for account: AccountModel) async throws -> String? {
|
||||
// Load data from API and operate on CoreData on background context.
|
||||
let backgroundContext = CoreDataHandler.shared.newBackgroundContext()
|
||||
|
||||
// Refresh/load home timeline (refreshing on top downloads always first 40 items).
|
||||
// TODO: When Apple introduce good way to show new items without scroll to top then we can change that method.
|
||||
try await self.refresh(for: accountData, on: backgroundContext)
|
||||
let lastSeenStatusId = try await self.refresh(for: account, on: backgroundContext)
|
||||
|
||||
// Save data into database.
|
||||
try backgroundContext.save()
|
||||
|
||||
// Return id of last seen status.
|
||||
return lastSeenStatusId
|
||||
}
|
||||
|
||||
public func save(lastSeenStatusId: String, for account: AccountModel) async throws {
|
||||
// Load data from API and operate on CoreData on background context.
|
||||
let backgroundContext = CoreDataHandler.shared.newBackgroundContext()
|
||||
|
||||
// Save information about last seen status.
|
||||
guard let accountDataFromDb = AccountDataHandler.shared.getAccountData(accountId: account.id, viewContext: backgroundContext) else {
|
||||
throw DatabaseError.cannotDownloadAccount
|
||||
}
|
||||
|
||||
accountDataFromDb.lastSeenStatusId = lastSeenStatusId
|
||||
try backgroundContext.save()
|
||||
}
|
||||
|
||||
public func update(status statusData: StatusData, basedOn status: Status, for accountData: AccountData) async throws -> StatusData? {
|
||||
public func update(status statusData: StatusData, basedOn status: Status, for account: AccountModel) async throws -> StatusData? {
|
||||
// Load data from API and operate on CoreData on background context.
|
||||
let backgroundContext = CoreDataHandler.shared.newBackgroundContext()
|
||||
|
||||
|
@ -59,17 +80,18 @@ public class HomeTimelineService {
|
|||
CoreDataHandler.shared.save()
|
||||
}
|
||||
|
||||
private func refresh(for accountData: AccountData, on backgroundContext: NSManagedObjectContext) async throws {
|
||||
guard let accessToken = accountData.accessToken else {
|
||||
return
|
||||
private func refresh(for account: AccountModel, on backgroundContext: NSManagedObjectContext) async throws -> String? {
|
||||
guard let accessToken = account.accessToken else {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Retrieve statuses from API.
|
||||
let client = MastodonClient(baseURL: accountData.serverUrl).getAuthenticated(token: accessToken)
|
||||
let client = MastodonClient(baseURL: account.serverUrl).getAuthenticated(token: accessToken)
|
||||
let statuses = try await client.getHomeTimeline(limit: 40)
|
||||
|
||||
// Retrieve all statuses from database.
|
||||
let dbStatuses = StatusDataHandler.shared.getAllStatuses(accountId: accountData.id)
|
||||
let dbStatuses = StatusDataHandler.shared.getAllStatuses(accountId: account.id)
|
||||
let lastSeenStatusId = dbStatuses.last?.rebloggedStatusId ?? dbStatuses.last?.id
|
||||
|
||||
// Remove statuses that are not in 40 downloaded once.
|
||||
var dbStatusesToRemove: [StatusData] = []
|
||||
|
@ -80,7 +102,7 @@ public class HomeTimelineService {
|
|||
}
|
||||
|
||||
if !dbStatusesToRemove.isEmpty {
|
||||
StatusDataHandler.shared.remove(accountId: accountData.id, statuses: dbStatusesToRemove)
|
||||
StatusDataHandler.shared.remove(accountId: account.id, statuses: dbStatusesToRemove)
|
||||
}
|
||||
|
||||
// Add statuses which are not existing in database, but has been downloaded via API.
|
||||
|
@ -93,32 +115,35 @@ public class HomeTimelineService {
|
|||
|
||||
// Save statuses in database.
|
||||
if !statusesToAdd.isEmpty {
|
||||
_ = try await self.save(statuses: statusesToAdd, for: accountData, on: backgroundContext)
|
||||
_ = try await self.save(statuses: statusesToAdd, for: account, on: backgroundContext)
|
||||
}
|
||||
|
||||
return lastSeenStatusId
|
||||
}
|
||||
|
||||
private func load(for accountData: AccountData,
|
||||
private func load(for account: AccountModel,
|
||||
on backgroundContext: NSManagedObjectContext,
|
||||
minId: String? = nil,
|
||||
maxId: String? = nil
|
||||
) async throws -> [Status] {
|
||||
guard let accessToken = accountData.accessToken else {
|
||||
guard let accessToken = account.accessToken else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
||||
// Retrieve statuses from API.
|
||||
let client = MastodonClient(baseURL: accountData.serverUrl).getAuthenticated(token: accessToken)
|
||||
let client = MastodonClient(baseURL: account.serverUrl).getAuthenticated(token: accessToken)
|
||||
let statuses = try await client.getHomeTimeline(maxId: maxId, minId: minId, limit: 20)
|
||||
|
||||
// Save statuses in database.
|
||||
return try await self.save(statuses: statuses, for: accountData, on: backgroundContext)
|
||||
return try await self.save(statuses: statuses, for: account, on: backgroundContext)
|
||||
}
|
||||
|
||||
private func save(statuses: [Status],
|
||||
for accountData: AccountData,
|
||||
for account: AccountModel,
|
||||
on backgroundContext: NSManagedObjectContext
|
||||
) async throws -> [Status] {
|
||||
guard let dbAccount = AccountDataHandler.shared.getAccountData(accountId: accountData.id, viewContext: backgroundContext) else {
|
||||
|
||||
guard let accountDataFromDb = AccountDataHandler.shared.getAccountData(accountId: account.id, viewContext: backgroundContext) else {
|
||||
throw DatabaseError.cannotDownloadAccount
|
||||
}
|
||||
|
||||
|
@ -129,8 +154,8 @@ public class HomeTimelineService {
|
|||
for status in statusesWithImages {
|
||||
let statusData = StatusDataHandler.shared.createStatusDataEntity(viewContext: backgroundContext)
|
||||
|
||||
statusData.pixelfedAccount = dbAccount
|
||||
dbAccount.addToStatuses(statusData)
|
||||
statusData.pixelfedAccount = accountDataFromDb
|
||||
accountDataFromDb.addToStatuses(statusData)
|
||||
|
||||
self.copy(from: status, to: statusData, on: backgroundContext)
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@ public class NotificationService {
|
|||
public static let shared = NotificationService()
|
||||
private init() { }
|
||||
|
||||
public func notifications(for accountData: AccountData?,
|
||||
public func notifications(for account: AccountModel?,
|
||||
maxId: MaxId? = nil,
|
||||
sinceId: SinceId? = nil,
|
||||
minId: MinId? = nil,
|
||||
limit: Int? = nil
|
||||
) async throws -> Linkable<[MastodonKit.Notification]> {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return Linkable<[MastodonKit.Notification]>(data: [])
|
||||
}
|
||||
|
||||
|
|
|
@ -11,14 +11,14 @@ public class PublicTimelineService {
|
|||
public static let shared = PublicTimelineService()
|
||||
private init() { }
|
||||
|
||||
public func getStatuses(for accountData: AccountData?,
|
||||
public func getStatuses(for account: AccountModel?,
|
||||
local: Bool,
|
||||
remote: Bool,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ public class PublicTimelineService {
|
|||
return try await client.getPublicTimeline(local: local, remote: remote, onlyMedia: true, maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
|
||||
}
|
||||
|
||||
public func getTagStatuses(for accountData: AccountData?,
|
||||
public func getTagStatuses(for account: AccountModel?,
|
||||
tag: String,
|
||||
local: Bool,
|
||||
remote: Bool,
|
||||
|
@ -34,7 +34,7 @@ public class PublicTimelineService {
|
|||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ enum RouteurDestinations: Hashable {
|
|||
|
||||
enum SheetDestinations: Identifiable {
|
||||
case newStatusEditor
|
||||
case replyToStatusEditor(status: StatusViewModel)
|
||||
case replyToStatusEditor(status: StatusModel)
|
||||
case settings
|
||||
|
||||
public var id: String {
|
||||
|
@ -45,14 +45,14 @@ class RouterPath: ObservableObject {
|
|||
path.append(to)
|
||||
}
|
||||
|
||||
public func handle(url: URL, accountData: AccountData? = nil) -> OpenURLAction.Result {
|
||||
public func handle(url: URL, account: AccountModel? = nil) -> OpenURLAction.Result {
|
||||
if url.pathComponents.contains(where: { $0 == "tags" }), let tag = url.pathComponents.last {
|
||||
navigate(to: .tag(hashTag: tag))
|
||||
return .handled
|
||||
} else if url.lastPathComponent.first == "@", let host = url.host {
|
||||
let acct = "\(url.lastPathComponent)@\(host)"
|
||||
Task {
|
||||
await navigateToAccountFrom(acct: acct, url: url, accountData: accountData)
|
||||
await navigateToAccountFrom(acct: acct, url: url, account: account)
|
||||
}
|
||||
|
||||
return .handled
|
||||
|
@ -61,16 +61,18 @@ class RouterPath: ObservableObject {
|
|||
return urlHandler?(url) ?? .systemAction
|
||||
}
|
||||
|
||||
public func navigateToAccountFrom(acct: String, url: URL, accountData: AccountData? = nil) async {
|
||||
guard let accountData else { return }
|
||||
public func navigateToAccountFrom(acct: String, url: URL, account: AccountModel? = nil) async {
|
||||
guard let account else { return }
|
||||
|
||||
Task {
|
||||
let results = try? await SearchService.shared.search(for: accountData,
|
||||
let results = try? await SearchService.shared.search(for: account,
|
||||
query: acct,
|
||||
resultsType: Mastodon.Search.ResultsType.accounts)
|
||||
|
||||
if let account = results?.accounts.first {
|
||||
navigate(to: .userProfile(accountId: account.id, accountDisplayName: account.displayNameWithoutEmojis, accountUserName: account.acct))
|
||||
if let accountFromApi = results?.accounts.first {
|
||||
navigate(to: .userProfile(accountId: accountFromApi.id,
|
||||
accountDisplayName: accountFromApi.displayNameWithoutEmojis,
|
||||
accountUserName: accountFromApi.acct))
|
||||
} else {
|
||||
await UIApplication.shared.open(url)
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ public class SearchService {
|
|||
public static let shared = SearchService()
|
||||
private init() { }
|
||||
|
||||
public func search(for accountData: AccountData?,
|
||||
public func search(for account: AccountModel?,
|
||||
query: String,
|
||||
resultsType: Mastodon.Search.ResultsType) async throws -> SearchResults? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ public class StatusService {
|
|||
public static let shared = StatusService()
|
||||
private init() { }
|
||||
|
||||
public func status(withId statusId: String, for accountData: AccountData?) async throws -> Status? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func status(withId statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,8 @@ public class StatusService {
|
|||
return try await client.status(statusId: statusId)
|
||||
}
|
||||
|
||||
func favourite(statusId: String, for accountData: AccountData?) async throws -> Status? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
func favourite(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,8 @@ public class StatusService {
|
|||
return try await client.favourite(statusId: statusId)
|
||||
}
|
||||
|
||||
func unfavourite(statusId: String, for accountData: AccountData?) async throws -> Status? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
func unfavourite(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,8 @@ public class StatusService {
|
|||
return try await client.unfavourite(statusId: statusId)
|
||||
}
|
||||
|
||||
func boost(statusId: String, for accountData: AccountData?) async throws -> Status? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
func boost(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -47,8 +47,8 @@ public class StatusService {
|
|||
return try await client.boost(statusId: statusId)
|
||||
}
|
||||
|
||||
func unboost(statusId: String, for accountData: AccountData?) async throws -> Status? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
func unboost(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -56,8 +56,8 @@ public class StatusService {
|
|||
return try await client.unboost(statusId: statusId)
|
||||
}
|
||||
|
||||
func bookmark(statusId: String, for accountData: AccountData?) async throws -> Status? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
func bookmark(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -65,8 +65,8 @@ public class StatusService {
|
|||
return try await client.bookmark(statusId: statusId)
|
||||
}
|
||||
|
||||
func unbookmark(statusId: String, for accountData: AccountData?) async throws -> Status? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
func unbookmark(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -74,8 +74,8 @@ public class StatusService {
|
|||
return try await client.unbookmark(statusId: statusId)
|
||||
}
|
||||
|
||||
func new(status: Mastodon.Statuses.Components, for accountData: AccountData?) async throws -> Status? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
func new(status: Mastodon.Statuses.Components, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -83,17 +83,17 @@ public class StatusService {
|
|||
return try await client.new(statusComponents: status)
|
||||
}
|
||||
|
||||
func comments(to statusId: String, for accountData: AccountData) async throws -> [CommentViewModel] {
|
||||
var commentViewModels: [CommentViewModel] = []
|
||||
func comments(to statusId: String, for account: AccountModel) async throws -> [CommentModel] {
|
||||
var commentViewModels: [CommentModel] = []
|
||||
|
||||
let client = MastodonClient(baseURL: accountData.serverUrl).getAuthenticated(token: accountData.accessToken ?? String.empty())
|
||||
let client = MastodonClient(baseURL: account.serverUrl).getAuthenticated(token: account.accessToken ?? String.empty())
|
||||
try await self.getCommentDescendants(to: statusId, client: client, showDivider: true, to: &commentViewModels)
|
||||
|
||||
return commentViewModels
|
||||
}
|
||||
|
||||
public func favouritedBy(statusId: String, for accountData: AccountData?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func favouritedBy(statusId: String, for account: AccountModel?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
@ -101,8 +101,8 @@ public class StatusService {
|
|||
return try await client.favouritedBy(for: statusId, page: page)
|
||||
}
|
||||
|
||||
public func rebloggedBy(statusId: String, for accountData: AccountData?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func rebloggedBy(statusId: String, for account: AccountModel?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
@ -110,12 +110,12 @@ public class StatusService {
|
|||
return try await client.rebloggedBy(for: statusId, page: page)
|
||||
}
|
||||
|
||||
private func getCommentDescendants(to statusId: String, client: MastodonClientAuthenticated, showDivider: Bool, to commentViewModels: inout [CommentViewModel]) async throws {
|
||||
private func getCommentDescendants(to statusId: String, client: MastodonClientAuthenticated, showDivider: Bool, to commentViewModels: inout [CommentModel]) async throws {
|
||||
let context = try await client.getContext(for: statusId)
|
||||
|
||||
let descendants = context.descendants.toStatusViewModel()
|
||||
for status in descendants {
|
||||
commentViewModels.append(CommentViewModel(status: status, showDivider: showDivider))
|
||||
commentViewModels.append(CommentModel(status: status, showDivider: showDivider))
|
||||
|
||||
if status.repliesCount > 0 {
|
||||
try await self.getCommentDescendants(to: status.id, client: client, showDivider: false, to: &commentViewModels)
|
||||
|
|
|
@ -11,8 +11,8 @@ public class TagsService {
|
|||
public static let shared = TagsService()
|
||||
private init() { }
|
||||
|
||||
public func get(tag: String, for accountData: AccountData?) async throws -> Tag? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func get(tag: String, for account: AccountModel?) async throws -> Tag? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,8 @@ public class TagsService {
|
|||
return try await client.tag(hashtag: tag)
|
||||
}
|
||||
|
||||
public func follow(tag: String, for accountData: AccountData?) async throws -> Tag? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func follow(tag: String, for account: AccountModel?) async throws -> Tag? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,8 @@ public class TagsService {
|
|||
return try await client.follow(hashtag: tag)
|
||||
}
|
||||
|
||||
public func unfollow(tag: String, for accountData: AccountData?) async throws -> Tag? {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
public func unfollow(tag: String, for account: AccountModel?) async throws -> Tag? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ public class TrendsService {
|
|||
public static let shared = TrendsService()
|
||||
private init() { }
|
||||
|
||||
public func statuses(for accountData: AccountData?,
|
||||
public func statuses(for account: AccountModel?,
|
||||
range: Mastodon.PixelfedTrends.TrendRange) async throws -> [Status] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>_XCCurrentVersionName</key>
|
||||
<string>Vernissage.xcdatamodel</string>
|
||||
<string>Vernissage-001.xcdatamodel</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="22C65" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="AccountData" representedClassName="AccountData" syncable="YES">
|
||||
<attribute name="accessToken" optional="YES" attributeType="String"/>
|
||||
<attribute name="acct" attributeType="String"/>
|
||||
<attribute name="avatar" optional="YES" attributeType="URI"/>
|
||||
<attribute name="avatarData" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="clientId" attributeType="String"/>
|
||||
<attribute name="clientSecret" attributeType="String"/>
|
||||
<attribute name="clientVapidKey" attributeType="String"/>
|
||||
<attribute name="createdAt" attributeType="String"/>
|
||||
<attribute name="displayName" optional="YES" attributeType="String"/>
|
||||
<attribute name="followersCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="followingCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="header" optional="YES" attributeType="URI"/>
|
||||
<attribute name="id" attributeType="String"/>
|
||||
<attribute name="lastSeenStatusId" optional="YES" attributeType="String"/>
|
||||
<attribute name="locked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="note" optional="YES" attributeType="String"/>
|
||||
<attribute name="refreshToken" optional="YES" attributeType="String"/>
|
||||
<attribute name="serverUrl" attributeType="URI"/>
|
||||
<attribute name="statusesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="url" optional="YES" attributeType="URI"/>
|
||||
<attribute name="username" attributeType="String"/>
|
||||
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="StatusData" inverseName="pixelfedAccount" inverseEntity="StatusData"/>
|
||||
</entity>
|
||||
<entity name="ApplicationSettings" representedClassName="ApplicationSettings" syncable="YES">
|
||||
<attribute name="avatarShape" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
|
||||
<attribute name="currentAccount" optional="YES" attributeType="String"/>
|
||||
<attribute name="theme" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="tintColor" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
|
||||
</entity>
|
||||
<entity name="AttachmentData" representedClassName="AttachmentData" syncable="YES">
|
||||
<attribute name="blurhash" optional="YES" attributeType="String"/>
|
||||
<attribute name="data" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES"/>
|
||||
<attribute name="exifCamera" optional="YES" attributeType="String"/>
|
||||
<attribute name="exifCreatedDate" optional="YES" attributeType="String"/>
|
||||
<attribute name="exifExposure" optional="YES" attributeType="String"/>
|
||||
<attribute name="exifLens" optional="YES" attributeType="String"/>
|
||||
<attribute name="id" attributeType="String"/>
|
||||
<attribute name="metaImageHeight" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="metaImageWidth" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="previewUrl" optional="YES" attributeType="URI"/>
|
||||
<attribute name="remoteUrl" optional="YES" attributeType="URI"/>
|
||||
<attribute name="statusId" attributeType="String"/>
|
||||
<attribute name="text" optional="YES" attributeType="String"/>
|
||||
<attribute name="type" attributeType="String"/>
|
||||
<attribute name="url" attributeType="URI"/>
|
||||
<relationship name="statusRelation" maxCount="1" deletionRule="Nullify" destinationEntity="StatusData" inverseName="attachmentsRelation" inverseEntity="StatusData"/>
|
||||
</entity>
|
||||
<entity name="StatusData" representedClassName="StatusData" syncable="YES">
|
||||
<attribute name="accountAvatar" optional="YES" attributeType="URI"/>
|
||||
<attribute name="accountDisplayName" optional="YES" attributeType="String"/>
|
||||
<attribute name="accountId" attributeType="String"/>
|
||||
<attribute name="accountUsername" optional="YES" attributeType="String"/>
|
||||
<attribute name="applicationName" optional="YES" attributeType="String"/>
|
||||
<attribute name="applicationWebsite" optional="YES" attributeType="URI"/>
|
||||
<attribute name="bookmarked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="content" attributeType="String"/>
|
||||
<attribute name="createdAt" attributeType="String"/>
|
||||
<attribute name="favourited" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="favouritesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="id" attributeType="String"/>
|
||||
<attribute name="inReplyToAccount" optional="YES" attributeType="String"/>
|
||||
<attribute name="inReplyToId" optional="YES" attributeType="String"/>
|
||||
<attribute name="muted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="pinned" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="reblogged" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="rebloggedAccountAvatar" optional="YES" attributeType="URI"/>
|
||||
<attribute name="rebloggedAccountDisplayName" optional="YES" attributeType="String"/>
|
||||
<attribute name="rebloggedAccountId" optional="YES" attributeType="String"/>
|
||||
<attribute name="rebloggedAccountUsername" optional="YES" attributeType="String"/>
|
||||
<attribute name="rebloggedStatusId" optional="YES" attributeType="String"/>
|
||||
<attribute name="reblogsCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="repliesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="sensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="spoilerText" optional="YES" attributeType="String"/>
|
||||
<attribute name="uri" attributeType="String"/>
|
||||
<attribute name="url" optional="YES" attributeType="URI"/>
|
||||
<attribute name="visibility" attributeType="String"/>
|
||||
<relationship name="attachmentsRelation" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AttachmentData" inverseName="statusRelation" inverseEntity="AttachmentData"/>
|
||||
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="statuses" inverseEntity="AccountData"/>
|
||||
</entity>
|
||||
</model>
|
|
@ -65,7 +65,8 @@ struct VernissageApp: App {
|
|||
}
|
||||
|
||||
Task { @MainActor in
|
||||
self.applicationState.accountData = accountData
|
||||
self.applicationState.account = AccountModel(accountData: accountData)
|
||||
self.applicationState.lastSeenStatusId = accountData.lastSeenStatusId
|
||||
self.applicationViewMode = .mainView
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
public extension View {
|
||||
func onFirstAppear(_ action: @escaping () async -> ()) -> some View {
|
||||
modifier(FirstAppear(action: action))
|
||||
}
|
||||
}
|
||||
|
||||
private struct FirstAppear: ViewModifier {
|
||||
let action: () async -> ()
|
||||
@State private var hasAppeared = false
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content.task {
|
||||
guard !hasAppeared else { return }
|
||||
hasAppeared = true
|
||||
|
||||
await action()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,11 +70,7 @@ struct AccountsView: View {
|
|||
}
|
||||
.navigationBarTitle(self.getTitle())
|
||||
.listStyle(.plain)
|
||||
.task {
|
||||
if self.accounts.isEmpty == false {
|
||||
return
|
||||
}
|
||||
|
||||
.onFirstAppear {
|
||||
await self.loadAccounts(page: self.page)
|
||||
}
|
||||
}
|
||||
|
@ -113,22 +109,22 @@ struct AccountsView: View {
|
|||
case .followers:
|
||||
return try await AccountService.shared.followers(
|
||||
account: self.entityId,
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
page: page)
|
||||
case .following:
|
||||
return try await AccountService.shared.following(
|
||||
account: self.entityId,
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
page: page)
|
||||
case .favourited:
|
||||
return try await StatusService.shared.favouritedBy(
|
||||
statusId: self.entityId,
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
page: page)
|
||||
case .reblogged:
|
||||
return try await StatusService.shared.rebloggedBy(
|
||||
statusId: self.entityId,
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
page: page)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ struct ComposeView: View {
|
|||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@State var statusViewModel: StatusViewModel?
|
||||
@State var statusViewModel: StatusModel?
|
||||
@State private var text = String.empty()
|
||||
|
||||
@FocusState private var focusedField: FocusField?
|
||||
|
@ -26,7 +26,7 @@ struct ComposeView: View {
|
|||
NavigationView {
|
||||
ScrollView {
|
||||
VStack (alignment: .leading){
|
||||
if let accountData = applicationState.accountData {
|
||||
if let accountData = applicationState.account {
|
||||
HStack {
|
||||
UsernameRow(
|
||||
accountId: accountData.id,
|
||||
|
@ -102,7 +102,7 @@ struct ComposeView: View {
|
|||
do {
|
||||
_ = try await StatusService.shared.new(
|
||||
status: Mastodon.Statuses.Components(inReplyToId: self.statusViewModel?.id, text: self.text),
|
||||
for: self.applicationState.accountData)
|
||||
for: self.applicationState.account)
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during post status.", showToastr: true)
|
||||
}
|
||||
|
|
|
@ -29,6 +29,11 @@ struct HomeFeedView: View {
|
|||
ScrollView {
|
||||
LazyVGrid(columns: gridColumns) {
|
||||
ForEach(dbStatuses, id: \.self) { item in
|
||||
|
||||
if self.shouldUpToDateBeVisible(statusId: item.id) {
|
||||
self.upToDatePlaceholder()
|
||||
}
|
||||
|
||||
NavigationLink(value: RouteurDestinations.status(
|
||||
id: item.rebloggedStatusId ?? item.id,
|
||||
blurhash: item.attachments().first?.blurhash,
|
||||
|
@ -45,8 +50,8 @@ struct HomeFeedView: View {
|
|||
LoadingIndicator()
|
||||
.task {
|
||||
do {
|
||||
if let accountData = self.applicationState.accountData {
|
||||
let newStatusesCount = try await HomeTimelineService.shared.loadOnBottom(for: accountData)
|
||||
if let account = self.applicationState.account {
|
||||
let newStatusesCount = try await HomeTimelineService.shared.loadOnBottom(for: account)
|
||||
if newStatusesCount == 0 {
|
||||
allItemsBottomLoaded = true
|
||||
}
|
||||
|
@ -75,8 +80,11 @@ struct HomeFeedView: View {
|
|||
}
|
||||
.refreshable {
|
||||
do {
|
||||
if let accountData = self.applicationState.accountData {
|
||||
try await HomeTimelineService.shared.loadOnTop(for: accountData)
|
||||
if let account = self.applicationState.account {
|
||||
if let lastSeenStatusId = try await HomeTimelineService.shared.loadOnTop(for: account) {
|
||||
try await HomeTimelineService.shared.save(lastSeenStatusId: lastSeenStatusId, for: account)
|
||||
self.applicationState.lastSeenStatusId = lastSeenStatusId
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
print("Error", error)
|
||||
|
@ -94,12 +102,33 @@ struct HomeFeedView: View {
|
|||
return
|
||||
}
|
||||
|
||||
if let accountData = self.applicationState.accountData {
|
||||
try await HomeTimelineService.shared.loadOnTop(for: accountData)
|
||||
if let account = self.applicationState.account {
|
||||
_ = try await HomeTimelineService.shared.loadOnTop(for: account)
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during download statuses from server.", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func shouldUpToDateBeVisible(statusId: String) -> Bool {
|
||||
return self.applicationState.lastSeenStatusId != dbStatuses.first?.id && self.applicationState.lastSeenStatusId == statusId
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func upToDatePlaceholder() -> some View {
|
||||
VStack(alignment: .center) {
|
||||
Image(systemName: "checkmark.seal")
|
||||
.resizable()
|
||||
.frame(width: 64, height: 64)
|
||||
.fontWeight(.ultraLight)
|
||||
.foregroundColor(.accentColor.opacity(0.6))
|
||||
Text("You're all caught up")
|
||||
.font(.title2)
|
||||
.fontWeight(.thin)
|
||||
.foregroundColor(Color.mainTextColor.opacity(0.6))
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width * 0.75)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,28 +47,28 @@ struct MainView: View {
|
|||
private func getMainView() -> some View {
|
||||
switch self.viewMode {
|
||||
case .home:
|
||||
HomeFeedView(accountId: applicationState.accountData?.id ?? String.empty())
|
||||
.id(applicationState.accountData?.id ?? String.empty())
|
||||
HomeFeedView(accountId: applicationState.account?.id ?? String.empty())
|
||||
.id(applicationState.account?.id ?? String.empty())
|
||||
case .trending:
|
||||
TrendStatusesView(accountId: applicationState.accountData?.id ?? String.empty())
|
||||
.id(applicationState.accountData?.id ?? String.empty())
|
||||
TrendStatusesView(accountId: applicationState.account?.id ?? String.empty())
|
||||
.id(applicationState.account?.id ?? String.empty())
|
||||
case .local:
|
||||
StatusesView(listType: .local)
|
||||
.id(applicationState.accountData?.id ?? String.empty())
|
||||
.id(applicationState.account?.id ?? String.empty())
|
||||
case .federated:
|
||||
StatusesView(listType: .federated)
|
||||
.id(applicationState.accountData?.id ?? String.empty())
|
||||
.id(applicationState.account?.id ?? String.empty())
|
||||
case .profile:
|
||||
if let accountData = self.applicationState.accountData {
|
||||
if let accountData = self.applicationState.account {
|
||||
UserProfileView(accountId: accountData.id,
|
||||
accountDisplayName: accountData.displayName,
|
||||
accountUserName: accountData.acct)
|
||||
.id(applicationState.accountData?.id ?? String.empty())
|
||||
.id(applicationState.account?.id ?? String.empty())
|
||||
}
|
||||
case .notifications:
|
||||
if let accountData = self.applicationState.accountData {
|
||||
if let accountData = self.applicationState.account {
|
||||
NotificationsView(accountId: accountData.id)
|
||||
.id(applicationState.accountData?.id ?? String.empty())
|
||||
.id(applicationState.account?.id ?? String.empty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,11 +151,12 @@ struct MainView: View {
|
|||
Menu {
|
||||
ForEach(self.dbAccounts) { account in
|
||||
Button {
|
||||
self.applicationState.accountData = account
|
||||
self.applicationState.account = AccountModel(accountData: account)
|
||||
self.applicationState.lastSeenStatusId = account.lastSeenStatusId
|
||||
|
||||
ApplicationSettingsHandler.shared.setAccountAsDefault(accountData: account)
|
||||
} label: {
|
||||
if self.applicationState.accountData?.id == account.id {
|
||||
if self.applicationState.account?.id == account.id {
|
||||
Label(account.displayName ?? account.acct, systemImage: "checkmark")
|
||||
} else {
|
||||
Text(account.displayName ?? account.acct)
|
||||
|
@ -171,7 +172,7 @@ struct MainView: View {
|
|||
Label("Settings", systemImage: "gear")
|
||||
}
|
||||
} label: {
|
||||
if let avatarData = self.applicationState.accountData?.avatarData, let uiImage = UIImage(data: avatarData) {
|
||||
if let avatarData = self.applicationState.account?.avatarData, let uiImage = UIImage(data: avatarData) {
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.clipShape(self.applicationState.avatarShape.shape())
|
||||
|
|
|
@ -57,11 +57,7 @@ struct NotificationsView: View {
|
|||
.refreshable {
|
||||
await self.loadNewNotifications()
|
||||
}
|
||||
.task {
|
||||
if self.notifications.isEmpty == false {
|
||||
return
|
||||
}
|
||||
|
||||
.onFirstAppear {
|
||||
await self.loadNotifications()
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +65,7 @@ struct NotificationsView: View {
|
|||
func loadNotifications() async {
|
||||
do {
|
||||
let linkable = try await NotificationService.shared.notifications(
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
maxId: maxId,
|
||||
minId: minId,
|
||||
limit: 5)
|
||||
|
@ -91,7 +87,7 @@ struct NotificationsView: View {
|
|||
private func loadMoreNotifications() async {
|
||||
do {
|
||||
let linkable = try await NotificationService.shared.notifications(
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
maxId: self.maxId,
|
||||
limit: self.defaultPageSize)
|
||||
|
||||
|
@ -109,7 +105,7 @@ struct NotificationsView: View {
|
|||
private func loadNewNotifications() async {
|
||||
do {
|
||||
let linkable = try await NotificationService.shared.notifications(
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
minId: self.minId,
|
||||
limit: self.defaultPageSize)
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ struct SignInView: View {
|
|||
try await AuthorizationService.shared.sign(in: self.getServerAddress(),
|
||||
session: authorizationSession) { accountData in
|
||||
DispatchQueue.main.async {
|
||||
self.applicationState.accountData = accountData
|
||||
self.applicationState.account = AccountModel(accountData: accountData)
|
||||
onSignInStateChenge?(.mainView)
|
||||
dismiss()
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ struct StatusView: View {
|
|||
@State private var showImageViewer = false
|
||||
@State private var firstLoadFinished = false
|
||||
|
||||
@State private var statusViewModel: StatusViewModel?
|
||||
@State private var statusViewModel: StatusModel?
|
||||
|
||||
@State private var selectedAttachmentId: String?
|
||||
@State private var exifCamera: String?
|
||||
|
@ -62,7 +62,7 @@ struct StatusView: View {
|
|||
|
||||
MarkdownFormattedText(statusViewModel.content.asMarkdown)
|
||||
.environment(\.openURL, OpenURLAction { url in
|
||||
routerPath.handle(url: url, accountData: self.applicationState.accountData)
|
||||
routerPath.handle(url: url, account: self.applicationState.account)
|
||||
})
|
||||
|
||||
VStack (alignment: .leading) {
|
||||
|
@ -114,21 +114,21 @@ struct StatusView: View {
|
|||
}
|
||||
|
||||
// Get status from API.
|
||||
if let status = try await StatusService.shared.status(withId: self.statusId, for: self.applicationState.accountData) {
|
||||
let statusViewModel = StatusViewModel(status: status)
|
||||
if let status = try await StatusService.shared.status(withId: self.statusId, for: self.applicationState.account) {
|
||||
let statusViewModel = StatusModel(status: status)
|
||||
|
||||
self.statusViewModel = statusViewModel
|
||||
self.selectedAttachmentId = statusViewModel.mediaAttachments.first?.id ?? String.empty()
|
||||
self.firstLoadFinished = true
|
||||
|
||||
// If we have status in database then we can update data.
|
||||
if let accountData = self.applicationState.accountData,
|
||||
if let accountData = self.applicationState.account,
|
||||
let statusDataFromDatabase = StatusDataHandler.shared.getStatusData(accountId: accountData.id, statusId: self.statusId) {
|
||||
_ = try await HomeTimelineService.shared.update(status: statusDataFromDatabase, basedOn: status, for: accountData)
|
||||
}
|
||||
}
|
||||
} catch NetworkError.notSuccessResponse(let response) {
|
||||
if response.statusCode() == HTTPStatusCode.notFound, let accountId = self.applicationState.accountData?.id {
|
||||
if response.statusCode() == HTTPStatusCode.notFound, let accountId = self.applicationState.account?.id {
|
||||
StatusDataHandler.shared.remove(accountId: accountId, statusId: self.statusId)
|
||||
ErrorService.shared.handle(NetworkError.notSuccessResponse(response), message: "Status not existing anymore.", showToastr: true)
|
||||
dismiss()
|
||||
|
|
|
@ -25,7 +25,7 @@ struct StatusesView: View {
|
|||
@State private var firstLoadFinished = false
|
||||
|
||||
@State private var tag: Tag?
|
||||
@State private var statusViewModels: [StatusViewModel] = []
|
||||
@State private var statusViewModels: [StatusModel] = []
|
||||
private let defaultLimit = 20
|
||||
|
||||
var body: some View {
|
||||
|
@ -82,7 +82,7 @@ struct StatusesView: View {
|
|||
// TODO: It seems like pixelfed is not supporting the endpoints.
|
||||
// self.getTrailingToolbar()
|
||||
}
|
||||
.task {
|
||||
.onFirstAppear {
|
||||
do {
|
||||
try await self.loadStatuses()
|
||||
|
||||
|
@ -107,10 +107,10 @@ struct StatusesView: View {
|
|||
}
|
||||
|
||||
let statuses = try await self.loadFromApi()
|
||||
var inPlaceStatuses: [StatusViewModel] = []
|
||||
var inPlaceStatuses: [StatusModel] = []
|
||||
|
||||
for item in statuses.getStatusesWithImagesOnly() {
|
||||
inPlaceStatuses.append(StatusViewModel(status: item))
|
||||
inPlaceStatuses.append(StatusModel(status: item))
|
||||
}
|
||||
|
||||
self.firstLoadFinished = true
|
||||
|
@ -129,9 +129,9 @@ struct StatusesView: View {
|
|||
self.allItemsLoaded = true
|
||||
}
|
||||
|
||||
var inPlaceStatuses: [StatusViewModel] = []
|
||||
var inPlaceStatuses: [StatusModel] = []
|
||||
for item in previousStatuses.getStatusesWithImagesOnly() {
|
||||
inPlaceStatuses.append(StatusViewModel(status: item))
|
||||
inPlaceStatuses.append(StatusModel(status: item))
|
||||
}
|
||||
|
||||
self.statusViewModels.append(contentsOf: inPlaceStatuses)
|
||||
|
@ -142,9 +142,9 @@ struct StatusesView: View {
|
|||
if let firstStatusId = self.statusViewModels.first?.id {
|
||||
let newestStatuses = try await self.loadFromApi(sinceId: firstStatusId)
|
||||
|
||||
var inPlaceStatuses: [StatusViewModel] = []
|
||||
var inPlaceStatuses: [StatusModel] = []
|
||||
for item in newestStatuses.getStatusesWithImagesOnly() {
|
||||
inPlaceStatuses.append(StatusViewModel(status: item))
|
||||
inPlaceStatuses.append(StatusModel(status: item))
|
||||
}
|
||||
|
||||
self.statusViewModels.insert(contentsOf: inPlaceStatuses, at: 0)
|
||||
|
@ -155,7 +155,7 @@ struct StatusesView: View {
|
|||
switch self.listType {
|
||||
case .local:
|
||||
return try await PublicTimelineService.shared.getStatuses(
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
local: true,
|
||||
remote: false,
|
||||
maxId: maxId,
|
||||
|
@ -164,7 +164,7 @@ struct StatusesView: View {
|
|||
limit: self.defaultLimit)
|
||||
case .federated:
|
||||
return try await PublicTimelineService.shared.getStatuses(
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
local: false,
|
||||
remote: true,
|
||||
maxId: maxId,
|
||||
|
@ -173,21 +173,21 @@ struct StatusesView: View {
|
|||
limit: self.defaultLimit)
|
||||
case .favourites:
|
||||
return try await AccountService.shared.favourites(
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
case .bookmarks:
|
||||
return try await AccountService.shared.bookmarks(
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
case .hashtag(let tag):
|
||||
return try await PublicTimelineService.shared.getTagStatuses(
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
tag: tag,
|
||||
local: false,
|
||||
remote: true,
|
||||
|
@ -235,7 +235,7 @@ struct StatusesView: View {
|
|||
|
||||
private func loadTag(hashtag: String) async {
|
||||
do {
|
||||
self.tag = try await TagsService.shared.get(tag: hashtag, for: self.applicationState.accountData)
|
||||
self.tag = try await TagsService.shared.get(tag: hashtag, for: self.applicationState.account)
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during loading tag from server.", showToastr: false)
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ struct StatusesView: View {
|
|||
|
||||
private func follow(hashtag: String) async {
|
||||
do {
|
||||
self.tag = try await TagsService.shared.follow(tag: hashtag, for: self.applicationState.accountData)
|
||||
self.tag = try await TagsService.shared.follow(tag: hashtag, for: self.applicationState.account)
|
||||
ToastrService.shared.showSuccess("You are following the tag.", imageSystemName: "number.square.fill")
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during following tag.", showToastr: true)
|
||||
|
@ -252,7 +252,7 @@ struct StatusesView: View {
|
|||
|
||||
private func unfollow(hashtag: String) async {
|
||||
do {
|
||||
self.tag = try await TagsService.shared.unfollow(tag: hashtag, for: self.applicationState.accountData)
|
||||
self.tag = try await TagsService.shared.unfollow(tag: hashtag, for: self.applicationState.account)
|
||||
ToastrService.shared.showSuccess("Tag has been unfollowed.", imageSystemName: "number.square")
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during unfollowing tag.", showToastr: true)
|
||||
|
|
|
@ -15,7 +15,7 @@ struct TrendStatusesView: View {
|
|||
@State private var firstLoadFinished = false
|
||||
@State private var tabSelectedValue: Mastodon.PixelfedTrends.TrendRange = .daily
|
||||
|
||||
@State private var statusViewModels: [StatusViewModel] = []
|
||||
@State private var statusViewModels: [StatusModel] = []
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
|
@ -73,7 +73,7 @@ struct TrendStatusesView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.task {
|
||||
.onFirstAppear {
|
||||
do {
|
||||
try await self.loadStatuses()
|
||||
} catch {
|
||||
|
@ -94,13 +94,13 @@ struct TrendStatusesView: View {
|
|||
}
|
||||
|
||||
let statuses = try await TrendsService.shared.statuses(
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
range: tabSelectedValue)
|
||||
|
||||
var inPlaceStatuses: [StatusViewModel] = []
|
||||
var inPlaceStatuses: [StatusModel] = []
|
||||
|
||||
for item in statuses.getStatusesWithImagesOnly() {
|
||||
inPlaceStatuses.append(StatusViewModel(status: item))
|
||||
inPlaceStatuses.append(StatusModel(status: item))
|
||||
}
|
||||
|
||||
self.statusViewModels = inPlaceStatuses
|
||||
|
|
|
@ -33,7 +33,7 @@ struct UserProfileView: View {
|
|||
.navigationBarTitle(self.accountDisplayName ?? self.accountUserName)
|
||||
.toolbar {
|
||||
if let account = self.account {
|
||||
if self.applicationState.accountData?.id != account.id {
|
||||
if self.applicationState.account?.id != account.id {
|
||||
self.getTrailingAccountToolbar(account: account)
|
||||
} else {
|
||||
self.getTrailingProfileToolbar(account: account)
|
||||
|
@ -54,8 +54,8 @@ struct UserProfileView: View {
|
|||
return
|
||||
}
|
||||
|
||||
async let relationshipTask = AccountService.shared.relationships(withId: self.accountId, for: self.applicationState.accountData)
|
||||
async let accountTask = AccountService.shared.account(withId: self.accountId, for: self.applicationState.accountData)
|
||||
async let relationshipTask = AccountService.shared.relationships(withId: self.accountId, for: self.applicationState.account)
|
||||
async let accountTask = AccountService.shared.account(withId: self.accountId, for: self.applicationState.account)
|
||||
|
||||
// Wait for download account and relationships.
|
||||
self.firstLoadFinished = true
|
||||
|
@ -148,14 +148,14 @@ struct UserProfileView: View {
|
|||
if self.relationship?.muting == true {
|
||||
if let relationship = try await AccountService.shared.unmute(
|
||||
account: account.id,
|
||||
for: self.applicationState.accountData
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
} else {
|
||||
if let relationship = try await AccountService.shared.mute(
|
||||
account: account.id,
|
||||
for: self.applicationState.accountData
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
|
@ -170,14 +170,14 @@ struct UserProfileView: View {
|
|||
if self.relationship?.blocking == true {
|
||||
if let relationship = try await AccountService.shared.unblock(
|
||||
account: account.id,
|
||||
for: self.applicationState.accountData
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
} else {
|
||||
if let relationship = try await AccountService.shared.block(
|
||||
account: account.id,
|
||||
for: self.applicationState.accountData
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
import SwiftUI
|
||||
|
||||
struct ImageCarouselPicture: View {
|
||||
@ObservedObject public var attachment: AttachmentViewModel
|
||||
@ObservedObject public var attachment: AttachmentModel
|
||||
|
||||
private let onImageDownloaded: (AttachmentViewModel, Data) -> Void
|
||||
private let onImageDownloaded: (AttachmentModel, Data) -> Void
|
||||
|
||||
init(attachment: AttachmentViewModel, onImageDownloaded: @escaping (_: AttachmentViewModel, _: Data) -> Void) {
|
||||
init(attachment: AttachmentModel, onImageDownloaded: @escaping (_: AttachmentModel, _: Data) -> Void) {
|
||||
self.attachment = attachment
|
||||
self.onImageDownloaded = onImageDownloaded
|
||||
}
|
||||
|
|
|
@ -9,13 +9,13 @@ import MastodonKit
|
|||
import NukeUI
|
||||
|
||||
struct ImageRowAsync: View {
|
||||
@State public var statusViewModel: StatusViewModel
|
||||
@State public var statusViewModel: StatusModel
|
||||
|
||||
@State private var imageHeight: Double
|
||||
@State private var imageWidth: Double
|
||||
@State private var heightWasPrecalculated: Bool
|
||||
|
||||
init(statusViewModel: StatusViewModel) {
|
||||
init(statusViewModel: StatusModel) {
|
||||
self.statusViewModel = statusViewModel
|
||||
|
||||
// Calculate size of frame (first from cache, then from metadata).
|
||||
|
|
|
@ -8,7 +8,7 @@ import SwiftUI
|
|||
import MastodonKit
|
||||
|
||||
struct ImagesCarousel: View {
|
||||
@State public var attachments: [AttachmentViewModel]
|
||||
@State public var attachments: [AttachmentModel]
|
||||
@State private var imageHeight: Double
|
||||
@State private var imageWidth: Double
|
||||
@State private var selected: String
|
||||
|
@ -20,7 +20,7 @@ struct ImagesCarousel: View {
|
|||
@Binding public var exifCreatedDate: String?
|
||||
@Binding public var exifLens: String?
|
||||
|
||||
init(attachments: [AttachmentViewModel],
|
||||
init(attachments: [AttachmentModel],
|
||||
selectedAttachmentId: Binding<String?>,
|
||||
exifCamera: Binding<String?>,
|
||||
exifExposure: Binding<String?>,
|
||||
|
@ -92,7 +92,7 @@ struct ImagesCarousel: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func recalculateImageHeight(attachment: AttachmentViewModel, imageData: Data) {
|
||||
private func recalculateImageHeight(attachment: AttachmentModel, imageData: Data) {
|
||||
guard heightWasPrecalculated == false else {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import SwiftUI
|
||||
|
||||
struct ImagesViewer: View {
|
||||
@State var statusViewModel: StatusViewModel
|
||||
@State var statusViewModel: StatusModel
|
||||
@State var selectedAttachmentId: String = String.empty()
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ struct InteractionRow: View {
|
|||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var routerPath: RouterPath
|
||||
|
||||
@State var statusViewModel: StatusViewModel
|
||||
@State var statusViewModel: StatusModel
|
||||
|
||||
@State private var repliesCount = 0
|
||||
@State private var reblogged = false
|
||||
|
@ -38,8 +38,8 @@ struct InteractionRow: View {
|
|||
ActionButton {
|
||||
do {
|
||||
let status = self.reblogged
|
||||
? try await StatusService.shared.unboost(statusId: self.statusViewModel.id, for: self.applicationState.accountData)
|
||||
: try await StatusService.shared.boost(statusId: self.statusViewModel.id, for: self.applicationState.accountData)
|
||||
? try await StatusService.shared.unboost(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
: try await StatusService.shared.boost(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
|
||||
if let status {
|
||||
self.reblogsCount = status.reblogsCount == self.reblogsCount
|
||||
|
@ -66,8 +66,8 @@ struct InteractionRow: View {
|
|||
ActionButton {
|
||||
do {
|
||||
let status = self.favourited
|
||||
? try await StatusService.shared.unfavourite(statusId: self.statusViewModel.id, for: self.applicationState.accountData)
|
||||
: try await StatusService.shared.favourite(statusId: self.statusViewModel.id, for: self.applicationState.accountData)
|
||||
? try await StatusService.shared.unfavourite(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
: try await StatusService.shared.favourite(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
|
||||
if let status {
|
||||
self.favouritesCount = status.favouritesCount == self.favouritesCount
|
||||
|
@ -94,8 +94,8 @@ struct InteractionRow: View {
|
|||
ActionButton {
|
||||
do {
|
||||
_ = self.bookmarked
|
||||
? try await StatusService.shared.unbookmark(statusId: self.statusViewModel.id, for: self.applicationState.accountData)
|
||||
: try await StatusService.shared.bookmark(statusId: self.statusViewModel.id, for: self.applicationState.accountData)
|
||||
? try await StatusService.shared.unbookmark(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
: try await StatusService.shared.bookmark(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
|
||||
self.bookmarked.toggle()
|
||||
ToastrService.shared.showSuccess("Bookmarked", imageSystemName: "bookmark.fill")
|
||||
|
|
|
@ -106,7 +106,7 @@ struct NotificationRow: View {
|
|||
switch notification.type {
|
||||
case .favourite, .reblog, .mention, .status, .poll, .update:
|
||||
if let status = notification.status {
|
||||
let statusViewModel = StatusViewModel(status: status)
|
||||
let statusViewModel = StatusModel(status: status)
|
||||
self.routerPath.navigate(to: .status(id: statusViewModel.id,
|
||||
blurhash: statusViewModel.mediaAttachments.first?.blurhash,
|
||||
highestImageUrl: statusViewModel.mediaAttachments.getHighestImage()?.url,
|
||||
|
|
|
@ -20,12 +20,12 @@ struct AccountsSection: View {
|
|||
accountDisplayName: account.displayName,
|
||||
accountUsername: account.username)
|
||||
Spacer()
|
||||
if self.applicationState.accountData?.id == account.id {
|
||||
if self.applicationState.account?.id == account.id {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(self.applicationState.tintColor.color())
|
||||
}
|
||||
}
|
||||
.deleteDisabled(self.applicationState.accountData?.id == account.id)
|
||||
.deleteDisabled(self.applicationState.account?.id == account.id)
|
||||
}
|
||||
.onDelete(perform: delete)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ struct CommentBody: View {
|
|||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var routerPath: RouterPath
|
||||
|
||||
@State var statusViewModel: StatusViewModel
|
||||
@State var statusViewModel: StatusModel
|
||||
private let contentWidth = Int(UIScreen.main.bounds.width) - 60
|
||||
|
||||
var body: some View {
|
||||
|
@ -85,7 +85,7 @@ struct CommentBody: View {
|
|||
.background(self.getSelectedRowColor(statusViewModel: statusViewModel))
|
||||
}
|
||||
|
||||
private func getSelectedRowColor(statusViewModel: StatusViewModel) -> Color {
|
||||
private func getSelectedRowColor(statusViewModel: StatusModel) -> Color {
|
||||
return self.applicationState.showInteractionStatusId == statusViewModel.id ? Color.selectedRowColor : Color.systemBackground
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ struct CommentsSection: View {
|
|||
@EnvironmentObject var applicationState: ApplicationState
|
||||
|
||||
@State public var statusId: String
|
||||
@State private var commentViewModels: [CommentViewModel]?
|
||||
@State private var commentViewModels: [CommentModel]?
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
|
@ -51,7 +51,7 @@ struct CommentsSection: View {
|
|||
}
|
||||
.task {
|
||||
do {
|
||||
if let accountData = applicationState.accountData {
|
||||
if let accountData = applicationState.account {
|
||||
self.commentViewModels = try await StatusService.shared.comments(to: statusId, for: accountData)
|
||||
}
|
||||
} catch {
|
||||
|
|
|
@ -67,7 +67,7 @@ struct UserProfileHeader: View {
|
|||
|
||||
Spacer()
|
||||
|
||||
if self.applicationState.accountData?.id != self.account.id {
|
||||
if self.applicationState.account?.id != self.account.id {
|
||||
self.otherAccountActionButtons()
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ struct UserProfileHeader: View {
|
|||
if let note = account.note, !note.isEmpty {
|
||||
MarkdownFormattedText(note.asMarkdown, withFontSize: 14, andWidth: Int(UIScreen.main.bounds.width) - 16)
|
||||
.environment(\.openURL, OpenURLAction { url in
|
||||
routerPath.handle(url: url, accountData: self.applicationState.accountData)
|
||||
routerPath.handle(url: url, account: self.applicationState.account)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -106,14 +106,14 @@ struct UserProfileHeader: View {
|
|||
if self.relationship?.following == true {
|
||||
if let relationship = try await AccountService.shared.unfollow(
|
||||
account: self.account.id,
|
||||
for: self.applicationState.accountData
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
} else {
|
||||
if let relationship = try await AccountService.shared.follow(
|
||||
account: self.account.id,
|
||||
for: self.applicationState.accountData
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ struct UserProfileStatuses: View {
|
|||
@State private var allItemsLoaded = false
|
||||
@State private var firstLoadFinished = false
|
||||
|
||||
@State private var statusViewModels: [StatusViewModel] = []
|
||||
@State private var statusViewModels: [StatusModel] = []
|
||||
private let defaultLimit = 20
|
||||
|
||||
var body: some View {
|
||||
|
@ -66,12 +66,12 @@ struct UserProfileStatuses: View {
|
|||
|
||||
let statuses = try await AccountService.shared.statuses(
|
||||
createdBy: self.accountId,
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
limit: self.defaultLimit)
|
||||
var inPlaceStatuses: [StatusViewModel] = []
|
||||
var inPlaceStatuses: [StatusModel] = []
|
||||
|
||||
for item in statuses {
|
||||
inPlaceStatuses.append(StatusViewModel(status: item))
|
||||
inPlaceStatuses.append(StatusModel(status: item))
|
||||
}
|
||||
|
||||
self.firstLoadFinished = true
|
||||
|
@ -86,7 +86,7 @@ struct UserProfileStatuses: View {
|
|||
if let lastStatusId = self.statusViewModels.last?.id {
|
||||
let previousStatuses = try await AccountService.shared.statuses(
|
||||
createdBy: self.accountId,
|
||||
for: self.applicationState.accountData,
|
||||
for: self.applicationState.account,
|
||||
maxId: lastStatusId,
|
||||
limit: self.defaultLimit)
|
||||
|
||||
|
@ -94,9 +94,9 @@ struct UserProfileStatuses: View {
|
|||
self.allItemsLoaded = true
|
||||
}
|
||||
|
||||
var inPlaceStatuses: [StatusViewModel] = []
|
||||
var inPlaceStatuses: [StatusModel] = []
|
||||
for item in previousStatuses {
|
||||
inPlaceStatuses.append(StatusViewModel(status: item))
|
||||
inPlaceStatuses.append(StatusModel(status: item))
|
||||
}
|
||||
|
||||
self.statusViewModels.append(contentsOf: inPlaceStatuses)
|
||||
|
|
Loading…
Reference in New Issue