no message

This commit is contained in:
Peter 2018-09-09 00:44:06 +03:00
parent 54f4ffdac9
commit acd863f780
18 changed files with 2571 additions and 2402 deletions

View File

@ -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 */,

View File

@ -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))

View File

@ -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?()
}),

View File

@ -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)
}

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)
}

View 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
}
}

View File

@ -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"]

View File

@ -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);

View File

@ -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;

View File

@ -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);