2021-05-27 07:56:55 +02:00
|
|
|
//
|
|
|
|
// ProfileFieldSection.swift
|
|
|
|
// Mastodon
|
|
|
|
//
|
|
|
|
// Created by MainasuK Cirno on 2021-5-25.
|
|
|
|
//
|
|
|
|
|
|
|
|
import os
|
|
|
|
import UIKit
|
|
|
|
import Combine
|
2021-07-23 13:10:27 +02:00
|
|
|
import MastodonMeta
|
2021-05-27 07:56:55 +02:00
|
|
|
|
|
|
|
enum ProfileFieldSection: Equatable, Hashable {
|
|
|
|
case main
|
|
|
|
}
|
|
|
|
|
|
|
|
extension ProfileFieldSection {
|
|
|
|
static func collectionViewDiffableDataSource(
|
|
|
|
for collectionView: UICollectionView,
|
|
|
|
profileFieldCollectionViewCellDelegate: ProfileFieldCollectionViewCellDelegate,
|
|
|
|
profileFieldAddEntryCollectionViewCellDelegate: ProfileFieldAddEntryCollectionViewCellDelegate
|
|
|
|
) -> UICollectionViewDiffableDataSource<ProfileFieldSection, ProfileFieldItem> {
|
|
|
|
let dataSource = UICollectionViewDiffableDataSource<ProfileFieldSection, ProfileFieldItem>(collectionView: collectionView) {
|
|
|
|
[
|
|
|
|
weak profileFieldCollectionViewCellDelegate,
|
|
|
|
weak profileFieldAddEntryCollectionViewCellDelegate
|
|
|
|
] collectionView, indexPath, item in
|
|
|
|
switch item {
|
|
|
|
case .field(let field, let attribute):
|
|
|
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ProfileFieldCollectionViewCell.self), for: indexPath) as! ProfileFieldCollectionViewCell
|
|
|
|
|
|
|
|
// set key
|
2021-07-23 13:10:27 +02:00
|
|
|
do {
|
|
|
|
let mastodonContent = MastodonContent(content: field.name.value, emojis: attribute.emojiMeta.value)
|
|
|
|
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
|
|
|
|
cell.fieldView.titleMetaLabel.configure(content: metaContent)
|
|
|
|
} catch {
|
|
|
|
let content = PlaintextMetaContent(string: field.name.value)
|
|
|
|
cell.fieldView.titleMetaLabel.configure(content: content)
|
|
|
|
}
|
2021-05-27 07:56:55 +02:00
|
|
|
cell.fieldView.titleTextField.text = field.name.value
|
2021-05-27 08:57:20 +02:00
|
|
|
Publishers.CombineLatest(
|
|
|
|
field.name.removeDuplicates(),
|
2021-07-23 13:10:27 +02:00
|
|
|
attribute.emojiMeta.removeDuplicates()
|
2021-05-27 08:57:20 +02:00
|
|
|
)
|
|
|
|
.receive(on: RunLoop.main)
|
2021-07-23 13:10:27 +02:00
|
|
|
.sink { [weak cell] name, emojiMeta in
|
2021-05-27 08:57:20 +02:00
|
|
|
guard let cell = cell else { return }
|
2021-07-23 13:10:27 +02:00
|
|
|
do {
|
|
|
|
let mastodonContent = MastodonContent(content: name, emojis: emojiMeta)
|
|
|
|
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
|
|
|
|
cell.fieldView.titleMetaLabel.configure(content: metaContent)
|
|
|
|
} catch {
|
|
|
|
let content = PlaintextMetaContent(string: name)
|
|
|
|
cell.fieldView.titleMetaLabel.configure(content: content)
|
|
|
|
}
|
2021-07-07 09:39:57 +02:00
|
|
|
// only bind label. The text field should only set once
|
2021-05-27 08:57:20 +02:00
|
|
|
}
|
|
|
|
.store(in: &cell.disposeBag)
|
|
|
|
|
2021-05-27 07:56:55 +02:00
|
|
|
|
|
|
|
// set value
|
2021-07-23 13:10:27 +02:00
|
|
|
do {
|
|
|
|
let mastodonContent = MastodonContent(content: field.value.value, emojis: attribute.emojiMeta.value)
|
|
|
|
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
|
|
|
|
cell.fieldView.valueMetaLabel.configure(content: metaContent)
|
|
|
|
} catch {
|
|
|
|
let content = PlaintextMetaContent(string: field.value.value)
|
|
|
|
cell.fieldView.valueMetaLabel.configure(content: content)
|
|
|
|
}
|
2021-05-27 08:57:20 +02:00
|
|
|
cell.fieldView.valueTextField.text = field.value.value
|
2021-05-27 07:56:55 +02:00
|
|
|
Publishers.CombineLatest(
|
|
|
|
field.value.removeDuplicates(),
|
2021-07-23 13:10:27 +02:00
|
|
|
attribute.emojiMeta.removeDuplicates()
|
2021-05-27 07:56:55 +02:00
|
|
|
)
|
|
|
|
.receive(on: RunLoop.main)
|
2021-07-23 13:10:27 +02:00
|
|
|
.sink { [weak cell] value, emojiMeta in
|
2021-05-27 07:56:55 +02:00
|
|
|
guard let cell = cell else { return }
|
2021-07-23 13:10:27 +02:00
|
|
|
do {
|
|
|
|
let mastodonContent = MastodonContent(content: value, emojis: emojiMeta)
|
|
|
|
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
|
|
|
|
cell.fieldView.valueMetaLabel.configure(content: metaContent)
|
|
|
|
} catch {
|
|
|
|
let content = PlaintextMetaContent(string: value)
|
|
|
|
cell.fieldView.valueMetaLabel.configure(content: content)
|
|
|
|
}
|
2021-07-07 09:39:57 +02:00
|
|
|
// only bind label. The text field should only set once
|
2021-05-27 07:56:55 +02:00
|
|
|
}
|
|
|
|
.store(in: &cell.disposeBag)
|
|
|
|
|
|
|
|
// bind editing
|
|
|
|
if attribute.isEditing {
|
|
|
|
cell.fieldView.name
|
|
|
|
.removeDuplicates()
|
|
|
|
.receive(on: RunLoop.main)
|
|
|
|
.assign(to: \.value, on: field.name)
|
|
|
|
.store(in: &cell.disposeBag)
|
|
|
|
cell.fieldView.value
|
|
|
|
.removeDuplicates()
|
|
|
|
.receive(on: RunLoop.main)
|
|
|
|
.assign(to: \.value, on: field.value)
|
|
|
|
.store(in: &cell.disposeBag)
|
|
|
|
}
|
|
|
|
|
|
|
|
// setup editing state
|
2021-05-27 08:57:20 +02:00
|
|
|
cell.fieldView.titleTextField.isHidden = !attribute.isEditing
|
2021-05-27 07:56:55 +02:00
|
|
|
cell.fieldView.valueTextField.isHidden = !attribute.isEditing
|
2021-07-23 13:10:27 +02:00
|
|
|
cell.fieldView.titleMetaLabel.isHidden = attribute.isEditing
|
|
|
|
cell.fieldView.valueMetaLabel.isHidden = attribute.isEditing
|
2021-05-27 07:56:55 +02:00
|
|
|
|
|
|
|
// set control hidden
|
|
|
|
let isHidden = !attribute.isEditing
|
|
|
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: update editing state: %s", ((#file as NSString).lastPathComponent), #line, #function, isHidden ? "true" : "false")
|
|
|
|
cell.editButton.isHidden = isHidden
|
|
|
|
cell.reorderBarImageView.isHidden = isHidden
|
|
|
|
|
|
|
|
// update separator line
|
|
|
|
cell.bottomSeparatorLine.isHidden = attribute.isLast
|
|
|
|
|
|
|
|
cell.delegate = profileFieldCollectionViewCellDelegate
|
|
|
|
|
|
|
|
return cell
|
|
|
|
|
|
|
|
case .addEntry(let attribute):
|
|
|
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ProfileFieldAddEntryCollectionViewCell.self), for: indexPath) as! ProfileFieldAddEntryCollectionViewCell
|
|
|
|
|
|
|
|
cell.bottomSeparatorLine.isHidden = attribute.isLast
|
|
|
|
cell.delegate = profileFieldAddEntryCollectionViewCellDelegate
|
|
|
|
|
|
|
|
return cell
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dataSource.supplementaryViewProvider = { collectionView, kind, indexPath in
|
|
|
|
switch kind {
|
|
|
|
case UICollectionView.elementKindSectionHeader:
|
|
|
|
let reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.headerReuseIdentifer, for: indexPath) as! ProfileFieldCollectionViewHeaderFooterView
|
|
|
|
return reusableView
|
|
|
|
case UICollectionView.elementKindSectionFooter:
|
|
|
|
let reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.footerReuseIdentifer, for: indexPath) as! ProfileFieldCollectionViewHeaderFooterView
|
|
|
|
return reusableView
|
|
|
|
default:
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return dataSource
|
|
|
|
}
|
|
|
|
}
|