Skip to content
This repository was archived by the owner on Jun 7, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Rocket.Chat.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fileprivate extension SubscriptionType {
}
}

class SubscriptionFilesRequest: APIRequest {
final class SubscriptionFilesRequest: APIRequest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

typealias APIResourceType = SubscriptionFilesResource

var path: String {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// SubscriptionRolesRequest.swift
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// Rocket.Chat
//
// Created by Rafael Kellermann Streit on 11/05/18.
// Copyright © 2018 Rocket.Chat. All rights reserved.
//

import SwiftyJSON
import RealmSwift

fileprivate extension SubscriptionType {
var path: String {
switch self {
case .channel:
return "/api/v1/channels.roles"
case .group:
return "/api/v1/groups.roles"
case .directMessage:
return ""
}
}
}

final class SubscriptionRolesRequest: APIRequest {
typealias APIResourceType = SubscriptionRolesResource

let requiredVersion = Version(0, 64, 2)

var path: String {
return type.path
}

var query: String?
let roomName: String?
let type: SubscriptionType

init(roomName: String, subscriptionType: SubscriptionType) {
self.type = subscriptionType
self.roomName = roomName
self.query = "roomName=\(roomName)"
}
}

final class SubscriptionRolesResource: APIResource {
var subscriptionRoles: [SubscriptionRoles]? {
guard let realm = Realm.current else { return nil }
return raw?["roles"].arrayValue.map {
let object = SubscriptionRoles()
object.user = User.getOrCreate(realm: realm, values: $0["u"], updates: nil)
object.roles.append(contentsOf: $0["roles"].arrayValue.compactMap({ $0.string }))
return object
}
}

var success: Bool {
return raw?["success"].bool ?? false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ import Foundation
extension AuthViewController {
internal func handleAuthenticationResponse(_ response: LoginResponse) {
if case let .resource(resource) = response, let error = resource.error {
stopLoading()
DispatchQueue.main.async { [weak self] in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

self?.stopLoading()

switch error.lowercased() {
case "totp-required":
return performSegue(withIdentifier: "TwoFactor", sender: nil)
case "unauthorized":
return Alert(key: "error.login_unauthorized").present()
default:
return Alert(key: "error.login").present()
switch error.lowercased() {
case "totp-required":
self?.performSegue(withIdentifier: "TwoFactor", sender: nil)
case "unauthorized":
Alert(key: "error.login_unauthorized").present()
default:
Alert(key: "error.login").present()
}
}
}

Expand Down
5 changes: 2 additions & 3 deletions Rocket.Chat/Controllers/Chat/ChannelInfoViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ class ChannelInfoViewController: BaseViewController {
didSet {
guard let subscription = self.subscription else { return }

let shouldListMentions = subscription.type != .directMessage
let channelInfoData = [
ChannelInfoDetailCellData(title: localized("chat.info.item.files"), detail: "", action: showFilesList),
ChannelInfoDetailCellData(title: localized("chat.info.item.members"), detail: "", action: showMembersList),
subscription.canViewMembersList ? ChannelInfoDetailCellData(title: localized("chat.info.item.members"), detail: "", action: showMembersList) : nil,
ChannelInfoDetailCellData(title: localized("chat.info.item.pinned"), detail: "", action: showPinnedList),
ChannelInfoDetailCellData(title: localized("chat.info.item.starred"), detail: "", action: showStarredList),
shouldListMentions ? ChannelInfoDetailCellData(title: localized("chat.info.item.mentions"), detail: "", action: showMentionsList) : nil
subscription.canViewMentionsList ? ChannelInfoDetailCellData(title: localized("chat.info.item.mentions"), detail: "", action: showMentionsList) : nil
].compactMap({$0})

if subscription.type == .directMessage {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ extension ChatViewController: ChatMessageCellProtocol, UserActionSheetPresenter
present(controller, animated: true, completion: nil)
}

func openReplyMessage(message: Message) {
guard let username = message.user?.username else { return }
AppManager.openDirectMessage(username: username, replyMessageIdentifier: message.identifier, completion: nil)
}

func openImageFromCell(attachment: Attachment, thumbnail: FLAnimatedImageView) {
textView.resignFirstResponder()

Expand Down
44 changes: 44 additions & 0 deletions Rocket.Chat/Controllers/Chat/ChatControllerRolesController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// ChatControllerRolesController.swift
// Rocket.Chat
//
// Created by Rafael Kellermann Streit on 11/05/18.
// Copyright © 2018 Rocket.Chat. All rights reserved.
//

import Foundation
import RealmSwift

extension ChatViewController {

func updateSubscriptionRoles() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be a good method for SubscriptionsClient, with realm and subscription as parameters, instead of being in the ViewController. This would make it more testable and reusable.

I can do it in another PR if you want.

guard
let subscription = subscription,
subscription.type != .directMessage
else {
return
}

let rid = subscription.rid
let rolesRequest = SubscriptionRolesRequest(roomName: subscription.name, subscriptionType: subscription.type)
API.current()?.fetch(rolesRequest, completion: { result in
switch result {
case .resource(let resource):
if let subscription = Subscription.find(rid: rid) {
Realm.executeOnMainThread({ (realm) in
subscription.usersRoles.removeAll()
resource.subscriptionRoles?.forEach({ (role) in
subscription.usersRoles.append(role)
})

realm.add(subscription, update: true)
})
}

// Fail silently
default: break
}
})
}

}
1 change: 1 addition & 0 deletions Rocket.Chat/Controllers/Chat/ChatViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ final class ChatViewController: SLKTextViewController {
})
}

updateSubscriptionRoles()
updateMessageSendingPermission()
}

Expand Down
26 changes: 26 additions & 0 deletions Rocket.Chat/Extensions/Models/MessageExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,32 @@
//

import UIKit
import RealmSwift

extension Message {

/**
This method will return if the reply button
in a broadcast room needs to be displayed or
not for the message. If the subscription is not
a broadcast type, it'll return false.
*/
func isBroadcastReplyAvailable(realm: Realm? = Realm.current) -> Bool {
guard
!temporary,
!failed,
!markedForDeletion,
subscription.roomBroadcast,
!isSystemMessage(),
let currentUser = AuthManager.currentUser(realm: realm),
currentUser.identifier != user?.identifier
else {
return false
}

return true
}

func isSystemMessage() -> Bool {
return !(
type == .text ||
Expand Down Expand Up @@ -112,9 +136,11 @@ extension Message {

return text
}

}

// MARK: Accessibility

extension Message {
override var accessibilityLabel: String? {
get {
Expand Down
36 changes: 36 additions & 0 deletions Rocket.Chat/Extensions/Models/SubscriptionExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,42 @@
import Foundation
import RealmSwift

// MARK: Information Viewing Options

extension Subscription {

var canViewMembersList: Bool {
if !roomBroadcast {
return true
}

guard let currentUser = AuthManager.currentUser() else {
return false
}

if currentUser == roomOwner {
return true
}

if currentUser.canViewAdminPanel() {
return true
}

if let currentUserRoles = usersRoles.filter({ $0.user?.identifier == currentUser.identifier }).first?.roles {
if currentUserRoles.contains(Role.admin.rawValue) { return true }
if currentUserRoles.contains(Role.moderator.rawValue) { return true }
if currentUserRoles.contains(Role.owner.rawValue) { return true }
}

return false
}

var canViewMentionsList: Bool {
return type != .directMessage
}

}

extension LinkingObjects where Element == Subscription {
func sortedByLastSeen() -> Results<Subscription> {
return self.sorted(byKeyPath: "lastSeen", ascending: false)
Expand Down
8 changes: 7 additions & 1 deletion Rocket.Chat/Managers/AppManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,19 @@ extension AppManager {
// MARK: Open Rooms

extension AppManager {
static func openDirectMessage(username: String, completion: (() -> Void)? = nil) {
static func openDirectMessage(username: String, replyMessageIdentifier: String? = nil, completion: (() -> Void)? = nil) {
func openDirectMessage() -> Bool {
guard let directMessageRoom = Subscription.find(name: username, subscriptionType: [.directMessage]) else { return false }

let controller = ChatViewController.shared
controller?.subscription = directMessageRoom

if let identifier = replyMessageIdentifier {
if let message = Realm.current?.object(ofType: Message.self, forPrimaryKey: identifier) {
controller?.reply(to: message)
}
}

completion?()

return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
//

import Foundation
import RealmSwift

extension AuthManager {
/**
- returns: Current user object, if exists.
*/
static func currentUser() -> User? {
return isAuthenticated()?.user
static func currentUser(realm: Realm? = Realm.current) -> User? {
return isAuthenticated(realm: realm)?.user
}
}
9 changes: 6 additions & 3 deletions Rocket.Chat/Models/Base/ModelMappeable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ protocol ModelMappeable {

extension ModelMappeable where Self: BaseModel {

static func getOrCreate(realm: Realm, values: JSON, updates: UpdateBlock<Self>?) -> Self {
static func getOrCreate(realm: Realm, values: JSON?, updates: UpdateBlock<Self>?) -> Self {
var object: Self!

if let primaryKey = values["_id"].string {
if let primaryKey = values?["_id"].string {
if let newObject = realm.object(ofType: Self.self, forPrimaryKey: primaryKey as AnyObject) {
object = newObject
}
Expand All @@ -32,7 +32,10 @@ extension ModelMappeable where Self: BaseModel {
object = Self()
}

object.map(values, realm: realm)
if let values = values {
object.map(values, realm: realm)
}

updates?(object)
return object
}
Expand Down
2 changes: 1 addition & 1 deletion Rocket.Chat/Models/File.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Foundation
import RealmSwift

class File: BaseModel {
final class File: BaseModel {
@objc dynamic var name = ""
@objc dynamic var rid = ""
@objc dynamic var size: Double = 0
Expand Down
11 changes: 3 additions & 8 deletions Rocket.Chat/Models/Mapping/SubscriptionModelMapping.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,13 @@ extension Subscription: ModelMappeable {
func mapRoom(_ values: JSON) {
self.roomDescription = values["description"].stringValue
self.roomTopic = values["topic"].stringValue
self.roomReadOnly = values["ro"].boolValue
self.roomBroadcast = values["broadcast"].boolValue
self.roomOwnerId = values["u"]["_id"].stringValue

self.roomMuted.removeAll()
if let roomMuted = values["muted"].array?.compactMap({ $0.string }) {
self.roomMuted.append(objectsIn: roomMuted)
}

if let readOnly = values["ro"].bool {
self.roomReadOnly = readOnly
}

if let ownerId = values["u"]["_id"].string {
self.roomOwnerId = ownerId
}
}
}
14 changes: 9 additions & 5 deletions Rocket.Chat/Models/Mapping/UserModelMapping.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ extension User: ModelMappeable {
self.name = name
}

if let roles = values["roles"].array?.compactMap({ $0.string }) {
self.roles.removeAll()
self.roles.append(contentsOf: roles)
}

if let status = values["status"].string {
self.status = UserStatus(rawValue: status) ?? .offline
}
Expand All @@ -52,5 +47,14 @@ extension User: ModelMappeable {
self.emails.removeAll()
self.emails.append(contentsOf: emails)
}

mapRoles(values["roles"])
}

func mapRoles(_ values: JSON) {
if let roles = values.array?.compactMap({ $0.string }) {
self.roles.removeAll()
self.roles.append(contentsOf: roles)
}
}
}
Loading