mastodon-ios/Mastodon/Diffiable/Profile/ProfileFieldSection.swift

172 lines
8.0 KiB
Swift
Raw Normal View History

Release v1.3.0 (#347) * New translations app.json (Thai) * New translations app.json (Spanish) * New translations Localizable.stringsdict (Spanish) * New translations app.json (Thai) * New translations app.json (Thai) * feat: adapt the app to async & await. Update timeline UI * fix: update the Xcode version to fix the CI failure * fix: remove unavailable framework import * fix: project dependency issue * feat: add content warning for post spoiler * feat: add content warning for post media * chore: update version to 1.3.0 (92) * New translations app.json (French) * New translations Intents.strings (French) * New translations app.json (Thai) * feat: update report flow * feat: update setting scene UI * feat: update status content warning UI * feat: add notification gap fetcher * chore: update version to 1.3.0 (93) * feat: add video player for audio/video kind media * chore: update version to 1.3.0 (94) * fix: text strip wrong color in the Dark Mode issue * chore: remove spoiler toggle animation for table cell * fix: add missing shadow for compose publish button * fix: add missing margin for timeline with horizontal regular size class * fix: profile segmented controls missing margin issue * fix: the profile segmented control use wrong selection tint color under force light UI style issue * fix: add notification count clear logic back * fix: add missing home timeline bottom fetcher * fix: [WIP] add suggestion account scene back * New translations app.json (Kabyle) * New translations ios-infoPlist.json (Kabyle) * New translations Localizable.stringsdict (Kabyle) * New translations Intents.strings (Kabyle) * New translations Intents.stringsdict (Kabyle) * feat: make the home timeline readable for VoiceOver * chore: update version to 1.3.0 (95) * New translations app.json (French) * New translations Intents.strings (French) * New translations app.json (Kabyle) * New translations ios-infoPlist.json (Kabyle) * New translations Localizable.stringsdict (Kabyle) * New translations Intents.strings (Kabyle) * New translations Intents.stringsdict (Kabyle) * New translations Localizable.stringsdict (French) * New translations app.json (Kabyle) * New translations app.json (French) * chore: update action toolbar icons * fix: instal state missing issue * fix: follow push notification deep-link not works issue * fix: foreground notification not trigger tab bell icon update issue * feat: add notification timeline fetcher * feat: add content warning toggle button * chore: update version to 1.3.0 (96) * New translations app.json (Thai) * New translations app.json (Russian) * New translations app.json (Kurmanji (Kurdish)) * New translations app.json (Scottish Gaelic) * New translations app.json (Welsh) * New translations app.json (Hindi) * New translations app.json (Spanish, Argentina) * New translations app.json (Indonesian) * New translations app.json (Portuguese, Brazilian) * New translations app.json (English) * New translations app.json (Chinese Traditional) * New translations app.json (Chinese Simplified) * New translations app.json (Swedish) * New translations app.json (Portuguese) * New translations app.json (Dutch) * New translations app.json (Korean) * New translations app.json (Japanese) * New translations app.json (Basque) * New translations app.json (German) * New translations app.json (Danish) * New translations app.json (Catalan) * New translations app.json (Arabic) * New translations app.json (Spanish) * New translations app.json (Romanian) * New translations app.json (Kabyle) * New translations app.json (French) * New translations app.json (Swedish, Finland) * New translations app.json (Spanish, Argentina) * New translations app.json (Kurmanji (Kurdish)) * fix: notification i18n word typo * New translations app.json (Thai) * New translations app.json (Swedish) * New translations Localizable.stringsdict (Swedish) * New translations app.json (Swedish, Finland) * New translations app.json (Kurmanji (Kurdish)) * New translations app.json (Scottish Gaelic) * New translations app.json (Welsh) * New translations app.json (Hindi) * New translations app.json (Indonesian) * New translations app.json (Portuguese, Brazilian) * New translations app.json (English) * New translations app.json (Chinese Traditional) * New translations app.json (Chinese Simplified) * New translations app.json (Russian) * New translations app.json (Portuguese) * New translations app.json (Dutch) * New translations app.json (Korean) * New translations app.json (Japanese) * New translations app.json (Basque) * New translations app.json (German) * New translations app.json (Danish) * New translations app.json (Catalan) * New translations app.json (Arabic) * New translations app.json (Spanish) * New translations app.json (Romanian) * New translations app.json (Kabyle) * New translations app.json (French) * New translations Intents.strings (Swedish) * New translations app.json (Swedish) * New translations Localizable.stringsdict (Japanese) * New translations app.json (Thai) * New translations app.json (Thai) * New translations Localizable.stringsdict (Swedish) * New translations app.json (Kabyle) * New translations ios-infoPlist.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (French) * New translations app.json (French) * feat: restore scroll-to-top tap gesture for TabBar * feat: add cell height cache for user timeline * feat: display no results when profile field empty * New translations app.json (Chinese Traditional) * New translations app.json (Chinese Traditional) * New translations Intents.strings (Japanese) * feat: make status detail accessible * chore: restore the appearance settings * chore: update version to 1.3.0 (97) * New translations app.json (Kabyle) * New translations Intents.strings (Japanese) * New translations app.json (Swedish) * New translations app.json (Basque) * New translations app.json (Basque) * chore: add a11y hint for profile dashboard * feat: add media interaction for notification timeline * New translations app.json (Chinese Simplified) * New translations app.json (Chinese Simplified) * chore: update i18n strings * fix: setting switch use wrong tint color issue * chore: restore RTL layout for post content * chore: update profile relationship button UI * chore: update color panel * fix: post reblog header may display empty reblogger name issue * fix: wrong reply header redirect logic issue * feat: restore post filter supports * chore: update version to 1.3.0 (98) * chore: update post content sensitive style * fix: blurhash image not display during image loading issue * chore: update version to 1.3.0 (99) * feat: restore user recommend scene * chore: update badge tint color * feat: restore keyboard shortcut supports * chore: update version to 1.3.0 (100) * fix: relationship background use wrong color when force dark style * fix: player button icon not reset issue * chore: update version to 1.3.0 (101) * fix: profile relationship button fill the width on iPad issue * fix: inputAssistantItem duplicate setup issue * chore: update textView minimum height from 88 to 64 * chore: update version to 1.3.0 (102) * chore: update status timeline margin * chore: update sidebar background color * fix: split view column state after size class transition not stable issue * chore: update notification timeline margin * chore: update profile header and segmented bar margin * fix: profile segmented bar use wrong tint color when force Dark Mode issue * chore: update horizontal compact mode notification timeline margin looks like * chore: update version to 1.3.0 (103) * feat: dismiss image preview when tap empty area * chore: update version to 1.3.0 (104) * New translations app.json (Italian) * New translations ios-infoPlist.json (Italian) * New translations Localizable.stringsdict (Italian) * New translations Intents.strings (Italian) * New translations Intents.stringsdict (Italian) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Japanese) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Spanish) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Kabyle) * New translations ios-infoPlist.json (Kabyle) * New translations Localizable.stringsdict (Kabyle) * New translations Localizable.stringsdict (Kabyle) * New translations Intents.strings (Kabyle) * New translations app.json (Kabyle) * New translations Intents.strings (Kabyle) * New translations Intents.stringsdict (Kabyle) * New translations app.json (Kabyle) * New translations app.json (Scottish Gaelic) * New translations app.json (Scottish Gaelic) * New translations app.json (Thai) * New translations app.json (Thai) * feat: add UITests for snapshots * feat: add snapshot UITest and document * New translations app.json (Thai) * feat: add notification snapshot * chore: add domain and update guide for the snapshot UITest * chore: use the first photo for compose snapshot * New translations app.json (Thai) * New translations app.json (German) * New translations app.json (German) * chore: update settings scene UI * chore: update i18n for open link words * chore: update i18n resources * fix: share extension not accept plaintext content issue. resolve #335 * chore: update version to 1.3.0 (105) * New translations app.json (Japanese) * New translations app.json (Japanese) * New translations app.json (Japanese) * feat: add onion domain ATS exception rule. resolve #338 * chore: update app version footer and i18n strings * chore: update version to 1.3.0 (106) * chore: update version to 1.3.0 (108) * Handle onboarding authentication errors in /api/v1/instance * New translations app.json (Kurmanji (Kurdish)) * New translations app.json (Kurmanji (Kurdish)) * chore: update Xcode schemes index * chore: update the snapshot documents and UITests * chore: update i18n resources. resolve #343 * chore: retain the API model semantic * fix: force LTR for some text fields. #318 * fix: textView break IME input issue. resolve #342 * chore: update version to 1.3.0 (109) * chore: update README * chore: fix typo * chore: add bug report template and contributing document Co-authored-by: Eugen Rochko <eugen@zeonfederated.com> Co-authored-by: Zac West <zacwest@gmail.com>
2022-03-29 11:51:14 +02:00
//
// ProfileFieldSection.swift
// Mastodon
//
// Created by MainasuK Cirno on 2021-5-25.
//
import os
import UIKit
import Combine
import MastodonMeta
import MastodonLocalization
enum ProfileFieldSection: Equatable, Hashable {
case main
}
extension ProfileFieldSection {
struct Configuration {
weak var profileFieldCollectionViewCellDelegate: ProfileFieldCollectionViewCellDelegate?
weak var profileFieldEditCollectionViewCellDelegate: ProfileFieldEditCollectionViewCellDelegate?
}
static func diffableDataSource(
collectionView: UICollectionView,
context: AppContext,
configuration: Configuration
) -> UICollectionViewDiffableDataSource<ProfileFieldSection, ProfileFieldItem> {
collectionView.register(ProfileFieldCollectionViewHeaderFooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.headerReuseIdentifer)
collectionView.register(ProfileFieldCollectionViewHeaderFooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.footerReuseIdentifer)
let fieldCellRegistration = UICollectionView.CellRegistration<ProfileFieldCollectionViewCell, ProfileFieldItem> { cell, indexPath, item in
guard case let .field(field) = item else { return }
// set key
do {
let mastodonContent = MastodonContent(content: field.name.value, emojis: field.emojiMeta)
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
cell.keyMetaLabel.configure(content: metaContent)
} catch {
let content = PlaintextMetaContent(string: field.name.value)
cell.keyMetaLabel.configure(content: content)
}
// set value
do {
let mastodonContent = MastodonContent(content: field.value.value, emojis: field.emojiMeta)
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
cell.valueMetaLabel.configure(content: metaContent)
} catch {
let content = PlaintextMetaContent(string: field.value.value)
cell.valueMetaLabel.configure(content: content)
}
// set background
var backgroundConfiguration = UIBackgroundConfiguration.listPlainCell()
backgroundConfiguration.backgroundColor = UIColor.secondarySystemBackground
cell.backgroundConfiguration = backgroundConfiguration
cell.delegate = configuration.profileFieldCollectionViewCellDelegate
}
let editFieldCellRegistration = UICollectionView.CellRegistration<ProfileFieldEditCollectionViewCell, ProfileFieldItem> { cell, indexPath, item in
guard case let .editField(field) = item else { return }
cell.keyTextField.text = field.name.value
cell.valueTextField.text = field.value.value
NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: cell.keyTextField)
.compactMap { $0.object as? UITextField }
.map { $0.text ?? "" }
.removeDuplicates()
.assign(to: \.value, on: field.name)
.store(in: &cell.disposeBag)
NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: cell.valueTextField)
.compactMap { $0.object as? UITextField }
.map { $0.text ?? "" }
.removeDuplicates()
.assign(to: \.value, on: field.value)
.store(in: &cell.disposeBag)
// set background
var backgroundConfiguration = UIBackgroundConfiguration.listPlainCell()
backgroundConfiguration.backgroundColor = UIColor.secondarySystemBackground
cell.backgroundConfiguration = backgroundConfiguration
cell.delegate = configuration.profileFieldEditCollectionViewCellDelegate
}
let addEntryCellRegistration = UICollectionView.CellRegistration<ProfileFieldAddEntryCollectionViewCell, ProfileFieldItem> { cell, indexPath, item in
guard case .addEntry = item else { return }
var backgroundConfiguration = UIBackgroundConfiguration.listPlainCell()
backgroundConfiguration.backgroundColorTransformer = .init { [weak cell] _ in
guard let cell = cell else {
return .secondarySystemBackground
}
let state = cell.configurationState
if state.isHighlighted || state.isSelected {
return .secondarySystemBackground.withAlphaComponent(0.5)
} else {
return .secondarySystemBackground
}
}
cell.backgroundConfiguration = backgroundConfiguration
}
let noResultCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, ProfileFieldItem> { cell, indexPath, item in
guard case .noResult = item else { return }
var contentConfiguration = cell.defaultContentConfiguration()
contentConfiguration.text = L10n.Scene.Search.Searching.EmptyState.noResults // FIXME:
contentConfiguration.textProperties.alignment = .center
cell.contentConfiguration = contentConfiguration
var backgroundConfiguration = UIBackgroundConfiguration.listPlainCell()
backgroundConfiguration.backgroundColorTransformer = .init { _ in
return .secondarySystemBackground
}
cell.backgroundConfiguration = backgroundConfiguration
}
let dataSource = UICollectionViewDiffableDataSource<ProfileFieldSection, ProfileFieldItem>(collectionView: collectionView) { collectionView, indexPath, item in
switch item {
case .field:
return collectionView.dequeueConfiguredReusableCell(
using: fieldCellRegistration,
for: indexPath,
item: item
)
case .editField:
return collectionView.dequeueConfiguredReusableCell(
using: editFieldCellRegistration,
for: indexPath,
item: item
)
case .addEntry:
return collectionView.dequeueConfiguredReusableCell(
using: addEntryCellRegistration,
for: indexPath,
item: item
)
case .noResult:
return collectionView.dequeueConfiguredReusableCell(
using: noResultCellRegistration,
for: indexPath,
item: item
)
}
}
dataSource.supplementaryViewProvider = { collectionView, kind, indexPath in
switch kind {
case UICollectionView.elementKindSectionHeader:
let reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.headerReuseIdentifer, for: indexPath) as! ProfileFieldCollectionViewHeaderFooterView
reusableView.frame.size.height = 20
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
}
}