mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-25 09:41:00 +00:00
Reply long press account menu
This commit is contained in:
parent
f3040eaad5
commit
12d0cf5ca0
8 changed files with 82 additions and 20 deletions
|
@ -146,11 +146,24 @@ public extension StatusService {
|
||||||
.flatMap { contentDatabase.update(id: status.displayStatus.id, poll: $0) }
|
.flatMap { contentDatabase.update(id: status.displayStatus.id, poll: $0) }
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func asIdentity(id: Identity.Id) -> AnyPublisher<Self, Error> {
|
||||||
|
fetchAs(identityId: id).tryMap {
|
||||||
|
Self(environment: environment,
|
||||||
|
status: $0,
|
||||||
|
mastodonAPIClient: try MastodonAPIClient.forIdentity(id: id, environment: environment),
|
||||||
|
contentDatabase: try ContentDatabase(
|
||||||
|
id: id,
|
||||||
|
useHomeTimelineLastReadId: true,
|
||||||
|
inMemory: environment.inMemoryContent,
|
||||||
|
appGroup: AppEnvironment.appGroup,
|
||||||
|
keychain: environment.keychain)) }
|
||||||
|
.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension StatusService {
|
private extension StatusService {
|
||||||
func request(identityId: Identity.Id,
|
func fetchAs(identityId: Identity.Id) -> AnyPublisher<Status, Error> {
|
||||||
endpointClosure: @escaping (Status.Id) -> StatusEndpoint) -> AnyPublisher<Never, Error> {
|
|
||||||
let client: MastodonAPIClient
|
let client: MastodonAPIClient
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -162,11 +175,25 @@ private extension StatusService {
|
||||||
return client
|
return client
|
||||||
.request(ResultsEndpoint.search(.init(query: status.displayStatus.uri, resolve: true, limit: 1)))
|
.request(ResultsEndpoint.search(.init(query: status.displayStatus.uri, resolve: true, limit: 1)))
|
||||||
.tryMap {
|
.tryMap {
|
||||||
guard let id = $0.statuses.first?.id else { throw APIError.unableToFetchRemoteStatus }
|
guard let status = $0.statuses.first else { throw APIError.unableToFetchRemoteStatus }
|
||||||
|
|
||||||
return id
|
return status
|
||||||
}
|
}
|
||||||
.flatMap { client.request(endpointClosure($0)) }
|
.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
func request(identityId: Identity.Id,
|
||||||
|
endpointClosure: @escaping (Status.Id) -> StatusEndpoint) -> AnyPublisher<Never, Error> {
|
||||||
|
let client: MastodonAPIClient
|
||||||
|
|
||||||
|
do {
|
||||||
|
client = try MastodonAPIClient.forIdentity(id: identityId, environment: environment)
|
||||||
|
} catch {
|
||||||
|
return Fail(error: error).eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetchAs(identityId: identityId)
|
||||||
|
.flatMap { client.request(endpointClosure($0.id)) }
|
||||||
.flatMap { _ in mastodonAPIClient.request(StatusEndpoint.status(id: status.displayStatus.id)) }
|
.flatMap { _ in mastodonAPIClient.request(StatusEndpoint.status(id: status.displayStatus.id)) }
|
||||||
.flatMap(contentDatabase.insert(status:))
|
.flatMap(contentDatabase.insert(status:))
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
|
|
|
@ -533,8 +533,11 @@ private extension TableViewController {
|
||||||
handle(navigation: navigation)
|
handle(navigation: navigation)
|
||||||
case let .attachment(attachmentViewModel, statusViewModel):
|
case let .attachment(attachmentViewModel, statusViewModel):
|
||||||
present(attachmentViewModel: attachmentViewModel, statusViewModel: statusViewModel)
|
present(attachmentViewModel: attachmentViewModel, statusViewModel: statusViewModel)
|
||||||
case let .compose(inReplyToViewModel, redraft, directMessageTo):
|
case let .compose(identity, inReplyToViewModel, redraft, directMessageTo):
|
||||||
compose(inReplyToViewModel: inReplyToViewModel, redraft: redraft, directMessageTo: directMessageTo)
|
compose(identity: identity,
|
||||||
|
inReplyToViewModel: inReplyToViewModel,
|
||||||
|
redraft: redraft,
|
||||||
|
directMessageTo: directMessageTo)
|
||||||
case let .confirmDelete(statusViewModel, redraft):
|
case let .confirmDelete(statusViewModel, redraft):
|
||||||
confirmDelete(statusViewModel: statusViewModel, redraft: redraft)
|
confirmDelete(statusViewModel: statusViewModel, redraft: redraft)
|
||||||
case let .confirmUnfollow(accountViewModel):
|
case let .confirmUnfollow(accountViewModel):
|
||||||
|
@ -613,9 +616,13 @@ private extension TableViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func compose(inReplyToViewModel: StatusViewModel?, redraft: Status?, directMessageTo: AccountViewModel?) {
|
func compose(identity: Identity?,
|
||||||
|
inReplyToViewModel: StatusViewModel?,
|
||||||
|
redraft: Status?,
|
||||||
|
directMessageTo: AccountViewModel?) {
|
||||||
rootViewModel?.navigationViewModel?.presentedNewStatusViewModel = rootViewModel?.newStatusViewModel(
|
rootViewModel?.navigationViewModel?.presentedNewStatusViewModel = rootViewModel?.newStatusViewModel(
|
||||||
identityContext: viewModel.identityContext,
|
identityContext: viewModel.identityContext,
|
||||||
|
identity: identity,
|
||||||
inReplyTo: inReplyToViewModel,
|
inReplyTo: inReplyToViewModel,
|
||||||
redraft: redraft,
|
redraft: redraft,
|
||||||
directMessageTo: directMessageTo)
|
directMessageTo: directMessageTo)
|
||||||
|
|
|
@ -9,7 +9,10 @@ public enum CollectionItemEvent {
|
||||||
case refresh
|
case refresh
|
||||||
case navigation(Navigation)
|
case navigation(Navigation)
|
||||||
case attachment(AttachmentViewModel, StatusViewModel)
|
case attachment(AttachmentViewModel, StatusViewModel)
|
||||||
case compose(inReplyTo: StatusViewModel? = nil, redraft: Status? = nil, directMessageTo: AccountViewModel? = nil)
|
case compose(identity: Identity? = nil,
|
||||||
|
inReplyTo: StatusViewModel? = nil,
|
||||||
|
redraft: Status? = nil,
|
||||||
|
directMessageTo: AccountViewModel? = nil)
|
||||||
case confirmDelete(StatusViewModel, redraft: Bool)
|
case confirmDelete(StatusViewModel, redraft: Bool)
|
||||||
case confirmUnfollow(AccountViewModel)
|
case confirmUnfollow(AccountViewModel)
|
||||||
case confirmHideReblogs(AccountViewModel)
|
case confirmHideReblogs(AccountViewModel)
|
||||||
|
|
|
@ -26,6 +26,7 @@ public final class NewStatusViewModel: ObservableObject {
|
||||||
public init(allIdentitiesService: AllIdentitiesService,
|
public init(allIdentitiesService: AllIdentitiesService,
|
||||||
identityContext: IdentityContext,
|
identityContext: IdentityContext,
|
||||||
environment: AppEnvironment,
|
environment: AppEnvironment,
|
||||||
|
identity: Identity?,
|
||||||
inReplyTo: StatusViewModel?,
|
inReplyTo: StatusViewModel?,
|
||||||
redraft: Status?,
|
redraft: Status?,
|
||||||
directMessageTo: AccountViewModel?,
|
directMessageTo: AccountViewModel?,
|
||||||
|
@ -37,7 +38,7 @@ public final class NewStatusViewModel: ObservableObject {
|
||||||
events = eventsSubject.eraseToAnyPublisher()
|
events = eventsSubject.eraseToAnyPublisher()
|
||||||
visibility = redraft?.visibility
|
visibility = redraft?.visibility
|
||||||
?? inReplyTo?.visibility
|
?? inReplyTo?.visibility
|
||||||
?? identityContext.identity.preferences.postingDefaultVisibility
|
?? (identity ?? identityContext.identity).preferences.postingDefaultVisibility
|
||||||
|
|
||||||
if let inReplyTo = inReplyTo {
|
if let inReplyTo = inReplyTo {
|
||||||
switch inReplyTo.visibility {
|
switch inReplyTo.visibility {
|
||||||
|
@ -74,7 +75,7 @@ public final class NewStatusViewModel: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
mentions.formUnion(inReplyTo.mentions.map(\.acct)
|
mentions.formUnion(inReplyTo.mentions.map(\.acct)
|
||||||
.filter { $0 != identityContext.identity.account?.username }
|
.filter { $0 != (identity ?? identityContext.identity).account?.username }
|
||||||
.map("@".appending))
|
.map("@".appending))
|
||||||
|
|
||||||
compositionViewModel.text = mentions.joined(separator: " ").appending(" ")
|
compositionViewModel.text = mentions.joined(separator: " ").appending(" ")
|
||||||
|
@ -95,6 +96,10 @@ public final class NewStatusViewModel: ObservableObject {
|
||||||
compositionEventsSubject
|
compositionEventsSubject
|
||||||
.sink { [weak self] in self?.handle(event: $0) }
|
.sink { [weak self] in self?.handle(event: $0) }
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
if let identity = identity {
|
||||||
|
setIdentity(identity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ public extension RootViewModel {
|
||||||
|
|
||||||
func newStatusViewModel(
|
func newStatusViewModel(
|
||||||
identityContext: IdentityContext,
|
identityContext: IdentityContext,
|
||||||
|
identity: Identity? = nil,
|
||||||
inReplyTo: StatusViewModel? = nil,
|
inReplyTo: StatusViewModel? = nil,
|
||||||
redraft: Status? = nil,
|
redraft: Status? = nil,
|
||||||
directMessageTo: AccountViewModel? = nil) -> NewStatusViewModel {
|
directMessageTo: AccountViewModel? = nil) -> NewStatusViewModel {
|
||||||
|
@ -72,6 +73,7 @@ public extension RootViewModel {
|
||||||
allIdentitiesService: allIdentitiesService,
|
allIdentitiesService: allIdentitiesService,
|
||||||
identityContext: identityContext,
|
identityContext: identityContext,
|
||||||
environment: environment,
|
environment: environment,
|
||||||
|
identity: identity,
|
||||||
inReplyTo: inReplyTo,
|
inReplyTo: inReplyTo,
|
||||||
redraft: redraft,
|
redraft: redraft,
|
||||||
directMessageTo: directMessageTo,
|
directMessageTo: directMessageTo,
|
||||||
|
|
|
@ -37,6 +37,7 @@ public extension ShareExtensionNavigationViewModel {
|
||||||
allIdentitiesService: allIdentitiesService,
|
allIdentitiesService: allIdentitiesService,
|
||||||
identityContext: identityContext,
|
identityContext: identityContext,
|
||||||
environment: environment,
|
environment: environment,
|
||||||
|
identity: nil,
|
||||||
inReplyTo: nil,
|
inReplyTo: nil,
|
||||||
redraft: nil,
|
redraft: nil,
|
||||||
directMessageTo: nil,
|
directMessageTo: nil,
|
||||||
|
|
|
@ -242,17 +242,33 @@ public extension StatusViewModel {
|
||||||
.eraseToAnyPublisher())
|
.eraseToAnyPublisher())
|
||||||
}
|
}
|
||||||
|
|
||||||
func reply() {
|
func reply(identity: Identity? = nil) {
|
||||||
let replyViewModel = Self(statusService: statusService,
|
if let identity = identity {
|
||||||
identityContext: identityContext,
|
let identityContext = self.identityContext
|
||||||
eventsSubject: .init())
|
let configuration = self.configuration.reply()
|
||||||
|
|
||||||
replyViewModel.configuration = configuration.reply()
|
eventsSubject.send(statusService.asIdentity(id: identity.id).map {
|
||||||
|
let replyViewModel = Self(statusService: $0,
|
||||||
|
identityContext: identityContext,
|
||||||
|
eventsSubject: .init())
|
||||||
|
|
||||||
eventsSubject.send(
|
replyViewModel.configuration = configuration
|
||||||
Just(.compose(inReplyTo: replyViewModel))
|
|
||||||
.setFailureType(to: Error.self)
|
return CollectionItemEvent.compose(identity: identity, inReplyTo: replyViewModel)
|
||||||
.eraseToAnyPublisher())
|
}
|
||||||
|
.eraseToAnyPublisher())
|
||||||
|
} else {
|
||||||
|
let replyViewModel = Self(statusService: statusService,
|
||||||
|
identityContext: identityContext,
|
||||||
|
eventsSubject: .init())
|
||||||
|
|
||||||
|
replyViewModel.configuration = configuration.reply()
|
||||||
|
|
||||||
|
eventsSubject.send(
|
||||||
|
Just(.compose(inReplyTo: replyViewModel))
|
||||||
|
.setFailureType(to: Error.self)
|
||||||
|
.eraseToAnyPublisher())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toggleReblogged(identityId: Identity.Id? = nil) {
|
func toggleReblogged(identityId: Identity.Id? = nil) {
|
||||||
|
|
|
@ -605,6 +605,7 @@ private extension StatusView {
|
||||||
|
|
||||||
replyButton.setCountTitle(count: viewModel.repliesCount, isContextParent: isContextParent)
|
replyButton.setCountTitle(count: viewModel.repliesCount, isContextParent: isContextParent)
|
||||||
replyButton.isEnabled = isAuthenticated
|
replyButton.isEnabled = isAuthenticated
|
||||||
|
replyButton.menu = authenticatedIdentitiesMenu { viewModel.reply(identity: $0) }
|
||||||
|
|
||||||
if viewModel.identityContext.appPreferences.showReblogAndFavoriteCounts || isContextParent {
|
if viewModel.identityContext.appPreferences.showReblogAndFavoriteCounts || isContextParent {
|
||||||
reblogButton.setCountTitle(count: viewModel.reblogsCount, isContextParent: isContextParent)
|
reblogButton.setCountTitle(count: viewModel.reblogsCount, isContextParent: isContextParent)
|
||||||
|
|
Loading…
Reference in a new issue