Skip to content
This repository has been archived by the owner on Aug 11, 2024. It is now read-only.

Commit

Permalink
Refresh Feed + Profile view after successful recovery (#912)
Browse files Browse the repository at this point in the history
Ensures the feed is populated when dismissing recovery mode after a
successful recovery. Refreshing the profile is less important, given
that the feed is the default tab, but probably still worth refreshing it
to be safe.

I found a few other refresh and notification-centric issues too.

# Changes

- Refresh feed after successful recovery
- Refresh profile after successful recovery
- Refresh feed based on DetailStack notifications
- Rename NotebookAction's for detail stack for consistency
(`succeedSaveMemo` -> `succeedSaveEntry`)
- Extract logic from NotebookModel that should be in DetailStackModel
- Refresh Notebook when switching to Notebook Tab
  • Loading branch information
bfollington authored Oct 2, 2023
1 parent 52f7151 commit d088130
Show file tree
Hide file tree
Showing 5 changed files with 451 additions and 203 deletions.
139 changes: 126 additions & 13 deletions xcode/Subconscious/Shared/Components/Detail/DetailStackView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ enum DetailStackAction: Hashable {
/// Deletion attempt succeeded. Forwarded down from parent.
case succeedDeleteMemo(Slashlink)

case succeedMoveMemo(from: Slashlink, to: Slashlink)
case succeedMergeMemo(parent: Slashlink, child: Slashlink)
case succeedSaveMemo(address: Slashlink, modified: Date)
case succeedMoveEntry(from: Slashlink, to: Slashlink)
case succeedMergeEntry(parent: Slashlink, child: Slashlink)
case succeedSaveEntry(address: Slashlink, modified: Date)
case succeedUpdateAudience(MoveReceipt)

/// Synonym for `.pushDetail` that wraps editor detail in `.editor()`
Expand Down Expand Up @@ -245,14 +245,28 @@ struct DetailStackModel: Hashable, ModelProtocol {
error: error
)
// These act as notifications for parent models to react to
case .succeedMoveMemo:
return Update(state: state)
case .succeedMergeMemo:
return Update(state: state)
case .succeedSaveMemo:
return Update(state: state)
case .succeedUpdateAudience:
case let .succeedMoveEntry(from, to):
return succeedMoveEntry(
state: state,
environment: environment,
from: from,
to: to
)
case let .succeedMergeEntry(parent, child):
return succeedMergeEntry(
state: state,
environment: environment,
parent: parent,
child: child
)
case .succeedSaveEntry:
return Update(state: state)
case let.succeedUpdateAudience(receipt):
return succeedUpdateAudience(
state: state,
environment: environment,
receipt: receipt
)
}
}

Expand Down Expand Up @@ -480,6 +494,105 @@ struct DetailStackModel: Hashable, ModelProtocol {
) -> Update<Self> {
return Update(state: state)
}

/// Move success lifecycle handler.
/// Updates UI in response.
static func succeedMoveEntry(
state: Self,
environment: Environment,
from: Slashlink,
to: Slashlink
) -> Update<Self> {
/// Find all instances of this model in the stack and update them
let details = state.details.map({ (detail: MemoDetailDescription) in
guard detail.address == from else {
return detail
}
switch detail {
case .editor(var description):
description.address = to
return .editor(description)
case .viewer(var description):
description.address = to
return .viewer(description)
case .profile(let description):
return .profile(description)
}
})

return update(
state: state,
action: .setDetails(details),
environment: environment
)
}

/// Merge success lifecycle handler.
/// Updates UI in response.
static func succeedMergeEntry(
state: Self,
environment: Environment,
parent: Slashlink,
child: Slashlink
) -> Update<Self> {
/// Find all instances of child and update them to become parent
let details = state.details.map({ (detail: MemoDetailDescription) in
guard detail.address == child else {
return detail
}
switch detail {
case .editor(var description):
description.address = parent
return .editor(description)
case .viewer(var description):
description.address = parent
return .viewer(description)
case .profile(let description):
return .profile(description)
}
})

return update(
state: state,
action: .setDetails(details),
environment: environment
)
}

/// Retitle success lifecycle handler.
/// Updates UI in response.
static func succeedUpdateAudience(
state: Self,
environment: Environment,
receipt: MoveReceipt
) -> Update<Self> {
/// Find all instances of this model in the stack and update them
let details = state.details.map({ (detail: MemoDetailDescription) in
guard let address = detail.address else {
return detail
}
guard address.slug == receipt.to.slug else {
return detail
}
switch detail {
case .editor(var description):
description.address = receipt.to
return .editor(description)
case .viewer(var description):
description.address = receipt.to
return .viewer(description)
case .profile(let description):
return .profile(description)
}
})

return update(
state: state,
action: .setDetails(details),
environment: environment
)
}

}

extension DetailStackAction {
Expand All @@ -495,11 +608,11 @@ extension DetailStackAction {
link: link
)
case let .succeedMoveEntry(from, to):
return .succeedMoveMemo(from: from, to: to)
return .succeedMoveEntry(from: from, to: to)
case let .succeedMergeEntry(parent, child):
return .succeedMergeMemo(parent: parent, child: child)
return .succeedMergeEntry(parent: parent, child: child)
case let .succeedSaveEntry(address, modified):
return .succeedSaveMemo(address: address, modified: modified)
return .succeedSaveEntry(address: address, modified: modified)
case let .succeedUpdateAudience(receipt):
return .succeedUpdateAudience(receipt)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ struct UserProfileDetailView: View {
store.actions.compactMap(UserProfileDetailAction.toAppAction),
perform: app.send
)
.onReceive(
app.actions.compactMap(UserProfileDetailAction.from),
perform: store.send
)
.onReceive(store.actions) { action in
UserProfileDetailAction.logger.debug(
"\(String(describing: action))"
Expand Down Expand Up @@ -104,6 +108,21 @@ extension UserProfileDetailAction {
}
}

extension UserProfileDetailAction {
static func from(_ action: AppAction) -> Self? {
switch action {
case .succeedIndexOurSphere:
return .refresh(forceSync: false)
case .succeedIndexPeer:
return .refresh(forceSync: false)
case .succeedRecoverOurSphere:
return .refresh(forceSync: false)
default:
return nil
}
}
}

/// A description of a user profile that can be used to set up the user
/// profile's internal state.
struct UserProfileDetailDescription: Hashable {
Expand Down
67 changes: 60 additions & 7 deletions xcode/Subconscious/Shared/Components/Feed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,11 @@ struct FeedView: View {
extension FeedAction {
static func from(_ action: AppAction) -> Self? {
switch action {
case .succeedIndexOurSphere(_):
case .succeedIndexOurSphere:
return .refreshAll
case .succeedIndexPeer(_):
case .succeedIndexPeer:
return .refreshAll
case .succeedRecoverOurSphere:
return .refreshAll
case .requestFeedRoot:
return .requestFeedRoot
Expand All @@ -149,11 +151,15 @@ enum FeedAction {

/// Set search view presented
case setSearchPresented(Bool)

case ready

case refreshAll


/// DetailStack notification actions
case succeedSaveEntry(slug: Slashlink, modified: Date)
case succeedMoveEntry(from: Slashlink, to: Slashlink)
case succeedMergeEntry(parent: Slashlink, child: Slashlink)
case succeedUpdateAudience(MoveReceipt)

// Feed
/// Fetch stories for feed
case fetchFeed
Expand Down Expand Up @@ -207,7 +213,18 @@ struct FeedDetailStackCursor: CursorProtocol {
}

static func tag(_ action: ViewModel.Action) -> Model.Action {
.detailStack(action)
switch action {
case let .succeedMergeEntry(parent: parent, child: child):
return .succeedMergeEntry(parent: parent, child: child)
case let .succeedMoveEntry(from: from, to: to):
return .succeedMoveEntry(from: from, to: to)
case let .succeedUpdateAudience(receipt):
return .succeedUpdateAudience(receipt)
case let .succeedSaveEntry(address: address, modified: modified):
return .succeedSaveEntry(slug: address, modified: modified)
case _:
return .detailStack(action)
}
}
}

Expand Down Expand Up @@ -288,9 +305,45 @@ struct FeedModel: ModelProtocol {
state: state,
environment: environment
)
case let .succeedUpdateAudience(receipt):
return update(
state: state,
actions: [
.detailStack(.succeedUpdateAudience(receipt)),
.refreshAll
],
environment: environment
)
case let .succeedMoveEntry(from, to):
return update(
state: state,
actions: [
.detailStack(.succeedMoveEntry(from: from, to: to)),
.refreshAll
],
environment: environment
)
case let .succeedMergeEntry(parent, child):
return update(
state: state,
actions: [
.detailStack(.succeedMergeEntry(parent: parent, child: child)),
.refreshAll
],
environment: environment
)
case let .succeedSaveEntry(address, modified):
return update(
state: state,
actions: [
.detailStack(.succeedSaveEntry(address: address, modified: modified)),
.refreshAll
],
environment: environment
)
}
}

/// Log error at log level
static func log(
state: FeedModel,
Expand Down
Loading

0 comments on commit d088130

Please sign in to comment.