mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Display a toast after sticker list changes
This commit is contained in:
parent
7dbf4cd90d
commit
4ed2893065
@ -1198,11 +1198,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
|
||||
let text = strongSelf.presentationData.strings.ChatList_DeletedChats(Int32(peerIds.count))
|
||||
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .removedChat(text: text), elevatedLayout: false, animateInAsReplacement: true, action: { shouldCommit in
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .removedChat(text: text), elevatedLayout: false, animateInAsReplacement: true, action: { value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
return false
|
||||
}
|
||||
if shouldCommit {
|
||||
if value == .commit {
|
||||
let context = strongSelf.context
|
||||
let presentationData = strongSelf.presentationData
|
||||
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||
@ -1230,7 +1230,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
}
|
||||
let _ = (signal
|
||||
|> deliverOnMainQueue).start()
|
||||
} else {
|
||||
return true
|
||||
} else if value == .undo {
|
||||
strongSelf.chatListDisplayNode.chatListNode.setCurrentRemovingPeerId(peerIds.first!)
|
||||
strongSelf.chatListDisplayNode.chatListNode.updateState({ state in
|
||||
var state = state
|
||||
@ -1240,7 +1241,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
return state
|
||||
})
|
||||
self?.chatListDisplayNode.chatListNode.setCurrentRemovingPeerId(peerIds.first!)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), in: .current)
|
||||
|
||||
strongSelf.donePressed()
|
||||
@ -1310,11 +1313,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
})
|
||||
|
||||
if value {
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .hidArchive(title: strongSelf.presentationData.strings.ChatList_UndoArchiveHiddenTitle, text: strongSelf.presentationData.strings.ChatList_UndoArchiveHiddenText, undo: false), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] shouldCommit in
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .hidArchive(title: strongSelf.presentationData.strings.ChatList_UndoArchiveHiddenTitle, text: strongSelf.presentationData.strings.ChatList_UndoArchiveHiddenText, undo: false), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
return false
|
||||
}
|
||||
if !shouldCommit {
|
||||
if value == .undo {
|
||||
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Bool in
|
||||
var updatedValue = false
|
||||
updateChatArchiveSettings(transaction: transaction, { settings in
|
||||
@ -1325,10 +1328,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
})
|
||||
return updatedValue
|
||||
}).start()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), in: .current)
|
||||
} else {
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .revealedArchive(title: strongSelf.presentationData.strings.ChatList_UndoArchiveRevealedTitle, text: strongSelf.presentationData.strings.ChatList_UndoArchiveRevealedText, undo: false), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .revealedArchive(title: strongSelf.presentationData.strings.ChatList_UndoArchiveRevealedTitle, text: strongSelf.presentationData.strings.ChatList_UndoArchiveRevealedText, undo: false), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false
|
||||
}), in: .current)
|
||||
}
|
||||
})
|
||||
@ -1422,11 +1427,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
return true
|
||||
})
|
||||
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .removedChat(text: strongSelf.presentationData.strings.Undo_ChatCleared), elevatedLayout: false, animateInAsReplacement: true, action: { shouldCommit in
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .removedChat(text: strongSelf.presentationData.strings.Undo_ChatCleared), elevatedLayout: false, animateInAsReplacement: true, action: { value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
return false
|
||||
}
|
||||
if shouldCommit {
|
||||
if value == .commit {
|
||||
let _ = clearHistoryInteractively(postbox: strongSelf.context.account.postbox, peerId: peerId, type: type).start(completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -1437,13 +1442,16 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
return state
|
||||
})
|
||||
})
|
||||
} else {
|
||||
return true
|
||||
} else if value == .undo {
|
||||
strongSelf.chatListDisplayNode.chatListNode.updateState({ state in
|
||||
var state = state
|
||||
state.pendingClearHistoryPeerIds.remove(peer.peerId)
|
||||
return state
|
||||
})
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), in: .current)
|
||||
}
|
||||
|
||||
@ -1618,11 +1626,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
deleteSendMessageIntents(peerId: peerId)
|
||||
}
|
||||
|
||||
let action: (Bool) -> Void = { shouldCommit in
|
||||
let action: (UndoOverlayAction) -> Bool = { value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
return false
|
||||
}
|
||||
if !shouldCommit {
|
||||
if value == .undo {
|
||||
strongSelf.chatListDisplayNode.chatListNode.setCurrentRemovingPeerId(peerIds[0])
|
||||
let _ = (postbox.transaction { transaction -> Void in
|
||||
for peerId in peerIds {
|
||||
@ -1635,6 +1643,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
}
|
||||
strongSelf.chatListDisplayNode.chatListNode.setCurrentRemovingPeerId(nil)
|
||||
})
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@ -1721,11 +1732,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
return true
|
||||
})
|
||||
|
||||
self.present(UndoOverlayController(presentationData: self.context.sharedContext.currentPresentationData.with { $0 }, content: .removedChat(text: statusText), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] shouldCommit in
|
||||
self.present(UndoOverlayController(presentationData: self.context.sharedContext.currentPresentationData.with { $0 }, content: .removedChat(text: statusText), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
return false
|
||||
}
|
||||
if shouldCommit {
|
||||
if value == .commit {
|
||||
strongSelf.chatListDisplayNode.chatListNode.setCurrentRemovingPeerId(peerId)
|
||||
if let channel = chatPeer as? TelegramChannel {
|
||||
strongSelf.context.peerChannelMemberCategoriesContextsManager.externallyRemoved(peerId: channel.id, memberId: strongSelf.context.account.peerId)
|
||||
@ -1744,7 +1755,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
deleteSendMessageIntents(peerId: peerId)
|
||||
})
|
||||
completion()
|
||||
} else {
|
||||
return true
|
||||
} else if value == .undo {
|
||||
strongSelf.chatListDisplayNode.chatListNode.setCurrentRemovingPeerId(peerId)
|
||||
strongSelf.chatListDisplayNode.chatListNode.updateState({ state in
|
||||
var state = state
|
||||
@ -1752,7 +1764,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
return state
|
||||
})
|
||||
strongSelf.chatListDisplayNode.chatListNode.setCurrentRemovingPeerId(nil)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), in: .current)
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import TextFormat
|
||||
import AccountContext
|
||||
import StickerPackPreviewUI
|
||||
import ItemListStickerPackItem
|
||||
import UndoUI
|
||||
|
||||
private final class InstalledStickerPacksControllerArguments {
|
||||
let account: Account
|
||||
@ -494,6 +495,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
let archivedPromise = Promise<[ArchivedStickerPackItem]?>()
|
||||
|
||||
var presentStickerPackController: ((StickerPackCollectionInfo) -> Void)?
|
||||
var navigationControllerImpl: (() -> NavigationController?)?
|
||||
|
||||
let arguments = InstalledStickerPacksControllerArguments(account: context.account, openStickerPack: { info in
|
||||
presentStickerPackController?(info)
|
||||
@ -511,6 +513,31 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
let removeAction: (RemoveStickerPackOption) -> Void = { action in
|
||||
let _ = (removeStickerPackInteractively(postbox: context.account.postbox, id: archivedItem.info.id, option: .archive)
|
||||
|> deliverOnMainQueue).start(next: { indexAndItems in
|
||||
guard let (positionInList, items) = indexAndItems else {
|
||||
return
|
||||
}
|
||||
|
||||
var animateInAsReplacement = false
|
||||
if let navigationController = navigationControllerImpl?() {
|
||||
for controller in navigationController.overlayControllers {
|
||||
if let controller = controller as? UndoOverlayController {
|
||||
controller.dismissWithCommitActionAndReplacementAnimation()
|
||||
animateInAsReplacement = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(archivedItem.info.title).0, undo: true, info: archivedItem.info, topItem: archivedItem.topItems.first, account: context.account), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in
|
||||
if case .undo = action {
|
||||
let _ = addStickerPackInteractively(postbox: context.account.postbox, info: archivedItem.info, items: items, positionInList: positionInList).start()
|
||||
}
|
||||
return true
|
||||
}))
|
||||
})
|
||||
}
|
||||
controller.setItemGroups([
|
||||
ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: presentationData.strings.StickerSettings_ContextInfo),
|
||||
@ -524,12 +551,12 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
archivedPromise.set(.single(packs))
|
||||
updatedPacks(packs)
|
||||
})
|
||||
|
||||
let _ = removeStickerPackInteractively(postbox: context.account.postbox, id: archivedItem.info.id, option: .archive).start()
|
||||
|
||||
removeAction(.archive)
|
||||
}),
|
||||
ActionSheetButtonItem(title: presentationData.strings.Common_Delete, color: .destructive, action: {
|
||||
dismissAction()
|
||||
let _ = removeStickerPackInteractively(postbox: context.account.postbox, id: archivedItem.info.id, option: .delete).start()
|
||||
removeAction(.delete)
|
||||
})
|
||||
]),
|
||||
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
||||
@ -800,10 +827,37 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
packs.insert(packReference, at: 0)
|
||||
}
|
||||
if let mainStickerPack = mainStickerPack {
|
||||
presentControllerImpl?(StickerPackScreen(context: context, mainStickerPack: mainStickerPack, stickerPacks: packs, parentNavigationController: controller?.navigationController as? NavigationController), nil)
|
||||
presentControllerImpl?(StickerPackScreen(context: context, mainStickerPack: mainStickerPack, stickerPacks: packs, parentNavigationController: controller?.navigationController as? NavigationController, actionPerformed: { info, items, action in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
var animateInAsReplacement = false
|
||||
if let navigationController = navigationControllerImpl?() {
|
||||
for controller in navigationController.overlayControllers {
|
||||
if let controller = controller as? UndoOverlayController {
|
||||
controller.dismissWithCommitActionAndReplacementAnimation()
|
||||
animateInAsReplacement = true
|
||||
}
|
||||
}
|
||||
}
|
||||
switch action {
|
||||
case .add:
|
||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, account: context.account), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||
return true
|
||||
}))
|
||||
case let .remove(positionInList):
|
||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).0, undo: true, info: info, topItem: items.first, account: context.account), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in
|
||||
if case .undo = action {
|
||||
let _ = addStickerPackInteractively(postbox: context.account.postbox, info: info, items: items, positionInList: positionInList).start()
|
||||
}
|
||||
return true
|
||||
}))
|
||||
}
|
||||
}), nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
navigationControllerImpl = { [weak controller] in
|
||||
return controller?.navigationController as? NavigationController
|
||||
}
|
||||
pushControllerImpl = { [weak controller] c in
|
||||
(controller?.navigationController as? NavigationController)?.pushViewController(c)
|
||||
}
|
||||
|
@ -63,10 +63,13 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
|
||||
}
|
||||
}
|
||||
|
||||
public init(context: AccountContext, stickerPack: StickerPackReference, mode: StickerPackPreviewControllerMode = .default, parentNavigationController: NavigationController?) {
|
||||
private let actionPerformed: ((StickerPackCollectionInfo, [ItemCollectionItem], StickerPackScreenPerformedAction) -> Void)?
|
||||
|
||||
public init(context: AccountContext, stickerPack: StickerPackReference, mode: StickerPackPreviewControllerMode = .default, parentNavigationController: NavigationController?, actionPerformed: ((StickerPackCollectionInfo, [ItemCollectionItem], StickerPackScreenPerformedAction) -> Void)? = nil) {
|
||||
self.context = context
|
||||
self.mode = mode
|
||||
self.parentNavigationController = parentNavigationController
|
||||
self.actionPerformed = actionPerformed
|
||||
|
||||
self.stickerPack = stickerPack
|
||||
|
||||
@ -133,7 +136,7 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: parentNavigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: true))
|
||||
}
|
||||
}))
|
||||
})
|
||||
}, actionPerformed: self.actionPerformed)
|
||||
self.controllerNode.dismiss = { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol
|
||||
var dismiss: (() -> Void)?
|
||||
var cancel: (() -> Void)?
|
||||
var sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?
|
||||
private let actionPerformed: ((StickerPackCollectionInfo, [ItemCollectionItem], StickerPackScreenPerformedAction) -> Void)?
|
||||
|
||||
let ready = Promise<Bool>()
|
||||
private var didSetReady = false
|
||||
@ -87,10 +88,11 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol
|
||||
|
||||
private var hapticFeedback: HapticFeedback?
|
||||
|
||||
init(context: AccountContext, openShare: (() -> Void)?, openMention: @escaping (String) -> Void) {
|
||||
init(context: AccountContext, openShare: (() -> Void)?, openMention: @escaping (String) -> Void, actionPerformed: ((StickerPackCollectionInfo, [ItemCollectionItem], StickerPackScreenPerformedAction) -> Void)?) {
|
||||
self.context = context
|
||||
self.openShare = openShare
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.actionPerformed = actionPerformed
|
||||
|
||||
self.wrappingScrollNode = ASScrollNode()
|
||||
self.wrappingScrollNode.view.alwaysBounceVertical = true
|
||||
@ -509,23 +511,27 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol
|
||||
}
|
||||
|
||||
@objc func installActionButtonPressed() {
|
||||
let dismissOnAction: Bool
|
||||
if let initiallyInstalled = self.stickerPackInitiallyInstalled, initiallyInstalled {
|
||||
dismissOnAction = false
|
||||
} else {
|
||||
dismissOnAction = true
|
||||
}
|
||||
let dismissOnAction = true
|
||||
if let stickerPack = self.stickerPack, let stickerSettings = self.stickerSettings {
|
||||
switch stickerPack {
|
||||
case let .result(info, items, installed):
|
||||
if installed {
|
||||
let _ = removeStickerPackInteractively(postbox: self.context.account.postbox, id: info.id, option: .delete).start()
|
||||
self.updateStickerPack(.result(info: info, items: items, installed: false), stickerSettings: stickerSettings)
|
||||
let _ = (removeStickerPackInteractively(postbox: self.context.account.postbox, id: info.id, option: .delete)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] indexAndItems in
|
||||
guard let strongSelf = self, let (positionInList, _) = indexAndItems else {
|
||||
return
|
||||
}
|
||||
strongSelf.actionPerformed?(info, items, .remove(positionInList: positionInList))
|
||||
})
|
||||
if !dismissOnAction {
|
||||
self.updateStickerPack(.result(info: info, items: items, installed: false), stickerSettings: stickerSettings)
|
||||
}
|
||||
} else {
|
||||
let _ = addStickerPackInteractively(postbox: self.context.account.postbox, info: info, items: items).start()
|
||||
if !dismissOnAction {
|
||||
self.updateStickerPack(.result(info: info, items: items, installed: true), stickerSettings: stickerSettings)
|
||||
}
|
||||
self.actionPerformed?(info, items, .add)
|
||||
}
|
||||
if dismissOnAction {
|
||||
self.cancelButtonPressed()
|
||||
|
@ -842,8 +842,13 @@ public final class StickerPackScreenImpl: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public func StickerPackScreen(context: AccountContext, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil) -> ViewController {
|
||||
let controller = StickerPackPreviewController(context: context, stickerPack: mainStickerPack, mode: .default, parentNavigationController: parentNavigationController)
|
||||
public enum StickerPackScreenPerformedAction {
|
||||
case add
|
||||
case remove(positionInList: Int)
|
||||
}
|
||||
|
||||
public func StickerPackScreen(context: AccountContext, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [ItemCollectionItem], StickerPackScreenPerformedAction) -> Void)? = nil) -> ViewController {
|
||||
let controller = StickerPackPreviewController(context: context, stickerPack: mainStickerPack, mode: .default, parentNavigationController: parentNavigationController, actionPerformed: actionPerformed)
|
||||
controller.sendSticker = sendSticker
|
||||
return controller
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import SwiftSignalKit
|
||||
|
||||
import SyncCore
|
||||
|
||||
public func addStickerPackInteractively(postbox: Postbox, info: StickerPackCollectionInfo, items: [ItemCollectionItem]) -> Signal<Void, NoError> {
|
||||
public func addStickerPackInteractively(postbox: Postbox, info: StickerPackCollectionInfo, items: [ItemCollectionItem], positionInList: Int? = nil) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
let namespace: SynchronizeInstalledStickerPacksOperationNamespace?
|
||||
switch info.id.namespace {
|
||||
@ -23,7 +23,11 @@ public func addStickerPackInteractively(postbox: Postbox, info: StickerPackColle
|
||||
updatedInfos.remove(at: index)
|
||||
updatedInfos.insert(currentInfo, at: 0)
|
||||
} else {
|
||||
updatedInfos.insert(info, at: 0)
|
||||
if let positionInList = positionInList, positionInList <= updatedInfos.count {
|
||||
updatedInfos.insert(info, at: positionInList)
|
||||
} else {
|
||||
updatedInfos.insert(info, at: 0)
|
||||
}
|
||||
transaction.replaceItemCollectionItems(collectionId: info.id, items: items)
|
||||
}
|
||||
transaction.replaceItemCollectionInfos(namespace: info.id.namespace, itemCollectionInfos: updatedInfos.map { ($0.id, $0) })
|
||||
@ -36,8 +40,8 @@ public enum RemoveStickerPackOption {
|
||||
case archive
|
||||
}
|
||||
|
||||
public func removeStickerPackInteractively(postbox: Postbox, id: ItemCollectionId, option: RemoveStickerPackOption) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
public func removeStickerPackInteractively(postbox: Postbox, id: ItemCollectionId, option: RemoveStickerPackOption) -> Signal<(Int, [ItemCollectionItem])?, NoError> {
|
||||
return postbox.transaction { transaction -> (Int, [ItemCollectionItem])? in
|
||||
let namespace: SynchronizeInstalledStickerPacksOperationNamespace?
|
||||
switch id.namespace {
|
||||
case Namespaces.ItemCollection.CloudStickerPacks:
|
||||
@ -55,8 +59,14 @@ public func removeStickerPackInteractively(postbox: Postbox, id: ItemCollectionI
|
||||
case .archive:
|
||||
content = .archive([id])
|
||||
}
|
||||
let index = transaction.getItemCollectionsInfos(namespace: id.namespace).index(where: { $0.0 == id })
|
||||
let items = transaction.getItemCollectionItems(collectionId: id)
|
||||
|
||||
addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: namespace, content: content)
|
||||
transaction.removeItemCollection(collectionId: id)
|
||||
return index.flatMap { ($0, items) }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1727,7 +1727,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
})
|
||||
}, displaySwipeToReplyHint: { [weak self] in
|
||||
if let strongSelf = self, let validLayout = strongSelf.validLayout, min(validLayout.size.width, validLayout.size.height) > 320.0 {
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .swipeToReply(title: strongSelf.presentationData.strings.Conversation_SwipeToReplyHintTitle, text: strongSelf.presentationData.strings.Conversation_SwipeToReplyHintText), elevatedLayout: true, action: { _ in }), in: .window(.root))
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .swipeToReply(title: strongSelf.presentationData.strings.Conversation_SwipeToReplyHintTitle, text: strongSelf.presentationData.strings.Conversation_SwipeToReplyHintText), elevatedLayout: true, action: { _ in return false }), in: .window(.root))
|
||||
}
|
||||
}, dismissReplyMarkupMessage: { [weak self] message in
|
||||
guard let strongSelf = self, strongSelf.presentationInterfaceState.keyboardButtonsMessage?.id == message.id else {
|
||||
|
@ -20,6 +20,7 @@ import SettingsUI
|
||||
import AlertUI
|
||||
import PresentationDataUtils
|
||||
import ShareController
|
||||
import UndoUI
|
||||
|
||||
private enum ChatMessageGalleryControllerData {
|
||||
case url(String)
|
||||
@ -304,7 +305,31 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
||||
params.navigationController?.pushViewController(controller)
|
||||
return true
|
||||
case let .stickerPack(reference):
|
||||
let controller = StickerPackScreen(context: params.context, mainStickerPack: reference, stickerPacks: [reference], sendSticker: params.sendSticker)
|
||||
let controller = StickerPackScreen(context: params.context, mainStickerPack: reference, stickerPacks: [reference], sendSticker: params.sendSticker, actionPerformed: { info, items, action in
|
||||
let presentationData = params.context.sharedContext.currentPresentationData.with { $0 }
|
||||
var animateInAsReplacement = false
|
||||
if let navigationController = params.navigationController {
|
||||
for controller in navigationController.overlayControllers {
|
||||
if let controller = controller as? UndoOverlayController {
|
||||
controller.dismissWithCommitActionAndReplacementAnimation()
|
||||
animateInAsReplacement = true
|
||||
}
|
||||
}
|
||||
}
|
||||
switch action {
|
||||
case .add:
|
||||
params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, account: params.context.account), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||
return true
|
||||
}))
|
||||
case let .remove(positionInList):
|
||||
params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).0, undo: true, info: info, topItem: items.first, account: params.context.account), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in
|
||||
if case .undo = action {
|
||||
let _ = addStickerPackInteractively(postbox: params.context.account.postbox, info: info, items: items, positionInList: positionInList).start()
|
||||
}
|
||||
return true
|
||||
}))
|
||||
}
|
||||
})
|
||||
params.dismissInput()
|
||||
params.present(controller, nil)
|
||||
return true
|
||||
|
@ -2,6 +2,9 @@ import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import TelegramPresentationData
|
||||
import SyncCore
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
|
||||
public enum UndoOverlayContent {
|
||||
case removedChat(text: String)
|
||||
@ -12,6 +15,13 @@ public enum UndoOverlayContent {
|
||||
case emoji(path: String, text: String)
|
||||
case swipeToReply(title: String, text: String)
|
||||
case actionSucceeded(title: String, text: String, cancel: String)
|
||||
case stickersModified(title: String, text: String, undo: Bool, info: StickerPackCollectionInfo, topItem: ItemCollectionItem?, account: Account)
|
||||
}
|
||||
|
||||
public enum UndoOverlayAction {
|
||||
case info
|
||||
case undo
|
||||
case commit
|
||||
}
|
||||
|
||||
public final class UndoOverlayController: ViewController {
|
||||
@ -19,12 +29,12 @@ public final class UndoOverlayController: ViewController {
|
||||
public let content: UndoOverlayContent
|
||||
private let elevatedLayout: Bool
|
||||
private let animateInAsReplacement: Bool
|
||||
private var action: (Bool) -> Void
|
||||
private var action: (UndoOverlayAction) -> Bool
|
||||
|
||||
private var didPlayPresentationAnimation = false
|
||||
private var dismissed = false
|
||||
|
||||
public init(presentationData: PresentationData, content: UndoOverlayContent, elevatedLayout: Bool, animateInAsReplacement: Bool = false, action: @escaping (Bool) -> Void) {
|
||||
public init(presentationData: PresentationData, content: UndoOverlayContent, elevatedLayout: Bool, animateInAsReplacement: Bool = false, action: @escaping (UndoOverlayAction) -> Bool) {
|
||||
self.presentationData = presentationData
|
||||
self.content = content
|
||||
self.elevatedLayout = elevatedLayout
|
||||
@ -42,7 +52,7 @@ public final class UndoOverlayController: ViewController {
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = UndoOverlayControllerNode(presentationData: self.presentationData, content: self.content, elevatedLayout: self.elevatedLayout, action: { [weak self] value in
|
||||
self?.action(value)
|
||||
return self?.action(value) ?? false
|
||||
}, dismiss: { [weak self] in
|
||||
self?.dismiss()
|
||||
})
|
||||
@ -50,12 +60,12 @@ public final class UndoOverlayController: ViewController {
|
||||
}
|
||||
|
||||
public func dismissWithCommitAction() {
|
||||
self.action(true)
|
||||
self.action(.commit)
|
||||
self.dismiss()
|
||||
}
|
||||
|
||||
public func dismissWithCommitActionAndReplacementAnimation() {
|
||||
self.action(true)
|
||||
self.action(.commit)
|
||||
(self.displayNode as! UndoOverlayControllerNode).animateOutWithReplacement(completion: { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
})
|
||||
|
@ -9,23 +9,31 @@ import Markdown
|
||||
import RadialStatusNode
|
||||
import AppBundle
|
||||
import AnimatedStickerNode
|
||||
import TelegramAnimatedStickerNode
|
||||
import AnimationUI
|
||||
import SyncCore
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import StickerResources
|
||||
|
||||
final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
private let elevatedLayout: Bool
|
||||
private let statusNode: RadialStatusNode
|
||||
private var statusNode: RadialStatusNode?
|
||||
private let timerTextNode: ImmediateTextNode
|
||||
private let iconNode: ASImageNode?
|
||||
private let iconCheckNode: RadialStatusNode?
|
||||
private let animationNode: AnimationNode?
|
||||
private let animatedStickerNode: AnimatedStickerNode?
|
||||
private var animatedStickerNode: AnimatedStickerNode?
|
||||
private var stillStickerNode: TransformImageNode?
|
||||
private var stickerImageSize: CGSize?
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let textNode: ImmediateTextNode
|
||||
private let buttonTextNode: ImmediateTextNode
|
||||
private let buttonNode: HighlightTrackingButtonNode
|
||||
private let undoButtonTextNode: ImmediateTextNode
|
||||
private let undoButtonNode: HighlightTrackingButtonNode
|
||||
private let panelNode: ASDisplayNode
|
||||
private let panelWrapperNode: ASDisplayNode
|
||||
private let action: (Bool) -> Void
|
||||
private let action: (UndoOverlayAction) -> Bool
|
||||
private let dismiss: () -> Void
|
||||
|
||||
private let effectView: UIView
|
||||
@ -38,7 +46,9 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
init(presentationData: PresentationData, content: UndoOverlayContent, elevatedLayout: Bool, action: @escaping (Bool) -> Void, dismiss: @escaping () -> Void) {
|
||||
private var fetchResourceDisposable: Disposable?
|
||||
|
||||
init(presentationData: PresentationData, content: UndoOverlayContent, elevatedLayout: Bool, action: @escaping (UndoOverlayAction) -> Bool, dismiss: @escaping () -> Void) {
|
||||
self.elevatedLayout = elevatedLayout
|
||||
|
||||
self.action = action
|
||||
@ -55,6 +65,8 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
self.textNode.displaysAsynchronously = false
|
||||
self.textNode.maximumNumberOfLines = 0
|
||||
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
|
||||
var displayUndo = true
|
||||
var undoText = presentationData.strings.Undo_Undo
|
||||
var undoTextColor = UIColor(rgb: 0x5ac8fa)
|
||||
@ -74,6 +86,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white)
|
||||
displayUndo = true
|
||||
self.originalRemainingSeconds = 5
|
||||
self.statusNode = RadialStatusNode(backgroundNodeColor: .clear)
|
||||
case let .archivedChat(_, title, text, undo):
|
||||
if undo {
|
||||
self.iconNode = ASImageNode()
|
||||
@ -129,12 +142,17 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
self.iconCheckNode = nil
|
||||
self.animationNode = AnimationNode(animation: "anim_success", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0)
|
||||
self.animatedStickerNode = nil
|
||||
|
||||
undoTextColor = UIColor(rgb: 0xff7b74)
|
||||
|
||||
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white)
|
||||
let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)
|
||||
let link = MarkdownAttributeSet(font: Font.regular(14.0), textColor: undoTextColor)
|
||||
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: link, linkAttribute: { _ in return nil }), textAlignment: .natural)
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
|
||||
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white)
|
||||
self.textNode.attributedText = attributedText
|
||||
displayUndo = true
|
||||
undoText = cancel
|
||||
undoTextColor = UIColor(rgb: 0xff7b74)
|
||||
self.originalRemainingSeconds = 3
|
||||
case let .emoji(path, text):
|
||||
self.iconNode = nil
|
||||
@ -161,17 +179,102 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
self.textNode.maximumNumberOfLines = 2
|
||||
displayUndo = false
|
||||
self.originalRemainingSeconds = 5
|
||||
case let .stickersModified(title, text, undo, info, topItem, account):
|
||||
self.iconNode = nil
|
||||
self.iconCheckNode = nil
|
||||
self.animationNode = nil
|
||||
|
||||
let stillStickerNode = TransformImageNode()
|
||||
|
||||
self.stillStickerNode = stillStickerNode
|
||||
|
||||
enum StickerPackThumbnailItem {
|
||||
case still(TelegramMediaImageRepresentation)
|
||||
case animated(MediaResource)
|
||||
}
|
||||
|
||||
var thumbnailItem: StickerPackThumbnailItem?
|
||||
var resourceReference: MediaResourceReference?
|
||||
|
||||
if let thumbnail = info.thumbnail {
|
||||
if info.flags.contains(.isAnimated) {
|
||||
thumbnailItem = .animated(thumbnail.resource)
|
||||
resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)
|
||||
} else {
|
||||
thumbnailItem = .still(thumbnail)
|
||||
resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)
|
||||
}
|
||||
} else if let item = topItem as? StickerPackItem {
|
||||
if item.file.isAnimatedSticker {
|
||||
thumbnailItem = .animated(item.file.resource)
|
||||
resourceReference = MediaResourceReference.media(media: .standalone(media: item.file), resource: item.file.resource)
|
||||
} else if let dimensions = item.file.dimensions, let resource = chatMessageStickerResource(file: item.file, small: true) as? TelegramMediaResource {
|
||||
thumbnailItem = .still(TelegramMediaImageRepresentation(dimensions: dimensions, resource: resource))
|
||||
resourceReference = MediaResourceReference.media(media: .standalone(media: item.file), resource: resource)
|
||||
}
|
||||
}
|
||||
|
||||
var updatedImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
|
||||
var updatedFetchSignal: Signal<FetchResourceSourceType, FetchResourceError>?
|
||||
|
||||
let imageBoundingSize = CGSize(width: 34.0, height: 34.0)
|
||||
|
||||
if let thumbnailItem = thumbnailItem {
|
||||
switch thumbnailItem {
|
||||
case let .still(representation):
|
||||
let stillImageSize = representation.dimensions.cgSize.aspectFitted(imageBoundingSize)
|
||||
self.stickerImageSize = stillImageSize
|
||||
|
||||
updatedImageSignal = chatMessageStickerPackThumbnail(postbox: account.postbox, resource: representation.resource)
|
||||
case let .animated(resource):
|
||||
self.stickerImageSize = imageBoundingSize
|
||||
|
||||
updatedImageSignal = chatMessageStickerPackThumbnail(postbox: account.postbox, resource: resource, animated: true)
|
||||
}
|
||||
if let resourceReference = resourceReference {
|
||||
updatedFetchSignal = fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: resourceReference)
|
||||
}
|
||||
} else {
|
||||
updatedImageSignal = .single({ _ in return nil })
|
||||
updatedFetchSignal = .complete()
|
||||
}
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
|
||||
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white)
|
||||
let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)
|
||||
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in return nil }), textAlignment: .natural)
|
||||
self.textNode.attributedText = attributedText
|
||||
self.textNode.maximumNumberOfLines = 2
|
||||
displayUndo = undo
|
||||
self.originalRemainingSeconds = 2
|
||||
|
||||
if let updatedFetchSignal = updatedFetchSignal {
|
||||
self.fetchResourceDisposable = updatedFetchSignal.start()
|
||||
}
|
||||
|
||||
if let updatedImageSignal = updatedImageSignal {
|
||||
stillStickerNode.setSignal(updatedImageSignal)
|
||||
}
|
||||
|
||||
if let thumbnailItem = thumbnailItem {
|
||||
switch thumbnailItem {
|
||||
case .still:
|
||||
break
|
||||
case let .animated(resource):
|
||||
let animatedStickerNode = AnimatedStickerNode()
|
||||
self.animatedStickerNode = animatedStickerNode
|
||||
animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: account, resource: resource), width: 80, height: 80, mode: .cached)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.remainingSeconds = self.originalRemainingSeconds
|
||||
|
||||
self.statusNode = RadialStatusNode(backgroundNodeColor: .clear)
|
||||
self.undoButtonTextNode = ImmediateTextNode()
|
||||
self.undoButtonTextNode.displaysAsynchronously = false
|
||||
self.undoButtonTextNode.attributedText = NSAttributedString(string: undoText, font: Font.regular(17.0), textColor: undoTextColor)
|
||||
|
||||
self.buttonTextNode = ImmediateTextNode()
|
||||
self.buttonTextNode.displaysAsynchronously = false
|
||||
self.buttonTextNode.attributedText = NSAttributedString(string: undoText, font: Font.regular(17.0), textColor: undoTextColor)
|
||||
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
self.undoButtonNode = HighlightTrackingButtonNode()
|
||||
|
||||
self.panelNode = ASDisplayNode()
|
||||
if presentationData.theme.overallDarkAppearance {
|
||||
@ -191,35 +294,46 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
switch content {
|
||||
case .removedChat:
|
||||
self.panelWrapperNode.addSubnode(self.timerTextNode)
|
||||
self.panelWrapperNode.addSubnode(self.statusNode)
|
||||
case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply, .actionSucceeded:
|
||||
case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified:
|
||||
break
|
||||
}
|
||||
self.statusNode.flatMap(self.panelWrapperNode.addSubnode)
|
||||
self.iconNode.flatMap(self.panelWrapperNode.addSubnode)
|
||||
self.iconCheckNode.flatMap(self.panelWrapperNode.addSubnode)
|
||||
self.animationNode.flatMap(self.panelWrapperNode.addSubnode)
|
||||
self.stillStickerNode.flatMap(self.panelWrapperNode.addSubnode)
|
||||
self.animatedStickerNode.flatMap(self.panelWrapperNode.addSubnode)
|
||||
self.panelWrapperNode.addSubnode(self.titleNode)
|
||||
self.panelWrapperNode.addSubnode(self.textNode)
|
||||
self.panelWrapperNode.addSubnode(self.buttonNode)
|
||||
if displayUndo {
|
||||
self.panelWrapperNode.addSubnode(self.buttonTextNode)
|
||||
self.panelWrapperNode.addSubnode(self.buttonNode)
|
||||
self.panelWrapperNode.addSubnode(self.undoButtonTextNode)
|
||||
self.panelWrapperNode.addSubnode(self.undoButtonNode)
|
||||
}
|
||||
self.addSubnode(self.panelNode)
|
||||
self.addSubnode(self.panelWrapperNode)
|
||||
|
||||
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
||||
self.undoButtonNode.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted {
|
||||
strongSelf.buttonTextNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.buttonTextNode.alpha = 0.4
|
||||
strongSelf.undoButtonTextNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.undoButtonTextNode.alpha = 0.4
|
||||
} else {
|
||||
strongSelf.buttonTextNode.alpha = 1.0
|
||||
strongSelf.buttonTextNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
strongSelf.undoButtonTextNode.alpha = 1.0
|
||||
strongSelf.undoButtonTextNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
||||
self.undoButtonNode.addTarget(self, action: #selector(self.undoButtonPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
self.animatedStickerNode?.started = { [weak self] in
|
||||
self?.stillStickerNode?.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.fetchResourceDisposable?.dispose()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -230,7 +344,13 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
|
||||
@objc private func buttonPressed() {
|
||||
self.action(false)
|
||||
if self.action(.info) {
|
||||
self.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func undoButtonPressed() {
|
||||
self.action(.undo)
|
||||
self.dismiss()
|
||||
}
|
||||
|
||||
@ -239,7 +359,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
self.remainingSeconds -= 1
|
||||
}
|
||||
if self.remainingSeconds == 0 {
|
||||
self.action(true)
|
||||
self.action(.commit)
|
||||
self.dismiss()
|
||||
} else {
|
||||
if !self.timerTextNode.bounds.size.width.isZero, let snapshot = self.timerTextNode.view.snapshotContentTree() {
|
||||
@ -286,9 +406,9 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
|
||||
let margin: CGFloat = 16.0
|
||||
|
||||
let buttonTextSize = self.buttonTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude))
|
||||
let buttonTextSize = self.undoButtonTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude))
|
||||
let buttonMinX: CGFloat
|
||||
if self.buttonNode.supernode != nil {
|
||||
if self.undoButtonNode.supernode != nil {
|
||||
buttonMinX = layout.size.width - layout.safeInsets.left - rightInset - buttonTextSize.width - margin * 2.0
|
||||
} else {
|
||||
buttonMinX = layout.size.width - layout.safeInsets.left - rightInset
|
||||
@ -316,8 +436,12 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
self.effectView.frame = CGRect(x: 0.0, y: 0.0, width: layout.size.width - margin * 2.0 - layout.safeInsets.left - layout.safeInsets.right, height: contentHeight)
|
||||
|
||||
let buttonTextFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - margin * 2.0, y: floor((contentHeight - buttonTextSize.height) / 2.0)), size: buttonTextSize)
|
||||
transition.updateFrame(node: self.buttonTextNode, frame: buttonTextFrame)
|
||||
self.buttonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - 8.0 - margin * 2.0, y: 0.0), size: CGSize(width: layout.safeInsets.right + rightInset + buttonTextSize.width + 8.0 + margin, height: contentHeight))
|
||||
transition.updateFrame(node: self.undoButtonTextNode, frame: buttonTextFrame)
|
||||
|
||||
let undoButtonFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - 8.0 - margin * 2.0, y: 0.0), size: CGSize(width: layout.safeInsets.right + rightInset + buttonTextSize.width + 8.0 + margin, height: contentHeight))
|
||||
self.undoButtonNode.frame = undoButtonFrame
|
||||
|
||||
self.buttonNode.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left, y: 0.0), size: CGSize(width: undoButtonFrame.minX - layout.safeInsets.left, height: contentHeight))
|
||||
|
||||
var textContentHeight = textSize.height
|
||||
var textOffset: CGFloat = 0.0
|
||||
@ -351,7 +475,22 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
transition.updateFrame(node: animationNode, frame: iconFrame)
|
||||
}
|
||||
|
||||
if let animatedStickerNode = self.animatedStickerNode {
|
||||
if let stickerImageSize = self.stickerImageSize {
|
||||
let iconSize = stickerImageSize
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((leftInset - iconSize.width) / 2.0), y: floor((contentHeight - iconSize.height) / 2.0)), size: iconSize)
|
||||
|
||||
if let stillStickerNode = self.stillStickerNode {
|
||||
let makeImageLayout = stillStickerNode.asyncLayout()
|
||||
let imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: stickerImageSize, boundingSize: stickerImageSize, intrinsicInsets: UIEdgeInsets()))
|
||||
let _ = imageApply()
|
||||
transition.updateFrame(node: stillStickerNode, frame: iconFrame)
|
||||
}
|
||||
|
||||
if let animatedStickerNode = self.animatedStickerNode {
|
||||
animatedStickerNode.updateLayout(size: iconFrame.size)
|
||||
transition.updateFrame(node: animatedStickerNode, frame: iconFrame)
|
||||
}
|
||||
} else if let animatedStickerNode = self.animatedStickerNode {
|
||||
let iconSize = CGSize(width: 32.0, height: 32.0)
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((leftInset - iconSize.width) / 2.0), y: floor((contentHeight - iconSize.height) / 2.0)), size: iconSize)
|
||||
animatedStickerNode.updateLayout(size: iconFrame.size)
|
||||
@ -361,9 +500,11 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
let timerTextSize = self.timerTextNode.updateLayout(CGSize(width: 100.0, height: 100.0))
|
||||
transition.updateFrame(node: self.timerTextNode, frame: CGRect(origin: CGPoint(x: floor((leftInset - timerTextSize.width) / 2.0), y: floor((contentHeight - timerTextSize.height) / 2.0)), size: timerTextSize))
|
||||
let statusSize: CGFloat = 30.0
|
||||
transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(x: floor((leftInset - statusSize) / 2.0), y: floor((contentHeight - statusSize) / 2.0)), size: CGSize(width: statusSize, height: statusSize)))
|
||||
if firstLayout {
|
||||
self.statusNode.transitionToState(.secretTimeout(color: .white, icon: nil, beginTime: CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970, timeout: Double(self.remainingSeconds), sparks: false), completion: {})
|
||||
if let statusNode = self.statusNode {
|
||||
transition.updateFrame(node: statusNode, frame: CGRect(origin: CGPoint(x: floor((leftInset - statusSize) / 2.0), y: floor((contentHeight - statusSize) / 2.0)), size: CGSize(width: statusSize, height: statusSize)))
|
||||
if firstLayout {
|
||||
statusNode.transitionToState(.secretTimeout(color: .white, icon: nil, beginTime: CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970, timeout: Double(self.remainingSeconds), sparks: false), completion: {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user