Merge branch 'dev' of https://github.com/loki-project/session-ios into bug-fix
This commit is contained in:
commit
8b03a1b185
|
@ -9,7 +9,7 @@ public final class MentionUtilities : NSObject {
|
|||
}
|
||||
|
||||
@objc public static func highlightMentions(in string: String, isOutgoingMessage: Bool, threadID: String, attributes: [NSAttributedString.Key:Any]) -> NSAttributedString {
|
||||
let userHexEncodedPublicKey = getUserHexEncodedPublicKey()
|
||||
let userPublicKey = getUserHexEncodedPublicKey()
|
||||
var publicChat: PublicChat?
|
||||
OWSPrimaryStorage.shared().dbReadConnection.read { transaction in
|
||||
publicChat = LokiDatabaseUtilities.getPublicChat(for: threadID, in: transaction)
|
||||
|
@ -17,34 +17,34 @@ public final class MentionUtilities : NSObject {
|
|||
}
|
||||
var string = string
|
||||
let regex = try! NSRegularExpression(pattern: "@[0-9a-fA-F]*", options: [])
|
||||
let knownHexEncodedPublicKeys = MentionsManager.userPublicKeyCache[threadID] ?? [] // Should always be populated at this point
|
||||
var mentions: [(range: NSRange, hexEncodedPublicKey: String)] = []
|
||||
var outerMatch = regex.firstMatch(in: string, options: .withoutAnchoringBounds, range: NSRange(location: 0, length: string.count))
|
||||
let knownPublicKeys = MentionsManager.userPublicKeyCache[threadID] ?? [] // Should always be populated at this point
|
||||
var mentions: [(range: NSRange, publicKey: String)] = []
|
||||
var outerMatch = regex.firstMatch(in: string, options: .withoutAnchoringBounds, range: NSRange(location: 0, length: string.utf16.count))
|
||||
while let match = outerMatch {
|
||||
let hexEncodedPublicKey = String((string as NSString).substring(with: match.range).dropFirst()) // Drop the @
|
||||
let publicKey = String((string as NSString).substring(with: match.range).dropFirst()) // Drop the @
|
||||
let matchEnd: Int
|
||||
if knownHexEncodedPublicKeys.contains(hexEncodedPublicKey) {
|
||||
if knownPublicKeys.contains(publicKey) {
|
||||
var displayName: String?
|
||||
if hexEncodedPublicKey == userHexEncodedPublicKey {
|
||||
if publicKey == userPublicKey {
|
||||
displayName = OWSProfileManager.shared().localProfileName()
|
||||
} else {
|
||||
if let publicChat = publicChat {
|
||||
displayName = UserDisplayNameUtilities.getPublicChatDisplayName(for: hexEncodedPublicKey, in: publicChat.channel, on: publicChat.server)
|
||||
displayName = UserDisplayNameUtilities.getPublicChatDisplayName(for: publicKey, in: publicChat.channel, on: publicChat.server)
|
||||
} else {
|
||||
displayName = UserDisplayNameUtilities.getPrivateChatDisplayName(for: hexEncodedPublicKey)
|
||||
displayName = UserDisplayNameUtilities.getPrivateChatDisplayName(for: publicKey)
|
||||
}
|
||||
}
|
||||
if let displayName = displayName {
|
||||
string = (string as NSString).replacingCharacters(in: match.range, with: "@\(displayName)")
|
||||
mentions.append((range: NSRange(location: match.range.location, length: displayName.count + 1), hexEncodedPublicKey: hexEncodedPublicKey)) // + 1 to include the @
|
||||
matchEnd = match.range.location + displayName.count
|
||||
mentions.append((range: NSRange(location: match.range.location, length: displayName.utf16.count + 1), publicKey: publicKey)) // + 1 to include the @
|
||||
matchEnd = match.range.location + displayName.utf16.count
|
||||
} else {
|
||||
matchEnd = match.range.location + match.range.length
|
||||
}
|
||||
} else {
|
||||
matchEnd = match.range.location + match.range.length
|
||||
}
|
||||
outerMatch = regex.firstMatch(in: string, options: .withoutAnchoringBounds, range: NSRange(location: matchEnd, length: string.count - matchEnd))
|
||||
outerMatch = regex.firstMatch(in: string, options: .withoutAnchoringBounds, range: NSRange(location: matchEnd, length: string.utf16.count - matchEnd))
|
||||
}
|
||||
let result = NSMutableAttributedString(string: string, attributes: attributes)
|
||||
mentions.forEach { mention in
|
||||
|
|
|
@ -130,11 +130,6 @@ final class DisplayNameVC : BaseVC {
|
|||
guard !displayName.isEmpty else {
|
||||
return showError(title: NSLocalizedString("vc_display_name_display_name_missing_error", comment: ""))
|
||||
}
|
||||
let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_ ")
|
||||
let hasInvalidCharacters = !displayName.allSatisfy { $0.unicodeScalars.allSatisfy { allowedCharacters.contains($0) } }
|
||||
guard !hasInvalidCharacters else {
|
||||
return showError(title: NSLocalizedString("vc_display_name_display_name_invalid_error", comment: ""))
|
||||
}
|
||||
guard !OWSProfileManager.shared().isProfileNameTooLong(displayName) else {
|
||||
return showError(title: NSLocalizedString("vc_display_name_display_name_too_long_error", comment: ""))
|
||||
}
|
||||
|
|
|
@ -301,11 +301,6 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
|||
guard !displayName.isEmpty else {
|
||||
return showError(title: NSLocalizedString("vc_settings_display_name_missing_error", comment: ""))
|
||||
}
|
||||
let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_ ")
|
||||
let hasInvalidCharacters = !displayName.allSatisfy { $0.unicodeScalars.allSatisfy { allowedCharacters.contains($0) } }
|
||||
guard !hasInvalidCharacters else {
|
||||
return showError(title: NSLocalizedString("vc_settings_invalid_display_name_error", comment: ""))
|
||||
}
|
||||
guard !OWSProfileManager.shared().isProfileNameTooLong(displayName) else {
|
||||
return showError(title: NSLocalizedString("vc_settings_display_name_too_long_error", comment: ""))
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@ public enum OnionRequestAPI {
|
|||
]
|
||||
let destination = Destination.server(host: host, x25519PublicKey: x25519PublicKey)
|
||||
return sendOnionRequest(with: payload, to: destination, isJSONRequired: isJSONRequired).recover2 { error -> Promise<JSON> in
|
||||
print("[Loki] [Onion Request API] Couldn't reach server: \(server) due to error: \(error).")
|
||||
print("[Loki] [Onion Request API] Couldn't reach server: \(url) due to error: \(error).")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,9 +114,9 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let url = URL(string: "\(server)/channels/\(channel)/messages?\(queryParameters)")!
|
||||
let request = TSRequest(url: url)
|
||||
request.allHTTPHeaderFields = [ "Content-Type" : "application/json", "Authorization" : "Bearer \(token)" ]
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { rawResponse in
|
||||
guard let json = rawResponse as? JSON, let rawMessages = json["data"] as? [JSON] else {
|
||||
print("[Loki] Couldn't parse messages for public chat channel with ID: \(channel) on server: \(server) from: \(rawResponse).")
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { json in
|
||||
guard let rawMessages = json["data"] as? [JSON] else {
|
||||
print("[Loki] Couldn't parse messages for public chat channel with ID: \(channel) on server: \(server) from: \(json).")
|
||||
throw DotNetAPIError.parsingFailed
|
||||
}
|
||||
return rawMessages.flatMap { message in
|
||||
|
@ -207,13 +207,13 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let request = TSRequest(url: url, method: "POST", parameters: parameters)
|
||||
request.allHTTPHeaderFields = [ "Content-Type" : "application/json", "Authorization" : "Bearer \(token)" ]
|
||||
let displayName = userDisplayName
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { rawResponse in
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { json in
|
||||
// ISO8601DateFormatter doesn't support milliseconds before iOS 11
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
|
||||
guard let json = rawResponse as? JSON, let messageAsJSON = json["data"] as? JSON, let serverID = messageAsJSON["id"] as? UInt64, let body = messageAsJSON["text"] as? String,
|
||||
guard let messageAsJSON = json["data"] as? JSON, let serverID = messageAsJSON["id"] as? UInt64, let body = messageAsJSON["text"] as? String,
|
||||
let dateAsString = messageAsJSON["created_at"] as? String, let date = dateFormatter.date(from: dateAsString) else {
|
||||
print("[Loki] Couldn't parse message for public chat channel with ID: \(channel) on server: \(server) from: \(rawResponse).")
|
||||
print("[Loki] Couldn't parse message for public chat channel with ID: \(channel) on server: \(server) from: \(json).")
|
||||
throw DotNetAPIError.parsingFailed
|
||||
}
|
||||
let timestamp = UInt64(date.timeIntervalSince1970) * 1000
|
||||
|
@ -244,9 +244,9 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let url = URL(string: "\(server)/loki/v1/channel/\(channel)/deletes?\(queryParameters)")!
|
||||
let request = TSRequest(url: url)
|
||||
request.allHTTPHeaderFields = [ "Content-Type" : "application/json", "Authorization" : "Bearer \(token)" ]
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { rawResponse in
|
||||
guard let json = rawResponse as? JSON, let deletions = json["data"] as? [JSON] else {
|
||||
print("[Loki] Couldn't parse deleted messages for public chat channel with ID: \(channel) on server: \(server) from: \(rawResponse).")
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { json in
|
||||
guard let body = json["body"] as? JSON, let deletions = body["data"] as? [JSON] else {
|
||||
print("[Loki] Couldn't parse deleted messages for public chat channel with ID: \(channel) on server: \(server) from: \(json).")
|
||||
throw DotNetAPIError.parsingFailed
|
||||
}
|
||||
return deletions.flatMap { deletion in
|
||||
|
@ -278,7 +278,7 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let url = URL(string: urlAsString)!
|
||||
let request = TSRequest(url: url, method: "DELETE", parameters: [:])
|
||||
request.allHTTPHeaderFields = [ "Content-Type" : "application/json", "Authorization" : "Bearer \(token)" ]
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).done(on: DispatchQueue.global(qos: .default)) { result -> Void in
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey, isJSONRequired: false).done(on: DispatchQueue.global(qos: .default)) { _ -> Void in
|
||||
print("[Loki] Deleted message with ID: \(messageID) on server: \(server).")
|
||||
}
|
||||
}
|
||||
|
@ -297,9 +297,9 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let queryParameters = "ids=\(publicKeys.map { "@\($0)" }.joined(separator: ","))&include_user_annotations=1"
|
||||
let url = URL(string: "\(server)/users?\(queryParameters)")!
|
||||
let request = TSRequest(url: url)
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { rawResponse in
|
||||
guard let json = rawResponse as? JSON, let data = json["data"] as? [JSON] else {
|
||||
print("[Loki] Couldn't parse display names for users: \(publicKeys) from: \(rawResponse).")
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { json in
|
||||
guard let data = json["data"] as? [JSON] else {
|
||||
print("[Loki] Couldn't parse display names for users: \(publicKeys) from: \(json).")
|
||||
throw DotNetAPIError.parsingFailed
|
||||
}
|
||||
try! Storage.writeSync { transaction in
|
||||
|
@ -424,9 +424,8 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let url = URL(string: "\(server)/channels/\(channel)?include_annotations=1")!
|
||||
let request = TSRequest(url: url)
|
||||
request.allHTTPHeaderFields = [ "Content-Type" : "application/json", "Authorization" : "Bearer \(token)" ]
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { rawResponse in
|
||||
guard let json = rawResponse as? JSON,
|
||||
let data = json["data"] as? JSON,
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { json in
|
||||
guard let data = json["data"] as? JSON,
|
||||
let annotations = data["annotations"] as? [JSON],
|
||||
let annotation = annotations.first,
|
||||
let info = annotation["value"] as? JSON,
|
||||
|
@ -434,7 +433,7 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let profilePictureURL = info["avatar"] as? String,
|
||||
let countInfo = data["counts"] as? JSON,
|
||||
let memberCount = countInfo["subscribers"] as? Int else {
|
||||
print("[Loki] Couldn't parse info for public chat channel with ID: \(channel) on server: \(server) from: \(rawResponse).")
|
||||
print("[Loki] Couldn't parse info for public chat channel with ID: \(channel) on server: \(server) from: \(json).")
|
||||
throw DotNetAPIError.parsingFailed
|
||||
}
|
||||
let storage = OWSPrimaryStorage.shared()
|
||||
|
@ -457,7 +456,7 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let url = URL(string: "\(server)/channels/\(channel)/subscribe")!
|
||||
let request = TSRequest(url: url, method: "POST", parameters: [:])
|
||||
request.allHTTPHeaderFields = [ "Content-Type" : "application/json", "Authorization" : "Bearer \(token)" ]
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).done(on: DispatchQueue.global(qos: .default)) { result -> Void in
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).done(on: DispatchQueue.global(qos: .default)) { _ -> Void in
|
||||
print("[Loki] Joined channel with ID: \(channel) on server: \(server).")
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +471,7 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let url = URL(string: "\(server)/channels/\(channel)/subscribe")!
|
||||
let request = TSRequest(url: url, method: "DELETE", parameters: [:])
|
||||
request.allHTTPHeaderFields = [ "Content-Type" : "application/json", "Authorization" : "Bearer \(token)" ]
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).done(on: DispatchQueue.global(qos: .default)) { result -> Void in
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).done(on: DispatchQueue.global(qos: .default)) { _ -> Void in
|
||||
print("[Loki] Left channel with ID: \(channel) on server: \(server).")
|
||||
}
|
||||
}
|
||||
|
@ -491,7 +490,7 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let request = TSRequest(url: url, method: "POST", parameters: [:])
|
||||
// Only used for the Loki Public Chat which doesn't require authentication
|
||||
return getOpenGroupServerPublicKey(for: server).then(on: DispatchQueue.global(qos: .default)) { serverPublicKey in
|
||||
OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { _ in}
|
||||
OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { _ in }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -502,9 +501,9 @@ public final class PublicChatAPI : DotNetAPI {
|
|||
let url = URL(string: "\(server)/loki/v1/channel/\(channel)/get_moderators")!
|
||||
let request = TSRequest(url: url)
|
||||
request.allHTTPHeaderFields = [ "Content-Type" : "application/json", "Authorization" : "Bearer \(token)" ]
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { rawResponse in
|
||||
guard let json = rawResponse as? JSON, let moderators = json["moderators"] as? [String] else {
|
||||
print("[Loki] Couldn't parse moderators for public chat channel with ID: \(channel) on server: \(server) from: \(rawResponse).")
|
||||
return OnionRequestAPI.sendOnionRequest(request, to: server, using: serverPublicKey).map(on: DispatchQueue.global(qos: .default)) { json in
|
||||
guard let moderators = json["moderators"] as? [String] else {
|
||||
print("[Loki] Couldn't parse moderators for public chat channel with ID: \(channel) on server: \(server) from: \(json).")
|
||||
throw DotNetAPIError.parsingFailed
|
||||
}
|
||||
let moderatorsAsSet = Set(moderators);
|
||||
|
|
Loading…
Reference in New Issue