mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 13:38:21 +00:00
Merge commit 'e53ef3c9f55b4b9721ffdef663223851e133589b'
This commit is contained in:
commit
dc2551e660
@ -311,14 +311,22 @@ func autodownloadMediaConnectionTypeController(context: AccountContext, connecti
|
||||
pushControllerImpl?(controller)
|
||||
})
|
||||
|
||||
let signal = combineLatest(context.sharedContext.presentationData, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings]))
|
||||
let signal = combineLatest(context.sharedContext.presentationData, context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings]))
|
||||
|> deliverOnMainQueue
|
||||
|> map { presentationData, sharedData -> (ItemListControllerState, (ItemListNodeState<AutodownloadMediaCategoryEntry>, AutodownloadMediaCategoryEntry.ItemGenerationArguments)) in
|
||||
let settings: MediaAutoDownloadSettings
|
||||
var automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
||||
if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings] as? MediaAutoDownloadSettings {
|
||||
settings = value
|
||||
automaticMediaDownloadSettings = value
|
||||
} else {
|
||||
settings = MediaAutoDownloadSettings.defaultSettings
|
||||
automaticMediaDownloadSettings = MediaAutoDownloadSettings.defaultSettings
|
||||
}
|
||||
|
||||
var autodownloadSettings: AutodownloadSettings
|
||||
if let value = sharedData.entries[SharedDataKeys.autodownloadSettings] as? AutodownloadSettings {
|
||||
autodownloadSettings = value
|
||||
automaticMediaDownloadSettings = automaticMediaDownloadSettings.updatedWithAutodownloadSettings(autodownloadSettings)
|
||||
} else {
|
||||
autodownloadSettings = .defaultSettings
|
||||
}
|
||||
|
||||
let title: String
|
||||
@ -330,7 +338,7 @@ func autodownloadMediaConnectionTypeController(context: AccountContext, connecti
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: autodownloadMediaConnectionTypeControllerEntries(presentationData: presentationData, connectionType: connectionType, settings: settings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: autodownloadMediaConnectionTypeControllerEntries(presentationData: presentationData, connectionType: connectionType, settings: automaticMediaDownloadSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
||||
@ -392,15 +392,23 @@ func autodownloadMediaCategoryController(context: AccountContext, connectionType
|
||||
let initialValuePromise: Promise<MediaAutoDownloadSettings> = Promise()
|
||||
initialValuePromise.set(currentAutodownloadSettings())
|
||||
|
||||
let signal = combineLatest(context.sharedContext.presentationData, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings])) |> deliverOnMainQueue
|
||||
let signal = combineLatest(context.sharedContext.presentationData, context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings])) |> deliverOnMainQueue
|
||||
|> map { presentationData, sharedData -> (ItemListControllerState, (ItemListNodeState<AutodownloadMediaCategoryEntry>, AutodownloadMediaCategoryEntry.ItemGenerationArguments)) in
|
||||
let automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
||||
var automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
||||
if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings] as? MediaAutoDownloadSettings {
|
||||
automaticMediaDownloadSettings = value
|
||||
} else {
|
||||
automaticMediaDownloadSettings = .defaultSettings
|
||||
}
|
||||
|
||||
var autodownloadSettings: AutodownloadSettings
|
||||
if let value = sharedData.entries[SharedDataKeys.autodownloadSettings] as? AutodownloadSettings {
|
||||
autodownloadSettings = value
|
||||
automaticMediaDownloadSettings = automaticMediaDownloadSettings.updatedWithAutodownloadSettings(autodownloadSettings)
|
||||
} else {
|
||||
autodownloadSettings = .defaultSettings
|
||||
}
|
||||
|
||||
let title: String
|
||||
switch category {
|
||||
case .photo:
|
||||
|
||||
@ -5487,6 +5487,10 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
|
||||
}
|
||||
|
||||
func previewingController(from sourceView: UIView, for location: CGPoint) -> (UIViewController, CGRect)? {
|
||||
guard let view = self.chatDisplayNode.view.hitTest(location, with: nil), view.isDescendant(of: self.chatDisplayNode.historyNode.view) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let historyPoint = sourceView.convert(location, to: self.chatDisplayNode.historyNode.view)
|
||||
var result: (Message, ChatMessagePeekPreviewContent)?
|
||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
|
||||
@ -34,7 +34,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
|
||||
private var item: ChatMessageBubbleContentItem?
|
||||
private var automaticDownload: Bool?
|
||||
var telegramFile: TelegramMediaFile?
|
||||
var media: TelegramMediaFile?
|
||||
private var secretProgressIcon: UIImage?
|
||||
|
||||
private let fetchDisposable = MetaDisposable()
|
||||
@ -112,7 +112,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ item: ChatMessageBubbleContentItem, _ width: CGFloat, _ displaySize: CGSize, _ statusType: ChatMessageInteractiveInstantVideoNodeStatusType, _ automaticDownload: Bool) -> (ChatMessageInstantVideoItemLayoutResult, (ChatMessageInstantVideoItemLayoutData, ContainedViewLayoutTransition) -> Void) {
|
||||
let previousFile = self.telegramFile
|
||||
let previousFile = self.media
|
||||
|
||||
let currentItem = self.item
|
||||
let previousAutomaticDownload = self.automaticDownload
|
||||
@ -283,7 +283,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
strongSelf.secretVideoPlaceholderBackground.image = secretVideoPlaceholderBackgroundImage
|
||||
}
|
||||
|
||||
strongSelf.telegramFile = updatedFile
|
||||
strongSelf.media = updatedFile
|
||||
|
||||
if let infoBackgroundImage = strongSelf.infoBackgroundNode.image, let muteImage = strongSelf.muteIconNode.image {
|
||||
let infoWidth = muteImage.size.width
|
||||
@ -603,10 +603,16 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
if self.infoBackgroundNode.alpha.isZero {
|
||||
item.context.sharedContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: .voice)
|
||||
if let status = self.status, case let .fetchStatus(fetchStatus) = status, case .Remote = fetchStatus {
|
||||
item.context.sharedContext.mediaManager.playlistControl(.playback(.pause), type: .voice)
|
||||
self.videoNode?.fetchControl(.fetch)
|
||||
} else {
|
||||
item.context.sharedContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: .voice)
|
||||
}
|
||||
} else {
|
||||
let _ = item.controllerInteraction.openMessage(item.message, .default)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
@ -623,7 +629,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
private func progressPressed() {
|
||||
guard let item = self.item, let file = self.telegramFile else {
|
||||
guard let item = self.item, let file = self.media else {
|
||||
return
|
||||
}
|
||||
if let status = self.status {
|
||||
|
||||
@ -444,7 +444,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
if let currentFile = currentMedia as? TelegramMediaFile, currentFile.resource is EmptyMediaResource {
|
||||
replaceVideoNode = true
|
||||
}
|
||||
} else {
|
||||
} else if !(file.resource is LocalFileVideoMediaResource) {
|
||||
replaceVideoNode = true
|
||||
}
|
||||
} else {
|
||||
@ -592,7 +592,11 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
let streamVideo = !updatedVideoFile.isAnimated && isMediaStreamable(message: message, media: updatedVideoFile)
|
||||
let videoNode = UniversalVideoNode(postbox: context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: decoration, content: NativeVideoContent(id: .message(message.id, message.stableId, updatedVideoFile.fileId), fileReference: .message(message: MessageReference(message), media: updatedVideoFile), streamVideo: streamVideo, enableSound: false, fetchAutomatically: false, onlyFullSizeThumbnail: (onlyFullSizeVideoThumbnail ?? false), continuePlayingWithoutSoundOnLostAudioSession: isInlinePlayableVideo, placeholderColor: emptyColor), priority: .embedded)
|
||||
videoNode.isUserInteractionEnabled = false
|
||||
|
||||
videoNode.ownsContentNodeUpdated = { [weak self] owns in
|
||||
if let strongSelf = self {
|
||||
strongSelf.videoNode?.isHidden = !owns
|
||||
}
|
||||
}
|
||||
strongSelf.videoNode = videoNode
|
||||
|
||||
updatedVideoNodeReadySignal = videoNode.ready
|
||||
|
||||
@ -313,12 +313,14 @@ private struct DataAndStorageControllerState: Equatable {
|
||||
|
||||
private struct DataAndStorageData: Equatable {
|
||||
let automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
||||
let autodownloadSettings: AutodownloadSettings
|
||||
let generatedMediaStoreSettings: GeneratedMediaStoreSettings
|
||||
let voiceCallSettings: VoiceCallSettings
|
||||
let proxySettings: ProxySettings?
|
||||
|
||||
init(automaticMediaDownloadSettings: MediaAutoDownloadSettings, generatedMediaStoreSettings: GeneratedMediaStoreSettings, voiceCallSettings: VoiceCallSettings, proxySettings: ProxySettings?) {
|
||||
init(automaticMediaDownloadSettings: MediaAutoDownloadSettings, autodownloadSettings: AutodownloadSettings, generatedMediaStoreSettings: GeneratedMediaStoreSettings, voiceCallSettings: VoiceCallSettings, proxySettings: ProxySettings?) {
|
||||
self.automaticMediaDownloadSettings = automaticMediaDownloadSettings
|
||||
self.autodownloadSettings = autodownloadSettings
|
||||
self.generatedMediaStoreSettings = generatedMediaStoreSettings
|
||||
self.voiceCallSettings = voiceCallSettings
|
||||
self.proxySettings = proxySettings
|
||||
@ -329,14 +331,16 @@ private struct DataAndStorageData: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private func stringForUseLessDataSetting(strings: PresentationStrings, settings: VoiceCallSettings) -> String {
|
||||
switch settings.dataSaving {
|
||||
private func stringForUseLessDataSetting(_ dataSaving: VoiceCallDataSaving, strings: PresentationStrings) -> String {
|
||||
switch dataSaving {
|
||||
case .never:
|
||||
return strings.CallSettings_Never
|
||||
case .cellular:
|
||||
return strings.CallSettings_OnMobile
|
||||
case .always:
|
||||
return strings.CallSettings_Always
|
||||
case .default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,7 +409,8 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat
|
||||
entries.append(.autoplayVideos(presentationData.theme, presentationData.strings.ChatSettings_AutoPlayVideos, data.automaticMediaDownloadSettings.autoplayVideos))
|
||||
|
||||
entries.append(.voiceCallsHeader(presentationData.theme, presentationData.strings.Settings_CallSettings.uppercased()))
|
||||
entries.append(.useLessVoiceData(presentationData.theme, presentationData.strings.CallSettings_UseLessData, stringForUseLessDataSetting(strings: presentationData.strings, settings: data.voiceCallSettings)))
|
||||
let dataSaving = effectiveDataSaving(for: data.voiceCallSettings, autodownloadSettings: data.autodownloadSettings)
|
||||
entries.append(.useLessVoiceData(presentationData.theme, presentationData.strings.CallSettings_UseLessData, stringForUseLessDataSetting(dataSaving, strings: presentationData.strings)))
|
||||
|
||||
entries.append(.otherHeader(presentationData.theme, presentationData.strings.ChatSettings_Other))
|
||||
entries.append(.saveIncomingPhotos(presentationData.theme, presentationData.strings.Settings_SaveIncomingPhotos))
|
||||
@ -449,8 +454,12 @@ func dataAndStorageController(context: AccountContext) -> ViewController {
|
||||
automaticMediaDownloadSettings = .defaultSettings
|
||||
}
|
||||
|
||||
var autodownloadSettings: AutodownloadSettings
|
||||
if let value = sharedData.entries[SharedDataKeys.autodownloadSettings] as? AutodownloadSettings {
|
||||
automaticMediaDownloadSettings = automaticMediaDownloadSettings.updatedWithAutodownloadSettings(value)
|
||||
autodownloadSettings = value
|
||||
automaticMediaDownloadSettings = automaticMediaDownloadSettings.updatedWithAutodownloadSettings(autodownloadSettings)
|
||||
} else {
|
||||
autodownloadSettings = .defaultSettings
|
||||
}
|
||||
|
||||
let generatedMediaStoreSettings: GeneratedMediaStoreSettings
|
||||
@ -472,7 +481,7 @@ func dataAndStorageController(context: AccountContext) -> ViewController {
|
||||
proxySettings = value
|
||||
}
|
||||
|
||||
return DataAndStorageData(automaticMediaDownloadSettings: automaticMediaDownloadSettings, generatedMediaStoreSettings: generatedMediaStoreSettings, voiceCallSettings: voiceCallSettings, proxySettings: proxySettings)
|
||||
return DataAndStorageData(automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, generatedMediaStoreSettings: generatedMediaStoreSettings, voiceCallSettings: voiceCallSettings, proxySettings: proxySettings)
|
||||
})
|
||||
|
||||
let arguments = DataAndStorageControllerArguments(openStorageUsage: {
|
||||
|
||||
@ -51,8 +51,8 @@ class VideoConversionWatcher: TGMediaVideoFileWatcher {
|
||||
}
|
||||
|
||||
struct VideoConversionConfiguration {
|
||||
public static var defaultValue: VideoConversionConfiguration {
|
||||
return VideoConversionConfiguration(remuxToFMp4: true)
|
||||
static var defaultValue: VideoConversionConfiguration {
|
||||
return VideoConversionConfiguration(remuxToFMp4: false)
|
||||
}
|
||||
|
||||
public let remuxToFMp4: Bool
|
||||
|
||||
@ -16,14 +16,6 @@ const uint8_t ID3v3Artwork[4] = {0x41, 0x50, 0x49, 0x43};
|
||||
const uint8_t JPGMagic[3] = {0xff, 0xd8, 0xff};
|
||||
const uint8_t PNGMagic[4] = {0x89, 0x50, 0x4e, 0x47};
|
||||
|
||||
uint32_t getSize(const uint8_t *bytes) {
|
||||
uint32_t size = CFSwapInt32HostToBig(*(const uint32_t *)(bytes + ID3SizeOffset));
|
||||
uint32_t b1 = (size & 0x7F000000) >> 3;
|
||||
uint32_t b2 = (size & 0x007F0000) >> 2;
|
||||
uint32_t b3 = (size & 0x00007F00) >> 1;
|
||||
uint32_t b4 = size & 0x0000007F;
|
||||
return b1 + b2 + b3 + b4;
|
||||
}
|
||||
|
||||
uint32_t frameOffsetForVersion(uint8_t version) {
|
||||
return version == 2 ? ID3v2FrameOffset : ID3v3FrameOffset;
|
||||
|
||||
@ -112,10 +112,10 @@ final class InstantVideoRadialStatusNode: ASDisplayNode {
|
||||
if let (timestamp, duration, baseRate) = timestampAndDuration, let statusValue = self.statusValue {
|
||||
let progress = CGFloat(timestamp / duration)
|
||||
|
||||
if progress.isNaN || !progress.isFinite || statusValue.generationTimestamp.isZero {
|
||||
if progress.isNaN || !progress.isFinite {
|
||||
self.pop_removeAnimation(forKey: "progress")
|
||||
self.effectiveProgress = 0.0
|
||||
} else if statusValue.status != .playing {
|
||||
} else if statusValue.status != .playing || statusValue.generationTimestamp.isZero {
|
||||
self.pop_removeAnimation(forKey: "progress")
|
||||
self.effectiveProgress = progress
|
||||
} else {
|
||||
@ -130,14 +130,11 @@ final class InstantVideoRadialStatusNode: ASDisplayNode {
|
||||
(node as! InstantVideoRadialStatusNode).effectiveProgress = values!.pointee
|
||||
}
|
||||
property?.threshold = 0.01
|
||||
}) as! POPAnimatableProperty
|
||||
}) as? POPAnimatableProperty
|
||||
animation.fromValue = progress as NSNumber
|
||||
animation.toValue = 1.0 as NSNumber
|
||||
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
|
||||
animation.duration = max(0.0, duration - timestamp) / baseRate
|
||||
animation.completionBlock = { [weak self] _, _ in
|
||||
|
||||
}
|
||||
animation.beginTime = statusValue.generationTimestamp
|
||||
self.pop_add(animation, forKey: "progress")
|
||||
}
|
||||
|
||||
@ -95,8 +95,8 @@ public struct MediaAutoDownloadCategories: PostboxCoding, Equatable, Comparable
|
||||
}
|
||||
|
||||
public static func < (lhs: MediaAutoDownloadCategories, rhs: MediaAutoDownloadCategories) -> Bool {
|
||||
let lhsSizeLimit = (isAutodownloadEnabledForAnyPeerType(category: lhs.video) ? lhs.video.sizeLimit : 0) + (isAutodownloadEnabledForAnyPeerType(category: lhs.file) ? lhs.file.sizeLimit : 0)
|
||||
let rhsSizeLimit = (isAutodownloadEnabledForAnyPeerType(category: rhs.video) ? rhs.video.sizeLimit : 0) + (isAutodownloadEnabledForAnyPeerType(category: rhs.file) ? rhs.file.sizeLimit : 0)
|
||||
let lhsSizeLimit: Int64 = Int64((isAutodownloadEnabledForAnyPeerType(category: lhs.video) ? lhs.video.sizeLimit : 0)) + Int64((isAutodownloadEnabledForAnyPeerType(category: lhs.file) ? lhs.file.sizeLimit : 0))
|
||||
let rhsSizeLimit: Int64 = Int64((isAutodownloadEnabledForAnyPeerType(category: rhs.video) ? rhs.video.sizeLimit : 0)) + Int64((isAutodownloadEnabledForAnyPeerType(category: rhs.file) ? rhs.file.sizeLimit : 0))
|
||||
return lhsSizeLimit < rhsSizeLimit
|
||||
}
|
||||
}
|
||||
@ -228,7 +228,7 @@ public struct MediaAutoDownloadSettings: PreferencesEntry, Equatable {
|
||||
func updatedWithAutodownloadSettings(_ autodownloadSettings: AutodownloadSettings) -> MediaAutoDownloadSettings {
|
||||
var settings = self
|
||||
settings.presets = presetsWithAutodownloadSettings(autodownloadSettings)
|
||||
return self
|
||||
return settings
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -124,6 +124,8 @@ private func ongoingDataSavingForType(_ type: VoiceCallDataSaving) -> OngoingCal
|
||||
return .cellular
|
||||
case .always:
|
||||
return .always
|
||||
default:
|
||||
return .never
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -33,10 +33,13 @@ public enum RequestCallResult {
|
||||
|
||||
public final class PresentationCallManager {
|
||||
private let getDeviceAccessData: () -> (presentationData: PresentationData, present: (ViewController, Any?) -> Void, openSettings: () -> Void)
|
||||
|
||||
private let accountManager: AccountManager
|
||||
private let audioSession: ManagedAudioSession
|
||||
private let callKitIntegration: CallKitIntegration?
|
||||
|
||||
private var currentCall: PresentationCall?
|
||||
private var currentCallDisposable = MetaDisposable()
|
||||
private let removeCurrentCallDisposable = MetaDisposable()
|
||||
|
||||
private var ringingStatesDisposable: Disposable?
|
||||
@ -56,7 +59,7 @@ public final class PresentationCallManager {
|
||||
private var proxyServer: ProxyServerSettings?
|
||||
private var proxyServerDisposable: Disposable?
|
||||
|
||||
private var callSettings: (VoiceCallSettings, VoipConfiguration, VoipDerivedState)?
|
||||
private var callSettings: VoiceCallSettings?
|
||||
private var callSettingsDisposable: Disposable?
|
||||
|
||||
public static var voipMaxLayer: Int32 {
|
||||
@ -65,6 +68,7 @@ public final class PresentationCallManager {
|
||||
|
||||
public init(accountManager: AccountManager, getDeviceAccessData: @escaping () -> (presentationData: PresentationData, present: (ViewController, Any?) -> Void, openSettings: () -> Void), audioSession: ManagedAudioSession, activeAccounts: Signal<[Account], NoError>) {
|
||||
self.getDeviceAccessData = getDeviceAccessData
|
||||
self.accountManager = accountManager
|
||||
self.audioSession = audioSession
|
||||
|
||||
var startCallImpl: ((Account, UUID, String) -> Signal<Bool, NoError>)?
|
||||
@ -200,37 +204,16 @@ public final class PresentationCallManager {
|
||||
}
|
||||
})
|
||||
|
||||
self.callSettingsDisposable = (combineLatest(queue: .mainQueue(), accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.voiceCallSettings]), Signal<Void, NoError>.single(Void())/*, postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState])*/)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] sharedData, preferences in
|
||||
let callSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.voiceCallSettings] as? VoiceCallSettings ?? .defaultSettings
|
||||
let configuration: VoipConfiguration = .defaultValue// = preferences.values[PreferencesKeys.voipConfiguration] as? VoipConfiguration ?? .defaultValue
|
||||
let derivedState: VoipDerivedState = .default// = preferences.values[ApplicationSpecificPreferencesKeys.voipDerivedState] as? VoipDerivedState ?? .default
|
||||
self.callSettingsDisposable = (accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.voiceCallSettings])
|
||||
|> deliverOnMainQueue).start(next: { [weak self] sharedData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.callSettings = (callSettings, configuration, derivedState)
|
||||
|
||||
if let legacyP2PMode = callSettings.legacyP2PMode {
|
||||
_ = updateVoiceCallSettingsSettingsInteractively(accountManager: accountManager, { settings -> VoiceCallSettings in
|
||||
var settings = settings
|
||||
settings.legacyP2PMode = nil
|
||||
return settings
|
||||
}).start()
|
||||
|
||||
/*let settings: SelectivePrivacySettings
|
||||
switch legacyP2PMode {
|
||||
case .always:
|
||||
settings = .enableEveryone(disableFor: Set<PeerId>())
|
||||
case .contacts:
|
||||
settings = .enableContacts(enableFor: Set<PeerId>(), disableFor: Set<PeerId>())
|
||||
case .never:
|
||||
settings = .disableEveryone(enableFor: Set<PeerId>())
|
||||
}
|
||||
_ = updateSelectiveAccountPrivacySettings(account: strongSelf.tempAccount, type: .voiceCallsP2P, settings: settings).start()*/
|
||||
}
|
||||
strongSelf.callSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.voiceCallSettings] as? VoiceCallSettings ?? .defaultSettings
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.currentCallDisposable.dispose()
|
||||
self.ringingStatesDisposable?.dispose()
|
||||
self.removeCurrentCallDisposable.dispose()
|
||||
self.startCallDisposable.dispose()
|
||||
@ -241,19 +224,30 @@ public final class PresentationCallManager {
|
||||
private func ringingStatesUpdated(_ ringingStates: [(Account, Peer, CallSessionRingingState, Bool, NetworkType)], enableCallKit: Bool) {
|
||||
if let firstState = ringingStates.first {
|
||||
if self.currentCall == nil {
|
||||
let call = PresentationCall(account: firstState.0, audioSession: self.audioSession, callSessionManager: firstState.0.callSessionManager, callKitIntegration: enableCallKit ? callKitIntegrationIfEnabled(self.callKitIntegration, settings: self.callSettings?.0) : nil, serializedData: self.callSettings?.1.serializedData, dataSaving: self.callSettings?.0.dataSaving ?? .never, derivedState: self.callSettings?.2 ?? VoipDerivedState.default, getDeviceAccessData: self.getDeviceAccessData, internalId: firstState.2.id, peerId: firstState.2.peerId, isOutgoing: false, peer: firstState.1, proxyServer: self.proxyServer, currentNetworkType: firstState.4, updatedNetworkType: firstState.0.networkType)
|
||||
self.currentCall = call
|
||||
self.currentCallPromise.set(.single(call))
|
||||
self.hasActiveCallsPromise.set(true)
|
||||
self.removeCurrentCallDisposable.set((call.canBeRemoved
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak call] value in
|
||||
if value, let strongSelf = self, let call = call {
|
||||
if strongSelf.currentCall === call {
|
||||
strongSelf.currentCall = nil
|
||||
strongSelf.currentCallPromise.set(.single(nil))
|
||||
strongSelf.hasActiveCallsPromise.set(false)
|
||||
}
|
||||
self.currentCallDisposable.set((combineLatest(firstState.0.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings]) |> take(1))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] preferences, sharedData in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
let configuration = preferences.values[PreferencesKeys.voipConfiguration] as? VoipConfiguration ?? .defaultValue
|
||||
let derivedState = preferences.values[ApplicationSpecificPreferencesKeys.voipDerivedState] as? VoipDerivedState ?? .default
|
||||
let autodownloadSettings = sharedData.entries[SharedDataKeys.autodownloadSettings] as? AutodownloadSettings ?? .defaultSettings
|
||||
|
||||
let call = PresentationCall(account: firstState.0, audioSession: strongSelf.audioSession, callSessionManager: firstState.0.callSessionManager, callKitIntegration: enableCallKit ? callKitIntegrationIfEnabled(strongSelf.callKitIntegration, settings: strongSelf.callSettings) : nil, serializedData: configuration.serializedData, dataSaving: effectiveDataSaving(for: strongSelf.callSettings, autodownloadSettings: autodownloadSettings), derivedState: derivedState, getDeviceAccessData: strongSelf.getDeviceAccessData, internalId: firstState.2.id, peerId: firstState.2.peerId, isOutgoing: false, peer: firstState.1, proxyServer: strongSelf.proxyServer, currentNetworkType: firstState.4, updatedNetworkType: firstState.0.networkType)
|
||||
strongSelf.currentCall = call
|
||||
strongSelf.currentCallPromise.set(.single(call))
|
||||
strongSelf.hasActiveCallsPromise.set(true)
|
||||
strongSelf.removeCurrentCallDisposable.set((call.canBeRemoved
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak call] value in
|
||||
if value, let strongSelf = self, let call = call {
|
||||
if strongSelf.currentCall === call {
|
||||
strongSelf.currentCall = nil
|
||||
strongSelf.currentCallPromise.set(.single(nil))
|
||||
strongSelf.hasActiveCallsPromise.set(false)
|
||||
}
|
||||
}
|
||||
}))
|
||||
}))
|
||||
} else {
|
||||
for (account, _, state, _, _) in ringingStates {
|
||||
@ -269,7 +263,7 @@ public final class PresentationCallManager {
|
||||
if let call = self.currentCall, !endCurrentIfAny {
|
||||
return .alreadyInProgress(call.peerId)
|
||||
}
|
||||
if let _ = callKitIntegrationIfEnabled(self.callKitIntegration, settings: self.callSettings?.0) {
|
||||
if let _ = callKitIntegrationIfEnabled(self.callKitIntegration, settings: self.callSettings) {
|
||||
let begin: () -> Void = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -350,22 +344,27 @@ public final class PresentationCallManager {
|
||||
|> runOn(Queue.mainQueue())
|
||||
|
||||
let networkType = account.networkType
|
||||
let accountManager = self.accountManager
|
||||
return accessEnabledSignal
|
||||
|> mapToSignal { [weak self] accessEnabled -> Signal<Bool, NoError> in
|
||||
if !accessEnabled {
|
||||
return .single(false)
|
||||
}
|
||||
return (combineLatest(queue: .mainQueue(), account.callSessionManager.request(peerId: peerId, internalId: internalId), networkType |> take(1), account.postbox.peerView(id: peerId) |> take(1) |> map({ peerView -> Bool in
|
||||
return (combineLatest(queue: .mainQueue(), account.callSessionManager.request(peerId: peerId, internalId: internalId), networkType |> take(1), account.postbox.peerView(id: peerId) |> map { peerView -> Bool in
|
||||
return peerView.peerIsContact
|
||||
}) |> take(1))
|
||||
} |> take(1), account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings]) |> take(1))
|
||||
|> deliverOnMainQueue
|
||||
|> beforeNext { internalId, currentNetworkType, isContact in
|
||||
|> beforeNext { internalId, currentNetworkType, isContact, preferences, sharedData in
|
||||
if let strongSelf = self, accessEnabled {
|
||||
if let currentCall = strongSelf.currentCall {
|
||||
currentCall.rejectBusy()
|
||||
}
|
||||
|
||||
let call = PresentationCall(account: account, audioSession: strongSelf.audioSession, callSessionManager: account.callSessionManager, callKitIntegration: callKitIntegrationIfEnabled(strongSelf.callKitIntegration, settings: strongSelf.callSettings?.0), serializedData: strongSelf.callSettings?.1.serializedData, dataSaving: strongSelf.callSettings?.0.dataSaving ?? .never, derivedState: strongSelf.callSettings?.2 ?? VoipDerivedState.default, getDeviceAccessData: strongSelf.getDeviceAccessData, internalId: internalId, peerId: peerId, isOutgoing: true, peer: nil, proxyServer: strongSelf.proxyServer, currentNetworkType: currentNetworkType, updatedNetworkType: account.networkType)
|
||||
let configuration = preferences.values[PreferencesKeys.voipConfiguration] as? VoipConfiguration ?? .defaultValue
|
||||
let derivedState = preferences.values[ApplicationSpecificPreferencesKeys.voipDerivedState] as? VoipDerivedState ?? .default
|
||||
let autodownloadSettings = sharedData.entries[SharedDataKeys.autodownloadSettings] as? AutodownloadSettings ?? .defaultSettings
|
||||
|
||||
let call = PresentationCall(account: account, audioSession: strongSelf.audioSession, callSessionManager: account.callSessionManager, callKitIntegration: callKitIntegrationIfEnabled(strongSelf.callKitIntegration, settings: strongSelf.callSettings), serializedData: configuration.serializedData, dataSaving: effectiveDataSaving(for: strongSelf.callSettings, autodownloadSettings: autodownloadSettings), derivedState: derivedState, getDeviceAccessData: strongSelf.getDeviceAccessData, internalId: internalId, peerId: peerId, isOutgoing: true, peer: nil, proxyServer: strongSelf.proxyServer, currentNetworkType: currentNetworkType, updatedNetworkType: account.networkType)
|
||||
strongSelf.currentCall = call
|
||||
strongSelf.currentCallPromise.set(.single(call))
|
||||
strongSelf.hasActiveCallsPromise.set(true)
|
||||
|
||||
@ -692,7 +692,7 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective
|
||||
return state.withUpdatedSaving(false)
|
||||
}
|
||||
if case .voiceCalls = kind, let dataSaving = state.callDataSaving, let callP2PSettings = callP2PSettings, let systemIntegrationEnabled = state.callIntegrationEnabled {
|
||||
updated(settings, (callP2PSettings, VoiceCallSettings(dataSaving: dataSaving, p2pMode: nil, enableSystemIntegration: systemIntegrationEnabled)))
|
||||
updated(settings, (callP2PSettings, VoiceCallSettings(dataSaving: dataSaving, enableSystemIntegration: systemIntegrationEnabled)))
|
||||
} else {
|
||||
updated(settings, nil)
|
||||
}
|
||||
|
||||
@ -571,10 +571,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
} else {
|
||||
videoNode.continuePlayingWithoutSound()
|
||||
}
|
||||
self.updateDisplayPlaceholder(!videoNode.ownsContentNode)
|
||||
} else if !item.fromPlayingVideo {
|
||||
videoNode.canAttachContent = isVisible
|
||||
self.updateDisplayPlaceholder(!videoNode.ownsContentNode)
|
||||
}
|
||||
self.updateDisplayPlaceholder(!videoNode.ownsContentNode)
|
||||
if self.shouldAutoplayOnCentrality() {
|
||||
self.hideStatusNodeUntilCentrality = true
|
||||
self.statusButtonNode.isHidden = true
|
||||
@ -593,6 +594,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
}
|
||||
if isAnimated {
|
||||
videoNode.seek(0.0)
|
||||
videoNode.play()
|
||||
} else {
|
||||
videoNode.playOnceWithSound(playAndRecord: false, actionAtEnd: .stop)
|
||||
}
|
||||
@ -765,7 +767,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
let fromTransform: CATransform3D
|
||||
let toTransform: CATransform3D
|
||||
|
||||
if let interactiveMediaNode = node.0 as? ChatMessageInteractiveMediaNode, interactiveMediaNode.automaticPlayback ?? false {
|
||||
if let interactiveMediaNode = node.0 as? ChatMessageInteractiveMediaNode, interactiveMediaNode.automaticPlayback ?? false, videoNode.hasAttachedContext {
|
||||
copyView.removeFromSuperview()
|
||||
surfaceCopyView.removeFromSuperview()
|
||||
|
||||
|
||||
@ -100,24 +100,23 @@ private func stringForDataSavingOption(_ option: VoiceCallDataSaving, strings: P
|
||||
return strings.CallSettings_OnMobile
|
||||
case .always:
|
||||
return strings.CallSettings_Always
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
private func voiceCallDataSavingControllerEntries(presentationData: PresentationData, settings: VoiceCallSettings) -> [VoiceCallDataSavingEntry] {
|
||||
private func voiceCallDataSavingControllerEntries(presentationData: PresentationData, dataSaving: VoiceCallDataSaving) -> [VoiceCallDataSavingEntry] {
|
||||
var entries: [VoiceCallDataSavingEntry] = []
|
||||
|
||||
entries.append(.never(presentationData.theme, stringForDataSavingOption(.never, strings: presentationData.strings), settings.dataSaving == .never))
|
||||
entries.append(.cellular(presentationData.theme, stringForDataSavingOption(.cellular, strings: presentationData.strings), settings.dataSaving == .cellular))
|
||||
entries.append(.always(presentationData.theme, stringForDataSavingOption(.always, strings: presentationData.strings), settings.dataSaving == .always))
|
||||
entries.append(.never(presentationData.theme, stringForDataSavingOption(.never, strings: presentationData.strings), dataSaving == .never))
|
||||
entries.append(.cellular(presentationData.theme, stringForDataSavingOption(.cellular, strings: presentationData.strings), dataSaving == .cellular))
|
||||
entries.append(.always(presentationData.theme, stringForDataSavingOption(.always, strings: presentationData.strings), dataSaving == .always))
|
||||
entries.append(.info(presentationData.theme, presentationData.strings.CallSettings_UseLessDataLongDescription))
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
func voiceCallDataSavingController(context: AccountContext) -> ViewController {
|
||||
let voiceCallSettingsPromise = Promise<VoiceCallSettings>()
|
||||
voiceCallSettingsPromise.set(context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.voiceCallSettings])
|
||||
|> map { sharedData -> VoiceCallSettings in
|
||||
let sharedSettings = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.voiceCallSettings])
|
||||
|> map { sharedData -> (VoiceCallSettings, AutodownloadSettings) in
|
||||
let voiceCallSettings: VoiceCallSettings
|
||||
if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.voiceCallSettings] as? VoiceCallSettings {
|
||||
voiceCallSettings = value
|
||||
@ -125,8 +124,15 @@ func voiceCallDataSavingController(context: AccountContext) -> ViewController {
|
||||
voiceCallSettings = VoiceCallSettings.defaultSettings
|
||||
}
|
||||
|
||||
return voiceCallSettings
|
||||
})
|
||||
let autodownloadSettings: AutodownloadSettings
|
||||
if let value = sharedData.entries[SharedDataKeys.autodownloadSettings] as? AutodownloadSettings {
|
||||
autodownloadSettings = value
|
||||
} else {
|
||||
autodownloadSettings = AutodownloadSettings.defaultSettings
|
||||
}
|
||||
|
||||
return (voiceCallSettings, autodownloadSettings)
|
||||
}
|
||||
|
||||
let arguments = VoiceCallDataSavingControllerArguments(updateSelection: { option in
|
||||
let _ = updateVoiceCallSettingsSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
|
||||
@ -136,11 +142,13 @@ func voiceCallDataSavingController(context: AccountContext) -> ViewController {
|
||||
}).start()
|
||||
})
|
||||
|
||||
let signal = combineLatest(context.sharedContext.presentationData, voiceCallSettingsPromise.get()) |> deliverOnMainQueue
|
||||
|> map { presentationData, data -> (ItemListControllerState, (ItemListNodeState<VoiceCallDataSavingEntry>, VoiceCallDataSavingEntry.ItemGenerationArguments)) in
|
||||
let signal = combineLatest(context.sharedContext.presentationData, sharedSettings) |> deliverOnMainQueue
|
||||
|> map { presentationData, sharedSettings -> (ItemListControllerState, (ItemListNodeState<VoiceCallDataSavingEntry>, VoiceCallDataSavingEntry.ItemGenerationArguments)) in
|
||||
|
||||
let dataSaving = effectiveDataSaving(for: sharedSettings.0, autodownloadSettings: sharedSettings.1)
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.CallSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: voiceCallDataSavingControllerEntries(presentationData: presentationData, settings: data), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: voiceCallDataSavingControllerEntries(presentationData: presentationData, dataSaving: dataSaving), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
||||
@ -3,44 +3,52 @@ import Postbox
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
|
||||
func effectiveDataSaving(for settings: VoiceCallSettings?, autodownloadSettings: AutodownloadSettings) -> VoiceCallDataSaving {
|
||||
if let settings = settings {
|
||||
if case .default = settings.dataSaving {
|
||||
switch (autodownloadSettings.mediumPreset.lessDataForPhoneCalls, autodownloadSettings.highPreset.lessDataForPhoneCalls) {
|
||||
case (true, true):
|
||||
return .always
|
||||
case (true, false):
|
||||
return .cellular
|
||||
default:
|
||||
return .never
|
||||
}
|
||||
} else {
|
||||
return settings.dataSaving
|
||||
}
|
||||
} else {
|
||||
return .never
|
||||
}
|
||||
}
|
||||
|
||||
public enum VoiceCallDataSaving: Int32 {
|
||||
case never
|
||||
case cellular
|
||||
case always
|
||||
case `default`
|
||||
}
|
||||
|
||||
public struct VoiceCallSettings: PreferencesEntry, Equatable {
|
||||
public var dataSaving: VoiceCallDataSaving
|
||||
public var legacyP2PMode: VoiceCallP2PMode?
|
||||
public var enableSystemIntegration: Bool
|
||||
|
||||
public static var defaultSettings: VoiceCallSettings {
|
||||
return VoiceCallSettings(dataSaving: .never, p2pMode: nil, enableSystemIntegration: true)
|
||||
return VoiceCallSettings(dataSaving: .default, enableSystemIntegration: true)
|
||||
}
|
||||
|
||||
init(dataSaving: VoiceCallDataSaving, p2pMode: VoiceCallP2PMode?, enableSystemIntegration: Bool) {
|
||||
init(dataSaving: VoiceCallDataSaving, enableSystemIntegration: Bool) {
|
||||
self.dataSaving = dataSaving
|
||||
self.legacyP2PMode = p2pMode
|
||||
self.enableSystemIntegration = enableSystemIntegration
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.dataSaving = VoiceCallDataSaving(rawValue: decoder.decodeInt32ForKey("ds", orElse: 0))!
|
||||
if let value = decoder.decodeOptionalInt32ForKey("p2pMode") {
|
||||
self.legacyP2PMode = VoiceCallP2PMode(rawValue: value)
|
||||
} else {
|
||||
self.legacyP2PMode = nil
|
||||
}
|
||||
self.enableSystemIntegration = decoder.decodeInt32ForKey("enableSystemIntegration", orElse: 1) != 0
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt32(self.dataSaving.rawValue, forKey: "ds")
|
||||
if let p2pMode = self.legacyP2PMode {
|
||||
encoder.encodeInt32(p2pMode.rawValue, forKey: "p2pMode")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "p2pMode")
|
||||
}
|
||||
encoder.encodeInt32(self.enableSystemIntegration ? 1 : 0, forKey: "enableSystemIntegration")
|
||||
}
|
||||
|
||||
@ -56,9 +64,6 @@ public struct VoiceCallSettings: PreferencesEntry, Equatable {
|
||||
if lhs.dataSaving != rhs.dataSaving {
|
||||
return false
|
||||
}
|
||||
if lhs.legacyP2PMode != rhs.legacyP2PMode {
|
||||
return false
|
||||
}
|
||||
if lhs.enableSystemIntegration != rhs.enableSystemIntegration {
|
||||
return false
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user