mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 21:39:12 +00:00
Diffable fade animations (#1343)
* animate only 2 seconds after the appearence * scrolling is stable * code improvement * comment and removing code that is not necessary anymore * feature flag * comment * better code * the day divider ID is the timestamp itself as ISO * Apply suggestions from code review Co-authored-by: Alfonso Grillo <alfogrillo@gmail.com> * format fix --------- Co-authored-by: Alfonso Grillo <alfogrillo@gmail.com>
This commit is contained in:
parent
48dbbfb4d0
commit
f46abbaf9e
@ -36,6 +36,7 @@ final class AppSettings {
|
||||
case shareLocationEnabled
|
||||
case hasShownWelcomeScreen
|
||||
case notificationSettingsEnabled
|
||||
case timelineDiffableAnimationsEnabled
|
||||
}
|
||||
|
||||
private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier
|
||||
@ -226,4 +227,7 @@ final class AppSettings {
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.notificationSettingsEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var notificationSettingsEnabled
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.timelineDiffableAnimationsEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var timelineDiffableAnimationsEnabled
|
||||
}
|
||||
|
@ -97,6 +97,8 @@ class TimelineTableViewController: UIViewController {
|
||||
private var previousLayout: LayoutDescriptor?
|
||||
/// Whether or not the view has been shown on screen yet.
|
||||
private var hasAppearedOnce = false
|
||||
/// Whether the scroll and the animations should happen
|
||||
private var shouldAnimate = false
|
||||
|
||||
init(coordinator: TimelineView.Coordinator,
|
||||
timelineStyle: TimelineStyle,
|
||||
@ -168,6 +170,11 @@ class TimelineTableViewController: UIViewController {
|
||||
guard !hasAppearedOnce else { return }
|
||||
scrollToBottom(animated: false)
|
||||
hasAppearedOnce = true
|
||||
// This is to prevent the SS proxy issue that forces a full refresh of all the timeline items
|
||||
// the first time the timeline is opened
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
||||
self.shouldAnimate = ServiceLocator.shared.settings.timelineDiffableAnimationsEnabled
|
||||
}
|
||||
}
|
||||
|
||||
override func didMove(toParent parent: UIViewController?) {
|
||||
@ -231,8 +238,7 @@ class TimelineTableViewController: UIViewController {
|
||||
return cell
|
||||
}
|
||||
|
||||
// dataSource?.defaultRowAnimation = .automatic
|
||||
|
||||
dataSource?.defaultRowAnimation = .fade
|
||||
tableView.delegate = self
|
||||
}
|
||||
|
||||
@ -249,13 +255,14 @@ class TimelineTableViewController: UIViewController {
|
||||
snapshot.appendSections([.main])
|
||||
snapshot.appendItems(timelineItemsIDs)
|
||||
|
||||
MXLog.verbose("DIFF: \(snapshot.itemIdentifiers.difference(from: dataSource.snapshot().itemIdentifiers))")
|
||||
dataSource.apply(snapshot, animatingDifferences: false)
|
||||
|
||||
// Probably redundant now we observe content size changes…
|
||||
// Leaving in place for the release and will reassess after.
|
||||
updateTopPadding()
|
||||
|
||||
let currentSnapshot = dataSource.snapshot()
|
||||
MXLog.verbose("DIFF: \(snapshot.itemIdentifiers.difference(from: currentSnapshot.itemIdentifiers))")
|
||||
|
||||
// We only animate if the last item has changed
|
||||
// We don't care to animate backpagination since we want to keep the scrolling position when that happens
|
||||
let animated = shouldAnimate && snapshot.itemIdentifiers.last != currentSnapshot.itemIdentifiers.last
|
||||
dataSource.apply(snapshot, animatingDifferences: animated)
|
||||
|
||||
if previousLayout.isBottomVisible {
|
||||
scrollToBottom(animated: false)
|
||||
} else if let pinnedItem = previousLayout.pinnedItem {
|
||||
|
@ -32,6 +32,7 @@ struct DeveloperOptionsScreenViewStateBindings {
|
||||
var locationEventsEnabled: Bool
|
||||
var shareLocationEnabled: Bool
|
||||
var notificationSettingsEnabled: Bool
|
||||
var timelineDiffableAnimationsEnabled: Bool
|
||||
}
|
||||
|
||||
enum DeveloperOptionsScreenViewAction {
|
||||
@ -42,5 +43,6 @@ enum DeveloperOptionsScreenViewAction {
|
||||
case changedLocationEventsEnabled
|
||||
case changedShareLocationEnabled
|
||||
case changedNotificationSettingsEnabled
|
||||
case changedTimelineDiffableAnimationsEnabled
|
||||
case clearCache
|
||||
}
|
||||
|
@ -32,7 +32,8 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve
|
||||
isEncryptionSyncEnabled: appSettings.isEncryptionSyncEnabled,
|
||||
locationEventsEnabled: appSettings.locationEventsEnabled,
|
||||
shareLocationEnabled: appSettings.shareLocationEnabled,
|
||||
notificationSettingsEnabled: appSettings.notificationSettingsEnabled)
|
||||
notificationSettingsEnabled: appSettings.notificationSettingsEnabled,
|
||||
timelineDiffableAnimationsEnabled: appSettings.timelineDiffableAnimationsEnabled)
|
||||
let state = DeveloperOptionsScreenViewState(bindings: bindings)
|
||||
|
||||
super.init(initialViewState: state)
|
||||
@ -58,6 +59,8 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve
|
||||
appSettings.shareLocationEnabled = state.bindings.shareLocationEnabled
|
||||
case .changedNotificationSettingsEnabled:
|
||||
appSettings.notificationSettingsEnabled = state.bindings.notificationSettingsEnabled
|
||||
case .changedTimelineDiffableAnimationsEnabled:
|
||||
appSettings.timelineDiffableAnimationsEnabled = state.bindings.timelineDiffableAnimationsEnabled
|
||||
case .clearCache:
|
||||
callback?(.clearCache)
|
||||
}
|
||||
|
@ -79,6 +79,13 @@ struct DeveloperOptionsScreen: View {
|
||||
.onChange(of: context.userSuggestionsEnabled) { _ in
|
||||
context.send(viewAction: .changedUserSuggestionsEnabled)
|
||||
}
|
||||
|
||||
Toggle(isOn: $context.timelineDiffableAnimationsEnabled) {
|
||||
Text("Enable diffable animations in the timeline")
|
||||
}
|
||||
.onChange(of: context.timelineDiffableAnimationsEnabled) { _ in
|
||||
context.send(viewAction: .changedTimelineDiffableAnimationsEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
|
@ -355,8 +355,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
let date = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000))
|
||||
let dateString = date.formatted(date: .complete, time: .omitted)
|
||||
|
||||
// Separators without stable identifiers cause UI glitches
|
||||
let identifier = "\(chunkIndex)-\(dateString)"
|
||||
let identifier = date.formatted(.iso8601.dateSeparator(.dash))
|
||||
return SeparatorRoomTimelineItem(id: .init(timelineID: identifier), text: dateString)
|
||||
case .readMarker:
|
||||
return ReadMarkerRoomTimelineItem()
|
||||
|
Loading…
x
Reference in New Issue
Block a user