Postbox refactor waves 278-356: squash

Squashes 79 sequential refactor waves into a single commit.

Highlights:
- Drop `import Postbox` (and matching `//submodules/Postbox` BUILD deps) from a wide swath of consumer files: ChatList, ChatMessage*BubbleContentNode subclasses, ListMessageNode/ListMessageItem, GalleryData, ChatHistorySearchContainerNode, ChatPanelInterfaceInteraction, ChatControllerInteraction, ChatMessageStickerItemNode, ChatMessageReplyInfoNode, ChatMessageInstantVideoItemNode, ChatPresentationInterfaceState, BrowserMarkdown/Readability, MediaResources, LocalMediaResources, ICloudResources, FetchManager, ShareController, OpenChatMessage, GalleryController, GroupStickerSearchContainerNode, GroupStickerPackCurrentItem, ChatPinnedMessageTitlePanelNode, OverlayAudioPlayerController, PresentationThemeSettings, StatisticsUI/StoryIconNode, TextFormat/StringWithAppliedEntities, GalleryUI/VideoAdComponent, StickerPackPreviewUI, WallpaperPreviewMedia, WallpaperResources, YoutubeEmbedImplementation, InstantPageExternalMediaResource, PlatformRestrictionMatching, TelegramUIDeclareEncodables, ChatListNode/ChatListSearchContainerNode.
- Add `TelegramEngine` facades: `Themes.wallpapers`, `Themes.themes`, `AccountData.addAppLogEvent`.
- Add `EngineMessageHistoryEntryLocation` wrapper.
- Add `EngineRaw*` escape-hatch typealiases (`EngineRawMessage`, `EngineRawPeer`, `EngineRawMedia`, `EngineRawMediaResource`, `EngineRawMediaResourceData`, `EngineRawItemCollectionItem`, `EngineRawItemCollectionInfo`) and `engineDeclareEncodable` forwarder.
- Drop unused `account:`/`postbox:`/`network:` parameters from several public functions and delete the dead overloads/types/functions left over: `automaticThemeShouldSwitchNow`, `cancelFreeMediaFileInteractiveFetch`, `legacyEnqueueVideoMessage`, `TelegramMediaFileReference`, plus assorted dead public TelegramCore/AccountContext SecureId entry points.
- Delete entire dead modules: `LegacyDataImport`, `TonBinding`, `SpotlightSupport`, `SvgRendering`, third-party `AppCenter`/`VectorPlus`/`SwiftColor`/`SwiftSVG`.
- Drop orphan `//submodules/Postbox` BUILD deps across 3 cleanup rounds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
isaac 2026-05-05 14:11:06 +02:00
parent ea0f6a685c
commit e918b353ec
252 changed files with 829 additions and 11680 deletions

View file

@ -1,5 +1,4 @@
import Foundation
import Postbox
import TelegramCore
import SwiftSignalKit
import TelegramUIPreferences
@ -13,7 +12,7 @@ public enum FetchManagerCategory: Int32 {
}
public enum FetchManagerLocationKey: Comparable, Hashable {
case messageId(MessageId)
case messageId(EngineMessage.Id)
case free
public static func <(lhs: FetchManagerLocationKey, rhs: FetchManagerLocationKey) -> Bool {
@ -87,7 +86,7 @@ public struct FetchManagerPriorityKey: Comparable {
}
public enum FetchManagerLocation: Hashable, CustomStringConvertible {
case chat(PeerId)
case chat(EnginePeer.Id)
public var description: String {
switch self {
@ -104,8 +103,8 @@ public enum FetchManagerForegroundDirection {
public enum FetchManagerPriority: Comparable {
case userInitiated
case foregroundPrefetch(direction: FetchManagerForegroundDirection, localOrder: MessageIndex)
case backgroundPrefetch(locationOrder: HistoryPreloadIndex, localOrder: MessageIndex)
case foregroundPrefetch(direction: FetchManagerForegroundDirection, localOrder: EngineMessage.Index)
case backgroundPrefetch(locationOrder: HistoryPreloadIndex, localOrder: EngineMessage.Index)
public static func <(lhs: FetchManagerPriority, rhs: FetchManagerPriority) -> Bool {
switch lhs {
@ -160,11 +159,11 @@ public protocol FetchManager {
var queue: Queue { get }
func interactivelyFetched(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, mediaReference: AnyMediaReference?, resourceReference: MediaResourceReference, ranges: RangeSet<Int64>, statsCategory: MediaResourceStatsCategory, elevatedPriority: Bool, userInitiated: Bool, priority: FetchManagerPriority, storeToDownloadsPeerId: EnginePeer.Id?) -> Signal<Void, NoError>
func cancelInteractiveFetches(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: MediaResource)
func cancelInteractiveFetches(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: EngineRawMediaResource)
func cancelInteractiveFetches(resourceId: String)
func toggleInteractiveFetchPaused(resourceId: String, isPaused: Bool)
func raisePriority(resourceId: String)
func fetchStatus(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: MediaResource) -> Signal<MediaResourceStatus, NoError>
func fetchStatus(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: EngineRawMediaResource) -> Signal<EngineMediaResourceStatus, NoError>
}
public protocol PrefetchManager {

View file

@ -24,10 +24,6 @@ public func freeMediaFileResourceInteractiveFetched(postbox: Postbox, userLocati
return fetchedMediaResource(mediaBox: postbox.mediaBox, userLocation: userLocation, userContentType: MediaResourceUserContentType(file: fileReference.media), reference: fileReference.resourceReference(resource), range: range)
}
public func cancelFreeMediaFileInteractiveFetch(account: Account, file: TelegramMediaFile) {
account.postbox.mediaBox.cancelInteractiveResourceFetch(file.resource)
}
private func fetchCategoryForFile(_ file: TelegramMediaFile) -> FetchManagerCategory {
if file.isVoice || file.isInstantVideo {
return .voice

View file

@ -1,7 +1,6 @@
import Foundation
import UIKit
import Display
import Postbox
import SwiftSignalKit
import TelegramCore
@ -10,13 +9,13 @@ public enum GalleryMediaSubject: Hashable {
case pollDescription
case pollOption(Data)
case pollSolution
case instantPageMedia(MediaId)
case instantPageMedia(EngineMedia.Id)
}
public enum GalleryControllerItemSource {
case peerMessagesAtId(messageId: MessageId, chatLocation: ChatLocation, customTag: MemoryBuffer?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>)
case standaloneMessage(Message, GalleryMediaSubject?)
case custom(messages: Signal<([Message], Int32, Bool), NoError>, messageId: MessageId, loadMore: (() -> Void)?)
case peerMessagesAtId(messageId: EngineMessage.Id, chatLocation: ChatLocation, customTag: EngineMemoryBuffer?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>)
case standaloneMessage(EngineRawMessage, GalleryMediaSubject?)
case custom(messages: Signal<([EngineRawMessage], Int32, Bool), NoError>, messageId: EngineMessage.Id, loadMore: (() -> Void)?)
}
public final class GalleryControllerActionInteraction {
@ -26,10 +25,10 @@ public final class GalleryControllerActionInteraction {
public let openPeer: (EnginePeer) -> Void
public let openHashtag: (String?, String) -> Void
public let openBotCommand: (String) -> Void
public let openAd: (MessageId) -> Void
public let openAd: (EngineMessage.Id) -> Void
public let addContact: (String) -> Void
public let storeMediaPlaybackState: (MessageId, Double?, Double) -> Void
public let editMedia: (MessageId, [UIView], @escaping () -> Void) -> Void
public let storeMediaPlaybackState: (EngineMessage.Id, Double?, Double) -> Void
public let editMedia: (EngineMessage.Id, [UIView], @escaping () -> Void) -> Void
public let updateCanReadHistory: (Bool) -> Void
public let sendSticker: ((FileMediaReference) -> Void)?
@ -40,10 +39,10 @@ public final class GalleryControllerActionInteraction {
openPeer: @escaping (EnginePeer) -> Void,
openHashtag: @escaping (String?, String) -> Void,
openBotCommand: @escaping (String) -> Void,
openAd: @escaping (MessageId) -> Void,
openAd: @escaping (EngineMessage.Id) -> Void,
addContact: @escaping (String) -> Void,
storeMediaPlaybackState: @escaping (MessageId, Double?, Double) -> Void,
editMedia: @escaping (MessageId, [UIView], @escaping () -> Void) -> Void,
storeMediaPlaybackState: @escaping (EngineMessage.Id, Double?, Double) -> Void,
editMedia: @escaping (EngineMessage.Id, [UIView], @escaping () -> Void) -> Void,
updateCanReadHistory: @escaping (Bool) -> Void,
sendSticker: ((FileMediaReference) -> Void)?
) {

View file

@ -1,6 +1,5 @@
import Foundation
import UIKit
import Postbox
import TelegramCore
import SwiftSignalKit
import Display
@ -22,9 +21,9 @@ public final class OpenChatMessageParams {
public let context: AccountContext
public let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
public let chatLocation: ChatLocation?
public let chatFilterTag: MemoryBuffer?
public let chatFilterTag: EngineMemoryBuffer?
public let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>?
public let message: Message
public let message: EngineRawMessage
public let mediaSubject: GalleryMediaSubject?
public let standalone: Bool
public let copyProtected: Bool
@ -34,21 +33,21 @@ public final class OpenChatMessageParams {
public let modal: Bool
public let dismissInput: () -> Void
public let present: (ViewController, Any?, PresentationContextType) -> Void
public let transitionNode: (MessageId, Media, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
public let transitionNode: (EngineMessage.Id, EngineRawMedia, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
public let addToTransitionSurface: (UIView) -> Void
public let openUrl: (String) -> Void
public let openPeer: (Peer, ChatControllerInteractionNavigateToPeer) -> Void
public let callPeer: (PeerId, Bool) -> Void
public let openConferenceCall: (Message) -> Void
public let openPeer: (EngineRawPeer, ChatControllerInteractionNavigateToPeer) -> Void
public let callPeer: (EnginePeer.Id, Bool) -> Void
public let openConferenceCall: (EngineRawMessage) -> Void
public let enqueueMessage: (EnqueueMessage) -> Void
public let sendSticker: ((FileMediaReference, UIView?, CGRect?) -> Bool)?
public let sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)?
public let setupTemporaryHiddenMedia: (Signal<Any?, NoError>, Int, Media) -> Void
public let chatAvatarHiddenMedia: (Signal<MessageId?, NoError>, Media) -> Void
public let setupTemporaryHiddenMedia: (Signal<Any?, NoError>, Int, EngineRawMedia) -> Void
public let chatAvatarHiddenMedia: (Signal<EngineMessage.Id?, NoError>, EngineRawMedia) -> Void
public let actionInteraction: GalleryControllerActionInteraction?
public let playlistLocation: PeerMessagesPlaylistLocation?
public let gallerySource: GalleryControllerItemSource?
public let centralItemUpdated: ((MessageId) -> Void)?
public let centralItemUpdated: ((EngineMessage.Id) -> Void)?
public let navigateToMessageContext: ((EngineMessage) -> Void)?
public let getSourceRect: (() -> CGRect?)?
public let blockInteraction: Promise<Bool>
@ -57,9 +56,9 @@ public final class OpenChatMessageParams {
context: AccountContext,
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
chatLocation: ChatLocation?,
chatFilterTag: MemoryBuffer?,
chatFilterTag: EngineMemoryBuffer?,
chatLocationContextHolder: Atomic<ChatLocationContextHolder?>?,
message: Message,
message: EngineRawMessage,
mediaSubject: GalleryMediaSubject? = nil,
standalone: Bool,
copyProtected: Bool = false,
@ -69,21 +68,21 @@ public final class OpenChatMessageParams {
modal: Bool = false,
dismissInput: @escaping () -> Void,
present: @escaping (ViewController, Any?, PresentationContextType) -> Void,
transitionNode: @escaping (MessageId, Media, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?,
transitionNode: @escaping (EngineMessage.Id, EngineRawMedia, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?,
addToTransitionSurface: @escaping (UIView) -> Void,
openUrl: @escaping (String) -> Void,
openPeer: @escaping (Peer, ChatControllerInteractionNavigateToPeer) -> Void,
callPeer: @escaping (PeerId, Bool) -> Void,
openConferenceCall: @escaping (Message) -> Void,
openPeer: @escaping (EngineRawPeer, ChatControllerInteractionNavigateToPeer) -> Void,
callPeer: @escaping (EnginePeer.Id, Bool) -> Void,
openConferenceCall: @escaping (EngineRawMessage) -> Void,
enqueueMessage: @escaping (EnqueueMessage) -> Void,
sendSticker: ((FileMediaReference, UIView?, CGRect?) -> Bool)?,
sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)?,
setupTemporaryHiddenMedia: @escaping (Signal<Any?, NoError>, Int, Media) -> Void,
chatAvatarHiddenMedia: @escaping (Signal<MessageId?, NoError>, Media) -> Void,
setupTemporaryHiddenMedia: @escaping (Signal<Any?, NoError>, Int, EngineRawMedia) -> Void,
chatAvatarHiddenMedia: @escaping (Signal<EngineMessage.Id?, NoError>, EngineRawMedia) -> Void,
actionInteraction: GalleryControllerActionInteraction? = nil,
playlistLocation: PeerMessagesPlaylistLocation? = nil,
gallerySource: GalleryControllerItemSource? = nil,
centralItemUpdated: ((MessageId) -> Void)? = nil,
centralItemUpdated: ((EngineMessage.Id) -> Void)? = nil,
navigateToMessageContext: ((EngineMessage) -> Void)? = nil,
getSourceRect: (() -> CGRect?)? = nil
) {

View file

@ -2,7 +2,6 @@ import Foundation
import Display
import SwiftSignalKit
import TelegramCore
import Postbox
import TelegramPresentationData
import AnimationCache
import MultiAnimationRenderer
@ -125,39 +124,6 @@ public enum AttachmentTextInputPanelSendMode {
case whenOnline
}
public enum PeerSelectionControllerContext {
public final class Custom {
public let accountPeerId: EnginePeer.Id
public let postbox: Postbox
public let network: Network
public let animationCache: AnimationCache
public let animationRenderer: MultiAnimationRenderer
public let presentationData: PresentationData
public let updatedPresentationData: Signal<PresentationData, NoError>
public init(
accountPeerId: EnginePeer.Id,
postbox: Postbox,
network: Network,
animationCache: AnimationCache,
animationRenderer: MultiAnimationRenderer,
presentationData: PresentationData,
updatedPresentationData: Signal<PresentationData, NoError>
) {
self.accountPeerId = accountPeerId
self.postbox = postbox
self.network = network
self.animationCache = animationCache
self.animationRenderer = animationRenderer
self.presentationData = presentationData
self.updatedPresentationData = updatedPresentationData
}
}
case account(AccountContext)
case custom(Custom)
}
public protocol PeerSelectionController: ViewController {
var peerSelected: ((EnginePeer, Int64?) -> Void)? { get set }
var multiplePeersSelected: (([EnginePeer], [EnginePeer.Id: EnginePeer], NSAttributedString, AttachmentTextInputPanelSendMode, ChatInterfaceForwardOptionsState?, ChatSendMessageActionSheetController.SendParameters?) -> Void)? { get set }

View file

@ -309,22 +309,6 @@ public struct PresentationGroupCallSummaryState: Equatable {
}
}
public struct PresentationGroupCallMemberState: Equatable {
public var ssrc: UInt32
public var muteState: GroupCallParticipantsContext.Participant.MuteState?
public var speaking: Bool
public init(
ssrc: UInt32,
muteState: GroupCallParticipantsContext.Participant.MuteState?,
speaking: Bool
) {
self.ssrc = ssrc
self.muteState = muteState
self.speaking = speaking
}
}
public enum PresentationGroupCallMuteAction: Equatable {
case muted(isPushToTalkActive: Bool)
case unmuted

View file

@ -1,6 +1,5 @@
import Foundation
import SwiftSignalKit
import Postbox
import TelegramCore
import TelegramPresentationData
import TelegramUIPreferences
@ -9,7 +8,7 @@ import MultiAnimationRenderer
import Display
public enum StorySharingSubject {
case messages([Message])
case messages([EngineRawMessage])
case gift(StarGift.UniqueGift)
}
@ -110,11 +109,11 @@ public enum ShareControllerSubject {
case url(String)
case text(String)
case quote(text: String, url: String)
case messages([Message])
case messages([EngineRawMessage])
case image([ImageRepresentationWithReference])
case media(AnyMediaReference, MediaParameters?)
case mapMedia(TelegramMediaMap)
case fromExternal(Int, ([PeerId], [PeerId: Int64], [PeerId: StarsAmount], String, ShareControllerAccountContext, Bool) -> Signal<ShareControllerExternalStatus, ShareControllerError>)
case fromExternal(Int, ([EnginePeer.Id], [EnginePeer.Id: Int64], [EnginePeer.Id: StarsAmount], String, ShareControllerAccountContext, Bool) -> Signal<ShareControllerExternalStatus, ShareControllerError>)
}
public struct ShareControllerAction {
@ -151,12 +150,12 @@ public final class ShareControllerParams {
public let subject: ShareControllerSubject
public let presetText: String?
public let preferredAction: ShareControllerPreferredAction
public let showInChat: ((Message) -> Void)?
public let showInChat: ((EngineRawMessage) -> Void)?
public let fromForeignApp: Bool
public let segmentedValues: [ShareControllerSegmentedValue]?
public let externalShare: Bool
public let immediateExternalShare: Bool
public let immediatePeerId: PeerId?
public let immediatePeerId: EnginePeer.Id?
public let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
public let forceTheme: PresentationTheme?
public let forcedActionTitle: String?
@ -165,8 +164,8 @@ public final class ShareControllerParams {
public let actionCompleted: (() -> Void)?
public let dismissed: ((Bool) -> Void)?
public let completed: (([PeerId]) -> Void)?
public let enqueued: (([PeerId], [Int64]) -> Void)?
public let completed: (([EnginePeer.Id]) -> Void)?
public let enqueued: (([EnginePeer.Id], [Int64]) -> Void)?
public let shareStory: (() -> Void)?
public let debugAction: (() -> Void)?
public let onMediaTimestampLinkCopied: ((Int32?) -> Void)?
@ -177,12 +176,12 @@ public final class ShareControllerParams {
subject: ShareControllerSubject,
presetText: String? = nil,
preferredAction: ShareControllerPreferredAction = .default,
showInChat: ((Message) -> Void)? = nil,
showInChat: ((EngineRawMessage) -> Void)? = nil,
fromForeignApp: Bool = false,
segmentedValues: [ShareControllerSegmentedValue]? = nil,
externalShare: Bool = true,
immediateExternalShare: Bool = false,
immediatePeerId: PeerId? = nil,
immediatePeerId: EnginePeer.Id? = nil,
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
forceTheme: PresentationTheme? = nil,
forcedActionTitle: String? = nil,
@ -190,8 +189,8 @@ public final class ShareControllerParams {
collectibleItemInfo: TelegramCollectibleItemInfo? = nil,
actionCompleted: (() -> Void)? = nil,
dismissed: ((Bool) -> Void)? = nil,
completed: (([PeerId]) -> Void)? = nil,
enqueued: (([PeerId], [Int64]) -> Void)? = nil,
completed: (([EnginePeer.Id]) -> Void)? = nil,
enqueued: (([EnginePeer.Id], [Int64]) -> Void)? = nil,
shareStory: (() -> Void)? = nil,
debugAction: (() -> Void)? = nil,
onMediaTimestampLinkCopied: ((Int32?) -> Void)? = nil,

View file

@ -12,7 +12,6 @@ swift_library(
deps = [
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/TelegramCore:TelegramCore",
"//submodules/Postbox:Postbox",
"//submodules/Display:Display",
"//submodules/SSignalKit/SSignalKit",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",

View file

@ -643,7 +643,7 @@ public final class AvatarNode: ASDisplayNode {
let parameters: AvatarNodeParameters
if let peer = peer, let signal = peerAvatarImage(postbox: postbox, network: network, peerReference: PeerReference(peer), authorOfMessage: authorOfMessage, representation: representation, displayDimensions: displayDimensions, clipStyle: clipStyle, emptyColor: emptyColor, synchronousLoad: synchronousLoad, provideUnrounded: storeUnrounded, cutoutRect: cutoutRect) {
if let peer = peer, let signal = peerAvatarImage(postbox: postbox, peerReference: PeerReference(peer), authorOfMessage: authorOfMessage, representation: representation, displayDimensions: displayDimensions, clipStyle: clipStyle, emptyColor: emptyColor, synchronousLoad: synchronousLoad, provideUnrounded: storeUnrounded, cutoutRect: cutoutRect) {
self.contents = nil
self.displaySuspended = true
self.imageReady.set(self.imageNode.contentReady)

View file

@ -27,11 +27,7 @@ public enum PeerAvatarImageType {
case complete
}
public func peerAvatarImageData(account: Account, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, synchronousLoad: Bool) -> Signal<(Data, PeerAvatarImageType)?, NoError>? {
return peerAvatarImageData(postbox: account.postbox, network: account.network, peerReference: peerReference, authorOfMessage: authorOfMessage, representation: representation, synchronousLoad: synchronousLoad)
}
public func peerAvatarImageData(postbox: Postbox, network: Network, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, synchronousLoad: Bool) -> Signal<(Data, PeerAvatarImageType)?, NoError>? {
public func peerAvatarImageData(postbox: Postbox, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, synchronousLoad: Bool) -> Signal<(Data, PeerAvatarImageType)?, NoError>? {
if let smallProfileImage = representation {
let resourceData = postbox.mediaBox.resourceData(smallProfileImage.resource, attemptSynchronously: synchronousLoad)
let imageData = resourceData
@ -92,7 +88,6 @@ public func peerAvatarImageData(postbox: Postbox, network: Network, peerReferenc
public func peerAvatarCompleteImage(account: Account, peer: EnginePeer, forceProvidedRepresentation: Bool = false, representation: TelegramMediaImageRepresentation? = nil, size: CGSize, round: Bool = true, font: UIFont = avatarPlaceholderFont(size: 13.0), drawLetters: Bool = true, fullSize: Bool = false, blurred: Bool = false) -> Signal<UIImage?, NoError> {
return peerAvatarCompleteImage(
postbox: account.postbox,
network: account.network,
peer: peer,
forceProvidedRepresentation: forceProvidedRepresentation,
representation: representation,
@ -105,7 +100,7 @@ public func peerAvatarCompleteImage(account: Account, peer: EnginePeer, forcePro
)
}
public func peerAvatarCompleteImage(postbox: Postbox, network: Network, peer: EnginePeer, forceProvidedRepresentation: Bool = false, representation: TelegramMediaImageRepresentation? = nil, size: CGSize, round: Bool = true, font: UIFont = avatarPlaceholderFont(size: 13.0), drawLetters: Bool = true, fullSize: Bool = false, blurred: Bool = false) -> Signal<UIImage?, NoError> {
public func peerAvatarCompleteImage(postbox: Postbox, peer: EnginePeer, forceProvidedRepresentation: Bool = false, representation: TelegramMediaImageRepresentation? = nil, size: CGSize, round: Bool = true, font: UIFont = avatarPlaceholderFont(size: 13.0), drawLetters: Bool = true, fullSize: Bool = false, blurred: Bool = false) -> Signal<UIImage?, NoError> {
let iconSignal: Signal<UIImage?, NoError>
let clipStyle: AvatarNodeClipStyle
@ -126,8 +121,8 @@ public func peerAvatarCompleteImage(postbox: Postbox, network: Network, peer: En
thumbnailRepresentation = peer.profileImageRepresentations.first
}
if let signal = peerAvatarImage(postbox: postbox, network: network, peerReference: PeerReference(peer), authorOfMessage: nil, representation: thumbnailRepresentation, displayDimensions: size, clipStyle: clipStyle, blurred: blurred, inset: 0.0, emptyColor: nil, synchronousLoad: fullSize) {
if fullSize, let fullSizeSignal = peerAvatarImage(postbox: postbox, network: network, peerReference: PeerReference(peer), authorOfMessage: nil, representation: peer.profileImageRepresentations.last, displayDimensions: size, emptyColor: nil, synchronousLoad: true) {
if let signal = peerAvatarImage(postbox: postbox, peerReference: PeerReference(peer), authorOfMessage: nil,representation: thumbnailRepresentation, displayDimensions: size, clipStyle: clipStyle, blurred: blurred, inset: 0.0, emptyColor: nil, synchronousLoad: fullSize) {
if fullSize, let fullSizeSignal = peerAvatarImage(postbox: postbox, peerReference: PeerReference(peer), authorOfMessage: nil,representation: peer.profileImageRepresentations.last, displayDimensions: size, emptyColor: nil, synchronousLoad: true) {
iconSignal = combineLatest(.single(nil) |> then(signal), .single(nil) |> then(fullSizeSignal))
|> mapToSignal { thumbnailImage, fullSizeImage -> Signal<UIImage?, NoError> in
if let fullSizeImage = fullSizeImage {
@ -174,7 +169,6 @@ public func peerAvatarCompleteImage(postbox: Postbox, network: Network, peer: En
public func peerAvatarImage(account: Account, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0), clipStyle: AvatarNodeClipStyle = .round, blurred: Bool = false, inset: CGFloat = 0.0, emptyColor: UIColor? = nil, synchronousLoad: Bool = false, provideUnrounded: Bool = false, cutoutRect: CGRect? = nil) -> Signal<(UIImage, UIImage)?, NoError>? {
return peerAvatarImage(
postbox: account.postbox,
network: account.network,
peerReference: peerReference,
authorOfMessage: authorOfMessage,
representation: representation,
@ -189,8 +183,8 @@ public func peerAvatarImage(account: Account, peerReference: PeerReference?, aut
)
}
public func peerAvatarImage(postbox: Postbox, network: Network, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0), clipStyle: AvatarNodeClipStyle = .round, blurred: Bool = false, inset: CGFloat = 0.0, emptyColor: UIColor? = nil, synchronousLoad: Bool = false, provideUnrounded: Bool = false, cutoutRect: CGRect? = nil) -> Signal<(UIImage, UIImage)?, NoError>? {
if let imageData = peerAvatarImageData(postbox: postbox, network: network, peerReference: peerReference, authorOfMessage: authorOfMessage, representation: representation, synchronousLoad: synchronousLoad) {
public func peerAvatarImage(postbox: Postbox, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0), clipStyle: AvatarNodeClipStyle = .round, blurred: Bool = false, inset: CGFloat = 0.0, emptyColor: UIColor? = nil, synchronousLoad: Bool = false, provideUnrounded: Bool = false, cutoutRect: CGRect? = nil) -> Signal<(UIImage, UIImage)?, NoError>? {
if let imageData = peerAvatarImageData(postbox: postbox, peerReference: peerReference, authorOfMessage: authorOfMessage, representation: representation, synchronousLoad: synchronousLoad) {
return imageData
|> mapToSignal { data -> Signal<(UIImage, UIImage)?, NoError> in
let generate = deferred { () -> Signal<(UIImage, UIImage)?, NoError> in

View file

@ -1,6 +1,5 @@
import Foundation
import UIKit
import Postbox
import TelegramCore
import AccountContext
import InstantPageUI
@ -211,7 +210,7 @@ private final class MarkdownConversionBudget {
private struct MarkdownPageResult {
let blocks: [InstantPageBlock]
let media: [MediaId: Media]
let media: [EngineMedia.Id: EngineRawMedia]
}
private enum MarkdownFormulaMode {
@ -315,7 +314,7 @@ private struct MarkdownInlineContent {
}
private struct MarkdownResolvedImage {
let mediaId: MediaId
let mediaId: EngineMedia.Id
let inlineDimensions: PixelDimensions
let caption: InstantPageCaption
let linkUrl: String?
@ -340,7 +339,7 @@ private final class MarkdownConversionContext {
private var nextRemoteMediaId: Int64 = 0
private var nextLocalMediaId: Int64 = 0
private(set) var media: [MediaId: Media] = [:]
private(set) var media: [EngineMedia.Id: EngineRawMedia] = [:]
init(context: AccountContext, documentURL: URL, formulasByPlaceholder: [String: MarkdownFormulaDescriptor], budget: MarkdownConversionBudget) {
self.context = context
@ -426,14 +425,14 @@ private final class MarkdownConversionContext {
}
}
private func nextMediaId(namespace: Int32) -> MediaId {
private func nextMediaId(namespace: Int32) -> EngineMedia.Id {
switch namespace {
case Namespaces.Media.LocalImage:
self.nextLocalMediaId += 1
return MediaId(namespace: namespace, id: self.nextLocalMediaId)
return EngineMedia.Id(namespace: namespace, id: self.nextLocalMediaId)
default:
self.nextRemoteMediaId += 1
return MediaId(namespace: namespace, id: self.nextRemoteMediaId)
return EngineMedia.Id(namespace: namespace, id: self.nextRemoteMediaId)
}
}
}
@ -1028,7 +1027,7 @@ private func markdownWebpage(context: AccountContext, file: FileMediaReference,
)
return TelegramMediaWebpage(
webpageId: MediaId(namespace: 0, id: 0),
webpageId: EngineMedia.Id(namespace: 0, id: 0),
content: .Loaded(
TelegramMediaWebpageLoadedContent(
url: fileURL.absoluteString,

View file

@ -1,7 +1,6 @@
import Foundation
import WebKit
import AppBundle
import Postbox
import TelegramCore
import InstantPageUI
@ -115,14 +114,14 @@ private func parseJson(_ input: [String: Any], url: String) -> TelegramMediaWebp
let byline = input["byline"] as? String
let excerpt = input["excerpt"] as? String
var media: [MediaId: Media] = [:]
var media: [EngineMedia.Id: EngineRawMedia] = [:]
let blocks = parseContent(input, url, &media)
guard !blocks.isEmpty else {
return nil
}
return TelegramMediaWebpage(
webpageId: MediaId(namespace: 0, id: 0),
webpageId: EngineMedia.Id(namespace: 0, id: 0),
content: .Loaded(
TelegramMediaWebpageLoadedContent(
url: url,
@ -156,7 +155,7 @@ private func parseJson(_ input: [String: Any], url: String) -> TelegramMediaWebp
)
}
private func parseContent(_ input: [String: Any], _ url: String, _ media: inout [MediaId: Media]) -> [InstantPageBlock] {
private func parseContent(_ input: [String: Any], _ url: String, _ media: inout [EngineMedia.Id: EngineRawMedia]) -> [InstantPageBlock] {
let title = input["title"] as? String
let byline = input["byline"] as? String
let date = input["publishedTime"] as? String
@ -185,7 +184,7 @@ private func parseRichText(_ input: String) -> RichText {
return .plain(input)
}
private func parseRichText(_ input: [String: Any], _ media: inout [MediaId: Media]) -> RichText {
private func parseRichText(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> RichText {
var text: RichText
if let string = input["content"] as? String {
text = parseRichText(string)
@ -204,7 +203,7 @@ private func parseRichText(_ input: [String: Any], _ media: inout [MediaId: Medi
return text
}
private func parseRichText(_ input: [Any], _ media: inout [MediaId: Media]) -> RichText {
private func parseRichText(_ input: [Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> RichText {
var result: [RichText] = []
for item in input {
@ -258,7 +257,7 @@ private func parseRichText(_ input: [Any], _ media: inout [MediaId: Media]) -> R
} else {
height = 0
}
let id = MediaId(namespace: Namespaces.Media.CloudFile, id: Int64(media.count))
let id = EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: Int64(media.count))
media[id] = TelegramMediaImage(
imageId: id,
representations: [
@ -489,7 +488,7 @@ private func applyAnchor(_ input: RichText, item: [String: Any]) -> RichText {
return .anchor(text: input, name: id)
}
private func parseTable(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageBlock {
private func parseTable(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock {
let title = (input["title"] as? String) ?? ""
return .table(
title: trim(applyAnchor(parseRichText(title), item: input)),
@ -499,7 +498,7 @@ private func parseTable(_ input: [String: Any], _ media: inout [MediaId: Media])
)
}
private func parseTableRows(_ input: [Any], _ media: inout [MediaId: Media]) -> [InstantPageTableRow] {
private func parseTableRows(_ input: [Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> [InstantPageTableRow] {
var result: [InstantPageTableRow] = []
for item in input {
if let item = item as? [String: Any] {
@ -514,7 +513,7 @@ private func parseTableRows(_ input: [Any], _ media: inout [MediaId: Media]) ->
return result
}
private func parseTableRow(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageTableRow {
private func parseTableRow(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageTableRow {
var cells: [InstantPageTableCell] = []
if let content = input["content"] as? [Any] {
@ -552,7 +551,7 @@ private func parseTableRow(_ input: [String: Any], _ media: inout [MediaId: Medi
return InstantPageTableRow(cells: cells)
}
private func parseDetails(_ item: [String: Any], _ url: String, _ media: inout [MediaId: Media]) -> InstantPageBlock? {
private func parseDetails(_ item: [String: Any], _ url: String, _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? {
guard var content = item["contant"] as? [Any] else {
return nil
}
@ -576,7 +575,7 @@ private func parseDetails(_ item: [String: Any], _ url: String, _ media: inout [
}
private let nonListCharacters = CharacterSet(charactersIn: "0123456789").inverted
private func parseList(_ input: [String: Any], _ url: String, _ media: inout [MediaId: Media]) -> InstantPageBlock? {
private func parseList(_ input: [String: Any], _ url: String, _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? {
guard let content = input["content"] as? [Any], let tag = input["tag"] as? String else {
return nil
}
@ -625,7 +624,7 @@ private func parseList(_ input: [String: Any], _ url: String, _ media: inout [Me
return .list(items: items, ordered: ordered)
}
private func parseImage(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageBlock? {
private func parseImage(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? {
guard let src = input["src"] as? String else {
return nil
}
@ -654,7 +653,7 @@ private func parseImage(_ input: [String: Any], _ media: inout [MediaId: Media])
height = 0
}
let id = MediaId(namespace: Namespaces.Media.CloudImage, id: Int64(media.count))
let id = EngineMedia.Id(namespace: Namespaces.Media.CloudImage, id: Int64(media.count))
media[id] = TelegramMediaImage(
imageId: id,
representations: [
@ -679,7 +678,7 @@ private func parseImage(_ input: [String: Any], _ media: inout [MediaId: Media])
)
}
private func parseVideo(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageBlock? {
private func parseVideo(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? {
guard let src = input["src"] as? String else {
return nil
}
@ -709,7 +708,7 @@ private func parseVideo(_ input: [String: Any], _ media: inout [MediaId: Media])
)
}
private func parseFigure(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageBlock? {
private func parseFigure(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? {
guard let content = input["content"] as? [Any] else {
return nil
}
@ -743,7 +742,7 @@ private func parseFigure(_ input: [String: Any], _ media: inout [MediaId: Media]
return block
}
private func parsePageBlocks(_ input: [Any], _ url: String, _ media: inout [MediaId: Media]) -> [InstantPageBlock] {
private func parsePageBlocks(_ input: [Any], _ url: String, _ media: inout [EngineMedia.Id: EngineRawMedia]) -> [InstantPageBlock] {
var result: [InstantPageBlock] = []
for item in input {
if let string = item as? String {

View file

@ -28,7 +28,6 @@ import InstantPageUI
import ChatInterfaceState
import UndoUI
import TextFormat
import Postbox
import TelegramAnimatedStickerNode
import AnimationCache
import MultiAnimationRenderer
@ -63,12 +62,12 @@ final class ChatListSearchInteraction {
let present: (ViewController, Any?) -> Void
let dismissInput: () -> Void
let getSelectedMessageIds: () -> Set<EngineMessage.Id>?
let openStories: ((PeerId, ASDisplayNode) -> Void)?
let openStories: ((EnginePeer.Id, ASDisplayNode) -> Void)?
let switchToFilter: (ChatListSearchPaneKey) -> Void
let dismissSearch: () -> Void
let openAdInfo: (ASDisplayNode, AdPeer) -> Void
init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set<EngineMessage.Id>?, openStories: ((PeerId, ASDisplayNode) -> Void)?, switchToFilter: @escaping (ChatListSearchPaneKey) -> Void, dismissSearch: @escaping () -> Void, openAdInfo: @escaping (ASDisplayNode, AdPeer) -> Void) {
init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set<EngineMessage.Id>?, openStories: ((EnginePeer.Id, ASDisplayNode) -> Void)?, switchToFilter: @escaping (ChatListSearchPaneKey) -> Void, dismissSearch: @escaping () -> Void, openAdInfo: @escaping (ASDisplayNode, AdPeer) -> Void) {
self.openPeer = openPeer
self.openDisabledPeer = openDisabledPeer
self.openMessage = openMessage
@ -215,14 +214,14 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
let interaction = ChatListSearchInteraction(openPeer: { peer, chatPeer, threadId, value in
originalOpenPeer(peer, chatPeer, threadId, value)
if peer.id.namespace != Namespaces.Peer.SecretChat {
addAppLogEvent(postbox: context.account.postbox, type: "search_global_open_peer", peerId: peer.id)
context.engine.accountData.addAppLogEvent(type: "search_global_open_peer")
}
}, openDisabledPeer: { peer, threadId, reason in
openDisabledPeer(peer, threadId, reason)
}, openMessage: { peer, threadId, messageId, deactivateOnAction in
originalOpenMessage(peer, threadId, messageId, deactivateOnAction)
if peer.id.namespace != Namespaces.Peer.SecretChat {
addAppLogEvent(postbox: context.account.postbox, type: "search_global_open_message", peerId: peer.id, data: .dictionary(["msg_id": .number(Double(messageId.id))]))
context.engine.accountData.addAppLogEvent(type: "search_global_open_message", data: .dictionary(["msg_id": .number(Double(messageId.id))]))
}
}, openUrl: { [weak self] url in
let _ = openUserGeneratedUrl(context: context, peerId: nil, url: url, concealed: false, present: { c in
@ -1396,16 +1395,16 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
return
}
var resourceIds = Set<MediaResourceId>()
var resourceIds = Set<EngineMediaResource.Id>()
for message in messages {
for media in message.media {
if let file = media as? TelegramMediaFile {
resourceIds.insert(file.resource.id)
resourceIds.insert(EngineMediaResource.Id(file.resource.id))
}
}
}
let _ = (strongSelf.context.engine.resources.removeCachedResources(ids: resourceIds.map { EngineMediaResource.Id($0) }, force: true, notify: true)
let _ = (strongSelf.context.engine.resources.removeCachedResources(ids: Array(resourceIds), force: true, notify: true)
|> deliverOnMainQueue).startStandalone(completed: {
guard let strongSelf = self else {
return

View file

@ -2732,7 +2732,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
}
} else {
if !finalQuery.isEmpty {
addAppLogEvent(postbox: context.account.postbox, type: "search_global_query")
context.engine.accountData.addAppLogEvent(type: "search_global_query")
}
let searchSignals: [Signal<(SearchMessagesResult, SearchMessagesState), NoError>]

View file

@ -3,7 +3,6 @@ import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
import Postbox
import TelegramCore
import TelegramPresentationData
import ItemListUI
@ -2624,18 +2623,18 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
}
if case .chatList = item.chatListLocation, itemPeer.peerId == item.context.account.peerId, let message = messages.first {
var effectiveAuthor: Peer? = message.author?._asPeer()
var effectiveAuthor: EngineRawPeer? = message.author?._asPeer()
if let forwardInfo = message.forwardInfo {
effectiveAuthor = forwardInfo.author
if effectiveAuthor == nil, let authorSignature = forwardInfo.authorSignature {
effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)
effectiveAuthor = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)
}
}
if let sourceAuthorInfo = message._asMessage().sourceAuthorInfo {
if let originalAuthor = sourceAuthorInfo.originalAuthor, let peer = message.peers[originalAuthor] {
effectiveAuthor = peer
} else if let authorSignature = sourceAuthorInfo.originalAuthorName {
effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)
effectiveAuthor = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)
}
}
@ -2960,10 +2959,10 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
case let .preview(dimensions, immediateThumbnailData, videoDuration):
if let immediateThumbnailData {
if let videoDuration {
let thumbnailMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: index), partialReference: nil, resource: EmptyMediaResource(), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Video(duration: Double(videoDuration), size: dimensions ?? PixelDimensions(width: 1, height: 1), flags: [], preloadSize: nil, coverTime: nil, videoCodec: nil)], alternativeRepresentations: [])
let thumbnailMedia = TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: index), partialReference: nil, resource: EmptyMediaResource(), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Video(duration: Double(videoDuration), size: dimensions ?? PixelDimensions(width: 1, height: 1), flags: [], preloadSize: nil, coverTime: nil, videoCodec: nil)], alternativeRepresentations: [])
contentImageSpecs.append(ContentImageSpec(message: message, media: .file(thumbnailMedia), size: fitSize))
} else {
let thumbnailMedia = TelegramMediaImage(imageId: MediaId(namespace: 0, id: index), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: [])
let thumbnailMedia = TelegramMediaImage(imageId: EngineMedia.Id(namespace: 0, id: index), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: [])
contentImageSpecs.append(ContentImageSpec(message: message, media: .image(thumbnailMedia), size: fitSize))
}
index += 1
@ -3196,7 +3195,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
textAttributedString = attributedText
let dateText: String
var topIndex: MessageIndex?
var topIndex: EngineMessage.Index?
switch item.content {
case .loading:
break

View file

@ -16,7 +16,6 @@ import ChatListSearchItemHeader
import PremiumUI
import AnimationCache
import MultiAnimationRenderer
import Postbox
import ChatFolderLinkPreviewScreen
import StoryContainerScreen
import ChatListHeaderComponent
@ -1239,7 +1238,7 @@ public final class ChatListNode: ListViewImpl {
case .Header, .Hole:
return nil
case let .PeerId(value):
return PeerId(value)
return EnginePeer.Id(value)
case .ThreadId, .GroupId, .ContactId, .ArchiveIntro, .EmptyIntro, .SectionHeader, .Notice, .additionalCategory, .TopPeer:
return nil
}
@ -2618,7 +2617,7 @@ public final class ChatListNode: ListViewImpl {
strongSelf.enqueueHistoryPreloadUpdate()
}
var refreshStoryPeerIds: [PeerId] = []
var refreshStoryPeerIds: [EnginePeer.Id] = []
var isHiddenItemVisible = false
if let range = range.visibleRange {
let entryCount = chatListView.filteredEntries.count

View file

@ -1,7 +1,6 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Postbox
import SwiftSignalKit
import TelegramCore
import Display
@ -71,18 +70,18 @@ public final class ChatPanelInterfaceInteraction {
case editPrice
}
public let setupReplyMessage: (MessageId?, EngineMessageReplyInnerSubject?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void
public let setupEditMessage: (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void
public let beginMessageSelection: ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void
public let setupReplyMessage: (EngineMessage.Id?, EngineMessageReplyInnerSubject?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void
public let setupEditMessage: (EngineMessage.Id?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void
public let beginMessageSelection: ([EngineMessage.Id], @escaping (ContainedViewLayoutTransition) -> Void) -> Void
public let cancelMessageSelection: (ContainedViewLayoutTransition) -> Void
public let deleteSelectedMessages: () -> Void
public let reportSelectedMessages: () -> Void
public let reportMessages: ([Message], ContextControllerProtocol?) -> Void
public let blockMessageAuthor: (Message, ContextControllerProtocol?) -> Void
public let deleteMessages: ([Message], ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void
public let reportMessages: ([EngineRawMessage], ContextControllerProtocol?) -> Void
public let blockMessageAuthor: (EngineRawMessage, ContextControllerProtocol?) -> Void
public let deleteMessages: ([EngineRawMessage], ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void
public let forwardSelectedMessages: () -> Void
public let forwardCurrentForwardMessages: () -> Void
public let forwardMessages: ([Message]) -> Void
public let forwardMessages: ([EngineRawMessage]) -> Void
public let updateForwardOptionsState: ((ChatInterfaceForwardOptionsState) -> ChatInterfaceForwardOptionsState) -> Void
public let presentForwardOptions: (UIView) -> Void
public let presentReplyOptions: (UIView) -> Void
@ -90,7 +89,7 @@ public final class ChatPanelInterfaceInteraction {
public let presentSuggestPostOptions: () -> Void
public let shareSelectedMessages: () -> Void
public let updateTextInputStateAndMode: (@escaping (ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void
public let updateInputModeAndDismissedButtonKeyboardMessageId: ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void
public let updateInputModeAndDismissedButtonKeyboardMessageId: ((ChatPresentationInterfaceState) -> (ChatInputMode, EngineMessage.Id?)) -> Void
public let openStickers: () -> Void
public let editMessage: () -> Void
public let beginMessageSearch: (ChatSearchDomain, String) -> Void
@ -100,17 +99,17 @@ public final class ChatPanelInterfaceInteraction {
public let openSearchResults: () -> Void
public let openCalendarSearch: () -> Void
public let toggleMembersSearch: (Bool) -> Void
public let navigateToMessage: (MessageId, Bool, Bool, ChatLoadingMessageSubject) -> Void
public let navigateToChat: (PeerId) -> Void
public let navigateToProfile: (PeerId) -> Void
public let navigateToMessage: (EngineMessage.Id, Bool, Bool, ChatLoadingMessageSubject) -> Void
public let navigateToChat: (EnginePeer.Id) -> Void
public let navigateToProfile: (EnginePeer.Id) -> Void
public let openPeerInfo: () -> Void
public let togglePeerNotifications: () -> Void
public let sendContextResult: (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool
public let sendBotCommand: (Peer, String) -> Void
public let sendBotCommand: (EngineRawPeer, String) -> Void
public let sendShortcut: (Int32) -> Void
public let openEditShortcuts: () -> Void
public let sendBotStart: (String?) -> Void
public let botSwitchChatWithPayload: (PeerId, String) -> Void
public let botSwitchChatWithPayload: (EnginePeer.Id, String) -> Void
public let beginMediaRecording: (Bool) -> Void
public let finishMediaRecording: (ChatFinishMediaRecordingAction) -> Void
public let stopMediaRecording: () -> Void
@ -122,20 +121,20 @@ public final class ChatPanelInterfaceInteraction {
public let displayVideoUnmuteTip: (CGPoint?) -> Void
public let switchMediaRecordingMode: () -> Void
public let setupMessageAutoremoveTimeout: () -> Void
public let sendSticker: (FileMediaReference, Bool, UIView?, CGRect?, CALayer?, [ItemCollectionId]) -> Bool
public let sendSticker: (FileMediaReference, Bool, UIView?, CGRect?, CALayer?, [EngineItemCollectionId]) -> Bool
public let editSticker: (TelegramMediaFile) -> Void
public let unblockPeer: () -> Void
public let pinMessage: (MessageId, ContextControllerProtocol?) -> Void
public let unpinMessage: (MessageId, Bool, ContextControllerProtocol?) -> Void
public let pinMessage: (EngineMessage.Id, ContextControllerProtocol?) -> Void
public let unpinMessage: (EngineMessage.Id, Bool, ContextControllerProtocol?) -> Void
public let unpinAllMessages: () -> Void
public let openPinnedList: (MessageId) -> Void
public let openPinnedList: (EngineMessage.Id) -> Void
public let shareAccountContact: () -> Void
public let reportPeer: () -> Void
public let presentPeerContact: () -> Void
public let dismissReportPeer: () -> Void
public let deleteChat: () -> Void
public let beginCall: (Bool) -> Void
public let toggleMessageStickerStarred: (MessageId) -> Void
public let toggleMessageStickerStarred: (EngineMessage.Id) -> Void
public let presentController: (ViewController, Any?) -> Void
public let presentControllerInCurrent: (ViewController, Any?) -> Void
public let getNavigationController: () -> NavigationController?
@ -143,8 +142,8 @@ public final class ChatPanelInterfaceInteraction {
public let navigateFeed: () -> Void
public let openGrouping: () -> Void
public let toggleSilentPost: () -> Void
public let requestUnvoteInMessage: (MessageId) -> Void
public let requestStopPollInMessage: (MessageId) -> Void
public let requestUnvoteInMessage: (EngineMessage.Id) -> Void
public let requestStopPollInMessage: (EngineMessage.Id) -> Void
public let updateInputLanguage: (@escaping (String?) -> String?) -> Void
public let unarchiveChat: () -> Void
public let openLinkEditing: () -> Void
@ -156,9 +155,9 @@ public final class ChatPanelInterfaceInteraction {
public let openPeersNearby: () -> Void
public let unarchivePeer: () -> Void
public let scrollToTop: () -> Void
public let viewReplies: (MessageId?, ChatReplyThreadMessage) -> Void
public let viewReplies: (EngineMessage.Id?, ChatReplyThreadMessage) -> Void
public let activatePinnedListPreview: (ASDisplayNode, ContextGesture) -> Void
public let editMessageMedia: (MessageId, Bool) -> Void
public let editMessageMedia: (EngineMessage.Id, Bool) -> Void
public let joinGroupCall: (CachedChannelData.ActiveCall) -> Void
public let presentInviteMembers: () -> Void
public let presentGigagroupHelp: () -> Void
@ -179,7 +178,7 @@ public final class ChatPanelInterfaceInteraction {
public let addDoNotTranslateLanguage: (String) -> Void
public let hideTranslationPanel: () -> Void
public let openPremiumGift: () -> Void
public let openSuggestPost: (Message?, OpenSuggestPostMode) -> Void
public let openSuggestPost: (EngineRawMessage?, OpenSuggestPostMode) -> Void
public let openPremiumRequiredForMessaging: () -> Void
public let openStarsPurchase: (Int64?) -> Void
public let openMessagePayment: () -> Void
@ -190,7 +189,7 @@ public final class ChatPanelInterfaceInteraction {
public let openBoostToUnrestrict: () -> Void
public let updateRecordingTrimRange: (Double, Double, Bool, Bool) -> Void
public let dismissAllTooltips: () -> Void
public let editTodoMessage: (MessageId, Int32?, Bool) -> Void
public let editTodoMessage: (EngineMessage.Id, Int32?, Bool) -> Void
public let dismissUrlPreview: () -> Void
public let dismissForwardMessages: () -> Void
public let dismissSuggestPost: () -> Void
@ -204,18 +203,18 @@ public final class ChatPanelInterfaceInteraction {
public let statuses: ChatPanelInterfaceInteractionStatuses?
public init(
setupReplyMessage: @escaping (MessageId?, EngineMessageReplyInnerSubject?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void,
setupEditMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
beginMessageSelection: @escaping ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
setupReplyMessage: @escaping (EngineMessage.Id?, EngineMessageReplyInnerSubject?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void,
setupEditMessage: @escaping (EngineMessage.Id?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
beginMessageSelection: @escaping ([EngineMessage.Id], @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
cancelMessageSelection: @escaping (ContainedViewLayoutTransition) -> Void,
deleteSelectedMessages: @escaping () -> Void,
reportSelectedMessages: @escaping () -> Void,
reportMessages: @escaping ([Message], ContextControllerProtocol?) -> Void,
blockMessageAuthor: @escaping (Message, ContextControllerProtocol?) -> Void,
deleteMessages: @escaping ([Message], ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void,
reportMessages: @escaping ([EngineRawMessage], ContextControllerProtocol?) -> Void,
blockMessageAuthor: @escaping (EngineRawMessage, ContextControllerProtocol?) -> Void,
deleteMessages: @escaping ([EngineRawMessage], ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void,
forwardSelectedMessages: @escaping () -> Void,
forwardCurrentForwardMessages: @escaping () -> Void,
forwardMessages: @escaping ([Message]) -> Void,
forwardMessages: @escaping ([EngineRawMessage]) -> Void,
updateForwardOptionsState: @escaping ((ChatInterfaceForwardOptionsState) -> ChatInterfaceForwardOptionsState) -> Void,
presentForwardOptions: @escaping (UIView) -> Void,
presentReplyOptions: @escaping (UIView) -> Void,
@ -223,7 +222,7 @@ public final class ChatPanelInterfaceInteraction {
presentSuggestPostOptions: @escaping () -> Void,
shareSelectedMessages: @escaping () -> Void,
updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void,
updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void,
updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, EngineMessage.Id?)) -> Void,
openStickers: @escaping () -> Void,
editMessage: @escaping () -> Void,
beginMessageSearch: @escaping (ChatSearchDomain, String) -> Void,
@ -233,17 +232,17 @@ public final class ChatPanelInterfaceInteraction {
navigateMessageSearch: @escaping (ChatPanelSearchNavigationAction) -> Void,
openCalendarSearch: @escaping () -> Void,
toggleMembersSearch: @escaping (Bool) -> Void,
navigateToMessage: @escaping (MessageId, Bool, Bool, ChatLoadingMessageSubject) -> Void,
navigateToChat: @escaping (PeerId) -> Void,
navigateToProfile: @escaping (PeerId) -> Void,
navigateToMessage: @escaping (EngineMessage.Id, Bool, Bool, ChatLoadingMessageSubject) -> Void,
navigateToChat: @escaping (EnginePeer.Id) -> Void,
navigateToProfile: @escaping (EnginePeer.Id) -> Void,
openPeerInfo: @escaping () -> Void,
togglePeerNotifications: @escaping () -> Void,
sendContextResult: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool,
sendBotCommand: @escaping (Peer, String) -> Void,
sendBotCommand: @escaping (EngineRawPeer, String) -> Void,
sendShortcut: @escaping (Int32) -> Void,
openEditShortcuts: @escaping () -> Void,
sendBotStart: @escaping (String?) -> Void,
botSwitchChatWithPayload: @escaping (PeerId, String) -> Void,
botSwitchChatWithPayload: @escaping (EnginePeer.Id, String) -> Void,
beginMediaRecording: @escaping (Bool) -> Void,
finishMediaRecording: @escaping (ChatFinishMediaRecordingAction) -> Void,
stopMediaRecording: @escaping () -> Void,
@ -255,20 +254,20 @@ public final class ChatPanelInterfaceInteraction {
displayVideoUnmuteTip: @escaping (CGPoint?) -> Void,
switchMediaRecordingMode: @escaping () -> Void,
setupMessageAutoremoveTimeout: @escaping () -> Void,
sendSticker: @escaping (FileMediaReference, Bool, UIView?, CGRect?, CALayer?, [ItemCollectionId]) -> Bool,
sendSticker: @escaping (FileMediaReference, Bool, UIView?, CGRect?, CALayer?, [EngineItemCollectionId]) -> Bool,
editSticker: @escaping (TelegramMediaFile) -> Void,
unblockPeer: @escaping () -> Void,
pinMessage: @escaping (MessageId, ContextControllerProtocol?) -> Void,
unpinMessage: @escaping (MessageId, Bool, ContextControllerProtocol?) -> Void,
pinMessage: @escaping (EngineMessage.Id, ContextControllerProtocol?) -> Void,
unpinMessage: @escaping (EngineMessage.Id, Bool, ContextControllerProtocol?) -> Void,
unpinAllMessages: @escaping () -> Void,
openPinnedList: @escaping (MessageId) -> Void,
openPinnedList: @escaping (EngineMessage.Id) -> Void,
shareAccountContact: @escaping () -> Void,
reportPeer: @escaping () -> Void,
presentPeerContact: @escaping () -> Void,
dismissReportPeer: @escaping () -> Void,
deleteChat: @escaping () -> Void,
beginCall: @escaping (Bool) -> Void,
toggleMessageStickerStarred: @escaping (MessageId) -> Void,
toggleMessageStickerStarred: @escaping (EngineMessage.Id) -> Void,
presentController: @escaping (ViewController, Any?) -> Void,
presentControllerInCurrent: @escaping (ViewController, Any?) -> Void,
getNavigationController: @escaping () -> NavigationController?,
@ -276,8 +275,8 @@ public final class ChatPanelInterfaceInteraction {
navigateFeed: @escaping () -> Void,
openGrouping: @escaping () -> Void,
toggleSilentPost: @escaping () -> Void,
requestUnvoteInMessage: @escaping (MessageId) -> Void,
requestStopPollInMessage: @escaping (MessageId) -> Void,
requestUnvoteInMessage: @escaping (EngineMessage.Id) -> Void,
requestStopPollInMessage: @escaping (EngineMessage.Id) -> Void,
updateInputLanguage: @escaping ((String?) -> String?) -> Void,
unarchiveChat: @escaping () -> Void,
openLinkEditing: @escaping () -> Void,
@ -289,13 +288,13 @@ public final class ChatPanelInterfaceInteraction {
displaySearchResultsTooltip: @escaping (ASDisplayNode, CGRect) -> Void,
unarchivePeer: @escaping () -> Void,
scrollToTop: @escaping () -> Void,
viewReplies: @escaping (MessageId?, ChatReplyThreadMessage) -> Void,
viewReplies: @escaping (EngineMessage.Id?, ChatReplyThreadMessage) -> Void,
activatePinnedListPreview: @escaping (ASDisplayNode, ContextGesture) -> Void,
joinGroupCall: @escaping (CachedChannelData.ActiveCall) -> Void,
presentInviteMembers: @escaping () -> Void,
presentGigagroupHelp: @escaping () -> Void,
openMonoforum: @escaping () -> Void,
editMessageMedia: @escaping (MessageId, Bool) -> Void,
editMessageMedia: @escaping (EngineMessage.Id, Bool) -> Void,
updateShowCommands: @escaping ((Bool) -> Bool) -> Void,
updateShowSendAsPeers: @escaping ((Bool) -> Bool) -> Void,
openInviteRequests: @escaping () -> Void,
@ -312,14 +311,14 @@ public final class ChatPanelInterfaceInteraction {
addDoNotTranslateLanguage: @escaping (String) -> Void,
hideTranslationPanel: @escaping () -> Void,
openPremiumGift: @escaping () -> Void,
openSuggestPost: @escaping (Message?, OpenSuggestPostMode) -> Void,
openSuggestPost: @escaping (EngineRawMessage?, OpenSuggestPostMode) -> Void,
openPremiumRequiredForMessaging: @escaping () -> Void,
openStarsPurchase: @escaping (Int64?) -> Void,
openMessagePayment: @escaping () -> Void,
openBoostToUnrestrict: @escaping () -> Void,
updateRecordingTrimRange: @escaping (Double, Double, Bool, Bool) -> Void,
dismissAllTooltips: @escaping () -> Void,
editTodoMessage: @escaping (MessageId, Int32?, Bool) -> Void,
editTodoMessage: @escaping (EngineMessage.Id, Int32?, Bool) -> Void,
dismissUrlPreview: @escaping () -> Void,
dismissForwardMessages: @escaping () -> Void,
dismissSuggestPost: @escaping () -> Void,
@ -472,7 +471,7 @@ public final class ChatPanelInterfaceInteraction {
public convenience init(
updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void,
updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void,
updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, EngineMessage.Id?)) -> Void,
openLinkEditing: @escaping () -> Void
) {
self.init(setupReplyMessage: { _, _, _ in

View file

@ -13,7 +13,6 @@ swift_library(
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/Display:Display",
"//submodules/Postbox:Postbox",
"//submodules/TelegramCore:TelegramCore",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/AccountContext:AccountContext",

View file

@ -1,7 +1,6 @@
import Foundation
import Display
import AsyncDisplayKit
import Postbox
import TelegramCore
import SwiftSignalKit
import PassKit
@ -19,20 +18,20 @@ import StoryContainerScreen
public enum ChatMessageGalleryControllerData {
case url(String)
case pass(TelegramMediaFile)
case instantPage(InstantPageGalleryController, Int, Media)
case instantPage(InstantPageGalleryController, Int, EngineRawMedia)
case map(TelegramMediaMap)
case stickerPack(StickerPackReference, TelegramMediaFile?)
case audio(TelegramMediaFile)
case document(TelegramMediaFile, Bool)
case gallery(Signal<GalleryController, NoError>)
case secretGallery(SecretMediaPreviewController)
case chatAvatars(AvatarGalleryController, Media)
case chatAvatars(AvatarGalleryController, EngineRawMedia)
case theme(TelegramMediaFile)
case other(Media)
case other(EngineRawMedia)
case story(Signal<StoryContainerScreen, NoError>)
}
private func instantPageBlockMedia(pageId: MediaId, block: InstantPageBlock, media: [MediaId: Media], counter: inout Int) -> [InstantPageGalleryEntry] {
private func instantPageBlockMedia(pageId: EngineMedia.Id, block: InstantPageBlock, media: [EngineMedia.Id: EngineRawMedia], counter: inout Int) -> [InstantPageGalleryEntry] {
switch block {
case let .image(id, caption, _, _):
if let m = media[id] {
@ -64,7 +63,7 @@ private func instantPageBlockMedia(pageId: MediaId, block: InstantPageBlock, med
return []
}
public func instantPageGalleryMedia(webpageId: MediaId, page: InstantPage.Accessor, galleryMedia: Media) -> [InstantPageGalleryEntry] {
public func instantPageGalleryMedia(webpageId: EngineMedia.Id, page: InstantPage.Accessor, galleryMedia: EngineRawMedia) -> [InstantPageGalleryEntry] {
var result: [InstantPageGalleryEntry] = []
var counter: Int = 0
@ -96,9 +95,9 @@ public func instantPageGalleryMedia(webpageId: MediaId, page: InstantPage.Access
public func chatMessageGalleryControllerData(
context: AccountContext,
chatLocation: ChatLocation?,
chatFilterTag: MemoryBuffer?,
chatFilterTag: EngineMemoryBuffer?,
chatLocationContextHolder: Atomic<ChatLocationContextHolder?>?,
message: Message,
message: EngineRawMessage,
mediaSubject: GalleryMediaSubject? = nil,
navigationController: NavigationController?,
standalone: Bool,
@ -113,10 +112,10 @@ public func chatMessageGalleryControllerData(
standalone = true
}
var galleryMedia: Media?
var otherMedia: Media?
var galleryMedia: EngineRawMedia?
var otherMedia: EngineRawMedia?
var instantPageMedia: (TelegramMediaWebpage, [InstantPageGalleryEntry])?
if message.media.isEmpty, let entities = message.textEntitiesAttribute?.entities, entities.count == 1, let firstEntity = entities.first, case let .CustomEmoji(_, fileId) = firstEntity.type, let file = message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile {
if message.media.isEmpty, let entities = message.textEntitiesAttribute?.entities, entities.count == 1, let firstEntity = entities.first, case let .CustomEmoji(_, fileId) = firstEntity.type, let file = message.associatedMedia[EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile {
for attribute in file.attributes {
if case let .CustomEmoji(_, _, _, reference) = attribute {
if let reference = reference {
@ -356,25 +355,11 @@ public func chatMessageGalleryControllerData(
}
public enum ChatMessagePreviewControllerData {
case instantPage(InstantPageGalleryController, Int, Media)
case instantPage(InstantPageGalleryController, Int, EngineRawMedia)
case gallery(GalleryController)
}
public func chatMessagePreviewControllerData(context: AccountContext, chatLocation: ChatLocation?, chatFilterTag: MemoryBuffer?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>?, message: Message, standalone: Bool, reverseMessageGalleryOrder: Bool, navigationController: NavigationController?) -> ChatMessagePreviewControllerData? {
if let mediaData = chatMessageGalleryControllerData(context: context, chatLocation: chatLocation, chatFilterTag: chatFilterTag, chatLocationContextHolder: chatLocationContextHolder, message: message, navigationController: navigationController, standalone: standalone, reverseMessageGalleryOrder: reverseMessageGalleryOrder, mode: .default, source: nil, synchronousLoad: true, actionInteraction: nil) {
switch mediaData {
case .gallery:
break
case let .instantPage(gallery, centralIndex, galleryMedia):
return .instantPage(gallery, centralIndex, galleryMedia)
default:
break
}
}
return nil
}
public func chatMediaListPreviewControllerData(context: AccountContext, chatLocation: ChatLocation?, chatFilterTag: MemoryBuffer?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>?, message: Message, standalone: Bool, reverseMessageGalleryOrder: Bool, navigationController: NavigationController?) -> Signal<ChatMessagePreviewControllerData?, NoError> {
public func chatMediaListPreviewControllerData(context: AccountContext, chatLocation: ChatLocation?, chatFilterTag: EngineMemoryBuffer?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>?, message: EngineRawMessage, standalone: Bool, reverseMessageGalleryOrder: Bool, navigationController: NavigationController?) -> Signal<ChatMessagePreviewControllerData?, NoError> {
if let mediaData = chatMessageGalleryControllerData(context: context, chatLocation: chatLocation, chatFilterTag: chatFilterTag, chatLocationContextHolder: chatLocationContextHolder, message: message, navigationController: navigationController, standalone: standalone, reverseMessageGalleryOrder: reverseMessageGalleryOrder, mode: .default, source: nil, synchronousLoad: true, actionInteraction: nil) {
switch mediaData {
case let .gallery(gallery):

View file

@ -1,7 +1,6 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Postbox
import Display
import SwiftSignalKit
import WebKit
@ -17,10 +16,10 @@ class ChatDocumentGalleryItem: GalleryItem {
let context: AccountContext
let presentationData: PresentationData
let message: Message
let location: MessageHistoryEntryLocation?
let message: EngineRawMessage
let location: EngineMessageHistoryEntryLocation?
init(context: AccountContext, presentationData: PresentationData, message: Message, location: MessageHistoryEntryLocation?) {
init(context: AccountContext, presentationData: PresentationData, message: EngineRawMessage, location: EngineMessageHistoryEntryLocation?) {
self.context = context
self.presentationData = presentationData
self.message = message
@ -104,7 +103,7 @@ class ChatDocumentGalleryItemNode: ZoomableContentGalleryItemNode, WKNavigationD
private var itemIsVisible = false
private var message: Message?
private var message: EngineRawMessage?
private let footerContentNode: ChatItemGalleryFooterContentNode
@ -163,7 +162,7 @@ class ChatDocumentGalleryItemNode: ZoomableContentGalleryItemNode, WKNavigationD
transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(), size: statusSize))
}
fileprivate func setMessage(_ message: Message) {
fileprivate func setMessage(_ message: EngineRawMessage) {
self.footerContentNode.setMessage(message)
}
@ -187,7 +186,7 @@ class ChatDocumentGalleryItemNode: ZoomableContentGalleryItemNode, WKNavigationD
}
}
private func setupStatus(context: AccountContext, resource: MediaResource) {
private func setupStatus(context: AccountContext, resource: EngineRawMediaResource) {
self.statusDisposable.set((context.engine.resources.status(resource: EngineMediaResource(resource))
|> deliverOnMainQueue).start(next: { [weak self] status in
if let strongSelf = self {

View file

@ -1,7 +1,6 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Postbox
import Display
import SwiftSignalKit
import WebKit
@ -17,10 +16,10 @@ class ChatExternalFileGalleryItem: GalleryItem {
let context: AccountContext
let presentationData: PresentationData
let message: Message
let location: MessageHistoryEntryLocation?
init(context: AccountContext, presentationData: PresentationData, message: Message, location: MessageHistoryEntryLocation?) {
let message: EngineRawMessage
let location: EngineMessageHistoryEntryLocation?
init(context: AccountContext, presentationData: PresentationData, message: EngineRawMessage, location: EngineMessageHistoryEntryLocation?) {
self.context = context
self.presentationData = presentationData
self.message = message
@ -78,7 +77,7 @@ class ChatExternalFileGalleryItemNode: GalleryItemNode {
private var itemIsVisible = false
private var message: Message?
private var message: EngineRawMessage?
private let footerContentNode: ChatItemGalleryFooterContentNode
@ -164,7 +163,7 @@ class ChatExternalFileGalleryItemNode: GalleryItemNode {
transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(), size: statusSize))
}
fileprivate func setMessage(_ message: Message) {
fileprivate func setMessage(_ message: EngineRawMessage) {
self.message = message
self.footerContentNode.setMessage(message)
}
@ -182,7 +181,7 @@ class ChatExternalFileGalleryItemNode: GalleryItemNode {
}
}
private func setupStatus(context: AccountContext, resource: MediaResource) {
private func setupStatus(context: AccountContext, resource: EngineRawMediaResource) {
self.statusDisposable.set((context.engine.resources.status(resource: EngineMediaResource(resource))
|> deliverOnMainQueue).start(next: { [weak self] status in
if let strongSelf = self {

View file

@ -2949,7 +2949,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
}
if swipeUpToClose {
addAppLogEvent(postbox: self.context.account.postbox, type: "swipe_up_close", peerId: self.context.account.peerId)
self.context.engine.accountData.addAppLogEvent(type: "swipe_up_close")
return false
}
@ -2957,7 +2957,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
if #available(iOS 15.0, *) {
if let nativePictureInPictureContent = self.nativePictureInPictureContent as? NativePictureInPictureContentImpl {
addAppLogEvent(postbox: self.context.account.postbox, type: "swipe_up_pip", peerId: self.context.account.peerId)
self.context.engine.accountData.addAppLogEvent(type: "swipe_up_pip")
nativePictureInPictureContent.beginPictureInPicture()
return true
}
@ -2966,7 +2966,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
}
override func maybePerformActionForSwipeDownDismiss() -> Bool {
addAppLogEvent(postbox: self.context.account.postbox, type: "swipe_down_close", peerId: self.context.account.peerId)
self.context.engine.accountData.addAppLogEvent(type: "swipe_down_close")
return false
}
@ -3184,7 +3184,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
self.activePictureInPictureController = nil
self.activePictureInPictureNavigationController = nil
addAppLogEvent(postbox: self.context.account.postbox, type: "pip_close_btn", peerId: self.context.account.peerId)
self.context.engine.accountData.addAppLogEvent(type: "pip_close_btn")
}
}, expand: { [weak self] completion in
didExpand = true
@ -3234,7 +3234,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
if #available(iOS 15.0, *) {
if let nativePictureInPictureContent = self.nativePictureInPictureContent as? NativePictureInPictureContentImpl {
addAppLogEvent(postbox: self.context.account.postbox, type: "pip_btn", peerId: self.context.account.peerId)
self.context.engine.accountData.addAppLogEvent(type: "pip_btn")
nativePictureInPictureContent.beginPictureInPicture()
return
}

View file

@ -5,7 +5,6 @@ import SwiftSignalKit
import ComponentFlow
import MultilineTextComponent
import MultilineTextWithEntitiesComponent
import Postbox
import TelegramCore
import TelegramPresentationData
import ContextUI
@ -111,7 +110,7 @@ final class VideoAdComponent: Component {
let titleString = component.message.author?.compactDisplayTitle ?? ""
var media: Media?
var media: EngineRawMedia?
if let photo = component.message.media.first as? TelegramMediaImage {
media = photo
} else if let file = component.message.media.first as? TelegramMediaFile {

View file

@ -11,7 +11,6 @@ swift_library(
],
deps = [
"//submodules/TelegramCore",
"//submodules/Postbox",
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/Display",
"//submodules/Pdf",

View file

@ -1,6 +1,5 @@
import Foundation
import UIKit
import Postbox
import TelegramCore
import SwiftSignalKit
import Display
@ -13,9 +12,9 @@ public struct ICloudFileResourceId {
public var uniqueId: String {
if self.thumbnail {
return "icloud-thumb-\(persistentHash32(self.urlData))"
return "icloud-thumb-\(enginePersistentHash32(self.urlData))"
} else {
return "icloud-\(persistentHash32(self.urlData))"
return "icloud-\(enginePersistentHash32(self.urlData))"
}
}
@ -37,21 +36,21 @@ public class ICloudFileResource: TelegramMediaResource {
self.thumbnail = thumbnail
}
public required init(decoder: PostboxDecoder) {
public required init(decoder: EnginePostboxDecoder) {
self.urlData = decoder.decodeStringForKey("url", orElse: "")
self.thumbnail = decoder.decodeBoolForKey("thumb", orElse: false)
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
encoder.encodeString(self.urlData, forKey: "url")
encoder.encodeBool(self.thumbnail, forKey: "thumb")
}
public var id: MediaResourceId {
return MediaResourceId(ICloudFileResourceId(urlData: self.urlData, thumbnail: self.thumbnail).uniqueId)
public var id: EngineRawMediaResourceId {
return EngineRawMediaResourceId(ICloudFileResourceId(urlData: self.urlData, thumbnail: self.thumbnail).uniqueId)
}
public func isEqual(to: MediaResource) -> Bool {
public func isEqual(to: EngineRawMediaResource) -> Bool {
if let to = to as? ICloudFileResource {
if self.urlData != to.urlData || self.thumbnail != to.thumbnail {
return false
@ -252,7 +251,7 @@ public func iCloudFileDescription(_ url: URL) -> Signal<ICloudFileDescription?,
}
}
private final class ICloudFileResourceCopyItem: MediaResourceDataFetchCopyLocalItem {
private final class ICloudFileResourceCopyItem: EngineRawMediaResourceDataFetchCopyLocalItem {
private let url: URL
init(url: URL) {
@ -274,7 +273,7 @@ private final class ICloudFileResourceCopyItem: MediaResourceDataFetchCopyLocalI
}
}
public func fetchICloudFileResource(resource: ICloudFileResource) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
public func fetchICloudFileResource(resource: ICloudFileResource) -> Signal<EngineMediaResourceDataFetchResult, EngineMediaResourceDataFetchError> {
return Signal { subscriber in
subscriber.putNext(.reset)
@ -306,7 +305,7 @@ public func fetchICloudFileResource(resource: ICloudFileResource) -> Signal<Medi
let complete = {
if resource.thumbnail {
let tempFile = TempBox.shared.tempFile(fileName: "thumb.jpg")
let tempFile = EngineTempBox.shared.tempFile(fileName: "thumb.jpg")
var data = Data()
let fileExtension = url.pathExtension.lowercased()
let isAudioFile = audioFileExtensions.contains(fileExtension)

View file

@ -1,5 +1,4 @@
import Foundation
import Postbox
import TelegramCore
import PersistentStringHash
@ -7,9 +6,9 @@ public struct InstantPageExternalMediaResourceId {
public let url: String
public var uniqueId: String {
return "instantpage-media-\(persistentHash32(self.url))"
return "instantpage-media-\(enginePersistentHash32(self.url))"
}
public var hashValue: Int {
return self.uniqueId.hashValue
}
@ -17,28 +16,28 @@ public struct InstantPageExternalMediaResourceId {
public class InstantPageExternalMediaResource: TelegramMediaResource {
public let url: String
public var size: Int64? {
return nil
}
public init(url: String) {
self.url = url
}
public required init(decoder: PostboxDecoder) {
public required init(decoder: EnginePostboxDecoder) {
self.url = decoder.decodeStringForKey("u", orElse: "")
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
encoder.encodeString(self.url, forKey: "u")
}
public var id: MediaResourceId {
return MediaResourceId(InstantPageExternalMediaResourceId(url: self.url).uniqueId)
public var id: EngineRawMediaResourceId {
return EngineRawMediaResourceId(InstantPageExternalMediaResourceId(url: self.url).uniqueId)
}
public func isEqual(to: MediaResource) -> Bool {
public func isEqual(to: EngineRawMediaResource) -> Bool {
if let to = to as? InstantPageExternalMediaResource {
return self.url == to.url
} else {

View file

@ -1,23 +0,0 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "LegacyDataImport",
module_name = "LegacyDataImport",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/TelegramCore:TelegramCore",
"//submodules/SyncCore:SyncCore",
"//submodules/Postbox:Postbox",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/TelegramNotices:TelegramNotices",
"//submodules/TelegramUIPreferences:TelegramUIPreferences",
"//submodules/RadialStatusNode:RadialStatusNode",
"//submodules/LegacyComponents:LegacyComponents",
"//submodules/LegacyDataImport/Impl:LegacyDataImportImpl",
],
visibility = [
"//visibility:public",
],
)

View file

@ -1,22 +0,0 @@
objc_library(
name = "LegacyDataImportImpl",
enable_modules = True,
module_name = "LegacyDataImportImpl",
srcs = glob([
"Sources/**/*.m",
"Sources/**/*.h",
]),
hdrs = glob([
"PublicHeaders/**/*.h",
]),
includes = [
"PublicHeaders",
],
sdk_frameworks = [
"Foundation",
],
visibility = [
"//visibility:public",
],
)

View file

@ -1,7 +0,0 @@
#import <UIKit/UIKit.h>
#import <LegacyDataImportImpl/TGProxyItem.h>
#import <LegacyDataImportImpl/TGAutoDownloadPreferences.h>
#import <LegacyDataImportImpl/TGPresentationAutoNightPreferences.h>

View file

@ -1,76 +0,0 @@
#import <Foundation/Foundation.h>
typedef enum {
TGNetworkTypeUnknown,
TGNetworkTypeNone,
TGNetworkTypeGPRS,
TGNetworkTypeEdge,
TGNetworkType3G,
TGNetworkTypeLTE,
TGNetworkTypeWiFi,
} TGNetworkType;
typedef enum {
TGAutoDownloadModeNone = 0,
TGAutoDownloadModeCellularContacts = 1 << 0,
TGAutoDownloadModeWifiContacts = 1 << 1,
TGAutoDownloadModeCellularPrivateChats = 1 << 2,
TGAutoDownloadModeWifiPrivateChats = 1 << 3,
TGAutoDownloadModeCellularGroups = 1 << 4,
TGAutoDownloadModeWifiGroups = 1 << 5,
TGAutoDownloadModeCellularChannels = 1 << 6,
TGAutoDownloadModeWifiChannels = 1 << 7,
TGAutoDownloadModeAutosavePhotosAll = TGAutoDownloadModeCellularContacts | TGAutoDownloadModeCellularPrivateChats | TGAutoDownloadModeCellularGroups | TGAutoDownloadModeCellularChannels,
TGAutoDownloadModeAllPrivateChats = TGAutoDownloadModeCellularContacts | TGAutoDownloadModeWifiContacts | TGAutoDownloadModeCellularPrivateChats | TGAutoDownloadModeWifiPrivateChats,
TGAutoDownloadModeAllGroups = TGAutoDownloadModeCellularGroups | TGAutoDownloadModeWifiGroups | TGAutoDownloadModeCellularChannels | TGAutoDownloadModeWifiChannels,
TGAutoDownloadModeAll = TGAutoDownloadModeCellularContacts | TGAutoDownloadModeWifiContacts | TGAutoDownloadModeCellularPrivateChats | TGAutoDownloadModeWifiPrivateChats | TGAutoDownloadModeCellularGroups | TGAutoDownloadModeWifiGroups | TGAutoDownloadModeCellularChannels | TGAutoDownloadModeWifiChannels
} TGAutoDownloadMode;
typedef enum {
TGAutoDownloadChatContact,
TGAutoDownloadChatOtherPrivateChat,
TGAutoDownloadChatGroup,
TGAutoDownloadChatChannel
} TGAutoDownloadChat;
@interface TGAutoDownloadPreferences : NSObject <NSCoding>
@property (nonatomic, readonly) bool disabled;
@property (nonatomic, readonly) TGAutoDownloadMode photos;
@property (nonatomic, readonly) TGAutoDownloadMode videos;
@property (nonatomic, readonly) int32_t maximumVideoSize;
@property (nonatomic, readonly) TGAutoDownloadMode documents;
@property (nonatomic, readonly) int32_t maximumDocumentSize;
@property (nonatomic, readonly) TGAutoDownloadMode gifs;
@property (nonatomic, readonly) TGAutoDownloadMode voiceMessages;
@property (nonatomic, readonly) TGAutoDownloadMode videoMessages;
- (instancetype)updateDisabled:(bool)disabled;
- (instancetype)updatePhotosMode:(TGAutoDownloadMode)mode;
- (instancetype)updateVideosMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize;
- (instancetype)updateDocumentsMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize;
- (instancetype)updateGifsMode:(TGAutoDownloadMode)mode;
- (instancetype)updateVoiceMessagesMode:(TGAutoDownloadMode)mode;
- (instancetype)updateVideoMessagesMode:(TGAutoDownloadMode)mode;
+ (bool)shouldDownload:(TGAutoDownloadMode)mode inChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType;
- (bool)shouldDownloadPhotoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType;
- (bool)shouldDownloadVideoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType;
- (bool)shouldDownloadDocumentInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType;
- (bool)shouldDownloadGifInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType;
- (bool)shouldDownloadVoiceMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType;
- (bool)shouldDownloadVideoMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType;
- (bool)isDefaultPreferences;
+ (instancetype)defaultPreferences;
+ (instancetype)preferencesWithLegacyDownloadPrivatePhotos:(bool)privatePhotos groupPhotos:(bool)groupPhotos privateVoiceMessages:(bool)privateVoiceMessages groupVoiceMessages:(bool)groupVoiceMessages privateVideoMessages:(bool)privateVideoMessages groupVideoMessages:(bool)groupVideoMessages;
@end

View file

@ -1,250 +0,0 @@
#import <LegacyDataImportImpl/TGAutoDownloadPreferences.h>
@implementation TGAutoDownloadPreferences
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self != nil)
{
_disabled = [aDecoder decodeBoolForKey:@"disabled"];
_photos = [aDecoder decodeInt32ForKey:@"photos"];
_videos = [aDecoder decodeInt32ForKey:@"videos"];
_maximumVideoSize = [aDecoder decodeInt32ForKey:@"maxVideoSize"];
_documents = [aDecoder decodeInt32ForKey:@"documents"];
_maximumDocumentSize = [aDecoder decodeInt32ForKey:@"maxDocumentSize"];
_voiceMessages = [aDecoder decodeInt32ForKey:@"voiceMessages"];
_videoMessages = [aDecoder decodeInt32ForKey:@"videoMessages"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeBool:_disabled forKey:@"disabled"];
[aCoder encodeInt32:_photos forKey:@"photos"];
[aCoder encodeInt32:_videos forKey:@"videos"];
[aCoder encodeInt32:_maximumVideoSize forKey:@"maxVideoSize"];
[aCoder encodeInt32:_documents forKey:@"documents"];
[aCoder encodeInt32:_maximumDocumentSize forKey:@"maxDocumentSize"];
[aCoder encodeInt32:_voiceMessages forKey:@"voiceMessages"];
[aCoder encodeInt32:_videoMessages forKey:@"videoMessages"];
}
+ (instancetype)defaultPreferences
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = TGAutoDownloadModeAll;
preferences->_videos = TGAutoDownloadModeNone;
preferences->_maximumVideoSize = 10;
preferences->_documents = TGAutoDownloadModeNone;
preferences->_maximumDocumentSize = 10;
preferences->_voiceMessages = TGAutoDownloadModeAll;
preferences->_videoMessages = TGAutoDownloadModeAll;
return preferences;
}
+ (instancetype)preferencesWithLegacyDownloadPrivatePhotos:(bool)privatePhotos groupPhotos:(bool)groupPhotos privateVoiceMessages:(bool)privateVoiceMessages groupVoiceMessages:(bool)groupVoiceMessages privateVideoMessages:(bool)privateVideoMessages groupVideoMessages:(bool)groupVideoMessages
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
if (privatePhotos)
preferences->_photos |= TGAutoDownloadModeAllPrivateChats;
if (groupPhotos)
preferences->_photos |= TGAutoDownloadModeAllGroups;
if (privateVoiceMessages)
preferences->_voiceMessages |= TGAutoDownloadModeAllPrivateChats;
if (groupVoiceMessages)
preferences->_voiceMessages |= TGAutoDownloadModeAllGroups;
if (privateVideoMessages)
preferences->_videoMessages |= TGAutoDownloadModeAllPrivateChats;
if (groupVideoMessages)
preferences->_videoMessages |= TGAutoDownloadModeAllGroups;
preferences->_maximumVideoSize = 10;
preferences->_maximumDocumentSize = 10;
return preferences;
}
- (instancetype)updateDisabled:(bool)disabled
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_disabled = disabled;
preferences->_photos = _photos;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updatePhotosMode:(TGAutoDownloadMode)mode
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = mode;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updateVideosMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = _photos;
preferences->_videos = mode;
preferences->_maximumVideoSize = maximumSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updateDocumentsMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = _photos;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = mode;
preferences->_maximumDocumentSize = maximumSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updateVoiceMessagesMode:(TGAutoDownloadMode)mode
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = _photos;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = mode;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updateVideoMessagesMode:(TGAutoDownloadMode)mode
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = _photos;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = mode;
return preferences;
}
+ (bool)shouldDownload:(TGAutoDownloadMode)mode inChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
bool isWiFi = networkType == TGNetworkTypeWiFi;
bool isCellular = !isWiFi && networkType != TGNetworkTypeNone;
bool shouldDownload = false;
switch (chat)
{
case TGAutoDownloadChatContact:
if (isCellular)
shouldDownload = (mode & TGAutoDownloadModeCellularContacts) != 0;
else if (isWiFi)
shouldDownload = (mode & TGAutoDownloadModeWifiContacts) != 0;
break;
case TGAutoDownloadChatOtherPrivateChat:
if (isCellular)
shouldDownload = (mode & TGAutoDownloadModeCellularPrivateChats) != 0;
else if (isWiFi)
shouldDownload = (mode & TGAutoDownloadModeWifiPrivateChats) != 0;
break;
case TGAutoDownloadChatGroup:
if (isCellular)
shouldDownload = (mode & TGAutoDownloadModeCellularGroups) != 0;
else if (isWiFi)
shouldDownload = (mode & TGAutoDownloadModeWifiGroups) != 0;
break;
case TGAutoDownloadChatChannel:
if (isCellular)
shouldDownload = (mode & TGAutoDownloadModeCellularChannels) != 0;
else if (isWiFi)
shouldDownload = (mode & TGAutoDownloadModeWifiChannels) != 0;
break;
default:
break;
}
return shouldDownload;
}
- (bool)shouldDownloadPhotoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_photos inChat:chat networkType:networkType];
}
- (bool)shouldDownloadVideoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_videos inChat:chat networkType:networkType];
}
- (bool)shouldDownloadDocumentInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_documents inChat:chat networkType:networkType];
}
- (bool)shouldDownloadVoiceMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_voiceMessages inChat:chat networkType:networkType];
}
- (bool)shouldDownloadVideoMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_videoMessages inChat:chat networkType:networkType];
}
- (bool)isDefaultPreferences
{
return [self isEqual:[TGAutoDownloadPreferences defaultPreferences]];
}
- (BOOL)isEqual:(id)object
{
if (object == self)
return YES;
if (!object || ![object isKindOfClass:[self class]])
return NO;
TGAutoDownloadPreferences *preferences = (TGAutoDownloadPreferences *)object;
return preferences.photos == _photos && preferences.videos == _videos && preferences.documents == _documents && preferences.voiceMessages == _voiceMessages && preferences.videoMessages == _videoMessages && preferences.maximumVideoSize == _maximumVideoSize && preferences.maximumDocumentSize == _maximumDocumentSize && preferences.disabled == _disabled;
}
@end

View file

@ -1,31 +0,0 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef enum
{
TGPresentationAutoNightModeDisabled,
TGPresentationAutoNightModeBrightness,
TGPresentationAutoNightModeScheduled,
TGPresentationAutoNightModeSunsetSunrise
} TGPresentationAutoNightMode;
@interface TGPresentationAutoNightPreferences : NSObject <NSCoding>
@property (nonatomic, readonly) TGPresentationAutoNightMode mode;
@property (nonatomic, readonly) CGFloat brightnessThreshold;
@property (nonatomic, readonly) int32_t scheduleStart;
@property (nonatomic, readonly) int32_t scheduleEnd;
@property (nonatomic, readonly) CGFloat latitude;
@property (nonatomic, readonly) CGFloat longitude;
@property (nonatomic, readonly) NSString *cachedLocationName;
@property (nonatomic, readonly) int32_t preferredPalette;
@end
NS_ASSUME_NONNULL_END

View file

@ -1,23 +0,0 @@
#import <LegacyDataImportImpl/TGPresentationAutoNightPreferences.h>
@implementation TGPresentationAutoNightPreferences
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self != nil) {
_mode = [aDecoder decodeInt32ForKey:@"m"];
_brightnessThreshold = [aDecoder decodeDoubleForKey:@"b"];
_scheduleStart = [aDecoder decodeInt32ForKey:@"ss"];
_scheduleEnd = [aDecoder decodeInt32ForKey:@"se"];
_latitude = [aDecoder decodeDoubleForKey:@"lat"];
_longitude = [aDecoder decodeDoubleForKey:@"lon"];
_cachedLocationName = [aDecoder decodeObjectForKey:@"loc"];
_preferredPalette = [aDecoder decodeInt32ForKey:@"p"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
}
@end

View file

@ -1,15 +0,0 @@
#import <Foundation/Foundation.h>
@interface TGProxyItem : NSObject <NSCoding>
@property (nonatomic, readonly) NSString *server;
@property (nonatomic, readonly) int16_t port;
@property (nonatomic, readonly) NSString *username;
@property (nonatomic, readonly) NSString *password;
@property (nonatomic, readonly) NSString *secret;
@property (nonatomic, readonly) bool isMTProxy;
- (instancetype)initWithServer:(NSString *)server port:(int16_t)port username:(NSString *)username password:(NSString *)password secret:(NSString *)secret;
@end

View file

@ -1,73 +0,0 @@
#import <LegacyDataImportImpl/TGProxyItem.h>
static bool TGObjectCompare(id obj1, id obj2) {
if (obj1 == nil && obj2 == nil)
return true;
return [obj1 isEqual:obj2];
}
@implementation TGProxyItem
- (instancetype)initWithServer:(NSString *)server port:(int16_t)port username:(NSString *)username password:(NSString *)password secret:(NSString *)secret
{
self = [super init];
if (self != nil)
{
_server = server;
_port = port;
_username = username;
_password = password;
_secret = secret;
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
return [self initWithServer:[aDecoder decodeObjectForKey:@"server"] port:(int16_t)[aDecoder decodeInt32ForKey:@"port"] username:[aDecoder decodeObjectForKey:@"user"] password:[aDecoder decodeObjectForKey:@"pass"] secret:[aDecoder decodeObjectForKey:@"secret"]];
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_server forKey:@"server"];
[aCoder encodeInt32:_port forKey:@"port"];
[aCoder encodeObject:_username forKey:@"user"];
[aCoder encodeObject:_password forKey:@"pass"];
[aCoder encodeObject:_secret forKey:@"secret"];
}
- (bool)isMTProxy
{
return _secret.length > 0;
}
- (BOOL)isEqual:(id)object
{
if (object == self)
return true;
if (!object || ![object isKindOfClass:[self class]])
return false;
TGProxyItem *proxy = (TGProxyItem *)object;
if (![_server isEqualToString:proxy.server])
return false;
if (_port != proxy.port)
return false;
if (!TGObjectCompare(_username ?: @"", proxy.username ?: @""))
return false;
if (!TGObjectCompare(_password ?: @"", proxy.password ?: @""))
return false;
if (!TGObjectCompare(_secret ?: @"", proxy.secret ?: @""))
return false;
return true;
}
@end

View file

@ -1,250 +0,0 @@
#import <LegacyDataImportImpl/TGAutoDownloadPreferences.h>
@implementation TGAutoDownloadPreferences
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self != nil)
{
_disabled = [aDecoder decodeBoolForKey:@"disabled"];
_photos = [aDecoder decodeInt32ForKey:@"photos"];
_videos = [aDecoder decodeInt32ForKey:@"videos"];
_maximumVideoSize = [aDecoder decodeInt32ForKey:@"maxVideoSize"];
_documents = [aDecoder decodeInt32ForKey:@"documents"];
_maximumDocumentSize = [aDecoder decodeInt32ForKey:@"maxDocumentSize"];
_voiceMessages = [aDecoder decodeInt32ForKey:@"voiceMessages"];
_videoMessages = [aDecoder decodeInt32ForKey:@"videoMessages"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeBool:_disabled forKey:@"disabled"];
[aCoder encodeInt32:_photos forKey:@"photos"];
[aCoder encodeInt32:_videos forKey:@"videos"];
[aCoder encodeInt32:_maximumVideoSize forKey:@"maxVideoSize"];
[aCoder encodeInt32:_documents forKey:@"documents"];
[aCoder encodeInt32:_maximumDocumentSize forKey:@"maxDocumentSize"];
[aCoder encodeInt32:_voiceMessages forKey:@"voiceMessages"];
[aCoder encodeInt32:_videoMessages forKey:@"videoMessages"];
}
+ (instancetype)defaultPreferences
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = TGAutoDownloadModeAll;
preferences->_videos = TGAutoDownloadModeNone;
preferences->_maximumVideoSize = 10;
preferences->_documents = TGAutoDownloadModeNone;
preferences->_maximumDocumentSize = 10;
preferences->_voiceMessages = TGAutoDownloadModeAll;
preferences->_videoMessages = TGAutoDownloadModeAll;
return preferences;
}
+ (instancetype)preferencesWithLegacyDownloadPrivatePhotos:(bool)privatePhotos groupPhotos:(bool)groupPhotos privateVoiceMessages:(bool)privateVoiceMessages groupVoiceMessages:(bool)groupVoiceMessages privateVideoMessages:(bool)privateVideoMessages groupVideoMessages:(bool)groupVideoMessages
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
if (privatePhotos)
preferences->_photos |= TGAutoDownloadModeAllPrivateChats;
if (groupPhotos)
preferences->_photos |= TGAutoDownloadModeAllGroups;
if (privateVoiceMessages)
preferences->_voiceMessages |= TGAutoDownloadModeAllPrivateChats;
if (groupVoiceMessages)
preferences->_voiceMessages |= TGAutoDownloadModeAllGroups;
if (privateVideoMessages)
preferences->_videoMessages |= TGAutoDownloadModeAllPrivateChats;
if (groupVideoMessages)
preferences->_videoMessages |= TGAutoDownloadModeAllGroups;
preferences->_maximumVideoSize = 10;
preferences->_maximumDocumentSize = 10;
return preferences;
}
- (instancetype)updateDisabled:(bool)disabled
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_disabled = disabled;
preferences->_photos = _photos;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updatePhotosMode:(TGAutoDownloadMode)mode
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = mode;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updateVideosMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = _photos;
preferences->_videos = mode;
preferences->_maximumVideoSize = maximumSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updateDocumentsMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = _photos;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = mode;
preferences->_maximumDocumentSize = maximumSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updateVoiceMessagesMode:(TGAutoDownloadMode)mode
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = _photos;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = mode;
preferences->_videoMessages = _videoMessages;
return preferences;
}
- (instancetype)updateVideoMessagesMode:(TGAutoDownloadMode)mode
{
TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init];
preferences->_photos = _photos;
preferences->_videos = _videos;
preferences->_maximumVideoSize = _maximumVideoSize;
preferences->_documents = _documents;
preferences->_maximumDocumentSize = _maximumDocumentSize;
preferences->_voiceMessages = _voiceMessages;
preferences->_videoMessages = mode;
return preferences;
}
+ (bool)shouldDownload:(TGAutoDownloadMode)mode inChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
bool isWiFi = networkType == TGNetworkTypeWiFi;
bool isCellular = !isWiFi && networkType != TGNetworkTypeNone;
bool shouldDownload = false;
switch (chat)
{
case TGAutoDownloadChatContact:
if (isCellular)
shouldDownload = (mode & TGAutoDownloadModeCellularContacts) != 0;
else if (isWiFi)
shouldDownload = (mode & TGAutoDownloadModeWifiContacts) != 0;
break;
case TGAutoDownloadChatOtherPrivateChat:
if (isCellular)
shouldDownload = (mode & TGAutoDownloadModeCellularPrivateChats) != 0;
else if (isWiFi)
shouldDownload = (mode & TGAutoDownloadModeWifiPrivateChats) != 0;
break;
case TGAutoDownloadChatGroup:
if (isCellular)
shouldDownload = (mode & TGAutoDownloadModeCellularGroups) != 0;
else if (isWiFi)
shouldDownload = (mode & TGAutoDownloadModeWifiGroups) != 0;
break;
case TGAutoDownloadChatChannel:
if (isCellular)
shouldDownload = (mode & TGAutoDownloadModeCellularChannels) != 0;
else if (isWiFi)
shouldDownload = (mode & TGAutoDownloadModeWifiChannels) != 0;
break;
default:
break;
}
return shouldDownload;
}
- (bool)shouldDownloadPhotoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_photos inChat:chat networkType:networkType];
}
- (bool)shouldDownloadVideoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_videos inChat:chat networkType:networkType];
}
- (bool)shouldDownloadDocumentInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_documents inChat:chat networkType:networkType];
}
- (bool)shouldDownloadVoiceMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_voiceMessages inChat:chat networkType:networkType];
}
- (bool)shouldDownloadVideoMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType
{
if (self.disabled)
return false;
return [TGAutoDownloadPreferences shouldDownload:_videoMessages inChat:chat networkType:networkType];
}
- (bool)isDefaultPreferences
{
return [self isEqual:[TGAutoDownloadPreferences defaultPreferences]];
}
- (BOOL)isEqual:(id)object
{
if (object == self)
return YES;
if (!object || ![object isKindOfClass:[self class]])
return NO;
TGAutoDownloadPreferences *preferences = (TGAutoDownloadPreferences *)object;
return preferences.photos == _photos && preferences.videos == _videos && preferences.documents == _documents && preferences.voiceMessages == _voiceMessages && preferences.videoMessages == _videoMessages && preferences.maximumVideoSize == _maximumVideoSize && preferences.maximumDocumentSize == _maximumDocumentSize && preferences.disabled == _disabled;
}
@end

View file

@ -1,23 +0,0 @@
#import <LegacyDataImportImpl/TGPresentationAutoNightPreferences.h>
@implementation TGPresentationAutoNightPreferences
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self != nil) {
_mode = [aDecoder decodeInt32ForKey:@"m"];
_brightnessThreshold = [aDecoder decodeDoubleForKey:@"b"];
_scheduleStart = [aDecoder decodeInt32ForKey:@"ss"];
_scheduleEnd = [aDecoder decodeInt32ForKey:@"se"];
_latitude = [aDecoder decodeDoubleForKey:@"lat"];
_longitude = [aDecoder decodeDoubleForKey:@"lon"];
_cachedLocationName = [aDecoder decodeObjectForKey:@"loc"];
_preferredPalette = [aDecoder decodeInt32ForKey:@"p"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
}
@end

View file

@ -1,73 +0,0 @@
#import <LegacyDataImportImpl/TGProxyItem.h>
static bool TGObjectCompare(id obj1, id obj2) {
if (obj1 == nil && obj2 == nil)
return true;
return [obj1 isEqual:obj2];
}
@implementation TGProxyItem
- (instancetype)initWithServer:(NSString *)server port:(int16_t)port username:(NSString *)username password:(NSString *)password secret:(NSString *)secret
{
self = [super init];
if (self != nil)
{
_server = server;
_port = port;
_username = username;
_password = password;
_secret = secret;
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
return [self initWithServer:[aDecoder decodeObjectForKey:@"server"] port:(int16_t)[aDecoder decodeInt32ForKey:@"port"] username:[aDecoder decodeObjectForKey:@"user"] password:[aDecoder decodeObjectForKey:@"pass"] secret:[aDecoder decodeObjectForKey:@"secret"]];
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_server forKey:@"server"];
[aCoder encodeInt32:_port forKey:@"port"];
[aCoder encodeObject:_username forKey:@"user"];
[aCoder encodeObject:_password forKey:@"pass"];
[aCoder encodeObject:_secret forKey:@"secret"];
}
- (bool)isMTProxy
{
return _secret.length > 0;
}
- (BOOL)isEqual:(id)object
{
if (object == self)
return true;
if (!object || ![object isKindOfClass:[self class]])
return false;
TGProxyItem *proxy = (TGProxyItem *)object;
if (![_server isEqualToString:proxy.server])
return false;
if (_port != proxy.port)
return false;
if (!TGObjectCompare(_username ?: @"", proxy.username ?: @""))
return false;
if (!TGObjectCompare(_password ?: @"", proxy.password ?: @""))
return false;
if (!TGObjectCompare(_secret ?: @"", proxy.secret ?: @""))
return false;
return true;
}
@end

View file

@ -1,197 +0,0 @@
import Foundation
class LegacyBuffer: CustomStringConvertible {
var data: UnsafeMutableRawPointer?
var _size: UInt = 0
private var capacity: UInt = 0
private let freeWhenDone: Bool
var size: Int {
return Int(self._size)
}
deinit {
if self.freeWhenDone {
free(self.data)
}
}
init(memory: UnsafeMutableRawPointer?, size: Int, capacity: Int, freeWhenDone: Bool) {
self.data = memory
self._size = UInt(size)
self.capacity = UInt(capacity)
self.freeWhenDone = freeWhenDone
}
init() {
self.data = nil
self._size = 0
self.capacity = 0
self.freeWhenDone = true
}
convenience init(data: Data?) {
self.init()
if let data = data {
data.withUnsafeBytes { bytes in
self.appendBytes(bytes, length: UInt(data.count))
}
}
}
func makeData() -> Data {
return self.withUnsafeMutablePointer { pointer, size -> Data in
if let pointer = pointer {
return Data(bytes: pointer.assumingMemoryBound(to: UInt8.self), count: Int(size))
} else {
return Data()
}
}
}
var description: String {
get {
var string = ""
if let data = self.data {
var i: UInt = 0
let bytes = data.assumingMemoryBound(to: UInt8.self)
while i < _size && i < 8 {
string += String(format: "%02x", Int(bytes.advanced(by: Int(i)).pointee))
i += 1
}
if i < _size {
string += "...\(_size)b"
}
} else {
string += "<null>"
}
return string
}
}
func appendBytes(_ bytes: UnsafeRawPointer, length: UInt) {
if self.capacity < self._size + length {
self.capacity = self._size + length + 128
if self.data == nil {
self.data = malloc(Int(self.capacity))!
}
else {
self.data = realloc(self.data, Int(self.capacity))!
}
}
memcpy(self.data?.advanced(by: Int(self._size)), bytes, Int(length))
self._size += length
}
func appendBuffer(_ buffer: LegacyBuffer) {
if self.capacity < self._size + buffer._size {
self.capacity = self._size + buffer._size + 128
if self.data == nil {
self.data = malloc(Int(self.capacity))!
}
else {
self.data = realloc(self.data, Int(self.capacity))!
}
}
memcpy(self.data?.advanced(by: Int(self._size)), buffer.data, Int(buffer._size))
}
func appendInt32(_ value: Int32) {
var v = value
self.appendBytes(&v, length: 4)
}
func appendInt64(_ value: Int64) {
var v = value
self.appendBytes(&v, length: 8)
}
func appendDouble(_ value: Double) {
var v = value
self.appendBytes(&v, length: 8)
}
func withUnsafeMutablePointer<R>(_ f: (UnsafeMutableRawPointer?, UInt) -> R) -> R {
return f(self.data, self._size)
}
}
class LegacyBufferReader {
private let buffer: LegacyBuffer
private(set) var offset: UInt = 0
init(_ buffer: LegacyBuffer) {
self.buffer = buffer
}
func reset() {
self.offset = 0
}
func skip(_ count: Int) {
self.offset = min(self.buffer._size, self.offset + UInt(count))
}
func readInt32() -> Int32? {
if self.offset + 4 <= self.buffer._size {
let value: Int32 = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Int32.self).pointee
self.offset += 4
return value
}
return nil
}
func readInt64() -> Int64? {
if self.offset + 8 <= self.buffer._size {
let value: Int64 = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Int64.self).pointee
self.offset += 8
return value
}
return nil
}
func readDouble() -> Double? {
if self.offset + 8 <= self.buffer._size {
let value: Double = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Double.self).pointee
self.offset += 8
return value
}
return nil
}
func readBytesAsInt32(_ count: Int) -> Int32? {
if count == 0 {
return 0
}
guard count > 0, count <= 4, self.offset + UInt(count) <= self.buffer._size else {
return nil
}
guard let bufferData = self.buffer.data else {
return nil
}
var value: Int32 = 0
memcpy(&value, bufferData.advanced(by: Int(self.offset)), count)
self.offset += UInt(count)
return value
}
func readBuffer(_ count: Int) -> LegacyBuffer? {
if count >= 0 && self.offset + UInt(count) <= self.buffer._size {
let buffer = LegacyBuffer()
buffer.appendBytes((self.buffer.data?.advanced(by: Int(self.offset)))!, length: UInt(count))
self.offset += UInt(count)
return buffer
}
return nil
}
func withReadBufferNoCopy<T>(_ count: Int, _ f: (LegacyBuffer) -> T) -> T? {
if count >= 0 && self.offset + UInt(count) <= self.buffer._size {
return f(LegacyBuffer(memory: self.buffer.data!.advanced(by: Int(self.offset)), size: count, capacity: count, freeWhenDone: false))
}
return nil
}
}

View file

@ -1,780 +0,0 @@
import Foundation
import TelegramCore
import SyncCore
import SwiftSignalKit
import Postbox
import LegacyComponents
private let reportedLayer_hash: Int32 = -717538193
private let layer_hash: Int32 = 849537378
private let seq_out_hash: Int32 = -737765753
private let seq_in_hash: Int32 = -7646011
private let defaultPrime: Data = {
let bytes: [UInt8] = [
0xc7, 0x1c, 0xae, 0xb9, 0xc6, 0xb1, 0xc9, 0x04, 0x8e, 0x6c, 0x52, 0x2f,
0x70, 0xf1, 0x3f, 0x73, 0x98, 0x0d, 0x40, 0x23, 0x8e, 0x3e, 0x21, 0xc1,
0x49, 0x34, 0xd0, 0x37, 0x56, 0x3d, 0x93, 0x0f, 0x48, 0x19, 0x8a, 0x0a,
0xa7, 0xc1, 0x40, 0x58, 0x22, 0x94, 0x93, 0xd2, 0x25, 0x30, 0xf4, 0xdb,
0xfa, 0x33, 0x6f, 0x6e, 0x0a, 0xc9, 0x25, 0x13, 0x95, 0x43, 0xae, 0xd4,
0x4c, 0xce, 0x7c, 0x37, 0x20, 0xfd, 0x51, 0xf6, 0x94, 0x58, 0x70, 0x5a,
0xc6, 0x8c, 0xd4, 0xfe, 0x6b, 0x6b, 0x13, 0xab, 0xdc, 0x97, 0x46, 0x51,
0x29, 0x69, 0x32, 0x84, 0x54, 0xf1, 0x8f, 0xaf, 0x8c, 0x59, 0x5f, 0x64,
0x24, 0x77, 0xfe, 0x96, 0xbb, 0x2a, 0x94, 0x1d, 0x5b, 0xcd, 0x1d, 0x4a,
0xc8, 0xcc, 0x49, 0x88, 0x07, 0x08, 0xfa, 0x9b, 0x37, 0x8e, 0x3c, 0x4f,
0x3a, 0x90, 0x60, 0xbe, 0xe6, 0x7c, 0xf9, 0xa4, 0xa4, 0xa6, 0x95, 0x81,
0x10, 0x51, 0x90, 0x7e, 0x16, 0x27, 0x53, 0xb5, 0x6b, 0x0f, 0x6b, 0x41,
0x0d, 0xba, 0x74, 0xd8, 0xa8, 0x4b, 0x2a, 0x14, 0xb3, 0x14, 0x4e, 0x0e,
0xf1, 0x28, 0x47, 0x54, 0xfd, 0x17, 0xed, 0x95, 0x0d, 0x59, 0x65, 0xb4,
0xb9, 0xdd, 0x46, 0x58, 0x2d, 0xb1, 0x17, 0x8d, 0x16, 0x9c, 0x6b, 0xc4,
0x65, 0xb0, 0xd6, 0xff, 0x9c, 0xa3, 0x92, 0x8f, 0xef, 0x5b, 0x9a, 0xe4,
0xe4, 0x18, 0xfc, 0x15, 0xe8, 0x3e, 0xbe, 0xa0, 0xf8, 0x7f, 0xa9, 0xff,
0x5e, 0xed, 0x70, 0x05, 0x0d, 0xed, 0x28, 0x49, 0xf4, 0x7b, 0xf9, 0x59,
0xd9, 0x56, 0x85, 0x0c, 0xe9, 0x29, 0x85, 0x1f, 0x0d, 0x81, 0x15, 0xf6,
0x35, 0xb1, 0x05, 0xee, 0x2e, 0x4e, 0x15, 0xd0, 0x4b, 0x24, 0x54, 0xbf,
0x6f, 0x4f, 0xad, 0xf0, 0x34, 0xb1, 0x04, 0x03, 0x11, 0x9c, 0xd8, 0xe3,
0xb9, 0x2f, 0xcc, 0x5b
]
var data = Data(count: bytes.count)
data.withUnsafeMutableBytes { (dst: UnsafeMutablePointer<UInt8>) -> Void in
for i in 0 ..< bytes.count {
dst.advanced(by: i).pointee = bytes[i]
}
}
return data
}()
@objc(TGEncryptionKeyData) private final class TGEncryptionKeyData: NSObject, NSCoding {
let keyId: Int64
let key: Data
let firstSeqOut: Int32
init?(coder aDecoder: NSCoder) {
self.keyId = aDecoder.decodeInt64(forKey: "keyId")
self.key = (aDecoder.decodeObject(forKey: "key") as? Data) ?? Data()
self.firstSeqOut = aDecoder.decodeInt32(forKey: "firstSeqOut")
}
func encode(with aCoder: NSCoder) {
assertionFailure()
}
}
private struct SecretChatData {
let accessHash: Int64
let handshakeState: Int32
let rekeyState: SecretChatRekeySessionState?
}
private func readSecretChatParticipantData(accountPeerId: PeerId, data: Data) -> (SecretChatRole, PeerId)? {
let reader = LegacyBufferReader(LegacyBuffer(data: data))
guard reader.readInt32() == Int32(bitPattern: 0xabcdef12) else {
return nil
}
guard let formatVersion = reader.readInt32(), formatVersion >= 2 else {
return nil
}
reader.skip(4)
guard let adminId = reader.readInt32() else {
return nil
}
guard let count = reader.readInt32() else {
return nil
}
var ids: [Int32] = []
for _ in 0 ..< Int(count) {
guard let id = reader.readInt32() else {
return nil
}
reader.skip(4)
reader.skip(4)
ids.append(id)
}
guard let otherPeerId = ids.first else {
return nil
}
return (adminId == accountPeerId.id ? .creator : .participant, PeerId(namespace: Namespaces.Peer.CloudUser, id: otherPeerId))
}
private func readSecretChatData(reader: LegacyBufferReader) -> SecretChatData? {
guard let version = reader.readBytesAsInt32(1) else {
return nil
}
if version != 3 {
return nil
}
reader.skip(8)
guard let accessHash = reader.readInt64() else {
return nil
}
guard let _ = reader.readInt64() else {
return nil
}
guard let handshakeState = reader.readInt32() else {
return nil
}
guard let currentRekeyExchangeId = reader.readInt64() else {
return nil
}
guard let currentRekeyIsInitiatedByLocalClient = reader.readBytesAsInt32(1) else {
return nil
}
guard let currentRekeyNumberLength = reader.readInt32() else {
return nil
}
var currentRekeyNumber: Data?
if currentRekeyNumberLength > 0 {
guard let value = reader.readBuffer(Int(currentRekeyNumberLength))?.makeData() else {
return nil
}
currentRekeyNumber = value
}
guard let currentRekeyKeyLength = reader.readInt32() else {
return nil
}
var currentRekeyKey: Data?
if currentRekeyKeyLength > 0 {
guard let value = reader.readBuffer(Int(currentRekeyKeyLength))?.makeData() else {
return nil
}
currentRekeyKey = value
}
guard let currentRekeyKeyId = reader.readInt64() else {
return nil
}
var rekeyState: SecretChatRekeySessionState?
if currentRekeyExchangeId != 0 {
let innerState: SecretChatRekeySessionData?
if currentRekeyIsInitiatedByLocalClient != 0, let currentRekeyNumber = currentRekeyNumber {
innerState = .requested(a: MemoryBuffer(data: currentRekeyNumber), config: SecretChatEncryptionConfig(g: 3, p: MemoryBuffer(data: defaultPrime), version: 0))
} else if currentRekeyIsInitiatedByLocalClient == 0, let currentRekeyKey = currentRekeyKey, currentRekeyKeyId != 0 {
innerState = .accepted(key: MemoryBuffer(data: currentRekeyKey), keyFingerprint: currentRekeyKeyId)
} else {
innerState = nil
}
if let innerState = innerState {
rekeyState = SecretChatRekeySessionState(id: currentRekeyExchangeId, data: innerState)
}
}
return SecretChatData(accessHash: accessHash, handshakeState: handshakeState, rekeyState: rekeyState)
}
let registeredAttachmentParsers: Bool = {
let parsers: [(Int32, TGMediaAttachmentParser)] = [
(TGActionMediaAttachmentType, TGActionMediaAttachment()),
(TGImageMediaAttachmentType, TGImageMediaAttachment()),
(TGLocationMediaAttachmentType, TGLocationMediaAttachment()),
(TGVideoMediaAttachmentType, TGVideoMediaAttachment()),
(Int32(bitPattern: 0xB90A5663), TGContactMediaAttachment()),
(Int32(bitPattern: 0xE6C64318), TGDocumentMediaAttachment()),
(TGAudioMediaAttachmentType, TGAudioMediaAttachment()),
(Int32(bitPattern: 0x8C2E3CCE), TGMessageEntitiesAttachment()),
(Int32(bitPattern: 0x944DE6B6), TGLocalMessageMetaMediaAttachment()),
(TGAuthorSignatureMediaAttachmentType, TGAuthorSignatureMediaAttachment()),
(TGInvoiceMediaAttachmentType, TGInvoiceMediaAttachment()),
(TGGameAttachmentType, TGGameMediaAttachment()),
(Int32(bitPattern: 0xA3F4C8F5), TGViaUserAttachment()),
(TGBotContextResultAttachmentType, TGBotContextResultAttachment()),
(TGReplyMarkupAttachmentType, TGReplyMarkupAttachment()),
(TGWebPageMediaAttachmentType, TGWebPageMediaAttachment()),
(TGReplyMessageMediaAttachmentType, TGReplyMessageMediaAttachment()),
(TGAudioMediaAttachmentType, TGAudioMediaAttachment()),
(Int32(bitPattern: 0xaa1050c1), TGForwardedMessageMediaAttachment())
]
for (id, parser) in parsers {
TGMessage.registerMediaAttachmentParser(id, parser: parser)
}
return true
}()
private func parseSecretChatData(peerId: PeerId, data: Data, unreadCount: Int32) -> (SecretChatData, [MessageId.Namespace: PeerReadState], Int32)? {
let reader = LegacyBufferReader(LegacyBuffer(data: data))
guard let magic = reader.readInt32() else {
return nil
}
var version: Int32 = 1
if magic == 0x7acde441 {
guard let value = reader.readInt32() else {
return nil
}
version = value
}
if version < 2 {
return nil
}
for _ in 0 ..< 3 {
guard let length = reader.readInt32() else {
return nil
}
reader.skip(Int(length))
}
guard let hasEncryptedData = reader.readBytesAsInt32(1), hasEncryptedData == 1 else {
return nil
}
guard let secretChatData = readSecretChatData(reader: reader) else {
return nil
}
reader.skip(4)
reader.skip(4)
reader.skip(8)
reader.skip(4)
reader.skip(4)
reader.skip(4)
reader.skip(4)
guard let maxReadDate = reader.readInt32() else {
return nil
}
guard let maxOutgoingReadDate = reader.readInt32() else {
return nil
}
guard let messageDate = reader.readInt32() else {
return nil
}
guard let minMessageDate = reader.readInt32() else {
return nil
}
let readStates: [MessageId.Namespace: PeerReadState] = [
Namespaces.Message.SecretIncoming: .indexBased(maxIncomingReadIndex: MessageIndex(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: 1), timestamp: maxReadDate), maxOutgoingReadIndex: MessageIndex.lowerBound(peerId: peerId), count: 0, markedUnread: false),
Namespaces.Message.Local: .indexBased(maxIncomingReadIndex: MessageIndex.lowerBound(peerId: peerId), maxOutgoingReadIndex: MessageIndex(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Local, id: 1), timestamp: maxOutgoingReadDate), count: 0, markedUnread: false)
]
return (secretChatData, readStates, max(messageDate, minMessageDate))
}
private enum CustomPropertyKey {
case string(String)
case hash(Int32)
}
private func loadLegacyPeerCustomProperyData(database: SqliteInterface, peerId: Int64, key: CustomPropertyKey) -> Data? {
var propertiesData: Data?
database.select("SELECT custom_properties FROM peers_v29 WHERE pid=\(peerId)", { cursor in
propertiesData = cursor.getData(at: 0)
return false
})
if let propertiesData = propertiesData {
let keyHash: Int32
switch key {
case let .string(string):
keyHash = HashFunctions.murMurHash32(string)
case let .hash(hash):
keyHash = hash
}
let reader = LegacyBufferReader(LegacyBuffer(data: propertiesData))
guard let _ = reader.readInt32() else {
return nil
}
guard let count = reader.readInt32() else {
return nil
}
for _ in 0 ..< Int(count) {
guard let valueKey = reader.readInt32() else {
return nil
}
guard let valueLength = reader.readInt32() else {
return nil
}
if valueKey == keyHash {
return reader.readBuffer(Int(valueLength))?.makeData()
}
reader.skip(Int(valueLength))
}
}
return nil
}
private func loadLegacyPeerCustomProperyInt32(database: SqliteInterface, peerId: Int64, key: CustomPropertyKey) -> Int32? {
guard let data = loadLegacyPeerCustomProperyData(database: database, peerId: peerId, key: key), data.count == 4 else {
return nil
}
var result: Int32 = 0
withUnsafeMutablePointer(to: &result, { bytes -> Void in
data.copyBytes(to: UnsafeMutableRawPointer(bytes).assumingMemoryBound(to: UInt8.self), from: 0 ..< 4)
})
return result
}
private func loadLegacyMessages(account: TemporaryAccount, basePath: String, accountPeerId: PeerId, peerId: PeerId, userPeerId: PeerId, database: SqliteInterface, conversationId: Int64, expectedTotalCount: Int32) -> Signal<Float, NoError> {
return Signal { subscriber in
subscriber.putNext(0.0)
var copyLocalFiles: [(MediaResource, String)] = []
var messages: [StoreMessage] = []
Logger.shared.log("loadLegacyMessages", "begin peerId \(peerId) conversationId \(conversationId) count \(expectedTotalCount)")
database.select("CREATE INDEX IF NOT EXISTS random_ids_mid ON random_ids_v29 (mid)", { _ in
return true
})
var messageIndex: Int32 = -1
let reportBase = max(1, expectedTotalCount / 100)
database.select("SELECT mid, message, media, from_id, dstate, date, flags, localMid, content_properties FROM messages_v29 WHERE cid=\(conversationId)", { cursor in
messageIndex += 1
#if DEBUG
//usleep(500000)
#endif
if messageIndex % reportBase == 0 {
subscriber.putNext(min(1.0, Float(messageIndex) / Float(expectedTotalCount)))
}
let messageId = cursor.getInt32(at: 0)
//Logger.shared.log("loadLegacyMessages", "import message \(messageId)")
var globallyUniqueId: Int64?
database.select("SELECT random_id FROM random_ids_v29 where mid=\(messageId)", { innerCursor in
globallyUniqueId = innerCursor.getInt64(at: 0)
return false
})
let text = cursor.getString(at: 1)
let fromId = cursor.getInt64(at: 3)
let deliveryState = cursor.getInt32(at: 4)
let timestamp = cursor.getInt32(at: 5)
let autoremoveTimeout = cursor.getInt32(at: 7)
let contentPropertiesData = cursor.getData(at: 8)
let parsedAuthorId: PeerId
let parsedId: StoreMessageId
var parsedFlags: StoreMessageFlags = []
var parsedAttributes: [MessageAttribute] = []
var parsedMedia: [Media] = []
var parsedGroupingKey: Int64?
if fromId == accountPeerId.id {
parsedAuthorId = accountPeerId
parsedId = .Partial(peerId, Namespaces.Message.Local)
} else {
parsedAuthorId = userPeerId
parsedId = .Partial(peerId, Namespaces.Message.SecretIncoming)
parsedFlags.insert(.Incoming)
}
if deliveryState != 0 {
return true
}
if !contentPropertiesData.isEmpty {
if let contentProperties = TGMessage.parseContentProperties(contentPropertiesData) {
for (_, value) in contentProperties {
if let value = value as? TGMessageGroupedIdContentProperty {
parsedGroupingKey = value.groupedId
}
}
}
}
//Logger.shared.log("loadLegacyMessages", "message \(messageId) read content properties")
let media = cursor.getData(at: 2)
if let mediaList = TGMessage.parseMediaAttachments(media) {
for item in mediaList {
if let item = item as? TGImageMediaAttachment {
let mediaId = MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64())
var representations: [TelegramMediaImageRepresentation] = []
if let allSizes = item.imageInfo?.allSizes() as? [String: NSValue] {
for (imageUrl, sizeValue) in allSizes {
var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64())
var resourcePath: String?
if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: imageUrl, type: .image) {
resource = updatedResource
copyLocalFiles.append((updatedResource, path))
resourcePath = path
} else if imageUrl.hasPrefix("file://"), let path = URL(string: imageUrl)?.path {
copyLocalFiles.append((resource, path))
resourcePath = path
}
var dimensions = sizeValue.cgSizeValue
if let resourcePath = resourcePath, let image = UIImage(contentsOfFile: resourcePath) {
dimensions = image.size
}
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(dimensions), resource: resource, progressiveSizes: []))
}
}
if item.localImageId != 0 {
let fullSizePath = basePath + "/Documents/files/image-local-\(String(item.localImageId, radix: 16))/image.jpg"
if let image = UIImage(contentsOfFile: fullSizePath) {
let resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64())
copyLocalFiles.append((resource, fullSizePath))
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(image.size), resource: resource, progressiveSizes: []))
}
}
parsedMedia.append(TelegramMediaImage(imageId: mediaId, representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []))
} else if let item = item as? TGVideoMediaAttachment {
let mediaId = MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64())
var representations: [TelegramMediaImageRepresentation] = []
if let allSizes = item.thumbnailInfo?.allSizes() as? [String: NSValue] {
for (imageUrl, sizeValue) in allSizes {
var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64())
if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: imageUrl, type: .image) {
resource = updatedResource
copyLocalFiles.append((updatedResource, path))
} else if imageUrl.hasPrefix("file://"), let path = URL(string: imageUrl)?.path {
copyLocalFiles.append((resource, path))
}
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(sizeValue.cgSizeValue), resource: resource, progressiveSizes: []))
}
}
var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64())
var attributes: [TelegramMediaFileAttribute] = []
attributes.append(.Video(duration: Int(item.duration), size: PixelDimensions(item.dimensions), flags: item.roundMessage ? .instantRoundVideo : []))
var size: Int32 = 0
if let videoUrl = item.videoInfo?.url(withQuality: 1, actualQuality: nil, actualSize: &size) {
if let path = pathFromLegacyLocalVideoUrl(basePath: basePath, url: videoUrl) {
copyLocalFiles.append((resource, path))
} else if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: videoUrl, type: .video) {
resource = updatedResource
copyLocalFiles.append((updatedResource, path))
} else if videoUrl.hasPrefix("file://"), let path = URL(string: videoUrl)?.path {
copyLocalFiles.append((resource, path))
}
}
parsedMedia.append(TelegramMediaFile(fileId: mediaId, partialReference: nil, resource: resource, previewRepresentations: representations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: size == 0 ? nil : Int(size), attributes: attributes))
} else if let item = item as? TGAudioMediaAttachment {
let mediaId = MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64())
let representations: [TelegramMediaImageRepresentation] = []
var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64())
var attributes: [TelegramMediaFileAttribute] = []
attributes.append(.Audio(isVoice: true, duration: Int(item.duration), title: nil, performer: nil, waveform: nil))
let size: Int32 = item.fileSize
let audioUrl = item.audioUri ?? ""
if let path = pathFromLegacyLocalVideoUrl(basePath: basePath, url: audioUrl) {
copyLocalFiles.append((resource, path))
} else if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: audioUrl, type: .audio) {
resource = updatedResource
copyLocalFiles.append((updatedResource, path))
} else if audioUrl.hasPrefix("file://"), let path = URL(string: audioUrl)?.path {
copyLocalFiles.append((resource, path))
}
parsedMedia.append(TelegramMediaFile(fileId: mediaId, partialReference: nil, resource: resource, previewRepresentations: representations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: size == 0 ? nil : Int(size), attributes: attributes))
} else if let item = item as? TGDocumentMediaAttachment {
let mediaId = MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64())
var representations: [TelegramMediaImageRepresentation] = []
if let allSizes = (item.thumbnailInfo?.allSizes()) as? [String: NSValue] {
for (imageUrl, sizeValue) in allSizes {
var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64())
if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: imageUrl, type: .image) {
resource = updatedResource
copyLocalFiles.append((updatedResource, path))
} else if imageUrl.hasPrefix("file://"), let path = URL(string: imageUrl)?.path {
copyLocalFiles.append((resource, path))
} else if let updatedResource = resourceFromLegacyImageUrl(imageUrl) {
resource = updatedResource
copyLocalFiles.append((resource, pathFromLegacyImageUrl(basePath: basePath, url: imageUrl)))
}
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(sizeValue.cgSizeValue), resource: resource, progressiveSizes: []))
}
}
var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64())
var attributes: [TelegramMediaFileAttribute] = []
var fileName = "file"
if let itemAttributes = item.attributes {
for attribute in itemAttributes {
if let attribute = attribute as? TGDocumentAttributeFilename {
attributes.append(.FileName(fileName: attribute.filename ?? "file"))
fileName = attribute.filename ?? "file"
} else if let attribute = attribute as? TGDocumentAttributeAudio {
let title = attribute.title ?? ""
let performer = attribute.performer ?? ""
var waveform: MemoryBuffer?
if let data = attribute.waveform {
waveform = MemoryBuffer(data: data.bitstream()!)
}
attributes.append(.Audio(isVoice: attribute.isVoice, duration: Int(attribute.duration), title: title.isEmpty ? nil : title, performer: performer.isEmpty ? nil : performer, waveform: waveform))
} else if let _ = attribute as? TGDocumentAttributeAnimated {
attributes.append(.Animated)
} else if let attribute = attribute as? TGDocumentAttributeVideo {
attributes.append(.Video(duration: Int(attribute.duration), size: PixelDimensions(attribute.size), flags: attribute.isRoundMessage ? .instantRoundVideo : []))
} else if let attribute = attribute as? TGDocumentAttributeSticker {
var packReference: StickerPackReference?
if let reference = attribute.packReference as? TGStickerPackIdReference {
packReference = .id(id: reference.packId, accessHash: reference.packAccessHash)
} else if let reference = attribute.packReference as? TGStickerPackShortnameReference {
packReference = .name(reference.shortName ?? "")
}
attributes.append(.Sticker(displayText: attribute.alt ?? "", packReference: packReference, maskData: nil))
} else if let attribute = attribute as? TGDocumentAttributeImageSize {
attributes.append(.ImageSize(size: PixelDimensions(attribute.size)))
}
}
}
let documentUri = item.documentUri ?? ""
let size: Int32 = item.size
if documentUri.hasPrefix("file://"), let path = URL(string: documentUri)?.path {
copyLocalFiles.append((resource, path))
} else if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: documentUri, type: .document(fileName: fileName)) {
resource = updatedResource
copyLocalFiles.append((resource, path))
} else if item.localDocumentId != 0 {
copyLocalFiles.append((resource, pathFromLegacyFile(basePath: basePath, fileId: item.localDocumentId, isLocal: true, fileName: TGDocumentMediaAttachment.safeFileName(forFileName: fileName) ?? "")))
} else if item.documentId != 0 {
copyLocalFiles.append((resource, pathFromLegacyFile(basePath: basePath, fileId: item.documentId, isLocal: false, fileName: TGDocumentMediaAttachment.safeFileName(forFileName: fileName) ?? "")))
}
parsedMedia.append(TelegramMediaFile(fileId: mediaId, partialReference: nil, resource: resource, previewRepresentations: representations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: item.mimeType ?? "application/octet-stream", size: size == 0 ? nil : Int(size), attributes: attributes))
} else if let item = item as? TGActionMediaAttachment {
if item.actionType == TGMessageActionEncryptedChatMessageLifetime, let actionData = item.actionData, let timeout = actionData["messageLifetime"] as? Int32 {
parsedMedia.append(TelegramMediaAction(action: .messageAutoremoveTimeoutUpdated(timeout)))
}
} else if let item = item as? TGContactMediaAttachment {
parsedMedia.append(TelegramMediaContact(firstName: item.firstName ?? "", lastName: item.lastName ?? "", phoneNumber: item.phoneNumber ?? "", peerId: nil, vCardData: nil))
} else if let item = item as? TGLocationMediaAttachment {
var venue: MapVenue?
if let v = item.venue {
venue = MapVenue(title: v.title ?? "", address: v.address ?? "", provider: v.provider == "" ? nil : v.provider, id: v.venueId == "" ? nil : v.venueId, type: v.type == "" ? nil : v.type)
}
parsedMedia.append(TelegramMediaMap(latitude: item.latitude, longitude: item.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: venue, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))
}
}
}
//Logger.shared.log("loadLegacyMessages", "message \(messageId) read media")
if autoremoveTimeout != 0 {
var countdownBeginTime: Int32?
database.select("SELECT date FROM selfdestruct_v29 where mid=\(messageId)", { innerCursor in
countdownBeginTime = innerCursor.getInt32(at: 0) - autoremoveTimeout
return false
})
parsedAttributes.append(AutoremoveTimeoutMessageAttribute(timeout: autoremoveTimeout, countdownBeginTime: countdownBeginTime))
}
let (parsedTags, parsedGlobalTags) = tagsForStoreMessage(incoming: parsedFlags.contains(.Incoming), attributes: parsedAttributes, media: parsedMedia, textEntities: nil, isPinned: false)
messages.append(StoreMessage(id: parsedId, globallyUniqueId: globallyUniqueId, groupingKey: parsedGroupingKey, threadId: nil, timestamp: timestamp, flags: parsedFlags, tags: parsedTags, globalTags: parsedGlobalTags, localTags: [], forwardInfo: nil, authorId: parsedAuthorId, text: text, attributes: parsedAttributes, media: parsedMedia))
//Logger.shared.log("loadLegacyMessages", "message \(messageId) completed")
return true
})
let disposable = (account.postbox.transaction { transaction -> Void in
//Logger.shared.log("loadLegacyMessages", "conversation \(conversationId) storing messages")
let _ = transaction.addMessages(messages, location: .UpperHistoryBlock)
//Logger.shared.log("loadLegacyMessages", "conversation \(conversationId) copying \(copyLocalFiles.count) files")
for (resource, path) in copyLocalFiles {
account.postbox.mediaBox.copyResourceData(resource.id, fromTempPath: path)
}
Logger.shared.log("loadLegacyMessages", "conversation \(conversationId) done")
}).start(completed: {
subscriber.putCompletion()
})
return disposable
}
}
private func importChannelBroadcastPreferences(account: TemporaryAccount, basePath: String, database: SqliteInterface) -> Signal<Never, NoError> {
return deferred { () -> Signal<Never, NoError> in
var peerIds: [Int64] = []
database.select("SELECT cid FROM channel_conversations_v29", { cursor in
peerIds.append(cursor.getInt64(at: 0))
return true
})
var peerIdsWithMutedMessages: [Int64] = []
for peerId in peerIds {
if let data = loadLegacyPeerCustomProperyData(database: database, peerId: peerId, key: .hash(0x374BF349)), !data.isEmpty {
let reader = LegacyBufferReader(LegacyBuffer(data: data))
guard let version = reader.readBytesAsInt32(1) else {
continue
}
guard let _ = reader.readBytesAsInt32(1) else {
continue
}
if version >= 2 {
guard let messagesMuted = reader.readBytesAsInt32(1) else {
continue
}
if messagesMuted == 1 {
peerIdsWithMutedMessages.append(peerId)
}
}
}
}
return .complete()
}
}
func loadLegacySecretChats(account: TemporaryAccount, basePath: String, accountPeerId: PeerId, database: SqliteInterface) -> Signal<Float, NoError> {
return deferred { () -> Signal<Float, NoError> in
var peerIdToConversationId: [PeerId: Int64] = [:]
database.select("SELECT encrypted_id, cid FROM encrypted_cids_v29", { cursor in
peerIdToConversationId[PeerId(namespace: Namespaces.Peer.SecretChat, id: cursor.getInt32(at: 0))] = cursor.getInt64(at: 1)
return true
})
var chatInfos: [(TelegramSecretChat, SecretChatState, Int32?, [MessageId.Namespace: PeerReadState], Int64)] = []
for (peerId, conversationId) in peerIdToConversationId {
database.select("SELECT chat_photo, unread_count, participants, date FROM convesations_v29 WHERE cid=\(conversationId)", { cursor in
guard let (secretChatData, readStates, minMessageDate) = parseSecretChatData(peerId: peerId, data: cursor.getData(at: 0), unreadCount: cursor.getInt32(at: 1)) else {
return false
}
guard let (role, userPeerId) = readSecretChatParticipantData(accountPeerId: accountPeerId, data: cursor.getData(at: 2)) else {
return false
}
let chatMessageDate = cursor.getInt32(at: 3)
let messageDate = min(minMessageDate, chatMessageDate)
let messageLifetime = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .string("messageLifetime")) ?? 0
let state: SecretChatState
var seqOut: Int32?
switch secretChatData.handshakeState {
case 1: //requested
guard let a = loadLegacyPeerCustomProperyData(database: database, peerId: conversationId, key: .string("a")), !a.isEmpty else {
return false
}
state = SecretChatState(role: .creator, embeddedState: .handshake(.requested(g: 3, p: MemoryBuffer(data: defaultPrime), a: MemoryBuffer(data: a))), keychain: SecretChatKeychain(keys: []), keyFingerprint: nil, messageAutoremoveTimeout: nil)
case 2: //accepting
return false
case 3: //terminated
state = SecretChatState(role: .creator, embeddedState: .terminated, keychain: SecretChatKeychain(keys: []), keyFingerprint: nil, messageAutoremoveTimeout: nil)
case 4:
guard let sha1Fingerprint = loadLegacyPeerCustomProperyData(database: database, peerId: conversationId, key: .string("encryptionKeySha1")) else {
return false
}
guard let sha256Fingerprint = loadLegacyPeerCustomProperyData(database: database, peerId: conversationId, key: .string("encryptionKeySha256")) else {
return false
}
guard let keysData = loadLegacyPeerCustomProperyData(database: database, peerId: conversationId, key: .string("encryptionKeys")) else {
return false
}
guard let keysArray = NSKeyedUnarchiver.unarchiveObject(with: keysData) as? [TGEncryptionKeyData] else {
return false
}
let parsedKeys: [SecretChatKey] = keysArray.map({ key in
return SecretChatKey(fingerprint: key.keyId, key: MemoryBuffer(data: key.key), validity: .sequenceBasedIndexRange(fromCanonicalIndex: key.firstSeqOut), useCount: 1)
})
let requestedLayerValue = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .hash(reportedLayer_hash)) ?? 0
let appliedSeqInValue = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .hash(seq_in_hash)) ?? 0
guard let seqOutValue = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .hash(seq_out_hash)) else {
return false
}
seqOut = seqOutValue
guard let activeLayerValue = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .hash(layer_hash)) else {
return false
}
guard let activeLayer = SecretChatSequenceBasedLayer(rawValue: activeLayerValue) else {
return false
}
let rekeyState: SecretChatRekeySessionState? = secretChatData.rekeyState
let embeddedState: SecretChatEmbeddedState = .sequenceBasedLayer(SecretChatSequenceBasedLayerState(layerNegotiationState: SecretChatLayerNegotiationState(activeLayer: activeLayer, locallyRequestedLayer: requestedLayerValue == 0 ? nil : requestedLayerValue, remotelyRequestedLayer: nil), rekeyState: rekeyState, baseIncomingOperationIndex: 0, baseOutgoingOperationIndex: 0, topProcessedCanonicalIncomingOperationIndex: appliedSeqInValue == 0 ? nil : max(0, appliedSeqInValue - 1)))
state = SecretChatState(role: role, embeddedState: embeddedState, keychain: SecretChatKeychain(keys: parsedKeys), keyFingerprint: SecretChatKeyFingerprint(sha1: SecretChatKeySha1Fingerprint(digest: sha1Fingerprint), sha256: SecretChatKeySha256Fingerprint(digest: sha256Fingerprint)), messageAutoremoveTimeout: messageLifetime == 0 ? nil : messageLifetime)
default:
return false
}
let secretChat = TelegramSecretChat(id: peerId, creationDate: messageDate, regularPeerId: userPeerId, accessHash: secretChatData.accessHash, role: role, embeddedState: state.embeddedState.peerState, messageAutoremoveTimeout: messageLifetime == 0 ? nil : messageLifetime)
chatInfos.append((secretChat, state, seqOut, readStates, conversationId))
return false
})
}
var userPeers: [PeerId: Peer] = [:]
var presences: [PeerId: PeerPresence] = [:]
for info in chatInfos {
if let (peer, presence) = loadLegacyUser(database: database, id: info.0.regularPeerId.id) {
userPeers[peer.id] = peer
presences[peer.id] = presence
}
}
let storedChats = account.postbox.transaction { transaction -> Void in
updatePeers(transaction: transaction, peers: Array(userPeers.values), update: { _, updated in
return updated
})
transaction.updatePeerPresencesInternal(presences: presences, merge: { _, updated in return updated })
for (peer, state, seqOutValue, readStates, _) in chatInfos {
if userPeers[peer.regularPeerId] == nil {
continue
}
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in
return updated
})
transaction.setPeerChatState(peer.id, state: state)
switch state.embeddedState {
case .sequenceBasedLayer:
if let seqOutValue = seqOutValue {
transaction.operationLogResetIndices(peerId: peer.id, tag: OperationLogTags.SecretOutgoing, nextTagLocalIndex: seqOutValue + 1)
}
default:
break
}
transaction.resetIncomingReadStates([peer.id: readStates])
}
}
|> ignoreValues
let _ = registeredAttachmentParsers
var countByConversationId: [Int64: Int32] = [:]
var totalCount: Int32 = 0
for info in chatInfos {
database.select("SELECT COUNT(*) FROM messages_v29 WHERE cid=\(info.4)", { cursor in
let count = cursor.getInt32(at: 0)
countByConversationId[info.4] = count
totalCount += count
return true
})
}
var storedMessagesSignals: Signal<Float, NoError> = .single(0.0)
var cumulativeCount: Int32 = 0
for info in chatInfos {
let localBaseline = cumulativeCount
let localCount = countByConversationId[info.4] ?? 0
storedMessagesSignals = storedMessagesSignals
|> then(
loadLegacyMessages(account: account, basePath: basePath, accountPeerId: accountPeerId, peerId: info.0.id, userPeerId: info.0.regularPeerId, database: database, conversationId: info.4, expectedTotalCount: localCount)
|> map { localProgress -> Float in
if totalCount <= 0 {
return 0.0
}
let globalCount = localBaseline + Int32(localProgress * Float(localCount))
return Float(globalCount) / Float(totalCount)
}
)
cumulativeCount += countByConversationId[info.4] ?? 0
}
return storedChats
|> map { _ -> Float in return 0.0 }
|> then(storedMessagesSignals)
}
}

View file

@ -1,245 +0,0 @@
import Foundation
import UIKit
import TelegramCore
import SyncCore
import SwiftSignalKit
import Postbox
import MtProtoKit
import LegacyDataImportImpl
public enum AccountImportError: Error {
case generic
}
public enum AccountImportProgressType {
case generic
case messages
case media
}
private func importedAccountData(basePath: String, documentsPath: String, accountManager: AccountManager, account: TemporaryAccount, database: SqliteInterface) -> Signal<(AccountImportProgressType, Float), AccountImportError> {
return deferred { () -> Signal<(AccountImportProgressType, Float), AccountImportError> in
let keychain = MTFileBasedKeychain(name: "Telegram", documentsPath: documentsPath)
guard let masterDatacenterId = keychain.object(forKey: "defaultDatacenterId", group: "persistent") as? Int else {
return .fail(.generic)
}
let keychainContents = keychain.contents(forGroup: "persistent")
let importKeychain = account.postbox.transaction { transaction -> Void in
for (key, value) in keychainContents {
let data = NSKeyedArchiver.archivedData(withRootObject: value)
transaction.setKeychainEntry(data, forKey: "persistent" + ":" + key)
}
}
|> ignoreValues
|> castError(AccountImportError.self)
let importData = importPreferencesData(documentsPath: documentsPath, masterDatacenterId: Int32(masterDatacenterId), account: account, database: database)
|> mapToSignal { accountUserId -> Signal<(AccountImportProgressType, Float), AccountImportError> in
return importDatabaseData(accountManager: accountManager, account: account, basePath: basePath, database: database, accountUserId: accountUserId)
}
return importKeychain
|> map { _ -> (AccountImportProgressType, Float) in return (.generic, 0.0) }
|> then(importData)
}
}
private func importPreferencesData(documentsPath: String, masterDatacenterId: Int32, account: TemporaryAccount, database: SqliteInterface) -> Signal<Int32, AccountImportError> {
return deferred { () -> Signal<Int32, AccountImportError> in
let defaultsPath = documentsPath + "/standard.defaults"
var parsedAccountUserId: Int32?
if let data = try? Data(contentsOf: URL(fileURLWithPath: defaultsPath)), let dict = NSKeyedUnarchiver.unarchiveObject(with: data) as? [String: Any], let id = dict["telegraphUserId"] as? Int {
parsedAccountUserId = Int32(id)
}
if parsedAccountUserId == nil {
if let id = UserDefaults.standard.object(forKey: "telegraphUserId") as? Int {
parsedAccountUserId = Int32(id)
}
}
if let parsedAccountUserId = parsedAccountUserId {
return account.postbox.transaction { transaction -> Int32 in
transaction.setState(AuthorizedAccountState(isTestingEnvironment: false, masterDatacenterId: masterDatacenterId, peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: parsedAccountUserId), state: nil))
return parsedAccountUserId
}
|> castError(AccountImportError.self)
} else {
return .fail(.generic)
}
}
}
private func importDatabaseData(accountManager: AccountManager, account: TemporaryAccount, basePath: String, database: SqliteInterface, accountUserId: Int32) -> Signal<(AccountImportProgressType, Float), AccountImportError> {
return deferred { () -> Signal<(AccountImportProgressType, Float), AccountImportError> in
var importedAccountUser: Signal<Never, AccountImportError> = .complete()
if let (user, presence) = loadLegacyUser(database: database, id: accountUserId) {
importedAccountUser = account.postbox.transaction { transaction -> Void in
updatePeers(transaction: transaction, peers: [user], update: { _, updated in updated })
transaction.updatePeerPresencesInternal(presences: [user.id: presence], merge: { _, updated in return updated })
}
|> ignoreValues
|> castError(AccountImportError.self)
}
let importedSecretChats = loadLegacySecretChats(account: account, basePath: basePath, accountPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: accountUserId), database: database)
|> castError(AccountImportError.self)
/*let importedFiles = loadLegacyFiles(account: account, basePath: basePath, accountPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: accountUserId), database: database)
|> castError(AccountImportError.self)*/
let importedLegacyPreferences = importLegacyPreferences(accountManager: accountManager, account: account, documentsPath: basePath + "/Documents", database: database)
|> castError(AccountImportError.self)
return importedAccountUser
|> map { _ -> (AccountImportProgressType, Float) in return (.generic, 0.0) }
|> then(
importedLegacyPreferences
|> map { _ -> (AccountImportProgressType, Float) in return (.generic, 0.0) }
)
|> then(
importedSecretChats
|> map { value -> (AccountImportProgressType, Float) in return (.messages, value) }
)
}
}
public enum ImportedLegacyAccountEvent {
case progress(AccountImportProgressType, Float)
case result(AccountRecordId?)
}
public func importedLegacyAccount(basePath: String, accountManager: AccountManager, encryptionParameters: ValueBoxEncryptionParameters, present: @escaping (UIViewController) -> Void) -> Signal<ImportedLegacyAccountEvent, AccountImportError> {
let queue = Queue()
return deferred { () -> Signal<ImportedLegacyAccountEvent, AccountImportError> in
let documentsPath = basePath + "/Documents"
if FileManager.default.fileExists(atPath: documentsPath + "/importcompleted") {
return .single(.result(nil))
}
let unlockedDatabasePathAndKey: Signal<(String, Data?)?, AccountImportError>
if FileManager.default.fileExists(atPath: documentsPath + "/tgdata.db.y") {
let databasePath = documentsPath + "/tgdata.db.y"
let unlockDatabase = Signal<(String, Data?)?, AccountImportError> { subscriber in
let alertController = UIAlertController(title: nil, message: "Enter your passcode", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "Enter", style: .default) { _ in
let passcode = alertController.textFields?[0].text
func checkPasscode(_ value: String) -> Bool {
guard let database = SqliteInterface(databasePath: databasePath) else {
return false
}
let key = value.data(using: .utf8)!
if !database.unlock(password: hexString(key).data(using: .utf8)!) {
return false
}
return true
}
if checkPasscode(passcode ?? "") {
subscriber.putNext((databasePath, (passcode ?? "").data(using: .utf8)!))
subscriber.putCompletion()
} else {
let alertController = UIAlertController(title: nil, message: "Invalid passcode. Please try again.", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "OK", style: .default) { _ in
subscriber.putCompletion()
}
alertController.addAction(confirmAction)
present(alertController)
}
}
let cancelAction = UIAlertAction(title: "Skip", style: .cancel) { _ in
subscriber.putNext(nil)
subscriber.putCompletion()
}
alertController.addTextField { textField in
textField.placeholder = "Passcode"
}
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
present(alertController)
return EmptyDisposable
}
|> runOn(Queue.mainQueue())
unlockedDatabasePathAndKey = (unlockDatabase
|> mapToSignal { result -> Signal<(String, Data?)?, AccountImportError> in
if let result = result {
return .single(result)
} else {
let askAgain = Signal<(String, Data?)?, AccountImportError> { subscriber in
let alertController = UIAlertController(title: "Warning", message: "If you continue without entering your passcode, all your secret chats will be lost.", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "Skip", style: .destructive) { _ in
subscriber.putError(.generic)
}
let cancelAction = UIAlertAction(title: "Try Again", style: .cancel) { _ in
subscriber.putCompletion()
}
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
present(alertController)
return EmptyDisposable
}
|> runOn(Queue.mainQueue())
return askAgain
}
})
|> restart
|> take(1)
} else if FileManager.default.fileExists(atPath: documentsPath + "/tgdata.db") {
unlockedDatabasePathAndKey = .single((documentsPath + "/tgdata.db", nil))
} else {
return .single(.result(nil))
}
return unlockedDatabasePathAndKey
|> mapToSignal { pathAndKey -> Signal<ImportedLegacyAccountEvent, AccountImportError> in
guard let pathAndKey = pathAndKey else {
return .fail(.generic)
}
guard let database = SqliteInterface(databasePath: pathAndKey.0) else {
return .fail(.generic)
}
if let key = pathAndKey.1 {
if !database.unlock(password: hexString(key).data(using: .utf8)!) {
return .fail(.generic)
}
}
return temporaryAccount(manager: accountManager, rootPath: rootPathForBasePath(basePath), encryptionParameters: encryptionParameters)
|> castError(AccountImportError.self)
|> mapToSignal { account -> Signal<ImportedLegacyAccountEvent, AccountImportError> in
let actions = importedAccountData(basePath: basePath, documentsPath: documentsPath, accountManager: accountManager, account: account, database: database)
var result = actions
|> map { typeAndProgress -> ImportedLegacyAccountEvent in
return .progress(typeAndProgress.0, typeAndProgress.1)
}
#if DEBUG
//result = result
//|> then(.never())
#endif
result = result
|> then(.single(.result(account.id)))
return result
}
}
}
|> runOn(queue)
}

View file

@ -1,89 +0,0 @@
import Foundation
import Display
import AsyncDisplayKit
import TelegramPresentationData
import RadialStatusNode
public protocol LegacyDataImportSplash: WindowCoveringView {
var progress: (AccountImportProgressType, Float) { get set }
var serviceAction: (() -> Void)? { get set }
}
private final class LegacyDataImportSplashImpl: WindowCoveringView, LegacyDataImportSplash {
private let theme: PresentationTheme?
private let strings: PresentationStrings?
public var progress: (AccountImportProgressType, Float) = (.generic, 0.0) {
didSet {
if self.progress.0 != oldValue.0 {
if let size = self.validSize {
switch self.progress.0 {
case .generic:
self.textNode.attributedText = NSAttributedString(string: self.strings?.AppUpgrade_Running ?? "Optimizing...", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black)
case .media:
self.textNode.attributedText = NSAttributedString(string: "Optimizing cache", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black)
case .messages:
self.textNode.attributedText = NSAttributedString(string: "Optimizing database", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black)
}
self.updateLayout(size)
}
}
self.progressNode.transitionToState(.progress(color: self.theme?.list.itemAccentColor ?? UIColor(rgb: 0x007ee5), lineWidth: 2.0, value: CGFloat(max(0.025, self.progress.1)), cancelEnabled: false, animateRotation: true), animated: false, completion: {})
}
}
public var serviceAction: (() -> Void)?
private let progressNode: RadialStatusNode
private let textNode: ImmediateTextNode
private var validSize: CGSize?
public init(theme: PresentationTheme?, strings: PresentationStrings?) {
self.theme = theme
self.strings = strings
self.progressNode = RadialStatusNode(backgroundNodeColor: theme?.list.plainBackgroundColor ?? .white)
self.textNode = ImmediateTextNode()
self.textNode.maximumNumberOfLines = 0
self.textNode.textAlignment = .center
self.textNode.attributedText = NSAttributedString(string: self.strings?.AppUpgrade_Running ?? "Optimizing...", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black)
super.init(frame: CGRect())
self.backgroundColor = self.theme?.list.plainBackgroundColor ?? .white
self.addSubnode(self.progressNode)
self.progressNode.isUserInteractionEnabled = false
self.addSubnode(self.textNode)
self.textNode.isUserInteractionEnabled = false
self.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:))))
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func updateLayout(_ size: CGSize) {
self.validSize = size
let progressSize = CGSize(width: 60.0, height: 60.0)
let textSize = self.textNode.updateLayout(CGSize(width: size.width - 20.0, height: .greatestFiniteMagnitude))
let progressFrame = CGRect(origin: CGPoint(x: floor((size.width - progressSize.width) / 2.0), y: floor((size.height - progressSize.height - 15.0 - textSize.height) / 2.0)), size: progressSize)
self.progressNode.frame = progressFrame
self.textNode.frame = CGRect(origin: CGPoint(x: floor((size.width - textSize.width) / 2.0), y: progressFrame.maxY + 15.0), size: textSize)
}
@objc private func longPressGesture(_ recognizer: UILongPressGestureRecognizer) {
if case .began = recognizer.state {
self.serviceAction?()
}
}
}
public func makeLegacyDataImportSplash(theme: PresentationTheme?, strings: PresentationStrings?) -> LegacyDataImportSplash {
return LegacyDataImportSplashImpl(theme: theme, strings: strings)
}

View file

@ -1,189 +0,0 @@
import Foundation
import TelegramCore
import SyncCore
import SwiftSignalKit
import Postbox
import LegacyComponents
private func importMediaFromMessageData(_ data: Data, basePath: String, copyLocalFiles: inout [(MediaResource, String)], cache: TGCache) {
if let message = TGMessage(keyValueCoder: PSKeyValueDecoder(data: data)) {
if let mediaAttachments = message.mediaAttachments {
importMediaFromMediaList(mediaAttachments, basePath: basePath, copyLocalFiles: &copyLocalFiles, cache: cache)
}
}
}
private func importMediaFromMediaData(_ data: Data, basePath: String, copyLocalFiles: inout [(MediaResource, String)], cache: TGCache) {
if let mediaAttachments = TGMessage.parseMediaAttachments(data) {
importMediaFromMediaList(mediaAttachments, basePath: basePath, copyLocalFiles: &copyLocalFiles, cache: cache)
}
}
private func importMediaFromMediaList(_ mediaAttachments: [Any], basePath: String, copyLocalFiles: inout [(MediaResource, String)], cache: TGCache) {
for media in mediaAttachments {
if let media = media as? TGDocumentMediaAttachment {
var fileName = "file"
if let itemAttributes = media.attributes {
for attribute in itemAttributes {
if let attribute = attribute as? TGDocumentAttributeFilename {
fileName = attribute.filename ?? "file"
}
}
}
if media.documentId != 0 {
let filePath = pathFromLegacyFile(basePath: basePath, fileId: media.documentId, isLocal: false, fileName: TGDocumentMediaAttachment.safeFileName(forFileName: fileName) ?? "")
if FileManager.default.fileExists(atPath: filePath) {
copyLocalFiles.append((CloudDocumentMediaResource(datacenterId: Int(media.datacenterId), fileId: media.documentId, accessHash: media.accessHash, size: nil, fileReference: nil, fileName: nil), filePath))
}
}
} else if let media = media as? TGVideoMediaAttachment {
if media.videoId != 0, let videoUrl = media.videoInfo?.url(withQuality: 1, actualQuality: nil, actualSize: nil) {
if let (id, accessHash, datacenterId, path) = pathFromLegacyVideoUrl(basePath: basePath, url: videoUrl) {
copyLocalFiles.append((CloudDocumentMediaResource(datacenterId: Int(datacenterId), fileId: id, accessHash: accessHash, size: nil, fileReference: nil, fileName: nil), path))
}
}
} else if let media = media as? TGImageMediaAttachment {
if let allSizes = media.imageInfo?.allSizes() as? [String: NSValue] {
for (imageUrl, _) in allSizes {
if let path = cache.path(forCachedData: imageUrl), let resource = resourceFromLegacyImageUrl(imageUrl), FileManager.default.fileExists(atPath: path) {
copyLocalFiles.append((resource, path))
}
}
}
}
}
}
private func makeMessageSortKey(tag: Int32, conversationId: Int64, space: Int8, timestamp: Int32, messageId: Int32) -> Data {
let key = ValueBoxKey(length: 4 + 8 + 1 + 4 + 4)
key.setInt32(0, value: tag.byteSwapped)
key.setInt64(4, value: conversationId.byteSwapped)
key.setInt8(4 + 8, value: space)
key.setInt32(4 + 8 + 1, value: timestamp)
key.setInt32(4 + 8 + 1 + 4, value: messageId.byteSwapped)
return Data(bytes: key.memory, count: key.length)
}
func loadLegacyFiles(account: TemporaryAccount, basePath: String, accountPeerId: PeerId, database: SqliteInterface) -> Signal<Float, NoError> {
return Signal<Float, NoError> { subscriber in
let _ = registeredAttachmentParsers
subscriber.putNext(0.0)
var channelIds: [Int64] = []
database.select("SELECT DISTINCT cid FROM channel_message_tags_v29", { cursor in
channelIds.append(cursor.getInt64(at: 0))
return true
})
print(database.explain("SELECT DISTINCT cid FROM channel_message_tags_v29"))
var channelMessageIds: [(Int64, Int32)] = []
print(database.explain("SELECT mid FROM channel_message_tags_v29 WHERE tag_sort_key<100 AND tag_sort_key>0 ORDER BY tag_sort_key DESC LIMIT 4000"))
if !channelIds.isEmpty {
/*
TGSharedMediaCacheItemTypePhoto = 0,
TGSharedMediaCacheItemTypeVideo = 1,
TGSharedMediaCacheItemTypeFile = 2,
TGSharedMediaCacheItemTypePhotoVideo = 3,
TGSharedMediaCacheItemTypePhotoVideoFile = 4,
TGSharedMediaCacheItemTypeAudio = 5,
TGSharedMediaCacheItemTypeLink = 6,
TGSharedMediaCacheItemTypeSticker = 7,
TGSharedMediaCacheItemTypeGif = 8,
TGSharedMediaCacheItemTypeVoiceVideoMessage = 9
*/
let tags: [Int32] = [
2, // File
5, // Audio
3, // PhotoVideo
]
database.withStatement("SELECT mid FROM channel_message_tags_v29 WHERE tag_sort_key<? AND tag_sort_key>? ORDER BY tag_sort_key DESC LIMIT 4000", { select in
for channelId in channelIds {
for tag in tags {
select([.data(makeMessageSortKey(tag: tag, conversationId: channelId, space: 0, timestamp: Int32.max - 1, messageId: 0)), .data(makeMessageSortKey(tag: tag, conversationId: channelId, space: 0, timestamp: 0, messageId: 0))], { cursor in
channelMessageIds.append((channelId, cursor.getInt32(at: 0)))
return true
})
select([.data(makeMessageSortKey(tag: tag, conversationId: channelId, space: 1, timestamp: Int32.max - 1, messageId: 0)), .data(makeMessageSortKey(tag: tag, conversationId: channelId, space: 1, timestamp: 0, messageId: 0))], { cursor in
channelMessageIds.append((channelId, cursor.getInt32(at: 0)))
return true
})
}
}
})
}
var chatMessageIds: [Int32] = []
let mediaTypes: [Int32] = [
1, // video
2, // image
3, // file
]
for type in mediaTypes {
database.select("SELECT mids FROM media_cache_v29 WHERE media_type=\(type) ORDER BY date DESC LIMIT 32000", { cursor in
let midsData = cursor.getData(at: 0)
let reader = LegacyBufferReader(LegacyBuffer(data: midsData))
while true {
if let mid = reader.readInt32() {
chatMessageIds.append(mid)
} else {
break
}
}
return true
})
}
var copyLocalFiles: [(MediaResource, String)] = []
let totalCount = channelMessageIds.count + chatMessageIds.count
let reportBase = max(1, totalCount / 100)
var itemIndex = -1
let cache = TGCache(cachesPath: basePath + "/Caches")!
if !channelMessageIds.isEmpty {
database.withStatement("SELECT data FROM channel_messages_v29 WHERE cid=? AND mid=?", { select in
for (peerId, messageId) in channelMessageIds {
itemIndex += 1
if itemIndex % reportBase == 0 {
subscriber.putNext(Float(itemIndex) / Float(totalCount))
}
select([.int64(peerId), .int32(messageId)], { cursor in
let data = cursor.getData(at: 0)
importMediaFromMessageData(data, basePath: basePath, copyLocalFiles: &copyLocalFiles, cache: cache)
return true
})
}
})
}
if !chatMessageIds.isEmpty {
database.withStatement("SELECT media FROM messages_v29 WHERE mid=?", { select in
for messageId in chatMessageIds {
itemIndex += 1
if itemIndex % reportBase == 0 {
subscriber.putNext(Float(itemIndex) / Float(totalCount))
}
select([.int32(messageId)], { cursor in
let data = cursor.getData(at: 0)
importMediaFromMediaData(data, basePath: basePath, copyLocalFiles: &copyLocalFiles, cache: cache)
return true
})
}
})
}
for (resource, path) in copyLocalFiles {
account.postbox.mediaBox.copyResourceData(resource.id, fromTempPath: path)
}
subscriber.putCompletion()
return EmptyDisposable
}
}

View file

@ -1,438 +0,0 @@
import Foundation
import UIKit
import TelegramCore
import SyncCore
import SwiftSignalKit
import MtProtoKit
import TelegramUIPreferences
import LegacyComponents
import TelegramNotices
import LegacyDataImportImpl
@objc(TGPresentationState) private final class TGPresentationState: NSObject, NSCoding {
let pallete: Int32
let userInfo: Int32
let fontSize: Int32
init?(coder aDecoder: NSCoder) {
self.pallete = aDecoder.decodeInt32(forKey: "p")
self.userInfo = aDecoder.decodeInt32(forKey: "u")
self.fontSize = aDecoder.decodeInt32(forKey: "f")
}
func encode(with aCoder: NSCoder) {
assertionFailure()
}
}
private enum PreferencesProvider {
case dict([String: Any])
case standard(UserDefaults)
subscript(_ key: String) -> Any? {
get {
switch self {
case let .dict(dict):
return dict[key]
case let .standard(standard):
return standard.object(forKey: key)
}
}
}
}
private func loadLegacyCustomProperyData(database: SqliteInterface, key: String) -> Data? {
var result: Data?
database.select("SELECT value FROM service_v29 WHERE key=\(HashFunctions.murMurHash32(key))", { cursor in
result = cursor.getData(at: 0)
return false
})
return result
}
private func convertLegacyProxyPort(_ value: Int) -> Int32 {
if value < 0 {
return Int32(UInt16(bitPattern: Int16(clamping: value)))
} else {
return Int32(clamping: value)
}
}
func importLegacyPreferences(accountManager: AccountManager, account: TemporaryAccount, documentsPath: String, database: SqliteInterface) -> Signal<Never, NoError> {
return deferred { () -> Signal<Never, NoError> in
var presentationState: TGPresentationState?
if let value = NSKeyedUnarchiver.unarchiveObject(withFile: documentsPath + "/presentation.dat") as? TGPresentationState {
presentationState = value
}
var autoNightPreferences: TGPresentationAutoNightPreferences?
if let value = NSKeyedUnarchiver.unarchiveObject(withFile: documentsPath + "/autonight.dat") as? TGPresentationAutoNightPreferences {
autoNightPreferences = value
}
let autoDownloadPreferences: TGAutoDownloadPreferences? = NSKeyedUnarchiver.unarchiveObject(withFile: documentsPath + "/autoDownload.pref") as? TGAutoDownloadPreferences
let preferencesProvider: PreferencesProvider
let defaultsPath = documentsPath + "/standard.defaults"
let standardPreferences = PreferencesProvider.standard(UserDefaults.standard)
if let data = try? Data(contentsOf: URL(fileURLWithPath: defaultsPath)), let dict = NSKeyedUnarchiver.unarchiveObject(with: data) as? [String: Any] {
preferencesProvider = .dict(dict)
} else {
preferencesProvider = standardPreferences
}
var showCallsTab: Bool?
if let data = try? Data(contentsOf: URL(fileURLWithPath: documentsPath + "/enablecalls.tab")), !data.isEmpty {
showCallsTab = data.withUnsafeBytes { (bytes: UnsafePointer<Int8>) -> Bool in
return bytes.pointee != 0
}
}
let parsedAutoplayGifs: Bool? = preferencesProvider["autoPlayAnimations"] as? Bool
let soundEnabled: Bool? = preferencesProvider["soundEnabled"] as? Bool
let vibrationEnabled: Bool? = preferencesProvider["vibrationEnabled"] as? Bool
let bannerEnabled: Bool? = preferencesProvider["bannerEnabled"] as? Bool
let callsDataUsageMode: Int? = preferencesProvider["callsDataUsageMode"] as? Int
let callsDisableCallKit: Bool? = preferencesProvider["callsDisableCallKit"] as? Bool
let callsUseProxy: Bool? = preferencesProvider["callsUseProxy"] as? Bool
let contactsInhibitSync: Bool? = preferencesProvider["contactsInhibitSync"] as? Bool
let stickersSuggestMode: Int? = preferencesProvider["stickersSuggestMode"] as? Int
let allowSecretWebpages: Bool? = preferencesProvider["allowSecretWebpages"] as? Bool
let allowSecretWebpagesInitialized: Bool? = preferencesProvider["allowSecretWebpagesInitialized"] as? Bool
let secretInlineBotsInitialized: Bool? = preferencesProvider["secretInlineBotsInitialized"] as? Bool
let musicPlayerOrderType: Int? = standardPreferences["musicPlayerOrderType_v1"] as? Int
let musicPlayerRepeatType: Int? = standardPreferences["musicPlayerRepeatType_v1"] as? Int
let instantPageFontSize: Float? = standardPreferences["instantPage_fontMultiplier_v0"] as? Float
let instantPageFontSerif: Int? = standardPreferences["instantPage_fontSerif_v0"] as? Int
let instantPageTheme: Int? = standardPreferences["instantPage_theme_v0"] as? Int
let instantPageAutoNightMode: Int? = standardPreferences["instantPage_autoNightTheme_v0"] as? Int
let proxyList = NSKeyedUnarchiver.unarchiveObject(withFile: documentsPath + "/proxies.data") as? [TGProxyItem]
var selectedProxy: (ProxyServerSettings, Bool)?
if let data = loadLegacyCustomProperyData(database: database, key: "socksProxyData"), let dict = NSKeyedUnarchiver.unarchiveObject(with: data) as? [String: Any], let host = dict["ip"] as? String, let port = dict["port"] as? Int {
let inactive = (dict["inactive"] as? Bool) ?? true
var connection: ProxyServerConnection?
if let secretString = dict["secret"] as? String {
let secret = MTProxySecret.parse(secretString)
if let secret = secret {
connection = .mtp(secret: secret.serialize())
}
} else {
connection = .socks5(username: (dict["username"] as? String) ?? "", password: (dict["password"] as? String) ?? "")
}
if let connection = connection {
selectedProxy = (ProxyServerSettings(host: host, port: convertLegacyProxyPort(port), connection: connection), !inactive)
}
}
var passcodeChallenge: PostboxAccessChallengeData?
if let data = try? Data(contentsOf: URL(fileURLWithPath: documentsPath + "/x.y")) {
let reader = LegacyBufferReader(LegacyBuffer(data: data))
if let mode = reader.readBytesAsInt32(1), let length = reader.readInt32(), let passwordData = reader.readBuffer(Int(length))?.makeData(), let passwordText = String(data: passwordData, encoding: .utf8) {
var lockTimeout: Int32?
if let value = UserDefaults.standard.object(forKey: "Passcode_lockTimeout") as? Int {
if value == 0 {
lockTimeout = nil
} else {
lockTimeout = max(60, Int32(clamping: value))
}
} else {
lockTimeout = 1 * 60 * 60
}
if mode == 3 {
passcodeChallenge = .numericalPassword(value: passwordText)
} else if mode == 4 {
passcodeChallenge = PostboxAccessChallengeData.plaintextPassword(value: passwordText)
}
}
}
var passcodeEnableBiometrics: Bool = true
if let value = UserDefaults.standard.object(forKey: "Passcode_useTouchId") as? Bool {
passcodeEnableBiometrics = value
}
var localization: TGLocalization?
if let nativeDocumentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
localization = NSKeyedUnarchiver.unarchiveObject(withFile: nativeDocumentsPath + "/localization") as? TGLocalization
}
return accountManager.transaction { transaction -> Signal<Void, NoError> in
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.presentationThemeSettings, { current in
var settings = (current as? PresentationThemeSettings) ?? PresentationThemeSettings.defaultSettings
if let presentationState = presentationState {
switch presentationState.pallete {
case 1:
settings.theme = .builtin(.day)
if presentationState.userInfo != 0 {
//themeSpecificAccentColors: current.themeSpecificAccentColors
//settings.themeAccentColor = presentationState.userInfo
}
settings.themeSpecificChatWallpapers[settings.theme.index] = .color(0xffffff)
case 2:
settings.theme = .builtin(.night)
settings.themeSpecificChatWallpapers[settings.theme.index] = .color(0x000000)
case 3:
settings.theme = .builtin(.nightAccent)
settings.themeSpecificChatWallpapers[settings.theme.index] = .color(0x18222d)
default:
settings.theme = .builtin(.dayClassic)
settings.themeSpecificChatWallpapers[settings.theme.index] = .builtin(WallpaperSettings())
}
let fontSizeMap: [Int32: PresentationFontSize] = [
14: .extraSmall,
15: .small,
16: .medium,
17: .regular,
19: .large,
23: .extraLarge,
26: .extraLargeX2
]
settings.fontSize = fontSizeMap[presentationState.fontSize] ?? .regular
if presentationState.userInfo != 0 {
//themeSpecificAccentColors: current.themeSpecificAccentColors
//settings.themeAccentColor = presentationState.userInfo
}
}
if let autoNightPreferences = autoNightPreferences {
let nightTheme: PresentationBuiltinThemeReference
switch autoNightPreferences.preferredPalette {
case 1:
nightTheme = .night
default:
nightTheme = .nightAccent
}
switch autoNightPreferences.mode {
case TGPresentationAutoNightModeSunsetSunrise:
settings.automaticThemeSwitchSetting = AutomaticThemeSwitchSetting(trigger: .timeBased(setting: .automatic(latitude: Double(autoNightPreferences.latitude), longitude: Double(autoNightPreferences.longitude), localizedName: autoNightPreferences.cachedLocationName)), theme: .builtin(nightTheme))
case TGPresentationAutoNightModeScheduled:
settings.automaticThemeSwitchSetting = AutomaticThemeSwitchSetting(trigger: .timeBased(setting: .manual(fromSeconds: autoNightPreferences.scheduleStart, toSeconds: autoNightPreferences.scheduleEnd)), theme: .builtin(nightTheme))
case TGPresentationAutoNightModeBrightness:
settings.automaticThemeSwitchSetting = AutomaticThemeSwitchSetting(trigger: .brightness(threshold: Double(autoNightPreferences.brightnessThreshold)), theme: .builtin(nightTheme))
default:
break
}
}
return settings
})
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings, { current in
var settings: MediaAutoDownloadSettings = current as? MediaAutoDownloadSettings ?? .defaultSettings
if let preferences = autoDownloadPreferences, !preferences.isDefaultPreferences() {
settings.cellular.enabled = !preferences.disabled
settings.wifi.enabled = !preferences.disabled
}
if let parsedAutoplayGifs = parsedAutoplayGifs {
settings.autoplayGifs = parsedAutoplayGifs
}
return settings
})
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.inAppNotificationSettings, { current in
var settings: InAppNotificationSettings = current as? InAppNotificationSettings ?? .defaultSettings
if let soundEnabled = soundEnabled {
settings.playSounds = soundEnabled
}
if let vibrationEnabled = vibrationEnabled {
settings.vibrate = vibrationEnabled
}
if let bannerEnabled = bannerEnabled {
settings.displayPreviews = bannerEnabled
}
return settings
})
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.voiceCallSettings, { current in
var settings: VoiceCallSettings = current as? VoiceCallSettings ?? .defaultSettings
if let callsDataUsageMode = callsDataUsageMode {
switch callsDataUsageMode {
case 1:
settings.dataSaving = .cellular
case 2:
settings.dataSaving = .always
default:
settings.dataSaving = .never
}
}
if let callsDisableCallKit = callsDisableCallKit, callsDisableCallKit {
settings.enableSystemIntegration = false
}
return settings
})
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.callListSettings, { current in
var settings: CallListSettings = current as? CallListSettings ?? .defaultSettings
if let showCallsTab = showCallsTab {
settings.showTab = showCallsTab
}
return settings
})
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.presentationPasscodeSettings, { current in
var settings: PresentationPasscodeSettings = current as? PresentationPasscodeSettings ?? .defaultSettings
if let passcodeChallenge = passcodeChallenge {
transaction.setAccessChallengeData(passcodeChallenge)
settings.enableBiometrics = passcodeEnableBiometrics
}
return settings
})
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.stickerSettings, { current in
var settings: StickerSettings = current as? StickerSettings ?? .defaultSettings
if let stickersSuggestMode = stickersSuggestMode {
switch stickersSuggestMode {
case 1:
settings.emojiStickerSuggestionMode = .installed
case 2:
settings.emojiStickerSuggestionMode = .none
default:
settings.emojiStickerSuggestionMode = .all
}
}
return settings
})
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.musicPlaybackSettings, { current in
var settings: MusicPlaybackSettings = current as? MusicPlaybackSettings ?? .defaultSettings
if let musicPlayerOrderType = musicPlayerOrderType {
switch musicPlayerOrderType {
case 1:
settings.order = .reversed
case 2:
settings.order = .random
default:
settings.order = .regular
}
}
if let musicPlayerRepeatType = musicPlayerRepeatType {
switch musicPlayerRepeatType {
case 1:
settings.looping = .all
case 2:
settings.looping = .item
default:
settings.looping = .none
}
}
return settings
})
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.instantPagePresentationSettings, { current in
let settings: InstantPagePresentationSettings = current as? InstantPagePresentationSettings ?? .defaultSettings
if let instantPageFontSize = instantPageFontSize {
switch instantPageFontSize {
case 0.85:
settings.fontSize = .small
case 1.15:
settings.fontSize = .large
case 1.30:
settings.fontSize = .xlarge
case 1.50:
settings.fontSize = .xxlarge
default:
settings.fontSize = .standard
}
}
if let instantPageFontSerif = instantPageFontSerif {
settings.forceSerif = instantPageFontSerif == 1
}
if let instantPageTheme = instantPageTheme {
switch instantPageTheme {
case 1:
settings.themeType = .sepia
case 2:
settings.themeType = .gray
case 3:
settings.themeType = .dark
default:
settings.themeType = .light
}
}
if let instantPageAutoNightMode = instantPageAutoNightMode {
settings.autoNightMode = instantPageAutoNightMode == 1
}
return settings
})
if let localization = localization {
transaction.updateSharedData(SharedDataKeys.localizationSettings, { _ in
var entries: [LocalizationEntry] = []
for (key, value) in localization.dict() {
entries.append(LocalizationEntry.string(key: key, value: value))
}
return LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: localization.code, localizedName: "", localization: Localization(version: 0, entries: entries), customPluralizationCode: nil), secondaryComponent: nil)
})
}
transaction.updateSharedData(SharedDataKeys.proxySettings, { current in
var settings: ProxySettings = current as? ProxySettings ?? .defaultSettings
if let callsUseProxy = callsUseProxy {
settings.useForCalls = callsUseProxy
}
if let proxyList = proxyList {
for item in proxyList {
let connection: ProxyServerConnection?
if item.isMTProxy, let secret = item.secret {
let parsedSecret = MTProxySecret.parse(secret)
if let parsedSecret = parsedSecret {
connection = .mtp(secret: parsedSecret.serialize())
} else {
connection = nil
}
} else if !item.isMTProxy {
connection = .socks5(username: item.username ?? "", password: item.password ?? "")
} else {
connection = nil
}
if let connection = connection {
settings.servers.append(ProxyServerSettings(host: item.server, port: convertLegacyProxyPort(Int(item.port)), connection: connection))
}
}
}
if let (server, active) = selectedProxy {
if !settings.servers.contains(server) {
settings.servers.insert(server, at: 0)
}
settings.activeServer = server
settings.enabled = active
}
return settings
})
if let secretInlineBotsInitialized = secretInlineBotsInitialized, secretInlineBotsInitialized {
ApplicationSpecificNotice.setSecretChatInlineBotUsage(transaction: transaction)
}
if let allowSecretWebpagesInitialized = allowSecretWebpagesInitialized, allowSecretWebpagesInitialized, let allowSecretWebpages = allowSecretWebpages {
ApplicationSpecificNotice.setSecretChatLinkPreviews(transaction: transaction, value: allowSecretWebpages)
}
return account.postbox.transaction { transaction -> Void in
transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in
var settings = current as? ContactsSettings ?? ContactsSettings.defaultSettings
if let contactsInhibitSync = contactsInhibitSync, contactsInhibitSync {
settings.synchronizeContacts = false
}
return settings
})
}
}
|> switchToLatest
|> ignoreValues
}
}

View file

@ -1,137 +0,0 @@
import Foundation
import TelegramCore
import SyncCore
import SwiftSignalKit
import LegacyComponents
func resourceFromLegacyImageUrl(_ fileRef: String) -> TelegramMediaResource? {
if fileRef.isEmpty {
return nil
}
let components = fileRef.components(separatedBy: "_")
if components.count != 4 {
return nil
}
guard let datacenterId = Int32(components[0]) else {
return nil
}
guard let volumeId = Int64(components[1]) else {
return nil
}
guard let localId = Int32(components[2]) else {
return nil
}
guard let secret = Int64(components[3]) else {
return nil
}
return CloudFileMediaResource(datacenterId: Int(datacenterId), volumeId: volumeId, localId: localId, secret: secret, size: nil, fileReference: nil)
}
func pathFromLegacyImageUrl(basePath: String, url: String) -> String {
let cache = TGCache(cachesPath: basePath + "/Caches")!
return cache.path(forCachedData: url)
}
func pathFromLegacyVideoUrl(basePath: String, url: String) -> (id: Int64, accessHash: Int64, datacenterId: Int32, path: String)? {
if !url.hasPrefix("video:") {
return nil
}
//[videoInfo addVideoWithQuality:1 url:[[NSString alloc] initWithFormat:@"video:%lld:%lld:%d:%d", videoMedia.videoId, videoMedia.accessHash, concreteResult.document.datacenterId, concreteResult.document.size] size:concreteResult.document.size];
let components = url.components(separatedBy: ":")
if components.count != 5 {
return nil
}
guard let videoId = Int64(components[1]) else {
return nil
}
guard let accessHash = Int64(components[2]) else {
return nil
}
guard let datacenterId = Int32(components[3]) else {
return nil
}
let documentsPath = basePath + "/Documents"
let videoPath = documentsPath + "/video/remote\(String(videoId, radix: 16)).mov"
return (videoId, accessHash, datacenterId, videoPath)
}
func pathFromLegacyLocalVideoUrl(basePath: String, url: String) -> String? {
let documentsPath = basePath + "/Documents"
if !url.hasPrefix("local-video:") {
return nil
}
let videoPath = documentsPath + "/video/" + String(url[url.index(url.startIndex, offsetBy: "local-video:".count)...])
return videoPath
}
func pathFromLegacyFile(basePath: String, fileId: Int64, isLocal: Bool, fileName: String) -> String {
let documentsPath = basePath + "/Documents"
let filePath = documentsPath + "/files/" + (isLocal ? "local" : "") + "\(String(fileId, radix: 16))/\(fileName)"
return filePath
}
enum EncryptedFileType {
case image
case video
case document(fileName: String)
case audio
}
func pathAndResourceFromEncryptedFileUrl(basePath: String, url: String, type: EncryptedFileType) -> (String, TelegramMediaResource)? {
let cache = TGCache(cachesPath: basePath + "/Caches")!
if url.hasPrefix("encryptedThumbnail:") {
let path = cache.path(forCachedData: url)!
return (path, LocalFileMediaResource(fileId: arc4random64()))
}
if !url.hasPrefix("mt-encrypted-file://?") {
return nil
}
guard let dict = TGStringUtils.argumentDictionary(inUrlString: String(url[url.index(url.startIndex, offsetBy: "mt-encrypted-file://?".count)...])) else {
return nil
}
guard let idString = dict["id"] as? String, let id = Int64(idString) else {
return nil
}
guard let datacenterIdString = dict["dc"] as? String, let datacenterId = Int32(datacenterIdString) else {
return nil
}
guard let accessHashString = dict["accessHash"] as? String, let accessHash = Int64(accessHashString) else {
return nil
}
guard let sizeString = dict["size"] as? String, let size = Int32(sizeString) else {
return nil
}
guard let decryptedSizeString = dict["decryptedSize"] as? String, let decryptedSize = Int32(decryptedSizeString) else {
return nil
}
guard let keyFingerprintString = dict["fingerprint"] as? String, let _ = Int32(keyFingerprintString) else {
return nil
}
guard let keyString = dict["key"] as? String else {
return nil
}
let keyData = dataWithHexString(keyString)
guard keyData.count == 64 else {
return nil
}
let resource = SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: decryptedSize, datacenterId: Int(datacenterId), key: SecretFileEncryptionKey(aesKey: keyData.subdata(in: 0 ..< 32), aesIv: keyData.subdata(in: 32 ..< 64)))
let filePath: String
switch type {
case .video:
filePath = basePath + "Documents/video/remote\(String(id, radix: 16)).mov"
case .image:
filePath = cache.path(forCachedData: url)
case let .document(fileName):
filePath = basePath + "Documents/files/\(String(id, radix: 16))/\(TGDocumentMediaAttachment.safeFileName(forFileName: fileName)!)"
case .audio:
filePath = basePath + "Documents/audio/\(String(id, radix: 16))"
}
return (filePath, resource)
}

View file

@ -1,47 +0,0 @@
import Foundation
import UIKit
import TelegramCore
import SyncCore
import SwiftSignalKit
func loadLegacyUser(database: SqliteInterface, id: Int32) -> (TelegramUser, TelegramUserPresence)? {
var result: (TelegramUser, TelegramUserPresence)?
database.select("SELECT uid, first_name, last_name, phone_number, access_hash, photo_small, photo_big, last_seen, username FROM users_v29 WHERE uid=\(id)", { cursor in
let accessHash = cursor.getInt64(at: 4)
let firstName = cursor.getString(at: 1)
let lastName = cursor.getString(at: 2)
let username = cursor.getString(at: 8)
let phone = cursor.getString(at: 3)
let photoSmall = cursor.getString(at: 5)
let photoBig = cursor.getString(at: 6)
var photo: [TelegramMediaImageRepresentation] = []
if let resource = resourceFromLegacyImageUrl(photoSmall) {
photo.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 80, height: 80), resource: resource, progressiveSizes: []))
}
if let resource = resourceFromLegacyImageUrl(photoBig) {
photo.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 600, height: 600), resource: resource, progressiveSizes: []))
}
let user = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: cursor.getInt32(at: 0)), accessHash: accessHash == 0 ? nil : .personal(accessHash), firstName: firstName.isEmpty ? nil : firstName, lastName: lastName.isEmpty ? nil : lastName, username: username.isEmpty ? nil : username, phone: phone.isEmpty ? nil : phone, photo: photo, botInfo: nil, restrictionInfo: nil, flags: [])
let status: UserPresenceStatus
let lastSeen = cursor.getInt32(at: 7)
if lastSeen == -2 {
status = .recently
} else if lastSeen == -3 {
status = .lastWeek
} else if lastSeen == -4 {
status = .lastMonth
} else if lastSeen <= 0 {
status = .none
} else {
status = .present(until: lastSeen)
}
let presence = TelegramUserPresence(status: status, lastActivity: 0)
result = (user, presence)
return false
})
return result
}

View file

@ -361,48 +361,6 @@ public func legacyEnqueueGifMessage(account: Account, data: Data, correlationId:
} |> runOn(Queue.concurrentDefaultQueue())
}
public func legacyEnqueueVideoMessage(account: Account, data: Data, correlationId: Int64? = nil) -> Signal<EnqueueMessage, Void> {
return Signal { subscriber in
if let previewImage = UIImage(data: data) {
let dimensions = previewImage.size
var previewRepresentations: [TelegramMediaImageRepresentation] = []
let thumbnailSize = dimensions.aspectFitted(CGSize(width: 320.0, height: 320.0))
let thumbnailImage = TGScaleImageToPixelSize(previewImage, thumbnailSize)!
if let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.4) {
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
account.postbox.mediaBox.storeResourceData(resource.id, data: thumbnailData)
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailSize), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
}
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let tempFilePath = NSTemporaryDirectory() + "\(randomId).mp4"
let _ = try? FileManager.default.removeItem(atPath: tempFilePath)
let _ = try? data.write(to: URL(fileURLWithPath: tempFilePath), options: [.atomic])
let resource = LocalFileGifMediaResource(randomId: Int64.random(in: Int64.min ... Int64.max), path: tempFilePath)
let fileName: String = "video.mp4"
let finalDimensions = TGMediaVideoConverter.dimensions(for: dimensions, adjustments: nil, preset: TGMediaVideoConversionPresetAnimation)
var fileAttributes: [TelegramMediaFileAttribute] = []
fileAttributes.append(.Video(duration: 0.0, size: PixelDimensions(finalDimensions), flags: [.supportsStreaming], preloadSize: nil, coverTime: nil, videoCodec: nil))
fileAttributes.append(.FileName(fileName: fileName))
fileAttributes.append(.Animated)
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes, alternativeRepresentations: [])
subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []))
subscriber.putCompletion()
} else {
subscriber.putError(Void())
}
return EmptyDisposable
} |> runOn(Queue.concurrentDefaultQueue())
}
public struct LegacyAssetPickerEnqueueMessage {
public var message: EnqueueMessage
public var uniqueId: String?

View file

@ -4,34 +4,33 @@ import AsyncDisplayKit
import Display
import TelegramCore
import SwiftSignalKit
import Postbox
import TelegramPresentationData
import AccountContext
import TelegramUIPreferences
import ItemListUI
public final class ListMessageItemInteraction {
public let openMessage: (Message, ChatControllerInteractionOpenMessageMode) -> Bool
public let openMessageContextMenu: (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void
public let toggleMessagesSelection: ([MessageId], Bool) -> Void
public let toggleMediaPlayback: ((Message) -> Void)?
let openUrl: (String, Bool, Bool?, Message?) -> Void
let openInstantPage: (Message, ChatMessageItemAssociatedData?) -> Void
let longTap: (ChatControllerInteractionLongTapAction, Message?) -> Void
let getHiddenMedia: () -> [MessageId: [Media]]
public let openMessage: (EngineRawMessage, ChatControllerInteractionOpenMessageMode) -> Bool
public let openMessageContextMenu: (EngineRawMessage, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void
public let toggleMessagesSelection: ([EngineMessage.Id], Bool) -> Void
public let toggleMediaPlayback: ((EngineRawMessage) -> Void)?
let openUrl: (String, Bool, Bool?, EngineRawMessage?) -> Void
let openInstantPage: (EngineRawMessage, ChatMessageItemAssociatedData?) -> Void
let longTap: (ChatControllerInteractionLongTapAction, EngineRawMessage?) -> Void
let getHiddenMedia: () -> [EngineMessage.Id: [EngineRawMedia]]
public var searchTextHighightState: String?
public var preferredStoryHighQuality: Bool = false
public init(
openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool,
openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void,
toggleMediaPlayback: ((Message) -> Void)?,
toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void,
openUrl: @escaping (String, Bool, Bool?, Message?) -> Void,
openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void,
longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void,
getHiddenMedia: @escaping () -> [MessageId: [Media]]
openMessage: @escaping (EngineRawMessage, ChatControllerInteractionOpenMessageMode) -> Bool,
openMessageContextMenu: @escaping (EngineRawMessage, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void,
toggleMediaPlayback: ((EngineRawMessage) -> Void)?,
toggleMessagesSelection: @escaping ([EngineMessage.Id], Bool) -> Void,
openUrl: @escaping (String, Bool, Bool?, EngineRawMessage?) -> Void,
openInstantPage: @escaping (EngineRawMessage, ChatMessageItemAssociatedData?) -> Void,
longTap: @escaping (ChatControllerInteractionLongTapAction, EngineRawMessage?) -> Void,
getHiddenMedia: @escaping () -> [EngineMessage.Id: [EngineRawMedia]]
) {
self.openMessage = openMessage
self.openMessageContextMenu = openMessageContextMenu
@ -51,7 +50,7 @@ public final class ListMessageItemInteraction {
openUrl: { _, _, _, _ in
}, openInstantPage: { _, _ in
}, longTap: { _, _ in
}, getHiddenMedia: { () -> [MessageId : [Media]] in
}, getHiddenMedia: { () -> [EngineMessage.Id : [EngineRawMedia]] in
return [:]
})
}
@ -67,7 +66,7 @@ public final class ListMessageItem: ListViewItem, ItemListItem {
let context: AccountContext
let chatLocation: ChatLocation
let interaction: ListMessageItemInteraction
let message: Message?
let message: EngineRawMessage?
let translateToLanguage: String?
public let selection: ChatHistoryMessageSelection
public let selectionSide: ListMessageItemSelectionSide
@ -94,7 +93,7 @@ public final class ListMessageItem: ListViewItem, ItemListItem {
context: AccountContext,
chatLocation: ChatLocation,
interaction: ListMessageItemInteraction,
message: Message?,
message: EngineRawMessage?,
translateToLanguage: String? = nil,
selection: ChatHistoryMessageSelection,
selectionSide: ListMessageItemSelectionSide = .right,

View file

@ -2,7 +2,7 @@ import Foundation
import UIKit
import Display
import AsyncDisplayKit
import Postbox
import TelegramCore
import AccountContext
public class ListMessageNode: ListViewItemNode {
@ -28,7 +28,7 @@ public class ListMessageNode: ListViewItemNode {
}
}
public func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
public func transitionNode(id: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
return nil
}

View file

@ -11,7 +11,6 @@ swift_library(
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/Postbox:Postbox",
"//submodules/TelegramCore:TelegramCore",
"//submodules/ImageCompression:ImageCompression",
"//submodules/PersistentStringHash:PersistentStringHash",

View file

@ -1,27 +1,26 @@
import Foundation
import UIKit
import Postbox
import TelegramCore
import PersistentStringHash
public final class VideoMediaResourceAdjustments: PostboxCoding, Equatable {
public let data: MemoryBuffer
public let digest: MemoryBuffer
public final class VideoMediaResourceAdjustments: EnginePostboxCoding, Equatable {
public let data: EngineMemoryBuffer
public let digest: EngineMemoryBuffer
public let isStory: Bool
public init(data: MemoryBuffer, digest: MemoryBuffer, isStory: Bool = false) {
public init(data: EngineMemoryBuffer, digest: EngineMemoryBuffer, isStory: Bool = false) {
self.data = data
self.digest = digest
self.isStory = isStory
}
public init(decoder: PostboxDecoder) {
public init(decoder: EnginePostboxDecoder) {
self.data = decoder.decodeBytesForKey("d")!
self.digest = decoder.decodeBytesForKey("h")!
self.isStory = decoder.decodeBoolForKey("s", orElse: false)
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
encoder.encodeBytes(self.data, forKey: "d")
encoder.encodeBytes(self.digest, forKey: "h")
encoder.encodeBool(self.isStory, forKey: "s")
@ -34,7 +33,7 @@ public final class VideoMediaResourceAdjustments: PostboxCoding, Equatable {
public struct VideoLibraryMediaResourceId {
public let localIdentifier: String
public let adjustmentsDigest: MemoryBuffer?
public let adjustmentsDigest: EngineMemoryBuffer?
public var uniqueId: String {
if let adjustmentsDigest = self.adjustmentsDigest {
@ -49,11 +48,11 @@ public struct VideoLibraryMediaResourceId {
}
}
public enum VideoLibraryMediaResourceConversion: PostboxCoding, Equatable {
public enum VideoLibraryMediaResourceConversion: EnginePostboxCoding, Equatable {
case passthrough
case compress(VideoMediaResourceAdjustments?)
public init(decoder: PostboxDecoder) {
public init(decoder: EnginePostboxDecoder) {
switch decoder.decodeInt32ForKey("v", orElse: 0) {
case 0:
self = .passthrough
@ -64,7 +63,7 @@ public enum VideoLibraryMediaResourceConversion: PostboxCoding, Equatable {
}
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
switch self {
case .passthrough:
encoder.encodeInt32(0, forKey: "v")
@ -113,28 +112,28 @@ public final class VideoLibraryMediaResource: TelegramMediaResource {
self.conversion = conversion
}
public required init(decoder: PostboxDecoder) {
public required init(decoder: EnginePostboxDecoder) {
self.localIdentifier = decoder.decodeStringForKey("i", orElse: "")
self.conversion = (decoder.decodeObjectForKey("conv", decoder: { VideoLibraryMediaResourceConversion(decoder: $0) }) as? VideoLibraryMediaResourceConversion) ?? .compress(nil)
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
encoder.encodeString(self.localIdentifier, forKey: "i")
encoder.encodeObject(self.conversion, forKey: "conv")
}
public var id: MediaResourceId {
var adjustmentsDigest: MemoryBuffer?
public var id: EngineRawMediaResourceId {
var adjustmentsDigest: EngineMemoryBuffer?
switch self.conversion {
case .passthrough:
break
case let .compress(adjustments):
adjustmentsDigest = adjustments?.digest
}
return MediaResourceId(VideoLibraryMediaResourceId(localIdentifier: self.localIdentifier, adjustmentsDigest: adjustmentsDigest).uniqueId)
return EngineRawMediaResourceId(VideoLibraryMediaResourceId(localIdentifier: self.localIdentifier, adjustmentsDigest: adjustmentsDigest).uniqueId)
}
public func isEqual(to: MediaResource) -> Bool {
public func isEqual(to: EngineRawMediaResource) -> Bool {
if let to = to as? VideoLibraryMediaResource {
return self.localIdentifier == to.localIdentifier && self.conversion == to.conversion
} else {
@ -180,7 +179,7 @@ public final class LocalFileVideoMediaResource: TelegramMediaResource {
self.adjustments = adjustments
}
public required init(decoder: PostboxDecoder) {
public required init(decoder: EnginePostboxDecoder) {
self.randomId = decoder.decodeInt64ForKey("i", orElse: 0)
let paths = decoder.decodeStringArrayForKey("ps")
if !paths.isEmpty {
@ -191,7 +190,7 @@ public final class LocalFileVideoMediaResource: TelegramMediaResource {
self.adjustments = decoder.decodeObjectForKey("a", decoder: { VideoMediaResourceAdjustments(decoder: $0) }) as? VideoMediaResourceAdjustments
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
encoder.encodeInt64(self.randomId, forKey: "i")
encoder.encodeStringArray(self.paths, forKey: "ps")
if let adjustments = self.adjustments {
@ -201,11 +200,11 @@ public final class LocalFileVideoMediaResource: TelegramMediaResource {
}
}
public var id: MediaResourceId {
return MediaResourceId(LocalFileVideoMediaResourceId(randomId: self.randomId).uniqueId)
public var id: EngineRawMediaResourceId {
return EngineRawMediaResourceId(LocalFileVideoMediaResourceId(randomId: self.randomId).uniqueId)
}
public func isEqual(to: MediaResource) -> Bool {
public func isEqual(to: EngineRawMediaResource) -> Bool {
if let to = to as? LocalFileVideoMediaResource {
return self.randomId == to.randomId && self.paths == to.paths && self.adjustments == to.adjustments
} else {
@ -245,7 +244,7 @@ public final class LocalFileAudioMediaResource: TelegramMediaResource {
self.trimRange = trimRange
}
public required init(decoder: PostboxDecoder) {
public required init(decoder: EnginePostboxDecoder) {
self.randomId = decoder.decodeInt64ForKey("i", orElse: 0)
self.path = decoder.decodeStringForKey("p", orElse: "")
@ -256,7 +255,7 @@ public final class LocalFileAudioMediaResource: TelegramMediaResource {
}
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
encoder.encodeInt64(self.randomId, forKey: "i")
encoder.encodeString(self.path, forKey: "p")
@ -269,11 +268,11 @@ public final class LocalFileAudioMediaResource: TelegramMediaResource {
}
}
public var id: MediaResourceId {
return MediaResourceId(LocalFileAudioMediaResourceId(randomId: self.randomId).uniqueId)
public var id: EngineRawMediaResourceId {
return EngineRawMediaResourceId(LocalFileAudioMediaResourceId(randomId: self.randomId).uniqueId)
}
public func isEqual(to: MediaResource) -> Bool {
public func isEqual(to: EngineRawMediaResource) -> Bool {
if let to = to as? LocalFileAudioMediaResource {
return self.randomId == to.randomId && self.path == to.path && self.trimRange == to.trimRange
} else {
@ -327,7 +326,7 @@ public class PhotoLibraryMediaResource: TelegramMediaResource {
self.forceHd = forceHd
}
public required init(decoder: PostboxDecoder) {
public required init(decoder: EnginePostboxDecoder) {
self.localIdentifier = decoder.decodeStringForKey("i", orElse: "")
self.uniqueId = decoder.decodeInt64ForKey("uid", orElse: 0)
self.width = decoder.decodeOptionalInt32ForKey("w")
@ -337,7 +336,7 @@ public class PhotoLibraryMediaResource: TelegramMediaResource {
self.forceHd = decoder.decodeBoolForKey("hd", orElse: false)
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
encoder.encodeString(self.localIdentifier, forKey: "i")
encoder.encodeInt64(self.uniqueId, forKey: "uid")
if let width = self.width {
@ -363,11 +362,11 @@ public class PhotoLibraryMediaResource: TelegramMediaResource {
encoder.encodeBool(self.forceHd, forKey: "hd")
}
public var id: MediaResourceId {
return MediaResourceId(PhotoLibraryMediaResourceId(localIdentifier: self.localIdentifier, resourceId: self.uniqueId).uniqueId)
public var id: EngineRawMediaResourceId {
return EngineRawMediaResourceId(PhotoLibraryMediaResourceId(localIdentifier: self.localIdentifier, resourceId: self.uniqueId).uniqueId)
}
public func isEqual(to: MediaResource) -> Bool {
public func isEqual(to: EngineRawMediaResource) -> Bool {
if let to = to as? PhotoLibraryMediaResource {
if self.localIdentifier != to.localIdentifier {
return false
@ -426,21 +425,21 @@ public final class LocalFileGifMediaResource: TelegramMediaResource {
self.path = path
}
public required init(decoder: PostboxDecoder) {
public required init(decoder: EnginePostboxDecoder) {
self.randomId = decoder.decodeInt64ForKey("i", orElse: 0)
self.path = decoder.decodeStringForKey("p", orElse: "")
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
encoder.encodeInt64(self.randomId, forKey: "i")
encoder.encodeString(self.path, forKey: "p")
}
public var id: MediaResourceId {
return MediaResourceId(LocalFileGifMediaResourceId(randomId: self.randomId).uniqueId)
public var id: EngineRawMediaResourceId {
return EngineRawMediaResourceId(LocalFileGifMediaResourceId(randomId: self.randomId).uniqueId)
}
public func isEqual(to: MediaResource) -> Bool {
public func isEqual(to: EngineRawMediaResource) -> Bool {
if let to = to as? LocalFileGifMediaResource {
return self.randomId == to.randomId && self.path == to.path
} else {
@ -475,21 +474,21 @@ public class BundleResource: TelegramMediaResource {
self.path = path
}
public required init(decoder: PostboxDecoder) {
public required init(decoder: EnginePostboxDecoder) {
self.nameHash = decoder.decodeInt64ForKey("h", orElse: 0)
self.path = decoder.decodeStringForKey("p", orElse: "")
}
public func encode(_ encoder: PostboxEncoder) {
public func encode(_ encoder: EnginePostboxEncoder) {
encoder.encodeInt64(self.nameHash, forKey: "h")
encoder.encodeString(self.path, forKey: "p")
}
public var id: MediaResourceId {
return MediaResourceId(BundleResourceId(nameHash: self.nameHash).uniqueId)
public var id: EngineRawMediaResourceId {
return EngineRawMediaResourceId(BundleResourceId(nameHash: self.nameHash).uniqueId)
}
public func isEqual(to: MediaResource) -> Bool {
public func isEqual(to: EngineRawMediaResource) -> Bool {
if let to = to as? BundleResource {
return self.nameHash == to.nameHash
} else {

View file

@ -11,7 +11,6 @@ swift_library(
],
deps = [
"//submodules/TelegramCore:TelegramCore",
"//submodules/Postbox:Postbox",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/TelegramUIPreferences:TelegramUIPreferences",
],

View file

@ -1,11 +1,11 @@
import Foundation
import UIKit
import SwiftSignalKit
import Postbox
import TelegramCore
public final class CachedStickerAJpegRepresentation: CachedMediaResourceRepresentation {
public final class CachedStickerAJpegRepresentation: EngineRawCachedMediaResourceRepresentation {
public let size: CGSize?
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public var uniqueId: String {
if let size = self.size {
@ -19,7 +19,7 @@ public final class CachedStickerAJpegRepresentation: CachedMediaResourceRepresen
self.size = size
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let to = to as? CachedStickerAJpegRepresentation {
return self.size == to.size
} else {
@ -33,8 +33,8 @@ public enum CachedScaledImageRepresentationMode: Int32 {
case aspectFit = 1
}
public final class CachedScaledImageRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedScaledImageRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public let size: CGSize
public let mode: CachedScaledImageRepresentationMode
@ -48,7 +48,7 @@ public final class CachedScaledImageRepresentation: CachedMediaResourceRepresent
self.mode = mode
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let to = to as? CachedScaledImageRepresentation {
return self.size == to.size && self.mode == to.mode
} else {
@ -57,8 +57,8 @@ public final class CachedScaledImageRepresentation: CachedMediaResourceRepresent
}
}
public final class CachedVideoFirstFrameRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedVideoFirstFrameRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public var uniqueId: String {
return "first-frame"
@ -67,7 +67,7 @@ public final class CachedVideoFirstFrameRepresentation: CachedMediaResourceRepre
public init() {
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if to is CachedVideoFirstFrameRepresentation {
return true
} else {
@ -76,8 +76,8 @@ public final class CachedVideoFirstFrameRepresentation: CachedMediaResourceRepre
}
}
public final class CachedVideoPrefixFirstFrameRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedVideoPrefixFirstFrameRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public var uniqueId: String {
return "prefix-first-frame"
@ -89,7 +89,7 @@ public final class CachedVideoPrefixFirstFrameRepresentation: CachedMediaResourc
self.prefixLength = prefixLength
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let to = to as? CachedVideoPrefixFirstFrameRepresentation {
if self.prefixLength != to.prefixLength {
return false
@ -101,8 +101,8 @@ public final class CachedVideoPrefixFirstFrameRepresentation: CachedMediaResourc
}
}
public final class CachedScaledVideoFirstFrameRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedScaledVideoFirstFrameRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public let size: CGSize
@ -114,7 +114,7 @@ public final class CachedScaledVideoFirstFrameRepresentation: CachedMediaResourc
self.size = size
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let to = to as? CachedScaledVideoFirstFrameRepresentation {
return self.size == to.size
} else {
@ -123,8 +123,8 @@ public final class CachedScaledVideoFirstFrameRepresentation: CachedMediaResourc
}
}
public final class CachedBlurredWallpaperRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedBlurredWallpaperRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public var uniqueId: String {
return "blurred-wallpaper"
@ -133,7 +133,7 @@ public final class CachedBlurredWallpaperRepresentation: CachedMediaResourceRepr
public init() {
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if to is CachedBlurredWallpaperRepresentation {
return true
} else {
@ -142,8 +142,8 @@ public final class CachedBlurredWallpaperRepresentation: CachedMediaResourceRepr
}
}
public final class CachedAlbumArtworkRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedAlbumArtworkRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public let size: CGSize?
@ -159,7 +159,7 @@ public final class CachedAlbumArtworkRepresentation: CachedMediaResourceRepresen
self.size = size
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let to = to as? CachedAlbumArtworkRepresentation {
return self.size == to.size
} else {
@ -168,8 +168,8 @@ public final class CachedAlbumArtworkRepresentation: CachedMediaResourceRepresen
}
}
public final class CachedEmojiThumbnailRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedEmojiThumbnailRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public let outline: Bool
@ -181,7 +181,7 @@ public final class CachedEmojiThumbnailRepresentation: CachedMediaResourceRepres
self.outline = outline
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let to = to as? CachedEmojiThumbnailRepresentation {
return self.outline == to.outline
} else {
@ -190,8 +190,8 @@ public final class CachedEmojiThumbnailRepresentation: CachedMediaResourceRepres
}
}
public final class CachedEmojiRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedEmojiRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public let tile: UInt8
public let outline: Bool
@ -205,7 +205,7 @@ public final class CachedEmojiRepresentation: CachedMediaResourceRepresentation
self.outline = outline
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let to = to as? CachedEmojiRepresentation {
return self.tile == to.tile && self.outline == to.outline
} else {
@ -239,8 +239,8 @@ public enum EmojiFitzModifier: Int32, Equatable {
}
}
public final class CachedAnimatedStickerFirstFrameRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedAnimatedStickerFirstFrameRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public let width: Int32
public let height: Int32
@ -261,7 +261,7 @@ public final class CachedAnimatedStickerFirstFrameRepresentation: CachedMediaRes
}
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let other = to as? CachedAnimatedStickerFirstFrameRepresentation {
if other.width != self.width {
return false
@ -279,8 +279,8 @@ public final class CachedAnimatedStickerFirstFrameRepresentation: CachedMediaRes
}
}
public final class CachedAnimatedStickerRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .shortLived
public final class CachedAnimatedStickerRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .shortLived
public let width: Int32
public let height: Int32
@ -301,7 +301,7 @@ public final class CachedAnimatedStickerRepresentation: CachedMediaResourceRepre
self.fitzModifier = fitzModifier
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let other = to as? CachedAnimatedStickerRepresentation {
if other.width != self.width {
return false
@ -319,8 +319,8 @@ public final class CachedAnimatedStickerRepresentation: CachedMediaResourceRepre
}
}
public final class CachedVideoStickerRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .shortLived
public final class CachedVideoStickerRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .shortLived
public let width: Int32
public let height: Int32
@ -336,7 +336,7 @@ public final class CachedVideoStickerRepresentation: CachedMediaResourceRepresen
self.height = height
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if let other = to as? CachedVideoStickerRepresentation {
if other.width != self.width {
return false
@ -351,8 +351,8 @@ public final class CachedVideoStickerRepresentation: CachedMediaResourceRepresen
}
}
public final class CachedPreparedPatternWallpaperRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedPreparedPatternWallpaperRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public var uniqueId: String {
return "prepared-pattern-wallpaper"
@ -361,7 +361,7 @@ public final class CachedPreparedPatternWallpaperRepresentation: CachedMediaReso
public init() {
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if to is CachedPreparedPatternWallpaperRepresentation {
return true
} else {
@ -371,8 +371,8 @@ public final class CachedPreparedPatternWallpaperRepresentation: CachedMediaReso
}
public final class CachedPreparedSvgRepresentation: CachedMediaResourceRepresentation {
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public final class CachedPreparedSvgRepresentation: EngineRawCachedMediaResourceRepresentation {
public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general
public var uniqueId: String {
return "prepared-svg"
@ -381,7 +381,7 @@ public final class CachedPreparedSvgRepresentation: CachedMediaResourceRepresent
public init() {
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool {
if to is CachedPreparedSvgRepresentation {
return true
} else {

View file

@ -76,7 +76,7 @@ func presentLegacySecureIdAttachmentMenu(context: AccountContext, present: @esca
|> runOn(.mainQueue())
|> delay(0.1, queue: .mainQueue())).start()
let _ = (processedLegacySecureIdAttachmentItems(postbox: context.account.postbox, signal: signal)
let _ = (processedLegacySecureIdAttachmentItems(signal: signal)
|> mapToSignal { resources -> Signal<([TelegramMediaResource], SecureIdRecognizedDocumentData?), NoError> in
switch type {
case .generic, .idCard:
@ -116,7 +116,7 @@ private enum AttachmentItem {
case iCloud(URL)
}
private func processedLegacySecureIdAttachmentItems(postbox: Postbox, signal: SSignal) -> Signal<[TelegramMediaResource], NoError> {
private func processedLegacySecureIdAttachmentItems(signal: SSignal) -> Signal<[TelegramMediaResource], NoError> {
let nativeSignal = Signal<AttachmentItem?, NoError> { subscriber in
let disposable = signal.start(next: { next in
if let dict = next as? [String: Any], let image = dict["image"] as? UIImage {

View file

@ -844,24 +844,6 @@ private func chatMessageVideoDatas(postbox: Postbox, userLocation: MediaResource
return signal
}
public func rawMessagePhoto(postbox: Postbox, userLocation: MediaResourceUserLocation, photoReference: ImageMediaReference) -> Signal<UIImage?, NoError> {
return chatMessagePhotoDatas(postbox: postbox, userLocation: userLocation, photoReference: photoReference, autoFetchFullSize: true)
|> map { value -> UIImage? in
let thumbnailData = value._0
let fullSizeData = value._1
let fullSizeComplete = value._3
if let fullSizeData = fullSizeData {
if fullSizeComplete {
return UIImage(data: fullSizeData)?.precomposed()
}
}
if let thumbnailData = thumbnailData {
return UIImage(data: thumbnailData)?.precomposed()
}
return nil
}
}
public func chatMessagePhoto(postbox: Postbox, userLocation: MediaResourceUserLocation, userContentType customUserContentType: MediaResourceUserContentType? = nil, photoReference: ImageMediaReference, synchronousLoad: Bool = false, highQuality: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
return chatMessagePhotoInternal(photoData: chatMessagePhotoDatas(postbox: postbox, userLocation: userLocation, customUserContentType: customUserContentType, photoReference: photoReference, tryAdditionalRepresentations: true, synchronousLoad: synchronousLoad), synchronousLoad: synchronousLoad)
|> map { _, _, generate in
@ -1766,79 +1748,6 @@ public func mediaGridMessagePhoto(account: Account, userLocation: MediaResourceU
}
}
public func gifPaneVideoThumbnail(account: Account, videoReference: FileMediaReference) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
if let smallestRepresentation = smallestImageRepresentation(videoReference.media.previewRepresentations) {
let thumbnailResource = smallestRepresentation.resource
let thumbnail = Signal<MediaResourceData, NoError> { subscriber in
let data = account.postbox.mediaBox.resourceData(thumbnailResource).start(next: { data in
subscriber.putNext(data)
}, completed: {
subscriber.putCompletion()
})
let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: videoReference.resourceReference(thumbnailResource)).start()
return ActionDisposable {
data.dispose()
fetched.dispose()
}
}
return thumbnail
|> map { data in
let thumbnailData = try? Data(contentsOf: URL(fileURLWithPath: data.path))
return { arguments in
guard let context = DrawingContext(size: arguments.drawingSize, clear: true) else {
return nil
}
let drawingRect = arguments.drawingRect
let fittedSize = arguments.imageSize.aspectFilled(arguments.boundingSize).fitted(arguments.imageSize)
let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize)
var thumbnailImage: CGImage?
if let thumbnailData = thumbnailData, let imageSource = CGImageSourceCreateWithData(thumbnailData as CFData, nil), let image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) {
thumbnailImage = image
}
var blurredThumbnailImage: UIImage?
if let thumbnailImage = thumbnailImage {
let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height)
let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 150.0, height: 150.0))
if let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) {
thumbnailContext.withFlippedContext { c in
c.interpolationQuality = .none
c.draw(thumbnailImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
}
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
blurredThumbnailImage = thumbnailContext.generateImage()
}
}
context.withFlippedContext { c in
c.setBlendMode(.copy)
if arguments.boundingSize != arguments.imageSize {
c.fill(arguments.drawingRect)
}
c.setBlendMode(.copy)
if let blurredThumbnailImage = blurredThumbnailImage, let cgImage = blurredThumbnailImage.cgImage {
c.interpolationQuality = .low
drawImage(context: c, image: cgImage, orientation: .up, in: fittedRect)
c.setBlendMode(.normal)
}
}
addCorners(context, arguments: arguments)
return context
}
}
} else {
return .never()
}
}
public func mediaGridMessageVideo(postbox: Postbox, userLocation: MediaResourceUserLocation, userContentType customUserContentType: MediaResourceUserContentType? = nil, videoReference: FileMediaReference, hlsFiles: [(playlist: TelegramMediaFile, video: TelegramMediaFile)] = [], onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, overlayColor: UIColor? = nil, nilForEmptyResult: Bool = false, useMiniThumbnailIfAvailable: Bool = false, blurred: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
return internalMediaGridMessageVideo(postbox: postbox, userLocation: userLocation, customUserContentType: customUserContentType, videoReference: videoReference, hlsFiles: hlsFiles, onlyFullSize: onlyFullSize, useLargeThumbnail: useLargeThumbnail, synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail, overlayColor: overlayColor, nilForEmptyResult: nilForEmptyResult, useMiniThumbnailIfAvailable: useMiniThumbnailIfAvailable)
|> map {
@ -2703,25 +2612,6 @@ public func chatMessageImageFile(account: Account, userLocation: MediaResourceUs
}
}
public func preloadedBotIcon(account: Account, fileReference: FileMediaReference) -> Signal<Bool, NoError> {
let signal = Signal<Bool, NoError> { subscriber in
let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: MediaResourceUserContentType(file: fileReference.media), reference: fileReference.resourceReference(fileReference.media.resource)).start()
let dataDisposable = account.postbox.mediaBox.resourceData(fileReference.media.resource, option: .incremental(waitUntilFetchStatus: false)).start(next: { data in
if data.complete {
subscriber.putNext(true)
subscriber.putCompletion()
} else {
subscriber.putNext(false)
}
})
return ActionDisposable {
fetched.dispose()
dataDisposable.dispose()
}
}
return signal
}
public func instantPageImageFile(account: Account, userLocation: MediaResourceUserLocation, fileReference: FileMediaReference, fetched: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
return chatMessageFileDatas(account: account, userLocation: userLocation, fileReference: fileReference, progressive: false, fetched: fetched)
|> map { value in

View file

@ -1,8 +1,7 @@
import Foundation
import TelegramCore
import Postbox
public extension Message {
public extension EngineRawMessage {
func isRestricted(platform: String, contentSettings: ContentSettings) -> Bool {
return self.restrictionReason(platform: platform, contentSettings: contentSettings) != nil
}

View file

@ -142,7 +142,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
jsonString += "]}}"
if let data = jsonString.data(using: .utf8), let json = JSON(data: data) {
addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium_gift.promo_screen_show", data: json)
strongSelf.context.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_show", data: json)
}
}
@ -568,7 +568,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
controller?.dismiss(animated: true, completion: nil)
}
addAppLogEvent(postbox: accountContext.account.postbox, type: "premium_gift.promo_screen_tap", data: ["item": perk.identifier])
accountContext.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_tap", data: ["item": perk.identifier])
}
))
i += 1
@ -900,7 +900,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
let (currency, amount) = product.storeProduct.priceCurrencyAndAmount
let duration = product.months
addAppLogEvent(postbox: self.context.account.postbox, type: "premium_gift.promo_screen_accept")
self.context.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_accept")
self.inProgress = true
self.updateInProgress(true)
@ -968,7 +968,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
}
if let errorText = errorText {
addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium_gift.promo_screen_fail")
strongSelf.context.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_fail")
let alertController = textAlertController(context: strongSelf.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
strongSelf.present(alertController)

View file

@ -1682,7 +1682,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
jsonString += "]}}"
if let context = screenContext.context, let data = jsonString.data(using: .utf8), let json = JSON(data: data) {
addAppLogEvent(postbox: context.account.postbox, type: "premium.promo_screen_show", data: json)
context.engine.accountData.addAppLogEvent(type: "premium.promo_screen_show", data: json)
}
}
})
@ -2260,7 +2260,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
}
updateIsFocused(true)
addAppLogEvent(postbox: accountContext.account.postbox, type: "premium.promo_screen_tap", data: ["item": perk.identifier])
accountContext.engine.accountData.addAppLogEvent(type: "premium.promo_screen_tap", data: ["item": perk.identifier])
},
highlighting: accountContext != nil ? .default : .disabled
))))
@ -3262,7 +3262,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
}
if let context = self.screenContext.context {
addAppLogEvent(postbox: context.account.postbox, type: "premium.promo_screen_accept")
context.engine.accountData.addAppLogEvent(type: "premium.promo_screen_accept")
}
self.inProgress = true
@ -3316,7 +3316,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
self.updated(transition: .immediate)
if let context = self.screenContext.context {
addAppLogEvent(postbox: context.account.postbox, type: "premium.promo_screen_fail")
context.engine.accountData.addAppLogEvent(type: "premium.promo_screen_fail")
}
let errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
@ -3368,7 +3368,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
if let errorText = errorText {
if let context = self.screenContext.context {
addAppLogEvent(postbox: context.account.postbox, type: "premium.promo_screen_fail")
context.engine.accountData.addAppLogEvent(type: "premium.promo_screen_fail")
}
let alertController = textAlertController(sharedContext: self.screenContext.sharedContext, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])

View file

@ -296,15 +296,15 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat
switch mode {
case .peers:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_cloud_cancel")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_cloud_cancel")
case .groups:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_groups_cancel")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_groups_cancel")
case .messages:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_messages_cancel")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_messages_cancel")
case .phone:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_phone_cancel")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_phone_cancel")
case .password:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_2fa_cancel")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_2fa_cancel")
}
}
@ -437,10 +437,10 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat
let controller = deleteAccountDataController(context: context, mode: nextMode, twoStepAuthData: twoStepAuthData)
replaceTopControllerImpl?(controller)
} else {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_confirmation_show")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_confirmation_show")
presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.DeleteAccount_ConfirmationAlertTitle, text: presentationData.strings.DeleteAccount_ConfirmationAlertText, actions: [TextAlertAction(type: .destructiveAction, title: presentationData.strings.DeleteAccount_ConfirmationAlertDelete, action: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.final")
context.engine.accountData.addAppLogEvent(type: "deactivate.final")
invokeAppLogEventsSynchronization(postbox: context.account.postbox)
@ -473,7 +473,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat
})
})
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_confirmation_cancel")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_confirmation_cancel")
dismissImpl?()
})], actionLayout: .vertical))
@ -581,15 +581,15 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat
switch mode {
case .peers:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_cloud_show")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_cloud_show")
case .groups:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_groups_show")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_groups_show")
case .messages:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_messages_show")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_messages_show")
case .phone:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_phone_show")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_phone_show")
case .password:
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_2fa_show")
context.engine.accountData.addAppLogEvent(type: "deactivate.step_2fa_show")
}
return controller

View file

@ -181,7 +181,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
let supportPeerDisposable = MetaDisposable()
let arguments = DeleteAccountOptionsArguments(changePhoneNumber: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_phone_change_tap")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_phone_change_tap")
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.engine.account.peerId))
|> deliverOnMainQueue).start(next: { accountPeer in
@ -195,7 +195,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
dismissImpl?()
})
}, addAccount: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_add_account_tap")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_add_account_tap")
let _ = (activeAccountsAndPeers(context: context)
|> take(1)
@ -233,11 +233,11 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
}
})
}, setupPrivacy: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_privacy_tap")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_privacy_tap")
replaceTopControllerImpl?(makePrivacyAndSecurityController(context: context), false)
}, setupTwoStepAuth: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_2fa_tap")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_2fa_tap")
if let data = twoStepAuthData {
switch data {
@ -263,7 +263,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
let controller = twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: false, data: twoStepAuthData.flatMap({ Signal<TwoStepVerificationUnlockSettingsControllerData, NoError>.single(.access(configuration: $0)) })))
replaceTopControllerImpl?(controller, false)
}, setPasscode: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_passcode_tap")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_passcode_tap")
let _ = passcodeOptionsAccessController(context: context, pushController: { controller in
replaceTopControllerImpl?(controller, false)
@ -276,18 +276,18 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
})
dismissImpl?()
}, clearCache: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_cache_tap")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_clear_cache_tap")
pushControllerImpl?(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
}))
dismissImpl?()
}, clearSyncedContacts: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_contacts_tap")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_clear_contacts_tap")
replaceTopControllerImpl?(dataPrivacyController(context: context), false)
}, deleteChats: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_delete_chats_tap")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_delete_chats_tap")
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -325,7 +325,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
openFaq(resolvedUrlPromise)
}, contactSupport: { [weak navigationController] in
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_support_tap")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_support_tap")
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -394,7 +394,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
]
)
alertController.dismissed = { _ in
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_support_cancel")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_support_cancel")
}
presentControllerImpl?(alertController, nil)
}, deleteAccount: {
@ -464,7 +464,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
let _ = controller?.dismiss()
}
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_show")
context.engine.accountData.addAppLogEvent(type: "deactivate.options_show")
return controller
}

View file

@ -363,10 +363,10 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
var selectAccentColorImpl: ((TelegramBaseTheme?, PresentationThemeAccentColor?) -> Void)?
var openAccentColorPickerImpl: ((PresentationThemeReference, Bool) -> Void)?
let _ = telegramWallpapers(postbox: context.account.postbox, network: context.account.network).start()
let _ = context.engine.themes.wallpapers().start()
let cloudThemes = Promise<[TelegramTheme]>()
let updatedCloudThemes = telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager)
let updatedCloudThemes = context.engine.themes.themes(accountManager: context.sharedContext.accountManager)
cloudThemes.set(updatedCloudThemes)
let removedThemeIndexesPromise = Promise<Set<Int64>>(Set())

View file

@ -565,7 +565,7 @@ public func themeAutoNightSettingsController(context: AccountContext) -> ViewCon
})
let cloudThemes = Promise<[TelegramTheme]>()
let updatedCloudThemes = telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager)
let updatedCloudThemes = context.engine.themes.themes(accountManager: context.sharedContext.accountManager)
cloudThemes.set(updatedCloudThemes)
let signal = combineLatest(context.sharedContext.presentationData |> deliverOnMainQueue, sharedData |> deliverOnMainQueue, cloudThemes.get() |> deliverOnMainQueue, stagingSettingsPromise.get() |> deliverOnMainQueue)

View file

@ -284,7 +284,7 @@ public final class ThemePreviewController: ViewController {
switch theme {
case let .cloud(info):
resolvedWallpaper = info.resolvedWallpaper
return telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager)
return context.engine.themes.themes(accountManager: context.sharedContext.accountManager)
|> take(1)
|> map { themes -> Bool in
if let _ = themes.first(where: { $0.id == info.theme.id }) {
@ -317,7 +317,7 @@ public final class ThemePreviewController: ViewController {
}, scale: 1.0)
let themeThumbnailData = themeThumbnail?.jpegData(compressionQuality: 0.6)
return telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager)
return context.engine.themes.themes(accountManager: context.sharedContext.accountManager)
|> take(1)
|> mapToSignal { themes -> Signal<(PresentationThemeReference, Bool), NoError> in
let similarTheme = themes.first(where: { $0.isCreator && $0.title == info.title })

View file

@ -520,7 +520,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
var selectAccentColorImpl: ((PresentationThemeAccentColor?) -> Void)?
var openAccentColorPickerImpl: ((PresentationThemeReference, Bool) -> Void)?
let _ = telegramWallpapers(postbox: context.account.postbox, network: context.account.network).start()
let _ = context.engine.themes.wallpapers().start()
let currentAppIcon: PresentationAppIcon?
var appIcons = context.sharedContext.applicationBindings.getAvailableAlternateIcons()
@ -540,7 +540,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
currentAppIconName.set(currentAppIcon?.name ?? "Blue")
let cloudThemes = Promise<[TelegramTheme]>()
let updatedCloudThemes = telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager)
let updatedCloudThemes = context.engine.themes.themes(accountManager: context.sharedContext.accountManager)
cloudThemes.set(updatedCloudThemes)
let removedThemeIndexesPromise = Promise<Set<Int64>>(Set())

View file

@ -1,18 +0,0 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SpotlightSupport",
module_name = "SpotlightSupport",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/SyncCore:SyncCore",
"//submodules/TelegramCore:TelegramCore",
"//submodules/Display:Display",
],
visibility = [
"//visibility:public",
],
)

View file

@ -4,7 +4,6 @@ import Display
import AsyncDisplayKit
import ComponentFlow
import SwiftSignalKit
import Postbox
import TelegramCore
import PhotoResources
import AvatarStoryIndicatorComponent
@ -15,7 +14,7 @@ final class StoryIconNode: ASDisplayNode {
private let imageNode = TransformImageNode()
private let storyIndicator = ComponentView<Empty>()
init(context: AccountContext, theme: PresentationTheme, peer: Peer, storyItem: EngineStoryItem) {
init(context: AccountContext, theme: PresentationTheme, peer: EngineRawPeer, storyItem: EngineStoryItem) {
self.imageNode.displaysAsynchronously = false
super.init()
@ -29,7 +28,7 @@ final class StoryIconNode: ASDisplayNode {
self.imageNode.frame = bounds.insetBy(dx: 3.0, dy: 3.0)
self.frame = bounds
let media: Media?
let media: EngineRawMedia?
switch storyItem.media {
case let .image(image):
media = image

View file

@ -13,7 +13,6 @@ swift_library(
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/Display:Display",
"//submodules/Postbox:Postbox",
"//submodules/TelegramCore:TelegramCore",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/AccountContext:AccountContext",

View file

@ -2,7 +2,6 @@ import Foundation
import UIKit
import Display
import AsyncDisplayKit
import Postbox
import TelegramCore
import SwiftSignalKit
import AccountContext
@ -802,19 +801,19 @@ private final class StickerPackContainer: ASDisplayNode {
private func emojiSuggestionPeekContent(itemLayer: CALayer, file: TelegramMediaFile) -> Signal<(UIView, CGRect, PeekControllerContent)?, NoError> {
let context = self.context
var collectionId: ItemCollectionId?
var collectionId: EngineItemCollectionId?
for attribute in file.attributes {
if case let .CustomEmoji(_, _, _, packReference) = attribute {
switch packReference {
case let .id(id, _):
collectionId = ItemCollectionId(namespace: Namespaces.ItemCollection.CloudEmojiPacks, id: id)
collectionId = EngineItemCollectionId(namespace: Namespaces.ItemCollection.CloudEmojiPacks, id: id)
default:
break
}
}
}
var bubbleUpEmojiOrStickersets: [ItemCollectionId] = []
var bubbleUpEmojiOrStickersets: [EngineItemCollectionId] = []
if let collectionId {
bubbleUpEmojiOrStickersets.append(collectionId)
}
@ -859,9 +858,9 @@ private final class StickerPackContainer: ASDisplayNode {
case let .CustomEmoji(_, _, displayText, stickerPackReference):
text = displayText
var packId: ItemCollectionId?
var packId: EngineItemCollectionId?
if case let .id(id, _) = stickerPackReference {
packId = ItemCollectionId(namespace: Namespaces.ItemCollection.CloudEmojiPacks, id: id)
packId = EngineItemCollectionId(namespace: Namespaces.ItemCollection.CloudEmojiPacks, id: id)
}
emojiAttribute = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: packId, fileId: file.fileId.id, file: file)
break loop
@ -1468,12 +1467,12 @@ private final class StickerPackContainer: ASDisplayNode {
}
if installedCount == self.currentStickerPacks.count {
var removedPacks: Signal<[(info: ItemCollectionInfo, index: Int, items: [ItemCollectionItem])], NoError> = .single([])
var removedPacks: Signal<[(info: EngineRawItemCollectionInfo, index: Int, items: [EngineRawItemCollectionItem])], NoError> = .single([])
for (info, _, _) in self.currentStickerPacks {
removedPacks = removedPacks
|> mapToSignal { current -> Signal<[(info: ItemCollectionInfo, index: Int, items: [ItemCollectionItem])], NoError> in
|> mapToSignal { current -> Signal<[(info: EngineRawItemCollectionInfo, index: Int, items: [EngineRawItemCollectionItem])], NoError> in
return self.context.engine.stickers.removeStickerPackInteractively(id: info.id, option: .delete)
|> map { result -> [(info: ItemCollectionInfo, index: Int, items: [ItemCollectionItem])] in
|> map { result -> [(info: EngineRawItemCollectionInfo, index: Int, items: [EngineRawItemCollectionItem])] in
if let result = result {
return current + [(info, result.0, result.1)]
} else {
@ -2968,13 +2967,6 @@ public final class StickerPackScreenImpl: ViewController, StickerPackScreen {
}
return .single(result)
}
|> mapToSignal { peer -> Signal<Peer?, NoError> in
if let peer = peer {
return .single(peer._asPeer())
} else {
return .single(nil)
}
}
|> deliverOnMainQueue).start(next: { peer in
guard let strongSelf = self else {
return
@ -2982,7 +2974,7 @@ public final class StickerPackScreenImpl: ViewController, StickerPackScreen {
if let peer {
if let parentNavigationController = strongSelf.parentNavigationController {
strongSelf.controllerNode.dismiss()
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: parentNavigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)), keepStack: .always, animated: true))
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: parentNavigationController, context: strongSelf.context, chatLocation: .peer(peer), keepStack: .always, animated: true))
}
} else {
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Resolve_ErrorNotFound, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))

View file

@ -260,74 +260,6 @@ public func chatMessageAnimatedStickerBackingData(postbox: Postbox, fileReferenc
}
}
public func chatMessageLegacySticker(account: Account, userLocation: MediaResourceUserLocation, file: TelegramMediaFile, small: Bool, fitSize: CGSize, fetched: Bool = false, onlyFullSize: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
let signal = chatMessageStickerDatas(postbox: account.postbox, userLocation: userLocation, file: file, small: small, fetched: fetched, onlyFullSize: onlyFullSize, synchronousLoad: false)
return signal |> map { value in
let fullSizeData = value._1
let fullSizeComplete = value._2
return { preArguments in
var fullSizeImage: (UIImage, UIImage)?
if let fullSizeData = fullSizeData, fullSizeComplete {
if let image = imageFromAJpeg(data: fullSizeData) {
fullSizeImage = image
}
}
if let fullSizeImage = fullSizeImage {
var updatedFitSize = fitSize
if updatedFitSize.width.isEqual(to: 1.0) {
updatedFitSize = fullSizeImage.0.size
}
let contextSize = fullSizeImage.0.size.aspectFitted(updatedFitSize)
let arguments = TransformImageArguments(corners: preArguments.corners, imageSize: contextSize, boundingSize: contextSize, intrinsicInsets: preArguments.intrinsicInsets)
guard let context = DrawingContext(size: arguments.drawingSize, clear: true) else {
return nil
}
let thumbnailImage: CGImage? = nil
var blurredThumbnailImage: UIImage?
if let thumbnailImage = thumbnailImage {
let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height)
let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 150.0, height: 150.0))
if let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) {
thumbnailContext.withFlippedContext { c in
c.interpolationQuality = .none
c.draw(thumbnailImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
}
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
blurredThumbnailImage = thumbnailContext.generateImage()
}
}
context.withFlippedContext { c in
c.setBlendMode(.copy)
if let blurredThumbnailImage = blurredThumbnailImage {
c.interpolationQuality = .low
c.draw(blurredThumbnailImage.cgImage!, in: arguments.drawingRect)
}
if let cgImage = fullSizeImage.0.cgImage, let cgImageAlpha = fullSizeImage.1.cgImage {
c.setBlendMode(.normal)
c.interpolationQuality = .medium
let mask = CGImage(maskWidth: cgImageAlpha.width, height: cgImageAlpha.height, bitsPerComponent: cgImageAlpha.bitsPerComponent, bitsPerPixel: cgImageAlpha.bitsPerPixel, bytesPerRow: cgImageAlpha.bytesPerRow, provider: cgImageAlpha.dataProvider!, decode: nil, shouldInterpolate: true)
c.draw(cgImage.masking(mask!)!, in: arguments.drawingRect)
}
}
return context
} else {
return nil
}
}
}
}
public func chatMessageSticker(account: Account, userLocation: MediaResourceUserLocation, file: TelegramMediaFile, small: Bool, fetched: Bool = false, onlyFullSize: Bool = false, thumbnail: Bool = false, synchronousLoad: Bool = false, colorSpace: CGColorSpace? = nil) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
return chatMessageSticker(postbox: account.postbox, userLocation: userLocation, file: file, small: small, fetched: fetched, onlyFullSize: onlyFullSize, thumbnail: thumbnail, synchronousLoad: synchronousLoad, colorSpace: colorSpace)

View file

@ -1,14 +0,0 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SvgRendering",
module_name = "SvgRendering",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
],
visibility = [
"//visibility:public",
],
)

View file

@ -2,7 +2,6 @@ import Foundation
import UIKit
import Display
import AsyncDisplayKit
import Postbox
import TelegramCore
import SwiftSignalKit
import TelegramPresentationData

View file

@ -5,10 +5,6 @@ import TelegramApi
import MtProtoKit
public enum ChatContextResultMessageDecodingError: Error {
case generic
}
public enum ChatContextResultMessage: PostboxCoding, Equatable, Codable {
enum CodingKeys: String, CodingKey {
case data

View file

@ -1,8 +0,0 @@
import Foundation
public enum CloudMediaResourceLocation: Equatable {
case photo(id: Int64, accessHash: Int64, fileReference: Data, thumbSize: String)
case file(id: Int64, accessHash: Int64, fileReference: Data, thumbSize: String)
case peerPhoto(peer: PeerReference, fullSize: Bool, volumeId: Int64, localId: Int64)
case stickerPackThumbnail(packReference: StickerPackReference, volumeId: Int64, localId: Int64)
}

View file

@ -1321,16 +1321,6 @@ public func authorizeWithPasskey(accountManager: AccountManager<TelegramAccountM
}
}
public enum PasswordRecoveryRequestError {
case limitExceeded
case generic
}
public enum PasswordRecoveryOption {
case none
case email(pattern: String)
}
public enum PasswordRecoveryError {
case invalidCode
case limitExceeded
@ -1586,18 +1576,6 @@ public func signUpWithName(accountManager: AccountManager<TelegramAccountManager
|> switchToLatest
}
public enum AuthorizationStateReset {
case empty
}
public func resetAuthorizationState(account: UnauthorizedAccount, to value: AuthorizationStateReset) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Void in
if let state = transaction.getState() as? UnauthorizedAccountState {
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: state.isTestingEnvironment, masterDatacenterId: state.masterDatacenterId, contents: .empty))
}
}
}
public func togglePreviousCodeEntry(account: UnauthorizedAccount) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> Void in
if let state = transaction.getState() as? UnauthorizedAccountState {

View file

@ -671,7 +671,7 @@ final class MediaReferenceRevalidationContext {
}
|> map { [$0] }
} else {
signal = telegramWallpapers(postbox: postbox, network: network, forceUpdate: true)
signal = _internal_telegramWallpapers(postbox: postbox, network: network, forceUpdate: true)
|> last
|> mapError { _ -> RevalidateMediaReferenceError in
}
@ -697,7 +697,7 @@ final class MediaReferenceRevalidationContext {
func themes(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramTheme], RevalidateMediaReferenceError> {
return self.genericItem(key: .themes, background: background, request: { next, error in
return (telegramThemes(postbox: postbox, network: network, accountManager: nil, forceUpdate: true)
return (_internal_telegramThemes(postbox: postbox, network: network, accountManager: nil, forceUpdate: true)
|> take(1)
|> mapError { _ -> RevalidateMediaReferenceError in
}).start(next: { value in

View file

@ -87,7 +87,7 @@ final class NetworkStatsContext {
for (targetKey, averageStats) in self.averageTargetStats {
if averageStats.count >= 1000 || averageStats.size >= 4 * 1024 * 1024 {
if let postbox = self.postbox {
addAppLogEvent(postbox: postbox, type: "download", data: .dictionary([
_internal_addAppLogEvent(postbox: postbox, type: "download", data: .dictionary([
"n": .number(Double(targetKey.networkType.rawValue)),
"d": .number(Double(targetKey.datacenterId)),
"b": .number(averageStats.networkBps / Double(averageStats.count)),

View file

@ -408,37 +408,6 @@ public func enqueueMessages(account: Account, peerId: PeerId, messages: [Enqueue
}
}
public func enqueueMessagesToMultiplePeers(account: Account, peerIds: [PeerId], threadIds: [PeerId: Int64], messages: [EnqueueMessage]) -> Signal<[MessageId], NoError> {
let signal: Signal<[(Bool, EnqueueMessage)], NoError>
if let transformOutgoingMessageMedia = account.transformOutgoingMessageMedia {
signal = opportunisticallyTransformOutgoingMedia(network: account.network, postbox: account.postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messages: messages, userInteractive: true)
} else {
signal = .single(messages.map { (false, $0) })
}
return signal
|> mapToSignal { messages -> Signal<[MessageId], NoError> in
return account.postbox.transaction { transaction -> [MessageId] in
var messageIds: [MessageId] = []
for peerId in peerIds {
var replyToMessageId: EngineMessageReplySubject?
if let threadIds = threadIds[peerId] {
replyToMessageId = EngineMessageReplySubject(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadIds)), quote: nil, innerSubject: nil)
}
var messages = messages
if let replyToMessageId = replyToMessageId {
messages = messages.map { ($0.0, $0.1.withUpdatedReplyToMessageId(replyToMessageId)) }
}
for id in enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: messages, disableAutoremove: false, transformGroupingKeysWithPeerId: true) {
if let id = id {
messageIds.append(id)
}
}
}
return messageIds
}
}
}
public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Void in
var removeMessageIds: [MessageId] = []

View file

@ -8,12 +8,6 @@ public enum StandaloneUploadMediaError {
case generic
}
public struct StandaloneUploadSecretFile {
let file: Api.InputEncryptedFile
let size: Int32
let key: SecretFileEncryptionKey
}
public enum StandaloneUploadMediaThumbnailResult {
case pending
case file(Api.InputFile)

View file

@ -1,20 +0,0 @@
import Foundation
import Postbox
import SwiftSignalKit
import MtProtoKit
public func updateContentPrivacySettings(postbox: Postbox, _ f: @escaping (ContentPrivacySettings) -> ContentPrivacySettings) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Void in
var updated: ContentPrivacySettings?
transaction.updatePreferencesEntry(key: PreferencesKeys.contentPrivacySettings, { current in
if let current = current?.get(ContentPrivacySettings.self) {
updated = f(current)
return PreferencesEntry(updated)
} else {
updated = f(ContentPrivacySettings.defaultSettings)
return PreferencesEntry(updated)
}
})
}
}

View file

@ -24,7 +24,7 @@ extension SplitTest {
public func addEvent(_ event: Self.Event, data: JSON = []) {
if let bucket = self.bucket {
//TODO: merge additional data
addAppLogEvent(postbox: self.postbox, type: event.rawValue, data: ["bucket": bucket])
_internal_addAppLogEvent(postbox: self.postbox, type: event.rawValue, data: ["bucket": bucket])
}
}
}

View file

@ -1423,10 +1423,6 @@ private final class CallSessionManagerContext {
}
}
public enum CallRequestError {
case generic
}
public final class CallSessionManager {
public static func getStableIncomingUUID(stableId: Int64) -> UUID {
return StableIncomingUUIDs.shared.with { impl in

View file

@ -4,7 +4,7 @@ import SwiftSignalKit
import MtProtoKit
public func addAppLogEvent(postbox: Postbox, time: Double = Date().timeIntervalSince1970, type: String, peerId: PeerId? = nil, data: JSON = .dictionary([:])) {
func _internal_addAppLogEvent(postbox: Postbox, time: Double = Date().timeIntervalSince1970, type: String, peerId: PeerId? = nil, data: JSON = .dictionary([:])) {
let tag: PeerOperationLogTag = OperationLogTags.SynchronizeAppLogEvents
let peerId = PeerId(0)
let _ = (postbox.transaction { transaction in

View file

@ -1,42 +0,0 @@
import Foundation
import Postbox
public struct ArchivedStickerPacksInfoId {
public let rawValue: MemoryBuffer
public let id: Int32
init(_ rawValue: MemoryBuffer) {
self.rawValue = rawValue
assert(rawValue.length == 4)
var idValue: Int32 = 0
memcpy(&idValue, rawValue.memory, 4)
self.id = idValue
}
init(_ id: Int32) {
self.id = id
var idValue: Int32 = id
self.rawValue = MemoryBuffer(memory: malloc(4)!, capacity: 4, length: 4, freeWhenDone: true)
memcpy(self.rawValue.memory, &idValue, 4)
}
}
public final class ArchivedStickerPacksInfo: Codable {
public let count: Int32
init(count: Int32) {
self.count = count
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
self.count = try container.decode(Int32.self, forKey: "c")
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(self.count, forKey: "c")
}
}

View file

@ -1,11 +1,5 @@
import Postbox
public enum AutodownloadPreset {
case low
case medium
case high
}
public struct AutodownloadPresetSettings: Codable {
public let disabled: Bool
public let photoSizeMax: Int64

View file

@ -1,18 +0,0 @@
import Foundation
import Postbox
public class LocalMediaPlaybackInfoAttribute: MessageAttribute {
public let data: Data
public init(data: Data) {
self.data = data
}
required public init(decoder: PostboxDecoder) {
self.data = decoder.decodeDataForKey("d") ?? Data()
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeData(self.data, forKey: "d")
}
}

View file

@ -114,23 +114,6 @@ public func newSessionReviews(postbox: Postbox) -> Signal<[NewSessionReview], No
}
}
public func addNewSessionReview(postbox: Postbox, item: NewSessionReview) -> Signal<Never, NoError> {
return postbox.transaction { transaction -> Void in
guard let entry = CodableEntry(item) else {
return
}
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.NewSessionReviews, item: OrderedItemListEntry(id: NewSessionReview.Id(id: item.id).rawValue, contents: entry), removeTailIfCountExceeds: 200)
}
|> ignoreValues
}
public func clearNewSessionReviews(postbox: Postbox) -> Signal<Never, NoError> {
return postbox.transaction { transaction -> Void in
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.NewSessionReviews, items: [])
}
|> ignoreValues
}
public func removeNewSessionReviews(postbox: Postbox, ids: [Int64]) -> Signal<Never, NoError> {
return postbox.transaction { transaction -> Void in
for id in ids {

View file

@ -653,34 +653,6 @@ public enum TelegramMediaFileAttribute: PostboxCoding, Equatable {
}
}
public enum TelegramMediaFileReference: PostboxCoding, Equatable {
case cloud(fileId: Int64, accessHash: Int64, fileReference: Data?)
public init(decoder: PostboxDecoder) {
switch decoder.decodeInt32ForKey("_v", orElse: 0) {
case 0:
self = .cloud(fileId: decoder.decodeInt64ForKey("i", orElse: 0), accessHash: decoder.decodeInt64ForKey("h", orElse: 0), fileReference: decoder.decodeBytesForKey("fr")?.makeData())
default:
self = .cloud(fileId: 0, accessHash: 0, fileReference: nil)
assertionFailure()
}
}
public func encode(_ encoder: PostboxEncoder) {
switch self {
case let .cloud(imageId, accessHash, fileReference):
encoder.encodeInt32(0, forKey: "_v")
encoder.encodeInt64(imageId, forKey: "i")
encoder.encodeInt64(accessHash, forKey: "h")
if let fileReference = fileReference {
encoder.encodeBytes(MemoryBuffer(data: fileReference), forKey: "fr")
} else {
encoder.encodeNil(forKey: "fr")
}
}
}
}
public enum TelegramMediaFileDecodingError: Error {
case generic
}

View file

@ -1,12 +1,6 @@
import Foundation
import Postbox
public enum VoiceCallP2PMode: Int32 {
case never = 0
case contacts = 1
case always = 2
}
public struct VoipConfiguration: Codable, Equatable {
public var serializedData: String?

View file

@ -15,6 +15,10 @@ public extension TelegramEngine {
return _internal_acceptTermsOfService(account: self.account, id: id)
}
public func addAppLogEvent(time: Double = Date().timeIntervalSince1970, type: String, data: JSON = .dictionary([:])) {
_internal_addAppLogEvent(postbox: self.account.postbox, time: time, type: type, peerId: nil, data: data)
}
public func requestChangeAccountPhoneNumberVerification(apiId: Int32, apiHash: String, phoneNumber: String, pushNotificationConfiguration: AuthorizationCodePushNotificationConfiguration?, firebaseSecretStream: Signal<[String: String], NoError>) -> Signal<ChangeAccountPhoneNumberData, RequestChangeAccountPhoneNumberVerificationError> {
return _internal_requestChangeAccountPhoneNumberVerification(account: self.account, apiId: apiId, apiHash: apiHash, phoneNumber: phoneNumber, pushNotificationConfiguration: pushNotificationConfiguration, firebaseSecretStream: firebaseSecretStream)
}

View file

@ -337,13 +337,6 @@ func _internal_requestTwoStepVerificationPasswordRecoveryCode(network: Network)
}
}
public enum RecoverTwoStepVerificationPasswordError {
case generic
case codeExpired
case limitExceeded
case invalidCode
}
func _internal_cachedTwoStepPasswordToken(postbox: Postbox) -> Signal<TemporaryTwoStepPasswordToken?, NoError> {
return postbox.transaction { transaction -> TemporaryTwoStepPasswordToken? in
let key = ValueBoxKey(length: 1)

View file

@ -3415,10 +3415,6 @@ func _internal_revokeConferenceInviteLink(account: Account, reference: InternalG
}
}
public enum ConfirmAddConferenceParticipantError {
case generic
}
func _internal_pollConferenceCallBlockchain(network: Network, reference: InternalGroupCallReference, subChainId: Int, offset: Int, limit: Int) -> Signal<(blocks: [Data], nextOffset: Int)?, NoError> {
return network.request(Api.functions.phone.getGroupCallChainBlocks(call: reference.apiInputGroupCall, subChainId: Int32(subChainId), offset: Int32(offset), limit: Int32(limit)))
|> map(Optional.init)

View file

@ -202,10 +202,6 @@ func _internal_sendAppStoreReceipt(postbox: Postbox, network: Network, stateMana
}
}
public enum RestoreAppStoreReceiptError {
case generic
}
func _internal_canPurchasePremium(postbox: Postbox, network: Network, purpose: AppStoreTransactionPurpose) -> Signal<Bool, NoError> {
return apiInputStorePaymentPurpose(postbox: postbox, purpose: purpose)
|> mapToSignal { purpose -> Signal<Bool, NoError> in

View file

@ -4,18 +4,6 @@ import SwiftSignalKit
import TelegramApi
public struct ChatListFilteringConfiguration: Equatable {
public let isEnabled: Bool
public init(appConfiguration: AppConfiguration) {
var isEnabled = false
if let data = appConfiguration.data, let value = data["dialog_filters_enabled"] as? Bool, value {
isEnabled = true
}
self.isEnabled = isEnabled
}
}
public struct ChatListFilterPeerCategories: OptionSet, Hashable {
public var rawValue: Int32

View file

@ -3,17 +3,6 @@ import Postbox
import TelegramApi
import SwiftSignalKit
public enum ResolvePeerByNameOptionCached {
case none
case cached
case cachedIfLaterThan(timestamp: Int32)
}
public enum ResolvePeerByNameOptionRemote {
case updateIfEarlierThan(timestamp: Int32)
case update
}
public enum ResolvePeerIdByNameResult {
case progress
case result(PeerId?)

View file

@ -276,44 +276,6 @@ public func deleteSecureIdValues(network: Network, keys: Set<SecureIdValueKey>)
}
}
public func dropSecureId(network: Network, currentPassword: String) -> Signal<Void, AuthorizationPasswordVerificationError> {
return _internal_twoStepAuthData(network)
|> mapError { _ -> AuthorizationPasswordVerificationError in
return .generic
}
|> mapToSignal { authData -> Signal<Void, AuthorizationPasswordVerificationError> in
let checkPassword: Api.InputCheckPasswordSRP
if let currentPasswordDerivation = authData.currentPasswordDerivation, let srpSessionData = authData.srpSessionData {
let kdfResult = passwordKDF(encryptionProvider: network.encryptionProvider, password: currentPassword, derivation: currentPasswordDerivation, srpSessionData: srpSessionData)
if let kdfResult = kdfResult {
checkPassword = .inputCheckPasswordSRP(.init(srpId: kdfResult.id, A: Buffer(data: kdfResult.A), M1: Buffer(data: kdfResult.M1)))
} else {
return .fail(.generic)
}
} else {
checkPassword = .inputCheckPasswordEmpty
}
let settings = network.request(Api.functions.account.getPasswordSettings(password: checkPassword), automaticFloodWait: false)
|> mapError { error in
return AuthorizationPasswordVerificationError.generic
}
return settings
|> mapToSignal { value -> Signal<Void, AuthorizationPasswordVerificationError> in
switch value {
case .passwordSettings:
var flags: Int32 = 0
flags |= (1 << 2)
return network.request(Api.functions.account.updatePasswordSettings(password: .inputCheckPasswordEmpty, newSettings: .passwordInputSettings(.init(flags: flags, newAlgo: nil, newPasswordHash: nil, hint: nil, email: nil, newSecureSettings: nil))), automaticFloodWait: false)
|> map { _ in }
|> mapError { _ in
return AuthorizationPasswordVerificationError.generic
}
}
}
}
}
public enum GetAllSecureIdValuesError {
case generic

View file

@ -15,10 +15,6 @@ public struct SecureIdValueAccessContext: Equatable {
}
}
public func generateSecureIdValueEmptyAccessContext() -> SecureIdValueAccessContext? {
return SecureIdValueAccessContext(secret: Data(), id: 0)
}
public func generateSecureIdValueAccessContext() -> SecureIdValueAccessContext? {
guard let secret = generateSecureSecretData() else {
return nil

View file

@ -12,6 +12,14 @@ public extension TelegramEngine {
public func getChatThemes(accountManager: AccountManager<TelegramAccountManagerTypes>, forceUpdate: Bool = false, onlyCached: Bool = false) -> Signal<[TelegramTheme], NoError> {
return _internal_getChatThemes(accountManager: accountManager, network: self.account.network, forceUpdate: forceUpdate, onlyCached: onlyCached)
}
public func themes(accountManager: AccountManager<TelegramAccountManagerTypes>, forceUpdate: Bool = false) -> Signal<[TelegramTheme], NoError> {
return _internal_telegramThemes(postbox: self.account.postbox, network: self.account.network, accountManager: accountManager, forceUpdate: forceUpdate)
}
public func wallpapers(forceUpdate: Bool = false) -> Signal<[TelegramWallpaper], NoError> {
return _internal_telegramWallpapers(postbox: self.account.postbox, network: self.account.network, forceUpdate: forceUpdate)
}
public func setChatTheme(peerId: PeerId, chatTheme: ChatTheme?) -> Signal<Void, NoError> {
return _internal_setChatTheme(account: self.account, peerId: peerId, chatTheme: chatTheme)

View file

@ -4,6 +4,7 @@ public typealias EngineMemoryBuffer = MemoryBuffer
public typealias EnginePostboxDecoder = PostboxDecoder
public typealias EnginePostboxEncoder = PostboxEncoder
public typealias EngineAdaptedPostboxDecoder = AdaptedPostboxDecoder
public typealias EngineAdaptedPostboxEncoder = AdaptedPostboxEncoder
public typealias EngineItemCollectionId = ItemCollectionId
public typealias EngineStoryId = StoryId
public typealias EngineFetchResourceSourceType = FetchResourceSourceType
@ -18,6 +19,7 @@ public typealias EngineValueBoxEncryptionParameters = ValueBoxEncryptionParamete
public typealias EngineMessageAndThreadId = MessageAndThreadId
public typealias EnginePeerStoryStats = PeerStoryStats
public typealias EngineMessageHistoryAnchorIndex = MessageHistoryAnchorIndex
public typealias EngineMessageHistoryEntryLocation = MessageHistoryEntryLocation
public typealias EngineChatListTotalUnreadStateCategory = ChatListTotalUnreadStateCategory
public typealias EngineChatListTotalUnreadStateStats = ChatListTotalUnreadStateStats
public typealias EngineChatListTotalUnreadState = ChatListTotalUnreadState
@ -28,8 +30,28 @@ public typealias EngineCachedMediaResourceRepresentationResult = CachedMediaReso
public typealias EngineMediaResourceDataFetchResult = MediaResourceDataFetchResult
public typealias EngineMediaResourceDataFetchError = MediaResourceDataFetchError
public typealias EngineMediaResourceStatus = MediaResourceStatus
public typealias EnginePostboxCoding = PostboxCoding
public typealias EngineRawItemCollectionInfo = ItemCollectionInfo
public typealias EngineRawItemCollectionItem = ItemCollectionItem
public typealias EngineRawMedia = Media
public typealias EngineRawMessage = Message
public typealias EngineRawPeer = Peer
public typealias EngineRawMediaResource = MediaResource
public typealias EngineRawMediaResourceId = MediaResourceId
public typealias EngineRawMediaResourceData = MediaResourceData
public typealias EngineRawMediaResourceDataFetchCopyLocalItem = MediaResourceDataFetchCopyLocalItem
public typealias EngineRawCachedMediaResourceRepresentation = CachedMediaResourceRepresentation
public typealias EngineCachedMediaRepresentationKeepDuration = CachedMediaRepresentationKeepDuration
public typealias EngineCachedPeerData = CachedPeerData
public func engineFileSize(_ path: String, useTotalFileAllocatedSize: Bool = false) -> Int64? {
return fileSize(path, useTotalFileAllocatedSize: useTotalFileAllocatedSize)
}
public func enginePersistentHash32(_ string: String) -> Int32 {
return persistentHash32(string)
}
public func engineDeclareEncodable(_ type: Any.Type, f: @escaping (EnginePostboxDecoder) -> EnginePostboxCoding) {
declareEncodable(type, f: f)
}

View file

@ -11,7 +11,7 @@ let telegramThemeFormat = "ios"
let telegramThemeFileExtension = "tgios-theme"
#endif
public func telegramThemes(postbox: Postbox, network: Network, accountManager: AccountManager<TelegramAccountManagerTypes>?, forceUpdate: Bool = false) -> Signal<[TelegramTheme], NoError> {
func _internal_telegramThemes(postbox: Postbox, network: Network, accountManager: AccountManager<TelegramAccountManagerTypes>?, forceUpdate: Bool = false) -> Signal<[TelegramTheme], NoError> {
let fetch: ([TelegramTheme]?, Int64?) -> Signal<[TelegramTheme], NoError> = { current, hash in
network.request(Api.functions.account.getThemes(format: telegramThemeFormat, hash: hash ?? 0))
|> retryRequest
@ -145,7 +145,7 @@ private func saveUnsaveTheme(account: Account, accountManager: AccountManager<Te
return .complete()
}
|> mapToSignal { _ -> Signal<Void, NoError> in
return telegramThemes(postbox: account.postbox, network: account.network, accountManager: accountManager, forceUpdate: true)
return _internal_telegramThemes(postbox: account.postbox, network: account.network, accountManager: accountManager, forceUpdate: true)
|> take(1)
|> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
@ -542,7 +542,7 @@ func managedThemesUpdates(accountManager: AccountManager<TelegramAccountManagerT
}
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
} else {
let _ = (telegramThemes(postbox: postbox, network: network, accountManager: accountManager, forceUpdate: true)
let _ = (_internal_telegramThemes(postbox: postbox, network: network, accountManager: accountManager, forceUpdate: true)
|> take(1)).start()
}
}.start()

Some files were not shown because too many files have changed in this diff Show more