Folder improvements

This commit is contained in:
Ali 2023-04-04 17:18:42 +04:00
parent 515ef8cfc5
commit 0e1dd66b04
6 changed files with 345 additions and 257 deletions

View File

@ -2815,6 +2815,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return return
} }
if self.chatListDisplayNode.inlineStackContainerNode != nil {
self.setInlineChatList(location: nil)
}
if self.chatListDisplayNode.mainContainerNode.currentItemNode.chatListFilter?.id != folderId { if self.chatListDisplayNode.mainContainerNode.currentItemNode.chatListFilter?.id != folderId {
self.chatListDisplayNode.mainContainerNode.switchToFilter(id: .filter(folderId), completion: { self.chatListDisplayNode.mainContainerNode.switchToFilter(id: .filter(folderId), completion: {
completion() completion()

View File

@ -1053,16 +1053,26 @@ private extension ChatListFilter {
} }
} }
func chatListFilterPresetController(context: AccountContext, currentPreset: ChatListFilter?, updated: @escaping ([ChatListFilter]) -> Void) -> ViewController { func chatListFilterPresetController(context: AccountContext, currentPreset initialPreset: ChatListFilter?, updated: @escaping ([ChatListFilter]) -> Void) -> ViewController {
var currentPreset = currentPreset
let initialName: String let initialName: String
if let currentPreset = currentPreset { if let initialPreset {
initialName = currentPreset.title initialName = initialPreset.title
} else { } else {
initialName = "" initialName = ""
} }
let initialState = ChatListFilterPresetControllerState(name: initialName, changedName: currentPreset != nil, includeCategories: currentPreset?.data?.categories ?? [], excludeMuted: currentPreset?.data?.excludeMuted ?? false, excludeRead: currentPreset?.data?.excludeRead ?? false, excludeArchived: currentPreset?.data?.excludeArchived ?? false, additionallyIncludePeers: currentPreset?.data?.includePeers.peers ?? [], additionallyExcludePeers: currentPreset?.data?.excludePeers ?? [], expandedSections: []) let initialState = ChatListFilterPresetControllerState(name: initialName, changedName: initialPreset != nil, includeCategories: initialPreset?.data?.categories ?? [], excludeMuted: initialPreset?.data?.excludeMuted ?? false, excludeRead: initialPreset?.data?.excludeRead ?? false, excludeArchived: initialPreset?.data?.excludeArchived ?? false, additionallyIncludePeers: initialPreset?.data?.includePeers.peers ?? [], additionallyExcludePeers: initialPreset?.data?.excludePeers ?? [], expandedSections: [])
let updatedCurrentPreset: Signal<ChatListFilter?, NoError>
if let initialPreset {
updatedCurrentPreset = context.engine.peers.updatedChatListFilters()
|> map { filters -> ChatListFilter? in
return filters.first(where: { $0.id == initialPreset.id })
}
|> distinctUntilChanged
} else {
updatedCurrentPreset = .single(nil)
}
let stateValue = Atomic(value: initialState) let stateValue = Atomic(value: initialState)
let statePromise = ValuePromise(initialState, ignoreRepeated: true) let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let updateState: ((ChatListFilterPresetControllerState) -> ChatListFilterPresetControllerState) -> Void = { f in let updateState: ((ChatListFilterPresetControllerState) -> ChatListFilterPresetControllerState) -> Void = { f in
@ -1072,7 +1082,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
var includePeers = ChatListFilterIncludePeers() var includePeers = ChatListFilterIncludePeers()
includePeers.setPeers(state.additionallyIncludePeers) includePeers.setPeers(state.additionallyIncludePeers)
let filter: ChatListFilter = .filter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(isShared: currentPreset?.data?.isShared ?? false, hasSharedLinks: currentPreset?.data?.hasSharedLinks ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) let filter: ChatListFilter = .filter(id: initialPreset?.id ?? -1, title: state.name, emoticon: initialPreset?.emoticon, data: ChatListFilterData(isShared: initialPreset?.data?.isShared ?? false, hasSharedLinks: initialPreset?.data?.hasSharedLinks ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
if let data = filter.data { if let data = filter.data {
switch chatListFilterType(data) { switch chatListFilterType(data) {
case .generic: case .generic:
@ -1114,8 +1124,8 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
var presentInGlobalOverlayImpl: ((ViewController) -> Void)? var presentInGlobalOverlayImpl: ((ViewController) -> Void)?
let sharedLinks = Promise<[ExportedChatFolderLink]?>(nil) let sharedLinks = Promise<[ExportedChatFolderLink]?>(nil)
if let currentPreset { if let initialPreset {
sharedLinks.set(Signal<[ExportedChatFolderLink]?, NoError>.single(nil) |> then(context.engine.peers.getExportedChatFolderLinks(id: currentPreset.id))) sharedLinks.set(Signal<[ExportedChatFolderLink]?, NoError>.single(nil) |> then(context.engine.peers.getExportedChatFolderLinks(id: initialPreset.id)))
} }
let currentPeers = Atomic<[PeerId: EngineRenderedPeer]>(value: [:]) let currentPeers = Atomic<[PeerId: EngineRenderedPeer]>(value: [:])
@ -1189,8 +1199,9 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false), TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false),
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true) TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true)
), ),
stateWithPeers |> take(1) stateWithPeers |> take(1),
).start(next: { result, state in updatedCurrentPreset |> take(1)
).start(next: { result, state, currentPreset in
let (accountPeer, limits, premiumLimits) = result let (accountPeer, limits, premiumLimits) = result
let isPremium = accountPeer?.isPremium ?? false let isPremium = accountPeer?.isPremium ?? false
@ -1238,6 +1249,9 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
}) })
}, },
openAddExcludePeer: { openAddExcludePeer: {
let _ = (updatedCurrentPreset
|> take(1)
|> deliverOnMainQueue).start(next: { currentPreset in
let state = stateValue.with { $0 } let state = stateValue.with { $0 }
var includePeers = ChatListFilterIncludePeers() var includePeers = ChatListFilterIncludePeers()
includePeers.setPeers(state.additionallyIncludePeers) includePeers.setPeers(state.additionallyIncludePeers)
@ -1260,6 +1274,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
}) })
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}) })
})
}, },
deleteIncludePeer: { peerId in deleteIncludePeer: { peerId in
updateState { state in updateState { state in
@ -1323,19 +1338,30 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
} }
}, },
createLink: { createLink: {
if currentPreset == nil { if initialPreset == nil {
//TODO:localize //TODO:localize
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let text = "Please finish creating this folder to share it." let text = "Please finish creating this folder to share it."
presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
} else { } else {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let state = stateValue.with({ $0 })
if state.additionallyIncludePeers.isEmpty {
//TODO:localize
let text = "Please add chats to this folder to share it."
presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
return
}
let statusController = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) let statusController = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
presentControllerImpl?(statusController, nil) presentControllerImpl?(statusController, nil)
applyImpl?(true, { [weak statusController] in applyImpl?(true, { [weak statusController] in
let state = stateValue.with({ $0 }) let state = stateValue.with({ $0 })
let _ = (updatedCurrentPreset |> take(1) |> deliverOnMainQueue).start(next: { currentPreset in
if let currentPreset, let data = currentPreset.data { if let currentPreset, let data = currentPreset.data {
//TODO:localize //TODO:localize
var unavailableText: String? var unavailableText: String?
@ -1390,8 +1416,10 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
statusController?.dismiss() statusController?.dismiss()
} }
}) })
})
} }
}, openLink: { link in }, openLink: { link in
let _ = (updatedCurrentPreset |> take(1) |> deliverOnMainQueue).start(next: { currentPreset in
if let currentPreset, let _ = currentPreset.data { if let currentPreset, let _ = currentPreset.data {
applyImpl?(false, { applyImpl?(false, {
let state = stateValue.with({ $0 }) let state = stateValue.with({ $0 })
@ -1420,8 +1448,10 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
})) }))
}) })
} }
})
}, },
removeLink: { link in removeLink: { link in
let _ = (updatedCurrentPreset |> take(1) |> deliverOnMainQueue).start(next: { currentPreset in
if let currentPreset { if let currentPreset {
let _ = (sharedLinks.get() |> take(1) |> deliverOnMainQueue).start(next: { links in let _ = (sharedLinks.get() |> take(1) |> deliverOnMainQueue).start(next: { links in
var links = links ?? [] var links = links ?? []
@ -1434,8 +1464,10 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
actionsDisposable.add(context.engine.peers.deleteChatFolderLink(filterId: currentPreset.id, link: link).start()) actionsDisposable.add(context.engine.peers.deleteChatFolderLink(filterId: currentPreset.id, link: link).start())
}) })
} }
})
}, },
linkContextAction: { invite, node, gesture in linkContextAction: { invite, node, gesture in
let _ = (updatedCurrentPreset |> take(1) |> deliverOnMainQueue).start(next: { currentPreset in
guard let node = node as? ContextExtractedContentContainingNode, let controller = getControllerImpl?(), let invite = invite, let currentPreset else { guard let node = node as? ContextExtractedContentContainingNode, let controller = getControllerImpl?(), let invite = invite, let currentPreset else {
return return
} }
@ -1487,6 +1519,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node, keepInPlace: false, blurBackground: true)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node, keepInPlace: false, blurBackground: true)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture)
presentInGlobalOverlayImpl?(contextController) presentInGlobalOverlayImpl?(contextController)
})
}, },
peerContextAction: { peer, node, gesture, location in peerContextAction: { peer, node, gesture, location in
let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true)) let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true))
@ -1516,8 +1549,9 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
} }
) )
var attemptNavigationImpl: (() -> Bool)? var attemptNavigationImpl: ((@escaping (Bool) -> Void) -> Void)?
applyImpl = { waitForSync, completed in applyImpl = { waitForSync, completed in
let _ = (updatedCurrentPreset |> take(1) |> deliverOnMainQueue).start(next: { currentPreset in
let state = stateValue.with { $0 } let state = stateValue.with { $0 }
var includePeers = ChatListFilterIncludePeers() var includePeers = ChatListFilterIncludePeers()
@ -1553,7 +1587,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
} }
filters.append(updatedFilter) filters.append(updatedFilter)
} }
currentPreset = updatedFilter //currentPreset = updatedFilter
} else { } else {
filters.append(updatedFilter) filters.append(updatedFilter)
} }
@ -1573,6 +1607,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
completed() completed()
} }
}) })
})
} }
var previousState = stateValue.with { $0 } var previousState = stateValue.with { $0 }
@ -1586,16 +1621,23 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
context.engine.data.get( context.engine.data.get(
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true) TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true)
), ),
sharedLinks.get() sharedLinks.get(),
updatedCurrentPreset
) )
|> deliverOnMainQueue |> deliverOnMainQueue
|> map { presentationData, stateWithPeers, peerView, premiumLimits, sharedLinks -> (ItemListControllerState, (ItemListNodeState, Any)) in |> map { presentationData, stateWithPeers, peerView, premiumLimits, sharedLinks, currentPreset -> (ItemListControllerState, (ItemListNodeState, Any)) in
let (state, includePeers, excludePeers) = stateWithPeers let (state, includePeers, excludePeers) = stateWithPeers
let isPremium = peerView.peers[peerView.peerId]?.isPremium ?? false let isPremium = peerView.peers[peerView.peerId]?.isPremium ?? false
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: {
if attemptNavigationImpl?() ?? true { if let attemptNavigationImpl {
attemptNavigationImpl({ value in
if value {
dismissImpl?()
}
})
} else {
dismissImpl?() dismissImpl?()
} }
}) })
@ -1659,7 +1701,16 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
controller.view.endEditing(true) controller.view.endEditing(true)
} }
controller.attemptNavigation = { _ in controller.attemptNavigation = { _ in
return attemptNavigationImpl?() ?? true if let attemptNavigationImpl {
attemptNavigationImpl({ value in
if value {
dismissImpl?()
}
})
return false
} else {
return true
}
} }
let displaySaveAlert: () -> Void = { let displaySaveAlert: () -> Void = {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -1682,7 +1733,8 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
controller.presentInGlobalOverlay(c) controller.presentInGlobalOverlay(c)
} }
} }
attemptNavigationImpl = { attemptNavigationImpl = { f in
let _ = (updatedCurrentPreset |> take(1) |> deliverOnMainQueue).start(next: { currentPreset in
let state = stateValue.with { $0 } let state = stateValue.with { $0 }
if let currentPreset = currentPreset, case let .filter(currentId, currentTitle, currentEmoticon, currentData) = currentPreset { if let currentPreset = currentPreset, case let .filter(currentId, currentTitle, currentEmoticon, currentData) = currentPreset {
var currentPresetWithoutPinnedPeers = currentPreset var currentPresetWithoutPinnedPeers = currentPreset
@ -1698,15 +1750,18 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
let filter: ChatListFilter = .filter(id: currentPreset.id, title: state.name, emoticon: currentPreset.emoticon, data: ChatListFilterData(isShared: currentPreset.data?.isShared ?? false, hasSharedLinks: currentPreset.data?.hasSharedLinks ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) let filter: ChatListFilter = .filter(id: currentPreset.id, title: state.name, emoticon: currentPreset.emoticon, data: ChatListFilterData(isShared: currentPreset.data?.isShared ?? false, hasSharedLinks: currentPreset.data?.hasSharedLinks ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
if currentPresetWithoutPinnedPeers != filter { if currentPresetWithoutPinnedPeers != filter {
displaySaveAlert() displaySaveAlert()
return false f(false)
return
} }
} else { } else {
if currentPreset != nil, state.isComplete { if currentPreset != nil, state.isComplete {
displaySaveAlert() displaySaveAlert()
return false f(false)
return
} }
} }
return true f(true)
})
} }
return controller return controller

View File

@ -324,7 +324,7 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch
let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in
var filters = filters var filters = filters
let id = context.engine.peers.generateNewChatListFilterId(filters: filters) let id = context.engine.peers.generateNewChatListFilterId(filters: filters)
filters.insert(.filter(id: id, title: title, emoticon: nil, data: data), at: 0) filters.append(.filter(id: id, title: title, emoticon: nil, data: data))
return filters return filters
} }
|> deliverOnMainQueue).start(next: { _ in |> deliverOnMainQueue).start(next: { _ in

View File

@ -684,7 +684,16 @@ public func folderInviteLinkListController(context: AccountContext, updatedPrese
} else if state.isSaving { } else if state.isSaving {
doneButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {}) doneButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {})
} else { } else {
doneButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Save), style: .bold, enabled: !state.selectedPeerIds.isEmpty, action: { var saveEnabled = false
if let currentLink = state.currentLink {
if currentLink.title != state.title || Set(currentLink.peerIds) != state.selectedPeerIds {
saveEnabled = true
}
} else {
saveEnabled = true
}
doneButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Save), style: .bold, enabled: !state.selectedPeerIds.isEmpty && saveEnabled, action: {
applyChangesImpl?() applyChangesImpl?()
}) })
} }
@ -739,7 +748,7 @@ public func folderInviteLinkListController(context: AccountContext, updatedPrese
f() f()
dismissImpl?() dismissImpl?()
}), }),
TextAlertAction(type: .defaultAction, title: "Apply", action: { TextAlertAction(type: .defaultAction, title: state.selectedPeerIds.isEmpty ? "Continue" : "Apply", action: {
applyChangesImpl?() applyChangesImpl?()
}) })
]), nil) ]), nil)

View File

@ -144,6 +144,10 @@ public class ItemListFolderInviteLinkListItemNode: ItemListRevealOptionsItemNode
private var nonExtractedRect: CGRect? private var nonExtractedRect: CGRect?
private let offsetContainerNode: ASDisplayNode private let offsetContainerNode: ASDisplayNode
public override var controlsContainer: ASDisplayNode {
//return super.controlsContainer
return self.containerNode
}
private let iconBackgroundNode: ASDisplayNode private let iconBackgroundNode: ASDisplayNode
private let iconNode: ASImageNode private let iconNode: ASImageNode
@ -428,7 +432,9 @@ public class ItemListFolderInviteLinkListItemNode: ItemListRevealOptionsItemNode
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
} }
if strongSelf.maskNode.supernode == nil { if strongSelf.maskNode.supernode == nil {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3) //strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
strongSelf.maskNode.isUserInteractionEnabled = false
strongSelf.addSubnode(strongSelf.maskNode)
} }
let hasCorners = itemListHasRoundedBlockLayout(params) let hasCorners = itemListHasRoundedBlockLayout(params)
@ -581,7 +587,7 @@ public class ItemListFolderInviteLinkListItemNode: ItemListRevealOptionsItemNode
override public func updateRevealOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) { override public func updateRevealOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) {
super.updateRevealOffset(offset: offset, transition: transition) super.updateRevealOffset(offset: offset, transition: transition)
transition.updateSublayerTransformOffset(layer: self.containerNode.layer, offset: CGPoint(x: offset, y: 0.0)) transition.updateSublayerTransformOffset(layer: self.offsetContainerNode.layer, offset: CGPoint(x: offset + (self.contextSourceNode.isExtractedToContextPreview ? 12.0 : 0.0), y: 0.0))
} }
override public func revealOptionSelected(_ option: ItemListRevealOption, animated: Bool) { override public func revealOptionSelected(_ option: ItemListRevealOption, animated: Bool) {

View File

@ -205,6 +205,9 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
return return
} }
if scrollView.contentOffset.y <= -100.0 && velocity.y <= -2.0 {
self.environment?.controller()?.dismiss()
} else {
var topOffset = -self.scrollView.bounds.minY + itemLayout.topInset var topOffset = -self.scrollView.bounds.minY + itemLayout.topInset
if topOffset > 0.0 { if topOffset > 0.0 {
topOffset = max(0.0, topOffset) topOffset = max(0.0, topOffset)
@ -215,6 +218,7 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
} }
} }
} }
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if !self.bounds.contains(point) { if !self.bounds.contains(point) {
@ -287,7 +291,10 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
controller.updateModalStyleOverlayTransitionFactor(0.0, transition: .animated(duration: 0.3, curve: .easeInOut)) controller.updateModalStyleOverlayTransitionFactor(0.0, transition: .animated(duration: 0.3, curve: .easeInOut))
} }
let animateOffset: CGFloat = self.bounds.height - self.backgroundLayer.frame.minY var animateOffset: CGFloat = self.bounds.height - self.backgroundLayer.frame.minY
if self.scrollView.contentOffset.y < 0.0 {
animateOffset += -self.scrollView.contentOffset.y
}
self.dimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false) self.dimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
self.scrollContentClippingView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: animateOffset), duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, additive: true, completion: { _ in self.scrollContentClippingView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: animateOffset), duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, additive: true, completion: { _ in
@ -698,11 +705,19 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
} }
var subtitle: String? var subtitle: String?
if case let .channel(channel) = peer, case .broadcast = channel.info {
if linkContents.alreadyMemberPeerIds.contains(peer.id) {
subtitle = "You are already a subscriber"
} else if let memberCount = linkContents.memberCounts[peer.id] {
subtitle = "\(memberCount) subscribers"
}
} else {
if linkContents.alreadyMemberPeerIds.contains(peer.id) { if linkContents.alreadyMemberPeerIds.contains(peer.id) {
subtitle = "You are already a member" subtitle = "You are already a member"
} else if let memberCount = linkContents.memberCounts[peer.id] { } else if let memberCount = linkContents.memberCounts[peer.id] {
subtitle = "\(memberCount) participants" subtitle = "\(memberCount) participants"
} }
}
let itemSize = item.update( let itemSize = item.update(
transition: itemTransition, transition: itemTransition,