This commit is contained in:
Ilya Laktyushin 2019-01-15 00:55:31 +04:00
parent c9aa4a85da
commit 10d5bf3d10
26 changed files with 430 additions and 249 deletions

View File

@ -89,6 +89,8 @@
09C9EA3821A044B500E90146 /* StringForDuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09C9EA3721A044B500E90146 /* StringForDuration.swift */; }; 09C9EA3821A044B500E90146 /* StringForDuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09C9EA3721A044B500E90146 /* StringForDuration.swift */; };
09D304152173C0E900C00567 /* WatchManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09D304142173C0E900C00567 /* WatchManager.swift */; }; 09D304152173C0E900C00567 /* WatchManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09D304142173C0E900C00567 /* WatchManager.swift */; };
09D304182173C15700C00567 /* WatchSettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09D304172173C15700C00567 /* WatchSettingsController.swift */; }; 09D304182173C15700C00567 /* WatchSettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09D304172173C15700C00567 /* WatchSettingsController.swift */; };
09DD5D5021ECC3C400D7007A /* SuppressContactsWarning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD5D4F21ECC3C400D7007A /* SuppressContactsWarning.swift */; };
09DD5D5221ED175300D7007A /* WallpaperColorPickerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD5D5121ED175300D7007A /* WallpaperColorPickerNode.swift */; };
09DD88E921BAF65E000766BC /* ItemListAddressItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88E821BAF65E000766BC /* ItemListAddressItem.swift */; }; 09DD88E921BAF65E000766BC /* ItemListAddressItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88E821BAF65E000766BC /* ItemListAddressItem.swift */; };
09DD88ED21BDC8B7000766BC /* FormEditableBlockItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88EC21BDC8B7000766BC /* FormEditableBlockItemNode.swift */; }; 09DD88ED21BDC8B7000766BC /* FormEditableBlockItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88EC21BDC8B7000766BC /* FormEditableBlockItemNode.swift */; };
09DD88EF21BDDE2B000766BC /* Geocoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88EE21BDDE2B000766BC /* Geocoding.swift */; }; 09DD88EF21BDDE2B000766BC /* Geocoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88EE21BDDE2B000766BC /* Geocoding.swift */; };
@ -1211,6 +1213,8 @@
09C9EA3721A044B500E90146 /* StringForDuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringForDuration.swift; sourceTree = "<group>"; }; 09C9EA3721A044B500E90146 /* StringForDuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringForDuration.swift; sourceTree = "<group>"; };
09D304142173C0E900C00567 /* WatchManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchManager.swift; sourceTree = "<group>"; }; 09D304142173C0E900C00567 /* WatchManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchManager.swift; sourceTree = "<group>"; };
09D304172173C15700C00567 /* WatchSettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchSettingsController.swift; sourceTree = "<group>"; }; 09D304172173C15700C00567 /* WatchSettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchSettingsController.swift; sourceTree = "<group>"; };
09DD5D4F21ECC3C400D7007A /* SuppressContactsWarning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuppressContactsWarning.swift; sourceTree = "<group>"; };
09DD5D5121ED175300D7007A /* WallpaperColorPickerNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperColorPickerNode.swift; sourceTree = "<group>"; };
09DD88E821BAF65E000766BC /* ItemListAddressItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemListAddressItem.swift; sourceTree = "<group>"; }; 09DD88E821BAF65E000766BC /* ItemListAddressItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemListAddressItem.swift; sourceTree = "<group>"; };
09DD88EC21BDC8B7000766BC /* FormEditableBlockItemNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormEditableBlockItemNode.swift; sourceTree = "<group>"; }; 09DD88EC21BDC8B7000766BC /* FormEditableBlockItemNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormEditableBlockItemNode.swift; sourceTree = "<group>"; };
09DD88EE21BDDE2B000766BC /* Geocoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Geocoding.swift; sourceTree = "<group>"; }; 09DD88EE21BDDE2B000766BC /* Geocoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Geocoding.swift; sourceTree = "<group>"; };
@ -3137,6 +3141,7 @@
09F664CB21EB552C00AB7E26 /* WallpaperSearchRecentQueries.swift */, 09F664CB21EB552C00AB7E26 /* WallpaperSearchRecentQueries.swift */,
09F664CD21EBB3A100AB7E26 /* ImageBlur.swift */, 09F664CD21EBB3A100AB7E26 /* ImageBlur.swift */,
09F664CF21EBCFB900AB7E26 /* WallpaperCropNode.swift */, 09F664CF21EBCFB900AB7E26 /* WallpaperCropNode.swift */,
09DD5D5121ED175300D7007A /* WallpaperColorPickerNode.swift */,
); );
name = Themes; name = Themes;
sourceTree = "<group>"; sourceTree = "<group>";
@ -4727,6 +4732,7 @@
09C9EA32219F79F600E90146 /* ID3Artwork.h */, 09C9EA32219F79F600E90146 /* ID3Artwork.h */,
09C9EA31219F79F500E90146 /* ID3Artwork.m */, 09C9EA31219F79F500E90146 /* ID3Artwork.m */,
099529B321D3E5D800805E13 /* CheckDiskSpace.swift */, 099529B321D3E5D800805E13 /* CheckDiskSpace.swift */,
09DD5D4F21ECC3C400D7007A /* SuppressContactsWarning.swift */,
); );
name = Utils; name = Utils;
sourceTree = "<group>"; sourceTree = "<group>";
@ -5104,6 +5110,7 @@
D0EC6CB61EB9F58800EBF1C3 /* RMGeometry.m in Sources */, D0EC6CB61EB9F58800EBF1C3 /* RMGeometry.m in Sources */,
0941A9A0210B057200EBE194 /* OpenInActionSheetController.swift in Sources */, 0941A9A0210B057200EBE194 /* OpenInActionSheetController.swift in Sources */,
D079FCDD1F05C4F20038FADE /* LocalAuth.swift in Sources */, D079FCDD1F05C4F20038FADE /* LocalAuth.swift in Sources */,
09DD5D5221ED175300D7007A /* WallpaperColorPickerNode.swift in Sources */,
D0B2F76820528E3D00D3BFB9 /* UserInfoEditingPhoneActionItem.swift in Sources */, D0B2F76820528E3D00D3BFB9 /* UserInfoEditingPhoneActionItem.swift in Sources */,
D0EC6CB71EB9F58800EBF1C3 /* RMIntroPageView.m in Sources */, D0EC6CB71EB9F58800EBF1C3 /* RMIntroPageView.m in Sources */,
D0EC6CB81EB9F58800EBF1C3 /* RMIntroViewController.m in Sources */, D0EC6CB81EB9F58800EBF1C3 /* RMIntroViewController.m in Sources */,
@ -5206,6 +5213,7 @@
D0EC6CE21EB9F58800EBF1C3 /* PresentationResourcesChatList.swift in Sources */, D0EC6CE21EB9F58800EBF1C3 /* PresentationResourcesChatList.swift in Sources */,
D0EC6CE31EB9F58800EBF1C3 /* PresentationResourcesChat.swift in Sources */, D0EC6CE31EB9F58800EBF1C3 /* PresentationResourcesChat.swift in Sources */,
D0AA840C1FEB2BA3005C6E91 /* OverlayPlayerControlsNode.swift in Sources */, D0AA840C1FEB2BA3005C6E91 /* OverlayPlayerControlsNode.swift in Sources */,
09DD5D5021ECC3C400D7007A /* SuppressContactsWarning.swift in Sources */,
D0F67FF21EE6B915000E5906 /* ChannelMembersSearchControllerNode.swift in Sources */, D0F67FF21EE6B915000E5906 /* ChannelMembersSearchControllerNode.swift in Sources */,
D0EC6CE41EB9F58800EBF1C3 /* PresentationData.swift in Sources */, D0EC6CE41EB9F58800EBF1C3 /* PresentationData.swift in Sources */,
D0EC6CE51EB9F58800EBF1C3 /* PresentationStrings.swift in Sources */, D0EC6CE51EB9F58800EBF1C3 /* PresentationStrings.swift in Sources */,

View File

@ -57,13 +57,13 @@ final class ChatBackgroundNode: ASDisplayNode {
} }
} }
private var backgroundImageForWallpaper: (TelegramWallpaper, UIImage)? private var backgroundImageForWallpaper: (TelegramWallpaper, PresentationWallpaperMode, UIImage)?
private var serviceBackgroundColorForWallpaper: (TelegramWallpaper, UIColor)? private var serviceBackgroundColorForWallpaper: (TelegramWallpaper, UIColor)?
func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mode: PresentationWallpaperMode = .still, postbox: Postbox) -> UIImage? { func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mode: PresentationWallpaperMode = .still, postbox: Postbox) -> UIImage? {
var backgroundImage: UIImage? var backgroundImage: UIImage?
if wallpaper == backgroundImageForWallpaper?.0 { if wallpaper == backgroundImageForWallpaper?.0, mode == backgroundImageForWallpaper?.1 {
backgroundImage = backgroundImageForWallpaper?.1 backgroundImage = backgroundImageForWallpaper?.2
} else { } else {
switch wallpaper { switch wallpaper {
case .builtin: case .builtin:
@ -105,7 +105,7 @@ func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mode: Presentat
} }
} }
if let backgroundImage = backgroundImage { if let backgroundImage = backgroundImage {
backgroundImageForWallpaper = (wallpaper, backgroundImage) backgroundImageForWallpaper = (wallpaper, mode, backgroundImage)
} }
} }
return backgroundImage return backgroundImage
@ -188,76 +188,94 @@ func chatServiceBackgroundColor(wallpaper: TelegramWallpaper, postbox: Postbox)
} }
func chatBackgroundContrastColor(wallpaper: TelegramWallpaper, postbox: Postbox) -> Signal<UIColor, NoError> { func chatBackgroundContrastColor(wallpaper: TelegramWallpaper, postbox: Postbox) -> Signal<UIColor, NoError> {
// if wallpaper == serviceBackgroundColorForWallpaper?.0, let color = serviceBackgroundColorForWallpaper?.1 { switch wallpaper {
// return .single(color) case .builtin:
// } else { return .single(UIColor(rgb: 0x888f96))
switch wallpaper { case let .color(color):
case .builtin: return .single(contrastingColor(for: UIColor(rgb: UInt32(bitPattern: color))))
return .single(UIColor(rgb: 0x888f96)) case let .image(representations):
case let .color(color): if let largest = largestImageRepresentation(representations) {
return .single(contrastingColor(for: UIColor(rgb: UInt32(bitPattern: color)))) return Signal<UIColor, NoError> { subscriber in
case let .image(representations): let fetch = postbox.mediaBox.fetchedResource(largest.resource, parameters: nil).start()
if let largest = largestImageRepresentation(representations) { let imageSignal = postbox.mediaBox.resourceData(largest.resource)
return Signal<UIColor, NoError> { subscriber in |> mapToSignal { data -> Signal<UIImage?, NoError> in
let fetch = postbox.mediaBox.fetchedResource(largest.resource, parameters: nil).start() if data.complete, let image = UIImage(contentsOfFile: data.path) {
let data = backgroundContrastColor(for: postbox.mediaBox.resourceData(largest.resource)).start(next: { next in return .single(image)
subscriber.putNext(next) } else {
}, completed: { return .complete()
subscriber.putCompletion()
})
return ActionDisposable {
fetch.dispose()
data.dispose()
} }
} }
// |> afterNext { color in let data = backgroundContrastColor(for: imageSignal).start(next: { next in
// serviceBackgroundColorForWallpaper = (wallpaper, color) subscriber.putNext(next)
//} }, completed: {
subscriber.putCompletion()
})
return ActionDisposable {
fetch.dispose()
data.dispose()
}
}
} else {
return .single(.white)
}
case let .file(file):
return Signal<UIColor, NoError> { subscriber in
let fetch = postbox.mediaBox.fetchedResource(file.file.resource, parameters: nil).start()
let imageSignal = postbox.mediaBox.resourceData(file.file.resource)
|> mapToSignal { data -> Signal<UIImage?, NoError> in
if data.complete, let image = UIImage(contentsOfFile: data.path) {
return .single(image)
} else { } else {
return .single(.white) return .complete()
} }
case let .file(file): }
return Signal<UIColor, NoError> { subscriber in let data = backgroundContrastColor(for: imageSignal).start(next: { next in
let fetch = postbox.mediaBox.fetchedResource(file.file.resource, parameters: nil).start() subscriber.putNext(next)
let data = backgroundContrastColor(for: postbox.mediaBox.resourceData(file.file.resource)).start(next: { next in }, completed: {
subscriber.putNext(next) subscriber.putCompletion()
}, completed: { })
subscriber.putCompletion() return ActionDisposable {
}) fetch.dispose()
return ActionDisposable { data.dispose()
fetch.dispose() }
data.dispose()
}
}
// |> afterNext { color in
// serviceBackgroundColorForWallpaper = (wallpaper, color)
//}
} }
// } }
} }
private func backgroundContrastColor(for data: Signal<MediaResourceData, NoError>) -> Signal<UIColor, NoError> { func backgroundContrastColor(for image: Signal<UIImage?, NoError>) -> Signal<UIColor, NoError> {
return data return image
|> mapToSignal { data -> Signal<UIColor, NoError> in |> map { image -> UIColor in
if data.complete { if let image = image {
let image = UIImage(contentsOfFile: data.path)
let context = DrawingContext(size: CGSize(width: 128.0, height: 32.0), scale: 1.0, clear: false) let context = DrawingContext(size: CGSize(width: 128.0, height: 32.0), scale: 1.0, clear: false)
context.withFlippedContext({ context in context.withFlippedContext({ context in
if let image = image, let cgImage = image.cgImage { if let cgImage = image.cgImage {
let size = image.size.aspectFilled(CGSize(width: 128.0, height: 128.0)) let size = image.size.aspectFilled(CGSize(width: 128.0, height: 128.0))
context.draw(cgImage, in: CGRect(x: floor((128.0 - size.width) / 2.0), y: 0.0, width: size.width, height: size.height)) context.draw(cgImage, in: CGRect(x: floor((128.0 - size.width) / 2.0), y: 0.0, width: size.width, height: size.height))
} }
}) })
let finalContext = DrawingContext(size: CGSize(width: 1.0, height: 1.0), scale: 1.0, clear: false)
finalContext.withFlippedContext({ c in var matching: Int = 0
if let cgImage = context.generateImage()?.cgImage { var total: Int = Int(context.size.width) * Int(context.size.height)
c.draw(cgImage, in: CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)) for y in 0 ..< Int(context.size.height) {
for x in 0 ..< Int(context.size.width) {
var saturation: CGFloat = 0.0
var brightness: CGFloat = 0.0
if context.colorAt(CGPoint(x: x, y: y)).getHue(nil, saturation: nil, brightness: &brightness, alpha: nil) {
if brightness > 0.6 {
matching += 1
}
}
} }
}) }
let color = finalContext.colorAt(CGPoint())
return .single(contrastingColor(for: color)) if CGFloat(matching) / CGFloat(total) > 0.4 {
return .black
} else {
return .white
}
} else {
return .black
} }
return .complete()
} }
} }
@ -266,11 +284,10 @@ private func contrastingColor(for color: UIColor) -> UIColor {
var green: CGFloat = 0.0 var green: CGFloat = 0.0
var blue: CGFloat = 0.0 var blue: CGFloat = 0.0
var luminance: CGFloat = 0.0 var luminance: CGFloat = 0.0
var alpha: CGFloat = 0.0;
if color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) { if color.getRed(&red, green: &green, blue: &blue, alpha: nil) {
luminance = red * 0.2126 + green * 0.7152 + blue * 0.0722 luminance = red * 0.2126 + green * 0.7152 + blue * 0.0722
} else if color.getWhite(&luminance, alpha: &alpha) { } else if color.getWhite(&luminance, alpha: nil) {
} }
if luminance > 0.6 { if luminance > 0.6 {

View File

@ -163,6 +163,14 @@ public class ComposeController: ViewController {
} }
} }
self.contactsNode.contactListNode.suppressPermissionWarning = { [weak self] in
if let strongSelf = self {
presentContactsWarningSuppression(account: strongSelf.account, present: { c, a in
strongSelf.present(c, in: .window(.root), with: a)
})
}
}
self.contactsNode.contactListNode.contentOffsetChanged = { [weak self] offset in self.contactsNode.contactListNode.contentOffsetChanged = { [weak self] offset in
if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode { if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode {
searchContentNode.updateListVisibleContentOffset(offset) searchContentNode.updateListVisibleContentOffset(offset)

View File

@ -154,6 +154,14 @@ class ContactSelectionController: ViewController {
self?.openPeer(peer: peer) self?.openPeer(peer: peer)
} }
self.contactsNode.contactListNode.suppressPermissionWarning = { [weak self] in
if let strongSelf = self {
presentContactsWarningSuppression(account: strongSelf.account, present: { c, a in
strongSelf.present(c, in: .window(.root), with: a)
})
}
}
self.contactsNode.dismiss = { [weak self] in self.contactsNode.dismiss = { [weak self] in
self?.presentingViewController?.dismiss(animated: true, completion: nil) self?.presentingViewController?.dismiss(animated: true, completion: nil)
} }

View File

@ -177,26 +177,9 @@ public class ContactsController: ViewController {
self.contactsNode.contactListNode.suppressPermissionWarning = { [weak self] in self.contactsNode.contactListNode.suppressPermissionWarning = { [weak self] in
if let strongSelf = self { if let strongSelf = self {
let presentationData = strongSelf.account.telegramApplicationContext.currentPresentationData.with { $0 } presentContactsWarningSuppression(account: strongSelf.account, present: { c, a in
strongSelf.present(textAlertController(account: strongSelf.account, title: presentationData.strings.Contacts_PermissionsSuppressWarningTitle, text: presentationData.strings.Contacts_PermissionsSuppressWarningText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Contacts_PermissionsKeepDisabled, action: { strongSelf.present(c, in: .window(.root), with: a)
ApplicationSpecificNotice.setContactsPermissionWarning(postbox: strongSelf.account.postbox, value: Int32(Date().timeIntervalSince1970)) })
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Contacts_PermissionsEnable, action: { [weak self] in
if let strongSelf = self {
let account = strongSelf.account
let _ = (DeviceAccess.authorizationStatus(account: account, subject: .contacts)
|> take(1)
|> deliverOnMainQueue).start(next: { status in
switch status {
case .notDetermined:
DeviceAccess.authorizeAccess(to: .contacts, account: account)
case .denied, .restricted:
account.telegramApplicationContext.applicationBindings.openSettings()
default:
break
}
})
}
})]), in: .window(.root))
} }
} }

View File

@ -208,6 +208,7 @@ func legacyWebSearchItem(account: Account, result: ChatContextResult) -> LegacyW
var thumbnailResource: TelegramMediaResource? var thumbnailResource: TelegramMediaResource?
var imageResource: TelegramMediaResource? var imageResource: TelegramMediaResource?
var imageDimensions = CGSize() var imageDimensions = CGSize()
var immediateThumbnailData: Data?
let thumbnailSignal: Signal<UIImage, NoError> let thumbnailSignal: Signal<UIImage, NoError>
let originalSignal: Signal<UIImage, NoError> let originalSignal: Signal<UIImage, NoError>
@ -225,6 +226,7 @@ func legacyWebSearchItem(account: Account, result: ChatContextResult) -> LegacyW
imageDimensions = dimensions imageDimensions = dimensions
} }
case let .internalReference(_, _, _, _, _, image, _, _): case let .internalReference(_, _, _, _, _, image, _, _):
immediateThumbnailData = image?.immediateThumbnailData
if let image = image { if let image = image {
if let imageRepresentation = imageRepresentationLargerThan(image.representations, size: CGSize(width: 1000.0, height: 800.0)) { if let imageRepresentation = imageRepresentationLargerThan(image.representations, size: CGSize(width: 1000.0, height: 800.0)) {
imageDimensions = imageRepresentation.dimensions imageDimensions = imageRepresentation.dimensions
@ -255,7 +257,7 @@ func legacyWebSearchItem(account: Account, result: ChatContextResult) -> LegacyW
representations.append(TelegramMediaImageRepresentation(dimensions: thumbnailDimensions, resource: thumbnailResource)) representations.append(TelegramMediaImageRepresentation(dimensions: thumbnailDimensions, resource: thumbnailResource))
} }
representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource)) representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource))
let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil) let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil)
thumbnailSignal = chatMessagePhotoDatas(postbox: account.postbox, photoReference: .standalone(media: tmpImage), autoFetchFullSize: false) thumbnailSignal = chatMessagePhotoDatas(postbox: account.postbox, photoReference: .standalone(media: tmpImage), autoFetchFullSize: false)
|> mapToSignal { (thumbnailData, _, _) -> Signal<UIImage, NoError> in |> mapToSignal { (thumbnailData, _, _) -> Signal<UIImage, NoError> in
if let data = thumbnailData, let image = UIImage(data: data) { if let data = thumbnailData, let image = UIImage(data: data) {

View File

@ -104,7 +104,9 @@ public final class PeerSelectionController: ViewController {
} }
override public func loadDisplayNode() { override public func loadDisplayNode() {
self.displayNode = PeerSelectionControllerNode(account: self.account, filter: self.filter, hasContactSelector: hasContactSelector, dismiss: { [weak self] in self.displayNode = PeerSelectionControllerNode(account: self.account, filter: self.filter, hasContactSelector: hasContactSelector, present: { [weak self] c, a in
self?.present(c, in: .window(.root), with: a)
}, dismiss: { [weak self] in
self?.presentingViewController?.dismiss(animated: false, completion: nil) self?.presentingViewController?.dismiss(animated: false, completion: nil)
}) })

View File

@ -7,6 +7,7 @@ import SwiftSignalKit
final class PeerSelectionControllerNode: ASDisplayNode { final class PeerSelectionControllerNode: ASDisplayNode {
private let account: Account private let account: Account
private let present: (ViewController, Any?) -> Void
private let dismiss: () -> Void private let dismiss: () -> Void
private let filter: ChatListNodePeersFilter private let filter: ChatListNodePeersFilter
@ -49,8 +50,9 @@ final class PeerSelectionControllerNode: ASDisplayNode {
} }
init(account: Account, filter: ChatListNodePeersFilter, hasContactSelector: Bool, dismiss: @escaping () -> Void) { init(account: Account, filter: ChatListNodePeersFilter, hasContactSelector: Bool, present: @escaping (ViewController, Any?) -> Void, dismiss: @escaping () -> Void) {
self.account = account self.account = account
self.present = present
self.dismiss = dismiss self.dismiss = dismiss
self.filter = filter self.filter = filter
@ -253,7 +255,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
strongSelf.requestOpenPeerFromSearch?(peer) strongSelf.requestOpenPeerFromSearch?(peer)
} }
}) })
case let .deviceContact(stableId, contact): case .deviceContact:
break break
} }
} }
@ -336,6 +338,13 @@ final class PeerSelectionControllerNode: ASDisplayNode {
self?.requestOpenPeer?(peer.id) self?.requestOpenPeer?(peer.id)
} }
} }
contactListNode.suppressPermissionWarning = { [weak self] in
if let strongSelf = self {
presentContactsWarningSuppression(account: strongSelf.account, present: { c, a in
strongSelf.present(c, a)
})
}
}
contactListNode.contentOffsetChanged = { [weak self] offset in contactListNode.contentOffsetChanged = { [weak self] offset in
self?.contentOffsetChanged?(offset) self?.contentOffsetChanged?(offset)
} }

View File

@ -2802,6 +2802,8 @@ func photoWallpaper(postbox: Postbox, photoLibraryResource: PhotoLibraryMediaRes
return { arguments in return { arguments in
let context = DrawingContext(size: arguments.drawingSize, scale: 1.0, clear: true) let context = DrawingContext(size: arguments.drawingSize, scale: 1.0, clear: true)
var dimensions = sourceImage?.size
if let thumbnailImage = sourceImage?.cgImage, isThumbnail { if let thumbnailImage = sourceImage?.cgImage, isThumbnail {
var fittedSize = arguments.imageSize var fittedSize = arguments.imageSize
if abs(fittedSize.width - arguments.boundingSize.width).isLessThanOrEqualTo(CGFloat(1.0)) { if abs(fittedSize.width - arguments.boundingSize.width).isLessThanOrEqualTo(CGFloat(1.0)) {
@ -2846,8 +2848,8 @@ func photoWallpaper(postbox: Postbox, photoLibraryResource: PhotoLibraryMediaRes
context.withFlippedContext { c in context.withFlippedContext { c in
c.setBlendMode(.copy) c.setBlendMode(.copy)
if let sourceImage = sourceImage, let cgImage = sourceImage.cgImage { if let sourceImage = sourceImage, let cgImage = sourceImage.cgImage, let dimensions = dimensions {
let imageSize = sourceImage.size.aspectFilled(arguments.drawingRect.size) let imageSize = dimensions.aspectFilled(arguments.drawingRect.size)
let fittedRect = CGRect(origin: CGPoint(x: floor((arguments.drawingRect.size.width - imageSize.width) / 2.0), y: floor((arguments.drawingRect.size.height - imageSize.height) / 2.0)), size: imageSize) let fittedRect = CGRect(origin: CGPoint(x: floor((arguments.drawingRect.size.width - imageSize.width) / 2.0), y: floor((arguments.drawingRect.size.height - imageSize.height) / 2.0)), size: imageSize)
c.draw(cgImage, in: fittedRect) c.draw(cgImage, in: fittedRect)
} }

View File

@ -3407,195 +3407,195 @@ public final class PresentationStrings {
public var Channel_Setup_TypePublicHelp: String { return self._s[3025]! } public var Channel_Setup_TypePublicHelp: String { return self._s[3025]! }
public var Passport_Identity_EditInternalPassport: String { return self._s[3026]! } public var Passport_Identity_EditInternalPassport: String { return self._s[3026]! }
public var PhotoEditor_Skip: String { return self._s[3027]! } public var PhotoEditor_Skip: String { return self._s[3027]! }
public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { public func StickerPack_RemoveMaskCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Notifications_Exceptions(_ value: Int32) -> String { public func SharedMedia_Link(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_ShortSeconds(_ value: Int32) -> String { public func Media_SharePhoto(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func GroupInfo_ParticipantCount(_ value: Int32) -> String { public func ForwardedFiles(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHAT_MESSAGES(_ value: Int32) -> String { public func InviteText_ContactsCountText(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Call_Minutes(_ value: Int32) -> String { public func StickerPack_RemoveStickerCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ value: Int32) -> String { public func ChatList_DeleteConfirmation(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedContacts(_ value: Int32) -> String { public func MessageTimer_ShortDays(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_ShortHours(_ value: Int32) -> String { public func PUSH_CHANNEL_MESSAGES(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func SharedMedia_Photo(_ value: Int32) -> String { public func MessageTimer_Minutes(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedVideos(_ value: Int32) -> String { public func Contacts_ImportersCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func StickerPack_StickerCount(_ value: Int32) -> String { public func MessageTimer_Months(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { public func MessagePoll_VotedCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Media_ShareItem(_ value: Int32) -> String { public func StickerPack_StickerCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedAudios(_ value: Int32) -> String { public func PUSH_MESSAGES(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func InviteText_ContactsCountText(_ value: Int32) -> String { public func ForwardedVideos(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { public func MessageTimer_ShortMinutes(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Map_ETAMinutes(_ value: Int32) -> String { public func SharedMedia_File(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_ShortDays(_ value: Int32) -> String { public func PUSH_MESSAGE_VIDEOS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MuteExpires_Days(_ value: Int32) -> String { public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { public func Notifications_Exceptions(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { public func ForwardedPolls(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHAT_MESSAGE_ROUNDS(_ value: Int32) -> String { public func MuteExpires_Days(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { public func Conversation_StatusOnline(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Call_Seconds(_ value: Int32) -> String { public func Passport_Scans(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHANNEL_MESSAGES(_ value: Int32) -> String { public func GroupInfo_ParticipantCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_Years(_ value: Int32) -> String { public func ForwardedAuthorsOthers(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_MESSAGE_PHOTOS(_ value: Int32) -> String { public func Conversation_StatusMembers(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_MESSAGES(_ value: Int32) -> String { public func LastSeen_HoursAgo(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHAT_MESSAGE_FWDS(_ value: Int32) -> String { public func QuickSend_Photos(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func StickerPack_AddMaskCount(_ value: Int32) -> String { public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { public func Invitation_Members(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Conversation_StatusSubscribers(_ value: Int32) -> String { public func SharedMedia_Photo(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedFiles(_ value: Int32) -> String { public func ForwardedVideoMessages(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ value: Int32) -> String { public func MuteExpires_Hours(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func QuickSend_Photos(_ value: Int32) -> String { public func PUSH_CHAT_MESSAGE_PHOTOS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedPolls(_ value: Int32) -> String { public func AttachmentMenu_SendPhoto(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedLocations(_ value: Int32) -> String { public func SharedMedia_Generic(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHAT_MESSAGE_PHOTOS(_ value: Int32) -> String { public func MuteFor_Days(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHAT_MESSAGE_VIDEOS(_ value: Int32) -> String { public func SharedMedia_Video(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_MESSAGE_ROUNDS(_ value: Int32) -> String { public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Call_ShortMinutes(_ value: Int32) -> String { public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { public func Media_ShareItem(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_Minutes(_ value: Int32) -> String { public func Call_ShortMinutes(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func SharedMedia_File(_ value: Int32) -> String { public func Call_ShortSeconds(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func LastSeen_HoursAgo(_ value: Int32) -> String { public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, "\(value)")
} }
@ -3603,227 +3603,227 @@ public final class PresentationStrings {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { public func MuteFor_Hours(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Conversation_StatusMembers(_ value: Int32) -> String { public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_ShortWeeks(_ value: Int32) -> String { public func MessageTimer_Weeks(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { public func StickerPack_AddMaskCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MuteExpires_Minutes(_ value: Int32) -> String { public func ForwardedGifs(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func SharedMedia_Generic(_ value: Int32) -> String { public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedMessages(_ value: Int32) -> String { public func PUSH_CHAT_MESSAGES(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Notification_GameScoreSimple(_ value: Int32) -> String { public func MuteExpires_Minutes(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_ShortMinutes(_ value: Int32) -> String { public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { public func MessageTimer_Hours(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Media_ShareVideo(_ value: Int32) -> String { public func ForwardedStickers(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func StickerPack_AddStickerCount(_ value: Int32) -> String { public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ value: Int32) -> String { public func AttachmentMenu_SendVideo(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { public func Map_ETAMinutes(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MuteFor_Days(_ value: Int32) -> String { public func ForwardedContacts(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Conversation_StatusOnline(_ value: Int32) -> String { public func Map_ETAHours(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { public func AttachmentMenu_SendGif(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { public func Notification_GameScoreSelfSimple(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func AttachmentMenu_SendGif(_ value: Int32) -> String { public func MessageTimer_Seconds(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Watch_UserInfo_Mute(_ value: Int32) -> String { public func PUSH_CHANNEL_MESSAGE_FWDS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_Days(_ value: Int32) -> String { public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_Hours(_ value: Int32) -> String { public func LiveLocation_MenuChatsCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Invitation_Members(_ value: Int32) -> String { public func PUSH_CHAT_MESSAGE_FWDS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_MESSAGE_VIDEOS(_ value: Int32) -> String { public func Conversation_StatusSubscribers(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func AttachmentMenu_SendItem(_ value: Int32) -> String { public func MessageTimer_Days(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MuteExpires_Hours(_ value: Int32) -> String { public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { public func MessageTimer_ShortWeeks(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func SharedMedia_Link(_ value: Int32) -> String { public func Call_Seconds(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func LastSeen_MinutesAgo(_ value: Int32) -> String { public func Call_Minutes(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_Months(_ value: Int32) -> String { public func PUSH_MESSAGE_FWDS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_CHANNEL_MESSAGE_FWDS(_ value: Int32) -> String { public func PUSH_CHAT_MESSAGE_VIDEOS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PUSH_MESSAGE_FWDS(_ value: Int32) -> String { public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedGifs(_ value: Int32) -> String { public func PUSH_MESSAGE_ROUNDS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedAuthorsOthers(_ value: Int32) -> String { public func StickerPack_AddStickerCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { public func Watch_UserInfo_Mute(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func SharedMedia_Video(_ value: Int32) -> String { public func MessageTimer_ShortSeconds(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MuteFor_Hours(_ value: Int32) -> String { public func MessageTimer_Years(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedStickers(_ value: Int32) -> String { public func LastSeen_MinutesAgo(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func UserCount(_ value: Int32) -> String { public func Notification_GameScoreExtended(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ChatList_DeleteConfirmation(_ value: Int32) -> String { public func Notification_GameScoreSimple(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_Seconds(_ value: Int32) -> String { public func ForwardedLocations(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Map_ETAHours(_ value: Int32) -> String { public func ForwardedMessages(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Contacts_ImportersCount(_ value: Int32) -> String { public func PUSH_MESSAGE_PHOTOS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedPhotos(_ value: Int32) -> String { public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Call_ShortSeconds(_ value: Int32) -> String { public func MessageTimer_ShortHours(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Passport_Scans(_ value: Int32) -> String { public func CreatePoll_AddMoreOptions(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { public func Media_ShareVideo(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func AttachmentMenu_SendVideo(_ value: Int32) -> String { public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessagePoll_VotedCount(_ value: Int32) -> String { public func ForwardedAudios(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Media_SharePhoto(_ value: Int32) -> String { public func PUSH_CHAT_MESSAGE_ROUNDS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func MessageTimer_Weeks(_ value: Int32) -> String { public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { public func AttachmentMenu_SendItem(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func ForwardedVideoMessages(_ value: Int32) -> String { public func UserCount(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, "\(value)")
} }
public func Notification_GameScoreExtended(_ value: Int32) -> String { public func ForwardedPhotos(_ value: Int32) -> String {
let form = presentationStringsPluralizationForm(self.lc, value) let form = presentationStringsPluralizationForm(self.lc, value)
return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, "\(value)") return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, "\(value)")
} }

View File

@ -30,6 +30,9 @@ final class SearchDisplayController {
self.searchBar.cancel = { [weak self] in self.searchBar.cancel = { [weak self] in
self?.isDeactivating = true self?.isDeactivating = true
cancel() cancel()
}
self.searchBar.clearPrefix = {
} }
self.contentNode.cancel = { [weak self] in self.contentNode.cancel = { [weak self] in
self?.isDeactivating = true self?.isDeactivating = true

View File

@ -36,7 +36,7 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
override init() { override init() {
self.imageNode.contentAnimations = [.subsequentUpdates] self.imageNode.contentAnimations = [.subsequentUpdates]
self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.6)) self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.3))
let progressDiameter: CGFloat = 50.0 let progressDiameter: CGFloat = 50.0
self.statusNode.frame = CGRect(x: 0.0, y: 0.0, width: progressDiameter, height: progressDiameter) self.statusNode.frame = CGRect(x: 0.0, y: 0.0, width: progressDiameter, height: progressDiameter)
self.statusNode.isUserInteractionEnabled = false self.statusNode.isUserInteractionEnabled = false

View File

@ -0,0 +1,25 @@
import Foundation
import AsyncDisplayKit
import Display
import SwiftSignalKit
import TelegramCore
func presentContactsWarningSuppression(account: Account, present: (ViewController, Any?) -> Void) {
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
present(textAlertController(account: account, title: presentationData.strings.Contacts_PermissionsSuppressWarningTitle, text: presentationData.strings.Contacts_PermissionsSuppressWarningText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Contacts_PermissionsKeepDisabled, action: {
ApplicationSpecificNotice.setContactsPermissionWarning(postbox: account.postbox, value: Int32(Date().timeIntervalSince1970))
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Contacts_PermissionsEnable, action: {
let _ = (DeviceAccess.authorizationStatus(account: account, subject: .contacts)
|> take(1)
|> deliverOnMainQueue).start(next: { status in
switch status {
case .notDetermined:
DeviceAccess.authorizeAccess(to: .contacts, account: account)
case .denied, .restricted:
account.telegramApplicationContext.applicationBindings.openSettings()
default:
break
}
})
})]), nil)
}

View File

@ -82,8 +82,8 @@ public final class TelegramRootController: NavigationController {
return return
} }
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.15) {
//(controller.navigationController as? NavigationController)?.pushViewController(ThemeGridController(account: self.account, mode: .wallpapers)) //(controller.navigationController as? NavigationController)?.pushViewController(ThemeGridController(account: self.account))
// let wrapperNode = ASDisplayNode() // let wrapperNode = ASDisplayNode()
// let bounds = controller.displayNode.bounds // let bounds = controller.displayNode.bounds

View File

@ -154,7 +154,7 @@ final class ThemeColorsGridControllerNode: ASDisplayNode {
let entries = previousEntries.with { $0 } let entries = previousEntries.with { $0 }
if let entries = entries, !entries.isEmpty { if let entries = entries, !entries.isEmpty {
let wallpapers = entries.map { $0.wallpaper } let wallpapers = entries.map { $0.wallpaper }
let controller = WallpaperListPreviewController(account: account, source: .list(wallpapers: wallpapers, central: wallpaper, mode: nil)) let controller = WallpaperListPreviewController(account: account, source: .list(wallpapers: wallpapers, central: wallpaper, type: .colors))
strongSelf.present(controller, nil) strongSelf.present(controller, nil)
} }
} }
@ -225,7 +225,13 @@ final class ThemeColorsGridControllerNode: ASDisplayNode {
insets.top += navigationBarHeight insets.top += navigationBarHeight
let scrollIndicatorInsets = insets let scrollIndicatorInsets = insets
let referenceImageSize = CGSize(width: 108.0, height: 108.0) let referenceImageSize: CGSize
let screenWidth = min(layout.size.width, layout.size.height)
if screenWidth >= 375.0 {
referenceImageSize = CGSize(width: 108.0, height: 108.0)
} else {
referenceImageSize = CGSize(width: 91.0, height: 91.0)
}
let minSpacing: CGFloat = 8.0 let minSpacing: CGFloat = 8.0

View File

@ -125,7 +125,7 @@ final class ThemeGridController: ViewController {
let controller = generator(legacyController.context) let controller = generator(legacyController.context)
legacyController.bind(controller: controller) legacyController.bind(controller: controller)
legacyController.deferScreenEdgeGestures = [.top] legacyController.deferScreenEdgeGestures = [.top]
controller.selectionBlock = { [weak self] asset, thumbnailImage in controller.selectionBlock = { [weak self, weak legacyController] asset, thumbnailImage in
if let strongSelf = self, let asset = asset { if let strongSelf = self, let asset = asset {
let controller = WallpaperListPreviewController(account: strongSelf.account, source: .asset(asset.backingAsset, thumbnailImage)) let controller = WallpaperListPreviewController(account: strongSelf.account, source: .asset(asset.backingAsset, thumbnailImage))
controller.apply = { [weak self, weak legacyController, weak controller] wallpaper, mode, cropRect in controller.apply = { [weak self, weak legacyController, weak controller] wallpaper, mode, cropRect in

View File

@ -222,7 +222,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
mode = strongSelf.presentationData.chatWallpaperMode mode = strongSelf.presentationData.chatWallpaperMode
} }
presentPreviewController(.list(wallpapers: wallpapers, central: wallpaper, mode: mode)) presentPreviewController(.list(wallpapers: wallpapers, central: wallpaper, type: .wallpapers(mode)))
} }
} }
}, toggleWallpaperSelection: { [weak self] index, value in }, toggleWallpaperSelection: { [weak self] index, value in
@ -412,7 +412,13 @@ final class ThemeGridControllerNode: ASDisplayNode {
let scrollIndicatorInsets = insets let scrollIndicatorInsets = insets
let minSpacing: CGFloat = 8.0 let minSpacing: CGFloat = 8.0
let referenceImageSize = CGSize(width: 108.0, height: 230.0) let referenceImageSize: CGSize
let screenWidth = min(layout.size.width, layout.size.height)
if screenWidth >= 375.0 {
referenceImageSize = CGSize(width: 108.0, height: 230.0)
} else {
referenceImageSize = CGSize(width: 91.0, height: 161.0)
}
let imageCount = Int((layout.size.width - minSpacing * 2.0) / (referenceImageSize.width + minSpacing)) let imageCount = Int((layout.size.width - minSpacing * 2.0) / (referenceImageSize.width + minSpacing))
let imageSize = referenceImageSize.aspectFilled(CGSize(width: floor((layout.size.width - CGFloat(imageCount + 1) * minSpacing) / CGFloat(imageCount)), height: referenceImageSize.height)) let imageSize = referenceImageSize.aspectFilled(CGSize(width: floor((layout.size.width - CGFloat(imageCount + 1) * minSpacing) / CGFloat(imageCount)), height: referenceImageSize.height))
let spacing = floor((layout.size.width - CGFloat(imageCount) * imageSize.width) / CGFloat(imageCount + 1)) let spacing = floor((layout.size.width - CGFloat(imageCount) * imageSize.width) / CGFloat(imageCount + 1))
@ -520,9 +526,9 @@ final class ThemeGridControllerNode: ASDisplayNode {
return return
} }
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ThemeGridSearchContainerNode(account: account, openResult: { [weak self] result, results in self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ThemeGridSearchContainerNode(account: account, openResult: { [weak self] result in
if let strongSelf = self { if let strongSelf = self {
strongSelf.presentPreviewController(.contextResults(results: results, central: result)) strongSelf.presentPreviewController(.contextResult(result))
} }
}), cancel: { [weak self] in }), cancel: { [weak self] in
self?.requestDeactivateSearch?() self?.requestDeactivateSearch?()

View File

@ -38,13 +38,20 @@ private func nodeColor(for color: WallpaperSearchColor) -> UIColor {
private class ThemeGridColorNode: HighlightableButtonNode { private class ThemeGridColorNode: HighlightableButtonNode {
let action: () -> Void let action: () -> Void
init(color: WallpaperSearchColor, action: @escaping (WallpaperSearchColor) -> Void) { init(color: WallpaperSearchColor, strokeColor: UIColor, action: @escaping (WallpaperSearchColor) -> Void) {
self.action = { self.action = {
action(color) action(color)
} }
super.init() super.init()
self.setImage(generateFilledCircleImage(diameter: 42.0, color: nodeColor(for: color)), for: .normal)
let image: UIImage?
if color == .white {
image = generateCircleImage(diameter: 42.0, lineWidth: 1.0, color: strokeColor)
} else {
image = generateFilledCircleImage(diameter: 42.0, color: nodeColor(for: color))
}
self.setImage(image, for: .normal)
} }
override func didLoad() { override func didLoad() {
@ -91,7 +98,7 @@ final class ThemeGridSearchColorsNode: ASDisplayNode {
self.addSubnode(self.scrollNode) self.addSubnode(self.scrollNode)
for color in WallpaperSearchColor.allCases { for color in WallpaperSearchColor.allCases {
let colorNode = ThemeGridColorNode(color: color, action: colorSelected) let colorNode = ThemeGridColorNode(color: color, strokeColor: theme.list.controlSecondaryColor, action: colorSelected)
self.scrollNode.addSubnode(colorNode) self.scrollNode.addSubnode(colorNode)
} }
self.scrollNode.view.contentSize = CGSize(width: (inset + diameter) * CGFloat(WallpaperSearchColor.allCases.count) + inset, height: 71.0) self.scrollNode.view.contentSize = CGSize(width: (inset + diameter) * CGFloat(WallpaperSearchColor.allCases.count) + inset, height: 71.0)

View File

@ -268,7 +268,7 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode {
return self._isSearching.get() return self._isSearching.get()
} }
init(account: Account, openResult: @escaping (ChatContextResult, [ChatContextResult]) -> Void) { init(account: Account, openResult: @escaping (ChatContextResult) -> Void) {
self.account = account self.account = account
self.dimNode = ASDisplayNode() self.dimNode = ASDisplayNode()
@ -330,12 +330,8 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode {
let previousSearchItems = Atomic<[ThemeGridSearchEntry]?>(value: nil) let previousSearchItems = Atomic<[ThemeGridSearchEntry]?>(value: nil)
let interaction = ThemeGridSearchInteraction(openResult: { [weak self] result in let interaction = ThemeGridSearchInteraction(openResult: { [weak self] result in
openResult(result)
self?.dismissInput?() self?.dismissInput?()
let previousEntries = previousSearchItems.with { $0 }
if let entries = previousEntries {
openResult(result, entries.map { $0.result })
}
}, selectColor: { [weak self] color in }, selectColor: { [weak self] color in
self?.setQuery?("#color\(color.string) ") self?.setQuery?("#color\(color.string) ")
}, setSearchQuery: { [weak self] query in }, setSearchQuery: { [weak self] query in
@ -381,23 +377,25 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode {
} }
|> mapToSignal { peer -> Signal<([ThemeGridSearchEntry], Bool)?, NoError> in |> mapToSignal { peer -> Signal<([ThemeGridSearchEntry], Bool)?, NoError> in
if let user = peer as? TelegramUser, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder { if let user = peer as? TelegramUser, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder {
return requestContextResults(account: account, botId: user.id, query: wallpaperQuery, peerId: account.peerId, limit: 16) return (.complete() |> delay(0.1, queue: Queue.concurrentDefaultQueue()))
|> map { collection -> ([ThemeGridSearchEntry], Bool)? in |> then(
guard let collection = collection else { requestContextResults(account: account, botId: user.id, query: wallpaperQuery, peerId: account.peerId, limit: 16)
return nil |> map { collection -> ([ThemeGridSearchEntry], Bool)? in
guard let collection = collection else {
return nil
}
var entries: [ThemeGridSearchEntry] = []
var i = 0
for result in collection.results {
entries.append(ThemeGridSearchEntry(index: i, result: result))
i += 1
}
updateSearchContext { _ in
return (ThemeGridSearchContext(result: ThemeGridSearchResult(query: query, items: collection.results, nextOffset: collection.nextOffset), loadMoreIndex: nil), true)
}
return (entries, false)
} }
var entries: [ThemeGridSearchEntry] = [] )
var i = 0
for result in collection.results {
entries.append(ThemeGridSearchEntry(index: i, result: result))
i += 1
}
updateSearchContext { _ in
return (ThemeGridSearchContext(result: ThemeGridSearchResult(query: query, items: collection.results, nextOffset: collection.nextOffset), loadMoreIndex: nil), true)
}
return (entries, false)
}
} else { } else {
return .single(nil) return .single(nil)
} }
@ -484,7 +482,6 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode {
self.backgroundColor = theme.chatList.backgroundColor self.backgroundColor = theme.chatList.backgroundColor
self.dimNode.backgroundColor = theme.chatList.backgroundColor self.dimNode.backgroundColor = theme.chatList.backgroundColor
self.recentListNode.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor self.recentListNode.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor
//self.gridNode.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor
} }
// private func updateState(_ f: (ChatListSearchContainerNodeState) -> ChatListSearchContainerNodeState) { // private func updateState(_ f: (ChatListSearchContainerNodeState) -> ChatListSearchContainerNodeState) {
@ -562,7 +559,13 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode {
self.validLayout = layout self.validLayout = layout
let minSpacing: CGFloat = 8.0 let minSpacing: CGFloat = 8.0
let referenceImageSize = CGSize(width: 108.0, height: 230.0) let referenceImageSize: CGSize
let screenWidth = min(layout.size.width, layout.size.height)
if screenWidth >= 375.0 {
referenceImageSize = CGSize(width: 108.0, height: 230.0)
} else {
referenceImageSize = CGSize(width: 91.0, height: 161.0)
}
let imageCount = Int((layout.size.width - minSpacing * 2.0) / (referenceImageSize.width + minSpacing)) let imageCount = Int((layout.size.width - minSpacing * 2.0) / (referenceImageSize.width + minSpacing))
let imageSize = referenceImageSize.aspectFilled(CGSize(width: floor((layout.size.width - CGFloat(imageCount + 1) * minSpacing) / CGFloat(imageCount)), height: referenceImageSize.height)) let imageSize = referenceImageSize.aspectFilled(CGSize(width: floor((layout.size.width - CGFloat(imageCount + 1) * minSpacing) / CGFloat(imageCount)), height: referenceImageSize.height))
let spacing = floor((layout.size.width - CGFloat(imageCount) * imageSize.width) / CGFloat(imageCount + 1)) let spacing = floor((layout.size.width - CGFloat(imageCount) * imageSize.width) / CGFloat(imageCount + 1))

View File

@ -65,6 +65,7 @@ final class ThemeGridSearchItemNode: GridItemNode {
var thumbnailResource: TelegramMediaResource? var thumbnailResource: TelegramMediaResource?
var imageResource: TelegramMediaResource? var imageResource: TelegramMediaResource?
var imageDimensions: CGSize? var imageDimensions: CGSize?
var immediateThumbnailData: Data?
switch item.result { switch item.result {
case let .externalReference(_, _, type, _, _, _, content, thumbnail, _): case let .externalReference(_, _, type, _, _, _, content, thumbnail, _):
if let content = content, type != "gif" { if let content = content, type != "gif" {
@ -75,6 +76,7 @@ final class ThemeGridSearchItemNode: GridItemNode {
imageDimensions = content?.dimensions imageDimensions = content?.dimensions
case let .internalReference(_, _, _, _, _, image, file, _): case let .internalReference(_, _, _, _, _, image, file, _):
if let image = image { if let image = image {
immediateThumbnailData = image.immediateThumbnailData
if let largestRepresentation = largestImageRepresentation(image.representations) { if let largestRepresentation = largestImageRepresentation(image.representations) {
imageDimensions = largestRepresentation.dimensions imageDimensions = largestRepresentation.dimensions
} }
@ -91,6 +93,7 @@ final class ThemeGridSearchItemNode: GridItemNode {
} }
} }
} else if let file = file { } else if let file = file {
immediateThumbnailData = file.immediateThumbnailData
if let dimensions = file.dimensions { if let dimensions = file.dimensions {
imageDimensions = dimensions imageDimensions = dimensions
} else if let largestRepresentation = largestImageRepresentation(file.previewRepresentations) { } else if let largestRepresentation = largestImageRepresentation(file.previewRepresentations) {
@ -108,7 +111,7 @@ final class ThemeGridSearchItemNode: GridItemNode {
representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource)) representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource))
} }
if !representations.isEmpty { if !representations.isEmpty {
let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil) let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil)
updateImageSignal = mediaGridMessagePhoto(account: item.account, photoReference: .standalone(media: tmpImage)) updateImageSignal = mediaGridMessagePhoto(account: item.account, photoReference: .standalone(media: tmpImage))
} else { } else {
updateImageSignal = .complete() updateImageSignal = .complete()

View File

@ -0,0 +1,27 @@
import Foundation
import AsyncDisplayKit
import SwiftSignalKit
import Display
//private class WallpaperColorKnobNode: ASDisplayNode {
//
//}
//
//private class WallpaperColorSpaceNode: ASDisplayNode {
// private let knobNode: WallpaperColorNode
//}
//
//
//private class WallpaperColorBrightnessNode: ASDisplayNode {
// private let knobNode: WallpaperColorNode
// var baseColor: UIColor {
// didSet {
// setNeedsDisplay()
// }
// }
//}
//
//class WallpaperColorPickerNode: ASDisplayNode {
// private baseColorNode: WallpaperColorSpaceNode
// private colorBrightnessNode: WallpaperColorSpaceNode
//}

View File

@ -6,12 +6,18 @@ import TelegramCore
import SwiftSignalKit import SwiftSignalKit
import Photos import Photos
enum WallpaperListType {
case wallpapers(PresentationWallpaperMode?)
case colors
}
enum WallpaperListPreviewSource { enum WallpaperListPreviewSource {
case list(wallpapers: [TelegramWallpaper], central: TelegramWallpaper, mode: PresentationWallpaperMode?) case list(wallpapers: [TelegramWallpaper], central: TelegramWallpaper, type: WallpaperListType)
case slug(String, TelegramMediaFile?)
case wallpaper(TelegramWallpaper) case wallpaper(TelegramWallpaper)
case slug(String, TelegramMediaFile?)
case asset(PHAsset, UIImage?) case asset(PHAsset, UIImage?)
case contextResults(results: [ChatContextResult], central: ChatContextResult) case contextResult(ChatContextResult)
case customColor
} }
final class WallpaperListPreviewController: ViewController { final class WallpaperListPreviewController: ViewController {
@ -45,6 +51,7 @@ final class WallpaperListPreviewController: ViewController {
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData)) super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style
self.presentationDataDisposable = (account.telegramApplicationContext.presentationData self.presentationDataDisposable = (account.telegramApplicationContext.presentationData

View File

@ -48,7 +48,8 @@ private final class WallpaperBackgroundNode: ASDisplayNode {
private let statusNode: RadialStatusNode private let statusNode: RadialStatusNode
private let blurredNode: BlurredImageNode private let blurredNode: BlurredImageNode
let segmentedControlColor = Promise<UIColor>(.white) let controlsColor = Promise<UIColor>(.white)
let status = Promise<MediaResourceStatus>(.Local)
init(account: Account, wallpaper: WallpaperEntry) { init(account: Account, wallpaper: WallpaperEntry) {
self.wallpaper = wallpaper self.wallpaper = wallpaper
@ -133,7 +134,6 @@ private final class WallpaperBackgroundNode: ASDisplayNode {
signal = photoWallpaper(postbox: account.postbox, photoLibraryResource: PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: arc4random64())) signal = photoWallpaper(postbox: account.postbox, photoLibraryResource: PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: arc4random64()))
fetchSignal = .complete() fetchSignal = .complete()
statusSignal = .single(.Local) statusSignal = .single(.Local)
self.wrapperNode.addSubnode(self.cropNode) self.wrapperNode.addSubnode(self.cropNode)
case let .contextResult(result): case let .contextResult(result):
var imageDimensions: CGSize? var imageDimensions: CGSize?
@ -197,6 +197,7 @@ private final class WallpaperBackgroundNode: ASDisplayNode {
} }
self.wrapperNode.addSubnode(self.statusNode) self.wrapperNode.addSubnode(self.statusNode)
let imagePromise = Promise<UIImage?>()
self.imageNode.setSignal(signal, dispatchOnDisplayLink: false) self.imageNode.setSignal(signal, dispatchOnDisplayLink: false)
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))() self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))()
self.imageNode.imageUpdated = { [weak self] image in self.imageNode.imageUpdated = { [weak self] image in
@ -208,6 +209,7 @@ private final class WallpaperBackgroundNode: ASDisplayNode {
} }
} }
strongSelf.blurredNode.image = image strongSelf.blurredNode.image = image
imagePromise.set(.single(image))
} }
} }
self.fetchDisposable = fetchSignal.start() self.fetchDisposable = fetchSignal.start()
@ -230,13 +232,14 @@ private final class WallpaperBackgroundNode: ASDisplayNode {
} }
}) })
let segmentedControlColorSignal: Signal<UIColor, NoError> let controlsColorSignal: Signal<UIColor, NoError>
if case let .wallpaper(wallpaper) = wallpaper { if case let .wallpaper(wallpaper) = wallpaper {
segmentedControlColorSignal = chatBackgroundContrastColor(wallpaper: wallpaper, postbox: account.postbox) controlsColorSignal = chatBackgroundContrastColor(wallpaper: wallpaper, postbox: account.postbox)
} else { } else {
segmentedControlColorSignal = .complete() controlsColorSignal = backgroundContrastColor(for: imagePromise.get())
} }
self.segmentedControlColor.set(.single(.white) |> then(segmentedControlColorSignal)) self.controlsColor.set(.single(.white) |> then(controlsColorSignal))
self.status.set(statusSignal)
} }
deinit { deinit {
@ -340,6 +343,7 @@ private final class WallpaperBackgroundNode: ASDisplayNode {
final class WallpaperListPreviewControllerNode: ViewControllerTracingNode { final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
private let account: Account private let account: Account
private var presentationData: PresentationData private var presentationData: PresentationData
private let source: WallpaperListPreviewSource
private let dismiss: () -> Void private let dismiss: () -> Void
private let apply: (WallpaperEntry, PresentationWallpaperMode, CGRect?) -> Void private let apply: (WallpaperEntry, PresentationWallpaperMode, CGRect?) -> Void
@ -357,6 +361,9 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
private var segmentedControlColor = Promise<UIColor>(.white) private var segmentedControlColor = Promise<UIColor>(.white)
private var segmentedControlColorDisposable: Disposable? private var segmentedControlColorDisposable: Disposable?
private var status = Promise<MediaResourceStatus>(.Local)
private var statusDisposable: Disposable?
private var wallpapersDisposable: Disposable? private var wallpapersDisposable: Disposable?
private var wallpapers: [WallpaperEntry]? private var wallpapers: [WallpaperEntry]?
let ready = ValuePromise<Bool>(false) let ready = ValuePromise<Bool>(false)
@ -375,6 +382,7 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
init(account: Account, presentationData: PresentationData, source: WallpaperListPreviewSource, dismiss: @escaping () -> Void, apply: @escaping (WallpaperEntry, PresentationWallpaperMode, CGRect?) -> Void) { init(account: Account, presentationData: PresentationData, source: WallpaperListPreviewSource, dismiss: @escaping () -> Void, apply: @escaping (WallpaperEntry, PresentationWallpaperMode, CGRect?) -> Void) {
self.account = account self.account = account
self.presentationData = presentationData self.presentationData = presentationData
self.source = source
self.dismiss = dismiss self.dismiss = dismiss
self.apply = apply self.apply = apply
@ -459,13 +467,27 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
} }
}) })
self.statusDisposable = (self.status.get()
|> deliverOnMainQueue).start(next: { [weak self] status in
if let strongSelf = self {
switch status {
case .Local:
strongSelf.toolbarButtonApply.isEnabled = true
strongSelf.toolbarButtonApply.alpha = 1.0
default:
strongSelf.toolbarButtonApply.isEnabled = false
strongSelf.toolbarButtonApply.alpha = 0.3
}
}
})
switch source { switch source {
case let .list(wallpapers, central, mode): case let .list(wallpapers, central, type):
self.wallpapers = wallpapers.map { .wallpaper($0) } self.wallpapers = wallpapers.map { .wallpaper($0) }
self.centralWallpaper = WallpaperEntry.wallpaper(central) self.centralWallpaper = WallpaperEntry.wallpaper(central)
self.ready.set(true) self.ready.set(true)
if let mode = mode { if case let .wallpapers(wallpaperMode) = type, let mode = wallpaperMode {
self.segmentedControl.selectedSegmentIndex = Int(clamping: mode.rawValue) self.segmentedControl.selectedSegmentIndex = Int(clamping: mode.rawValue)
} }
case let .slug(slug, file): case let .slug(slug, file):
@ -485,9 +507,12 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
self.wallpapers = [entry] self.wallpapers = [entry]
self.centralWallpaper = entry self.centralWallpaper = entry
self.ready.set(true) self.ready.set(true)
case let .contextResults(results, central): case let .contextResult(result):
self.wallpapers = results.map { .contextResult($0) } let entry = WallpaperEntry.contextResult(result)
self.centralWallpaper = WallpaperEntry.contextResult(central) self.wallpapers = [entry]
self.centralWallpaper = entry
self.ready.set(true)
case .customColor:
self.ready.set(true) self.ready.set(true)
} }
if let (layout, navigationHeight) = self.validLayout { if let (layout, navigationHeight) = self.validLayout {
@ -500,6 +525,8 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
deinit { deinit {
self.wallpapersDisposable?.dispose() self.wallpapersDisposable?.dispose()
self.segmentedControlColorDisposable?.dispose()
self.statusDisposable?.dispose()
} }
override func didLoad() { override func didLoad() {
@ -577,9 +604,32 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
let chatPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper), fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: false) let chatPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper), fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: false)
items.append(ChatMessageItem(presentationData: chatPresentationData, account: self.account, chatLocation: .peer(peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false), controllerInteraction: controllerInteraction, content: .message(message: Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: presentationData.strings.WallpaperPreview_MessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), read: true, selection: .none, isAdmin: false), disableDate: true)) let topMessageText: String = ""
let bottomMessageText: String = ""
// switch self.source {
// case .wallpaper, .slug:
// topMessageText = presentationData.strings.WallpaperPreview_PreviewTopText
// bottomMessageText = presentationData.strings.WallpaperPreview_PreviewBottomText
// case let .list(_, _, type):
// switch type {
// case .wallpapers:
// topMessageText = presentationData.strings.WallpaperPreview_SwipeTopText
// bottomMessageText = presentationData.strings.WallpaperPreview_SwipeBottomText
// case .colors:
// topMessageText = presentationData.strings.WallpaperPreview_SwipeColorsTopText
// bottomMessageText = presentationData.strings.WallpaperPreview_SwipeColorsBottomText
// }
// case .asset, .contextResult:
// topMessageText = presentationData.strings.WallpaperPreview_CropTopText
// bottomMessageText = presentationData.strings.WallpaperPreview_CropBottomText
// case .customColor:
// topMessageText = presentationData.strings.WallpaperPreview_CustomColorTopText
// bottomMessageText = presentationData.strings.WallpaperPreview_CustomColorBottomText
// }
items.append(ChatMessageItem(presentationData: chatPresentationData, account: self.account, chatLocation: .peer(peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false), controllerInteraction: controllerInteraction, content: .message(message: Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: presentationData.strings.WallpaperPreview_SwipeInfo, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), read: true, selection: .none, isAdmin: false), disableDate: true)) items.append(ChatMessageItem(presentationData: chatPresentationData, account: self.account, chatLocation: .peer(peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false), controllerInteraction: controllerInteraction, content: .message(message: Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), read: true, selection: .none, isAdmin: false), disableDate: true))
items.append(ChatMessageItem(presentationData: chatPresentationData, account: self.account, chatLocation: .peer(peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false), controllerInteraction: controllerInteraction, content: .message(message: Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), read: true, selection: .none, isAdmin: false), disableDate: true))
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right) let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right)
if let messageNodes = self.messageNodes { if let messageNodes = self.messageNodes {
@ -687,7 +737,8 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
} }
if j == i { if j == i {
self.segmentedControlColor.set(itemNode.segmentedControlColor.get()) self.segmentedControlColor.set(itemNode.controlsColor.get())
self.status.set(itemNode.status.get())
} }
itemNodeTransition.updateFrame(node: itemNode, frame: itemFrame) itemNodeTransition.updateFrame(node: itemNode, frame: itemFrame)

View File

@ -28,7 +28,7 @@ func requestContextResults(account: Account, botId: PeerId, query: String, peerI
collection = results collection = results
} }
if let collection = collection, collection.results.count < limit, let nextOffset = collection.nextOffset { if let collection = collection, collection.results.count < limit, let nextOffset = collection.nextOffset {
let nextResults = requestContextResults(account: account, botId: botId, query: query, peerId: peerId, offset: nextOffset, existingResults: collection) let nextResults = requestContextResults(account: account, botId: botId, query: query, peerId: peerId, offset: nextOffset, existingResults: collection, limit: limit)
if collection.results.count > 10 { if collection.results.count > 10 {
return .single(collection) return .single(collection)
|> then(nextResults) |> then(nextResults)

View File

@ -86,6 +86,8 @@ final class WebSearchItemNode: GridItemNode {
var thumbnailResource: TelegramMediaResource? var thumbnailResource: TelegramMediaResource?
var imageResource: TelegramMediaResource? var imageResource: TelegramMediaResource?
var imageDimensions: CGSize? var imageDimensions: CGSize?
var immediateThumbnailData: Data?
switch item.result { switch item.result {
case let .externalReference(_, _, type, _, _, _, content, thumbnail, _): case let .externalReference(_, _, type, _, _, _, content, thumbnail, _):
if let content = content, type != "gif" { if let content = content, type != "gif" {
@ -96,6 +98,7 @@ final class WebSearchItemNode: GridItemNode {
imageDimensions = content?.dimensions imageDimensions = content?.dimensions
case let .internalReference(_, _, _, _, _, image, file, _): case let .internalReference(_, _, _, _, _, image, file, _):
if let image = image { if let image = image {
immediateThumbnailData = image.immediateThumbnailData
if let largestRepresentation = largestImageRepresentation(image.representations) { if let largestRepresentation = largestImageRepresentation(image.representations) {
imageDimensions = largestRepresentation.dimensions imageDimensions = largestRepresentation.dimensions
} }
@ -112,6 +115,7 @@ final class WebSearchItemNode: GridItemNode {
} }
} }
} else if let file = file { } else if let file = file {
immediateThumbnailData = file.immediateThumbnailData
if let dimensions = file.dimensions { if let dimensions = file.dimensions {
imageDimensions = dimensions imageDimensions = dimensions
} else if let largestRepresentation = largestImageRepresentation(file.previewRepresentations) { } else if let largestRepresentation = largestImageRepresentation(file.previewRepresentations) {
@ -129,7 +133,7 @@ final class WebSearchItemNode: GridItemNode {
representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource)) representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource))
} }
if !representations.isEmpty { if !representations.isEmpty {
let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil) let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil)
updateImageSignal = mediaGridMessagePhoto(account: item.account, photoReference: .standalone(media: tmpImage)) updateImageSignal = mediaGridMessagePhoto(account: item.account, photoReference: .standalone(media: tmpImage))
} else { } else {
updateImageSignal = .complete() updateImageSignal = .complete()