Add notify next to follow button if following

This commit is contained in:
Thomas Ricouard 2023-01-12 07:36:19 +01:00
parent 3acd5aced4
commit 6f7c576c3a
7 changed files with 57 additions and 51 deletions

View file

@ -32,8 +32,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/kean/Nuke", "location" : "https://github.com/kean/Nuke",
"state" : { "state" : {
"revision" : "2e9337168d08acccf72c039bf9324be24a1cf7d7", "revision" : "81f6a3dea0c8ce3b87389c241c48601be07af0b1",
"version" : "11.5.3" "version" : "11.5.1"
} }
}, },
{ {
@ -50,8 +50,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/scinfu/SwiftSoup.git", "location" : "https://github.com/scinfu/SwiftSoup.git",
"state" : { "state" : {
"revision" : "f707b8680cddb96dc1855632340a572ef37bbb98", "revision" : "6778575285177365cbad3e5b8a72f2a20583cfec",
"version" : "2.5.3" "version" : "2.4.3"
} }
}, },
{ {

View file

@ -12,9 +12,8 @@ struct AccountDetailHeaderView: View {
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routeurPath: RouterPath
@Environment(\.redactionReasons) private var reasons @Environment(\.redactionReasons) private var reasons
let isCurrentUser: Bool @ObservedObject var viewModel: AccountDetailViewModel
let account: Account let account: Account
let relationship: Relationshionship?
let scrollViewProxy: ScrollViewProxy? let scrollViewProxy: ScrollViewProxy?
@Binding var scrollOffset: CGFloat @Binding var scrollOffset: CGFloat
@ -55,7 +54,7 @@ struct AccountDetailHeaderView: View {
.frame(height: bannerHeight) .frame(height: bannerHeight)
} }
if relationship?.followedBy == true { if viewModel.relationship?.followedBy == true {
Text("Follows You") Text("Follows You")
.font(.footnote) .font(.footnote)
.fontWeight(.semibold) .fontWeight(.semibold)
@ -116,11 +115,13 @@ struct AccountDetailHeaderView: View {
.foregroundColor(.gray) .foregroundColor(.gray)
} }
Spacer() Spacer()
if let relationship = relationship, !isCurrentUser { if let relationship = viewModel.relationship, !viewModel.isCurrentUser {
HStack {
FollowButton(viewModel: .init(accountId: account.id, FollowButton(viewModel: .init(accountId: account.id,
relationship: relationship)) relationship: relationship))
} }
} }
}
EmojiText(account.note, emojis: account.emojis) EmojiText(account.note, emojis: account.emojis)
.font(.body) .font(.body)
.padding(.top, 8) .padding(.top, 8)
@ -146,9 +147,8 @@ struct AccountDetailHeaderView: View {
struct AccountDetailHeaderView_Previews: PreviewProvider { struct AccountDetailHeaderView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
AccountDetailHeaderView(isCurrentUser: false, AccountDetailHeaderView(viewModel: .init(account: .placeholder()),
account: .placeholder(), account: .placeholder(),
relationship: .placeholder(),
scrollViewProxy: nil, scrollViewProxy: nil,
scrollOffset: .constant(0)) scrollOffset: .constant(0))
} }

View file

@ -122,17 +122,15 @@ public struct AccountDetailView: View {
private func makeHeaderView(proxy: ScrollViewProxy?) -> some View { private func makeHeaderView(proxy: ScrollViewProxy?) -> some View {
switch viewModel.accountState { switch viewModel.accountState {
case .loading: case .loading:
AccountDetailHeaderView(isCurrentUser: isCurrentUser, AccountDetailHeaderView(viewModel: viewModel,
account: .placeholder(), account: .placeholder(),
relationship: .placeholder(),
scrollViewProxy: proxy, scrollViewProxy: proxy,
scrollOffset: $scrollOffset) scrollOffset: $scrollOffset)
.redacted(reason: .placeholder) .redacted(reason: .placeholder)
.shimmering() .shimmering()
case let .data(account): case let .data(account):
AccountDetailHeaderView(isCurrentUser: isCurrentUser, AccountDetailHeaderView(viewModel: viewModel,
account: account, account: account,
relationship: viewModel.relationship,
scrollViewProxy: proxy, scrollViewProxy: proxy,
scrollOffset: $scrollOffset) scrollOffset: $scrollOffset)
case let .error(error): case let .error(error):

View file

@ -213,24 +213,6 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
} }
} }
func follow() async {
guard let client else { return }
do {
relationship = try await client.post(endpoint: Accounts.follow(id: accountId))
} catch {
print("Error while following: \(error.localizedDescription)")
}
}
func unfollow() async {
guard let client else { return }
do {
relationship = try await client.post(endpoint: Accounts.unfollow(id: accountId))
} catch {
print("Error while unfollowing: \(error.localizedDescription)")
}
}
private func reloadTabState() { private func reloadTabState() {
switch selectedTab { switch selectedTab {
case .statuses, .postsAndReplies, .media: case .statuses, .postsAndReplies, .media:

View file

@ -20,7 +20,7 @@ public class FollowButtonViewModel: ObservableObject {
guard let client else { return } guard let client else { return }
isUpdating = true isUpdating = true
do { do {
relationship = try await client.post(endpoint: Accounts.follow(id: accountId)) relationship = try await client.post(endpoint: Accounts.follow(id: accountId, notify: false))
} catch { } catch {
print("Error while following: \(error.localizedDescription)") print("Error while following: \(error.localizedDescription)")
} }
@ -37,6 +37,15 @@ public class FollowButtonViewModel: ObservableObject {
} }
isUpdating = false isUpdating = false
} }
func toggleNotify() async {
guard let client else { return }
do {
relationship = try await client.post(endpoint: Accounts.follow(id: accountId, notify: !relationship.notifying))
} catch {
print("Error while following: \(error.localizedDescription)")
}
}
} }
public struct FollowButton: View { public struct FollowButton: View {
@ -48,6 +57,7 @@ public struct FollowButton: View {
} }
public var body: some View { public var body: some View {
HStack {
Button { Button {
Task { Task {
if viewModel.relationship.following { if viewModel.relationship.following {
@ -65,6 +75,18 @@ public struct FollowButton: View {
} }
.buttonStyle(.bordered) .buttonStyle(.bordered)
.disabled(viewModel.isUpdating) .disabled(viewModel.isUpdating)
if viewModel.relationship.following {
Button {
Task {
await viewModel.toggleNotify()
}
} label: {
Image(systemName: viewModel.relationship.notifying ? "bell.fill" : "bell")
}
.buttonStyle(.bordered)
.disabled(viewModel.isUpdating)
}
}
.onAppear { .onAppear {
viewModel.client = client viewModel.client = client
} }

View file

@ -13,6 +13,7 @@ public struct Relationshionship: Codable {
public let domainBlocking: Bool public let domainBlocking: Bool
public let endorsed: Bool public let endorsed: Bool
public let note: String public let note: String
public let notifying: Bool
static public func placeholder() -> Relationshionship { static public func placeholder() -> Relationshionship {
.init(id: UUID().uuidString, .init(id: UUID().uuidString,
@ -26,6 +27,7 @@ public struct Relationshionship: Codable {
requested: false, requested: false,
domainBlocking: false, domainBlocking: false,
endorsed: false, endorsed: false,
note: "") note: "",
notifying: false)
} }
} }

View file

@ -22,7 +22,7 @@ public enum Accounts: Endpoint {
excludeReplies: Bool?, excludeReplies: Bool?,
pinned: Bool?) pinned: Bool?)
case relationships(ids: [String]) case relationships(ids: [String])
case follow(id: String) case follow(id: String, notify: Bool)
case unfollow(id: String) case unfollow(id: String)
case familiarFollowers(withAccount: String) case familiarFollowers(withAccount: String)
case suggestions case suggestions
@ -51,7 +51,7 @@ public enum Accounts: Endpoint {
return "accounts/\(id)/statuses" return "accounts/\(id)/statuses"
case .relationships: case .relationships:
return "accounts/relationships" return "accounts/relationships"
case .follow(let id): case .follow(let id, _):
return "accounts/\(id)/follow" return "accounts/\(id)/follow"
case .unfollow(let id): case .unfollow(let id):
return "accounts/\(id)/unfollow" return "accounts/\(id)/unfollow"
@ -94,6 +94,8 @@ public enum Accounts: Endpoint {
return ids.map { return ids.map {
URLQueryItem(name: "id[]", value: $0) URLQueryItem(name: "id[]", value: $0)
} }
case let .follow(_, notify):
return [.init(name: "notify", value: notify ? "true" : "false")]
case let .familiarFollowers(withAccount): case let .familiarFollowers(withAccount):
return [.init(name: "id[]", value: withAccount)] return [.init(name: "id[]", value: withAccount)]
case let .followers(_, maxId): case let .followers(_, maxId):