mirror of
https://github.com/mastodon/mastodon-ios
synced 2025-04-11 22:58:02 +02:00
fix: resolve #83 the text editor input content offset reset after input character issue
This commit is contained in:
parent
56bd6d0ae8
commit
6c973ed17c
@ -220,7 +220,7 @@
|
|||||||
DB68A05D25E9055900CFDF14 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DB68A05C25E9055900CFDF14 /* Settings.bundle */; };
|
DB68A05D25E9055900CFDF14 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DB68A05C25E9055900CFDF14 /* Settings.bundle */; };
|
||||||
DB68A06325E905E000CFDF14 /* UIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68A06225E905E000CFDF14 /* UIApplication.swift */; };
|
DB68A06325E905E000CFDF14 /* UIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68A06225E905E000CFDF14 /* UIApplication.swift */; };
|
||||||
DB6B35182601FA3400DC1E11 /* MastodonAttachmentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B35172601FA3400DC1E11 /* MastodonAttachmentService.swift */; };
|
DB6B35182601FA3400DC1E11 /* MastodonAttachmentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B35172601FA3400DC1E11 /* MastodonAttachmentService.swift */; };
|
||||||
DB6B351E2601FAEE00DC1E11 /* ComposeStatusAttachmentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentTableViewCell.swift */; };
|
DB6B351E2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift */; };
|
||||||
DB6C8C0F25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6C8C0E25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift */; };
|
DB6C8C0F25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6C8C0E25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift */; };
|
||||||
DB71FD2C25F86A5100512AE1 /* AvatarStackContainerButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB71FD2B25F86A5100512AE1 /* AvatarStackContainerButton.swift */; };
|
DB71FD2C25F86A5100512AE1 /* AvatarStackContainerButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB71FD2B25F86A5100512AE1 /* AvatarStackContainerButton.swift */; };
|
||||||
DB71FD3625F8A16C00512AE1 /* APIService+Persist+PersistMemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB71FD3525F8A16C00512AE1 /* APIService+Persist+PersistMemo.swift */; };
|
DB71FD3625F8A16C00512AE1 /* APIService+Persist+PersistMemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB71FD3525F8A16C00512AE1 /* APIService+Persist+PersistMemo.swift */; };
|
||||||
@ -618,7 +618,7 @@
|
|||||||
DB68A05C25E9055900CFDF14 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
|
DB68A05C25E9055900CFDF14 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
|
||||||
DB68A06225E905E000CFDF14 /* UIApplication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIApplication.swift; sourceTree = "<group>"; };
|
DB68A06225E905E000CFDF14 /* UIApplication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIApplication.swift; sourceTree = "<group>"; };
|
||||||
DB6B35172601FA3400DC1E11 /* MastodonAttachmentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonAttachmentService.swift; sourceTree = "<group>"; };
|
DB6B35172601FA3400DC1E11 /* MastodonAttachmentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonAttachmentService.swift; sourceTree = "<group>"; };
|
||||||
DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusAttachmentTableViewCell.swift; sourceTree = "<group>"; };
|
DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusAttachmentCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
DB6C8C0E25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+Error.swift"; sourceTree = "<group>"; };
|
DB6C8C0E25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+Error.swift"; sourceTree = "<group>"; };
|
||||||
DB71FD2B25F86A5100512AE1 /* AvatarStackContainerButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarStackContainerButton.swift; sourceTree = "<group>"; };
|
DB71FD2B25F86A5100512AE1 /* AvatarStackContainerButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarStackContainerButton.swift; sourceTree = "<group>"; };
|
||||||
DB71FD3525F8A16C00512AE1 /* APIService+Persist+PersistMemo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Persist+PersistMemo.swift"; sourceTree = "<group>"; };
|
DB71FD3525F8A16C00512AE1 /* APIService+Persist+PersistMemo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Persist+PersistMemo.swift"; sourceTree = "<group>"; };
|
||||||
@ -1458,7 +1458,7 @@
|
|||||||
children = (
|
children = (
|
||||||
DB789A2A25F9F7AB0071ACA0 /* ComposeRepliedToStatusContentCollectionViewCell.swift */,
|
DB789A2A25F9F7AB0071ACA0 /* ComposeRepliedToStatusContentCollectionViewCell.swift */,
|
||||||
DB789A1B25F9F76A0071ACA0 /* ComposeStatusContentCollectionViewCell.swift */,
|
DB789A1B25F9F76A0071ACA0 /* ComposeStatusContentCollectionViewCell.swift */,
|
||||||
DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentTableViewCell.swift */,
|
DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift */,
|
||||||
DB87D4442609BE0500D12C0D /* ComposeStatusPollOptionCollectionViewCell.swift */,
|
DB87D4442609BE0500D12C0D /* ComposeStatusPollOptionCollectionViewCell.swift */,
|
||||||
DB87D4502609CF1E00D12C0D /* ComposeStatusPollOptionAppendEntryCollectionViewCell.swift */,
|
DB87D4502609CF1E00D12C0D /* ComposeStatusPollOptionAppendEntryCollectionViewCell.swift */,
|
||||||
DB2FF50F260B113300ADA9FE /* ComposeStatusPollExpiresOptionCollectionViewCell.swift */,
|
DB2FF50F260B113300ADA9FE /* ComposeStatusPollExpiresOptionCollectionViewCell.swift */,
|
||||||
@ -2296,7 +2296,7 @@
|
|||||||
0FAA101C25E10E760017CCDE /* UIFont.swift in Sources */,
|
0FAA101C25E10E760017CCDE /* UIFont.swift in Sources */,
|
||||||
2D38F1D525CD465300561493 /* HomeTimelineViewController.swift in Sources */,
|
2D38F1D525CD465300561493 /* HomeTimelineViewController.swift in Sources */,
|
||||||
DB98338825C945ED00AD9700 /* Assets.swift in Sources */,
|
DB98338825C945ED00AD9700 /* Assets.swift in Sources */,
|
||||||
DB6B351E2601FAEE00DC1E11 /* ComposeStatusAttachmentTableViewCell.swift in Sources */,
|
DB6B351E2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift in Sources */,
|
||||||
2DA7D04425CA52B200804E11 /* TimelineLoaderTableViewCell.swift in Sources */,
|
2DA7D04425CA52B200804E11 /* TimelineLoaderTableViewCell.swift in Sources */,
|
||||||
DB87D44B2609C11900D12C0D /* PollOptionView.swift in Sources */,
|
DB87D44B2609C11900D12C0D /* PollOptionView.swift in Sources */,
|
||||||
DBE3CDFB261C6CA500430CC6 /* FavoriteViewModel.swift in Sources */,
|
DBE3CDFB261C6CA500430CC6 /* FavoriteViewModel.swift in Sources */,
|
||||||
|
@ -92,7 +92,12 @@ extension ComposeStatusSection {
|
|||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { text in
|
.sink { text in
|
||||||
// self size input cell
|
// self size input cell
|
||||||
|
// needs restore content offset to resolve issue #83
|
||||||
|
let oldContentOffset = collectionView.contentOffset
|
||||||
collectionView.collectionViewLayout.invalidateLayout()
|
collectionView.collectionViewLayout.invalidateLayout()
|
||||||
|
collectionView.layoutIfNeeded()
|
||||||
|
collectionView.contentOffset = oldContentOffset
|
||||||
|
|
||||||
// bind input data
|
// bind input data
|
||||||
attribute.composeContent.value = text
|
attribute.composeContent.value = text
|
||||||
}
|
}
|
||||||
@ -187,6 +192,7 @@ extension ComposeStatusSection {
|
|||||||
case .pollOption(let attribute):
|
case .pollOption(let attribute):
|
||||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ComposeStatusPollOptionCollectionViewCell.self), for: indexPath) as! ComposeStatusPollOptionCollectionViewCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ComposeStatusPollOptionCollectionViewCell.self), for: indexPath) as! ComposeStatusPollOptionCollectionViewCell
|
||||||
cell.pollOptionView.optionTextField.text = attribute.option.value
|
cell.pollOptionView.optionTextField.text = attribute.option.value
|
||||||
|
cell.pollOptionView.optionTextField.placeholder = L10n.Scene.Compose.Poll.optionNumber(indexPath.item + 1)
|
||||||
cell.pollOption
|
cell.pollOption
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.assign(to: \.value, on: attribute.option)
|
.assign(to: \.value, on: attribute.option)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// ComposeStatusAttachmentTableViewCell.swift
|
// ComposeStatusAttachmentCollectionViewCell.swift
|
||||||
// Mastodon
|
// Mastodon
|
||||||
//
|
//
|
||||||
// Created by MainasuK Cirno on 2021-3-17.
|
// Created by MainasuK Cirno on 2021-3-17.
|
@ -68,18 +68,7 @@ final class ComposeViewController: UIViewController, NeedsDependency {
|
|||||||
|
|
||||||
let composeToolbarView = ComposeToolbarView()
|
let composeToolbarView = ComposeToolbarView()
|
||||||
var composeToolbarViewBottomLayoutConstraint: NSLayoutConstraint!
|
var composeToolbarViewBottomLayoutConstraint: NSLayoutConstraint!
|
||||||
let composeToolbarBackgroundView: UIView = {
|
let composeToolbarBackgroundView = UIView()
|
||||||
let backgroundView = UIView()
|
|
||||||
// set keyboard background to make the keyboard blurred color fixed
|
|
||||||
backgroundView.backgroundColor = UIColor(dynamicProvider: { traitCollection -> UIColor in
|
|
||||||
// avoid elevated color
|
|
||||||
switch traitCollection.userInterfaceStyle {
|
|
||||||
case .light: return .white
|
|
||||||
default: return .black
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return backgroundView
|
|
||||||
}()
|
|
||||||
|
|
||||||
private(set) lazy var imagePicker: PHPickerViewController = {
|
private(set) lazy var imagePicker: PHPickerViewController = {
|
||||||
var configuration = PHPickerConfiguration()
|
var configuration = PHPickerConfiguration()
|
||||||
@ -203,13 +192,26 @@ extension ComposeViewController {
|
|||||||
.sink(receiveValue: { [weak self] isShow, state, endFrame, isCustomEmojiComposing in
|
.sink(receiveValue: { [weak self] isShow, state, endFrame, isCustomEmojiComposing in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
let extraMargin: CGFloat = {
|
||||||
|
if self.view.safeAreaInsets.bottom == .zero {
|
||||||
|
// needs extra margin for zero inset device to workaround UIKit issue
|
||||||
|
return self.composeToolbarView.frame.height
|
||||||
|
} else {
|
||||||
|
// default some magic 16 extra margin
|
||||||
|
return 16
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// update keyboard background color
|
||||||
|
|
||||||
guard isShow, state == .dock else {
|
guard isShow, state == .dock else {
|
||||||
self.collectionView.contentInset.bottom = self.view.safeAreaInsets.bottom
|
self.collectionView.contentInset.bottom = self.view.safeAreaInsets.bottom + extraMargin
|
||||||
self.collectionView.verticalScrollIndicatorInsets.bottom = self.view.safeAreaInsets.bottom
|
self.collectionView.verticalScrollIndicatorInsets.bottom = self.view.safeAreaInsets.bottom + extraMargin
|
||||||
UIView.animate(withDuration: 0.3) {
|
UIView.animate(withDuration: 0.3) {
|
||||||
self.composeToolbarViewBottomLayoutConstraint.constant = self.view.safeAreaInsets.bottom
|
self.composeToolbarViewBottomLayoutConstraint.constant = self.view.safeAreaInsets.bottom
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
self.updateKeyboardBackground(isKeyboardDisplay: isShow)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// isShow AND dock state
|
// isShow AND dock state
|
||||||
@ -218,22 +220,23 @@ extension ComposeViewController {
|
|||||||
let contentFrame = self.view.convert(self.collectionView.frame, to: nil)
|
let contentFrame = self.view.convert(self.collectionView.frame, to: nil)
|
||||||
let padding = contentFrame.maxY - endFrame.minY
|
let padding = contentFrame.maxY - endFrame.minY
|
||||||
guard padding > 0 else {
|
guard padding > 0 else {
|
||||||
self.collectionView.contentInset.bottom = self.view.safeAreaInsets.bottom
|
self.collectionView.contentInset.bottom = self.view.safeAreaInsets.bottom + extraMargin
|
||||||
self.collectionView.verticalScrollIndicatorInsets.bottom = self.view.safeAreaInsets.bottom
|
self.collectionView.verticalScrollIndicatorInsets.bottom = self.view.safeAreaInsets.bottom + extraMargin
|
||||||
UIView.animate(withDuration: 0.3) {
|
UIView.animate(withDuration: 0.3) {
|
||||||
self.composeToolbarViewBottomLayoutConstraint.constant = self.view.safeAreaInsets.bottom
|
self.composeToolbarViewBottomLayoutConstraint.constant = self.view.safeAreaInsets.bottom
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
self.updateKeyboardBackground(isKeyboardDisplay: false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// add 16pt margin
|
self.collectionView.contentInset.bottom = padding + extraMargin
|
||||||
self.collectionView.contentInset.bottom = padding + 16
|
self.collectionView.verticalScrollIndicatorInsets.bottom = padding + extraMargin
|
||||||
self.collectionView.verticalScrollIndicatorInsets.bottom = padding + 16
|
|
||||||
UIView.animate(withDuration: 0.3) {
|
UIView.animate(withDuration: 0.3) {
|
||||||
self.composeToolbarViewBottomLayoutConstraint.constant = padding
|
self.composeToolbarViewBottomLayoutConstraint.constant = padding
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
self.updateKeyboardBackground(isKeyboardDisplay: isShow)
|
||||||
})
|
})
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
@ -474,6 +477,20 @@ extension ComposeViewController {
|
|||||||
return imagePicker
|
return imagePicker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func updateKeyboardBackground(isKeyboardDisplay: Bool) {
|
||||||
|
guard isKeyboardDisplay else {
|
||||||
|
composeToolbarBackgroundView.backgroundColor = Asset.Scene.Compose.toolbarBackground.color
|
||||||
|
return
|
||||||
|
}
|
||||||
|
composeToolbarBackgroundView.backgroundColor = UIColor(dynamicProvider: { traitCollection -> UIColor in
|
||||||
|
// avoid elevated color
|
||||||
|
switch traitCollection.userInterfaceStyle {
|
||||||
|
case .light: return .white
|
||||||
|
default: return .black
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ComposeViewController {
|
extension ComposeViewController {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user