Skip to content

Commit

Permalink
Add control over list scrolling position. Improve test stability (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
BB9z authored Dec 5, 2023
1 parent 33d4062 commit 3f63a46
Show file tree
Hide file tree
Showing 8 changed files with 348 additions and 136 deletions.
74 changes: 74 additions & 0 deletions App/General/List/BottomAlignTableView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// BottomAlignTableView.swift
// B9ChatAI
//
// Copyright © 2023 B9Software. All rights reserved.
//

import UIKit

class BottomAlignTableView: UITableView {

override var contentSize: CGSize {
didSet {
if oldValue == contentSize {
return
}
debug("contentSize: \(oldValue) => \(contentSize)")
adjustContentInset()

let yDiff = contentSize.height - oldValue.height
var offset = contentOffset
offset.y += yDiff
if offset.y < -safeAreaInsets.top {
debug("reach top, skip")
return
}
debug("will adjust offset: \(offset)")
contentOffset = offset
ignoralNextOffsetUpdate = CFAbsoluteTimeGetCurrent()
}
}

private var ignoralNextOffsetUpdate: CFAbsoluteTime = 0
override var contentOffset: CGPoint {
get {
super.contentOffset
}
set {
if ignoralNextOffsetUpdate > 0 {
if CFAbsoluteTimeGetCurrent() - ignoralNextOffsetUpdate < 1e-3 {
debug("contentOffset: ignoral system adjust")
return
}
ignoralNextOffsetUpdate = 0
}
let oldValue = super.contentOffset
super.contentOffset = newValue
if oldValue.y != newValue.y {
debug("contentOffset: \(oldValue.y) => \(newValue.y)")
}
}
}

override func safeAreaInsetsDidChange() {
super.safeAreaInsetsDidChange()
adjustContentInset()
}

private func adjustContentInset() {
let oldValue = contentInset.top
let newValue = max(bounds.height - safeAreaInsets.top - safeAreaInsets.bottom - contentSize.height, 0)
if abs(newValue - oldValue) < 1 {
return
}
var inset = contentInset
inset.top = newValue
contentInset = inset
debug("adjust inset: \(inset)")
}

private func debug(_ value: @autoclosure () -> CustomStringConvertible) {
// print(value().description)
}
}
17 changes: 17 additions & 0 deletions App/Scene/Message/ConversationDetailVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -509,3 +509,20 @@ extension ConversationDetailViewController: UITextViewDelegate {
}
}
}

#if DEBUG
import Debugger
extension ConversationDetailViewController: DebugActionSource {
func debugActionItems() -> [DebugActionItem] {
[
DebugActionItem("列表布局") {
let view = self.listView!
debugPrint(view.safeAreaInsets)
debugPrint(view.safeAreaLayoutGuide.layoutFrame)
debugPrint(view.contentSize)
debugPrint(view.contentOffset)
}
]
}
}
#endif
85 changes: 1 addition & 84 deletions App/Scene/Message/MessageListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,90 +5,7 @@
// Copyright © 2023 B9Software. All rights reserved.
//

import B9Action
import UIKit


class MessageListView: UITableView {
/*
var debugText: String {
String(format: "ox%5.1f, ct%5.1f, %@", contentOffset.y, contentSize.height, bounds.size.debugDescription)
}

override var contentOffset: CGPoint {
get { super.contentOffset }
set {
if isKeepBottom { return }
super.contentOffset = newValue
}
}

override var bounds: CGRect {
didSet {
if contentSize.height > bounds.height {
// let diff = oldValue.height - bounds.height
// guard diff > 0 else { return }
// var offset = contentOffset
// offset.y += diff
// contentOffset = offset
}
}
}

override var contentSize: CGSize {
willSet {
if newValue == contentSize { return }
AppLog().debug("\(debugText) <= begin contentSize will => \(newValue.height)")
beginKeepBottom(newContentSize: newValue)
}
didSet {
if oldValue == contentSize { return }
endKeepBottom()
AppLog().debug("\(debugText) <= end keep")
}
}

private var offsetChange: CGFloat? {
didSet {
AppLog().debug("toBottomTrack = \(offsetChange?.description ?? "nil")")
}
}

var isKeepBottom = false
func beginKeepBottom(newContentSize: CGSize) {
if newContentSize.height < bounds.height {
return
}
if offsetChange != nil {
AppLog().warning("begin but already in keep bottom")
return
}
offsetChange = newContentSize.height - bounds.maxY
isKeepBottom = true
}

func endKeepBottom() {
defer { isKeepBottom = false }
if contentSize.height < bounds.height {
return
}

guard let diff = offsetChange else {
AppLog().warning("end but already in keep bottom")
return
}
defer { offsetChange = nil }
guard diff > 0 else {
AppLog().debug("igrnoal \(diff)")
return
}

var offset = contentOffset
offset.y += diff
super.contentOffset = offset
AppLog().debug("\(debugText) <= after update offset")
}
*/

private(set) var keepBottomVisiableCell: (some UITableViewCell, IndexPath)?
class MessageListView: BottomAlignTableView {
}
4 changes: 2 additions & 2 deletions App/Supporting Files/Shared.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
// Configuration settings file format documentation can be found at:
// https://help.apple.com/xcode/#/dev745c5c974

MARKETING_VERSION = 0.5.1;
CURRENT_PROJECT_VERSION = 60;
MARKETING_VERSION = 0.5.2;
CURRENT_PROJECT_VERSION = 62;
20 changes: 20 additions & 0 deletions B9ChatAI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@
D5D006D229D273F50063B366 /* EngineManageVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D006D129D273F50063B366 /* EngineManageVC.swift */; };
D5D641452A0E18A200921E98 /* NumberTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D641442A0E18A200921E98 /* NumberTextField.swift */; };
D5D7BCD829D4611100AF6DF5 /* B9Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D7BCD729D4611100AF6DF5 /* B9Keychain.swift */; };
D5D7E15F2B1C90CD005D4E0A /* TableHeightCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D5D7E15D2B1C90CD005D4E0A /* TableHeightCell.xib */; };
D5D7E1602B1C90CD005D4E0A /* BottomAlignTableViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D7E15E2B1C90CD005D4E0A /* BottomAlignTableViewTests.swift */; };
D5D7E1652B1CDA30005D4E0A /* BottomAlignTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D7E1642B1CDA30005D4E0A /* BottomAlignTableView.swift */; };
D5DB4C22241E39EA00832A0A /* UIKit+DynamicType.m in Sources */ = {isa = PBXBuildFile; fileRef = D5DB4C21241E39EA00832A0A /* UIKit+DynamicType.m */; };
D5DC60C124CA84BC00FBB147 /* ApplicationCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55959CD20AB95640019D733 /* ApplicationCondition.swift */; };
D5E80580226F403D00901C41 /* MBBottomLayoutView.m in Sources */ = {isa = PBXBuildFile; fileRef = D5E8057F226F403D00901C41 /* MBBottomLayoutView.m */; };
Expand Down Expand Up @@ -435,6 +438,9 @@
D5D4CC6E2043A6ED002FE9F0 /* OCBridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OCBridging-Header.h"; sourceTree = "<group>"; };
D5D641442A0E18A200921E98 /* NumberTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NumberTextField.swift; sourceTree = "<group>"; };
D5D7BCD729D4611100AF6DF5 /* B9Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = B9Keychain.swift; sourceTree = "<group>"; };
D5D7E15D2B1C90CD005D4E0A /* TableHeightCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TableHeightCell.xib; sourceTree = "<group>"; };
D5D7E15E2B1C90CD005D4E0A /* BottomAlignTableViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BottomAlignTableViewTests.swift; sourceTree = "<group>"; };
D5D7E1642B1CDA30005D4E0A /* BottomAlignTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomAlignTableView.swift; sourceTree = "<group>"; };
D5DB4C20241E39EA00832A0A /* UIKit+DynamicType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIKit+DynamicType.h"; sourceTree = "<group>"; };
D5DB4C21241E39EA00832A0A /* UIKit+DynamicType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIKit+DynamicType.m"; sourceTree = "<group>"; };
D5E8057E226F403C00901C41 /* MBBottomLayoutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBBottomLayoutView.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1027,6 +1033,7 @@
isa = PBXGroup;
children = (
D5B49EE71C41133A00847925 /* TableView */,
D5D7E1642B1CDA30005D4E0A /* BottomAlignTableView.swift */,
D51E92C029DB2DE000922497 /* ListGeneral.swift */,
D5031C3B25C04C9200C2849E /* ListStateView.swift */,
D56B65E52B1B27620023C82A /* MBCollectionViewColumnLayout.swift */,
Expand Down Expand Up @@ -1106,11 +1113,21 @@
path = AppIntents;
sourceTree = "<group>";
};
D5D7E1582B1C90A1005D4E0A /* UI */ = {
isa = PBXGroup;
children = (
D5D7E15E2B1C90CD005D4E0A /* BottomAlignTableViewTests.swift */,
D5D7E15D2B1C90CD005D4E0A /* TableHeightCell.xib */,
);
path = UI;
sourceTree = "<group>";
};
D5E8FA6F29CF088C00C3D753 /* UnitTests */ = {
isa = PBXGroup;
children = (
D57EF74529E427B300CD101E /* Networking */,
D5E8FA7B29CF23F800C3D753 /* Support */,
D5D7E1582B1C90A1005D4E0A /* UI */,
D5810C7829D9AFE00073F8C8 /* CDEntityFetchTests.swift */,
D5810C8029D9C2410073F8C8 /* ConversationManagerTests.swift */,
D52112AB2A33612100599DDB /* ConversationTests.swift */,
Expand Down Expand Up @@ -1457,6 +1474,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D5D7E15F2B1C90CD005D4E0A /* TableHeightCell.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1602,6 +1620,7 @@
D57D784E29C8B28C003099D6 /* B9NavigationController.swift in Sources */,
D507BC3929CCA12A001E2298 /* B9RootViewController.swift in Sources */,
D544CBDD29FA3A0A00A4F6F6 /* B9WindowSceneDelegate.swift in Sources */,
D5D7E1652B1CDA30005D4E0A /* BottomAlignTableView.swift in Sources */,
D587D48829E967FF0085CFCE /* BoxViews.swift in Sources */,
D52A04E520F85F2600F535ED /* Button.swift in Sources */,
D5E8FA6729CEEDF900C3D753 /* CD.xcdatamodeld in Sources */,
Expand Down Expand Up @@ -1750,6 +1769,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D5D7E1602B1C90CD005D4E0A /* BottomAlignTableViewTests.swift in Sources */,
D5810C7F29D9B8150073F8C8 /* CDEntity+Test.swift in Sources */,
D5810C7929D9AFE10073F8C8 /* CDEntityFetchTests.swift in Sources */,
D5810C8129D9C2410073F8C8 /* ConversationManagerTests.swift in Sources */,
Expand Down
Loading

0 comments on commit 3f63a46

Please sign in to comment.