Folder improvements

This commit is contained in:
Ali 2020-03-07 15:14:57 +04:00
parent a7c2818fa9
commit ec69b23599
12 changed files with 58 additions and 25 deletions

View File

@ -167,7 +167,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
super.init(context: context, navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData), mediaAccessoryPanelVisibility: .always, locationBroadcastPanelSource: .summary) super.init(context: context, navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData), mediaAccessoryPanelVisibility: .always, locationBroadcastPanelSource: .summary)
self.hasTabBarItemContextAction = true self.tabBarItemContextActionType = .whenActive
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
@ -2260,16 +2260,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
if presetList.isEmpty { strongSelf.push(chatListFilterPresetListController(context: strongSelf.context, updated: { _ in }))
if let navigationController = strongSelf.navigationController as? NavigationController {
var viewControllers = navigationController.viewControllers
//viewControllers.append(chatListFilterPresetListController(context: strongSelf.context, updated: { _ in }))
viewControllers.append(chatListFilterPresetController(context: strongSelf.context, currentPreset: nil, updated: { _ in }))
navigationController.setViewControllers(viewControllers, animated: true)
}
} else {
strongSelf.push(chatListFilterPresetListController(context: strongSelf.context, updated: { _ in }))
}
}) })
}))) })))

View File

@ -232,7 +232,7 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry {
case .includePeersHeader, .addIncludePeer, .includeCategory, .includePeer, .includePeerInfo: case .includePeersHeader, .addIncludePeer, .includeCategory, .includePeer, .includePeerInfo:
return ChatListFilterPresetControllerSection.includePeers.rawValue return ChatListFilterPresetControllerSection.includePeers.rawValue
case .excludePeersHeader, .addExcludePeer, .excludeCategory, .excludePeer, .excludePeerInfo: case .excludePeersHeader, .addExcludePeer, .excludeCategory, .excludePeer, .excludePeerInfo:
return ChatListFilterPresetControllerSection.includePeers.rawValue return ChatListFilterPresetControllerSection.excludePeers.rawValue
} }
} }
@ -859,7 +859,9 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
let (state, includePeers, excludePeers) = stateWithPeers let (state, includePeers, excludePeers) = stateWithPeers
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
let _ = attemptNavigationImpl?() if attemptNavigationImpl?() ?? true {
dismissImpl?()
}
}) })
let rightNavigationButton = ItemListNavigationButton(content: .text(currentPreset == nil ? presentationData.strings.Common_Create : presentationData.strings.Common_Done), style: .bold, enabled: state.isComplete, action: { let rightNavigationButton = ItemListNavigationButton(content: .text(currentPreset == nil ? presentationData.strings.Common_Create : presentationData.strings.Common_Done), style: .bold, enabled: state.isComplete, action: {
let state = stateValue.with { $0 } let state = stateValue.with { $0 }

View File

@ -305,7 +305,7 @@ public func chatListFilterPresetListController(context: AccountContext, updated:
}) })
} }
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Filters"), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Folders"), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: chatListFilterPresetListControllerEntries(presentationData: presentationData, state: state, filters: filtersWithCounts, suggestedFilters: suggestedFilters, settings: filterSettings), style: .blocks, animateChanges: true) let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: chatListFilterPresetListControllerEntries(presentationData: presentationData, state: state, filters: filtersWithCounts, suggestedFilters: suggestedFilters, settings: filterSettings), style: .blocks, animateChanges: true)
return (controllerState, (listState, arguments)) return (controllerState, (listState, arguments))

View File

@ -387,6 +387,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
private var reorderingItemPosition: (initial: CGFloat, offset: CGFloat)? private var reorderingItemPosition: (initial: CGFloat, offset: CGFloat)?
private var reorderingAutoScrollAnimator: ConstantDisplayLinkAnimator? private var reorderingAutoScrollAnimator: ConstantDisplayLinkAnimator?
private var reorderedItemIds: [ChatListFilterTabEntryId]? private var reorderedItemIds: [ChatListFilterTabEntryId]?
private lazy var hapticFeedback = { HapticFeedback() }()
private var currentParams: (size: CGSize, sideInset: CGFloat, filters: [ChatListFilterTabEntry], selectedFilter: ChatListFilterTabEntryId?, isReordering: Bool, isEditing: Bool, transitionFraction: CGFloat, presentationData: PresentationData)? private var currentParams: (size: CGSize, sideInset: CGFloat, filters: [ChatListFilterTabEntry], selectedFilter: ChatListFilterTabEntryId?, isReordering: Bool, isEditing: Bool, transitionFraction: CGFloat, presentationData: PresentationData)?
@ -443,6 +444,8 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
for (id, itemNode) in strongSelf.itemNodes { for (id, itemNode) in strongSelf.itemNodes {
let itemFrame = itemNode.view.convert(itemNode.bounds, to: strongSelf.view) let itemFrame = itemNode.view.convert(itemNode.bounds, to: strongSelf.view)
if itemFrame.contains(point) { if itemFrame.contains(point) {
strongSelf.hapticFeedback.impact()
strongSelf.reorderingItem = id strongSelf.reorderingItem = id
itemNode.frame = itemFrame itemNode.frame = itemFrame
strongSelf.reorderingAutoScrollAnimator = ConstantDisplayLinkAnimator(update: { strongSelf.reorderingAutoScrollAnimator = ConstantDisplayLinkAnimator(update: {
@ -507,6 +510,8 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
targetIndex = max(1, min(reorderedItemIds.count - 1, itemIndex)) targetIndex = max(1, min(reorderedItemIds.count - 1, itemIndex))
} }
if targetIndex != currentItemIndex { if targetIndex != currentItemIndex {
strongSelf.hapticFeedback.tap()
var updatedReorderedItemIds = reorderedItemIds var updatedReorderedItemIds = reorderedItemIds
if targetIndex > currentItemIndex { if targetIndex > currentItemIndex {
updatedReorderedItemIds.insert(reorderingItem, at: targetIndex + 1) updatedReorderedItemIds.insert(reorderingItem, at: targetIndex + 1)

View File

@ -197,6 +197,12 @@ public class ImmediateTextNode: TextNode {
} }
public class ASTextNode: ImmediateTextNode { public class ASTextNode: ImmediateTextNode {
override public var attributedText: NSAttributedString? {
didSet {
self.setNeedsLayout()
}
}
override public init() { override public init() {
super.init() super.init()

View File

@ -393,7 +393,7 @@ open class TabBarController: ViewController {
} }
} }
self.controllers = controllers self.controllers = controllers
self.tabBarControllerNode.tabBarNode.tabBarItems = self.controllers.map({ TabBarNodeItem(item: $0.tabBarItem, hasContext: $0.hasTabBarItemContextAction) }) self.tabBarControllerNode.tabBarNode.tabBarItems = self.controllers.map({ TabBarNodeItem(item: $0.tabBarItem, contextActionType: $0.tabBarItemContextActionType) })
let signals = combineLatest(self.controllers.map({ $0.tabBarItem }).map { tabBarItem -> Signal<Bool, NoError> in let signals = combineLatest(self.controllers.map({ $0.tabBarItem }).map { tabBarItem -> Signal<Bool, NoError> in
if let tabBarItem = tabBarItem, tabBarItem.image == nil { if let tabBarItem = tabBarItem, tabBarItem.image == nil {

View File

@ -102,6 +102,7 @@ private final class TabBarItemNode: ASDisplayNode {
let contextImageNode: ASImageNode let contextImageNode: ASImageNode
let contextTextImageNode: ASImageNode let contextTextImageNode: ASImageNode
var contentWidth: CGFloat? var contentWidth: CGFloat?
var isSelected: Bool = false
var swiped: ((TabBarItemSwipeDirection) -> Void)? var swiped: ((TabBarItemSwipeDirection) -> Void)?
@ -253,10 +254,24 @@ private final class TabBarNodeContainer {
} }
contextAction(strongSelf.imageNode.extractedContainerNode, gesture) contextAction(strongSelf.imageNode.extractedContainerNode, gesture)
} }
imageNode.swiped = { [weak self] direction in imageNode.swiped = { [weak imageNode] direction in
guard let imageNode = imageNode, imageNode.isSelected else {
return
}
swipeAction(direction) swipeAction(direction)
} }
imageNode.containerNode.isGestureEnabled = item.hasContext imageNode.containerNode.isGestureEnabled = item.contextActionType != .none
let contextActionType = item.contextActionType
imageNode.containerNode.shouldBegin = { [weak imageNode] _ in
switch contextActionType {
case .none:
return false
case .always:
return true
case .whenActive:
return imageNode?.isSelected ?? false
}
}
} }
deinit { deinit {
@ -269,11 +284,11 @@ private final class TabBarNodeContainer {
final class TabBarNodeItem { final class TabBarNodeItem {
let item: UITabBarItem let item: UITabBarItem
let hasContext: Bool let contextActionType: TabBarItemContextActionType
init(item: UITabBarItem, hasContext: Bool) { init(item: UITabBarItem, contextActionType: TabBarItemContextActionType) {
self.item = item self.item = item
self.hasContext = hasContext self.contextActionType = contextActionType
} }
} }
@ -429,6 +444,7 @@ class TabBarNode: ASDisplayNode {
node.imageNode.image = image node.imageNode.image = image
node.accessibilityLabel = item.item.title node.accessibilityLabel = item.item.title
node.contentWidth = max(contentWidth, imageContentWidth) node.contentWidth = max(contentWidth, imageContentWidth)
node.isSelected = true
} else { } else {
let (textImage, contentWidth) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: false, centered: self.centered) let (textImage, contentWidth) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: false, centered: self.centered)
let (image, imageContentWidth) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarIconColor, horizontal: self.horizontal, imageMode: true, centered: self.centered) let (image, imageContentWidth) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarIconColor, horizontal: self.horizontal, imageMode: true, centered: self.centered)
@ -436,6 +452,7 @@ class TabBarNode: ASDisplayNode {
node.accessibilityLabel = item.item.title node.accessibilityLabel = item.item.title
node.imageNode.image = image node.imageNode.image = image
node.contentWidth = max(contentWidth, imageContentWidth) node.contentWidth = max(contentWidth, imageContentWidth)
node.isSelected = false
} }
container.badgeBackgroundNode.image = self.badgeImage container.badgeBackgroundNode.image = self.badgeImage
node.extractedContainerNode.contentNode.addSubnode(container.badgeContainerNode) node.extractedContainerNode.contentNode.addSubnode(container.badgeContainerNode)
@ -468,6 +485,7 @@ class TabBarNode: ASDisplayNode {
node.contextTextImageNode.image = contextTextImage node.contextTextImageNode.image = contextTextImage
node.contextImageNode.image = contextImage node.contextImageNode.image = contextImage
node.contentWidth = max(contentWidth, imageContentWidth) node.contentWidth = max(contentWidth, imageContentWidth)
node.isSelected = true
} else { } else {
let (textImage, contentWidth) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: false, centered: self.centered) let (textImage, contentWidth) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: false, centered: self.centered)
let (image, imageContentWidth) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarIconColor, horizontal: self.horizontal, imageMode: true, centered: self.centered) let (image, imageContentWidth) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarIconColor, horizontal: self.horizontal, imageMode: true, centered: self.centered)
@ -479,6 +497,7 @@ class TabBarNode: ASDisplayNode {
node.contextTextImageNode.image = contextTextImage node.contextTextImageNode.image = contextTextImage
node.contextImageNode.image = contextImage node.contextImageNode.image = contextImage
node.contentWidth = max(contentWidth, imageContentWidth) node.contentWidth = max(contentWidth, imageContentWidth)
node.isSelected = false
} }
let updatedImageSize = node.imageNode.image?.size ?? CGSize() let updatedImageSize = node.imageNode.image?.size ?? CGSize()

View File

@ -67,6 +67,12 @@ public enum ViewControllerNavigationPresentation {
case modalInLargeLayout case modalInLargeLayout
} }
public enum TabBarItemContextActionType {
case none
case always
case whenActive
}
@objc open class ViewController: UIViewController, ContainableController { @objc open class ViewController: UIViewController, ContainableController {
private var validLayout: ContainerViewLayout? private var validLayout: ContainerViewLayout?
public var currentlyAppliedLayout: ContainerViewLayout? { public var currentlyAppliedLayout: ContainerViewLayout? {
@ -625,7 +631,7 @@ public enum ViewControllerNavigationPresentation {
open func toolbarActionSelected(action: ToolbarActionOption) { open func toolbarActionSelected(action: ToolbarActionOption) {
} }
open var hasTabBarItemContextAction: Bool = false open var tabBarItemContextActionType: TabBarItemContextActionType = .none
open func tabBarItemContextAction(sourceNode: ContextExtractedContentContainingNode, gesture: ContextGesture) { open func tabBarItemContextAction(sourceNode: ContextExtractedContentContainingNode, gesture: ContextGesture) {
} }

View File

@ -770,7 +770,7 @@ private final class SettingsControllerImpl: ItemListController, SettingsControll
super.init(presentationData: ItemListPresentationData(presentationData), updatedPresentationData: updatedPresentationData |> map(ItemListPresentationData.init(_:)), state: state, tabBarItem: tabBarItem) super.init(presentationData: ItemListPresentationData(presentationData), updatedPresentationData: updatedPresentationData |> map(ItemListPresentationData.init(_:)), state: state, tabBarItem: tabBarItem)
self.hasTabBarItemContextAction = true self.tabBarItemContextActionType = .always
self.accountsAndPeersDisposable = (accountsAndPeers self.accountsAndPeersDisposable = (accountsAndPeers
|> deliverOnMainQueue).start(next: { [weak self] value in |> deliverOnMainQueue).start(next: { [weak self] value in

View File

@ -172,7 +172,7 @@ extension ChatListFilter {
categories: ChatListFilterPeerCategories(apiFlags: flags), categories: ChatListFilterPeerCategories(apiFlags: flags),
excludeMuted: (flags & (1 << 11)) != 0, excludeMuted: (flags & (1 << 11)) != 0,
excludeRead: (flags & (1 << 12)) != 0, excludeRead: (flags & (1 << 12)) != 0,
excludeArchived: false, excludeArchived: (flags & (1 << 13)) != 0,
includePeers: includePeers.compactMap { peer -> PeerId? in includePeers: includePeers.compactMap { peer -> PeerId? in
switch peer { switch peer {
case let .inputPeerUser(userId, _): case let .inputPeerUser(userId, _):
@ -210,6 +210,9 @@ extension ChatListFilter {
if self.data.excludeRead { if self.data.excludeRead {
flags |= 1 << 12 flags |= 1 << 12
} }
if self.data.excludeArchived {
flags |= 1 << 13
}
flags |= self.data.categories.apiFlags flags |= self.data.categories.apiFlags
return .dialogFilter(flags: flags, id: self.id, title: self.title, includePeers: self.data.includePeers.compactMap { peerId -> Api.InputPeer? in return .dialogFilter(flags: flags, id: self.id, title: self.title, includePeers: self.data.includePeers.compactMap { peerId -> Api.InputPeer? in
return transaction.getPeer(peerId).flatMap(apiInputPeer) return transaction.getPeer(peerId).flatMap(apiInputPeer)

View File

@ -89,6 +89,7 @@ class ChatHistoryNavigationButtonNode: ASControlNode {
if let string = self.badgeTextNode.attributedText?.string { if let string = self.badgeTextNode.attributedText?.string {
self.badgeTextNode.attributedText = NSAttributedString(string: string, font: badgeFont, textColor: theme.chat.historyNavigation.badgeTextColor) self.badgeTextNode.attributedText = NSAttributedString(string: string, font: badgeFont, textColor: theme.chat.historyNavigation.badgeTextColor)
self.badgeTextNode.redrawIfPossible()
} }
} }
} }

View File

@ -122,7 +122,7 @@ final class ChatMessageInteractiveMediaBadge: ASDisplayNode {
} }
self.durationNode.attributedText = convertedText self.durationNode.attributedText = convertedText
let durationSize = self.durationNode.measure(CGSize(width: 160.0, height: 160.0)) let durationSize = self.durationNode.measure(CGSize(width: 160.0, height: 160.0))
self.durationNode.frame = CGRect(x: 7.0 + inset, y: 2.0, width: durationSize.width, height: durationSize.height) self.durationNode.frame = CGRect(x: 7.0 + inset, y: 3.0, width: durationSize.width, height: durationSize.height)
currentContentSize = CGSize(width: widthForString(text.string) + 14.0 + inset, height: 18.0) currentContentSize = CGSize(width: widthForString(text.string) + 14.0 + inset, height: 18.0)
if let iconNode = self.iconNode { if let iconNode = self.iconNode {
@ -188,7 +188,7 @@ final class ChatMessageInteractiveMediaBadge: ASDisplayNode {
transition.updateAlpha(node: statusNode, alpha: active ? 1.0 : 0.0) transition.updateAlpha(node: statusNode, alpha: active ? 1.0 : 0.0)
} }
let durationFrame = CGRect(x: active ? 42.0 : 7.0, y: active ? 6.0 : 2.0, width: durationSize.width, height: durationSize.height) let durationFrame = CGRect(x: active ? 42.0 : 7.0, y: active ? 6.0 : 3.0, width: durationSize.width, height: durationSize.height)
self.durationNode.bounds = CGRect(origin: CGPoint(), size: durationFrame.size) self.durationNode.bounds = CGRect(origin: CGPoint(), size: durationFrame.size)
textTransition.updatePosition(node: self.durationNode, position: durationFrame.center) textTransition.updatePosition(node: self.durationNode, position: durationFrame.center)