mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 11:20:18 +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 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()
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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()
|
||||||
}))
|
}))
|
||||||
}))
|
}))
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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)")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 }
|
||||||
|
|||||||
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user