This commit is contained in:
Justin Mazzocchi 2020-12-17 16:17:17 -08:00
parent 0c5a3de66b
commit d86bbda4c2
No known key found for this signature in database
GPG Key ID: E223E6937AAFB01C
11 changed files with 27 additions and 76 deletions

View File

@ -1,9 +0,0 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
import GRDB
struct CompositionRecord: Codable, FetchableRecord, PersistableRecord {
let id: Composition.Id
let text: String
}

View File

@ -1,28 +0,0 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Combine
import Foundation
import GRDB
import Mastodon
public class Composition {
public let id: Id
@Published public var text: String
@Published public var attachments: [Attachment]
public init(id: Id, text: String) {
self.id = id
self.text = text
attachments = []
}
}
public extension Composition {
typealias Id = UUID
}
extension Composition {
convenience init(record: CompositionRecord) {
self.init(id: record.id, text: record.text)
}
}

View File

@ -3,7 +3,7 @@
import UIKit
import ViewModels
final class NewStatusDataSource: UICollectionViewDiffableDataSource<Int, Composition.Id> {
final class NewStatusDataSource: UICollectionViewDiffableDataSource<Int, CompositionViewModel.Id> {
private let updateQueue =
DispatchQueue(label: "com.metabolist.metatext.new-status-data-source.update-queue")
@ -20,7 +20,7 @@ final class NewStatusDataSource: UICollectionViewDiffableDataSource<Int, Composi
}
}
override func apply(_ snapshot: NSDiffableDataSourceSnapshot<Int, Composition.Id>,
override func apply(_ snapshot: NSDiffableDataSourceSnapshot<Int, CompositionViewModel.Id>,
animatingDifferences: Bool = true,
completion: (() -> Void)? = nil) {
updateQueue.async {

View File

@ -8,14 +8,13 @@ import Mastodon
import UserNotifications
public struct AppEnvironment {
public let uuid: () -> UUID
let session: URLSession
let webAuthSessionType: WebAuthSession.Type
let keychain: Keychain.Type
let userDefaults: UserDefaults
let userNotificationClient: UserNotificationClient
let reduceMotion: () -> Bool
let uuid: () -> UUID
let inMemoryContent: Bool
let fixtureDatabase: IdentityDatabase?

View File

@ -1,5 +0,0 @@
// Copyright © 2020 Metabolist. All rights reserved.
import DB
public typealias Composition = DB.Composition

View File

@ -212,8 +212,8 @@ public extension IdentityService {
progress: progress)
}
func post(compositions: [Composition]) -> AnyPublisher<Never, Error> {
fatalError()
// func post(compositions: [Composition]) -> AnyPublisher<Never, Error> {
// fatalError()
// guard let composition = compositions.first else { fatalError() }
// guard let attachment = composition.attachments.first else { fatalError() }
@ -235,7 +235,7 @@ public extension IdentityService {
// return mastodonAPIClient.request(StatusEndpoint.post(components))
// .ignoreOutput()
// .eraseToAnyPublisher()
}
// }
func service(timeline: Timeline) -> TimelineService {
TimelineService(timeline: timeline, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)

View File

@ -61,7 +61,7 @@ class NewStatusViewController: UICollectionViewController {
guard let self = self else { return }
let oldSnapshot = self.dataSource.snapshot()
let newSnapshot = [$0.map(\.composition.id)].snapshot()
let newSnapshot = [$0.map(\.id)].snapshot()
let diff = newSnapshot.itemIdentifiers.difference(from: oldSnapshot.itemIdentifiers)
self.dataSource.apply(newSnapshot) {
@ -75,11 +75,8 @@ class NewStatusViewController: UICollectionViewController {
// Invalidate the collection view layout on anything that could change the height of a cell
viewModel.$compositionViewModels
.flatMap { Publishers.MergeMany($0.map(\.composition.$text)) }
.map { _ in () }
.merge(with: viewModel.$compositionViewModels
.flatMap { Publishers.MergeMany($0.map(\.objectWillChange)) }
.map { _ in () })
.flatMap { Publishers.MergeMany($0.map(\.objectWillChange)) }
.receive(on: DispatchQueue.main)
.sink { [weak self] in self?.collectionView.collectionViewLayout.invalidateLayout() }
.store(in: &cancellables)
@ -89,6 +86,7 @@ class NewStatusViewController: UICollectionViewController {
viewModel.$alertItem
.compactMap { $0 }
.receive(on: DispatchQueue.main)
.sink { [weak self] in self?.present(alertItem: $0) }
.store(in: &cancellables)
}

View File

@ -6,7 +6,9 @@ import Mastodon
import ServiceLayer
public final class CompositionViewModel: ObservableObject {
public let composition: Composition
public let id = Id()
@Published public var text = ""
@Published public private(set) var attachments = [Attachment]()
@Published public private(set) var isPostable = false
@Published public private(set) var identification: Identification
@Published public private(set) var attachmentUpload: AttachmentUpload?
@ -14,19 +16,19 @@ public final class CompositionViewModel: ObservableObject {
private let eventsSubject: PassthroughSubject<Event, Never>
private var cancellables = Set<AnyCancellable>()
init(composition: Composition,
identification: Identification,
init(identification: Identification,
identificationPublisher: AnyPublisher<Identification, Never>,
eventsSubject: PassthroughSubject<Event, Never>) {
self.composition = composition
self.identification = identification
self.eventsSubject = eventsSubject
identificationPublisher.assign(to: &$identification)
composition.$text.map { !$0.isEmpty }.removeDuplicates().assign(to: &$isPostable)
$text.map { !$0.isEmpty }.removeDuplicates().assign(to: &$isPostable)
}
}
public extension CompositionViewModel {
typealias Id = UUID
enum Event {
case insertAfter(CompositionViewModel)
case presentMediaPicker(CompositionViewModel)
@ -70,7 +72,7 @@ public extension CompositionViewModel {
self?.eventsSubject.send(.error(error))
}
} receiveValue: { [weak self] in
self?.composition.attachments.append($0)
self?.attachments.append($0)
}
.store(in: &cancellables)
}

View File

@ -1,5 +0,0 @@
// Copyright © 2020 Metabolist. All rights reserved.
import ServiceLayer
public typealias Composition = ServiceLayer.Composition

View File

@ -67,21 +67,20 @@ public extension NewStatusViewModel {
}
func post() {
identification.service.post(compositions: compositionViewModels.map(\.composition))
.receive(on: DispatchQueue.main)
.handleEvents(
receiveSubscription: { [weak self] _ in self?.loading = true },
receiveCompletion: { [weak self] _ in self?.loading = false })
.assignErrorsToAlertItem(to: \.alertItem, on: self)
.sink { _ in }
.store(in: &cancellables)
// identification.service.post(compositions: compositionViewModels.map(\.composition))
// .receive(on: DispatchQueue.main)
// .handleEvents(
// receiveSubscription: { [weak self] _ in self?.loading = true },
// receiveCompletion: { [weak self] _ in self?.loading = false })
// .assignErrorsToAlertItem(to: \.alertItem, on: self)
// .sink { _ in }
// .store(in: &cancellables)
}
}
private extension NewStatusViewModel {
func newCompositionViewModel() -> CompositionViewModel {
CompositionViewModel(
composition: .init(id: environment.uuid(), text: ""),
identification: identification,
identificationPublisher: $identification.eraseToAnyPublisher(),
eventsSubject: itemEventsSubject)

View File

@ -43,7 +43,7 @@ extension CompositionView: UIContentView {
extension CompositionView: UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
compositionConfiguration.viewModel.composition.text = textView.text
compositionConfiguration.viewModel.text = textView.text
}
}