mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Improve country selection search
This commit is contained in:
parent
615a77b3b6
commit
97c0dbebb9
@ -9,6 +9,7 @@ static_library(
|
||||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit#shared",
|
||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit#shared",
|
||||
"//submodules/Display:Display#shared",
|
||||
"//submodules/Postbox:Postbox#shared",
|
||||
"//submodules/TelegramCore:TelegramCore#shared",
|
||||
"//submodules/TelegramPresentationData:TelegramPresentationData",
|
||||
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
|
||||
|
@ -10,6 +10,7 @@ swift_library(
|
||||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||
"//submodules/Display:Display",
|
||||
"//submodules/Postbox:Postbox",
|
||||
"//submodules/TelegramCore:TelegramCore",
|
||||
"//submodules/TelegramPresentationData:TelegramPresentationData",
|
||||
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
|
||||
|
@ -236,6 +236,7 @@ public final class AuthorizationSequenceCountrySelectionController: ViewControll
|
||||
}
|
||||
|
||||
public static func lookupPatternByNumber(_ number: String, preferredCountries: [String: String]) -> String? {
|
||||
let number = removePlus(number)
|
||||
if let (_, code) = lookupCountryIdByNumber(number, preferredCountries: preferredCountries), !code.patterns.isEmpty {
|
||||
var prefixes: [String: String] = [:]
|
||||
for pattern in code.patterns {
|
||||
|
@ -2,6 +2,7 @@ import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SyncCore
|
||||
import TelegramPresentationData
|
||||
@ -73,6 +74,75 @@ func localizedCountryNamesAndCodes(strings: PresentationStrings) -> [((String, S
|
||||
return result
|
||||
}
|
||||
|
||||
private func stringTokens(_ string: String) -> [ValueBoxKey] {
|
||||
let nsString = string.replacingOccurrences(of: ".", with: "").folding(options: .diacriticInsensitive, locale: .current).lowercased() as NSString
|
||||
|
||||
let flag = UInt(kCFStringTokenizerUnitWord)
|
||||
let tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, nsString, CFRangeMake(0, nsString.length), flag, CFLocaleCopyCurrent())
|
||||
var tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)
|
||||
var tokens: [ValueBoxKey] = []
|
||||
|
||||
var addedTokens = Set<ValueBoxKey>()
|
||||
while tokenType != [] {
|
||||
let currentTokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer)
|
||||
|
||||
if currentTokenRange.location >= 0 && currentTokenRange.length != 0 {
|
||||
let token = ValueBoxKey(length: currentTokenRange.length * 2)
|
||||
nsString.getCharacters(token.memory.assumingMemoryBound(to: unichar.self), range: NSMakeRange(currentTokenRange.location, currentTokenRange.length))
|
||||
if !addedTokens.contains(token) {
|
||||
tokens.append(token)
|
||||
addedTokens.insert(token)
|
||||
}
|
||||
}
|
||||
tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)
|
||||
}
|
||||
|
||||
return tokens
|
||||
}
|
||||
|
||||
private func matchStringTokens(_ tokens: [ValueBoxKey], with other: [ValueBoxKey]) -> Bool {
|
||||
if other.isEmpty {
|
||||
return false
|
||||
} else if other.count == 1 {
|
||||
let otherToken = other[0]
|
||||
for token in tokens {
|
||||
if otherToken.isPrefix(to: token) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for otherToken in other {
|
||||
var found = false
|
||||
for token in tokens {
|
||||
if otherToken.isPrefix(to: token) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private func searchCountries(items: [((String, String), String, Int)], query: String) -> [((String, String), String, Int)] {
|
||||
let queryTokens = stringTokens(query.lowercased())
|
||||
|
||||
var result: [((String, String), String, Int)] = []
|
||||
for item in items {
|
||||
let string = "\(item.0) \(item.1)"
|
||||
let tokens = stringTokens(string)
|
||||
if matchStringTokens(tokens, with: queryTokens) {
|
||||
result.append(item)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
final class AuthorizationSequenceCountrySelectionControllerNode: ASDisplayNode, UITableViewDelegate, UITableViewDataSource {
|
||||
let itemSelected: (((String, String), String, Int)) -> Void
|
||||
|
||||
@ -88,6 +158,7 @@ final class AuthorizationSequenceCountrySelectionControllerNode: ASDisplayNode,
|
||||
private let sectionTitles: [String]
|
||||
|
||||
private var searchResults: [((String, String), String, Int)] = []
|
||||
private let countryNamesAndCodes: [((String, String), String, Int)]
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, displayCodes: Bool, itemSelected: @escaping (((String, String), String, Int)) -> Void) {
|
||||
self.theme = theme
|
||||
@ -107,6 +178,7 @@ final class AuthorizationSequenceCountrySelectionControllerNode: ASDisplayNode,
|
||||
}
|
||||
|
||||
let countryNamesAndCodes = localizedCountryNamesAndCodes(strings: strings)
|
||||
self.countryNamesAndCodes = countryNamesAndCodes
|
||||
|
||||
var sections: [(String, [((String, String), String, Int)])] = []
|
||||
for (names, id, code) in countryNamesAndCodes.sorted(by: { lhs, rhs in
|
||||
@ -176,18 +248,7 @@ final class AuthorizationSequenceCountrySelectionControllerNode: ASDisplayNode,
|
||||
self.searchTableView.reloadData()
|
||||
self.searchTableView.isHidden = true
|
||||
} else {
|
||||
let normalizedQuery = query.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
var results: [((String, String), String, Int)] = []
|
||||
for (_, items) in self.sections {
|
||||
for item in items {
|
||||
if item.0.0.lowercased().hasPrefix(normalizedQuery) || item.0.1.lowercased().hasPrefix(normalizedQuery) {
|
||||
results.append(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.searchResults = results
|
||||
self.searchResults = searchCountries(items: self.countryNamesAndCodes, query: query)
|
||||
self.searchTableView.isHidden = false
|
||||
self.searchTableView.reloadData()
|
||||
}
|
||||
|
@ -593,27 +593,6 @@ public final class ShareController: ViewController {
|
||||
}
|
||||
self.controllerNode.shareExternal = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
// if case let .messages(messages) = strongSelf.subject, let message = messages.first, let peer = message.peers[message.id.peerId] {
|
||||
// let renderer = MessageStoryRenderer(context: strongSelf.currentContext, messages: messages)
|
||||
//
|
||||
// let layout = ContainerViewLayout(size: CGSize(width: 414.0, height: 896.0), metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: .iPhoneX, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: 0.0, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false)
|
||||
// renderer.update(layout: layout) { image in
|
||||
// if let data = image?.pngData() {
|
||||
// let pasteboardItems: [[String: Any]] = [["com.instagram.sharedSticker.backgroundImage": data,
|
||||
// "com.instagram.sharedSticker.contentURL": "https://t.me/\(peer.addressName ?? "")/\(message.id.id)"]]
|
||||
// if #available(iOS 10.0, *) {
|
||||
// UIPasteboard.general.setItems(pasteboardItems, options: [.expirationDate: Date().addingTimeInterval(5 * 60)])
|
||||
// } else {
|
||||
//// UIPasteboard.general.setItems(pasteboardItems)
|
||||
// }
|
||||
// strongSelf.sharedContext.applicationBindings.openUrl("instagram-stories://share")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return .complete()
|
||||
// }
|
||||
|
||||
|
||||
var collectableItems: [CollectableExternalShareItem] = []
|
||||
switch strongSelf.subject {
|
||||
case let .url(text):
|
||||
@ -695,7 +674,25 @@ public final class ShareController: ViewController {
|
||||
activityItems.append(url)
|
||||
}
|
||||
}
|
||||
let activityController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
|
||||
|
||||
var activities: [UIActivity]?
|
||||
if false, #available(iOS 10.0, *), strongSelf.sharedContext.applicationBindings.canOpenUrl("instagram-stories://"), case let .messages(messages) = strongSelf.subject, let message = messages.first, let peer = message.peers[message.id.peerId] {
|
||||
let shareToInstagram = ShareToInstagramActivity(action: { sharedItems in
|
||||
let renderer = MessageStoryRenderer(context: strongSelf.currentContext, messages: messages)
|
||||
|
||||
let layout = ContainerViewLayout(size: CGSize(width: 414.0, height: 896.0), metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: .iPhoneX, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: 0.0, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false)
|
||||
renderer.update(layout: layout) { image in
|
||||
if let data = image?.pngData() {
|
||||
let pasteboardItems: [[String: Any]] = [["com.instagram.sharedSticker.backgroundImage": data,
|
||||
"com.instagram.sharedSticker.contentURL": "https://t.me/\(peer.addressName ?? "")/\(message.id.id)"]]
|
||||
UIPasteboard.general.setItems(pasteboardItems, options: [.expirationDate: Date().addingTimeInterval(5 * 60)])
|
||||
strongSelf.sharedContext.applicationBindings.openUrl("instagram-stories://share")
|
||||
}
|
||||
}
|
||||
})
|
||||
activities = [shareToInstagram]
|
||||
}
|
||||
let activityController = UIActivityViewController(activityItems: activityItems, applicationActivities: activities)
|
||||
|
||||
if let window = strongSelf.view.window, let rootViewController = window.rootViewController {
|
||||
activityController.popoverPresentationController?.sourceView = window
|
||||
@ -1015,3 +1012,42 @@ final class MessageStoryRenderer {
|
||||
dateHeaderNode.updateLayout(size: self.containerNode.frame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right)
|
||||
}
|
||||
}
|
||||
|
||||
private class ShareToInstagramActivity: UIActivity {
|
||||
private var activityItems = [Any]()
|
||||
private var action: ([Any]) -> Void
|
||||
|
||||
init(action: @escaping ([Any]) -> Void) {
|
||||
self.action = action
|
||||
super.init()
|
||||
}
|
||||
|
||||
override var activityTitle: String? {
|
||||
return "Share to Instagram Stories"
|
||||
}
|
||||
|
||||
override var activityImage: UIImage? {
|
||||
return nil
|
||||
}
|
||||
|
||||
override var activityType: UIActivity.ActivityType? {
|
||||
return UIActivity.ActivityType(rawValue: "org.telegram.Telegram.ShareToInstagram")
|
||||
}
|
||||
|
||||
override class var activityCategory: UIActivity.Category {
|
||||
return .action
|
||||
}
|
||||
|
||||
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override func prepare(withActivityItems activityItems: [Any]) {
|
||||
self.activityItems = activityItems
|
||||
}
|
||||
|
||||
override func perform() {
|
||||
self.action(self.activityItems)
|
||||
activityDidFinish(true)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user