mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 03:09:56 +00:00
Merge branch 'master' of github.com:peter-iakovlev/TelegramUI
This commit is contained in:
commit
cb30aa60a8
@ -323,11 +323,13 @@ public func channelMembersController(account: Account, peerId: PeerId) -> ViewCo
|
||||
|
||||
let arguments = ChannelMembersControllerArguments(account: account, addMember: {
|
||||
|
||||
let presentationData = account.telegramApplicationContext.currentPresentationData.with {$0}
|
||||
|
||||
actionsDisposable.add((peersPromise.get() |> take(1) |> deliverOnMainQueue).start(next: { members in
|
||||
let disabledIds = members?.compactMap({$0.peer.id}) ?? []
|
||||
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
|
||||
switch contact {
|
||||
case let .peer(peerId):
|
||||
@ -343,7 +345,9 @@ public func channelMembersController(account: Account, peerId: PeerId) -> ViewCo
|
||||
|> deliverOnMainQueue |> mapToSignal { [weak contactsController] contacts in
|
||||
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)
|
||||
} |> deliverOnMainQueue |> afterNext { _ in
|
||||
contactsController?.dismiss()
|
||||
|
||||
@ -4456,7 +4456,12 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
}
|
||||
|
||||
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()
|
||||
})]), in: .window(.root))
|
||||
} else {
|
||||
|
||||
@ -94,6 +94,10 @@ private let internalExtensions = Set<String>([
|
||||
"cs"
|
||||
])
|
||||
|
||||
private let internalNotSupportedExtensions = Set<String>([
|
||||
"djvu"
|
||||
])
|
||||
|
||||
private let internalMimeTypes = Set<String>([
|
||||
"application/pdf",
|
||||
"application/postscript",
|
||||
@ -101,7 +105,9 @@ private let internalMimeTypes = Set<String>([
|
||||
])
|
||||
|
||||
private let internalMimePrefixes: [String] = [
|
||||
"image/",
|
||||
"image/jpeg",
|
||||
"image/jpg",
|
||||
"image/png",
|
||||
"text/",
|
||||
"application/vnd.ms-"
|
||||
]
|
||||
@ -118,6 +124,9 @@ func internalDocumentItemSupportsMimeType(_ type: String, fileName: String?) ->
|
||||
if internalExtensions.contains(ext.lowercased()) {
|
||||
return true
|
||||
}
|
||||
if internalNotSupportedExtensions.contains(ext.lowercased()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if internalMimeTypes.contains(type) {
|
||||
|
||||
@ -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
|
||||
switch contact {
|
||||
case let .peer(peerId):
|
||||
@ -1474,29 +1474,31 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
|
||||
return account.postbox.multiplePeersView(memberIds)
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue
|
||||
|> mapToSignal { view -> Signal<Void, NoError> in
|
||||
updateState { state in
|
||||
var state = state
|
||||
for (memberId, peer) in view.peers {
|
||||
var found = false
|
||||
for participant in state.temporaryParticipants {
|
||||
if participant.peer.id == memberId {
|
||||
found = true
|
||||
break
|
||||
|> mapError { _ in return .generic}
|
||||
|> mapToSignal { view -> Signal<Void, AddChannelMemberError> in
|
||||
return account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.addMembers(account: account, peerId: peerId, memberIds: memberIds) |> map { _ in
|
||||
updateState { state in
|
||||
var state = state
|
||||
for (memberId, peer) in view.peers {
|
||||
var found = false
|
||||
for participant in state.temporaryParticipants {
|
||||
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)
|
||||
var temporaryParticipants = state.temporaryParticipants
|
||||
temporaryParticipants.append(TemporaryParticipant(peer: peer, presence: view.presences[memberId], timestamp: timestamp))
|
||||
state = state.withUpdatedTemporaryParticipants(temporaryParticipants)
|
||||
}
|
||||
|
||||
return state
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
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()
|
||||
}))
|
||||
}))
|
||||
|
||||
@ -12,16 +12,18 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable {
|
||||
public var vibrate: Bool
|
||||
public var displayPreviews: Bool
|
||||
public var totalUnreadCountDisplayStyle: TotalUnreadCountDisplayStyle
|
||||
public var displayNameOnLockscreen: Bool
|
||||
|
||||
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.vibrate = vibrate
|
||||
self.displayPreviews = displayPreviews
|
||||
self.totalUnreadCountDisplayStyle = totalUnreadCountDisplayStyle
|
||||
self.displayNameOnLockscreen = displayNameOnLockscreen
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
@ -29,6 +31,7 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable {
|
||||
self.vibrate = decoder.decodeInt32ForKey("v", orElse: 0) != 0
|
||||
self.displayPreviews = decoder.decodeInt32ForKey("p", orElse: 0) != 0
|
||||
self.totalUnreadCountDisplayStyle = TotalUnreadCountDisplayStyle(rawValue: decoder.decodeInt32ForKey("tds", orElse: 0)) ?? .filtered
|
||||
self.displayNameOnLockscreen = decoder.decodeInt32ForKey("displayNameOnLockscreen", orElse: 1) != 0
|
||||
}
|
||||
|
||||
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.displayPreviews ? 1 : 0, forKey: "p")
|
||||
encoder.encodeInt32(self.totalUnreadCountDisplayStyle.rawValue, forKey: "tds")
|
||||
}
|
||||
|
||||
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)
|
||||
encoder.encodeInt32(self.displayNameOnLockscreen ? 1 : 0, forKey: "displayNameOnLockscreen")
|
||||
}
|
||||
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
@ -61,22 +49,6 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable {
|
||||
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> {
|
||||
|
||||
@ -551,6 +551,8 @@ public final class ManagedAudioSession {
|
||||
print("ManagedAudioSession setting active false")
|
||||
do {
|
||||
try AVAudioSession.sharedInstance().setActive(false, with: [.notifyOthersOnDeactivation])
|
||||
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
|
||||
try AVAudioSession.sharedInstance().setPreferredInput(nil)
|
||||
} catch let error {
|
||||
print("ManagedAudioSession applyNone error \(error)")
|
||||
}
|
||||
|
||||
@ -21,11 +21,12 @@ private final class NotificationsAndSoundsArguments {
|
||||
let updateInAppVibration: (Bool) -> Void
|
||||
let updateInAppPreviews: (Bool) -> Void
|
||||
|
||||
let updateDisplayNameOnLockscreen: (Bool) -> Void
|
||||
let updateTotalUnreadCountStyle: (Bool) -> 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.presentController = presentController
|
||||
self.soundSelectionDisposable = soundSelectionDisposable
|
||||
@ -38,6 +39,7 @@ private final class NotificationsAndSoundsArguments {
|
||||
self.updateInAppSounds = updateInAppSounds
|
||||
self.updateInAppVibration = updateInAppVibration
|
||||
self.updateInAppPreviews = updateInAppPreviews
|
||||
self.updateDisplayNameOnLockscreen = updateDisplayNameOnLockscreen
|
||||
self.updateTotalUnreadCountStyle = updateTotalUnreadCountStyle
|
||||
self.resetNotifications = resetNotifications
|
||||
}
|
||||
@ -47,6 +49,7 @@ private enum NotificationsAndSoundsSection: Int32 {
|
||||
case messages
|
||||
case groups
|
||||
case inApp
|
||||
case displayNamesOnLockscreen
|
||||
case unreadCountStyle
|
||||
case reset
|
||||
}
|
||||
@ -69,6 +72,8 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
|
||||
case inAppVibrate(PresentationTheme, String, Bool)
|
||||
case inAppPreviews(PresentationTheme, String, Bool)
|
||||
|
||||
case displayNamesOnLockscreen(PresentationTheme, String, Bool)
|
||||
case displayNamesOnLockscreenInfo(PresentationTheme, String)
|
||||
case unreadCountStyle(PresentationTheme, String, Bool)
|
||||
|
||||
case reset(PresentationTheme, String)
|
||||
@ -82,6 +87,8 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
|
||||
return NotificationsAndSoundsSection.groups.rawValue
|
||||
case .inAppHeader, .inAppSounds, .inAppVibrate, .inAppPreviews:
|
||||
return NotificationsAndSoundsSection.inApp.rawValue
|
||||
case .displayNamesOnLockscreen, .displayNamesOnLockscreenInfo:
|
||||
return NotificationsAndSoundsSection.displayNamesOnLockscreen.rawValue
|
||||
case .unreadCountStyle:
|
||||
return NotificationsAndSoundsSection.unreadCountStyle.rawValue
|
||||
case .reset, .resetNotice:
|
||||
@ -119,12 +126,16 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
|
||||
return 12
|
||||
case .inAppPreviews:
|
||||
return 13
|
||||
case .unreadCountStyle:
|
||||
case .displayNamesOnLockscreen:
|
||||
return 14
|
||||
case .reset:
|
||||
case .displayNamesOnLockscreenInfo:
|
||||
return 15
|
||||
case .resetNotice:
|
||||
case .unreadCountStyle:
|
||||
return 16
|
||||
case .reset:
|
||||
return 17
|
||||
case .resetNotice:
|
||||
return 18
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,6 +225,18 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
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):
|
||||
if case let .unreadCountStyle(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
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
|
||||
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):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { updatedValue in
|
||||
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(.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(.resetNotice(presentationData.theme, presentationData.strings.Notifications_ResetAllNotificationsHelp))
|
||||
@ -386,19 +419,33 @@ public func notificationsAndSoundsController(account: Account) -> ViewController
|
||||
}).start()
|
||||
}, updateInAppSounds: { value in
|
||||
let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in
|
||||
return settings.withUpdatedPlaySounds(value)
|
||||
var settings = settings
|
||||
settings.playSounds = value
|
||||
return settings
|
||||
}).start()
|
||||
}, updateInAppVibration: { value in
|
||||
let _ = updateInAppNotificationSettingsInteractively(postbox: account.postbox, { settings in
|
||||
return settings.withUpdatedVibrate(value)
|
||||
var settings = settings
|
||||
settings.vibrate = value
|
||||
return settings
|
||||
}).start()
|
||||
}, updateInAppPreviews: { value 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()
|
||||
}, updateTotalUnreadCountStyle: { value 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()
|
||||
}, resetNotifications: {
|
||||
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
||||
|
||||
@ -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
|
||||
|> beforeNext { [weak self] result in
|
||||
if let strongSelf = self {
|
||||
@ -188,7 +188,7 @@ final class PeerChannelMemberCategoriesContextsManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
|> mapToSignal { _ -> Signal<Void, AddChannelMemberError> in
|
||||
return .single(Void())
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,6 +51,14 @@ private final class PresentationCallToneRenderer {
|
||||
}
|
||||
|
||||
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: {
|
||||
guard let toneData = data else {
|
||||
return .finished
|
||||
@ -65,6 +73,10 @@ private final class PresentationCallToneRenderer {
|
||||
}
|
||||
|
||||
if let takeOffset = takeOffset {
|
||||
if let toneDataMaxOffset = toneDataMaxOffset, takeOffset >= toneDataMaxOffset {
|
||||
return .finished
|
||||
}
|
||||
|
||||
var blockBuffer: CMBlockBuffer?
|
||||
|
||||
let bytes = malloc(frameSize)!
|
||||
@ -77,6 +89,12 @@ private final class PresentationCallToneRenderer {
|
||||
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)
|
||||
if status != noErr {
|
||||
return .finished
|
||||
@ -276,9 +294,11 @@ public final class PresentationCall {
|
||||
if let audioSessionControl = strongSelf.audioSessionControl {
|
||||
let audioSessionActive: Signal<Bool, NoError>
|
||||
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 {
|
||||
audioSessionControl.activate({ _ in })
|
||||
//audioSessionControl.activate({ _ in })
|
||||
}
|
||||
subscriber.putNext(true)
|
||||
subscriber.putCompletion()
|
||||
@ -432,12 +452,12 @@ public final class PresentationCall {
|
||||
if case .terminated = sessionState.state, !wasTerminated {
|
||||
if !self.didSetCanBeRemoved {
|
||||
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)
|
||||
if sessionState.isOutgoing {
|
||||
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 {
|
||||
strongSelf.dropCallKitCallTimer = nil
|
||||
if !strongSelf.droppedCall {
|
||||
|
||||
@ -71,6 +71,15 @@ enum PresentationCallTone {
|
||||
case busy
|
||||
case failed
|
||||
case ended
|
||||
|
||||
var loopCount: Int? {
|
||||
switch self {
|
||||
case .busy, .failed, .ended:
|
||||
return 3
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func presentationCallToneData(_ tone: PresentationCallTone) -> Data? {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -59,7 +59,8 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
if !filled {
|
||||
if let contentNode = strongSelf.contentNode as? SecureIdAuthFormContentNode {
|
||||
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)
|
||||
}
|
||||
@ -266,6 +267,9 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
case let .passwordChallenge(hint, challengeState, _):
|
||||
if let current = self.contentNode as? SecureIdAuthPasswordOptionContentNode {
|
||||
current.updateIsChecking(challengeState == .checking)
|
||||
if case .invalid = challengeState {
|
||||
current.updateIsInvalid()
|
||||
}
|
||||
contentNode = current
|
||||
} else {
|
||||
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()
|
||||
})
|
||||
current.updateIsChecking(challengeState == .checking)
|
||||
if case .invalid = challengeState {
|
||||
current.updateIsInvalid()
|
||||
}
|
||||
contentNode = current
|
||||
}
|
||||
case .verified:
|
||||
|
||||
@ -13,6 +13,7 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let inputBackground: ASImageNode
|
||||
private let inputField: TextFieldNode
|
||||
private var clearOnce: Bool = false
|
||||
private let inputButtonNode: HighlightableButtonNode
|
||||
private let inputActivityNode: ActivityIndicator
|
||||
|
||||
@ -180,7 +181,18 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -196,4 +208,8 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
|
||||
self.inputActivityNode.isHidden = !isChecking
|
||||
self.inputButtonNode.isHidden = isChecking
|
||||
}
|
||||
|
||||
func updateIsInvalid() {
|
||||
self.clearOnce = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
params.updateTextField(.email, value)
|
||||
}, returnPressed: {
|
||||
|
||||
params.save()
|
||||
})
|
||||
case .emailInputInfo:
|
||||
return FormControllerTextItem(text: strings.Passport_Email_Help)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user