Optimization interactor

This commit is contained in:
Lumaa 2024-01-21 15:36:59 +01:00
parent 51db0c2442
commit fc039504f7
4 changed files with 156 additions and 171 deletions

View File

@ -33,6 +33,7 @@
B9B63B232B447B8000BBC82D /* PostCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9B63B222B447B8000BBC82D /* PostCardView.swift */; };
B9B63B252B44997400BBC82D /* QuotePostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9B63B242B44997400BBC82D /* QuotePostView.swift */; };
B9B63B272B449CDC00BBC82D /* SearchResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9B63B262B449CDC00BBC82D /* SearchResults.swift */; };
B9BED5162B5D5E6500C9B715 /* PostInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9BED5152B5D5E6500C9B715 /* PostInteractor.swift */; };
B9CC45B82B40A2D6001E4FA5 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9CC45B72B40A2D6001E4FA5 /* AboutView.swift */; };
B9CFC43B2B4F08C9004CFCB7 /* LaunchStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B9CFC43A2B4F08C9004CFCB7 /* LaunchStoryboard.storyboard */; };
B9EBE8562B47256900FB594D /* PostAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9EBE8552B47256900FB594D /* PostAttachment.swift */; };
@ -115,6 +116,7 @@
B9B63B222B447B8000BBC82D /* PostCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostCardView.swift; sourceTree = "<group>"; };
B9B63B242B44997400BBC82D /* QuotePostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuotePostView.swift; sourceTree = "<group>"; };
B9B63B262B449CDC00BBC82D /* SearchResults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResults.swift; sourceTree = "<group>"; };
B9BED5152B5D5E6500C9B715 /* PostInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostInteractor.swift; sourceTree = "<group>"; };
B9CC45B72B40A2D6001E4FA5 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
B9CC45B92B40AA1E001E4FA5 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
B9CFC43A2B4F08C9004CFCB7 /* LaunchStoryboard.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchStoryboard.storyboard; sourceTree = "<group>"; };
@ -179,6 +181,18 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B9BED5142B5D5CCD00C9B715 /* Status */ = {
isa = PBXGroup;
children = (
B9842C0D2B2F21B700D9F3C1 /* CompactPostView.swift */,
B9B63B222B447B8000BBC82D /* PostCardView.swift */,
B9EBE8552B47256900FB594D /* PostAttachment.swift */,
B9B63B242B44997400BBC82D /* QuotePostView.swift */,
B9BED5152B5D5E6500C9B715 /* PostInteractor.swift */,
);
path = Status;
sourceTree = "<group>";
};
B9FB944E2B2DEECE00D81C07 = {
isa = PBXGroup;
children = (
@ -268,17 +282,14 @@
B9FB946E2B2DF3BB00D81C07 /* Components */ = {
isa = PBXGroup;
children = (
B9BED5142B5D5CCD00C9B715 /* Status */,
B9FB94752B2E023D00D81C07 /* TabsView.swift */,
B9FB94732B2DF6A100D81C07 /* ButtonStyles.swift */,
B93B67792B42EC51000892E9 /* MetaPicker.swift */,
B9FB948B2B2E232300D81C07 /* OnlineImage.swift */,
B9842C0D2B2F21B700D9F3C1 /* CompactPostView.swift */,
B93B67772B42E8F0000892E9 /* TextEmoji.swift */,
B9B63B202B442D1500BBC82D /* DynamicTextEditor.swift */,
B9B63B222B447B8000BBC82D /* PostCardView.swift */,
B9B63B242B44997400BBC82D /* QuotePostView.swift */,
B98BC74A2B46CF0400595441 /* ListStyle.swift */,
B9EBE8552B47256900FB594D /* PostAttachment.swift */,
);
path = Components;
sourceTree = "<group>";
@ -465,6 +476,7 @@
B9FB945B2B2DEECE00D81C07 /* ThreadedApp.swift in Sources */,
B9FB94862B2E211200D81C07 /* Account+Elms.swift in Sources */,
B9FB94BC2B2F035500D81C07 /* Tag.swift in Sources */,
B9BED5162B5D5E6500C9B715 /* PostInteractor.swift in Sources */,
B98BC74B2B46CF0400595441 /* ListStyle.swift in Sources */,
B9FB94812B2E1FEF00D81C07 /* HTMLString.swift in Sources */,
B9FB947F2B2E1D5F00D81C07 /* Account.swift in Sources */,

View File

@ -13,14 +13,17 @@ struct CompactPostView: View {
@State private var preferences: UserPreferences = .defaultPreferences
@State private var initialLike: Bool = false
@State private var isLiked: Bool = false
@State private var isReposted: Bool = false
@State private var isBookmarked: Bool = false
@State private var hasQuote: Bool = false
@State private var quoteStatus: Status? = nil
var body: some View {
VStack {
statusPost(status)
statusPost(status.reblog ?? status)
.contentShape(Rectangle())
.onTapGesture {
navigator.navigate(to: .post(status: status))
@ -40,9 +43,7 @@ struct CompactPostView: View {
print(error)
}
isLiked = status.reblog != nil ? status.reblog!.favourited ?? false : status.favourited ?? false
initialLike = isLiked
isReposted = status.reblog != nil ? status.reblog!.reblogged ?? false : status.reblogged ?? false
}
.task {
await loadEmbeddedStatus(status: status)
@ -55,34 +56,6 @@ struct CompactPostView: View {
}
}
func likePost() async throws {
if let client = accountManager.getClient() {
guard client.isAuth else { fatalError("Client is not authenticated") }
let statusId: String = status.reblog != nil ? status.reblog!.id : status.id
let endpoint = !isLiked ? Statuses.favorite(id: statusId) : Statuses.unfavorite(id: statusId)
isLiked = !isLiked
let newStatus: Status = try await client.post(endpoint: endpoint)
if isLiked != newStatus.favourited {
isLiked = newStatus.favourited ?? !isLiked
}
}
}
func repostPost() async throws {
if let client = accountManager.getClient() {
guard client.isAuth else { fatalError("Client is not authenticated") }
let statusId: String = status.reblog != nil ? status.reblog!.id : status.id
let endpoint = !isReposted ? Statuses.reblog(id: statusId) : Statuses.unreblog(id: statusId)
isReposted = !isReposted
let newStatus: Status = try await client.post(endpoint: endpoint)
if isReposted != newStatus.reblogged {
isReposted = newStatus.reblogged ?? !isReposted
}
}
}
@ViewBuilder
func statusPost(_ status: AnyStatus) -> some View {
HStack(alignment: .top, spacing: 0) {
@ -181,35 +154,7 @@ struct CompactPostView: View {
//MARK: Action buttons
if !quoted {
HStack(spacing: 13) {
asyncActionButton(isLiked ? "heart.fill" : "heart") {
do {
HapticManager.playHaptics(haptics: Haptic.tap)
try await likePost()
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
actionButton("bubble.right") {
navigator.presentedSheet = .post(content: "@\(status.account.acct)", replyId: status.id)
}
asyncActionButton(isReposted ? "bolt.horizontal.fill" : "bolt.horizontal") {
do {
HapticManager.playHaptics(haptics: Haptic.tap)
try await repostPost()
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
ShareLink(item: URL(string: status.url ?? "https://joinmastodon.org/")!) {
Image(systemName: "square.and.arrow.up")
.font(.title2)
}
.tint(Color(uiColor: UIColor.label))
}
.padding(.top)
}
// MARK: Status stats
@ -350,28 +295,4 @@ struct CompactPostView: View {
quoteStatus = nil
}
}
@ViewBuilder
func actionButton(_ image: String, action: @escaping () -> Void) -> some View {
Button {
action()
} label: {
Image(systemName: image)
.font(.title2)
}
.tint(Color(uiColor: UIColor.label))
}
@ViewBuilder
func asyncActionButton(_ image: String, action: @escaping () async -> Void) -> some View {
Button {
Task {
await action()
}
} label: {
Image(systemName: image)
.font(.title2)
}
.tint(Color(uiColor: UIColor.label))
}
}

View File

@ -0,0 +1,130 @@
//Made by Lumaa
import SwiftUI
struct PostInteractor: View {
@Environment(AccountManager.self) private var accountManager
@Environment(Navigator.self) private var navigator
var status: Status
@Binding var isLiked: Bool
@Binding var isReposted: Bool
@Binding var isBookmarked: Bool
var body: some View {
HStack(spacing: 13) {
asyncActionButton(isLiked ? "heart.fill" : "heart") {
do {
HapticManager.playHaptics(haptics: Haptic.tap)
try await likePost()
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
actionButton("bubble.right") {
navigator.presentedSheet = .post(content: "@\(status.account.acct)", replyId: status.id)
}
asyncActionButton(isReposted ? "bolt.horizontal.fill" : "bolt.horizontal") {
do {
HapticManager.playHaptics(haptics: Haptic.tap)
try await repostPost()
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
asyncActionButton(isBookmarked ? "bookmark.fill" : "bookmark") {
do {
HapticManager.playHaptics(haptics: Haptic.tap)
try await bookmarkPost()
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
Spacer()
ShareLink(item: URL(string: status.url ?? "https://joinmastodon.org/")!) {
Image(systemName: "square.and.arrow.up")
.font(.title2)
.padding(.horizontal)
}
.tint(Color(uiColor: UIColor.label))
}
.padding(.top)
.onAppear {
isLiked = status.reblog != nil ? status.reblog!.favourited ?? false : status.favourited ?? false
isReposted = status.reblog != nil ? status.reblog!.reblogged ?? false : status.reblogged ?? false
isBookmarked = status.reblog != nil ? status.reblog!.bookmarked ?? false : status.bookmarked ?? false
}
}
func likePost() async throws {
if let client = accountManager.getClient() {
guard client.isAuth else { fatalError("Client is not authenticated") }
let statusId: String = status.reblog != nil ? status.reblog!.id : status.id
let endpoint = !isLiked ? Statuses.favorite(id: statusId) : Statuses.unfavorite(id: statusId)
isLiked = !isLiked
let newStatus: Status = try await client.post(endpoint: endpoint)
if isLiked != newStatus.favourited {
isLiked = newStatus.favourited ?? !isLiked
}
}
}
func repostPost() async throws {
if let client = accountManager.getClient() {
guard client.isAuth else { fatalError("Client is not authenticated") }
let statusId: String = status.reblog != nil ? status.reblog!.id : status.id
let endpoint = !isReposted ? Statuses.reblog(id: statusId) : Statuses.unreblog(id: statusId)
isReposted = !isReposted
let newStatus: Status = try await client.post(endpoint: endpoint)
if isReposted != newStatus.reblogged {
isReposted = newStatus.reblogged ?? !isReposted
}
}
}
func bookmarkPost() async throws {
if let client = accountManager.getClient() {
guard client.isAuth else { fatalError("Client is not authenticated") }
let statusId: String = status.reblog != nil ? status.reblog!.id : status.id
let endpoint = !isBookmarked ? Statuses.bookmark(id: statusId) : Statuses.unbookmark(id: statusId)
isBookmarked = !isBookmarked
let newStatus: Status = try await client.post(endpoint: endpoint)
if isBookmarked != newStatus.bookmarked {
isBookmarked = newStatus.bookmarked ?? !isBookmarked
}
}
}
@ViewBuilder
func actionButton(_ image: String, action: @escaping () -> Void) -> some View {
Button {
action()
} label: {
Image(systemName: image)
.font(.title2)
}
.tint(Color(uiColor: UIColor.label))
}
@ViewBuilder
func asyncActionButton(_ image: String, action: @escaping () async -> Void) -> some View {
Button {
Task {
await action()
}
} label: {
Image(systemName: image)
.font(.title2)
}
.tint(Color(uiColor: UIColor.label))
}
}

View File

@ -11,8 +11,11 @@ struct PostDetailsView: View {
@State private var statuses: [Status] = []
@State private var scrollId: String? = nil
@State private var initialLike: Bool = false
@State private var isLiked: Bool = false
@State private var isReposted: Bool = false
@State private var isBookmarked: Bool = false
@State private var hasQuote: Bool = false
@State private var quoteStatus: Status? = nil
@ -27,7 +30,7 @@ struct PostDetailsView: View {
if statuses.isEmpty {
statusPost(detailedStatus)
Spacer()
// Spacer()
} else {
ForEach(statuses) { status in
if status.id == detailedStatus.id {
@ -104,36 +107,7 @@ struct PostDetailsView: View {
}
//MARK: Action buttons
HStack(spacing: 13) {
asyncActionButton(isLiked ? "heart.fill" : "heart") {
do {
HapticManager.playHaptics(haptics: Haptic.tap)
try await likePost()
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
actionButton("bubble.right") {
print("reply")
navigator.presentedSheet = .post()
}
asyncActionButton(isReposted ? "bolt.horizontal.fill" : "bolt.horizontal") {
do {
HapticManager.playHaptics(haptics: Haptic.tap)
try await repostPost()
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
ShareLink(item: URL(string: status.url ?? "https://joinmastodon.org/")!) {
Image(systemName: "square.and.arrow.up")
.font(.title2)
}
.tint(Color(uiColor: UIColor.label))
}
.padding(.top)
PostInteractor(status: status as! Status, isLiked: $isLiked, isReposted: $isReposted, isBookmarked: $isBookmarked)
// MARK: Status stats
stats.padding(.top, 5)
@ -169,34 +143,6 @@ struct PostDetailsView: View {
let context: StatusContext
}
func likePost() async throws {
if let client = accountManager.getClient() {
guard client.isAuth else { fatalError("Client is not authenticated") }
let statusId: String = detailedStatus.reblog != nil ? detailedStatus.reblog!.id : detailedStatus.id
let endpoint = !isLiked ? Statuses.favorite(id: statusId) : Statuses.unfavorite(id: statusId)
isLiked = !isLiked
let newStatus: Status = try await client.post(endpoint: endpoint)
if isLiked != newStatus.favourited {
isLiked = newStatus.favourited ?? !isLiked
}
}
}
func repostPost() async throws {
if let client = accountManager.getClient() {
guard client.isAuth else { fatalError("Client is not authenticated") }
let statusId: String = detailedStatus.reblog != nil ? detailedStatus.reblog!.id : detailedStatus.id
let endpoint = !isReposted ? Statuses.reblog(id: statusId) : Statuses.unreblog(id: statusId)
isReposted = !isReposted
let newStatus: Status = try await client.post(endpoint: endpoint)
if isReposted != newStatus.reblogged {
isReposted = newStatus.reblogged ?? !isReposted
}
}
}
var profilePicture: some View {
if detailedStatus.reblog != nil {
OnlineImage(url: detailedStatus.reblog!.account.avatar, size: 50, useNuke: true)
@ -292,28 +238,4 @@ struct PostDetailsView: View {
quoteStatus = nil
}
}
@ViewBuilder
func actionButton(_ image: String, action: @escaping () -> Void) -> some View {
Button {
action()
} label: {
Image(systemName: image)
.font(.title2)
}
.tint(Color(uiColor: UIColor.label))
}
@ViewBuilder
func asyncActionButton(_ image: String, action: @escaping () async -> Void) -> some View {
Button {
Task {
await action()
}
} label: {
Image(systemName: image)
.font(.title2)
}
.tint(Color(uiColor: UIColor.label))
}
}