UI fixes
@ -198,6 +198,7 @@
|
||||
09EBE2AF22B004EA00F670AB /* BlackIconIpad@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 09EBE2A322B004E900F670AB /* BlackIconIpad@2x.png */; };
|
||||
09EBE2B022B004EA00F670AB /* BlueFilledIconLargeIpad@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 09EBE2A422B004E900F670AB /* BlueFilledIconLargeIpad@2x.png */; };
|
||||
09EC0DE322C6339700E7185B /* IntentMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09EC0DE222C6339700E7185B /* IntentMessages.swift */; };
|
||||
09EC5CDA22CBBF9600292E42 /* telegram_plane1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 09EC5CD922CBBF9600292E42 /* telegram_plane1@2x.png */; };
|
||||
09FDAEE62140477F00BF856F /* MtProtoKitDynamic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09FDAEE52140477F00BF856F /* MtProtoKitDynamic.framework */; };
|
||||
D000CACF21FB6E380011B15D /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D000CAC821FB6E370011B15D /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
D001D5AA1F878DA300DF975A /* PhoneCountries.txt in Resources */ = {isa = PBXBuildFile; fileRef = D001D5A91F878DA300DF975A /* PhoneCountries.txt */; };
|
||||
@ -316,7 +317,6 @@
|
||||
D08DB0BC213F4D1D00F2ADBF /* start_arrow@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D050F2311E49DEDE00988324 /* start_arrow@2x.png */; };
|
||||
D08DB0BD213F4D1D00F2ADBF /* start_arrow_ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = D050F2321E49DEDE00988324 /* start_arrow_ipad.png */; };
|
||||
D08DB0BE213F4D1D00F2ADBF /* start_arrow_ipad@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D050F2331E49DEDE00988324 /* start_arrow_ipad@2x.png */; };
|
||||
D08DB0BF213F4D1D00F2ADBF /* telegram_plane1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D050F2341E49DEDE00988324 /* telegram_plane1@2x.png */; };
|
||||
D08DB0C0213F4D1D00F2ADBF /* telegram_sphere@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D050F2351E49DEDE00988324 /* telegram_sphere@2x.png */; };
|
||||
D096C2BE1CC3C021006D814E /* Display.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D096C2BD1CC3C021006D814E /* Display.framework */; };
|
||||
D096C2BF1CC3C021006D814E /* Display.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D096C2BD1CC3C021006D814E /* Display.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
@ -841,6 +841,7 @@
|
||||
09EBE2A322B004E900F670AB /* BlackIconIpad@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "BlackIconIpad@2x.png"; sourceTree = "<group>"; };
|
||||
09EBE2A422B004E900F670AB /* BlueFilledIconLargeIpad@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "BlueFilledIconLargeIpad@2x.png"; sourceTree = "<group>"; };
|
||||
09EC0DE222C6339700E7185B /* IntentMessages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentMessages.swift; sourceTree = "<group>"; };
|
||||
09EC5CD922CBBF9600292E42 /* telegram_plane1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "telegram_plane1@2x.png"; sourceTree = "<group>"; };
|
||||
09FDAEE52140477F00BF856F /* MtProtoKitDynamic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MtProtoKitDynamic.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D000CAC021FB6E160011B15D /* NotificationService-HockeyApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NotificationService-HockeyApp.entitlements"; sourceTree = "<group>"; };
|
||||
D000CAC121FB6E160011B15D /* NotificationService-Fork.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NotificationService-Fork.entitlements"; sourceTree = "<group>"; };
|
||||
@ -960,7 +961,6 @@
|
||||
D050F2311E49DEDE00988324 /* start_arrow@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "start_arrow@2x.png"; sourceTree = "<group>"; };
|
||||
D050F2321E49DEDE00988324 /* start_arrow_ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = start_arrow_ipad.png; sourceTree = "<group>"; };
|
||||
D050F2331E49DEDE00988324 /* start_arrow_ipad@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "start_arrow_ipad@2x.png"; sourceTree = "<group>"; };
|
||||
D050F2341E49DEDE00988324 /* telegram_plane1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "telegram_plane1@2x.png"; sourceTree = "<group>"; };
|
||||
D050F2351E49DEDE00988324 /* telegram_sphere@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "telegram_sphere@2x.png"; sourceTree = "<group>"; };
|
||||
D051DB0C215E5E2300F30F92 /* NotificationContent.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationContent.entitlements; sourceTree = "<group>"; };
|
||||
D052974422B0073E004ABAF6 /* WhiteFilledIcon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "WhiteFilledIcon@3x.png"; sourceTree = "<group>"; };
|
||||
@ -2173,6 +2173,7 @@
|
||||
D050F21B1E49DEDE00988324 /* intro */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
09EC5CD922CBBF9600292E42 /* telegram_plane1@2x.png */,
|
||||
D050F21C1E49DEDE00988324 /* fast_arrow@2x.png */,
|
||||
D050F21D1E49DEDE00988324 /* fast_arrow_shadow@2x.png */,
|
||||
D050F21E1E49DEDE00988324 /* fast_body@2x.png */,
|
||||
@ -2197,7 +2198,6 @@
|
||||
D050F2311E49DEDE00988324 /* start_arrow@2x.png */,
|
||||
D050F2321E49DEDE00988324 /* start_arrow_ipad.png */,
|
||||
D050F2331E49DEDE00988324 /* start_arrow_ipad@2x.png */,
|
||||
D050F2341E49DEDE00988324 /* telegram_plane1@2x.png */,
|
||||
D050F2351E49DEDE00988324 /* telegram_sphere@2x.png */,
|
||||
);
|
||||
name = intro;
|
||||
@ -2750,6 +2750,7 @@
|
||||
D0CE6F66213EDA4400BCD44B /* AppIntentVocabulary.plist in Resources */,
|
||||
D08DB0B8213F4D1D00F2ADBF /* powerful_mask@2x.png in Resources */,
|
||||
D08DB0B4213F4D1D00F2ADBF /* knot_down@2x.png in Resources */,
|
||||
09EC5CDA22CBBF9600292E42 /* telegram_plane1@2x.png in Resources */,
|
||||
D08DB0BC213F4D1D00F2ADBF /* start_arrow@2x.png in Resources */,
|
||||
D08DB0B6213F4D1D00F2ADBF /* powerful_infinity@2x.png in Resources */,
|
||||
09EBE2AA22B004EA00F670AB /* BlueIconLargeIpad@2x.png in Resources */,
|
||||
@ -2834,7 +2835,6 @@
|
||||
D021D4D9219CAEDD0064BEBA /* Config-Fork.xcconfig in Resources */,
|
||||
D08DB0AD213F4D1D00F2ADBF /* ic_cam@2x.png in Resources */,
|
||||
090E777622A6945900CD99F5 /* BlackClassicIcon@3x.png in Resources */,
|
||||
D08DB0BF213F4D1D00F2ADBF /* telegram_plane1@2x.png in Resources */,
|
||||
D0E8B8B02044496C00605593 /* voip_ringback.caf in Resources */,
|
||||
09E9600822C23FF200B13673 /* BlackNotificationIcon.png in Resources */,
|
||||
09EBE2A922B004EA00F670AB /* BlackFilledIconLargeIpad@2x.png in Resources */,
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 4.8 KiB |
@ -3,7 +3,7 @@
|
||||
{
|
||||
"size" : "24x24",
|
||||
"idiom" : "watch",
|
||||
"filename" : "NotificationIcon38@2x.png",
|
||||
"filename" : "Watch48@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "notificationCenter",
|
||||
"subtype" : "38mm"
|
||||
@ -11,7 +11,7 @@
|
||||
{
|
||||
"size" : "27.5x27.5",
|
||||
"idiom" : "watch",
|
||||
"filename" : "NotificationIcon42@2x.png",
|
||||
"filename" : "Watch55@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "notificationCenter",
|
||||
"subtype" : "42mm"
|
||||
@ -19,21 +19,21 @@
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "watch",
|
||||
"filename" : "CompanionIcon@2x.png",
|
||||
"filename" : "Simple@58x58.png",
|
||||
"role" : "companionSettings",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "watch",
|
||||
"filename" : "CompanionIcon@3x.png",
|
||||
"filename" : "Simple@87x87.png",
|
||||
"role" : "companionSettings",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon@2x.png",
|
||||
"filename" : "Simple@80x80.png",
|
||||
"scale" : "2x",
|
||||
"role" : "appLauncher",
|
||||
"subtype" : "38mm"
|
||||
@ -41,7 +41,7 @@
|
||||
{
|
||||
"size" : "44x44",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Home88@2x.png",
|
||||
"filename" : "Watch88@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "appLauncher",
|
||||
"subtype" : "40mm"
|
||||
@ -49,7 +49,7 @@
|
||||
{
|
||||
"size" : "50x50",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Home100@2x.png",
|
||||
"filename" : "Watch100@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "appLauncher",
|
||||
"subtype" : "44mm"
|
||||
@ -57,7 +57,7 @@
|
||||
{
|
||||
"size" : "86x86",
|
||||
"idiom" : "watch",
|
||||
"filename" : "ShortLook38@2x.png",
|
||||
"filename" : "Watch172@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "quickLook",
|
||||
"subtype" : "38mm"
|
||||
@ -65,7 +65,7 @@
|
||||
{
|
||||
"size" : "98x98",
|
||||
"idiom" : "watch",
|
||||
"filename" : "ShortLook42@2x.png",
|
||||
"filename" : "Watch196@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "quickLook",
|
||||
"subtype" : "42mm"
|
||||
@ -73,7 +73,7 @@
|
||||
{
|
||||
"size" : "108x108",
|
||||
"idiom" : "watch",
|
||||
"filename" : "ShortLook44@2x.png",
|
||||
"filename" : "Watch216@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "quickLook",
|
||||
"subtype" : "44mm"
|
||||
@ -81,7 +81,7 @@
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "watch-marketing",
|
||||
"filename" : "T-Ipad_1024.png",
|
||||
"filename" : "Simple-iTunesArtwork.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
|
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 159 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Simple@58x58.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Simple@80x80.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Simple@87x87.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 42 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Watch100@2x.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Watch172@2x.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Watch196@2x.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Watch216@2x.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Watch48@2x.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Watch55@2x.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
Watch/App/Assets.xcassets/AppIcon.appiconset/Watch88@2x.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
@ -179,7 +179,7 @@ public final class DeviceAccess {
|
||||
func statusForCellularState(_ state: CTCellularDataRestrictedState) -> AccessType? {
|
||||
switch state {
|
||||
case .restricted:
|
||||
return .allowed
|
||||
return .denied
|
||||
case .notRestricted:
|
||||
return .allowed
|
||||
default:
|
||||
|
@ -1177,10 +1177,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
var bottomItemEdge: CGFloat = 0.0
|
||||
|
||||
for i in 0 ..< self.itemNodes.count {
|
||||
if let index = itemNodes[i].index {
|
||||
if let index = self.itemNodes[i].index {
|
||||
if index == 0 {
|
||||
topItemFound = true
|
||||
topItemEdge = itemNodes[0].apparentFrame.origin.y
|
||||
topItemEdge = self.itemNodes[0].apparentFrame.origin.y
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -1194,9 +1194,9 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
|
||||
var completeHeight = effectiveInsets.top + effectiveInsets.bottom
|
||||
|
||||
if let index = itemNodes[itemNodes.count - 1].index, index == self.items.count - 1 {
|
||||
if let index = self.itemNodes[self.itemNodes.count - 1].index, index == self.items.count - 1 {
|
||||
bottomItemFound = true
|
||||
bottomItemEdge = itemNodes[itemNodes.count - 1].apparentFrame.maxY
|
||||
bottomItemEdge = self.itemNodes[self.itemNodes.count - 1].apparentFrame.maxY
|
||||
}
|
||||
|
||||
topItemEdge -= effectiveInsets.top
|
||||
@ -1223,12 +1223,12 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
let wasIgnoringScrollingEvents = self.ignoreScrollingEvents
|
||||
self.ignoreScrollingEvents = true
|
||||
if topItemFound && bottomItemFound {
|
||||
self.scroller.contentSize = CGSize(width: self.visibleSize.width, height: completeHeight)
|
||||
if self.stackFromBottom {
|
||||
self.lastContentOffset = CGPoint(x: 0.0, y: -topItemEdge)
|
||||
} else {
|
||||
self.lastContentOffset = CGPoint(x: 0.0, y: -topItemEdge)
|
||||
}
|
||||
self.scroller.contentSize = CGSize(width: self.visibleSize.width, height: completeHeight)
|
||||
self.scroller.contentOffset = self.lastContentOffset
|
||||
} else if topItemFound {
|
||||
self.scroller.contentSize = CGSize(width: self.visibleSize.width, height: infiniteScrollSize * 2.0)
|
||||
@ -1346,7 +1346,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
|
||||
private func deleteAndInsertItemsTransaction(deleteIndices: [ListViewDeleteItem], insertIndicesAndItems: [ListViewInsertItem], updateIndicesAndItems: [ListViewUpdateItem], options: ListViewDeleteAndInsertOptions, scrollToItem: ListViewScrollToItem?, additionalScrollDistance: CGFloat, updateSizeAndInsets: ListViewUpdateSizeAndInsets?, stationaryItemRange: (Int, Int)?, updateOpaqueState: Any?, completion: @escaping () -> Void) {
|
||||
if deleteIndices.isEmpty && insertIndicesAndItems.isEmpty && updateIndicesAndItems.isEmpty && scrollToItem == nil {
|
||||
if let updateSizeAndInsets = updateSizeAndInsets , (self.items.count == 0 || (updateSizeAndInsets.size == self.visibleSize && updateSizeAndInsets.insets == self.insets)) {
|
||||
if let updateSizeAndInsets = updateSizeAndInsets, (self.items.count == 0 || (updateSizeAndInsets.size == self.visibleSize && updateSizeAndInsets.insets == self.insets)) {
|
||||
self.visibleSize = updateSizeAndInsets.size
|
||||
self.insets = updateSizeAndInsets.insets
|
||||
self.headerInsets = updateSizeAndInsets.headerInsets ?? self.insets
|
||||
@ -2457,7 +2457,6 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
var headerNodesTransition: (ContainedViewLayoutTransition, Bool, CGFloat) = (.immediate, false, 0.0)
|
||||
|
||||
var deferredUpdateVisible = false
|
||||
var insetTransitionOffset: CGFloat = 0.0
|
||||
|
||||
if let updateSizeAndInsets = updateSizeAndInsets {
|
||||
if self.insets != updateSizeAndInsets.insets || self.headerInsets != updateSizeAndInsets.headerInsets || !self.visibleSize.height.isEqual(to: updateSizeAndInsets.size.height) {
|
||||
@ -2602,8 +2601,6 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
let (snappedTopInset, snapToBoundsOffset) = self.snapToBounds(snapTopItem: scrollToItem != nil, stackFromBottom: self.stackFromBottom, updateSizeAndInsets: updateSizeAndInsets, scrollToItem: scrollToItem)
|
||||
|
||||
if !snappedTopInset.isZero && previousApparentFrames.isEmpty {
|
||||
let offsetFix = snappedTopInset
|
||||
|
||||
for itemNode in self.itemNodes {
|
||||
let position = itemNode.position
|
||||
itemNode.position = CGPoint(x: position.x, y: position.y + snappedTopInset)
|
||||
|
@ -257,7 +257,9 @@ open class ViewControllerPresentationArguments {
|
||||
}
|
||||
}
|
||||
self.navigationBar?.requestContainerLayout = { [weak self] transition in
|
||||
self?.requestLayout(transition: transition)
|
||||
if let strongSelf = self, strongSelf.isNodeLoaded, let validLayout = strongSelf.validLayout {
|
||||
strongSelf.updateNavigationBarLayout(validLayout, transition: transition)
|
||||
}
|
||||
}
|
||||
self.navigationBar?.item = self.navigationItem
|
||||
self.automaticallyAdjustsScrollViewInsets = false
|
||||
@ -275,17 +277,7 @@ open class ViewControllerPresentationArguments {
|
||||
|
||||
}
|
||||
|
||||
open func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = layout
|
||||
|
||||
if !self.isViewLoaded {
|
||||
self.loadView()
|
||||
}
|
||||
transition.updateFrame(node: self.displayNode, frame: CGRect(origin: self.view.frame.origin, size: layout.size))
|
||||
if let _ = layout.statusBarHeight {
|
||||
self.statusBar.frame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: 40.0))
|
||||
}
|
||||
|
||||
private func updateNavigationBarLayout(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
let statusBarHeight: CGFloat = layout.statusBarHeight ?? 0.0
|
||||
let navigationBarHeight: CGFloat = max(20.0, statusBarHeight) + (self.navigationBar?.contentHeight ?? 44.0)
|
||||
let navigationBarOffset: CGFloat
|
||||
@ -318,6 +310,20 @@ open class ViewControllerPresentationArguments {
|
||||
transition.updateFrame(node: navigationBar, frame: navigationBarFrame)
|
||||
navigationBar.setHidden(!self.displayNavigationBar, animated: transition.isAnimated)
|
||||
}
|
||||
}
|
||||
|
||||
open func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = layout
|
||||
|
||||
if !self.isViewLoaded {
|
||||
self.loadView()
|
||||
}
|
||||
transition.updateFrame(node: self.displayNode, frame: CGRect(origin: self.view.frame.origin, size: layout.size))
|
||||
if let _ = layout.statusBarHeight {
|
||||
self.statusBar.frame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: 40.0))
|
||||
}
|
||||
|
||||
self.updateNavigationBarLayout(layout, transition: transition)
|
||||
|
||||
self.presentationContext.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
09EC5CD822CBB86B00292E42 /* telegram_plane1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 09EC5CD722CBB86A00292E42 /* telegram_plane1@2x.png */; };
|
||||
D0A25B8922B5C0CF00AD4DE8 /* LegacyComponents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0A25B8822B5C0CF00AD4DE8 /* LegacyComponents.framework */; };
|
||||
D0A25B8A22B5C0CF00AD4DE8 /* LegacyComponents.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D0A25B8822B5C0CF00AD4DE8 /* LegacyComponents.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D0AE304922B1D77E0058D3BC /* RMIntro.h in Headers */ = {isa = PBXBuildFile; fileRef = D0AE304722B1D77E0058D3BC /* RMIntro.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -56,7 +57,6 @@
|
||||
D0AE30C022B1D8ED0058D3BC /* powerful_infinity_white@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D0AE308422B1D8ED0058D3BC /* powerful_infinity_white@2x.png */; };
|
||||
D0AE30C122B1D8ED0058D3BC /* private_screw@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D0AE308522B1D8ED0058D3BC /* private_screw@2x.png */; };
|
||||
D0AE30C222B1D8ED0058D3BC /* powerful_infinity@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D0AE308622B1D8ED0058D3BC /* powerful_infinity@2x.png */; };
|
||||
D0AE30C322B1D8ED0058D3BC /* telegram_plane@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D0AE308722B1D8ED0058D3BC /* telegram_plane@2x.png */; };
|
||||
D0AE30C422B1D8ED0058D3BC /* ic_smile@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D0AE308822B1D8ED0058D3BC /* ic_smile@2x.png */; };
|
||||
D0AE30C522B1D8ED0058D3BC /* RMGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = D0AE308922B1D8ED0058D3BC /* RMGeometry.m */; };
|
||||
D0AE30C622B1D8ED0058D3BC /* RMIntroViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D0AE308A22B1D8ED0058D3BC /* RMIntroViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -84,6 +84,7 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
09EC5CD722CBB86A00292E42 /* telegram_plane1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "telegram_plane1@2x.png"; sourceTree = "<group>"; };
|
||||
D0A25B8822B5C0CF00AD4DE8 /* LegacyComponents.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LegacyComponents.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0AE304422B1D77E0058D3BC /* RMIntro.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RMIntro.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0AE304722B1D77E0058D3BC /* RMIntro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RMIntro.h; sourceTree = "<group>"; };
|
||||
@ -134,7 +135,6 @@
|
||||
D0AE308422B1D8ED0058D3BC /* powerful_infinity_white@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "powerful_infinity_white@2x.png"; sourceTree = "<group>"; };
|
||||
D0AE308522B1D8ED0058D3BC /* private_screw@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "private_screw@2x.png"; sourceTree = "<group>"; };
|
||||
D0AE308622B1D8ED0058D3BC /* powerful_infinity@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "powerful_infinity@2x.png"; sourceTree = "<group>"; };
|
||||
D0AE308722B1D8ED0058D3BC /* telegram_plane@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "telegram_plane@2x.png"; sourceTree = "<group>"; };
|
||||
D0AE308822B1D8ED0058D3BC /* ic_smile@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ic_smile@2x.png"; sourceTree = "<group>"; };
|
||||
D0AE308922B1D8ED0058D3BC /* RMGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMGeometry.m; sourceTree = "<group>"; };
|
||||
D0AE308A22B1D8ED0058D3BC /* RMIntroViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMIntroViewController.h; sourceTree = "<group>"; };
|
||||
@ -249,6 +249,7 @@
|
||||
D0AE306E22B1D8ED0058D3BC /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
09EC5CD722CBB86A00292E42 /* telegram_plane1@2x.png */,
|
||||
D0AE306F22B1D8ED0058D3BC /* ic_bubble_dot@2x.png */,
|
||||
D0AE307022B1D8ED0058D3BC /* powerful_mask@2x.png */,
|
||||
D0AE307122B1D8ED0058D3BC /* telegram_sphere@2x.png */,
|
||||
@ -273,7 +274,6 @@
|
||||
D0AE308422B1D8ED0058D3BC /* powerful_infinity_white@2x.png */,
|
||||
D0AE308522B1D8ED0058D3BC /* private_screw@2x.png */,
|
||||
D0AE308622B1D8ED0058D3BC /* powerful_infinity@2x.png */,
|
||||
D0AE308722B1D8ED0058D3BC /* telegram_plane@2x.png */,
|
||||
D0AE308822B1D8ED0058D3BC /* ic_smile@2x.png */,
|
||||
);
|
||||
path = Resources;
|
||||
@ -402,6 +402,7 @@
|
||||
D0AE30B522B1D8ED0058D3BC /* start_arrow_ipad@2x.png in Resources */,
|
||||
D0AE30BD22B1D8ED0058D3BC /* fast_spiral@2x.png in Resources */,
|
||||
D0AE30CD22B1D8ED0058D3BC /* .gitignore in Resources */,
|
||||
09EC5CD822CBB86B00292E42 /* telegram_plane1@2x.png in Resources */,
|
||||
D0AE30B822B1D8ED0058D3BC /* fast_arrow@2x.png in Resources */,
|
||||
D0AE30AC22B1D8ED0058D3BC /* powerful_mask@2x.png in Resources */,
|
||||
D0AE30B322B1D8ED0058D3BC /* fast_arrow_shadow@2x.png in Resources */,
|
||||
@ -414,7 +415,6 @@
|
||||
D0AE30B222B1D8ED0058D3BC /* start_arrow_ipad.png in Resources */,
|
||||
D0AE30C422B1D8ED0058D3BC /* ic_smile@2x.png in Resources */,
|
||||
D0AE30B922B1D8ED0058D3BC /* ic_pencil@2x.png in Resources */,
|
||||
D0AE30C322B1D8ED0058D3BC /* telegram_plane@2x.png in Resources */,
|
||||
D0AE30B422B1D8ED0058D3BC /* ic_cam@2x.png in Resources */,
|
||||
D0AE30B622B1D8ED0058D3BC /* fast_body@2x.png in Resources */,
|
||||
D0AE30BC22B1D8ED0058D3BC /* ic_pin@2x.png in Resources */,
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 8.1 KiB |
@ -1,6 +1,7 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import CallKit
|
||||
import Intents
|
||||
import AVFoundation
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
@ -49,6 +50,7 @@ public final class CallKitIntegration {
|
||||
func startCall(account: Account, peerId: PeerId, displayTitle: String) {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
(sharedProviderDelegate as? CallKitProviderDelegate)?.startCall(account: account, peerId: peerId, displayTitle: displayTitle)
|
||||
self.donateIntent(peerId: peerId, displayTitle: displayTitle)
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,6 +77,20 @@ public final class CallKitIntegration {
|
||||
(sharedProviderDelegate as? CallKitProviderDelegate)?.reportOutgoingCallConnected(uuid: uuid, at: date)
|
||||
}
|
||||
}
|
||||
|
||||
private func donateIntent(peerId: PeerId, displayTitle: String) {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
let handle = INPersonHandle(value: "tg\(peerId.id)", type: .unknown)
|
||||
let contact = INPerson(personHandle: handle, nameComponents: nil, displayName: displayTitle, image: nil, contactIdentifier: nil, customIdentifier: "tg\(peerId.id)")
|
||||
|
||||
let intent = INStartAudioCallIntent(contacts: [contact])
|
||||
|
||||
let interaction = INInteraction(intent: intent, response: nil)
|
||||
interaction.direction = .outgoing
|
||||
interaction.donate { _ in
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
|
||||
|
@ -68,8 +68,6 @@ public final class PresentationCallManager {
|
||||
private var callSettings: VoiceCallSettings?
|
||||
private var callSettingsDisposable: Disposable?
|
||||
|
||||
public var callRequested: ((_ accountPeerId: PeerId, _ peerId: PeerId) -> Void)?
|
||||
|
||||
public static var voipMaxLayer: Int32 {
|
||||
return OngoingCallContext.maxLayer
|
||||
}
|
||||
@ -316,8 +314,6 @@ public final class PresentationCallManager {
|
||||
} else {
|
||||
begin()
|
||||
}
|
||||
|
||||
self.callRequested?(account.peerId, peerId)
|
||||
} else {
|
||||
let begin: () -> Void = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
@ -333,7 +329,6 @@ public final class PresentationCallManager {
|
||||
} else {
|
||||
begin()
|
||||
}
|
||||
self.callRequested?(account.peerId, peerId)
|
||||
}
|
||||
return .requested
|
||||
}
|
||||
|
@ -107,6 +107,7 @@ public func searchStickers(account: Account, query: String, scope: SearchSticker
|
||||
|
||||
let currentItems = Set<MediaId>(result.map { $0.file.fileId })
|
||||
var recentItems: [TelegramMediaFile] = []
|
||||
var recentAnimatedItems: [TelegramMediaFile] = []
|
||||
var recentItemsIds = Set<MediaId>()
|
||||
var matchingRecentItemsIds = Set<MediaId>()
|
||||
|
||||
@ -118,14 +119,19 @@ public func searchStickers(account: Account, query: String, scope: SearchSticker
|
||||
matchingRecentItemsIds.insert(file.fileId)
|
||||
}
|
||||
recentItemsIds.insert(file.fileId)
|
||||
recentItems.append(file)
|
||||
if file.isAnimatedSticker {
|
||||
recentAnimatedItems.append(file)
|
||||
} else {
|
||||
recentItems.append(file)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var installed: [FoundStickerItem] = []
|
||||
var installedItems: [FoundStickerItem] = []
|
||||
var installedAnimatedItems: [FoundStickerItem] = []
|
||||
for item in transaction.searchItemCollection(namespace: Namespaces.ItemCollection.CloudStickerPacks, query: .exact(ValueBoxKey(query))) {
|
||||
if let item = item as? StickerPackItem {
|
||||
if !currentItems.contains(item.file.fileId) {
|
||||
@ -138,7 +144,11 @@ public func searchStickers(account: Account, query: String, scope: SearchSticker
|
||||
}
|
||||
}
|
||||
if !recentItemsIds.contains(item.file.fileId) {
|
||||
installed.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations))
|
||||
if item.file.isAnimatedSticker {
|
||||
installedAnimatedItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations))
|
||||
} else {
|
||||
installedItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations))
|
||||
}
|
||||
} else {
|
||||
matchingRecentItemsIds.insert(item.file.fileId)
|
||||
}
|
||||
@ -146,13 +156,20 @@ public func searchStickers(account: Account, query: String, scope: SearchSticker
|
||||
}
|
||||
}
|
||||
|
||||
for file in recentAnimatedItems {
|
||||
if matchingRecentItemsIds.contains(file.fileId) {
|
||||
result.append(FoundStickerItem(file: file, stringRepresentations: [query]))
|
||||
}
|
||||
}
|
||||
|
||||
for file in recentItems {
|
||||
if matchingRecentItemsIds.contains(file.fileId) {
|
||||
result.append(FoundStickerItem(file: file, stringRepresentations: [query]))
|
||||
}
|
||||
}
|
||||
|
||||
result.append(contentsOf: installed)
|
||||
result.append(contentsOf: installedAnimatedItems)
|
||||
result.append(contentsOf: installedItems)
|
||||
}
|
||||
|
||||
let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerQueryResults, key: CachedStickerQueryResult.cacheKey(query))) as? CachedStickerQueryResult
|
||||
|
@ -837,21 +837,6 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
|
||||
}
|
||||
}
|
||||
|
||||
/*self.chatListDisplayNode.chatListNode.contentOffsetChanged = { [weak self] offset in
|
||||
if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode {
|
||||
var progress: CGFloat = 0.0
|
||||
switch offset {
|
||||
case let .known(offset):
|
||||
progress = max(0.0, (searchContentNode.nominalHeight - max(0.0, offset - 76.0))) / searchContentNode.nominalHeight
|
||||
case .none:
|
||||
progress = 1.0
|
||||
default:
|
||||
break
|
||||
}
|
||||
searchContentNode.updateExpansionProgress(progress)
|
||||
}
|
||||
}*/
|
||||
|
||||
self.chatListDisplayNode.chatListNode.contentScrollingEnded = { [weak self] listView in
|
||||
if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode {
|
||||
return fixListNodeScrolling(listView, searchNode: searchContentNode)
|
||||
|
@ -67,7 +67,7 @@ private let boundingImageSize = CGSize(width: 28.0, height: 28.0)
|
||||
private let highlightSize = CGSize(width: 35.0, height: 35.0)
|
||||
private let verticalOffset: CGFloat = 3.0
|
||||
|
||||
private enum StickerPackThumbnailItem: Equatable {
|
||||
enum StickerPackThumbnailItem: Equatable {
|
||||
case still(TelegramMediaImageRepresentation)
|
||||
case animated(MediaResource)
|
||||
|
||||
|
@ -80,9 +80,11 @@ private let iconTextBackgroundImage = generateStretchableFilledCircleImage(radiu
|
||||
final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode {
|
||||
private let imageNodeBackground: ASDisplayNode
|
||||
private let imageNode: TransformImageNode
|
||||
private var animationNode: AnimatedStickerNode?
|
||||
private var videoLayer: (SoftwareVideoThumbnailLayer, SoftwareVideoLayerFrameManager, SampleBufferLayer)?
|
||||
private var currentImageResource: TelegramMediaResource?
|
||||
private var currentVideoFile: TelegramMediaFile?
|
||||
private var currentAnimatedStickerFile: TelegramMediaFile?
|
||||
private var resourceStatus: MediaResourceStatus?
|
||||
private(set) var item: HorizontalListContextResultsChatInputPanelItem?
|
||||
private var statusDisposable = MetaDisposable()
|
||||
@ -188,6 +190,7 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
|
||||
let imageLayout = self.imageNode.asyncLayout()
|
||||
let currentImageResource = self.currentImageResource
|
||||
let currentVideoFile = self.currentVideoFile
|
||||
let currentAnimatedStickerFile = self.currentAnimatedStickerFile
|
||||
|
||||
return { [weak self] item, params, mergedTop, mergedBottom in
|
||||
let height = params.width
|
||||
@ -199,6 +202,7 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
|
||||
|
||||
var imageResource: TelegramMediaResource?
|
||||
var stickerFile: TelegramMediaFile?
|
||||
var animatedStickerFile: TelegramMediaFile?
|
||||
var videoFile: TelegramMediaFile?
|
||||
var imageDimensions: CGSize?
|
||||
switch item.result {
|
||||
@ -231,7 +235,10 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
|
||||
} else if let largestRepresentation = largestImageRepresentation(file.previewRepresentations) {
|
||||
imageDimensions = largestRepresentation.dimensions
|
||||
}
|
||||
if file.isSticker {
|
||||
if file.isAnimatedSticker {
|
||||
animatedStickerFile = file
|
||||
imageResource = smallestImageRepresentation(file.previewRepresentations)?.resource
|
||||
} else if file.isSticker {
|
||||
stickerFile = file
|
||||
imageResource = file.resource
|
||||
} else {
|
||||
@ -286,6 +293,15 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
|
||||
updatedVideoFile = true
|
||||
}
|
||||
|
||||
var updatedAnimatedStickerFile = false
|
||||
if let currentAnimatedStickerFile = currentAnimatedStickerFile, let animatedStickerFile = animatedStickerFile {
|
||||
if !currentAnimatedStickerFile.isEqual(to: animatedStickerFile) {
|
||||
updatedAnimatedStickerFile = true
|
||||
}
|
||||
} else if (currentAnimatedStickerFile != nil) != (animatedStickerFile != nil) {
|
||||
updatedAnimatedStickerFile = true
|
||||
}
|
||||
|
||||
if updatedImageResource {
|
||||
if let imageResource = imageResource {
|
||||
if let stickerFile = stickerFile {
|
||||
@ -300,7 +316,6 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: CGSize(width: height, height: croppedImageDimensions.width + sideInset), insets: UIEdgeInsets())
|
||||
|
||||
return (nodeLayout, { _ in
|
||||
@ -348,6 +363,30 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
|
||||
}
|
||||
}
|
||||
|
||||
if updatedAnimatedStickerFile {
|
||||
if let animationNode = strongSelf.animationNode {
|
||||
strongSelf.animationNode = nil
|
||||
animationNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
if let animatedStickerFile = animatedStickerFile {
|
||||
let animationNode: AnimatedStickerNode
|
||||
if let currentAnimationNode = strongSelf.animationNode {
|
||||
animationNode = currentAnimationNode
|
||||
} else {
|
||||
animationNode = AnimatedStickerNode()
|
||||
animationNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||
animationNode.visibility = true
|
||||
strongSelf.addSubnode(animationNode)
|
||||
strongSelf.animationNode = animationNode
|
||||
}
|
||||
animationNode.started = { [weak self] in
|
||||
self?.imageNode.alpha = 0.0
|
||||
}
|
||||
animationNode.setup(account: item.account, resource: animatedStickerFile.resource, width: 140, height: 140, mode: .cached)
|
||||
}
|
||||
}
|
||||
|
||||
let progressSize = CGSize(width: 24.0, height: 24.0)
|
||||
let progressFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((nodeLayout.contentSize.width - progressSize.width) / 2.0), y: floorToScreenPixels((nodeLayout.contentSize.height - progressSize.height) / 2.0)), size: progressSize)
|
||||
|
||||
@ -363,20 +402,18 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
|
||||
if let strongSelf = strongSelf {
|
||||
strongSelf.resourceStatus = status
|
||||
|
||||
|
||||
let state: RadialStatusNodeState
|
||||
let statusForegroundColor: UIColor = .white
|
||||
|
||||
switch status {
|
||||
case let .Fetching(_, progress):
|
||||
state = .progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(max(progress, 0.2)), cancelEnabled: false)
|
||||
case .Remote:
|
||||
state = .download(statusForegroundColor)
|
||||
case .Local:
|
||||
state = .none
|
||||
case let .Fetching(_, progress):
|
||||
state = .progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(max(progress, 0.2)), cancelEnabled: false)
|
||||
case .Remote:
|
||||
state = .download(statusForegroundColor)
|
||||
case .Local:
|
||||
state = .none
|
||||
}
|
||||
|
||||
|
||||
strongSelf.statusNode.transitionToState(state, completion: { })
|
||||
}
|
||||
}
|
||||
@ -391,6 +428,12 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
|
||||
layer.layer.bounds = CGRect(origin: CGPoint(), size: CGSize(width: croppedImageDimensions.width, height: croppedImageDimensions.height))
|
||||
layer.layer.position = CGPoint(x: height / 2.0, y: (nodeLayout.contentSize.height - sideInset) / 2.0 + sideInset)
|
||||
}
|
||||
|
||||
if let animationNode = strongSelf.animationNode {
|
||||
animationNode.bounds = CGRect(origin: CGPoint(), size: CGSize(width: croppedImageDimensions.width, height: croppedImageDimensions.height))
|
||||
animationNode.position = CGPoint(x: height / 2.0, y: (nodeLayout.contentSize.height - sideInset) / 2.0 + sideInset)
|
||||
animationNode.updateLayout(size: croppedImageDimensions)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -302,9 +302,6 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode {
|
||||
self.backgroundNode.image = backgroundCenterImage(theme)
|
||||
self.backgroundLeftNode.image = backgroundLeftImage(theme)
|
||||
self.backgroundRightNode.image = backgroundLeftImage(theme)
|
||||
// if let currentEntries = self.currentEntries {
|
||||
// self.updateToEntries(entries: currentEntries, forceUpdate: true)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,14 +191,14 @@ private func inviteContactsEntries(accountPeer: Peer?, sortedContacts: [(DeviceC
|
||||
return entries
|
||||
}
|
||||
|
||||
private func preparedInviteContactsTransition(account: Account, from fromEntries: [InviteContactsEntry], to toEntries: [InviteContactsEntry], sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)]?, interaction: InviteContactsInteraction, firstTime: Bool, isLoading: Bool, animated: Bool) -> InviteContactsTransition {
|
||||
private func preparedInviteContactsTransition(account: Account, from fromEntries: [InviteContactsEntry], to toEntries: [InviteContactsEntry], sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)]?, interaction: InviteContactsInteraction, isLoading: Bool, firstTime: Bool, crossfade: Bool) -> InviteContactsTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction), directionHint: nil) }
|
||||
|
||||
return InviteContactsTransition(deletions: deletions, insertions: insertions, updates: updates, sortedContacts: sortedContacts, firstTime: firstTime, isLoading: isLoading, animated: animated)
|
||||
return InviteContactsTransition(deletions: deletions, insertions: insertions, updates: updates, sortedContacts: sortedContacts, isLoading: isLoading, firstTime: firstTime, crossfade: crossfade)
|
||||
}
|
||||
|
||||
private struct InviteContactsTransition {
|
||||
@ -206,9 +206,9 @@ private struct InviteContactsTransition {
|
||||
let insertions: [ListViewInsertItem]
|
||||
let updates: [ListViewUpdateItem]
|
||||
let sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)]?
|
||||
let firstTime: Bool
|
||||
let isLoading: Bool
|
||||
let animated: Bool
|
||||
let firstTime: Bool
|
||||
let crossfade: Bool
|
||||
}
|
||||
|
||||
final class InviteContactsControllerNode: ASDisplayNode {
|
||||
@ -229,7 +229,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
var requestShareTelegram: (() -> Void)?
|
||||
var requestShare: (([(DeviceContactBasicData, Int32)]) -> Void)?
|
||||
|
||||
let currentSortedContacts = Atomic<[(DeviceContactStableId, DeviceContactBasicData, Int32)]>(value: [])
|
||||
let currentSortedContacts = Atomic<[(DeviceContactStableId, DeviceContactBasicData, Int32)]?>(value: nil)
|
||||
|
||||
var selectionState = InviteContactsGroupSelectionState() {
|
||||
didSet {
|
||||
@ -290,6 +290,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
})
|
||||
|
||||
self.backgroundColor = self.presentationData.theme.chatList.backgroundColor
|
||||
self.listNode.backgroundColor = self.presentationData.theme.chatList.backgroundColor
|
||||
|
||||
self.addSubnode(self.listNode)
|
||||
self.addSubnode(self.countPanelNode)
|
||||
@ -310,7 +311,6 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
})
|
||||
|
||||
let account = self.context.account
|
||||
var firstTime: Int32 = 1
|
||||
let selectionStateSignal = self.selectionStatePromise.get()
|
||||
let transition: Signal<InviteContactsTransition, NoError>
|
||||
let themeAndStringsPromise = self.themeAndStringsPromise
|
||||
@ -387,36 +387,24 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|> beforeNext { sortedContacts in
|
||||
if let sortedContacts = sortedContacts {
|
||||
let _ = currentSortedContacts.swap(sortedContacts)
|
||||
}
|
||||
}
|
||||
|
||||
let processingQueue = Queue()
|
||||
transition = (combineLatest(.single(nil) |> then(sortedContacts), selectionStateSignal, themeAndStringsPromise.get())
|
||||
|> mapToQueue { sortedContacts, selectionState, themeAndStrings -> Signal<InviteContactsTransition, NoError> in
|
||||
transition = (combineLatest(.single(nil) |> then(sortedContacts), selectionStateSignal, themeAndStringsPromise.get(), .single(true) |> delay(0.2, queue: Queue.mainQueue()))
|
||||
|> mapToQueue { sortedContacts, selectionState, themeAndStrings, ready -> Signal<InviteContactsTransition, NoError> in
|
||||
guard sortedContacts != nil || ready else {
|
||||
return .never()
|
||||
}
|
||||
|
||||
let signal = deferred { () -> Signal<InviteContactsTransition, NoError> in
|
||||
let entries = inviteContactsEntries(accountPeer: nil, sortedContacts: sortedContacts, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, nameSortOrder: themeAndStrings.2, nameDisplayOrder: themeAndStrings.3, interaction: interaction)
|
||||
let previous = previousEntries.swap(entries)
|
||||
let animated: Bool
|
||||
if let previous = previous {
|
||||
animated = (entries.count - previous.count) < 20
|
||||
} else {
|
||||
animated = false
|
||||
}
|
||||
return .single(preparedInviteContactsTransition(account: context.account, from: previous ?? [], to: entries, sortedContacts: sortedContacts, interaction: interaction, firstTime: previous == nil, isLoading: false, animated: animated))
|
||||
let previousContacts = currentSortedContacts.with { $0 }
|
||||
let crossfade = previous != nil && previousContacts == nil
|
||||
|
||||
return .single(preparedInviteContactsTransition(account: context.account, from: previous ?? [], to: entries, sortedContacts: sortedContacts, interaction: interaction, isLoading: sortedContacts == nil, firstTime: previous == nil, crossfade: crossfade))
|
||||
}
|
||||
return signal
|
||||
|> runOn(processingQueue)
|
||||
|
||||
// if OSAtomicCompareAndSwap32(1, 0, &firstTime) {
|
||||
// return signal
|
||||
// |> runOn(Queue.mainQueue())
|
||||
// } else {
|
||||
// return signal
|
||||
// |> runOn(processingQueue)
|
||||
// }
|
||||
})
|
||||
|> deliverOnMainQueue
|
||||
|
||||
@ -424,12 +412,10 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
self?.enqueueTransition(transition)
|
||||
})
|
||||
|
||||
self.enqueueTransition(InviteContactsTransition(deletions: [], insertions: [], updates: [], sortedContacts: [], firstTime: true, isLoading: true, animated: false))
|
||||
|
||||
shareImpl = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
var result: [(DeviceContactBasicData, Int32)] = []
|
||||
for contact in (strongSelf.currentSortedContacts.with { $0 }) {
|
||||
for contact in (strongSelf.currentSortedContacts.with { $0 } ?? []) {
|
||||
if strongSelf.selectionState.selectedContactIndices[contact.0] != nil {
|
||||
result.append((contact.1, contact.2))
|
||||
}
|
||||
@ -448,6 +434,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
|
||||
private func updateThemeAndStrings() {
|
||||
self.backgroundColor = self.presentationData.theme.chatList.backgroundColor
|
||||
self.listNode.backgroundColor = self.presentationData.theme.chatList.backgroundColor
|
||||
self.searchDisplayController?.updatePresentationData(self.presentationData)
|
||||
}
|
||||
|
||||
@ -571,8 +558,8 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
if transition.firstTime {
|
||||
options.insert(.Synchronous)
|
||||
options.insert(.LowLatency)
|
||||
} else if transition.animated {
|
||||
options.insert(.AnimateInsertion)
|
||||
} else if transition.crossfade {
|
||||
options.insert(.AnimateCrossfade)
|
||||
}
|
||||
self.listNode.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, updateOpaqueState: nil, completion: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
@ -582,10 +569,16 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
let activityIndicator = ActivityIndicator(type: .custom(strongSelf.presentationData.theme.list.itemAccentColor, 22.0, 1.0, false))
|
||||
strongSelf.activityIndicator = activityIndicator
|
||||
strongSelf.insertSubnode(activityIndicator, aboveSubnode: strongSelf.listNode)
|
||||
|
||||
if let (layout, navigationHeight, actualNavigationBarHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationHeight, actualNavigationBarHeight: actualNavigationBarHeight, transition: .immediate)
|
||||
}
|
||||
} else if !transition.isLoading, let activityIndicator = strongSelf.activityIndicator {
|
||||
strongSelf.activityIndicator = nil
|
||||
activityIndicator.removeFromSupernode()
|
||||
}
|
||||
|
||||
let _ = strongSelf.currentSortedContacts.swap(transition.sortedContacts)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -593,7 +586,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
func selectAll() {
|
||||
let ids = self.currentSortedContacts.with { $0 }.map { $0.0 }
|
||||
let ids = self.currentSortedContacts.with { $0 }?.map { $0.0 } ?? []
|
||||
var allSelected = true
|
||||
for id in ids {
|
||||
if self.selectionState.selectedContactIndices[id] == nil {
|
||||
|
@ -121,6 +121,8 @@ private let titleFont = Font.bold(15.0)
|
||||
private let statusFont = Font.regular(14.0)
|
||||
|
||||
class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
private var currentThumbnailItem: StickerPackThumbnailItem?
|
||||
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
private let bottomStripeNode: ASDisplayNode
|
||||
@ -128,6 +130,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
private var disabledOverlayNode: ASDisplayNode?
|
||||
|
||||
fileprivate let imageNode: TransformImageNode
|
||||
private var animationNode: AnimatedStickerNode?
|
||||
private let unreadNode: ASImageNode
|
||||
private let titleNode: TextNode
|
||||
private let statusNode: TextNode
|
||||
@ -153,6 +156,17 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
override var visibility: ListViewItemNodeVisibility {
|
||||
didSet {
|
||||
let wasVisible = oldValue != .none
|
||||
let isVisible = self.visibility != .none
|
||||
|
||||
if wasVisible != isVisible {
|
||||
self.animationNode?.visibility = isVisible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
@ -230,13 +244,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
let editableControlLayout = ItemListEditableControlNode.asyncLayout(self.editableControlNode)
|
||||
let reorderControlLayout = ItemListEditableReorderControlNode.asyncLayout(self.reorderControlNode)
|
||||
|
||||
var previousThumbnailItem: TelegramMediaImageRepresentation?
|
||||
if let thumbnail = self.layoutParams?.0.packInfo.thumbnail {
|
||||
previousThumbnailItem = thumbnail
|
||||
} else if let item = self.layoutParams?.0.topItem, let dimensions = item.file.dimensions, let resource = chatMessageStickerResource(file: item.file, small: true) as? TelegramMediaResource {
|
||||
previousThumbnailItem = TelegramMediaImageRepresentation(dimensions: dimensions, resource: resource)
|
||||
}
|
||||
|
||||
var previousThumbnailItem = self.currentThumbnailItem
|
||||
var currentDisabledOverlayNode = self.disabledOverlayNode
|
||||
|
||||
let currentItem = self.layoutParams?.0
|
||||
@ -324,31 +332,47 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
currentDisabledOverlayNode = nil
|
||||
}
|
||||
|
||||
var thumbnailItem: TelegramMediaImageRepresentation?
|
||||
var thumbnailItem: StickerPackThumbnailItem?
|
||||
var resourceReference: MediaResourceReference?
|
||||
if let thumbnail = item.packInfo.thumbnail {
|
||||
thumbnailItem = thumbnail
|
||||
resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: item.packInfo.id.id, accessHash: item.packInfo.accessHash), resource: thumbnail.resource)
|
||||
} else if let item = item.topItem, let dimensions = item.file.dimensions, let resource = chatMessageStickerResource(file: item.file, small: true) as? TelegramMediaResource {
|
||||
thumbnailItem = TelegramMediaImageRepresentation(dimensions: dimensions, resource: resource)
|
||||
resourceReference = MediaResourceReference.media(media: .standalone(media: item.file), resource: resource)
|
||||
}
|
||||
|
||||
let fileUpdated = thumbnailItem != previousThumbnailItem
|
||||
|
||||
var imageApply: (() -> Void)?
|
||||
var imageSize: CGSize = CGSize(width: 34.0, height: 34.0)
|
||||
if let thumbnailItem = thumbnailItem {
|
||||
let imageBoundingSize = CGSize(width: 34.0, height: 34.0)
|
||||
imageSize = thumbnailItem.dimensions.aspectFitted(imageBoundingSize)
|
||||
imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))
|
||||
if item.packInfo.flags.contains(.isAnimated) {
|
||||
thumbnailItem = .animated(thumbnail.resource)
|
||||
resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: item.packInfo.id.id, accessHash: item.packInfo.accessHash), resource: thumbnail.resource)
|
||||
} else {
|
||||
thumbnailItem = .still(thumbnail)
|
||||
resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: item.packInfo.id.id, accessHash: item.packInfo.accessHash), resource: thumbnail.resource)
|
||||
}
|
||||
} else if let item = item.topItem {
|
||||
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)
|
||||
var imageApply: (() -> Void)?
|
||||
let fileUpdated = thumbnailItem != previousThumbnailItem
|
||||
|
||||
var imageSize: CGSize?
|
||||
|
||||
if fileUpdated {
|
||||
if let thumbnailItem = thumbnailItem {
|
||||
updatedImageSignal = chatMessageStickerPackThumbnail(postbox: item.account.postbox, representation: thumbnailItem)
|
||||
switch thumbnailItem {
|
||||
case let .still(representation):
|
||||
let stillImageSize = representation.dimensions.aspectFitted(imageBoundingSize)
|
||||
imageSize = stillImageSize
|
||||
|
||||
imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: stillImageSize, boundingSize: stillImageSize, intrinsicInsets: UIEdgeInsets()))
|
||||
updatedImageSignal = chatMessageStickerPackThumbnail(postbox: item.account.postbox, representation: representation)
|
||||
case .animated:
|
||||
imageSize = imageBoundingSize
|
||||
}
|
||||
if let resourceReference = resourceReference {
|
||||
updatedFetchSignal = fetchedMediaResource(postbox: item.account.postbox, reference: resourceReference)
|
||||
}
|
||||
@ -361,6 +385,10 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
return (layout, { [weak self] animated in
|
||||
if let strongSelf = self {
|
||||
strongSelf.layoutParams = (item, params, neighbors)
|
||||
|
||||
if fileUpdated {
|
||||
strongSelf.currentThumbnailItem = thumbnailItem
|
||||
}
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
@ -516,7 +544,27 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateFrame(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: 32.0), size: statusLayout.size))
|
||||
|
||||
let boundingSize = CGSize(width: 34.0, height: 34.0)
|
||||
transition.updateFrame(node: strongSelf.imageNode, frame: CGRect(origin: CGPoint(x: params.leftInset + revealOffset + editingOffset + 15.0 + floor((boundingSize.width - imageSize.width) / 2.0), y: 11.0 + floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize))
|
||||
if let thumbnailItem = thumbnailItem, let imageSize = imageSize {
|
||||
let imageFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset + editingOffset + 15.0 + floor((boundingSize.width - imageSize.width) / 2.0), y: 11.0 + floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize)
|
||||
switch thumbnailItem {
|
||||
case .still:
|
||||
transition.updateFrame(node: strongSelf.imageNode, frame: imageFrame)
|
||||
case let .animated(resource):
|
||||
let animationNode: AnimatedStickerNode
|
||||
if let current = strongSelf.animationNode {
|
||||
animationNode = current
|
||||
} else {
|
||||
animationNode = AnimatedStickerNode()
|
||||
strongSelf.animationNode = animationNode
|
||||
strongSelf.addSubnode(animationNode)
|
||||
animationNode.setup(account: item.account, resource: resource, width: 80, height: 80, mode: .cached)
|
||||
animationNode.visibility = strongSelf.visibility != .none
|
||||
}
|
||||
if let animationNode = strongSelf.animationNode {
|
||||
transition.updateFrame(node: animationNode, frame: imageFrame)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let updatedImageSignal = updatedImageSignal {
|
||||
strongSelf.imageNode.setSignal(updatedImageSignal)
|
||||
|
@ -66,7 +66,7 @@ private let titleFont = Font.bold(16.0)
|
||||
private let statusFont = Font.regular(15.0)
|
||||
private let buttonFont = Font.medium(13.0)
|
||||
|
||||
private final class TrendingTopItemNode: ASDisplayNode {
|
||||
final class TrendingTopItemNode: ASDisplayNode {
|
||||
private let imageNode: TransformImageNode
|
||||
private var animationNode: AnimatedStickerNode?
|
||||
public private(set) var file: TelegramMediaFile? = nil
|
||||
|
@ -78,30 +78,6 @@ private let titleFont = Font.bold(16.0)
|
||||
private let statusFont = Font.regular(15.0)
|
||||
private let buttonFont = Font.medium(13.0)
|
||||
|
||||
private final class TrendingTopItemNode: TransformImageNode {
|
||||
var file: TelegramMediaFile? = nil
|
||||
let loadDisposable = MetaDisposable()
|
||||
|
||||
var currentIsPreviewing = false
|
||||
|
||||
func updatePreviewing(animated: Bool, isPreviewing: Bool) {
|
||||
if self.currentIsPreviewing != isPreviewing {
|
||||
self.currentIsPreviewing = isPreviewing
|
||||
|
||||
if isPreviewing {
|
||||
if animated {
|
||||
self.layer.animateSpring(from: 1.0 as NSNumber, to: 0.8 as NSNumber, keyPath: "transform.scale", duration: 0.4, removeOnCompletion: false)
|
||||
}
|
||||
} else {
|
||||
self.layer.removeAnimation(forKey: "transform.scale")
|
||||
if animated {
|
||||
self.layer.animateSpring(from: 0.8 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class StickerPaneSearchGlobalItemNode: GridItemNode {
|
||||
private let titleNode: TextNode
|
||||
private let descriptionNode: TextNode
|
||||
@ -115,6 +91,16 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
|
||||
private var appliedItem: StickerPaneSearchGlobalItem?
|
||||
private let preloadDisposable = MetaDisposable()
|
||||
|
||||
override var isVisibleInGrid: Bool {
|
||||
didSet {
|
||||
if oldValue != self.isVisibleInGrid {
|
||||
for node in self.itemNodes {
|
||||
node.visibility = self.isVisibleInGrid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override init() {
|
||||
self.titleNode = TextNode()
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
@ -270,9 +256,14 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
|
||||
strongSelf.unreadNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + 2.0, y: titleFrame.minY + 7.0), size: image.size)
|
||||
}
|
||||
|
||||
var offset: CGFloat = params.leftInset + leftInset
|
||||
let itemSize = CGSize(width: 68.0, height: 68.0)
|
||||
|
||||
let sideInset: CGFloat = 2.0
|
||||
let availableWidth = params.width - params.leftInset - params.rightInset - sideInset * 2.0
|
||||
var itemSide: CGFloat = floor(availableWidth / 5.0)
|
||||
itemSide = min(itemSide, 75.0)
|
||||
let itemSize = CGSize(width: itemSide, height: itemSide)
|
||||
var offset = sideInset
|
||||
let itemSpacing = (max(0, availableWidth - 5.0 * itemSide - sideInset * 2.0)) / 4.0
|
||||
|
||||
for i in 0 ..< topItems.count {
|
||||
let file = topItems[i].file
|
||||
let node: TrendingTopItemNode
|
||||
@ -280,20 +271,17 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
|
||||
node = strongSelf.itemNodes[i]
|
||||
} else {
|
||||
node = TrendingTopItemNode()
|
||||
node.contentAnimations = [.subsequentUpdates]
|
||||
node.visibility = strongSelf.isVisibleInGrid
|
||||
strongSelf.itemNodes.append(node)
|
||||
strongSelf.addSubnode(node)
|
||||
}
|
||||
if file.fileId != node.file?.fileId {
|
||||
node.file = file
|
||||
node.setSignal(chatMessageSticker(account: item.account, file: file, small: true))
|
||||
node.loadDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.account, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: true)).start())
|
||||
node.setup(account: item.account, item: topItems[i], itemSize: itemSize, synchronousLoads: false)
|
||||
}
|
||||
if let dimensions = file.dimensions {
|
||||
let imageSize = dimensions.aspectFitted(itemSize)
|
||||
node.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))()
|
||||
node.frame = CGRect(origin: CGPoint(x: offset, y: 48.0 + topOffset), size: imageSize)
|
||||
offset += imageSize.width + 4.0
|
||||
offset += itemSize.width + itemSpacing
|
||||
}
|
||||
}
|
||||
|
||||
|