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

Fix delete note from detail view #954

Merged
merged 16 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion xcode/Subconscious/Shared/Components/AppTabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SwiftUI
import ObservableStore
import Combine

enum AppTab: String {
enum AppTab: String, Hashable {
bfollington marked this conversation as resolved.
Show resolved Hide resolved
case feed
case notebook
case profile
Expand Down
12 changes: 6 additions & 6 deletions xcode/Subconscious/Shared/Components/AppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ typealias NicknameFormField = FormField<String, Petname.Name>
typealias GatewayUrlFormField = FormField<String, GatewayURL>

// MARK: Action
enum AppAction {
enum AppAction: Hashable {
// Logger for actions
static let logger = Logger(
subsystem: Config.default.rdns,
Expand Down Expand Up @@ -213,7 +213,7 @@ enum AppAction {
/// Index the contents of a sphere in the database
case indexPeer(_ petname: Petname)
case succeedIndexPeer(_ peer: PeerRecord)
case failIndexPeer(petname: Petname, error: Error)
case failIndexPeer(petname: Petname, error: String)

/// Purge the contents of a sphere from the database
case purgePeer(_ did: Did)
Expand Down Expand Up @@ -461,7 +461,7 @@ enum AppDatabaseState {
case ready
}

enum FirstRunStep {
enum FirstRunStep: Hashable {
case sphere
case recovery
case profile
Expand Down Expand Up @@ -2026,7 +2026,7 @@ struct AppModel: ModelProtocol {
} catch {
return Action.failIndexPeer(
petname: petname,
error: error
error: error.localizedDescription
)
}

Expand Down Expand Up @@ -2054,13 +2054,13 @@ struct AppModel: ModelProtocol {
state: Self,
environment: Environment,
petname: Petname,
error: Error
error: String
) -> Update<Self> {
logger.log(
"Failed to index peer",
metadata: [
"petname": petname.description,
"error": error.localizedDescription
"error": error
]
)
return Update(state: state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -634,13 +634,17 @@ struct UserProfileDetailModel: ModelProtocol {
let fx: Fx<UserProfileDetailAction> = Future.detached {
try await Self.refresh(address: address, environment: environment)
}
.map { content in
UserProfileDetailAction.populate(content)
}
.catch { error in
Just(UserProfileDetailAction.failedToPopulate(error.localizedDescription))
}
.eraseToAnyPublisher()
.map { content in
UserProfileDetailAction.populate(content)
}
.catch { error in
Just(
UserProfileDetailAction.failedToPopulate(
error.localizedDescription
)
)
}
bfollington marked this conversation as resolved.
Show resolved Hide resolved
.eraseToAnyPublisher()

return Update(state: model, fx: fx)
}
Expand All @@ -657,7 +661,7 @@ struct UserProfileDetailModel: ModelProtocol {
model.following = content.following
model.loadingState = .loaded

return Update(state: model)
return Update(state: model).animation(.default)
bfollington marked this conversation as resolved.
Show resolved Hide resolved
}

static func failedToPopulate(
Expand Down
173 changes: 137 additions & 36 deletions xcode/Subconscious/Shared/Components/Feed/Feed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,28 +112,24 @@ struct FeedView: View {
app.actions.compactMap(FeedAction.from),
perform: store.send
)
}
}

extension FeedAction {
bfollington marked this conversation as resolved.
Show resolved Hide resolved
static func from(_ action: AppAction) -> Self? {
switch action {
case .succeedIndexOurSphere:
return .refreshAll
case .succeedIndexPeer:
return .refreshAll
case .succeedRecoverOurSphere:
return .refreshAll
case .requestFeedRoot:
return .requestFeedRoot
default:
return nil
/// Replay some feed actions on app store
.onReceive(
store.actions.compactMap(AppAction.from),
perform: app.send
)
.onReceive(store.actions) { action in
FeedAction.logger.debug("\(String(describing: action))")
bfollington marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

// MARK: Action
enum FeedAction {
static let logger = Logger(
subsystem: Config.default.rdns,
category: "FeedAction"
)

case search(SearchAction)
case activatedSuggestion(Suggestion)
case detailStack(DetailStackAction)
Expand All @@ -143,7 +139,10 @@ enum FeedAction {
case ready
case refreshAll

/// DetailStack notification actions
/// DetailStack-related actions
case requestDeleteMemo(Slashlink?)
case succeedDeleteMemo(Slashlink)
case failDeleteMemo(String)
case succeedSaveEntry(slug: Slashlink, modified: Date)
case succeedMoveEntry(from: Slashlink, to: Slashlink)
case succeedMergeEntry(parent: Slashlink, child: Slashlink)
Expand All @@ -160,6 +159,38 @@ enum FeedAction {
case requestFeedRoot
}

extension AppAction {
static func from(_ action: FeedAction) -> Self? {
switch action {
case let .requestDeleteMemo(slashlink):
return .deleteMemo(slashlink)
default:
return nil
}
}
}

extension FeedAction {
static func from(_ action: AppAction) -> Self? {
switch action {
case .succeedIndexOurSphere:
return .refreshAll
case .succeedIndexPeer:
return .refreshAll
case .succeedRecoverOurSphere:
return .refreshAll
case .requestFeedRoot:
return .requestFeedRoot
case let .succeedDeleteMemo(address):
return .succeedDeleteMemo(address)
case let .failDeleteMemo(error):
return .failDeleteMemo(error)
default:
return nil
}
}
}

struct FeedSearchCursor: CursorProtocol {
typealias Model = FeedModel
typealias ViewModel = SearchModel
Expand Down Expand Up @@ -202,6 +233,8 @@ struct FeedDetailStackCursor: CursorProtocol {

static func tag(_ action: ViewModel.Action) -> Model.Action {
switch action {
case let .requestDeleteMemo(slashlink):
return .requestDeleteMemo(slashlink)
case let .succeedMergeEntry(parent: parent, child: child):
return .succeedMergeEntry(parent: parent, child: child)
case let .succeedMoveEntry(from: from, to: to):
Expand Down Expand Up @@ -229,12 +262,12 @@ struct FeedModel: ModelProtocol {
/// Entry detail
var detailStack = DetailStackModel()
var entries: [StoryEntry]? = nil

static let logger = Logger(
subsystem: Config.default.rdns,
category: "Feed"
)

bfollington marked this conversation as resolved.
Show resolved Hide resolved
// MARK: Update
static func update(
state: FeedModel,
Expand Down Expand Up @@ -294,6 +327,24 @@ struct FeedModel: ModelProtocol {
state: state,
environment: environment
)
case .requestDeleteMemo(let address):
return requestDeleteMemo(
state: state,
environment: environment,
address: address
)
case .failDeleteMemo(let error):
return failDeleteMemo(
state: state,
environment: environment,
error: error
)
case .succeedDeleteMemo(let address):
return succeedDeleteMemo(
state: state,
environment: environment,
address: address
)
case let .succeedUpdateAudience(receipt):
return update(
state: state,
Expand Down Expand Up @@ -342,7 +393,7 @@ struct FeedModel: ModelProtocol {
logger.log("\(error.localizedDescription)")
return Update(state: state)
}

/// Log error at warning level
static func warn(
state: FeedModel,
Expand All @@ -352,7 +403,7 @@ struct FeedModel: ModelProtocol {
logger.warning("\(error.localizedDescription)")
return Update(state: state)
}

/// Set search presented flag
static func setSearchPresented(
state: FeedModel,
Expand All @@ -363,14 +414,14 @@ struct FeedModel: ModelProtocol {
model.isSearchPresented = isPresented
return Update(state: model)
}

static func ready(
state: FeedModel,
environment: AppEnvironment
) -> Update<FeedModel> {
return fetchFeed(state: state, environment: environment)
}

/// Refresh all list views from database
static func refreshAll(
state: FeedModel,
Expand All @@ -385,7 +436,7 @@ struct FeedModel: ModelProtocol {
environment: environment
)
}

/// Fetch latest from feed
static func fetchFeed(
state: FeedModel,
Expand All @@ -399,7 +450,7 @@ struct FeedModel: ModelProtocol {
Just(FeedAction.failFetchFeed(error))
})
.eraseToAnyPublisher()

var model = state
// only display loading state if we have no posts to show
// if we have stale posts, show them until we load the new ones
Expand All @@ -409,7 +460,7 @@ struct FeedModel: ModelProtocol {

return Update(state: model, fx: fx)
}

/// Set feed response
static func succeedFetchFeed(
state: FeedModel,
Expand All @@ -433,16 +484,6 @@ struct FeedModel: ModelProtocol {

return Update(state: model)
}

/// Handle entry deleted
static func entryDeleted(
state: FeedModel,
environment: AppEnvironment,
slug: Slug
) -> Update<FeedModel> {
logger.warning("Not implemented")
return Update(state: state)
}

static func requestFeedRoot(
state: FeedModel,
Expand All @@ -454,4 +495,64 @@ struct FeedModel: ModelProtocol {
environment: environment
)
}

/// Entry delete succeeded
static func requestDeleteMemo(
state: Self,
environment: Environment,
address: Slashlink?
) -> Update<Self> {
logger.log(
"Request delete memo",
metadata: [
"address": address?.description ?? ""
]
)
return update(
state: state,
action: .detailStack(.requestDeleteMemo(address)),
environment: environment
)
}

/// Entry delete succeeded
static func succeedDeleteMemo(
state: Self,
environment: Environment,
address: Slashlink
) -> Update<Self> {
logger.log(
"Memo was deleted",
metadata: [
"address": address.description
]
)
return update(
state: state,
actions: [
.detailStack(.succeedDeleteMemo(address)),
.refreshAll
],
environment: environment
)
}

/// Entry delete failed
static func failDeleteMemo(
state: Self,
environment: Environment,
error: String
) -> Update<Self> {
logger.log(
"Failed to delete memo",
metadata: [
"error": error
]
)
return update(
state: state,
action: .detailStack(.failDeleteMemo(error)),
environment: environment
)
}
}
Loading