mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 19:30:29 +00:00
no message
This commit is contained in:
parent
54f4ffdac9
commit
acd863f780
@ -188,6 +188,7 @@
|
||||
D056CD7C1FF3E92C00880D28 /* DirectionalPanGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D056CD7B1FF3E92C00880D28 /* DirectionalPanGestureRecognizer.swift */; };
|
||||
D0642EFC1F3E1E7B00792790 /* ChatHistoryNavigationButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0642EFB1F3E1E7B00792790 /* ChatHistoryNavigationButtons.swift */; };
|
||||
D064EF871F69A06F00AC0398 /* MessageContentKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = D064EF861F69A06F00AC0398 /* MessageContentKind.swift */; };
|
||||
D0671F232143BDA6000A8AE7 /* TwoStepVerificationEmptyItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0671F222143BDA6000A8AE7 /* TwoStepVerificationEmptyItem.swift */; };
|
||||
D067B4A5211C911C00796039 /* LegacyChannelIntroController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D067B4A4211C911C00796039 /* LegacyChannelIntroController.swift */; };
|
||||
D067B4AA211C916300796039 /* TGChannelIntroController.h in Headers */ = {isa = PBXBuildFile; fileRef = D067B4A6211C916200796039 /* TGChannelIntroController.h */; };
|
||||
D067B4AD211C916300796039 /* TGChannelIntroController.m in Sources */ = {isa = PBXBuildFile; fileRef = D067B4A9211C916200796039 /* TGChannelIntroController.m */; };
|
||||
@ -1439,6 +1440,7 @@
|
||||
D0613FD41E6064D200202CDB /* ConvertToSupergroupController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConvertToSupergroupController.swift; sourceTree = "<group>"; };
|
||||
D0642EFB1F3E1E7B00792790 /* ChatHistoryNavigationButtons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatHistoryNavigationButtons.swift; sourceTree = "<group>"; };
|
||||
D064EF861F69A06F00AC0398 /* MessageContentKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageContentKind.swift; sourceTree = "<group>"; };
|
||||
D0671F222143BDA6000A8AE7 /* TwoStepVerificationEmptyItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoStepVerificationEmptyItem.swift; sourceTree = "<group>"; };
|
||||
D067B4A4211C911C00796039 /* LegacyChannelIntroController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyChannelIntroController.swift; sourceTree = "<group>"; };
|
||||
D067B4A6211C916200796039 /* TGChannelIntroController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGChannelIntroController.h; sourceTree = "<group>"; };
|
||||
D067B4A9211C916200796039 /* TGChannelIntroController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGChannelIntroController.m; sourceTree = "<group>"; };
|
||||
@ -4342,6 +4344,7 @@
|
||||
D05A32EB1E6F1462002760B4 /* BlockedPeersController.swift */,
|
||||
D05B724C1E720393000BD3AD /* SelectivePrivacySettingsController.swift */,
|
||||
D0EF40DC1E72F00E000DFCD4 /* SelectivePrivacySettingsPeersController.swift */,
|
||||
D0671F222143BDA6000A8AE7 /* TwoStepVerificationEmptyItem.swift */,
|
||||
D01C2AAA1E75E010001F6F9A /* TwoStepVerificationUnlockController.swift */,
|
||||
D0FA0ABE1E76E17F005BB9B7 /* TwoStepVerificationPasswordEntryController.swift */,
|
||||
D0FA0AC01E7725AA005BB9B7 /* TwoStepVerificationResetController.swift */,
|
||||
@ -5325,6 +5328,7 @@
|
||||
D093D7E22062F40100BC3599 /* SecureIdDocumentFormControllerNode.swift in Sources */,
|
||||
D0B2F7702052B5A800D3BFB9 /* InviteContactsControllerNode.swift in Sources */,
|
||||
D0EC6E211EB9F58900EBF1C3 /* InstantPageController.swift in Sources */,
|
||||
D0671F232143BDA6000A8AE7 /* TwoStepVerificationEmptyItem.swift in Sources */,
|
||||
D0EC6E221EB9F58900EBF1C3 /* InstantPageControllerNode.swift in Sources */,
|
||||
D0EC6E231EB9F58900EBF1C3 /* StickerPackPreviewController.swift in Sources */,
|
||||
0941A9A4210B0E2E00EBE194 /* OpenInAppIconResources.swift in Sources */,
|
||||
|
||||
@ -133,20 +133,33 @@ public final class AuthorizationSequenceController: NavigationController {
|
||||
controller.inProgress = false
|
||||
|
||||
let text: String
|
||||
var actions: [TextAlertAction] = [
|
||||
TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})
|
||||
]
|
||||
switch error {
|
||||
case .limitExceeded:
|
||||
text = strongSelf.strings.Login_CodeFloodError
|
||||
case .invalidPhoneNumber:
|
||||
text = strongSelf.strings.Login_InvalidPhoneError
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.strings.Login_PhoneNumberHelp, action: {
|
||||
|
||||
}))
|
||||
case .phoneLimitExceeded:
|
||||
text = strongSelf.strings.Login_PhoneFloodError
|
||||
case .phoneBanned:
|
||||
text = strongSelf.strings.Login_PhoneBannedError
|
||||
case .generic:
|
||||
text = strongSelf.strings.Login_UnknownError
|
||||
case .timeout:
|
||||
text = strongSelf.strings.Login_NetworkError
|
||||
actions.append(TextAlertAction(type: .genericAction, title: strongSelf.strings.ChatSettings_ConnectionType_UseProxy, action: { [weak controller] in
|
||||
guard let strongSelf = self, let controller = controller else {
|
||||
return
|
||||
}
|
||||
|
||||
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
controller.present(proxySettingsController(postbox: strongSelf.account.postbox, network: strongSelf.account.network, mode: .modal, theme: defaultPresentationTheme, strings: strongSelf.strings, updatedPresentationData: .single((defaultPresentationTheme, strongSelf.strings))), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}))
|
||||
}
|
||||
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: actions), in: .window(.root))
|
||||
}
|
||||
}))
|
||||
}
|
||||
@ -236,6 +249,8 @@ public final class AuthorizationSequenceController: NavigationController {
|
||||
text = strongSelf.strings.Login_PhoneBannedError
|
||||
case .generic:
|
||||
text = strongSelf.strings.Login_UnknownError
|
||||
case .timeout:
|
||||
text = strongSelf.strings.Login_NetworkError
|
||||
}
|
||||
|
||||
controller.present(standardTextAlertController(theme: AlertControllerTheme(authTheme: strongSelf.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
|
||||
@ -34,7 +34,7 @@ final class ComposeControllerNode: ASDisplayNode {
|
||||
var openCreateNewSecretChatImpl: (() -> Void)?
|
||||
var openCreateNewChannelImpl: (() -> Void)?
|
||||
|
||||
self.contactListNode = ContactListNode(account: account, presentation: .natural(displaySearch: true, options: [
|
||||
self.contactListNode = ContactListNode(account: account, presentation: .natural(displaySearch: true, ordering: .lastFirst, options: [
|
||||
ContactListAdditionalOption(title: self.presentationData.strings.Compose_NewGroup, icon: generateTintedImage(image: UIImage(bundleImageName: "Contact List/CreateGroupActionIcon"), color: presentationData.theme.list.itemAccentColor), action: {
|
||||
openCreateNewGroupImpl?()
|
||||
}),
|
||||
|
||||
@ -247,7 +247,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
|
||||
}
|
||||
|
||||
private extension PeerIndexNameRepresentation {
|
||||
func isLessThan(other: PeerIndexNameRepresentation) -> ComparisonResult {
|
||||
func isLessThan(other: PeerIndexNameRepresentation, ordering: ContactNameOrdering) -> ComparisonResult {
|
||||
switch self {
|
||||
case let .title(lhsTitle, _):
|
||||
switch other {
|
||||
@ -271,6 +271,15 @@ private extension PeerIndexNameRepresentation {
|
||||
return lastResult
|
||||
}
|
||||
case let .personName(first, last, _, _):
|
||||
switch ordering {
|
||||
case .firstLast:
|
||||
let firstResult = lhsFirst.compare(first)
|
||||
if firstResult == .orderedSame {
|
||||
return lhsLast.compare(last)
|
||||
} else {
|
||||
return firstResult
|
||||
}
|
||||
case .lastFirst:
|
||||
let lastResult = lhsLast.compare(last)
|
||||
if lastResult == .orderedSame {
|
||||
return lhsFirst.compare(first)
|
||||
@ -281,6 +290,7 @@ private extension PeerIndexNameRepresentation {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func contactListNodeEntries(accountPeer: Peer?, peers: [ContactListPeer], presences: [PeerId: PeerPresence], presentation: ContactListPresentation, selectionState: ContactListNodeGroupSelectionState?, theme: PresentationTheme, strings: PresentationStrings, timeFormat: PresentationTimeFormat, disabledPeerIds:Set<PeerId>) -> [ContactListNodeEntry] {
|
||||
var entries: [ContactListNodeEntry] = []
|
||||
@ -316,9 +326,9 @@ private func contactListNodeEntries(accountPeer: Peer?, peers: [ContactListPeer]
|
||||
for i in 0 ..< options.count {
|
||||
entries.append(.option(i, options[i], theme, strings))
|
||||
}
|
||||
case let .natural(displaySearch, options):
|
||||
case let .natural(displaySearch, ordering, options):
|
||||
orderedPeers = peers.sorted(by: { lhs, rhs in
|
||||
let result = lhs.indexName.isLessThan(other: rhs.indexName)
|
||||
let result = lhs.indexName.isLessThan(other: rhs.indexName, ordering: ordering)
|
||||
if result == .orderedSame {
|
||||
if case let .peer(lhsPeer, _) = lhs, case let .peer(rhsPeer, _) = rhs {
|
||||
return lhsPeer.id < rhsPeer.id
|
||||
@ -452,9 +462,14 @@ public struct ContactListAdditionalOption: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
enum ContactNameOrdering {
|
||||
case firstLast
|
||||
case lastFirst
|
||||
}
|
||||
|
||||
enum ContactListPresentation {
|
||||
case orderedByPresence(options: [ContactListAdditionalOption])
|
||||
case natural(displaySearch: Bool, options: [ContactListAdditionalOption])
|
||||
case natural(displaySearch: Bool, ordering: ContactNameOrdering, options: [ContactListAdditionalOption])
|
||||
case search(signal: Signal<String, NoError>, searchDeviceContacts: Bool)
|
||||
}
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
|
||||
self.account = account
|
||||
self.presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.contactListNode = ContactListNode(account: account, presentation: .natural(displaySearch: false, options: options), filters: filters, selectionState: ContactListNodeGroupSelectionState())
|
||||
self.contactListNode = ContactListNode(account: account, presentation: .natural(displaySearch: false, ordering: .lastFirst, options: options), filters: filters, selectionState: ContactListNodeGroupSelectionState())
|
||||
self.tokenListNode = EditableTokenListNode(theme: EditableTokenListNodeTheme(backgroundColor: self.presentationData.theme.rootController.navigationBar.backgroundColor, separatorColor: self.presentationData.theme.rootController.navigationBar.separatorColor, placeholderTextColor: self.presentationData.theme.list.itemPlaceholderTextColor, primaryTextColor: self.presentationData.theme.list.itemPrimaryTextColor, selectedTextColor: self.presentationData.theme.list.itemAccentColor, keyboardColor: self.presentationData.theme.chatList.searchBarKeyboardColor), placeholder: self.presentationData.strings.Compose_TokenListPlaceholder)
|
||||
|
||||
super.init()
|
||||
|
||||
@ -38,7 +38,7 @@ final class ContactSelectionControllerNode: ASDisplayNode {
|
||||
self.account = account
|
||||
self.displayDeviceContacts = displayDeviceContacts
|
||||
|
||||
self.contactListNode = ContactListNode(account: account, presentation: .natural(displaySearch: true, options: options))
|
||||
self.contactListNode = ContactListNode(account: account, presentation: .natural(displaySearch: true, ordering: .lastFirst, options: options))
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
|
||||
|
||||
@ -94,13 +94,18 @@ private let internalMimeTypes = Set<String>([
|
||||
"application/text"
|
||||
])
|
||||
|
||||
private var intermalMimePrefixes: [String] = [
|
||||
private let internalMimePrefixes: [String] = [
|
||||
"image/",
|
||||
"text/",
|
||||
"application/vnd.ms-",
|
||||
"video/"
|
||||
"application/vnd.ms-"
|
||||
]
|
||||
|
||||
private let supportedVideoMimeTypes = Set<String>([
|
||||
"video/mp4",
|
||||
"video/mpeg4",
|
||||
"video/mov"
|
||||
])
|
||||
|
||||
func internalDocumentItemSupportsMimeType(_ type: String, fileName: String?) -> Bool {
|
||||
if let fileName = fileName {
|
||||
let ext = (fileName as NSString).pathExtension
|
||||
@ -112,7 +117,10 @@ func internalDocumentItemSupportsMimeType(_ type: String, fileName: String?) ->
|
||||
if internalMimeTypes.contains(type) {
|
||||
return true
|
||||
}
|
||||
for prefix in intermalMimePrefixes {
|
||||
if supportedVideoMimeTypes.contains(type) {
|
||||
return true
|
||||
}
|
||||
for prefix in internalMimePrefixes {
|
||||
if type.hasPrefix(prefix) {
|
||||
return true
|
||||
}
|
||||
@ -127,7 +135,7 @@ func galleryItemForEntry(account: Account, theme: PresentationTheme, strings: Pr
|
||||
if let _ = media as? TelegramMediaImage {
|
||||
return ChatImageGalleryItem(account: account, theme: theme, strings: strings, message: message, location: location)
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
if file.isVideo || file.mimeType.hasPrefix("video/") {
|
||||
if file.isVideo || supportedVideoMimeTypes.contains(file.mimeType) {
|
||||
let content: UniversalVideoContent
|
||||
if file.isAnimated {
|
||||
content = NativeVideoContent(id: .message(message.id, message.stableId + 1, file.fileId), fileReference: .message(message: MessageReference(message), media: file), streamVideo: streamVideos, loopVideo: true)
|
||||
|
||||
@ -186,16 +186,20 @@ class ItemListController<Entry: ItemListNodeEntry>: ViewController {
|
||||
|
||||
var willDisappear: ((Bool) -> Void)?
|
||||
|
||||
init(account: Account, state: Signal<(ItemListControllerState, (ItemListNodeState<Entry>, Entry.ItemGenerationArguments)), NoError>, tabBarItem: Signal<ItemListControllerTabBarItem, NoError>? = nil) {
|
||||
convenience init(account: Account, state: Signal<(ItemListControllerState, (ItemListNodeState<Entry>, Entry.ItemGenerationArguments)), NoError>, tabBarItem: Signal<ItemListControllerTabBarItem, NoError>? = nil) {
|
||||
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
||||
self.init(theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: account.telegramApplicationContext.presentationData |> map { ($0.theme, $0.strings) }, state: state, tabBarItem: tabBarItem)
|
||||
}
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>, state: Signal<(ItemListControllerState, (ItemListNodeState<Entry>, Entry.ItemGenerationArguments)), NoError>, tabBarItem: Signal<ItemListControllerTabBarItem, NoError>?) {
|
||||
self.state = state
|
||||
|
||||
let presentationData = (account.telegramApplicationContext.currentPresentationData.with { $0 })
|
||||
self.theme = presentationData.theme
|
||||
self.strings = presentationData.strings
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: presentationData))
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: theme), strings: NavigationBarStrings(presentationStrings: strings)))
|
||||
|
||||
self.statusBar.statusBarStyle = (account.telegramApplicationContext.currentPresentationData.with { $0 }).theme.rootController.statusBar.style.style
|
||||
self.statusBar.statusBarStyle = theme.rootController.statusBar.style.style
|
||||
|
||||
self.scrollToTop = { [weak self] in
|
||||
(self?.displayNode as! ItemListControllerNode<Entry>).scrollToTop()
|
||||
|
||||
@ -315,7 +315,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
self.recursivelyEnsureDisplaySynchronously(true)
|
||||
contactListNode.enableUpdates = true
|
||||
} else {
|
||||
let contactListNode = ContactListNode(account: account, presentation: .natural(displaySearch: true, options: []))
|
||||
let contactListNode = ContactListNode(account: account, presentation: .natural(displaySearch: true, ordering: .lastFirst, options: []))
|
||||
self.contactListNode = contactListNode
|
||||
contactListNode.enableUpdates = true
|
||||
contactListNode.activateSearch = { [weak self] in
|
||||
|
||||
@ -185,7 +185,7 @@ public func currentPresentationDataAndSettings(postbox: Postbox) -> Signal<Initi
|
||||
} else {
|
||||
stringsValue = defaultPresentationStrings
|
||||
}
|
||||
let timeFormat: PresentationTimeFormat = currentTimeFormat()
|
||||
let timeFormat = currentTimeFormat()
|
||||
return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: themeValue, chatWallpaper: effectiveChatWallpaper, fontSize: themeSettings.fontSize, timeFormat: timeFormat), automaticMediaDownloadSettings: automaticMediaDownloadSettings, loggingSettings: loggingSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, experimentalUISettings: experimentalUISettings)
|
||||
}
|
||||
}
|
||||
@ -313,7 +313,7 @@ public func updatedPresentationData(postbox: Postbox) -> Signal<PresentationData
|
||||
stringsValue = defaultPresentationStrings
|
||||
}
|
||||
|
||||
let timeFormat: PresentationTimeFormat = currentTimeFormat()
|
||||
let timeFormat = currentTimeFormat()
|
||||
|
||||
return PresentationData(strings: stringsValue, theme: themeValue, chatWallpaper: effectiveChatWallpaper, fontSize: themeSettings.fontSize, timeFormat: timeFormat)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -204,12 +204,12 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
private func proxySettingsControllerEntries(presentationData: PresentationData, state: ProxySettingsControllerState, proxySettings: ProxySettings, statuses: [ProxyServerSettings: ProxyServerStatus], connectionStatus: ConnectionStatus) -> [ProxySettingsControllerEntry] {
|
||||
private func proxySettingsControllerEntries(theme: PresentationTheme, strings: PresentationStrings, state: ProxySettingsControllerState, proxySettings: ProxySettings, statuses: [ProxyServerSettings: ProxyServerStatus], connectionStatus: ConnectionStatus) -> [ProxySettingsControllerEntry] {
|
||||
var entries: [ProxySettingsControllerEntry] = []
|
||||
|
||||
entries.append(.enabled(presentationData.theme, presentationData.strings.ChatSettings_ConnectionType_UseProxy, proxySettings.enabled, proxySettings.servers.isEmpty))
|
||||
entries.append(.serversHeader(presentationData.theme, presentationData.strings.SocksProxySetup_SavedProxies))
|
||||
entries.append(.addServer(presentationData.theme, presentationData.strings.SocksProxySetup_AddProxy, state.editing))
|
||||
entries.append(.enabled(theme, strings.ChatSettings_ConnectionType_UseProxy, proxySettings.enabled, proxySettings.servers.isEmpty))
|
||||
entries.append(.serversHeader(theme, strings.SocksProxySetup_SavedProxies))
|
||||
entries.append(.addServer(theme, strings.SocksProxySetup_AddProxy, state.editing))
|
||||
var index = 0
|
||||
for server in proxySettings.servers {
|
||||
let status: ProxyServerStatus = statuses[server] ?? .checking
|
||||
@ -217,35 +217,35 @@ private func proxySettingsControllerEntries(presentationData: PresentationData,
|
||||
if proxySettings.enabled && server == proxySettings.activeServer {
|
||||
switch connectionStatus {
|
||||
case .waitingForNetwork:
|
||||
displayStatus = DisplayProxyServerStatus(activity: true, text: presentationData.strings.State_WaitingForNetwork.lowercased(), textActive: false)
|
||||
displayStatus = DisplayProxyServerStatus(activity: true, text: strings.State_WaitingForNetwork.lowercased(), textActive: false)
|
||||
case .connecting, .updating:
|
||||
displayStatus = DisplayProxyServerStatus(activity: true, text: presentationData.strings.SocksProxySetup_ProxyStatusConnecting, textActive: false)
|
||||
displayStatus = DisplayProxyServerStatus(activity: true, text: strings.SocksProxySetup_ProxyStatusConnecting, textActive: false)
|
||||
case .online:
|
||||
var text = presentationData.strings.SocksProxySetup_ProxyStatusConnected
|
||||
var text = strings.SocksProxySetup_ProxyStatusConnected
|
||||
if case let .available(rtt) = status {
|
||||
let pingTime: Int = Int(rtt * 1000.0)
|
||||
text = text + ", \(presentationData.strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").0)"
|
||||
text = text + ", \(strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").0)"
|
||||
}
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: text, textActive: true)
|
||||
}
|
||||
} else {
|
||||
switch status {
|
||||
case .notAvailable:
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: presentationData.strings.SocksProxySetup_ProxyStatusUnavailable, textActive: false)
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: strings.SocksProxySetup_ProxyStatusUnavailable, textActive: false)
|
||||
case .checking:
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: presentationData.strings.SocksProxySetup_ProxyStatusChecking, textActive: false)
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: strings.SocksProxySetup_ProxyStatusChecking, textActive: false)
|
||||
case let .available(rtt):
|
||||
let pingTime: Int = Int(rtt * 1000.0)
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: presentationData.strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").0, textActive: false)
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").0, textActive: false)
|
||||
}
|
||||
}
|
||||
entries.append(.server(index, presentationData.theme, presentationData.strings, server, server == proxySettings.activeServer, displayStatus, ProxySettingsServerItemEditing(editable: true, editing: state.editing, revealed: state.revealedServer == server), proxySettings.enabled))
|
||||
entries.append(.server(index, theme, strings, server, server == proxySettings.activeServer, displayStatus, ProxySettingsServerItemEditing(editable: true, editing: state.editing, revealed: state.revealedServer == server), proxySettings.enabled))
|
||||
index += 1
|
||||
}
|
||||
|
||||
if let activeServer = proxySettings.activeServer, case .socks5 = activeServer.connection {
|
||||
entries.append(.useForCalls(presentationData.theme, presentationData.strings.SocksProxySetup_UseForCalls, proxySettings.useForCalls))
|
||||
entries.append(.useForCallsInfo(presentationData.theme, presentationData.strings.SocksProxySetup_UseForCallsHelp))
|
||||
entries.append(.useForCalls(theme, strings.SocksProxySetup_UseForCalls, proxySettings.useForCalls))
|
||||
entries.append(.useForCallsInfo(theme, strings.SocksProxySetup_UseForCallsHelp))
|
||||
}
|
||||
|
||||
return entries
|
||||
@ -256,8 +256,19 @@ private struct ProxySettingsControllerState: Equatable {
|
||||
var revealedServer: ProxyServerSettings? = nil
|
||||
}
|
||||
|
||||
public func proxySettingsController(account: Account) -> ViewController {
|
||||
public enum ProxySettingsControllerMode {
|
||||
case `default`
|
||||
case modal
|
||||
}
|
||||
|
||||
public func proxySettingsController(account: Account, mode: ProxySettingsControllerMode = .default) -> ViewController {
|
||||
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
||||
return proxySettingsController(postbox: account.postbox, network: account.network, mode: mode, theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: account.telegramApplicationContext.presentationData |> map { ($0.theme, $0.strings) })
|
||||
}
|
||||
|
||||
public func proxySettingsController(postbox: Postbox, network: Network, mode: ProxySettingsControllerMode, theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>) -> ViewController {
|
||||
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
|
||||
var dismissImpl: (() -> Void)?
|
||||
let stateValue = Atomic(value: ProxySettingsControllerState())
|
||||
let statePromise = ValuePromise<ProxySettingsControllerState>(stateValue.with { $0 })
|
||||
let updateState: ((ProxySettingsControllerState) -> ProxySettingsControllerState) -> Void = { f in
|
||||
@ -275,15 +286,15 @@ public func proxySettingsController(account: Account) -> ViewController {
|
||||
}
|
||||
|
||||
let arguments = ProxySettingsControllerArguments(toggleEnabled: { value in
|
||||
let _ = updateProxySettingsInteractively(postbox: account.postbox, network: account.network, { current in
|
||||
let _ = updateProxySettingsInteractively(postbox: postbox, network: network, { current in
|
||||
var current = current
|
||||
current.enabled = value
|
||||
return current
|
||||
}).start()
|
||||
}, addNewServer: {
|
||||
presentControllerImpl?(proxyServerSettingsController(account: account, currentSettings: nil), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
presentControllerImpl?(proxyServerSettingsController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, postbox: postbox, network: network, currentSettings: nil), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}, activateServer: { server in
|
||||
let _ = updateProxySettingsInteractively(postbox: account.postbox, network: account.network, { current in
|
||||
let _ = updateProxySettingsInteractively(postbox: postbox, network: network, { current in
|
||||
var current = current
|
||||
if current.activeServer != server {
|
||||
if let _ = current.servers.index(of: server) {
|
||||
@ -294,9 +305,9 @@ public func proxySettingsController(account: Account) -> ViewController {
|
||||
return current
|
||||
}).start()
|
||||
}, editServer: { server in
|
||||
presentControllerImpl?(proxyServerSettingsController(account: account, currentSettings: server), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
presentControllerImpl?(proxyServerSettingsController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, postbox: postbox, network: network, currentSettings: server), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}, removeServer: { server in
|
||||
let _ = updateProxySettingsInteractively(postbox: account.postbox, network: account.network, { current in
|
||||
let _ = updateProxySettingsInteractively(postbox: postbox, network: network, { current in
|
||||
var current = current
|
||||
if let index = current.servers.index(of: server) {
|
||||
current.servers.remove(at: index)
|
||||
@ -316,7 +327,7 @@ public func proxySettingsController(account: Account) -> ViewController {
|
||||
return state
|
||||
}
|
||||
}, toggleUseForCalls: { value in
|
||||
let _ = updateProxySettingsInteractively(postbox: account.postbox, network: account.network, { current in
|
||||
let _ = updateProxySettingsInteractively(postbox: postbox, network: network, { current in
|
||||
var current = current
|
||||
current.useForCalls = value
|
||||
return current
|
||||
@ -324,7 +335,7 @@ public func proxySettingsController(account: Account) -> ViewController {
|
||||
})
|
||||
|
||||
let proxySettings = Promise<ProxySettings>()
|
||||
proxySettings.set(account.postbox.preferencesView(keys: [PreferencesKeys.proxySettings])
|
||||
proxySettings.set(postbox.preferencesView(keys: [PreferencesKeys.proxySettings])
|
||||
|> map { preferencesView -> ProxySettings in
|
||||
if let value = preferencesView.values[PreferencesKeys.proxySettings] as? ProxySettings {
|
||||
return value
|
||||
@ -333,18 +344,25 @@ public func proxySettingsController(account: Account) -> ViewController {
|
||||
}
|
||||
})
|
||||
|
||||
let statusesContext = ProxyServersStatuses(network: account.network, servers: proxySettings.get()
|
||||
let statusesContext = ProxyServersStatuses(network: network, servers: proxySettings.get()
|
||||
|> map { proxySettings -> [ProxyServerSettings] in
|
||||
return proxySettings.servers
|
||||
})
|
||||
|
||||
let signal = combineLatest((account.applicationContext as! TelegramApplicationContext).presentationData, statePromise.get(), proxySettings.get(), statusesContext.statuses(), account.network.connectionStatus)
|
||||
|> map { presentationData, state, proxySettings, statuses, connectionStatus -> (ItemListControllerState, (ItemListNodeState<ProxySettingsControllerEntry>, ProxySettingsControllerEntry.ItemGenerationArguments)) in
|
||||
let signal = combineLatest(updatedPresentationData, statePromise.get(), proxySettings.get(), statusesContext.statuses(), network.connectionStatus)
|
||||
|> map { themeAndStrings, state, proxySettings, statuses, connectionStatus -> (ItemListControllerState, (ItemListNodeState<ProxySettingsControllerEntry>, ProxySettingsControllerEntry.ItemGenerationArguments)) in
|
||||
var leftNavigationButton: ItemListNavigationButton?
|
||||
if case .modal = mode {
|
||||
leftNavigationButton = ItemListNavigationButton(content: .text(themeAndStrings.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||
dismissImpl?()
|
||||
})
|
||||
}
|
||||
|
||||
let rightNavigationButton: ItemListNavigationButton?
|
||||
if proxySettings.servers.isEmpty {
|
||||
rightNavigationButton = nil
|
||||
} else if state.editing {
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: true, action: {
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(strings.Common_Done), style: .bold, enabled: true, action: {
|
||||
updateState { state in
|
||||
var state = state
|
||||
state.editing = false
|
||||
@ -352,7 +370,7 @@ public func proxySettingsController(account: Account) -> ViewController {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Edit), style: .regular, enabled: true, action: {
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(strings.Common_Edit), style: .regular, enabled: true, action: {
|
||||
updateState { state in
|
||||
var state = state
|
||||
state.editing = true
|
||||
@ -361,16 +379,19 @@ public func proxySettingsController(account: Account) -> ViewController {
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.SocksProxySetup_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: proxySettingsControllerEntries(presentationData: presentationData, state: state, proxySettings: proxySettings, statuses: statuses, connectionStatus: connectionStatus), style: .blocks)
|
||||
let controllerState = ItemListControllerState(theme: themeAndStrings.0, title: .text(themeAndStrings.1.SocksProxySetup_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: themeAndStrings.1.Common_Back))
|
||||
let listState = ItemListNodeState(entries: proxySettingsControllerEntries(theme: themeAndStrings.0, strings: themeAndStrings.1, state: state, proxySettings: proxySettings, statuses: statuses, connectionStatus: connectionStatus), style: .blocks)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
||||
let controller = ItemListController(account: account, state: signal)
|
||||
let controller = ItemListController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, state: signal, tabBarItem: nil)
|
||||
presentControllerImpl = { [weak controller] c, a in
|
||||
controller?.present(c, in: .window(.root), with: a)
|
||||
}
|
||||
dismissImpl = { [weak controller] in
|
||||
controller?.dismiss()
|
||||
}
|
||||
controller.reorderEntry = { fromIndex, toIndex, entries in
|
||||
let fromEntry = entries[fromIndex]
|
||||
guard case let .server(_, _, _, fromServer, _, _, _, _) = fromEntry else {
|
||||
@ -394,7 +415,7 @@ public func proxySettingsController(account: Account) -> ViewController {
|
||||
afterAll = true
|
||||
}
|
||||
|
||||
let _ = updateProxySettingsInteractively(postbox: account.postbox, network: account.network, { current in
|
||||
let _ = updateProxySettingsInteractively(postbox: postbox, network: network, { current in
|
||||
var current = current
|
||||
if let index = current.servers.index(of: fromServer) {
|
||||
current.servers.remove(at: index)
|
||||
|
||||
@ -8,14 +8,17 @@ import MtProtoKitDynamic
|
||||
private final class proxyServerSettingsControllerArguments {
|
||||
let updateState: ((ProxyServerSettingsControllerState) -> ProxyServerSettingsControllerState) -> Void
|
||||
let share: () -> Void
|
||||
let usePasteboardSettings: () -> Void
|
||||
|
||||
init(updateState: @escaping ((ProxyServerSettingsControllerState) -> ProxyServerSettingsControllerState) -> Void, share: @escaping () -> Void) {
|
||||
init(updateState: @escaping ((ProxyServerSettingsControllerState) -> ProxyServerSettingsControllerState) -> Void, share: @escaping () -> Void, usePasteboardSettings: @escaping () -> Void) {
|
||||
self.updateState = updateState
|
||||
self.share = share
|
||||
self.usePasteboardSettings = usePasteboardSettings
|
||||
}
|
||||
}
|
||||
|
||||
private enum ProxySettingsSection: Int32 {
|
||||
case pasteboard
|
||||
case mode
|
||||
case connection
|
||||
case credentials
|
||||
@ -23,6 +26,9 @@ private enum ProxySettingsSection: Int32 {
|
||||
}
|
||||
|
||||
private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
case usePasteboardSettings(PresentationTheme, String)
|
||||
case usePasteboardInfo(PresentationTheme, String)
|
||||
|
||||
case modeSocks5(PresentationTheme, String, Bool)
|
||||
case modeMtp(PresentationTheme, String, Bool)
|
||||
|
||||
@ -39,6 +45,8 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
|
||||
var section: ItemListSectionId {
|
||||
switch self {
|
||||
case .usePasteboardSettings, .usePasteboardInfo:
|
||||
return ProxySettingsSection.pasteboard.rawValue
|
||||
case .modeSocks5, .modeMtp:
|
||||
return ProxySettingsSection.mode.rawValue
|
||||
case .connectionHeader, .connectionServer, .connectionPort:
|
||||
@ -52,91 +60,30 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
|
||||
var stableId: Int32 {
|
||||
switch self {
|
||||
case .modeSocks5:
|
||||
case .usePasteboardSettings:
|
||||
return 0
|
||||
case .modeMtp:
|
||||
case .usePasteboardInfo:
|
||||
return 1
|
||||
case .connectionHeader:
|
||||
case .modeSocks5:
|
||||
return 2
|
||||
case .connectionServer:
|
||||
case .modeMtp:
|
||||
return 3
|
||||
case .connectionPort:
|
||||
case .connectionHeader:
|
||||
return 4
|
||||
case .credentialsHeader:
|
||||
case .connectionServer:
|
||||
return 5
|
||||
case .credentialsUsername:
|
||||
case .connectionPort:
|
||||
return 6
|
||||
case .credentialsPassword:
|
||||
case .credentialsHeader:
|
||||
return 7
|
||||
case .credentialsSecret:
|
||||
case .credentialsUsername:
|
||||
return 8
|
||||
case .share:
|
||||
case .credentialsPassword:
|
||||
return 9
|
||||
}
|
||||
}
|
||||
|
||||
static func ==(lhs: ProxySettingsEntry, rhs: ProxySettingsEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .modeSocks5(lhsTheme, lhsText, lhsValue):
|
||||
if case let .modeSocks5(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .modeMtp(lhsTheme, lhsText, lhsValue):
|
||||
if case let .modeMtp(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .connectionHeader(lhsTheme, lhsText):
|
||||
if case let .connectionHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .connectionServer(lhsTheme, lhsText, lhsValue):
|
||||
if case let .connectionServer(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .connectionPort(lhsTheme, lhsText, lhsValue):
|
||||
if case let .connectionPort(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .credentialsHeader(lhsTheme, lhsText):
|
||||
if case let .credentialsHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .credentialsUsername(lhsTheme, lhsText, lhsValue):
|
||||
if case let .credentialsUsername(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .credentialsPassword(lhsTheme, lhsText, lhsValue):
|
||||
if case let .credentialsPassword(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .credentialsSecret(lhsTheme, lhsText, lhsValue):
|
||||
if case let .credentialsSecret(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .share(lhsTheme, lhsText, lhsValue):
|
||||
if case let .share(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .credentialsSecret:
|
||||
return 10
|
||||
case .share:
|
||||
return 11
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,6 +93,12 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
|
||||
func item(_ arguments: proxyServerSettingsControllerArguments) -> ListViewItem {
|
||||
switch self {
|
||||
case let .usePasteboardSettings(theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.usePasteboardSettings()
|
||||
})
|
||||
case let .usePasteboardInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
case let .modeSocks5(theme, text, value):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateState { state in
|
||||
@ -250,9 +203,13 @@ private struct ProxyServerSettingsControllerState: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private func proxyServerSettingsControllerEntries(presentationData: PresentationData, state: ProxyServerSettingsControllerState) -> [ProxySettingsEntry] {
|
||||
private func proxyServerSettingsControllerEntries(presentationData: (theme: PresentationTheme, strings: PresentationStrings), state: ProxyServerSettingsControllerState, pasteboardSettings: ProxyServerSettings?) -> [ProxySettingsEntry] {
|
||||
var entries: [ProxySettingsEntry] = []
|
||||
|
||||
if let _ = pasteboardSettings {
|
||||
entries.append(.usePasteboardSettings(presentationData.theme, presentationData.strings.SocksProxySetup_PasteFromClipboard))
|
||||
}
|
||||
|
||||
entries.append(.modeSocks5(presentationData.theme, presentationData.strings.SocksProxySetup_ProxySocks5, state.mode == .socks5))
|
||||
entries.append(.modeMtp(presentationData.theme, presentationData.strings.SocksProxySetup_ProxyTelegram, state.mode == .mtp))
|
||||
|
||||
@ -275,11 +232,12 @@ private func proxyServerSettingsControllerEntries(presentationData: Presentation
|
||||
return entries
|
||||
}
|
||||
|
||||
func proxyServerSettingsController(account: Account, currentSettings: ProxyServerSettings?) -> ViewController {
|
||||
func proxyServerSettingsController(theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>, postbox: Postbox, network: Network, currentSettings: ProxyServerSettings?) -> ViewController {
|
||||
var currentMode: ProxyServerSettingsControllerMode = .socks5
|
||||
var currentUsername: String?
|
||||
var currentPassword: String?
|
||||
var currentSecret: String?
|
||||
var pasteboardSettings: ProxyServerSettings?
|
||||
if let currentSettings = currentSettings {
|
||||
switch currentSettings.connection {
|
||||
case let .socks5(username, password):
|
||||
@ -290,7 +248,16 @@ func proxyServerSettingsController(account: Account, currentSettings: ProxyServe
|
||||
currentSecret = hexString(secret)
|
||||
currentMode = .mtp
|
||||
}
|
||||
} else {
|
||||
if let proxy = parseProxyUrl(UIPasteboard.general.string ?? "") {
|
||||
if let secret = proxy.secret, secret.count == 16 || (secret.count == 17 && MTSocksProxySettings.secretSupportsExtendedPadding(secret)) {
|
||||
pasteboardSettings = ProxyServerSettings(host: proxy.host, port: proxy.port, connection: .mtp(secret: secret))
|
||||
} else {
|
||||
pasteboardSettings = ProxyServerSettings(host: proxy.host, port: proxy.port, connection: .socks5(username: proxy.username, password: proxy.password))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let initialState = ProxyServerSettingsControllerState(mode: currentMode, host: currentSettings?.host ?? "", port: (currentSettings?.port).flatMap { "\($0)" } ?? "", username: currentUsername ?? "", password: currentPassword ?? "", secret: currentSecret ?? "")
|
||||
let stateValue = Atomic(value: initialState)
|
||||
let statePromise = ValuePromise(initialState, ignoreRepeated: true)
|
||||
@ -306,7 +273,7 @@ func proxyServerSettingsController(account: Account, currentSettings: ProxyServe
|
||||
}, share: {
|
||||
let state = stateValue.with { $0 }
|
||||
if state.isComplete {
|
||||
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
||||
let presentationData: (theme: PresentationTheme, strings: PresentationStrings) = (theme, strings)
|
||||
var result: String
|
||||
switch state.mode {
|
||||
case .mtp:
|
||||
@ -323,9 +290,28 @@ func proxyServerSettingsController(account: Account, currentSettings: ProxyServe
|
||||
|
||||
presentImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: presentationData.strings.Username_LinkCopied, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
}
|
||||
}, usePasteboardSettings: {
|
||||
if let pasteboardSettings = pasteboardSettings {
|
||||
updateState { state in
|
||||
var state = state
|
||||
state.host = pasteboardSettings.host
|
||||
state.port = "\(pasteboardSettings.port)"
|
||||
switch pasteboardSettings.connection {
|
||||
case let .socks5(username, password):
|
||||
state.mode = .socks5
|
||||
state.username = username ?? ""
|
||||
state.password = password ?? ""
|
||||
case let .mtp(secret):
|
||||
state.mode = .mtp
|
||||
state.secret = hexString(secret)
|
||||
}
|
||||
return state
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let signal = combineLatest((account.applicationContext as! TelegramApplicationContext).presentationData, statePromise.get()) |> deliverOnMainQueue
|
||||
let signal = combineLatest(updatedPresentationData, statePromise.get())
|
||||
|> deliverOnMainQueue
|
||||
|> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState<ProxySettingsEntry>, ProxySettingsEntry.ItemGenerationArguments)) in
|
||||
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||
dismissImpl?()
|
||||
@ -350,7 +336,7 @@ func proxyServerSettingsController(account: Account, currentSettings: ProxyServe
|
||||
}
|
||||
}
|
||||
if let proxyServerSettings = proxyServerSettings {
|
||||
let _ = (updateProxySettingsInteractively(postbox: account.postbox, network: account.network, { settings in
|
||||
let _ = (updateProxySettingsInteractively(postbox: postbox, network: network, { settings in
|
||||
var settings = settings
|
||||
if let currentSettings = currentSettings {
|
||||
if let index = settings.servers.index(of: currentSettings) {
|
||||
@ -373,12 +359,12 @@ func proxyServerSettingsController(account: Account, currentSettings: ProxyServe
|
||||
})
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.SocksProxySetup_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: proxyServerSettingsControllerEntries(presentationData: presentationData, state: state), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: proxyServerSettingsControllerEntries(presentationData: presentationData, state: state, pasteboardSettings: pasteboardSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
||||
let controller = ItemListController(account: account, state: signal)
|
||||
let controller = ItemListController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, state: signal, tabBarItem: nil)
|
||||
presentImpl = { [weak controller] c, d in
|
||||
controller?.present(c, in: .window(.root), with: d)
|
||||
}
|
||||
|
||||
58
TelegramUI/TwoStepVerificationEmptyItem.swift
Normal file
58
TelegramUI/TwoStepVerificationEmptyItem.swift
Normal file
@ -0,0 +1,58 @@
|
||||
import Foundation
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
|
||||
final class TwoStepVerificationEmptyItem: ItemListControllerEmptyStateItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let setup: () -> Void
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, setup: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.setup = setup
|
||||
}
|
||||
|
||||
func isEqual(to: ItemListControllerEmptyStateItem) -> Bool {
|
||||
return to is TwoStepVerificationEmptyItem
|
||||
}
|
||||
|
||||
func node(current: ItemListControllerEmptyStateItemNode?) -> ItemListControllerEmptyStateItemNode {
|
||||
if let current = current as? TwoStepVerificationEmptyItemNode {
|
||||
current.item = self
|
||||
return current
|
||||
} else {
|
||||
return TwoStepVerificationEmptyItemNode(item: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class TwoStepVerificationEmptyItemNode: ItemListControllerEmptyStateItemNode {
|
||||
var item: TwoStepVerificationEmptyItem {
|
||||
didSet {
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.updateLayout(layout: layout, navigationBarHeight: navigationHeight, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var validLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
init(item: TwoStepVerificationEmptyItem) {
|
||||
self.item = item
|
||||
|
||||
super.init()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (layout, navigationBarHeight)
|
||||
|
||||
var insets = layout.insets(options: [.statusBar])
|
||||
insets.top += navigationBarHeight
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -139,6 +139,28 @@ private func resolveInternalUrl(account: Account, url: ParsedInternalUrl) -> Sig
|
||||
}
|
||||
}
|
||||
|
||||
func parseProxyUrl(_ url: String) -> (host: String, port: Int32, username: String?, password: String?, secret: Data?)? {
|
||||
let schemes = ["http://", "https://", ""]
|
||||
let baseTelegramMePaths = ["telegram.me", "t.me"]
|
||||
for basePath in baseTelegramMePaths {
|
||||
for scheme in schemes {
|
||||
let basePrefix = scheme + basePath + "/"
|
||||
if url.lowercased().hasPrefix(basePrefix) {
|
||||
if let internalUrl = parseInternalUrl(query: String(url[basePrefix.endIndex...])), case let .proxy(proxy) = internalUrl {
|
||||
return (proxy.host, proxy.port, proxy.username, proxy.password, proxy.secret)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let parsedUrl = URL(string: url), parsedUrl.scheme == "tg", let host = parsedUrl.host, let query = parsedUrl.query {
|
||||
if let internalUrl = parseInternalUrl(query: host + "?" + query), case let .proxy(proxy) = internalUrl {
|
||||
return (proxy.host, proxy.port, proxy.username, proxy.password, proxy.secret)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resolveUrl(account: Account, url: String) -> Signal<ResolvedUrl, NoError> {
|
||||
let schemes = ["http://", "https://", ""]
|
||||
let baseTelegramMePaths = ["telegram.me", "t.me"]
|
||||
|
||||
2
third-party/RMIntro/core/animations.c
vendored
2
third-party/RMIntro/core/animations.c
vendored
@ -2090,7 +2090,7 @@ void on_draw_frame() {
|
||||
|
||||
telegram_sphere.params.alpha = t(0, 1, 0, duration_const*.8, Linear);
|
||||
|
||||
scale = 1.01;
|
||||
scale = 1.005;
|
||||
|
||||
telegram_sphere.params.scale = xyzMake(scale, scale, 1);
|
||||
draw_textured_shape(&telegram_sphere, main_matrix, NORMAL);
|
||||
|
||||
@ -20,9 +20,6 @@
|
||||
#import <LegacyComponents/LegacyComponents.h>
|
||||
#import <LegacyComponents/TGAnimationUtils.h>
|
||||
|
||||
#define TGLog NSLog
|
||||
#define TGLocalized(x) NSLocalizedString(x, @"")
|
||||
|
||||
typedef enum {
|
||||
Inch35 = 0,
|
||||
Inch4 = 1,
|
||||
@ -94,6 +91,7 @@ static void TGDispatchOnMainThread(dispatch_block_t block) {
|
||||
TGSuggestedLocalization *_alternativeLocalizationInfo;
|
||||
|
||||
SVariable *_alternativeLocalization;
|
||||
NSDictionary<NSString *, NSString *> *_englishStrings;
|
||||
}
|
||||
@end
|
||||
|
||||
@ -116,8 +114,40 @@ static void TGDispatchOnMainThread(dispatch_block_t block) {
|
||||
|
||||
self.automaticallyAdjustsScrollViewInsets = false;
|
||||
|
||||
_headlines = @[ TGLocalized(@"Tour.Title1"), TGLocalized(@"Tour.Title2"), TGLocalized(@"Tour.Title6"), TGLocalized(@"Tour.Title3"), TGLocalized(@"Tour.Title4"), TGLocalized(@"Tour.Title5")];
|
||||
_descriptions = @[TGLocalized(@"Tour.Text1"), TGLocalized(@"Tour.Text2"), TGLocalized(@"Tour.Text6"), TGLocalized(@"Tour.Text3"), TGLocalized(@"Tour.Text4"), TGLocalized(@"Tour.Text5")];
|
||||
NSArray<NSString *> *stringKeys = @[
|
||||
@"Tour.Title1",
|
||||
@"Tour.Title2",
|
||||
@"Tour.Title3",
|
||||
@"Tour.Title4",
|
||||
@"Tour.Title5",
|
||||
@"Tour.Title6",
|
||||
@"Tour.Text1",
|
||||
@"Tour.Text2",
|
||||
@"Tour.Text3",
|
||||
@"Tour.Text4",
|
||||
@"Tour.Text5",
|
||||
@"Tour.Text6",
|
||||
@"Tour.StartButton"
|
||||
];
|
||||
|
||||
NSMutableDictionary *englishStrings = [[NSMutableDictionary alloc] init];
|
||||
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"]];
|
||||
for (NSString *key in stringKeys) {
|
||||
if (bundle != nil) {
|
||||
NSString *value = [bundle localizedStringForKey:key value:key table:nil];
|
||||
if (value != nil) {
|
||||
englishStrings[key] = value;
|
||||
} else {
|
||||
englishStrings[key] = key;
|
||||
}
|
||||
} else {
|
||||
englishStrings[key] = key;
|
||||
}
|
||||
}
|
||||
_englishStrings = englishStrings;
|
||||
|
||||
_headlines = @[ _englishStrings[@"Tour.Title1"], _englishStrings[@"Tour.Title2"], _englishStrings[@"Tour.Title6"], _englishStrings[@"Tour.Title3"], _englishStrings[@"Tour.Title4"], _englishStrings[@"Tour.Title5"]];
|
||||
_descriptions = @[_englishStrings[@"Tour.Text1"], _englishStrings[@"Tour.Text2"], _englishStrings[@"Tour.Text6"], _englishStrings[@"Tour.Text3"], _englishStrings[@"Tour.Text4"], _englishStrings[@"Tour.Text5"]];
|
||||
|
||||
__weak RMIntroViewController *weakSelf = self;
|
||||
_didEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil queue:nil usingBlock:^(__unused NSNotification *notification)
|
||||
@ -288,7 +318,7 @@ static void TGDispatchOnMainThread(dispatch_block_t block) {
|
||||
|
||||
_startButton = [[UIButton alloc] init];
|
||||
_startButton.adjustsImageWhenDisabled = false;
|
||||
[_startButton setTitle:TGLocalized(@"Tour.StartButton") forState:UIControlStateNormal];
|
||||
[_startButton setTitle:_englishStrings[@"Tour.StartButton"] forState:UIControlStateNormal];
|
||||
[_startButton.titleLabel setFont:TGMediumSystemFontOfSize(20.0f)];
|
||||
[_startButton setTitleColor:_backgroundColor forState:UIControlStateNormal];
|
||||
static UIImage *buttonBackgroundImage = nil;
|
||||
|
||||
@ -15,7 +15,7 @@ GLuint setup_texture(NSString *fileName)
|
||||
CGImageRef spriteImage = [[UIImage imageNamed:fileName] CGImage];
|
||||
if (!spriteImage) {
|
||||
NSLog(@"Failed to load image %@", fileName);
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -28,6 +28,10 @@ GLuint setup_texture(NSString *fileName)
|
||||
CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4, CGImageGetColorSpace(spriteImage), (CGBitmapInfo)kCGImageAlphaPremultipliedLast);
|
||||
|
||||
// 3
|
||||
if ([fileName isEqualToString:@"telegram_sphere.png"]) {
|
||||
CGContextSetFillColorWithColor(spriteContext, [UIColor whiteColor].CGColor);
|
||||
CGContextFillRect(spriteContext, CGRectMake(0, 0, width, height));
|
||||
}
|
||||
CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
|
||||
|
||||
CGContextRelease(spriteContext);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user