pull/213/head
nielsandriesse 4 years ago
parent b3800e0ad1
commit 5e40221936

@ -141,20 +141,15 @@ final class ConversationCell : UITableViewCell {
profilePictureView.hexEncodedPublicKey = ""
profilePictureView.isRSSFeed = true
} else {
if let groupAvatarImage = (threadViewModel.threadRecord as? TSGroupThread)?.groupModel.groupImage {
profilePictureView.groupAvatarImage = groupAvatarImage
if let openGroupProfilePicture = (threadViewModel.threadRecord as! TSGroupThread).groupModel.groupImage {
profilePictureView.openGroupProfilePicture = openGroupProfilePicture
} else {
profilePictureView.groupAvatarImage = nil
profilePictureView.openGroupProfilePicture = nil
var users = MentionsManager.userPublicKeyCache[threadViewModel.threadRecord.uniqueId!] ?? []
users.remove(getUserHexEncodedPublicKey())
let randomUsers = users.sorted().prefix(2) // Sort to provide a level of stability
if !randomUsers.isEmpty {
profilePictureView.hexEncodedPublicKey = randomUsers[0]
profilePictureView.additionalHexEncodedPublicKey = randomUsers.count >= 2 ? randomUsers[1] : ""
} else {
profilePictureView.hexEncodedPublicKey = ""
profilePictureView.additionalHexEncodedPublicKey = ""
}
profilePictureView.hexEncodedPublicKey = randomUsers.count >= 1 ? randomUsers[0] : ""
profilePictureView.additionalHexEncodedPublicKey = randomUsers.count >= 2 ? randomUsers[1] : ""
}
profilePictureView.isRSSFeed = (threadViewModel.threadRecord as? TSGroupThread)?.isRSSFeed ?? false
}

@ -133,11 +133,11 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
isJoining = true
let channelID: UInt64 = 1
let urlAsString = url.absoluteString
let userHexEncodedPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey()
let displayName = OWSProfileManager.shared().profileNameForRecipient(withID: userHexEncodedPublicKey)
let profilePictureURL = OWSProfileManager.shared().profilePictureURL()
let profileKey = OWSProfileManager.shared().localProfileKey().keyData
// TODO: Profile picture & profile key
let userPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey()
let profileManager = OWSProfileManager.shared()
let displayName = profileManager.profileNameForRecipient(withID: userPublicKey)
let profilePictureURL = profileManager.profilePictureURL()
let profileKey = profileManager.localProfileKey().keyData
try! Storage.writeSync { transaction in
transaction.removeObject(forKey: "\(urlAsString).\(channelID)", inCollection: LokiPublicChatAPI.lastMessageServerIDCollection)
transaction.removeObject(forKey: "\(urlAsString).\(channelID)", inCollection: LokiPublicChatAPI.lastDeletionServerIDCollection)

@ -957,9 +957,9 @@ const CGFloat kIconViewLength = 24;
[stackView setLayoutMarginsRelativeArrangement:YES];
if (self.isGroupThread) {
TSGroupThread* groupThread = (TSGroupThread*)self.thread;
if (groupThread.isPublicChat && groupThread.groupModel.groupImage != nil) {
profilePictureView.groupAvatarImage = groupThread.groupModel.groupImage;
TSGroupThread* groupThread = (TSGroupThread *)self.thread;
if (groupThread.isPublicChat && groupThread.groupModel.groupImage != nil && ![groupThread.groupModel.groupName isEqual:@"Session Public Chat"]) {
profilePictureView.openGroupProfilePicture = groupThread.groupModel.groupImage;
profilePictureView.isRSSFeed = false;
} else {
profilePictureView.hexEncodedPublicKey = @"";

@ -7,7 +7,7 @@ public final class ProfilePictureView : UIView {
@objc public var isRSSFeed = false
@objc public var hexEncodedPublicKey: String!
@objc public var additionalHexEncodedPublicKey: String?
@objc public var groupAvatarImage: UIImage?
@objc public var openGroupProfilePicture: UIImage?
// MARK: Components
private lazy var imageView = getImageView()
@ -62,9 +62,8 @@ public final class ProfilePictureView : UIView {
additionalImageView.isHidden = true
additionalImageView.image = nil
}
guard hexEncodedPublicKey != nil || groupAvatarImage != nil else { return } // Can happen in rare cases
imageView.image = isRSSFeed ? nil : groupAvatarImage != nil ? groupAvatarImage! : getProfilePicture(of: size, for: hexEncodedPublicKey)
guard hexEncodedPublicKey != nil || openGroupProfilePicture != nil else { return }
imageView.image = isRSSFeed ? nil : (openGroupProfilePicture ?? getProfilePicture(of: size, for: hexEncodedPublicKey))
imageView.backgroundColor = isRSSFeed ? UIColor(rgbHex: 0x353535) : UIColor(rgbHex: 0xD8D8D8) // UIColor(rgbHex: 0xD8D8D8) = Colors.unimportant
imageView.layer.cornerRadius = size / 2
imageView.contentMode = isRSSFeed ? .center : .scaleAspectFit

@ -19,8 +19,8 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
// MARK: Convenience
private static var userDisplayName: String {
let userHexEncodedPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey()
return SSKEnvironment.shared.profileManager.profileNameForRecipient(withID: userHexEncodedPublicKey) ?? "Anonymous"
let userPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey()
return SSKEnvironment.shared.profileManager.profileNameForRecipient(withID: userPublicKey) ?? "Anonymous"
}
// MARK: Database
@ -331,6 +331,51 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
}
}
static func updateProfileIfNeeded(for channel: UInt64, on server: String, from info: LokiPublicChatInfo) {
let storage = OWSPrimaryStorage.shared()
let publicChatID = "\(server).\(channel)"
try! Storage.writeSync { transaction in
// Update user count
storage.setUserCount(info.memberCount, forPublicChatWithID: publicChatID, in: transaction)
let groupThread = TSGroupThread.getOrCreateThread(withGroupId: publicChatID.data(using: .utf8)!, groupType: .openGroup, transaction: transaction)
// Update display name if needed
let groupModel = groupThread.groupModel
if groupModel.groupName != info.displayName {
let newGroupModel = TSGroupModel(title: info.displayName, memberIds: groupModel.groupMemberIds, image: groupModel.groupImage, groupId: groupModel.groupId, groupType: groupModel.groupType, adminIds: groupModel.groupAdminIds)
groupThread.groupModel = newGroupModel
groupThread.save(with: transaction)
}
// Download and update profile picture if needed
let oldProfilePictureURL = storage.getProfilePictureURL(forPublicChatWithID: publicChatID, in: transaction)
if oldProfilePictureURL != info.profilePictureURL || groupModel.groupImage == nil {
storage.setProfilePictureURL(info.profilePictureURL, forPublicChatWithID: publicChatID, in: transaction)
if let avatarURL = info.profilePictureURL {
let configuration = URLSessionConfiguration.default
let manager = AFURLSessionManager.init(sessionConfiguration: configuration)
let url = URL(string: "\(server)\(avatarURL)")!
let request = URLRequest(url: url)
let task = manager.downloadTask(with: request, progress: nil,
destination: { (targetPath: URL, response: URLResponse) -> URL in
let tempFilePath = URL(fileURLWithPath: OWSTemporaryDirectoryAccessibleAfterFirstAuth()).appendingPathComponent(UUID().uuidString)
return tempFilePath
},
completionHandler: { (response: URLResponse, filePath: URL?, error: Error?) in
if let error = error {
print("[Loki] Couldn't download profile picture for public chat channel with ID: \(channel) on server: \(server).")
return
}
if let filePath = filePath, let avatarData = try? Data.init(contentsOf: filePath) {
let attachmentStream = TSAttachmentStream(contentType: OWSMimeTypeImageJpeg, byteCount: UInt32(avatarData.count), sourceFilename: nil, caption: nil, albumMessageId: nil)
try! attachmentStream.write(avatarData)
groupThread.updateAvatar(with: attachmentStream)
}
})
task.resume()
}
}
}
}
// MARK: Joining & Leaving
@objc(getInfoForChannelWithID:onServer:)
public static func objc_getInfo(for channel: UInt64, on server: String) -> AnyPromise {
@ -361,60 +406,12 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
storage.setUserCount(memberCount, forPublicChatWithID: "\(server).\(channel)", in: transaction)
}
let publicChatInfo = LokiPublicChatInfo(displayName: displayName, profilePictureURL: profilePictureURL, memberCount: memberCount)
updateOpenGroupProfileIfNeeded(for: channel, on: server, with: publicChatInfo)
updateProfileIfNeeded(for: channel, on: server, from: publicChatInfo)
return publicChatInfo
}
}.handlingInvalidAuthTokenIfNeeded(for: server)
}
}
static func updateOpenGroupProfileIfNeeded(for channel: UInt64, on server: String, with info: LokiPublicChatInfo) {
let storage = OWSPrimaryStorage.shared()
let publicChatID = "\(server).\(channel)"
storage.dbReadWriteConnection.readWrite { transaction in
//Save user count
storage.setUserCount(info.memberCount, forPublicChatWithID: publicChatID, in: transaction)
let groupThread = TSGroupThread.getOrCreateThread(withGroupId: publicChatID.data(using: .utf8)!, groupType: .openGroup, transaction: transaction)
//Update display name if needed
let groupModel = groupThread.groupModel
if groupModel.groupName != info.displayName {
let newGroupModel = TSGroupModel.init(title: info.displayName, memberIds: groupModel.groupMemberIds, image: groupModel.groupImage, groupId: groupModel.groupId, groupType: groupModel.groupType, adminIds: groupModel.groupAdminIds)
groupThread.groupModel = newGroupModel
groupThread.save(with: transaction)
}
//Download and update profile picture if needed
let oldAvatarURL = storage.getAvatarURL(forPublicChatWithID: publicChatID, in: transaction)
if oldAvatarURL != info.profilePictureURL || groupModel.groupImage == nil {
storage.setAvatarURL(info.profilePictureURL, forPublicChatWithID: publicChatID, in: transaction)
if let avatarURL = info.profilePictureURL {
let configuration = URLSessionConfiguration.default
let manager = AFURLSessionManager.init(sessionConfiguration: configuration)
let url = URL(string: "\(server)\(avatarURL)")!
let request = URLRequest(url: url)
let task = manager.downloadTask(with: request, progress: nil,
destination: {(targetPath: URL, response: URLResponse) -> URL in
let tempFilePath = URL(fileURLWithPath: OWSTemporaryDirectoryAccessibleAfterFirstAuth()).appendingPathComponent(UUID().uuidString)
return tempFilePath
},
completionHandler: { (response: URLResponse, filePath: URL?, error: Error?) in
if let error = error {
print("[Loki] Couldn't download profile picture for public chat channel with ID: \(channel) on server: \(server)")
return
}
if let path = filePath, let avatarData = try? Data.init(contentsOf: path) {
let attachmentStream = TSAttachmentStream.init(contentType: OWSMimeTypeImageJpeg, byteCount: UInt32(avatarData.count), sourceFilename: nil, caption: nil, albumMessageId: nil)
try! attachmentStream.write(avatarData)
groupThread.updateAvatar(with: attachmentStream)
}
})
task.resume()
}
}
}
}
public static func join(_ channel: UInt64, on server: String) -> Promise<Void> {
return attempt(maxRetryCount: maxRetryCount, recoveringOn: DispatchQueue.global()) {

@ -150,7 +150,9 @@ public final class LokiPublicChatPoller : NSObject {
if !wasSentByCurrentUser {
content.setDataMessage(try! dataMessage.build())
} else {
SyncMessagesProtocol.addForceSyncMessageTimestamp(message.timestamp, from: senderHexEncodedPublicKey)
// The line below is necessary to make it so that when a user sends a message in an open group and then
// deletes and re-joins the open group without closing the app in between, the message isn't ignored.
SyncMessagesProtocol.dropFromSyncMessageTimestampCache(message.timestamp, for: senderHexEncodedPublicKey)
let syncMessageSentBuilder = SSKProtoSyncMessageSent.builder()
syncMessageSentBuilder.setMessage(try! dataMessage.build())
syncMessageSentBuilder.setDestination(userHexEncodedPublicKey)

@ -140,11 +140,11 @@ public extension OWSPrimaryStorage {
transaction.setObject(userCount, forKey: publicChatID, inCollection: Storage.openGroupUserCountCollection)
}
public func getAvatarURL(forPublicChatWithID publicChatID: String, in transaction: YapDatabaseReadTransaction) -> String? {
public func getProfilePictureURL(forPublicChatWithID publicChatID: String, in transaction: YapDatabaseReadTransaction) -> String? {
return transaction.object(forKey: publicChatID, inCollection: Storage.openGroupProfilePictureURLCollection) as? String
}
public func setAvatarURL(_ avatarURL: String?, forPublicChatWithID publicChatID: String, in transaction: YapDatabaseReadWriteTransaction) {
transaction.setObject(avatarURL, forKey: publicChatID, inCollection: Storage.openGroupProfilePictureURLCollection)
public func setProfilePictureURL(_ profilePictureURL: String?, forPublicChatWithID publicChatID: String, in transaction: YapDatabaseReadWriteTransaction) {
transaction.setObject(profilePictureURL, forKey: publicChatID, inCollection: Storage.openGroupProfilePictureURLCollection)
}
}

@ -112,13 +112,10 @@ public final class SyncMessagesProtocol : NSObject {
let hexEncodedPublicKey = envelope.source!
return LokiDatabaseUtilities.isUserLinkedDevice(hexEncodedPublicKey, transaction: transaction)
}
@objc(addForceSyncMessageTimestamp:from:)
public static func addForceSyncMessageTimestamp(_ timestamp: UInt64, from hexEncodedPublicKey: String) {
public static func dropFromSyncMessageTimestampCache(_ timestamp: UInt64, for hexEncodedPublicKey: String) {
var timestamps: Set<UInt64> = syncMessageTimestamps[hexEncodedPublicKey] ?? []
if timestamps.contains(timestamp) {
timestamps.remove(timestamp)
}
if timestamps.contains(timestamp) { timestamps.remove(timestamp) }
syncMessageTimestamps[hexEncodedPublicKey] = timestamps
}
@ -254,8 +251,8 @@ public final class SyncMessagesProtocol : NSObject {
for openGroup in groups {
let openGroupManager = LokiPublicChatManager.shared
guard openGroupManager.getChat(server: openGroup.url, channel: openGroup.channel) == nil else { return }
let userHexEncodedPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey()
let displayName = SSKEnvironment.shared.profileManager.profileNameForRecipient(withID: userHexEncodedPublicKey)
let userPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey()
let displayName = SSKEnvironment.shared.profileManager.profileNameForRecipient(withID: userPublicKey)
LokiPublicChatAPI.setDisplayName(to: displayName, on: openGroup.url)
openGroupManager.addChat(server: openGroup.url, channel: openGroup.channel)
}

Loading…
Cancel
Save