Clean & implement moderator tags UI

pull/50/head
Niels Andriesse 5 years ago
parent f0fda330de
commit af39b35da7

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "crown.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

@ -141,6 +141,6 @@ public final class LokiGroupChatPoller : NSObject {
}
private func pollForModerators() {
let _ = LokiGroupChatAPI.getModerators(for: self.group.serverID, on: self.group.server)
let _ = LokiGroupChatAPI.getModerators(for: group.serverID, on: group.server)
}
}

@ -20,6 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) OWSMessageBubbleView *messageBubbleView;
@property (nonatomic) NSLayoutConstraint *messageBubbleViewBottomConstraint;
@property (nonatomic) AvatarImageView *avatarView;
@property (nonatomic) UIImageView *moderatorIconView;
@property (nonatomic, nullable) LKFriendRequestView *friendRequestView;
@property (nonatomic, nullable) UIImageView *sendFailureBadgeView;
@ -61,6 +62,11 @@ NS_ASSUME_NONNULL_BEGIN
[self.avatarView autoSetDimension:ALDimensionWidth toSize:self.avatarSize];
[self.avatarView autoSetDimension:ALDimensionHeight toSize:self.avatarSize];
self.moderatorIconView = [[UIImageView alloc] init];
[self.moderatorIconView autoSetDimension:ALDimensionWidth toSize:20.f];
[self.moderatorIconView autoSetDimension:ALDimensionHeight toSize:20.f];
self.moderatorIconView.hidden = YES;
self.messageBubbleViewBottomConstraint = [self.messageBubbleView autoPinBottomToSuperviewMarginWithInset:0];
self.contentView.userInteractionEnabled = YES;
@ -227,6 +233,11 @@ NS_ASSUME_NONNULL_BEGIN
[self.messageBubbleView autoPinLeadingToTrailingEdgeOfView:self.avatarView offset:8],
[self.messageBubbleView autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:self.avatarView],
]];
[self.viewConstraints addObjectsFromArray:@[
[self.moderatorIconView autoPinEdge:ALEdgeTrailing toEdge:ALEdgeTrailing ofView:self.avatarView],
[self.moderatorIconView autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:self.avatarView withOffset:3.5]
]];
}
}
@ -285,6 +296,15 @@ NS_ASSUME_NONNULL_BEGIN
diameter:self.avatarSize] build];
self.avatarView.image = authorAvatarImage;
[self.contentView addSubview:self.avatarView];
if (self.viewItem.isGroupThread && !self.viewItem.isRSSFeed) {
BOOL isModerator = [LKGroupChatAPI isUserModerator:incomingMessage.authorId forGroup:LKGroupChatAPI.publicChatServerID onServer:LKGroupChatAPI.publicChatServer];
UIImage *moderatorIcon = [UIImage imageNamed:@"Crown"];
self.moderatorIconView.image = moderatorIcon;
self.moderatorIconView.hidden = !isModerator;
}
[self.contentView addSubview:self.moderatorIconView];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(otherUsersProfileDidChange:)
@ -385,6 +405,9 @@ NS_ASSUME_NONNULL_BEGIN
self.avatarView.image = nil;
[self.avatarView removeFromSuperview];
self.moderatorIconView.image = nil;
[self.moderatorIconView removeFromSuperview];
[self.sendFailureBadgeView removeFromSuperview];
self.sendFailureBadgeView = nil;

@ -1236,7 +1236,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
return NO;
}
- (NSString *)ourHexEncodedPublicKey {
- (NSString *)userHexEncodedPublicKey {
return OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey;
}
@ -1258,8 +1258,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
// Only allow deletion on incoming messages if the user has moderation permission
if (interationType == OWSInteractionType_IncomingMessage) {
BOOL isModerator = [LKGroupChatAPI isUserModerator:self.ourHexEncodedPublicKey forGroup:LKGroupChatAPI.publicChatServerID onServer: LKGroupChatAPI.publicChatServer];
BOOL isModerator = [LKGroupChatAPI isUserModerator:self.userHexEncodedPublicKey forGroup:LKGroupChatAPI.publicChatServerID onServer: LKGroupChatAPI.publicChatServer];
if (!isModerator) return false;
}

@ -4,23 +4,17 @@ import PromiseKit
public final class LokiGroupChatAPI : NSObject {
private static let storage = OWSPrimaryStorage.shared()
private static var moderators: [String:[UInt64:Set<String>]] = [:] // Server URL to (channel ID to set of moderator IDs)
// MARK: Settings
private static let fallbackBatchCount = 40
private static let maxRetryCount: UInt = 4
// MARK: Public Chat
@objc public static let publicChatServer = "https://chat.lokinet.org"
@objc public static let publicChatServer = "https://chat-dev.lokinet.org"
@objc public static let publicChatMessageType = "network.loki.messenger.publicChat"
@objc public static let publicChatServerID: UInt64 = 1
// Mark: Moderators
typealias ModeratorArray = Set<String>
typealias ChannelDictionary = [UInt64 : ModeratorArray]
typealias ServerMapping = [String : ChannelDictionary]
// A mapping from server to channel to moderator
private static var moderators = ServerMapping()
// MARK: Convenience
private static var userDisplayName: String {
return SSKEnvironment.shared.contactsManager.displayName(forPhoneIdentifier: userHexEncodedPublicKey) ?? "Anonymous"
@ -244,26 +238,6 @@ public final class LokiGroupChatAPI : NSObject {
}
}
public static func userHasModerationPermission(for group: UInt64, on server: String) -> Promise<Bool> {
return getAuthToken(for: server).then { token -> Promise<Bool> in
let url = URL(string: "\(server)/loki/v1/user_info")!
let request = TSRequest(url: url)
request.allHTTPHeaderFields = [ "Content-Type" : "application/json", "Authorization" : "Bearer \(token)" ]
return TSNetworkManager.shared().makePromise(request: request).map { $0.responseObject }.map { rawResponse in
guard let json = rawResponse as? JSON, let data = json["data"] as? JSON else {
print("[Loki] Couldn't parse moderation permission for group chat with ID: \(group) on server: \(server) from: \(rawResponse).")
throw Error.parsingFailed
}
return data["moderator_status"] as? Bool ?? false
}
}
}
@objc (isUserModerator:forGroup:onServer:)
public static func isUserModerator(user hexEncodedPublicString: String, for group: UInt64, on server: String) -> Bool {
return self.moderators[server]?[group]?.contains(hexEncodedPublicString) ?? false
}
public static func getModerators(for group: UInt64, on server: String) -> Promise<Set<String>> {
let url = URL(string: "\(server)/loki/v1/channel/\(group)/get_moderators")!
let request = TSRequest(url: url)
@ -272,20 +246,21 @@ public final class LokiGroupChatAPI : NSObject {
print("[Loki] Couldn't parse moderators for group chat with ID: \(group) on server: \(server) from: \(rawResponse).")
throw Error.parsingFailed
}
let moderatorSet = Set(moderators);
// Update our cache
if (self.moderators.keys.contains(server)) {
self.moderators[server]![group] = moderatorSet
let moderatorAsSet = Set(moderators);
if self.moderators.keys.contains(server) {
self.moderators[server]![group] = moderatorAsSet
} else {
self.moderators[server] = [group : moderatorSet]
self.moderators[server] = [ group : moderatorAsSet ]
}
return moderatorSet
return moderatorAsSet
}
}
@objc (isUserModerator:forGroup:onServer:)
public static func isUserModerator(_ hexEncodedPublicString: String, for group: UInt64, on server: String) -> Bool {
return moderators[server]?[group]?.contains(hexEncodedPublicString) ?? false
}
// MARK: Public API (Obj-C)
@objc(getMessagesForGroup:onServer:)
public static func objc_getMessages(for group: UInt64, on server: String) -> AnyPromise {

Loading…
Cancel
Save