mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit '76aacfc03eca5bcd74ba31aca25b5b4ff3c1f86c'
# Conflicts: # Telegram/Telegram-iOS/en.lproj/Localizable.strings
This commit is contained in:
commit
fbba4f9f94
@ -9084,3 +9084,9 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Conversation.SendMessageErrorTooFastTitle" = "Not so fast";
|
||||
"Conversation.SendMessageErrorTooFast" = "You are sending messages too fast. Please wait a bit.";
|
||||
|
||||
"PeerInfo.CancelSelectionAlertText" = "Cancel selection?";
|
||||
"PeerInfo.CancelSelectionAlertYes" = "Yes";
|
||||
"PeerInfo.CancelSelectionAlertNo" = "No";
|
||||
|
||||
"StickerPacksSettings.SuggestAnimatedEmojiInfo" = "Each time you enter an emoji you can replace it with an animated emoji.";
|
||||
|
@ -115,7 +115,7 @@ final class BotCheckoutNativeCardEntryControllerNode: ViewControllerTracingNode,
|
||||
|
||||
sectionItems.append(BotPaymentHeaderItemNode(text: strings.Checkout_NewCard_CardholderNameTitle))
|
||||
|
||||
let cardholderItem = BotPaymentFieldItemNode(title: "", placeholder: strings.Checkout_NewCard_CardholderNamePlaceholder, contentType: .name)
|
||||
let cardholderItem = BotPaymentFieldItemNode(title: "", placeholder: strings.Checkout_NewCard_CardholderNamePlaceholder, contentType: .asciiName)
|
||||
self.cardholderItem = cardholderItem
|
||||
sectionItems.append(cardholderItem)
|
||||
|
||||
|
@ -9,6 +9,7 @@ private let titleFont = Font.regular(17.0)
|
||||
enum BotPaymentFieldContentType {
|
||||
case generic
|
||||
case name
|
||||
case asciiName
|
||||
case phoneNumber
|
||||
case email
|
||||
case address
|
||||
@ -51,6 +52,9 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
|
||||
case .generic:
|
||||
break
|
||||
case .name:
|
||||
self.textField.textField.autocorrectionType = .no
|
||||
self.textField.textField.keyboardType = .default
|
||||
case .asciiName:
|
||||
self.textField.textField.autocorrectionType = .no
|
||||
self.textField.textField.keyboardType = .asciiCapable
|
||||
case .address:
|
||||
|
@ -2561,10 +2561,6 @@ public final class ChatListNode: ListView {
|
||||
return strongSelf.isSelectionGestureEnabled
|
||||
}
|
||||
self.view.addGestureRecognizer(selectionRecognizer)
|
||||
|
||||
// if case .forum = location {
|
||||
// self.isSelectionGestureEnabled = false
|
||||
// }
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
@ -139,6 +139,11 @@ open class ViewControllerComponentContainer: ViewController {
|
||||
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: Transition) {
|
||||
self.currentLayout = (layout, navigationHeight)
|
||||
|
||||
var theme = self.theme ?? self.presentationData.theme
|
||||
if theme.list.blocksBackgroundColor.rgb == theme.list.plainBackgroundColor.rgb {
|
||||
theme = theme.withModalBlocksBackground()
|
||||
}
|
||||
|
||||
let environment = ViewControllerComponentContainer.Environment(
|
||||
statusBarHeight: layout.statusBarHeight ?? 0.0,
|
||||
navigationHeight: navigationHeight,
|
||||
@ -147,7 +152,7 @@ open class ViewControllerComponentContainer: ViewController {
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
isVisible: self.currentIsVisible,
|
||||
theme: self.theme ?? self.presentationData.theme,
|
||||
theme: theme,
|
||||
strings: self.presentationData.strings,
|
||||
dateTimeFormat: self.presentationData.dateTimeFormat,
|
||||
controller: { [weak self] in
|
||||
|
@ -248,7 +248,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
self.addSubnode(self.containerNode)
|
||||
self.containerNode.addSubnode(self.backgroundNode)
|
||||
self.containerNode.addSubnode(self.gridNode)
|
||||
// self.containerNode.addSubnode(self.scrollingArea)
|
||||
//self.containerNode.addSubnode(self.scrollingArea)
|
||||
|
||||
let preloadPromise = self.preloadPromise
|
||||
let updatedState: Signal<State, NoError>
|
||||
@ -359,30 +359,36 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
self.itemsDimensionsUpdatedDisposable?.dispose()
|
||||
}
|
||||
|
||||
private var selectionGesture: MediaPickerGridSelectionGesture?
|
||||
private var selectionGesture: MediaPickerGridSelectionGesture<TGMediaSelectableItem>?
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.gridNode.scrollView.alwaysBounceVertical = true
|
||||
self.gridNode.scrollView.showsVerticalScrollIndicator = false
|
||||
|
||||
self.selectionGesture = MediaPickerGridSelectionGesture(target: nil, action: nil, gridNode: self.gridNode)
|
||||
self.selectionGesture?.delegate = self
|
||||
self.selectionGesture?.began = { [weak self] in
|
||||
let selectionGesture = MediaPickerGridSelectionGesture<TGMediaSelectableItem>()
|
||||
selectionGesture.delegate = self
|
||||
selectionGesture.began = { [weak self] in
|
||||
self?.controller?.cancelPanGesture()
|
||||
}
|
||||
self.selectionGesture?.itemAt = { [weak self] point in
|
||||
selectionGesture.updateIsScrollEnabled = { [weak self] isEnabled in
|
||||
self?.gridNode.scrollView.isScrollEnabled = isEnabled
|
||||
}
|
||||
selectionGesture.itemAt = { [weak self] point in
|
||||
if let strongSelf = self, let itemNode = strongSelf.gridNode.itemNodeAtPoint(point) as? MediaPickerGridItemNode, let selectableItem = itemNode.selectableItem {
|
||||
return (selectableItem, strongSelf.controller?.interaction?.selectionState?.isIdentifierSelected(selectableItem.uniqueIdentifier) ?? false)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
self.selectionGesture?.updateSelection = { [weak self] asset, selected in
|
||||
selectionGesture.updateSelection = { [weak self] asset, selected in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controller?.interaction?.selectionState?.setItem(asset, selected: selected, animated: true, sender: nil)
|
||||
}
|
||||
}
|
||||
selectionGesture.sideInset = 44.0
|
||||
self.gridNode.view.addGestureRecognizer(selectionGesture)
|
||||
self.selectionGesture = selectionGesture
|
||||
|
||||
if let controller = self.controller, case let .assets(collection) = controller.subject, collection != nil {
|
||||
self.gridNode.view.interactiveTransitionGestureRecognizerTest = { point -> Bool in
|
||||
@ -1546,7 +1552,6 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
}
|
||||
|
||||
let controller = textAlertController(context: self.context, title: nil, text: text, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Attachment_CancelSelectionAlertNo, action: {
|
||||
|
||||
}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Attachment_CancelSelectionAlertYes, action: { [weak self] in
|
||||
self?.dismissAllTooltips()
|
||||
completion()
|
||||
@ -1794,37 +1799,31 @@ private final class MediaPickerContextReferenceContentSource: ContextReferenceCo
|
||||
}
|
||||
}
|
||||
|
||||
private class MediaPickerGridSelectionGesture: UIPanGestureRecognizer {
|
||||
var itemAt: (CGPoint) -> (TGMediaSelectableItem, Bool)? = { _ in return nil }
|
||||
var updateSelection: (TGMediaSelectableItem, Bool) -> Void = { _, _ in}
|
||||
var began: () -> Void = {}
|
||||
|
||||
private weak var gridNode: GridNode?
|
||||
public class MediaPickerGridSelectionGesture<T> : UIPanGestureRecognizer {
|
||||
public var itemAt: (CGPoint) -> (T, Bool)? = { _ in return nil }
|
||||
public var updateSelection: (T, Bool) -> Void = { _, _ in}
|
||||
public var updateIsScrollEnabled: (Bool) -> Void = { _ in}
|
||||
public var began: () -> Void = {}
|
||||
|
||||
private var processing = false
|
||||
private var selecting = false
|
||||
|
||||
private var initialLocation: CGPoint?
|
||||
|
||||
var sideInset: CGFloat = 0.0
|
||||
public var sideInset: CGFloat = 0.0
|
||||
|
||||
init(target: Any?, action: Selector?, gridNode: GridNode) {
|
||||
self.gridNode = gridNode
|
||||
|
||||
super.init(target: target, action: action)
|
||||
|
||||
gridNode.view.addGestureRecognizer(self)
|
||||
public init() {
|
||||
super.init(target: nil, action: nil)
|
||||
}
|
||||
|
||||
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
super.touchesBegan(touches, with: event)
|
||||
|
||||
guard let touch = touches.first, self.numberOfTouches == 1, let gridNode = self.gridNode else {
|
||||
guard let touch = touches.first, self.numberOfTouches == 1 else {
|
||||
return
|
||||
}
|
||||
|
||||
let location = touch.location(in: gridNode.view)
|
||||
|
||||
let location = touch.location(in: self.view)
|
||||
if location.x > self.sideInset {
|
||||
self.initialLocation = location
|
||||
} else {
|
||||
@ -1832,15 +1831,15 @@ private class MediaPickerGridSelectionGesture: UIPanGestureRecognizer {
|
||||
}
|
||||
}
|
||||
|
||||
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
public override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
super.touchesMoved(touches, with: event)
|
||||
|
||||
guard let touch = touches.first, let gridNode = self.gridNode, let initialLocation = self.initialLocation else {
|
||||
guard let touch = touches.first, let initialLocation = self.initialLocation else {
|
||||
self.state = .failed
|
||||
return
|
||||
}
|
||||
|
||||
let location = touch.location(in: gridNode.view)
|
||||
let location = touch.location(in: self.view)
|
||||
let translation = CGPoint(x: location.x - initialLocation.x, y: location.y - initialLocation.y)
|
||||
|
||||
var additionalLocation: CGPoint?
|
||||
@ -1849,7 +1848,7 @@ private class MediaPickerGridSelectionGesture: UIPanGestureRecognizer {
|
||||
self.state = .failed
|
||||
} else if abs(translation.x) > 8.0 {
|
||||
self.processing = true
|
||||
self.gridNode?.scrollView.isScrollEnabled = false
|
||||
self.updateIsScrollEnabled(false)
|
||||
self.began()
|
||||
|
||||
if let (_, selected) = self.itemAt(location) {
|
||||
@ -1873,25 +1872,25 @@ private class MediaPickerGridSelectionGesture: UIPanGestureRecognizer {
|
||||
}
|
||||
}
|
||||
|
||||
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
public override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
super.touchesEnded(touches, with: event)
|
||||
|
||||
self.state = .failed
|
||||
self.reset()
|
||||
}
|
||||
|
||||
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
public override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
super.touchesCancelled(touches, with: event)
|
||||
|
||||
self.state = .failed
|
||||
self.reset()
|
||||
}
|
||||
|
||||
override func reset() {
|
||||
public override func reset() {
|
||||
super.reset()
|
||||
|
||||
self.processing = false
|
||||
self.initialLocation = nil
|
||||
self.gridNode?.scrollView.isScrollEnabled = true
|
||||
self.updateIsScrollEnabled(true)
|
||||
}
|
||||
}
|
||||
|
@ -593,7 +593,7 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI
|
||||
strongSelf.wallpaperBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, completion: { _ in
|
||||
completion()
|
||||
})
|
||||
strongSelf.wallpaperBackgroundNode.layer.animateScale(from: 1.2, to: 1.0, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
strongSelf.wallpaperBackgroundNode.layer.animateScale(from: 1.2, to: 1.0, duration: 0.33, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
|
||||
for (_, backgroundNode) in strongSelf.backgroundNodes {
|
||||
backgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: 0.1)
|
||||
@ -641,7 +641,7 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI
|
||||
}
|
||||
})
|
||||
|
||||
self.wallpaperBackgroundNode.layer.animateScale(from: 1.0, to: 1.2, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
self.wallpaperBackgroundNode.layer.animateScale(from: 1.0, to: 1.2, duration: 0.33, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
|
||||
for (_, backgroundNode) in self.backgroundNodes {
|
||||
backgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false)
|
||||
|
@ -167,7 +167,6 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
||||
|
||||
static var body: Body {
|
||||
let overscroll = Child(Rectangle.self)
|
||||
let fade = Child(RoundedRectangle.self)
|
||||
let text = Child(MultilineTextComponent.self)
|
||||
let optionsSection = Child(SectionGroupComponent.self)
|
||||
let perksSection = Child(SectionGroupComponent.self)
|
||||
@ -195,23 +194,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
||||
context.add(overscroll
|
||||
.position(CGPoint(x: overscroll.size.width / 2.0, y: -overscroll.size.height / 2.0))
|
||||
)
|
||||
|
||||
let fade = fade.update(
|
||||
component: RoundedRectangle(
|
||||
colors: [
|
||||
theme.list.plainBackgroundColor,
|
||||
theme.list.blocksBackgroundColor
|
||||
],
|
||||
cornerRadius: 0.0,
|
||||
gradientDirection: .vertical
|
||||
),
|
||||
availableSize: CGSize(width: availableWidth, height: 300),
|
||||
transition: context.transition
|
||||
)
|
||||
context.add(fade
|
||||
.position(CGPoint(x: fade.size.width / 2.0, y: fade.size.height / 2.0))
|
||||
)
|
||||
|
||||
|
||||
size.height += 183.0 + 10.0 + environment.navigationHeight - 56.0
|
||||
|
||||
let textColor = theme.list.itemPrimaryTextColor
|
||||
|
@ -45,13 +45,14 @@ public class ItemListReactionItem: ListViewItem, ItemListItem {
|
||||
|
||||
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||
async {
|
||||
let node = ItemListReactionItemNode()
|
||||
let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
||||
|
||||
node.contentSize = layout.contentSize
|
||||
node.insets = layout.insets
|
||||
|
||||
Queue.mainQueue().async {
|
||||
let node = ItemListReactionItemNode()
|
||||
let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
||||
|
||||
node.contentSize = layout.contentSize
|
||||
node.insets = layout.insets
|
||||
|
||||
|
||||
completion(node, {
|
||||
return (nil, { _ in apply() })
|
||||
})
|
||||
|
@ -92,6 +92,7 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
||||
case packOrder(PresentationTheme, String, Bool)
|
||||
case packOrderInfo(PresentationTheme, String)
|
||||
case suggestAnimatedEmoji(String, Bool)
|
||||
case suggestAnimatedEmojiInfo(PresentationTheme, String)
|
||||
case packsTitle(PresentationTheme, String)
|
||||
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool, Bool, ItemListStickerPackItemEditing, Bool?)
|
||||
case packsInfo(PresentationTheme, String)
|
||||
@ -100,7 +101,7 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
||||
switch self {
|
||||
case .trending, .masks, .emoji, .quickReaction, .archived:
|
||||
return InstalledStickerPacksSection.categories.rawValue
|
||||
case .suggestOptions, .largeEmoji, .suggestAnimatedEmoji, .packOrder, .packOrderInfo:
|
||||
case .suggestOptions, .largeEmoji, .suggestAnimatedEmoji, .suggestAnimatedEmojiInfo, .packOrder, .packOrderInfo:
|
||||
return InstalledStickerPacksSection.settings.rawValue
|
||||
case .packsTitle, .pack, .packsInfo:
|
||||
return InstalledStickerPacksSection.stickers.rawValue
|
||||
@ -125,16 +126,18 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
||||
return .index(6)
|
||||
case .suggestAnimatedEmoji:
|
||||
return .index(7)
|
||||
case .packOrder:
|
||||
case .suggestAnimatedEmojiInfo:
|
||||
return .index(8)
|
||||
case .packOrderInfo:
|
||||
case .packOrder:
|
||||
return .index(9)
|
||||
case .packsTitle:
|
||||
case .packOrderInfo:
|
||||
return .index(10)
|
||||
case .packsTitle:
|
||||
return .index(11)
|
||||
case let .pack(_, _, _, info, _, _, _, _, _, _):
|
||||
return .pack(info.id)
|
||||
case .packsInfo:
|
||||
return .index(11)
|
||||
return .index(12)
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,6 +203,12 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .suggestAnimatedEmojiInfo(lhsTheme, lhsText):
|
||||
if case let .suggestAnimatedEmojiInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .packsTitle(lhsTheme, lhsText):
|
||||
if case let .packsTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
@ -323,9 +332,16 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case .suggestAnimatedEmojiInfo:
|
||||
switch rhs {
|
||||
case .trending, .archived, .masks, .emoji, .quickReaction, .suggestOptions, .largeEmoji, .packOrder, .packOrderInfo, .suggestAnimatedEmoji, .suggestAnimatedEmojiInfo:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case .packsTitle:
|
||||
switch rhs {
|
||||
case .trending, .archived, .masks, .emoji, .quickReaction, .suggestOptions, .largeEmoji, .packOrder, .packOrderInfo, .suggestAnimatedEmoji, .packsTitle:
|
||||
case .trending, .archived, .masks, .emoji, .quickReaction, .suggestOptions, .largeEmoji, .packOrder, .packOrderInfo, .suggestAnimatedEmoji, .suggestAnimatedEmojiInfo, .packsTitle:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
@ -390,6 +406,8 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleSuggestAnimatedEmoji(value)
|
||||
})
|
||||
case let .suggestAnimatedEmojiInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .packsTitle(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .pack(_, _, _, info, topItem, count, animatedStickers, enabled, editing, selected):
|
||||
@ -531,6 +549,7 @@ private func installedStickerPacksControllerEntries(context: AccountContext, pre
|
||||
}
|
||||
|
||||
entries.append(.suggestAnimatedEmoji(presentationData.strings.StickerPacksSettings_SuggestAnimatedEmoji, stickerSettings.suggestAnimatedEmoji))
|
||||
entries.append(.suggestAnimatedEmojiInfo(presentationData.theme, presentationData.strings.StickerPacksSettings_SuggestAnimatedEmojiInfo))
|
||||
}
|
||||
|
||||
if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespaceForMode(mode)])] as? ItemCollectionInfosView {
|
||||
|
@ -711,11 +711,10 @@ class ThemeCarouselThemeItemNode: ListViewItemNode, ItemListItemNode {
|
||||
strongSelf.item = item
|
||||
strongSelf.layoutParams = params
|
||||
|
||||
strongSelf.listNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
|
||||
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
strongSelf.containerNode.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||
}
|
||||
@ -828,10 +827,11 @@ class ThemeCarouselThemeItemNode: ListViewItemNode, ItemListItemNode {
|
||||
self.snapshotView = snapshotView
|
||||
}
|
||||
|
||||
self.listNode.forEachVisibleItemNode { node in
|
||||
self.listNode.enumerateItemNodes { node in
|
||||
if let node = node as? ThemeCarouselThemeItemIconNode {
|
||||
node.prepareCrossfadeTransition()
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,22 +839,23 @@ class ThemeCarouselThemeItemNode: ListViewItemNode, ItemListItemNode {
|
||||
guard self.snapshotView?.layer.animationKeys()?.isEmpty ?? true else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
var views: [UIView] = []
|
||||
if let snapshotView = self.snapshotView {
|
||||
views.append(snapshotView)
|
||||
self.snapshotView = nil
|
||||
}
|
||||
|
||||
self.listNode.forEachVisibleItemNode { node in
|
||||
|
||||
self.listNode.enumerateItemNodes { node in
|
||||
if let node = node as? ThemeCarouselThemeItemIconNode {
|
||||
if let snapshotView = node.snapshotView {
|
||||
views.append(snapshotView)
|
||||
node.snapshotView = nil
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
UIView.animate(withDuration: 0.3, animations: {
|
||||
for view in views {
|
||||
view.alpha = 0.0
|
||||
|
@ -1292,9 +1292,7 @@ public final class ThemeSettingsCrossfadeController: ViewController {
|
||||
|
||||
public init(view: UIView? = nil, topOffset: CGFloat? = nil, bottomOffset: CGFloat? = nil, leftOffset: CGFloat? = nil, sideInset: CGFloat = 0.0) {
|
||||
if let view = view {
|
||||
if var leftOffset = leftOffset {
|
||||
leftOffset += UIScreenPixel
|
||||
|
||||
if let leftOffset = leftOffset {
|
||||
if let view = view.snapshotView(afterScreenUpdates: false) {
|
||||
let clipView = UIView()
|
||||
clipView.clipsToBounds = true
|
||||
@ -1306,13 +1304,13 @@ public final class ThemeSettingsCrossfadeController: ViewController {
|
||||
if let topOffset = topOffset, let bottomOffset = bottomOffset {
|
||||
var frame = view.frame
|
||||
frame.origin.y = topOffset
|
||||
frame.size.width = leftOffset
|
||||
frame.size.width = leftOffset + sideInset
|
||||
frame.size.height = bottomOffset - topOffset
|
||||
clipView.frame = frame
|
||||
|
||||
frame = view.frame
|
||||
frame.origin.y = -topOffset
|
||||
frame.size.width = leftOffset
|
||||
frame.size.width = leftOffset + sideInset
|
||||
frame.size.height = bottomOffset
|
||||
view.frame = frame
|
||||
}
|
||||
@ -1322,7 +1320,7 @@ public final class ThemeSettingsCrossfadeController: ViewController {
|
||||
}
|
||||
|
||||
if sideInset > 0.0 {
|
||||
if let view = view.snapshotView(afterScreenUpdates: false) {
|
||||
if let view = view.snapshotView(afterScreenUpdates: false), leftOffset == nil {
|
||||
let clipView = UIView()
|
||||
clipView.clipsToBounds = true
|
||||
clipView.addSubview(view)
|
||||
|
@ -1344,6 +1344,12 @@ public final class SparseItemGrid: ASDisplayNode {
|
||||
self.pinchRecognizer?.isEnabled = self.pinchEnabled
|
||||
}
|
||||
}
|
||||
|
||||
public var isScrollEnabled: Bool = true {
|
||||
didSet {
|
||||
self.currentViewport?.scrollView.isScrollEnabled = self.isScrollEnabled
|
||||
}
|
||||
}
|
||||
|
||||
public init(theme: PresentationTheme, initialZoomLevel: ZoomLevel? = nil) {
|
||||
self.theme = theme
|
||||
|
@ -8,22 +8,21 @@ import MtProtoKit
|
||||
func _internal_requestStartBot(account: Account, botPeerId: PeerId, payload: String?) -> Signal<Void, NoError> {
|
||||
if let payload = payload, !payload.isEmpty {
|
||||
return account.postbox.loadedPeerWithId(botPeerId)
|
||||
|> mapToSignal { botPeer -> Signal<Void, NoError> in
|
||||
if let inputUser = apiInputUser(botPeer) {
|
||||
let r = account.network.request(Api.functions.messages.startBot(bot: inputUser, peer: .inputPeerEmpty, randomId: Int64.random(in: Int64.min ... Int64.max), startParam: payload))
|
||||
|> mapToSignal { result -> Signal<Void, MTRpcError> in
|
||||
account.stateManager.addUpdates(result)
|
||||
return .complete()
|
||||
}
|
||||
|> `catch` { _ -> Signal<Void, MTRpcError> in
|
||||
return .complete()
|
||||
}
|
||||
return r
|
||||
|> retryRequest
|
||||
} else {
|
||||
|> mapToSignal { botPeer -> Signal<Void, NoError> in
|
||||
if let inputUser = apiInputUser(botPeer) {
|
||||
return account.network.request(Api.functions.messages.startBot(bot: inputUser, peer: .inputPeerEmpty, randomId: Int64.random(in: Int64.min ... Int64.max), startParam: payload))
|
||||
|> mapToSignal { result -> Signal<Void, MTRpcError> in
|
||||
account.stateManager.addUpdates(result)
|
||||
return .complete()
|
||||
}
|
||||
|> `catch` { _ -> Signal<Void, MTRpcError> in
|
||||
return .complete()
|
||||
}
|
||||
|> retryRequest
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return enqueueMessages(account: account, peerId: botPeerId, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) |> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
|
@ -4104,7 +4104,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return state.updatedShowWebView(true).updatedForceInputCommandsHidden(true)
|
||||
}
|
||||
|
||||
let params = WebAppParameters(peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, fromMenu: true, isInline: false, isSimple: false)
|
||||
let params = WebAppParameters(peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, fromMenu: true, fromAttachMenu: false, isInline: false, isSimple: false)
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url in
|
||||
self?.openUrl(url, concealed: true, forceExternal: true)
|
||||
}, getInputContainerNode: { [weak self] in
|
||||
@ -4159,7 +4159,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let params = WebAppParameters(peerId: peerId, botId: botId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, fromMenu: false, isInline: isInline, isSimple: true)
|
||||
let params = WebAppParameters(peerId: peerId, botId: botId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, fromMenu: false, fromAttachMenu: false, isInline: isInline, isSimple: true)
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url in
|
||||
self?.openUrl(url, concealed: true, forceExternal: true)
|
||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||
@ -4199,7 +4199,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let params = WebAppParameters(peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, payload: nil, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, fromMenu: false, isInline: false, isSimple: false)
|
||||
let params = WebAppParameters(peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, payload: nil, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, fromMenu: false, fromAttachMenu: false, isInline: false, isSimple: false)
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url in
|
||||
self?.openUrl(url, concealed: true, forceExternal: true)
|
||||
}, completion: { [weak self] in
|
||||
@ -12727,7 +12727,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let params = WebAppParameters(peerId: peerId, botId: peerId, botName: botApp.title, url: url, queryId: 0, payload: payload, buttonText: "", keepAliveSignal: nil, fromMenu: false, isInline: false, isSimple: false)
|
||||
let params = WebAppParameters(peerId: peerId, botId: peerId, botName: botApp.title, url: url, queryId: 0, payload: payload, buttonText: "", keepAliveSignal: nil, fromMenu: false, fromAttachMenu: false, isInline: false, isSimple: false)
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url in
|
||||
self?.openUrl(url, concealed: true, forceExternal: true)
|
||||
}, completion: { [weak self] in
|
||||
@ -13247,10 +13247,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
case let .app(bot, botName, _):
|
||||
var payload: String?
|
||||
var fromAttachMenu = true
|
||||
if case let .bot(_, botPayload, _) = subject {
|
||||
payload = botPayload
|
||||
fromAttachMenu = false
|
||||
}
|
||||
let params = WebAppParameters(peerId: peer.id, botId: bot.id, botName: botName, url: nil, queryId: nil, payload: payload, buttonText: nil, keepAliveSignal: nil, fromMenu: false, isInline: false, isSimple: false)
|
||||
let params = WebAppParameters(peerId: peer.id, botId: bot.id, botName: botName, url: nil, queryId: nil, payload: payload, buttonText: nil, keepAliveSignal: nil, fromMenu: false, fromAttachMenu: fromAttachMenu, isInline: false, isSimple: false)
|
||||
let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId
|
||||
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, replyToMessageId: replyMessageId, threadId: strongSelf.chatLocation.threadId)
|
||||
controller.openUrl = { [weak self] url in
|
||||
|
@ -1597,8 +1597,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
}
|
||||
|
||||
let keyboardAppearance = interfaceState.theme.rootController.keyboardColor.keyboardAppearance
|
||||
if let textInputNode = self.textInputNode, textInputNode.keyboardAppearance != keyboardAppearance, textInputNode.isFirstResponder() {
|
||||
if textInputNode.isCurrentlyEmoji() {
|
||||
if let textInputNode = self.textInputNode, textInputNode.keyboardAppearance != keyboardAppearance {
|
||||
if textInputNode.isFirstResponder() && textInputNode.isCurrentlyEmoji() {
|
||||
textInputNode.initialPrimaryLanguage = "emoji"
|
||||
textInputNode.resetInitialPrimaryLanguage()
|
||||
}
|
||||
@ -2268,7 +2268,13 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
|
||||
let _ = placeholderApply()
|
||||
|
||||
transition.updateFrame(node: contextPlaceholderNode, frame: CGRect(origin: CGPoint(x: hideOffset.x + leftInset + textFieldInsets.left + self.textInputViewInternalInsets.left, y: hideOffset.y + textFieldInsets.top + self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel), size: placeholderSize.size))
|
||||
let placeholderTransition: ContainedViewLayoutTransition
|
||||
if placeholderSize.size.width == contextPlaceholderNode.frame.width {
|
||||
placeholderTransition = transition
|
||||
} else {
|
||||
placeholderTransition = .immediate
|
||||
}
|
||||
placeholderTransition.updateFrame(node: contextPlaceholderNode, frame: CGRect(origin: CGPoint(x: hideOffset.x + leftInset + textFieldInsets.left + self.textInputViewInternalInsets.left, y: hideOffset.y + textFieldInsets.top + self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel), size: placeholderSize.size))
|
||||
contextPlaceholderNode.alpha = audioRecordingItemsAlpha
|
||||
} else if let contextPlaceholderNode = self.contextPlaceholderNode {
|
||||
self.contextPlaceholderNode = nil
|
||||
|
@ -210,7 +210,7 @@ final class CommandMenuChatInputPanelItemNode: ListViewItemNode {
|
||||
|
||||
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: textString, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 130.0, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (commandLayout, commandApply) = makeCommandLayout(TextNodeLayoutArguments(attributedString: commandString, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: 120.0, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (commandLayout, commandApply) = makeCommandLayout(TextNodeLayoutArguments(attributedString: commandString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - rightInset - textLayout.size.width - 16.0, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: max(CommandMenuChatInputPanelItemNode.itemHeight, textLayout.size.height + 14.0)), insets: UIEdgeInsets())
|
||||
|
||||
|
@ -25,6 +25,7 @@ import CheckNode
|
||||
import AppBundle
|
||||
import ChatControllerInteraction
|
||||
import InvisibleInkDustNode
|
||||
import MediaPickerUI
|
||||
|
||||
private final class FrameSequenceThumbnailNode: ASDisplayNode {
|
||||
private let context: AccountContext
|
||||
@ -1631,7 +1632,7 @@ private func tagMaskForType(_ type: PeerInfoVisualMediaPaneNode.ContentType) ->
|
||||
}
|
||||
}
|
||||
|
||||
final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate {
|
||||
final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate, UIGestureRecognizerDelegate {
|
||||
enum ContentType {
|
||||
case photoOrVideo
|
||||
case photo
|
||||
@ -2445,6 +2446,27 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
self.itemGrid.addToTransitionSurface(view: view)
|
||||
}
|
||||
|
||||
private var gridSelectionGesture: MediaPickerGridSelectionGesture<EngineMessage.Id>?
|
||||
private var listSelectionGesture: MediaPickerGridSelectionGesture<EngineMessage.Id>?
|
||||
|
||||
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
let location = gestureRecognizer.location(in: gestureRecognizer.view)
|
||||
if location.x < 44.0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
if gestureRecognizer.state != .failed, let otherGestureRecognizer = otherGestureRecognizer as? UIPanGestureRecognizer {
|
||||
otherGestureRecognizer.isEnabled = false
|
||||
otherGestureRecognizer.isEnabled = true
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func updateSelectedMessages(animated: Bool) {
|
||||
switch self.contentType {
|
||||
case .files, .music, .voiceAndVideoMessages:
|
||||
@ -2473,7 +2495,36 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
itemLayer.updateSelection(theme: self.itemGridBinding.checkNodeTheme, isSelected: self.chatControllerInteraction.selectionState?.selectedIds.contains(item.message.id), animated: animated)
|
||||
}
|
||||
|
||||
self.itemGrid.pinchEnabled = self.chatControllerInteraction.selectionState == nil
|
||||
let isSelecting = self.chatControllerInteraction.selectionState != nil
|
||||
self.itemGrid.pinchEnabled = !isSelecting
|
||||
|
||||
if isSelecting {
|
||||
if self.gridSelectionGesture == nil {
|
||||
let selectionGesture = MediaPickerGridSelectionGesture<EngineMessage.Id>()
|
||||
selectionGesture.delegate = self
|
||||
selectionGesture.sideInset = 44.0
|
||||
selectionGesture.updateIsScrollEnabled = { [weak self] isEnabled in
|
||||
self?.itemGrid.isScrollEnabled = isEnabled
|
||||
}
|
||||
selectionGesture.itemAt = { [weak self] point in
|
||||
if let strongSelf = self, let itemLayer = strongSelf.itemGrid.item(at: point)?.layer as? ItemLayer, let messageId = itemLayer.item?.message.id {
|
||||
return (messageId, strongSelf.chatControllerInteraction.selectionState?.selectedIds.contains(messageId) ?? false)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
selectionGesture.updateSelection = { [weak self] messageId, selected in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatControllerInteraction.toggleMessagesSelection([messageId], selected)
|
||||
}
|
||||
}
|
||||
self.itemGrid.view.addGestureRecognizer(selectionGesture)
|
||||
self.gridSelectionGesture = selectionGesture
|
||||
}
|
||||
} else if let gridSelectionGesture = self.gridSelectionGesture {
|
||||
self.itemGrid.view.removeGestureRecognizer(gridSelectionGesture)
|
||||
self.gridSelectionGesture = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2101,7 +2101,7 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode {
|
||||
|
||||
func update(width: CGFloat, safeInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, peer: Peer?, threadData: MessageHistoryThreadData?, chatLocation: ChatLocation, cachedData: CachedPeerData?, isContact: Bool, isSettings: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
let avatarSize: CGFloat = isModalOverlay ? 200.0 : 100.0
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 13.0), size: CGSize(width: avatarSize, height: avatarSize))
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 22.0), size: CGSize(width: avatarSize, height: avatarSize))
|
||||
transition.updateFrameAdditiveToCenter(node: self.avatarNode, frame: CGRect(origin: avatarFrame.center, size: CGSize()))
|
||||
|
||||
var contentHeight: CGFloat = statusBarHeight + 10.0 + avatarSize + 20.0
|
||||
@ -3675,12 +3675,16 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
private class DynamicIslandMaskNode: ManagedAnimationNode {
|
||||
var frameIndex: Int = 0
|
||||
|
||||
func update(_ value: CGFloat) {
|
||||
let lowerBound = 0
|
||||
let upperBound = 180
|
||||
let frameIndex = lowerBound + Int(value * CGFloat(upperBound - lowerBound))
|
||||
|
||||
self.trackTo(item: ManagedAnimationItem(source: .local("UserAvatarMask"), frames: .range(startFrame: frameIndex, endFrame: frameIndex), duration: 0.001))
|
||||
if frameIndex != self.frameIndex {
|
||||
self.frameIndex = frameIndex
|
||||
self.trackTo(item: ManagedAnimationItem(source: .local("UserAvatarMask"), frames: .range(startFrame: frameIndex, endFrame: frameIndex), duration: 0.001))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3730,6 +3734,7 @@ private class DynamicIslandBlurNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
func update(_ value: CGFloat) {
|
||||
let fadeAlpha = min(1.0, max(0.0, -0.25 + value * 1.55))
|
||||
if value > 0.0 {
|
||||
self.prepare()
|
||||
self.effectView?.layer.timeOffset = max(0.0, -0.1 + value * 1.1)
|
||||
@ -3739,8 +3744,7 @@ private class DynamicIslandBlurNode: ASDisplayNode {
|
||||
self.effectView?.layer.timeOffset = 0.0
|
||||
self.effectView?.effect = nil
|
||||
}
|
||||
|
||||
self.fadeNode.alpha = min(1.0, max(0.0, -0.25 + value * 1.55))
|
||||
self.fadeNode.alpha = fadeAlpha
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
|
@ -9313,6 +9313,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fileprivate func presentSelectionDiscardAlert(action: @escaping () -> Void = {}) -> Bool {
|
||||
if let selectedIds = self.chatInterfaceInteraction.selectionState?.selectedIds, !selectedIds.isEmpty {
|
||||
self.controller?.present(textAlertController(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, title: nil, text: self.presentationData.strings.PeerInfo_CancelSelectionAlertText, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.PeerInfo_CancelSelectionAlertNo, action: {}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.PeerInfo_CancelSelectionAlertYes, action: {
|
||||
action()
|
||||
})]), in: .window(.root))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortcutResponder {
|
||||
@ -9666,6 +9676,20 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if !isSettings {
|
||||
self.attemptNavigation = { [weak self] action in
|
||||
guard let strongSelf = self else {
|
||||
return true
|
||||
}
|
||||
|
||||
if strongSelf.controllerNode.presentSelectionDiscardAlert(action: action) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
|
@ -667,7 +667,7 @@ public class ShareRootControllerImpl {
|
||||
attemptSelectionImpl?(peer)
|
||||
}, createNewGroup: {
|
||||
createNewGroupImpl?()
|
||||
}, pretendPresentedInModal: true, selectForumThreads: true))
|
||||
}, pretendPresentedInModal: true, selectForumThreads: false))
|
||||
|
||||
controller.customDismiss = {
|
||||
self?.getExtensionContext()?.completeRequest(returningItems: nil, completionHandler: nil)
|
||||
|
@ -154,6 +154,7 @@ private final class EffectImageLayer: SimpleLayer, GradientBackgroundPatternOver
|
||||
}
|
||||
|
||||
private var isUsingSoftlight: Bool = false
|
||||
private var useFilter: Bool = false
|
||||
|
||||
var suspendCompositionUpdates: Bool = false
|
||||
private var needsCompositionUpdate: Bool = false
|
||||
@ -172,10 +173,11 @@ private final class EffectImageLayer: SimpleLayer, GradientBackgroundPatternOver
|
||||
useSoftlight = true
|
||||
useFilter = false
|
||||
}
|
||||
if self.isUsingSoftlight != useSoftlight {
|
||||
if self.isUsingSoftlight != useSoftlight || self.useFilter != useFilter {
|
||||
self.isUsingSoftlight = useSoftlight
|
||||
self.useFilter = useFilter
|
||||
|
||||
if self.isUsingSoftlight && useFilter {
|
||||
if self.isUsingSoftlight && self.useFilter {
|
||||
self.compositingFilter = "softLightBlendMode"
|
||||
} else {
|
||||
self.compositingFilter = nil
|
||||
@ -842,10 +844,6 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
}
|
||||
private static var cachedSharedPattern: (PatternKey, UIImage)?
|
||||
|
||||
//private var inlineAnimationNodes: [(AnimatedStickerNode, CGPoint)] = []
|
||||
//private let hierarchyTrackingLayer = HierarchyTrackingLayer()
|
||||
//private var activateInlineAnimationTimer: SwiftSignalKit.Timer?
|
||||
|
||||
private let _isReady = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
var isReady: Signal<Bool, NoError> {
|
||||
return self._isReady.get()
|
||||
@ -1308,13 +1306,6 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
}
|
||||
|
||||
self.loadPatternForSizeIfNeeded(size: size, displayMode: displayMode, transition: transition)
|
||||
|
||||
/*for (animationNode, relativePosition) in self.inlineAnimationNodes {
|
||||
let sizeNorm = CGSize(width: 1440, height: 2960)
|
||||
let animationSize = CGSize(width: 512.0 / sizeNorm.width * size.width, height: 512.0 / sizeNorm.height * size.height)
|
||||
animationNode.frame = CGRect(origin: CGPoint(x: relativePosition.x / sizeNorm.width * size.width, y: relativePosition.y / sizeNorm.height * size.height), size: animationSize)
|
||||
animationNode.updateLayout(size: animationNode.frame.size)
|
||||
}*/
|
||||
|
||||
if isFirstLayout && !self.frame.isEmpty {
|
||||
self.updateScale()
|
||||
|
@ -134,6 +134,7 @@ public struct WebAppParameters {
|
||||
let buttonText: String?
|
||||
let keepAliveSignal: Signal<Never, KeepWebViewError>?
|
||||
let fromMenu: Bool
|
||||
let fromAttachMenu: Bool
|
||||
let isInline: Bool
|
||||
let isSimple: Bool
|
||||
|
||||
@ -147,6 +148,7 @@ public struct WebAppParameters {
|
||||
buttonText: String?,
|
||||
keepAliveSignal: Signal<Never, KeepWebViewError>?,
|
||||
fromMenu: Bool,
|
||||
fromAttachMenu: Bool,
|
||||
isInline: Bool,
|
||||
isSimple: Bool
|
||||
) {
|
||||
@ -159,6 +161,7 @@ public struct WebAppParameters {
|
||||
self.buttonText = buttonText
|
||||
self.keepAliveSignal = keepAliveSignal
|
||||
self.fromMenu = fromMenu
|
||||
self.fromAttachMenu = fromAttachMenu
|
||||
self.isInline = isInline
|
||||
self.isSimple = isSimple
|
||||
}
|
||||
@ -656,7 +659,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
self.handleSendData(data: eventData)
|
||||
}
|
||||
case "web_app_setup_main_button":
|
||||
if let webView = self.webView, !webView.didTouchOnce && controller.url == nil {
|
||||
if let webView = self.webView, !webView.didTouchOnce && controller.url == nil && controller.fromAttachMenu {
|
||||
self.delayedScriptMessage = message
|
||||
} else if let json = json {
|
||||
if var isVisible = json["is_visible"] as? Bool {
|
||||
@ -1058,6 +1061,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
private let payload: String?
|
||||
private let buttonText: String?
|
||||
private let fromMenu: Bool
|
||||
private let fromAttachMenu: Bool
|
||||
private let isInline: Bool
|
||||
private let isSimple: Bool
|
||||
private let keepAliveSignal: Signal<Never, KeepWebViewError>?
|
||||
@ -1083,6 +1087,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
self.payload = params.payload
|
||||
self.buttonText = params.buttonText
|
||||
self.fromMenu = params.fromMenu
|
||||
self.fromAttachMenu = params.fromAttachMenu
|
||||
self.isInline = params.isInline
|
||||
self.isSimple = params.isSimple
|
||||
self.keepAliveSignal = params.keepAliveSignal
|
||||
|
Loading…
x
Reference in New Issue
Block a user