This repository has been archived by the owner on Aug 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract sheet modifiers and clarify naming
- Loading branch information
1 parent
e7ae1a5
commit 4d0b033
Showing
3 changed files
with
256 additions
and
240 deletions.
There are no files selected for viewing
247 changes: 247 additions & 0 deletions
247
xcode/Subconscious/Shared/Components/Common/Profile/UserProfileView+SheetModifier.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
// | ||
// UserProfileView+SheetModifier.swift | ||
// Subconscious | ||
// | ||
// Created by Ben Follington on 14/8/2023. | ||
// | ||
|
||
import Foundation | ||
import SwiftUI | ||
import ObservableStore | ||
|
||
struct MetaSheetModifier: ViewModifier { | ||
let state: UserProfileDetailModel | ||
let send: (UserProfileDetailAction) -> Void | ||
|
||
func body(content: Content) -> some View { | ||
content | ||
.sheet( | ||
isPresented: Binding( | ||
get: { state.isMetaSheetPresented }, | ||
send: send, | ||
tag: UserProfileDetailAction.presentMetaSheet | ||
) | ||
) { | ||
UserProfileDetailMetaSheet( | ||
state: state.metaSheet, | ||
profile: state, | ||
send: Address.forward( | ||
send: send, | ||
tag: UserProfileDetailMetaSheetCursor.tag | ||
) | ||
) | ||
} | ||
} | ||
} | ||
|
||
struct FollowSheetModifier: ViewModifier { | ||
let state: UserProfileDetailModel | ||
let send: (UserProfileDetailAction) -> Void | ||
|
||
func body(content: Content) -> some View { | ||
content | ||
.sheet( | ||
isPresented: Binding( | ||
get: { state.isFollowSheetPresented }, | ||
send: send, | ||
tag: UserProfileDetailAction.presentFollowSheet | ||
) | ||
) { | ||
FollowUserSheet( | ||
state: state.followUserSheet, | ||
send: Address.forward( | ||
send: send, | ||
tag: FollowUserSheetCursor.tag | ||
), | ||
onAttemptFollow: { | ||
let form = state.followUserSheet.followUserForm | ||
guard let did = form.did.validated else { | ||
return | ||
} | ||
guard let name = form.petname.validated else { | ||
return | ||
} | ||
|
||
send(.attemptFollow(did, name.toPetname())) | ||
}, | ||
label: Text("Follow"), | ||
failFollowError: state.failFollowErrorMessage, | ||
onDismissError: { | ||
send(.dismissFailFollowError) | ||
} | ||
) | ||
} | ||
} | ||
} | ||
|
||
struct RenameSheetModifier: ViewModifier { | ||
let state: UserProfileDetailModel | ||
let send: (UserProfileDetailAction) -> Void | ||
|
||
func body(content: Content) -> some View { | ||
content | ||
.sheet( | ||
isPresented: Binding( | ||
get: { state.isRenameSheetPresented }, | ||
send: send, | ||
tag: UserProfileDetailAction.presentRenameSheet | ||
) | ||
) { | ||
FollowUserSheet( | ||
state: state.followUserSheet, | ||
send: Address.forward( | ||
send: send, | ||
tag: FollowUserSheetCursor.tag | ||
), | ||
onAttemptFollow: { | ||
let form = state.followUserSheet.followUserForm | ||
guard let name = form.petname.validated else { | ||
return | ||
} | ||
guard let candidate = state.renameCandidate else { | ||
return | ||
} | ||
|
||
send(.attemptRename(from: candidate, to: name.toPetname())) | ||
}, | ||
label: Text("Rename"), | ||
failFollowError: state.failRenameMessage, | ||
onDismissError: { | ||
send(.dismissFailRenameErrorMessage) | ||
} | ||
) | ||
} | ||
} | ||
} | ||
|
||
struct UnfollowSheetModifier: ViewModifier { | ||
let state: UserProfileDetailModel | ||
let send: (UserProfileDetailAction) -> Void | ||
|
||
func body(content: Content) -> some View { | ||
content | ||
.alert( | ||
isPresented: Binding( | ||
get: { state.failUnfollowErrorMessage != nil }, | ||
set: { _ in send(.dismissFailUnfollowError) } | ||
) | ||
) { | ||
Alert( | ||
title: Text("Failed to Unfollow User"), | ||
message: Text(state.failUnfollowErrorMessage ?? "An unknown error occurred") | ||
) | ||
} | ||
.confirmationDialog( | ||
"Are you sure?", | ||
isPresented: | ||
Binding( | ||
get: { state.isUnfollowConfirmationPresented }, | ||
set: { _ in send(.presentUnfollowConfirmation(false)) } | ||
) | ||
) { | ||
Button( | ||
"Unfollow \(state.unfollowCandidate?.displayName ?? "user")?", | ||
role: .destructive | ||
) { | ||
send(.attemptUnfollow) | ||
} | ||
} message: { | ||
Text("You cannot undo this action") | ||
} | ||
} | ||
} | ||
|
||
struct EditProfileSheetModifier: ViewModifier { | ||
@ObservedObject var app: Store<AppModel> | ||
@ObservedObject var store: Store<UserProfileDetailModel> | ||
private var state: UserProfileDetailModel { | ||
store.state | ||
} | ||
private var send: (UserProfileDetailAction) -> Void { | ||
store.send | ||
} | ||
|
||
func body(content: Content) -> some View { | ||
content | ||
.sheet( | ||
isPresented: Binding( | ||
get: { state.isEditProfileSheetPresented }, | ||
send: send, | ||
tag: UserProfileDetailAction.presentEditProfile | ||
) | ||
) { | ||
if let user = state.user { | ||
EditProfileSheet( | ||
state: state.editProfileSheet, | ||
send: Address.forward( | ||
send: send, | ||
tag: EditProfileSheetCursor.tag | ||
), | ||
user: user, | ||
statistics: state.statistics, | ||
failEditProfileMessage: state.failEditProfileMessage, | ||
onEditProfile: { | ||
send(.requestEditProfile) | ||
}, | ||
onCancel: { | ||
send(.presentEditProfile(false)) | ||
}, | ||
onDismissError: { | ||
send(.dismissEditProfileError) | ||
} | ||
) | ||
} | ||
} | ||
.onReceive( | ||
store.actions.compactMap(AppAction.from), | ||
perform: app.send | ||
) | ||
.onReceive(app.actions, perform: { action in | ||
switch (action) { | ||
case .succeedIndexPeer(let peer) where peer.identity == store.state.user?.did: | ||
store.send(.refresh(forceSync: false)) | ||
break | ||
case _: | ||
break | ||
} | ||
}) | ||
} | ||
} | ||
|
||
struct FollowNewUserSheetModifier: ViewModifier { | ||
let state: UserProfileDetailModel | ||
let send: (UserProfileDetailAction) -> Void | ||
|
||
func body(content: Content) -> some View { | ||
content | ||
.sheet( | ||
isPresented: Binding( | ||
get: { state.isFollowNewUserFormSheetPresented }, | ||
send: send, | ||
tag: UserProfileDetailAction.presentFollowNewUserFormSheet | ||
) | ||
) { | ||
FollowNewUserFormSheetView( | ||
state: state.followNewUserFormSheet, | ||
send: Address.forward( | ||
send: send, | ||
tag: FollowNewUserFormSheetCursor.tag | ||
), | ||
did: state.user?.did, | ||
onAttemptFollow: { | ||
let form = state.followNewUserFormSheet.form | ||
guard let did = form.did.validated else { | ||
return | ||
} | ||
guard let name = form.petname.validated else { | ||
return | ||
} | ||
|
||
send(.attemptFollow(did, name.toPetname())) | ||
}, | ||
onCancel: { send(.presentFollowNewUserFormSheet(false)) }, | ||
onDismissFailFollowError: { send(.dismissFailFollowError) } | ||
) | ||
} | ||
} | ||
} |
Oops, something went wrong.