mirror of
https://github.com/mastodon/mastodon-ios.git
synced 2025-02-03 02:37:37 +01:00
Refactor compose intialization
- split ComposeContentViewModel.Kind into Destination (top level/reply) and an initial content string - replies get the mentions prepended to the initial content string
This commit is contained in:
parent
ebf3835403
commit
3661b5ce90
@ -117,7 +117,7 @@ extension DataSourceFacade {
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: provider.context,
|
||||
authContext: provider.authContext,
|
||||
kind: .reply(status: status)
|
||||
destination: .reply(parent: status)
|
||||
)
|
||||
_ = provider.coordinator.present(
|
||||
scene: .compose(viewModel: composeViewModel),
|
||||
|
@ -100,7 +100,7 @@ extension StatusTableViewControllerNavigateableCore where Self: DataSourceProvid
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: self.context,
|
||||
authContext: authContext,
|
||||
kind: .reply(status: status)
|
||||
destination: .reply(parent: status)
|
||||
)
|
||||
_ = self.coordinator.present(
|
||||
scene: .compose(viewModel: composeViewModel),
|
||||
|
@ -34,7 +34,8 @@ final class ComposeViewController: UIViewController, NeedsDependency {
|
||||
return ComposeContentViewModel(
|
||||
context: context,
|
||||
authContext: viewModel.authContext,
|
||||
kind: viewModel.kind
|
||||
destination: viewModel.destination,
|
||||
initialContent: viewModel.initialContent
|
||||
)
|
||||
}()
|
||||
private(set) lazy var composeContentViewController: ComposeContentViewController = {
|
||||
|
@ -29,7 +29,8 @@ final class ComposeViewModel {
|
||||
// input
|
||||
let context: AppContext
|
||||
let authContext: AuthContext
|
||||
let kind: ComposeContentViewModel.Kind
|
||||
let destination: ComposeContentViewModel.Destination
|
||||
let initialContent: String
|
||||
|
||||
let traitCollectionDidChangePublisher = CurrentValueSubject<Void, Never>(Void()) // use CurrentValueSubject to make initial event emit
|
||||
|
||||
@ -41,17 +42,19 @@ final class ComposeViewModel {
|
||||
init(
|
||||
context: AppContext,
|
||||
authContext: AuthContext,
|
||||
kind: ComposeContentViewModel.Kind
|
||||
destination: ComposeContentViewModel.Destination,
|
||||
initialContent: String = ""
|
||||
) {
|
||||
self.context = context
|
||||
self.authContext = authContext
|
||||
self.kind = kind
|
||||
self.destination = destination
|
||||
self.initialContent = initialContent
|
||||
// end init
|
||||
|
||||
self.title = {
|
||||
switch kind {
|
||||
case .post, .hashtag, .mention: return L10n.Scene.Compose.Title.newPost
|
||||
case .reply: return L10n.Scene.Compose.Title.newReply
|
||||
switch destination {
|
||||
case .topLevel: return L10n.Scene.Compose.Title.newPost
|
||||
case .reply: return L10n.Scene.Compose.Title.newReply
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
@ -162,10 +162,13 @@ extension HashtagTimelineViewController {
|
||||
|
||||
@objc private func composeBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||
let hashtag = "#" + viewModel.hashtag
|
||||
UITextChecker.learnWord(hashtag)
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: context,
|
||||
authContext: viewModel.authContext,
|
||||
kind: .hashtag(hashtag: viewModel.hashtag)
|
||||
destination: .topLevel,
|
||||
initialContent: hashtag
|
||||
)
|
||||
_ = coordinator.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil))
|
||||
}
|
||||
|
@ -538,10 +538,13 @@ extension ProfileViewController {
|
||||
@objc private func replyBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||
guard let mastodonUser = viewModel.user else { return }
|
||||
let mention = "@" + mastodonUser.acct
|
||||
UITextChecker.learnWord(mention)
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: context,
|
||||
authContext: viewModel.authContext,
|
||||
kind: .mention(user: mastodonUser.asRecord)
|
||||
destination: .topLevel,
|
||||
initialContent: mention
|
||||
)
|
||||
_ = coordinator.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil))
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ extension MainTabBarController {
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: context,
|
||||
authContext: authContext,
|
||||
kind: .post
|
||||
destination: .topLevel
|
||||
)
|
||||
_ = coordinator.present(scene: .compose(viewModel: composeViewModel), from: nil, transition: .modal(animated: true, completion: nil))
|
||||
}
|
||||
@ -804,7 +804,7 @@ extension MainTabBarController {
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: context,
|
||||
authContext: authContext,
|
||||
kind: .post
|
||||
destination: .topLevel
|
||||
)
|
||||
_ = coordinator.present(scene: .compose(viewModel: composeViewModel), from: nil, transition: .modal(animated: true, completion: nil))
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ extension SidebarViewController: UICollectionViewDelegate {
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: context,
|
||||
authContext: authContext,
|
||||
kind: .post
|
||||
destination: .topLevel
|
||||
)
|
||||
_ = coordinator.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil))
|
||||
default:
|
||||
|
@ -117,7 +117,7 @@ extension ThreadViewController {
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: context,
|
||||
authContext: viewModel.authContext,
|
||||
kind: .reply(status: threadContext.status)
|
||||
destination: .reply(parent: threadContext.status)
|
||||
)
|
||||
_ = coordinator.present(
|
||||
scene: .compose(viewModel: composeViewModel),
|
||||
|
@ -185,7 +185,7 @@ extension SceneDelegate {
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: AppContext.shared,
|
||||
authContext: authContext,
|
||||
kind: .post
|
||||
destination: .topLevel
|
||||
)
|
||||
_ = coordinator?.present(scene: .compose(viewModel: composeViewModel), from: nil, transition: .modal(animated: true, completion: nil))
|
||||
logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): present compose scene")
|
||||
|
@ -47,10 +47,7 @@ extension ComposeContentViewModel {
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
switch kind {
|
||||
case .post:
|
||||
break
|
||||
case .reply(let status):
|
||||
if case .reply(let status) = destination {
|
||||
let cell = composeReplyToTableViewCell
|
||||
// bind frame publisher
|
||||
cell.$framePublisher
|
||||
@ -66,10 +63,6 @@ extension ComposeContentViewModel {
|
||||
guard let replyTo = status.object(in: context.managedObjectContext) else { return }
|
||||
cell.statusView.configure(status: replyTo)
|
||||
}
|
||||
case .hashtag:
|
||||
break
|
||||
case .mention:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,7 +76,7 @@ extension ComposeContentViewModel: UITableViewDataSource {
|
||||
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
switch Section.allCases[section] {
|
||||
case .replyTo:
|
||||
switch kind {
|
||||
switch destination {
|
||||
case .reply: return 1
|
||||
default: return 0
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public final class ComposeContentViewModel: NSObject, ObservableObject {
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let kind: Kind
|
||||
let destination: Destination
|
||||
weak var delegate: ComposeContentViewModelDelegate?
|
||||
|
||||
@Published var viewLayoutFrame = ViewLayoutFrame()
|
||||
@ -59,8 +59,7 @@ public final class ComposeContentViewModel: NSObject, ObservableObject {
|
||||
customEmojiPickerInputViewModel.configure(textInput: textView)
|
||||
}
|
||||
}
|
||||
// for hashtag: "#<hashtag> "
|
||||
// for mention: "@<mention> "
|
||||
// allow dismissing the compose view without confirmation if content == intialContent
|
||||
@Published public var initialContent = ""
|
||||
@Published public var content = ""
|
||||
@Published public var contentWeightedLength = 0
|
||||
@ -138,11 +137,12 @@ public final class ComposeContentViewModel: NSObject, ObservableObject {
|
||||
public init(
|
||||
context: AppContext,
|
||||
authContext: AuthContext,
|
||||
kind: Kind
|
||||
destination: Destination,
|
||||
initialContent: String
|
||||
) {
|
||||
self.context = context
|
||||
self.authContext = authContext
|
||||
self.kind = kind
|
||||
self.destination = destination
|
||||
self.visibility = {
|
||||
// default private when user locked
|
||||
var visibility: Mastodon.Entity.Status.Visibility = {
|
||||
@ -152,8 +152,7 @@ public final class ComposeContentViewModel: NSObject, ObservableObject {
|
||||
return author.locked ? .private : .public
|
||||
}()
|
||||
// set visibility for reply post
|
||||
switch kind {
|
||||
case .reply(let record):
|
||||
if case .reply(let record) = destination {
|
||||
context.managedObjectContext.performAndWait {
|
||||
guard let status = record.object(in: context.managedObjectContext) else {
|
||||
assertionFailure()
|
||||
@ -173,8 +172,6 @@ public final class ComposeContentViewModel: NSObject, ObservableObject {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
return visibility
|
||||
}()
|
||||
@ -185,7 +182,8 @@ public final class ComposeContentViewModel: NSObject, ObservableObject {
|
||||
// end init
|
||||
|
||||
// setup initial value
|
||||
switch kind {
|
||||
let initialContentWithSpace = initialContent.isEmpty ? "" : initialContent + " "
|
||||
switch destination {
|
||||
case .reply(let record):
|
||||
context.managedObjectContext.performAndWait {
|
||||
guard let status = record.object(in: context.managedObjectContext) else {
|
||||
@ -214,29 +212,15 @@ public final class ComposeContentViewModel: NSObject, ObservableObject {
|
||||
}
|
||||
|
||||
let initialComposeContent = mentionAccts.joined(separator: " ")
|
||||
let preInsertedContent: String? = initialComposeContent.isEmpty ? nil : initialComposeContent + " "
|
||||
self.initialContent = preInsertedContent ?? ""
|
||||
self.content = preInsertedContent ?? ""
|
||||
let preInsertedContent = initialComposeContent.isEmpty ? "" : initialComposeContent + " "
|
||||
self.initialContent = preInsertedContent + initialContentWithSpace
|
||||
self.content = preInsertedContent + initialContentWithSpace
|
||||
}
|
||||
case .hashtag(let hashtag):
|
||||
let initialComposeContent = "#" + hashtag
|
||||
UITextChecker.learnWord(initialComposeContent)
|
||||
let preInsertedContent = initialComposeContent + " "
|
||||
self.initialContent = preInsertedContent
|
||||
self.content = preInsertedContent
|
||||
case .mention(let record):
|
||||
context.managedObjectContext.performAndWait {
|
||||
guard let user = record.object(in: context.managedObjectContext) else { return }
|
||||
let initialComposeContent = "@" + user.acct
|
||||
UITextChecker.learnWord(initialComposeContent)
|
||||
let preInsertedContent = initialComposeContent + " "
|
||||
self.initialContent = preInsertedContent
|
||||
self.content = preInsertedContent
|
||||
}
|
||||
case .post:
|
||||
break
|
||||
case .topLevel:
|
||||
self.initialContent = initialContentWithSpace
|
||||
self.content = initialContentWithSpace
|
||||
}
|
||||
|
||||
|
||||
// set limit
|
||||
let _configuration: Mastodon.Entity.Instance.Configuration? = {
|
||||
var configuration: Mastodon.Entity.Instance.Configuration? = nil
|
||||
@ -443,11 +427,9 @@ extension ComposeContentViewModel {
|
||||
}
|
||||
|
||||
extension ComposeContentViewModel {
|
||||
public enum Kind {
|
||||
case post
|
||||
case hashtag(hashtag: String)
|
||||
case mention(user: ManagedObjectRecord<MastodonUser>)
|
||||
case reply(status: ManagedObjectRecord<Status>)
|
||||
public enum Destination {
|
||||
case topLevel
|
||||
case reply(parent: ManagedObjectRecord<Status>)
|
||||
}
|
||||
|
||||
public enum ScrollViewState {
|
||||
@ -530,10 +512,10 @@ extension ComposeContentViewModel {
|
||||
return MastodonStatusPublisher(
|
||||
author: author,
|
||||
replyTo: {
|
||||
switch self.kind {
|
||||
case .reply(let status): return status
|
||||
default: return nil
|
||||
if case .reply(let status) = destination {
|
||||
return status
|
||||
}
|
||||
return nil
|
||||
}(),
|
||||
isContentWarningComposing: isContentWarningActive,
|
||||
contentWarning: contentWarning,
|
||||
|
Loading…
x
Reference in New Issue
Block a user