Merge branch 'master' of github.com:peter-iakovlev/TelegramUI

This commit is contained in:
Ilya Laktyushin 2018-09-23 14:46:54 +01:00
commit cb30aa60a8
14 changed files with 2419 additions and 2308 deletions

View File

@ -323,11 +323,13 @@ public func channelMembersController(account: Account, peerId: PeerId) -> ViewCo
let arguments = ChannelMembersControllerArguments(account: account, addMember: { let arguments = ChannelMembersControllerArguments(account: account, addMember: {
let presentationData = account.telegramApplicationContext.currentPresentationData.with {$0}
actionsDisposable.add((peersPromise.get() |> take(1) |> deliverOnMainQueue).start(next: { members in actionsDisposable.add((peersPromise.get() |> take(1) |> deliverOnMainQueue).start(next: { members in
let disabledIds = members?.compactMap({$0.peer.id}) ?? [] let disabledIds = members?.compactMap({$0.peer.id}) ?? []
let contactsController = ContactMultiselectionController(account: account, mode: .peerSelection, options: [], filters: [.excludeSelf, .disable(disabledIds)]) let contactsController = ContactMultiselectionController(account: account, mode: .peerSelection, options: [], filters: [.excludeSelf, .disable(disabledIds)])
let addMembers: ([ContactListPeerId]) -> Signal<Void, NoError> = { members -> Signal<Void, NoError> in let addMembers: ([ContactListPeerId]) -> Signal<Void, AddChannelMemberError> = { members -> Signal<Void, AddChannelMemberError> in
let peerIds = members.compactMap { contact -> PeerId? in let peerIds = members.compactMap { contact -> PeerId? in
switch contact { switch contact {
case let .peer(peerId): case let .peer(peerId):
@ -343,7 +345,9 @@ public func channelMembersController(account: Account, peerId: PeerId) -> ViewCo
|> deliverOnMainQueue |> mapToSignal { [weak contactsController] contacts in |> deliverOnMainQueue |> mapToSignal { [weak contactsController] contacts in
contactsController?.displayProgress = true contactsController?.displayProgress = true
return addMembers(contacts) |> mapToSignal { _ in return addMembers(contacts) |> `catch` { error -> Signal<Void, NoError> in
return .single(Void())
} |> mapToSignal { _ in
return channelMembers(postbox: account.postbox, network: account.network, peerId: peerId) return channelMembers(postbox: account.postbox, network: account.network, peerId: peerId)
} |> deliverOnMainQueue |> afterNext { _ in } |> deliverOnMainQueue |> afterNext { _ in
contactsController?.dismiss() contactsController?.dismiss()

View File

@ -4456,7 +4456,12 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
} }
if concealed, let parsedUrlValue = parsedUrlValue, (parsedUrlValue.scheme == "http" || parsedUrlValue.scheme == "https"), !isConcealedUrlWhitelisted(parsedUrlValue) { if concealed, let parsedUrlValue = parsedUrlValue, (parsedUrlValue.scheme == "http" || parsedUrlValue.scheme == "https"), !isConcealedUrlWhitelisted(parsedUrlValue) {
self.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: self.presentationData.theme), title: nil, text: self.presentationData.strings.Generic_OpenHiddenLinkAlert(url).0, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Yes, action: { var displayUrl = url
let maxLength = 180
if displayUrl.count > maxLength {
displayUrl = String(displayUrl[..<displayUrl.index(displayUrl.startIndex, offsetBy: maxLength - 2)]) + "..."
}
self.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: self.presentationData.theme), title: nil, text: self.presentationData.strings.Generic_OpenHiddenLinkAlert(displayUrl).0, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Yes, action: {
openImpl() openImpl()
})]), in: .window(.root)) })]), in: .window(.root))
} else { } else {

View File

@ -94,6 +94,10 @@ private let internalExtensions = Set<String>([
"cs" "cs"
]) ])
private let internalNotSupportedExtensions = Set<String>([
"djvu"
])
private let internalMimeTypes = Set<String>([ private let internalMimeTypes = Set<String>([
"application/pdf", "application/pdf",
"application/postscript", "application/postscript",
@ -101,7 +105,9 @@ private let internalMimeTypes = Set<String>([
]) ])
private let internalMimePrefixes: [String] = [ private let internalMimePrefixes: [String] = [
"image/", "image/jpeg",
"image/jpg",
"image/png",
"text/", "text/",
"application/vnd.ms-" "application/vnd.ms-"
] ]
@ -118,6 +124,9 @@ func internalDocumentItemSupportsMimeType(_ type: String, fileName: String?) ->
if internalExtensions.contains(ext.lowercased()) { if internalExtensions.contains(ext.lowercased()) {
return true return true
} }
if internalNotSupportedExtensions.contains(ext.lowercased()) {
return false
}
} }
if internalMimeTypes.contains(type) { if internalMimeTypes.contains(type) {

View File

@ -1462,7 +1462,7 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
} }
} }
let addMembers: ([ContactListPeerId]) -> Signal<Void, NoError> = { members -> Signal<Void, NoError> in let addMembers: ([ContactListPeerId]) -> Signal<Void, AddChannelMemberError> = { members -> Signal<Void, AddChannelMemberError> in
let memberIds = members.compactMap { contact -> PeerId? in let memberIds = members.compactMap { contact -> PeerId? in
switch contact { switch contact {
case let .peer(peerId): case let .peer(peerId):
@ -1474,29 +1474,31 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
return account.postbox.multiplePeersView(memberIds) return account.postbox.multiplePeersView(memberIds)
|> take(1) |> take(1)
|> deliverOnMainQueue |> deliverOnMainQueue
|> mapToSignal { view -> Signal<Void, NoError> in |> mapError { _ in return .generic}
updateState { state in |> mapToSignal { view -> Signal<Void, AddChannelMemberError> in
var state = state return account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.addMembers(account: account, peerId: peerId, memberIds: memberIds) |> map { _ in
for (memberId, peer) in view.peers { updateState { state in
var found = false var state = state
for participant in state.temporaryParticipants { for (memberId, peer) in view.peers {
if participant.peer.id == memberId { var found = false
found = true for participant in state.temporaryParticipants {
break if participant.peer.id == memberId {
found = true
break
}
}
if !found {
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
var temporaryParticipants = state.temporaryParticipants
temporaryParticipants.append(TemporaryParticipant(peer: peer, presence: view.presences[memberId], timestamp: timestamp))
state = state.withUpdatedTemporaryParticipants(temporaryParticipants)
} }
} }
if !found {
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) return state
var temporaryParticipants = state.temporaryParticipants
temporaryParticipants.append(TemporaryParticipant(peer: peer, presence: view.presences[memberId], timestamp: timestamp))
state = state.withUpdatedTemporaryParticipants(temporaryParticipants)
}
} }
return state
} }
return account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.addMembers(account: account, peerId: peerId, memberIds: memberIds)
} }
} }
@ -1531,7 +1533,21 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
contactsController?.displayProgress = true contactsController?.displayProgress = true
addMemberDisposable.set((addMembers(peers) addMemberDisposable.set((addMembers(peers)
|> deliverOnMainQueue).start(completed: { |> deliverOnMainQueue).start(error: { error in
if peers.count == 1, error == .restricted {
switch peers[0] {
case let .peer(peerId):
_ = (account.postbox.loadedPeerWithId(peerId) |> deliverOnMainQueue).start(next: { peer in
let alert = standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(peer.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})])
presentControllerImpl?(alert, nil)
})
default:
break
}
}
contactsController?.dismiss()
},completed: {
contactsController?.dismiss() contactsController?.dismiss()
})) }))
})) }))

View File

@ -12,16 +12,18 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable {
public var vibrate: Bool public var vibrate: Bool
public var displayPreviews: Bool public var displayPreviews: Bool
public var totalUnreadCountDisplayStyle: TotalUnreadCountDisplayStyle public var totalUnreadCountDisplayStyle: TotalUnreadCountDisplayStyle
public var displayNameOnLockscreen: Bool
public static var defaultSettings: InAppNotificationSettings { public static var defaultSettings: InAppNotificationSettings {
return InAppNotificationSettings(playSounds: true, vibrate: false, displayPreviews: true, totalUnreadCountDisplayStyle: .filtered) return InAppNotificationSettings(playSounds: true, vibrate: false, displayPreviews: true, totalUnreadCountDisplayStyle: .filtered, displayNameOnLockscreen: true)
} }
init(playSounds: Bool, vibrate: Bool, displayPreviews: Bool, totalUnreadCountDisplayStyle: TotalUnreadCountDisplayStyle) { init(playSounds: Bool, vibrate: Bool, displayPreviews: Bool, totalUnreadCountDisplayStyle: TotalUnreadCountDisplayStyle, displayNameOnLockscreen: Bool) {
self.playSounds = playSounds self.playSounds = playSounds
self.vibrate = vibrate self.vibrate = vibrate
self.displayPreviews = displayPreviews self.displayPreviews = displayPreviews
self.totalUnreadCountDisplayStyle = totalUnreadCountDisplayStyle self.totalUnreadCountDisplayStyle = totalUnreadCountDisplayStyle
self.displayNameOnLockscreen = displayNameOnLockscreen
} }
public init(decoder: PostboxDecoder) { public init(decoder: PostboxDecoder) {
@ -29,6 +31,7 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable {
self.vibrate = decoder.decodeInt32ForKey("v", orElse: 0) != 0 self.vibrate = decoder.decodeInt32ForKey("v", orElse: 0) != 0
self.displayPreviews = decoder.decodeInt32ForKey("p", orElse: 0) != 0 self.displayPreviews = decoder.decodeInt32ForKey("p", orElse: 0) != 0
self.totalUnreadCountDisplayStyle = TotalUnreadCountDisplayStyle(rawValue: decoder.decodeInt32ForKey("tds", orElse: 0)) ?? .filtered self.totalUnreadCountDisplayStyle = TotalUnreadCountDisplayStyle(rawValue: decoder.decodeInt32ForKey("tds", orElse: 0)) ?? .filtered
self.displayNameOnLockscreen = decoder.decodeInt32ForKey("displayNameOnLockscreen", orElse: 1) != 0
} }
public func encode(_ encoder: PostboxEncoder) { public func encode(_ encoder: PostboxEncoder) {
@ -36,22 +39,7 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable {
encoder.encodeInt32(self.vibrate ? 1 : 0, forKey: "v") encoder.encodeInt32(self.vibrate ? 1 : 0, forKey: "v")
encoder.encodeInt32(self.displayPreviews ? 1 : 0, forKey: "p") encoder.encodeInt32(self.displayPreviews ? 1 : 0, forKey: "p")
encoder.encodeInt32(self.totalUnreadCountDisplayStyle.rawValue, forKey: "tds") encoder.encodeInt32(self.totalUnreadCountDisplayStyle.rawValue, forKey: "tds")
} encoder.encodeInt32(self.displayNameOnLockscreen ? 1 : 0, forKey: "displayNameOnLockscreen")
func withUpdatedPlaySounds(_ playSounds: Bool) -> InAppNotificationSettings {
return InAppNotificationSettings(playSounds: playSounds, vibrate: self.vibrate, displayPreviews: self.displayPreviews, totalUnreadCountDisplayStyle: self.totalUnreadCountDisplayStyle)
}
func withUpdatedVibrate(_ vibrate: Bool) -> InAppNotificationSettings {
return InAppNotificationSettings(playSounds: self.playSounds, vibrate: vibrate, displayPreviews: self.displayPreviews, totalUnreadCountDisplayStyle: self.totalUnreadCountDisplayStyle)
}
func withUpdatedDisplayPreviews(_ displayPreviews: Bool) -> InAppNotificationSettings {
return InAppNotificationSettings(playSounds: self.playSounds, vibrate: self.vibrate, displayPreviews: displayPreviews, totalUnreadCountDisplayStyle: self.totalUnreadCountDisplayStyle)
}
func withUpdatedTotalUnreadCountDisplayStyle(_ totalUnreadCountDisplayStyle: TotalUnreadCountDisplayStyle) -> InAppNotificationSettings {
return InAppNotificationSettings(playSounds: self.playSounds, vibrate: self.vibrate, displayPreviews: self.displayPreviews, totalUnreadCountDisplayStyle: totalUnreadCountDisplayStyle)
} }
public func isEqual(to: PreferencesEntry) -> Bool { public func isEqual(to: PreferencesEntry) -> Bool {
@ -61,22 +49,6 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable {
return false return false
} }
} }
public static func ==(lhs: InAppNotificationSettings, rhs: InAppNotificationSettings) -> Bool {
if lhs.playSounds != rhs.playSounds {
return false
}
if lhs.vibrate != rhs.vibrate {
return false
}
if lhs.displayPreviews != rhs.displayPreviews {
return false
}
if lhs.totalUnreadCountDisplayStyle != rhs.totalUnreadCountDisplayStyle {
return false
}
return true
}
} }
func updateInAppNotificationSettingsInteractively(postbox: Postbox, _ f: @escaping (InAppNotificationSettings) -> InAppNotificationSettings) -> Signal<Void, NoError> { func updateInAppNotificationSettingsInteractively(postbox: Postbox, _ f: @escaping (InAppNotificationSettings) -> InAppNotificationSettings) -> Signal<Void, NoError> {

View File

@ -551,6 +551,8 @@ public final class ManagedAudioSession {
print("ManagedAudioSession setting active false") print("ManagedAudioSession setting active false")
do { do {
try AVAudioSession.sharedInstance().setActive(false, with: [.notifyOthersOnDeactivation]) try AVAudioSession.sharedInstance().setActive(false, with: [.notifyOthersOnDeactivation])
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
try AVAudioSession.sharedInstance().setPreferredInput(nil)
} catch let error { } catch let error {
print("ManagedAudioSession applyNone error \(error)") print("ManagedAudioSession applyNone error \(error)")
} }

View File

@ -21,11 +21,12 @@ private final class NotificationsAndSoundsArguments {
let updateInAppVibration: (Bool) -> Void let updateInAppVibration: (Bool) -> Void
let updateInAppPreviews: (Bool) -> Void let updateInAppPreviews: (Bool) -> Void
let updateDisplayNameOnLockscreen: (Bool) -> Void
let updateTotalUnreadCountStyle: (Bool) -> Void let updateTotalUnreadCountStyle: (Bool) -> Void
let resetNotifications: () -> Void let resetNotifications: () -> Void
init(account: Account, presentController: @escaping (ViewController, ViewControllerPresentationArguments) -> Void, soundSelectionDisposable: MetaDisposable, updateMessageAlerts: @escaping (Bool) -> Void, updateMessagePreviews: @escaping (Bool) -> Void, updateMessageSound: @escaping (PeerMessageSound) -> Void, updateGroupAlerts: @escaping (Bool) -> Void, updateGroupPreviews: @escaping (Bool) -> Void, updateGroupSound: @escaping (PeerMessageSound) -> Void, updateInAppSounds: @escaping (Bool) -> Void, updateInAppVibration: @escaping (Bool) -> Void, updateInAppPreviews: @escaping (Bool) -> Void, updateTotalUnreadCountStyle: @escaping (Bool) -> Void, resetNotifications: @escaping () -> Void) { init(account: Account, presentController: @escaping (ViewController, ViewControllerPresentationArguments) -> Void, soundSelectionDisposable: MetaDisposable, updateMessageAlerts: @escaping (Bool) -> Void, updateMessagePreviews: @escaping (Bool) -> Void, updateMessageSound: @escaping (PeerMessageSound) -> Void, updateGroupAlerts: @escaping (Bool) -> Void, updateGroupPreviews: @escaping (Bool) -> Void, updateGroupSound: @escaping (PeerMessageSound) -> Void, updateInAppSounds: @escaping (Bool) -> Void, updateInAppVibration: @escaping (Bool) -> Void, updateInAppPreviews: @escaping (Bool) -> Void, updateDisplayNameOnLockscreen: @escaping (Bool) -> Void, updateTotalUnreadCountStyle: @escaping (Bool) -> Void, resetNotifications: @escaping () -> Void) {
self.account = account self.account = account
self.presentController = presentController self.presentController = presentController
self.soundSelectionDisposable = soundSelectionDisposable self.soundSelectionDisposable = soundSelectionDisposable
@ -38,6 +39,7 @@ private final class NotificationsAndSoundsArguments {
self.updateInAppSounds = updateInAppSounds self.updateInAppSounds = updateInAppSounds
self.updateInAppVibration = updateInAppVibration self.updateInAppVibration = updateInAppVibration
self.updateInAppPreviews = updateInAppPreviews self.updateInAppPreviews = updateInAppPreviews
self.updateDisplayNameOnLockscreen = updateDisplayNameOnLockscreen
self.updateTotalUnreadCountStyle = updateTotalUnreadCountStyle self.updateTotalUnreadCountStyle = updateTotalUnreadCountStyle
self.resetNotifications = resetNotifications self.resetNotifications = resetNotifications
} }
@ -47,6 +49,7 @@ private enum NotificationsAndSoundsSection: Int32 {
case messages case messages
case groups case groups
case inApp case inApp
case displayNamesOnLockscreen
case unreadCountStyle case unreadCountStyle
case reset case reset
} }
@ -69,6 +72,8 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
case inAppVibrate(PresentationTheme, String, Bool) case inAppVibrate(PresentationTheme, String, Bool)
case inAppPreviews(PresentationTheme, String, Bool) case inAppPreviews(PresentationTheme, String, Bool)
case displayNamesOnLockscreen(PresentationTheme, String, Bool)
case displayNamesOnLockscreenInfo(PresentationTheme, String)
case unreadCountStyle(PresentationTheme, String, Bool) case unreadCountStyle(PresentationTheme, String, Bool)
case reset(PresentationTheme, String) case reset(PresentationTheme, String)
@ -82,6 +87,8 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
return NotificationsAndSoundsSection.groups.rawValue return NotificationsAndSoundsSection.groups.rawValue
case .inAppHeader, .inAppSounds, .inAppVibrate, .inAppPreviews: case .inAppHeader, .inAppSounds, .inAppVibrate, .inAppPreviews:
return NotificationsAndSoundsSection.inApp.rawValue return NotificationsAndSoundsSection.inApp.rawValue
case .displayNamesOnLockscreen, .displayNamesOnLockscreenInfo:
return NotificationsAndSoundsSection.displayNamesOnLockscreen.rawValue
case .unreadCountStyle: case .unreadCountStyle:
return NotificationsAndSoundsSection.unreadCountStyle.rawValue return NotificationsAndSoundsSection.unreadCountStyle.rawValue
case .reset, .resetNotice: case .reset, .resetNotice:
@ -119,12 +126,16 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
return 12 return 12
case .inAppPreviews: case .inAppPreviews:
return 13 return 13
case .unreadCountStyle: case .displayNamesOnLockscreen:
return 14 return 14
case .reset: case .displayNamesOnLockscreenInfo:
return 15 return 15
case .resetNotice: case .unreadCountStyle:
return 16 return 16
case .reset:
return 17
case .resetNotice:
return 18
} }
} }
@ -214,6 +225,18 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .displayNamesOnLockscreen(lhsTheme, lhsText, lhsValue):
if case let .displayNamesOnLockscreen(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .displayNamesOnLockscreenInfo(lhsTheme, lhsText):
if case let .displayNamesOnLockscreenInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .unreadCountStyle(lhsTheme, lhsText, lhsValue): case let .unreadCountStyle(lhsTheme, lhsText, lhsValue):
if case let .unreadCountStyle(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { if case let .unreadCountStyle(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true return true
@ -293,6 +316,12 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { updatedValue in return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { updatedValue in
arguments.updateInAppPreviews(updatedValue) arguments.updateInAppPreviews(updatedValue)
}) })
case let .displayNamesOnLockscreen(theme, text, value):
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { updatedValue in
arguments.updateDisplayNameOnLockscreen(updatedValue)
})
case let .displayNamesOnLockscreenInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
case let .unreadCountStyle(theme, text, value): case let .unreadCountStyle(theme, text, value):
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { updatedValue in return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { updatedValue in
arguments.updateTotalUnreadCountStyle(updatedValue) arguments.updateTotalUnreadCountStyle(updatedValue)
@ -335,7 +364,11 @@ private func notificationsAndSoundsEntries(globalSettings: GlobalNotificationSet
entries.append(.inAppVibrate(presentationData.theme, presentationData.strings.Notifications_InAppNotificationsVibrate, inAppSettings.vibrate)) entries.append(.inAppVibrate(presentationData.theme, presentationData.strings.Notifications_InAppNotificationsVibrate, inAppSettings.vibrate))
entries.append(.inAppPreviews(presentationData.theme, presentationData.strings.Notifications_InAppNotificationsPreview, inAppSettings.displayPreviews)) entries.append(.inAppPreviews(presentationData.theme, presentationData.strings.Notifications_InAppNotificationsPreview, inAppSettings.displayPreviews))
entries.append(.unreadCountStyle(presentationData.theme, "Include muted chats", inAppSettings.totalUnreadCountDisplayStyle == .raw)) entries.append(.displayNamesOnLockscreen(presentationData.theme, presentationData.strings.Notifications_DisplayNamesOnLockScreen, inAppSettings.displayNameOnLockscreen))
entries.append(.displayNamesOnLockscreenInfo(presentationData.theme, presentationData.strings.Notifications_DisplayNamesOnLockScreenInfo))
if !GlobalExperimentalSettings.isAppStoreBuild {
entries.append(.unreadCountStyle(presentationData.theme, "Include muted chats", inAppSettings.totalUnreadCountDisplayStyle == .raw))
}
entries.append(.reset(presentationData.theme, presentationData.strings.Notifications_ResetAllNotifications)) entries.append(.reset(presentationData.theme, presentationData.strings.Notifications_ResetAllNotifications))
entries.append(.resetNotice(presentationData.theme, presentationData.strings.Notifications_ResetAllNotificationsHelp)) entries.append(.resetNotice(presentationData.theme, presentationData.strings.Notifications_ResetAllNotificationsHelp))
@ -386,19 +419,33 @@ public func notificationsAndSoundsController(account: Account) -> ViewController
}).start() }).start()
}, updateInAppSounds: { value in }, updateInAppSounds: { value in
let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in
return settings.withUpdatedPlaySounds(value) var settings = settings
settings.playSounds = value
return settings
}).start() }).start()
}, updateInAppVibration: { value in }, updateInAppVibration: { value in
let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in
return settings.withUpdatedVibrate(value) var settings = settings
settings.vibrate = value
return settings
}).start() }).start()
}, updateInAppPreviews: { value in }, updateInAppPreviews: { value in
let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in
return settings.withUpdatedDisplayPreviews(value) var settings = settings
settings.displayPreviews = value
return settings
}).start()
}, updateDisplayNameOnLockscreen: { value in
let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in
var settings = settings
settings.displayNameOnLockscreen = value
return settings
}).start() }).start()
}, updateTotalUnreadCountStyle: { value in }, updateTotalUnreadCountStyle: { value in
let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in
return settings.withUpdatedTotalUnreadCountDisplayStyle(value ? .raw : .filtered) var settings = settings
settings.totalUnreadCountDisplayStyle = value ? .raw : .filtered
return settings
}).start() }).start()
}, resetNotifications: { }, resetNotifications: {
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }

View File

@ -175,7 +175,7 @@ final class PeerChannelMemberCategoriesContextsManager {
} }
} }
func addMembers(account: Account, peerId: PeerId, memberIds: [PeerId]) -> Signal<Void, NoError> { func addMembers(account: Account, peerId: PeerId, memberIds: [PeerId]) -> Signal<Void, AddChannelMemberError> {
return addChannelMembers(account: account, peerId: peerId, memberIds: memberIds) |> deliverOnMainQueue return addChannelMembers(account: account, peerId: peerId, memberIds: memberIds) |> deliverOnMainQueue
|> beforeNext { [weak self] result in |> beforeNext { [weak self] result in
if let strongSelf = self { if let strongSelf = self {
@ -188,7 +188,7 @@ final class PeerChannelMemberCategoriesContextsManager {
} }
} }
} }
|> mapToSignal { _ -> Signal<Void, NoError> in |> mapToSignal { _ -> Signal<Void, AddChannelMemberError> in
return .single(Void()) return .single(Void())
} }
} }

View File

@ -51,6 +51,14 @@ private final class PresentationCallToneRenderer {
} }
let toneDataOffset = Atomic<Int>(value: 0) let toneDataOffset = Atomic<Int>(value: 0)
let toneDataMaxOffset: Int?
if let loopCount = tone.loopCount {
toneDataMaxOffset = (data?.count ?? 0) * loopCount
} else {
toneDataMaxOffset = nil
}
self.toneRenderer.beginRequestingFrames(queue: DispatchQueue.global(), takeFrame: { self.toneRenderer.beginRequestingFrames(queue: DispatchQueue.global(), takeFrame: {
guard let toneData = data else { guard let toneData = data else {
return .finished return .finished
@ -65,6 +73,10 @@ private final class PresentationCallToneRenderer {
} }
if let takeOffset = takeOffset { if let takeOffset = takeOffset {
if let toneDataMaxOffset = toneDataMaxOffset, takeOffset >= toneDataMaxOffset {
return .finished
}
var blockBuffer: CMBlockBuffer? var blockBuffer: CMBlockBuffer?
let bytes = malloc(frameSize)! let bytes = malloc(frameSize)!
@ -77,6 +89,12 @@ private final class PresentationCallToneRenderer {
takenCount += dataCount takenCount += dataCount
} }
} }
if let toneDataMaxOffset = toneDataMaxOffset, takeOffset + frameSize > toneDataMaxOffset {
let validCount = max(0, toneDataMaxOffset - takeOffset)
memset(bytes.advanced(by: validCount), 0, frameSize - validCount)
}
let status = CMBlockBufferCreateWithMemoryBlock(nil, bytes, frameSize, nil, nil, 0, frameSize, 0, &blockBuffer) let status = CMBlockBufferCreateWithMemoryBlock(nil, bytes, frameSize, nil, nil, 0, frameSize, 0, &blockBuffer)
if status != noErr { if status != noErr {
return .finished return .finished
@ -276,9 +294,11 @@ public final class PresentationCall {
if let audioSessionControl = strongSelf.audioSessionControl { if let audioSessionControl = strongSelf.audioSessionControl {
let audioSessionActive: Signal<Bool, NoError> let audioSessionActive: Signal<Bool, NoError>
if let callKitIntegration = strongSelf.callKitIntegration { if let callKitIntegration = strongSelf.callKitIntegration {
audioSessionActive = callKitIntegration.audioSessionActive |> filter { $0 } |> timeout(2.0, queue: Queue.mainQueue(), alternate: Signal { subscriber in audioSessionActive = callKitIntegration.audioSessionActive
|> filter { $0 }
|> timeout(2.0, queue: Queue.mainQueue(), alternate: Signal { subscriber in
if let strongSelf = self, let audioSessionControl = strongSelf.audioSessionControl { if let strongSelf = self, let audioSessionControl = strongSelf.audioSessionControl {
audioSessionControl.activate({ _ in }) //audioSessionControl.activate({ _ in })
} }
subscriber.putNext(true) subscriber.putNext(true)
subscriber.putCompletion() subscriber.putCompletion()
@ -432,12 +452,12 @@ public final class PresentationCall {
if case .terminated = sessionState.state, !wasTerminated { if case .terminated = sessionState.state, !wasTerminated {
if !self.didSetCanBeRemoved { if !self.didSetCanBeRemoved {
self.didSetCanBeRemoved = true self.didSetCanBeRemoved = true
self.canBeRemovedPromise.set(.single(true) |> delay(2.0, queue: Queue.mainQueue())) self.canBeRemovedPromise.set(.single(true) |> delay(2.4, queue: Queue.mainQueue()))
} }
self.hungUpPromise.set(true) self.hungUpPromise.set(true)
if sessionState.isOutgoing { if sessionState.isOutgoing {
if !self.droppedCall && self.dropCallKitCallTimer == nil { if !self.droppedCall && self.dropCallKitCallTimer == nil {
let dropCallKitCallTimer = SwiftSignalKit.Timer(timeout: 2.0, repeat: false, completion: { [weak self] in let dropCallKitCallTimer = SwiftSignalKit.Timer(timeout: 2.4, repeat: false, completion: { [weak self] in
if let strongSelf = self { if let strongSelf = self {
strongSelf.dropCallKitCallTimer = nil strongSelf.dropCallKitCallTimer = nil
if !strongSelf.droppedCall { if !strongSelf.droppedCall {

View File

@ -71,6 +71,15 @@ enum PresentationCallTone {
case busy case busy
case failed case failed
case ended case ended
var loopCount: Int? {
switch self {
case .busy, .failed, .ended:
return 3
default:
return nil
}
}
} }
func presentationCallToneData(_ tone: PresentationCallTone) -> Data? { func presentationCallToneData(_ tone: PresentationCallTone) -> Data? {

File diff suppressed because it is too large Load Diff

View File

@ -59,7 +59,8 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
if !filled { if !filled {
if let contentNode = strongSelf.contentNode as? SecureIdAuthFormContentNode { if let contentNode = strongSelf.contentNode as? SecureIdAuthFormContentNode {
if let rect = contentNode.frameForField(field) { if let rect = contentNode.frameForField(field) {
strongSelf.scrollNode.view.scrollRectToVisible(rect, animated: true) let subRect = contentNode.view.convert(rect, to: strongSelf.scrollNode.view)
strongSelf.scrollNode.view.scrollRectToVisible(subRect, animated: true)
} }
contentNode.highlightField(field) contentNode.highlightField(field)
} }
@ -266,6 +267,9 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
case let .passwordChallenge(hint, challengeState, _): case let .passwordChallenge(hint, challengeState, _):
if let current = self.contentNode as? SecureIdAuthPasswordOptionContentNode { if let current = self.contentNode as? SecureIdAuthPasswordOptionContentNode {
current.updateIsChecking(challengeState == .checking) current.updateIsChecking(challengeState == .checking)
if case .invalid = challengeState {
current.updateIsInvalid()
}
contentNode = current contentNode = current
} else { } else {
let current = SecureIdAuthPasswordOptionContentNode(theme: presentationData.theme, strings: presentationData.strings, hint: hint, checkPassword: { [weak self] password in let current = SecureIdAuthPasswordOptionContentNode(theme: presentationData.theme, strings: presentationData.strings, hint: hint, checkPassword: { [weak self] password in
@ -276,6 +280,9 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
self?.interaction.openPasswordHelp() self?.interaction.openPasswordHelp()
}) })
current.updateIsChecking(challengeState == .checking) current.updateIsChecking(challengeState == .checking)
if case .invalid = challengeState {
current.updateIsInvalid()
}
contentNode = current contentNode = current
} }
case .verified: case .verified:

View File

@ -13,6 +13,7 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
private let titleNode: ImmediateTextNode private let titleNode: ImmediateTextNode
private let inputBackground: ASImageNode private let inputBackground: ASImageNode
private let inputField: TextFieldNode private let inputField: TextFieldNode
private var clearOnce: Bool = false
private let inputButtonNode: HighlightableButtonNode private let inputButtonNode: HighlightableButtonNode
private let inputActivityNode: ActivityIndicator private let inputActivityNode: ActivityIndicator
@ -180,7 +181,18 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
} }
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return !self.isChecking if self.isChecking {
return false
}
if self.clearOnce {
self.clearOnce = false
if range.length > string.count {
textField.text = ""
return false
}
}
return true
} }
func textFieldShouldReturn(_ textField: UITextField) -> Bool { func textFieldShouldReturn(_ textField: UITextField) -> Bool {
@ -196,4 +208,8 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
self.inputActivityNode.isHidden = !isChecking self.inputActivityNode.isHidden = !isChecking
self.inputButtonNode.isHidden = isChecking self.inputButtonNode.isHidden = isChecking
} }
func updateIsInvalid() {
self.clearOnce = true
}
} }

View File

@ -606,7 +606,7 @@ enum SecureIdPlaintextFormEntry: FormControllerEntry {
return FormControllerTextInputItem(title: strings.TwoStepAuth_Email, text: address, placeholder: strings.Passport_Email_EmailPlaceholder, type: .email, textUpdated: { value in return FormControllerTextInputItem(title: strings.TwoStepAuth_Email, text: address, placeholder: strings.Passport_Email_EmailPlaceholder, type: .email, textUpdated: { value in
params.updateTextField(.email, value) params.updateTextField(.email, value)
}, returnPressed: { }, returnPressed: {
params.save()
}) })
case .emailInputInfo: case .emailInputInfo:
return FormControllerTextItem(text: strings.Passport_Email_Help) return FormControllerTextItem(text: strings.Passport_Email_Help)