Added cellular data permission warning

Fixed people nearby initial opening
Fixed 3rd apps opening from group's location view screen
This commit is contained in:
Ilya Laktyushin 2019-06-25 23:58:11 +02:00
parent dfd1808d04
commit 3227b51ff8
13 changed files with 99 additions and 54 deletions

View File

@ -179,11 +179,11 @@ public final class DeviceAccess {
func statusForCellularState(_ state: CTCellularDataRestrictedState) -> AccessType? { func statusForCellularState(_ state: CTCellularDataRestrictedState) -> AccessType? {
switch state { switch state {
case .restricted: case .restricted:
return .denied return .allowed
case .notRestricted: case .notRestricted:
return .allowed return .allowed
default: default:
return nil return .allowed
} }
} }
let cellState = CTCellularData.init() let cellState = CTCellularData.init()
@ -196,7 +196,7 @@ public final class DeviceAccess {
} }
} }
} else { } else {
subscriber.putNext(.notDetermined) subscriber.putNext(.allowed)
subscriber.putCompletion() subscriber.putCompletion()
} }
return EmptyDisposable return EmptyDisposable
@ -446,8 +446,12 @@ public final class DeviceAccess {
completion(result) completion(result)
} }
} }
default: case .cellularData:
break if let presentationData = presentationData {
present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.Permissions_CellularDataTitle_v0, text: presentationData.strings.Permissions_CellularDataText_v0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
openSettings()
})]), nil)
}
} }
} }
} }

View File

@ -590,6 +590,9 @@ final class SharedApplicationContext {
}, requestSetAlternateIconName: { name, completion in }, requestSetAlternateIconName: { name, completion in
if #available(iOS 10.3, *) { if #available(iOS 10.3, *) {
application.setAlternateIconName(name, completionHandler: { error in application.setAlternateIconName(name, completionHandler: { error in
if let error = error {
Logger.shared.log("App \(self.episodeId)", "failed to set alternate icon with error \(error.localizedDescription)")
}
completion(error == nil) completion(error == nil)
}) })
} else { } else {

View File

@ -148,14 +148,7 @@ final class AuthorizedApplicationContext {
context.keyShortcutsController = keyShortcutsController context.keyShortcutsController = keyShortcutsController
} }
/*self.applicationInForegroundDisposable = context.sharedContext.applicationBindings.applicationInForeground.start(next: { [weak self] value in
Queue.mainQueue().async {
self?.notificationManager.isApplicationInForeground = value
}
})*/
let previousPasscodeState = Atomic<PasscodeState?>(value: nil) let previousPasscodeState = Atomic<PasscodeState?>(value: nil)
let passcodeStatusData = combineLatest(queue: Queue.mainQueue(), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationPasscodeSettings]), context.sharedContext.accountManager.accessChallengeData(), context.sharedContext.applicationBindings.applicationIsActive) let passcodeStatusData = combineLatest(queue: Queue.mainQueue(), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationPasscodeSettings]), context.sharedContext.accountManager.accessChallengeData(), context.sharedContext.applicationBindings.applicationIsActive)
let passcodeState = passcodeStatusData let passcodeState = passcodeStatusData
|> map { sharedData, accessChallengeDataView, isActive -> PasscodeState in |> map { sharedData, accessChallengeDataView, isActive -> PasscodeState in
@ -281,7 +274,7 @@ final class AuthorizedApplicationContext {
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
} else { } else {
DeviceAccess.authorizeAccess(to: .contacts, presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, present: { c, a in DeviceAccess.authorizeAccess(to: .contacts, presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, present: { c, a in
}, openSettings: {}, { _ in }) })
} }
if let passcodeController = strongSelf.passcodeController { if let passcodeController = strongSelf.passcodeController {
@ -520,23 +513,27 @@ final class AuthorizedApplicationContext {
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
let permissionsPosition = ValuePromise(0, ignoreRepeated: true) let permissionsPosition = ValuePromise(0, ignoreRepeated: true)
self.permissionsDisposable.set((combineLatest(queue: .mainQueue(), requiredPermissions(context: context), permissionUISplitTest(postbox: context.account.postbox), permissionsPosition.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.contactsPermissionWarningKey()), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.notificationsPermissionWarningKey())) self.permissionsDisposable.set((combineLatest(queue: .mainQueue(), requiredPermissions(context: context), permissionUISplitTest(postbox: context.account.postbox), permissionsPosition.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.permissionWarningKey(permission: .contacts)!), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.permissionWarningKey(permission: .notifications)!), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.permissionWarningKey(permission: .cellularData)!))
|> deliverOnMainQueue).start(next: { [weak self] required, splitTest, position, contactsPermissionWarningNotice, notificationsPermissionWarningNotice in |> deliverOnMainQueue).start(next: { [weak self] required, splitTest, position, contactsPermissionWarningNotice, notificationsPermissionWarningNotice, cellularDataPermissionWarningNotice in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
let contactsTimestamp = contactsPermissionWarningNotice.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) }) let contactsTimestamp = contactsPermissionWarningNotice.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) })
let notificationsTimestamp = notificationsPermissionWarningNotice.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) }) let notificationsTimestamp = notificationsPermissionWarningNotice.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) })
let cellularDataTimestamp = cellularDataPermissionWarningNotice.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) })
if contactsTimestamp == nil, case .requestable = required.0.status { if contactsTimestamp == nil, case .requestable = required.0.status {
ApplicationSpecificNotice.setContactsPermissionWarning(accountManager: context.sharedContext.accountManager, value: 1) ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .contacts, value: 1)
} }
if notificationsTimestamp == nil, case .requestable = required.1.status { if notificationsTimestamp == nil, case .requestable = required.1.status {
ApplicationSpecificNotice.setNotificationsPermissionWarning(accountManager: context.sharedContext.accountManager, value: 1) ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .notifications, value: 1)
} }
let config = splitTest.configuration let config = splitTest.configuration
var order = config.order var order = config.order
if !order.contains(.cellularData) {
order.append(.cellularData)
}
if !order.contains(.siri) { if !order.contains(.siri) {
order.append(.siri) order.append(.siri)
} }
@ -563,9 +560,13 @@ final class AuthorizedApplicationContext {
if case .requestable = required.1.status, notificationsTimestamp != 0 { if case .requestable = required.1.status, notificationsTimestamp != 0 {
requestedPermissions.append((required.1, modal)) requestedPermissions.append((required.1, modal))
} }
case .cellularData:
if case .denied = required.2.status, cellularDataTimestamp != 0 {
requestedPermissions.append((required.2, true))
}
case .siri: case .siri:
if case .requestable = required.2.status { if case .requestable = required.3.status {
requestedPermissions.append((required.2, false)) requestedPermissions.append((required.3, false))
} }
default: default:
break break
@ -590,9 +591,11 @@ final class AuthorizedApplicationContext {
permissionsPosition.set(position + 1) permissionsPosition.set(position + 1)
switch state { switch state {
case .contacts: case .contacts:
ApplicationSpecificNotice.setContactsPermissionWarning(accountManager: context.sharedContext.accountManager, value: 0) ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .contacts, value: 0)
case .notifications: case .notifications:
ApplicationSpecificNotice.setNotificationsPermissionWarning(accountManager: context.sharedContext.accountManager, value: 0) ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .notifications, value: 0)
case .cellularData:
ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .cellularData, value: 0)
default: default:
break break
} }
@ -616,7 +619,7 @@ final class AuthorizedApplicationContext {
splitTest.addEvent(.ContactsDenied) splitTest.addEvent(.ContactsDenied)
} }
permissionsPosition.set(position + 1) permissionsPosition.set(position + 1)
ApplicationSpecificNotice.setContactsPermissionWarning(accountManager: context.sharedContext.accountManager, value: 0) ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .contacts, value: 0)
} }
case .notifications: case .notifications:
splitTest.addEvent(.NotificationsRequest) splitTest.addEvent(.NotificationsRequest)
@ -629,8 +632,19 @@ final class AuthorizedApplicationContext {
splitTest.addEvent(.NotificationsDenied) splitTest.addEvent(.NotificationsDenied)
} }
permissionsPosition.set(position + 1) permissionsPosition.set(position + 1)
ApplicationSpecificNotice.setNotificationsPermissionWarning(accountManager: context.sharedContext.accountManager, value: 0) ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .notifications, value: 0)
} }
case .cellularData:
DeviceAccess.authorizeAccess(to: .cellularData, presentationData: context.sharedContext.currentPresentationData.with { $0 }, present: { [weak self] c, a in
if let strongSelf = self {
(strongSelf.rootController.viewControllers.last as? ViewController)?.present(c, in: .window(.root))
}
}, openSettings: {
context.sharedContext.applicationBindings.openSettings()
}, { result in
permissionsPosition.set(position + 1)
ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .cellularData, value: 0)
})
case .siri: case .siri:
DeviceAccess.authorizeAccess(to: .siri, requestSiriAuthorization: { completion in DeviceAccess.authorizeAccess(to: .siri, requestSiriAuthorization: { completion in
return context.sharedContext.applicationBindings.requestSiriAuthorization(completion) return context.sharedContext.applicationBindings.requestSiriAuthorization(completion)

View File

@ -849,7 +849,7 @@ final class ContactListNode: ASDisplayNode {
let contactsWarningSuppressed = Promise<(Bool, Bool)>() let contactsWarningSuppressed = Promise<(Bool, Bool)>()
contactsWarningSuppressed.set(.single((false, false)) contactsWarningSuppressed.set(.single((false, false))
|> then( |> then(
combineLatest(context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.contactsPermissionWarningKey()), context.account.postbox.preferencesView(keys: [PreferencesKeys.contactsSettings])) combineLatest(context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.permissionWarningKey(permission: .contacts)!), context.account.postbox.preferencesView(keys: [PreferencesKeys.contactsSettings]))
|> map { noticeView, preferences -> (Bool, Bool) in |> map { noticeView, preferences -> (Bool, Bool) in
let settings: ContactsSettings = preferences.values[PreferencesKeys.contactsSettings] as? ContactsSettings ?? ContactsSettings.defaultSettings let settings: ContactsSettings = preferences.values[PreferencesKeys.contactsSettings] as? ContactsSettings ?? ContactsSettings.defaultSettings
let synchronizeDeviceContacts: Bool = settings.synchronizeContacts let synchronizeDeviceContacts: Bool = settings.synchronizeContacts

View File

@ -132,7 +132,7 @@ public class ContactsController: ViewController {
}) })
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.authorizationDisposable = (combineLatest(DeviceAccess.authorizationStatus(subject: .contacts), combineLatest(context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.contactsPermissionWarningKey()), context.account.postbox.preferencesView(keys: [PreferencesKeys.contactsSettings]), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings])) self.authorizationDisposable = (combineLatest(DeviceAccess.authorizationStatus(subject: .contacts), combineLatest(context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.permissionWarningKey(permission: .contacts)!), context.account.postbox.preferencesView(keys: [PreferencesKeys.contactsSettings]), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]))
|> map { noticeView, preferences, sharedData -> (Bool, ContactsSortOrder) in |> map { noticeView, preferences, sharedData -> (Bool, ContactsSortOrder) in
let settings: ContactsSettings = preferences.values[PreferencesKeys.contactsSettings] as? ContactsSettings ?? ContactsSettings.defaultSettings let settings: ContactsSettings = preferences.values[PreferencesKeys.contactsSettings] as? ContactsSettings ?? ContactsSettings.defaultSettings
let synchronizeDeviceContacts: Bool = settings.synchronizeContacts let synchronizeDeviceContacts: Bool = settings.synchronizeContacts

View File

@ -2001,7 +2001,9 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
return return
} }
let mapMedia = TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, geoPlace: nil, venue: MapVenue(title: peer.displayTitle, address: location.address, provider: nil, id: nil, type: nil), liveBroadcastingTimeout: nil) let mapMedia = TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, geoPlace: nil, venue: MapVenue(title: peer.displayTitle, address: location.address, provider: nil, id: nil, type: nil), liveBroadcastingTimeout: nil)
let controller = legacyLocationController(message: nil, mapMedia: mapMedia, context: context, isModal: false, openPeer: { _ in }, sendLiveLocation: { _, _ in }, stopLiveLocation: {}, openUrl: { _ in }) let controller = legacyLocationController(message: nil, mapMedia: mapMedia, context: context, isModal: false, openPeer: { _ in }, sendLiveLocation: { _, _ in }, stopLiveLocation: {}, openUrl: { url in
context.sharedContext.applicationBindings.openUrl(url)
})
pushControllerImpl?(controller) pushControllerImpl?(controller)
}) })
}, changeLocation: { }, changeLocation: {

View File

@ -129,6 +129,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
case archiveChatTips = 10 case archiveChatTips = 10
case archiveIntroDismissed = 11 case archiveIntroDismissed = 11
case callsTabTip = 12 case callsTabTip = 12
case cellularDataPermissionWarning = 13
var key: ValueBoxKey { var key: ValueBoxKey {
let v = ValueBoxKey(length: 4) let v = ValueBoxKey(length: 4)
@ -137,6 +138,21 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
} }
} }
private extension PermissionKind {
var noticeKey: NoticeEntryKey? {
switch self {
case .contacts:
return ApplicationSpecificNoticeKeys.contactsPermissionWarning()
case .notifications:
return ApplicationSpecificNoticeKeys.notificationsPermissionWarning()
case .cellularData:
return ApplicationSpecificNoticeKeys.cellularDataPermissionWarning()
default:
return nil
}
}
}
private struct ApplicationSpecificNoticeKeys { private struct ApplicationSpecificNoticeKeys {
private static let botPaymentLiabilityNamespace: Int32 = 1 private static let botPaymentLiabilityNamespace: Int32 = 1
private static let globalNamespace: Int32 = 2 private static let globalNamespace: Int32 = 2
@ -195,6 +211,10 @@ private struct ApplicationSpecificNoticeKeys {
return NoticeEntryKey(namespace: noticeNamespace(namespace: permissionsNamespace), key: ApplicationSpecificGlobalNotice.notificationsPermissionWarning.key) return NoticeEntryKey(namespace: noticeNamespace(namespace: permissionsNamespace), key: ApplicationSpecificGlobalNotice.notificationsPermissionWarning.key)
} }
static func cellularDataPermissionWarning() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: permissionsNamespace), key: ApplicationSpecificGlobalNotice.cellularDataPermissionWarning.key)
}
static func volumeButtonToUnmuteTip() -> NoticeEntryKey { static func volumeButtonToUnmuteTip() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.volumeButtonToUnmuteTip.key) return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.volumeButtonToUnmuteTip.key)
} }
@ -408,20 +428,19 @@ public struct ApplicationSpecificNotice {
} }
} }
public static func contactsPermissionWarningKey() -> NoticeEntryKey { public static func permissionWarningKey(permission: PermissionKind) -> NoticeEntryKey? {
return ApplicationSpecificNoticeKeys.contactsPermissionWarning() return permission.noticeKey
} }
public static func setContactsPermissionWarning(accountManager: AccountManager, value: Int32) { public static func setPermissionWarning(accountManager: AccountManager, permission: PermissionKind, value: Int32) {
guard let noticeKey = permission.noticeKey else {
return
}
let _ = accountManager.transaction { transaction -> Void in let _ = accountManager.transaction { transaction -> Void in
transaction.setNotice(ApplicationSpecificNoticeKeys.contactsPermissionWarning(), ApplicationSpecificTimestampNotice(value: value)) transaction.setNotice(noticeKey, ApplicationSpecificTimestampNotice(value: value))
}.start() }.start()
} }
public static func notificationsPermissionWarningKey() -> NoticeEntryKey {
return ApplicationSpecificNoticeKeys.notificationsPermissionWarning()
}
public static func getTimestampValue(_ entry: NoticeEntry) -> Int32? { public static func getTimestampValue(_ entry: NoticeEntry) -> Int32? {
if let value = entry as? ApplicationSpecificTimestampNotice { if let value = entry as? ApplicationSpecificTimestampNotice {
return value.value return value.value
@ -430,12 +449,6 @@ public struct ApplicationSpecificNotice {
} }
} }
public static func setNotificationsPermissionWarning(accountManager: AccountManager, value: Int32) {
let _ = accountManager.transaction { transaction -> Void in
transaction.setNotice(ApplicationSpecificNoticeKeys.notificationsPermissionWarning(), ApplicationSpecificTimestampNotice(value: value))
}.start()
}
static func getVolumeButtonToUnmute(accountManager: AccountManager) -> Signal<Bool, NoError> { static func getVolumeButtonToUnmute(accountManager: AccountManager) -> Signal<Bool, NoError> {
return accountManager.transaction { transaction -> Bool in return accountManager.transaction { transaction -> Bool in
if let _ = transaction.getNotice(ApplicationSpecificNoticeKeys.volumeButtonToUnmuteTip()) as? ApplicationSpecificBoolNotice { if let _ = transaction.getNotice(ApplicationSpecificNoticeKeys.volumeButtonToUnmuteTip()) as? ApplicationSpecificBoolNotice {

View File

@ -836,7 +836,7 @@ public func notificationsAndSoundsController(context: AccountContext, exceptions
case .denied, .restricted: case .denied, .restricted:
context.sharedContext.applicationBindings.openSettings() context.sharedContext.applicationBindings.openSettings()
case .unreachable: case .unreachable:
ApplicationSpecificNotice.setNotificationsPermissionWarning(accountManager: context.sharedContext.accountManager, value: Int32(Date().timeIntervalSince1970)) ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .notifications, value: Int32(Date().timeIntervalSince1970))
context.sharedContext.applicationBindings.openSettings() context.sharedContext.applicationBindings.openSettings()
default: default:
break break
@ -845,7 +845,7 @@ public func notificationsAndSoundsController(context: AccountContext, exceptions
}, suppressWarning: { }, suppressWarning: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.Notifications_PermissionsSuppressWarningTitle, text: presentationData.strings.Notifications_PermissionsSuppressWarningText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Notifications_PermissionsKeepDisabled, action: { presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.Notifications_PermissionsSuppressWarningTitle, text: presentationData.strings.Notifications_PermissionsSuppressWarningText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Notifications_PermissionsKeepDisabled, action: {
ApplicationSpecificNotice.setNotificationsPermissionWarning(accountManager: context.sharedContext.accountManager, value: Int32(Date().timeIntervalSince1970)) ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .notifications, value: Int32(Date().timeIntervalSince1970))
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Notifications_PermissionsEnable, action: { }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Notifications_PermissionsEnable, action: {
context.sharedContext.applicationBindings.openSettings() context.sharedContext.applicationBindings.openSettings()
})]), nil) })]), nil)
@ -1051,7 +1051,7 @@ public func notificationsAndSoundsController(context: AccountContext, exceptions
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
notificationsWarningSuppressed.set(.single(true) notificationsWarningSuppressed.set(.single(true)
|> then( |> then(
context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.notificationsPermissionWarningKey()) context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.permissionWarningKey(permission: .notifications)!)
|> map { noticeView -> Bool in |> map { noticeView -> Bool in
let timestamp = noticeView.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) }) let timestamp = noticeView.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) })
if let timestamp = timestamp, timestamp > 0 { if let timestamp = timestamp, timestamp > 0 {

View File

@ -5,7 +5,7 @@ import TelegramCore
import MobileCoreServices import MobileCoreServices
private func rtfStringWithAppliedEntities(_ text: String, entities: [MessageTextEntity]) -> String { private func rtfStringWithAppliedEntities(_ text: String, entities: [MessageTextEntity]) -> String {
let test = stringWithAppliedEntities(text, entities: entities, baseColor: .black, linkColor: .black, baseFont: Font.regular(14.0), linkFont: Font.regular(14.0), boldFont: Font.semibold(14.0), italicFont: Font.italic(14.0), fixedFont: Font.monospace(14.0), underlineLinks: false, external: true) let test = stringWithAppliedEntities(text, entities: entities, baseColor: .black, linkColor: .black, baseFont: Font.regular(14.0), linkFont: Font.regular(14.0), boldFont: Font.semibold(14.0), italicFont: Font.italic(14.0), boldItalicFont: Font.semiboldItalic(14.0), fixedFont: Font.monospace(14.0), underlineLinks: false, external: true)
if let data = try? test.data(from: NSRange(location: 0, length: test.length), documentAttributes: [NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.rtf]) { if let data = try? test.data(from: NSRange(location: 0, length: test.length), documentAttributes: [NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.rtf]) {
if var rtf = String(data: data, encoding: .windowsCP1252) { if var rtf = String(data: data, encoding: .windowsCP1252) {

View File

@ -389,7 +389,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
} }
} }
} }
dataPromise.set(dataSignal) dataPromise.set(.single(nil) |> then(dataSignal))
let previousData = Atomic<PeersNearbyData?>(value: nil) let previousData = Atomic<PeersNearbyData?>(value: nil)
let displayLoading: Signal<Bool, NoError> = .single(false) let displayLoading: Signal<Bool, NoError> = .single(false)

View File

@ -36,7 +36,7 @@ public enum PermissionState: Equatable {
case contacts(status: PermissionRequestStatus) case contacts(status: PermissionRequestStatus)
case notifications(status: PermissionRequestStatus) case notifications(status: PermissionRequestStatus)
case siri(status: PermissionRequestStatus) case siri(status: PermissionRequestStatus)
case cellularData case cellularData(status: PermissionRequestStatus)
case nearbyLocation(status: PermissionRequestStatus) case nearbyLocation(status: PermissionRequestStatus)
var kind: PermissionKind { var kind: PermissionKind {
@ -62,19 +62,21 @@ public enum PermissionState: Equatable {
return status return status
case let .siri(status): case let .siri(status):
return status return status
case .cellularData: case let .cellularData(status):
return .unreachable return status
case let .nearbyLocation(status): case let .nearbyLocation(status):
return status return status
} }
} }
} }
public func requiredPermissions(context: AccountContext) -> Signal<(PermissionState, PermissionState, PermissionState), NoError> { public func requiredPermissions(context: AccountContext) -> Signal<(contacts: PermissionState, notifications: PermissionState, cellularData: PermissionState, siri: PermissionState), NoError> {
return combineLatest(DeviceAccess.authorizationStatus(subject: .contacts), DeviceAccess.authorizationStatus(applicationInForeground: context.sharedContext.applicationBindings.applicationInForeground, subject: .notifications), DeviceAccess.authorizationStatus(siriAuthorization: { return combineLatest(DeviceAccess.authorizationStatus(subject: .contacts), DeviceAccess.authorizationStatus(applicationInForeground: context.sharedContext.applicationBindings.applicationInForeground, subject: .notifications), DeviceAccess.authorizationStatus(siriAuthorization: {
return context.sharedContext.applicationBindings.siriAuthorization() return context.sharedContext.applicationBindings.siriAuthorization()
}, subject: .cellularData), DeviceAccess.authorizationStatus(siriAuthorization: {
return context.sharedContext.applicationBindings.siriAuthorization()
}, subject: .siri)) }, subject: .siri))
|> map { contactsStatus, notificationsStatus, siriStatus in |> map { contactsStatus, notificationsStatus, cellularDataStatus, siriStatus in
return (.contacts(status: PermissionRequestStatus(accessType: contactsStatus)), .notifications(status: PermissionRequestStatus(accessType: notificationsStatus)), .siri(status: PermissionRequestStatus(accessType: siriStatus))) return (.contacts(status: PermissionRequestStatus(accessType: contactsStatus)), .notifications(status: PermissionRequestStatus(accessType: notificationsStatus)), .cellularData(status: PermissionRequestStatus(accessType: cellularDataStatus)), .siri(status: PermissionRequestStatus(accessType: siriStatus)))
} }
} }

View File

@ -108,6 +108,11 @@ public final class PermissionController : ViewController {
self.state = state self.state = state
if case let .permission(permission) = state, let state = permission { if case let .permission(permission) = state, let state = permission {
if case .nearbyLocation = state {
} else {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Permissions_Skip, style: .plain, target: self, action: #selector(PermissionController.nextPressed))
}
switch state { switch state {
case let .contacts(status): case let .contacts(status):
self.splitTest?.addEvent(.ContactsModalRequest) self.splitTest?.addEvent(.ContactsModalRequest)
@ -170,11 +175,13 @@ public final class PermissionController : ViewController {
} }
case .cellularData: case .cellularData:
self.allow = { [weak self] in self.allow = { [weak self] in
self?.proceed?(true) if let strongSelf = self {
strongSelf.openAppSettings()
strongSelf.proceed?(true)
}
} }
case let .nearbyLocation(status): case let .nearbyLocation(status):
self.title = self.presentationData.strings.Permissions_PeopleNearbyTitle_v0 self.title = self.presentationData.strings.Permissions_PeopleNearbyTitle_v0
self.navigationItem.rightBarButtonItem = nil
self.allow = { [weak self] in self.allow = { [weak self] in
if let strongSelf = self { if let strongSelf = self {

View File

@ -1052,7 +1052,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|> then( |> then(
contextValue.get() contextValue.get()
|> mapToSignal { context -> Signal<Bool, NoError> in |> mapToSignal { context -> Signal<Bool, NoError> in
return context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.notificationsPermissionWarningKey()) return context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.permissionWarningKey(permission: .notifications)!)
|> map { noticeView -> Bool in |> map { noticeView -> Bool in
let timestamp = noticeView.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) }) let timestamp = noticeView.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) })
if let timestamp = timestamp, timestamp > 0 { if let timestamp = timestamp, timestamp > 0 {