فهرست منبع

add and call MapViewController

B. Petersen 2 سال پیش
والد
کامیت
e02abe0022

+ 83 - 2
DcCore/DcCore/DC/Wrapper.swift

@@ -144,13 +144,24 @@ public class DcContext {
         return DcMsg(pointer: messagePointer)
     }
 
+    public func msgExists(id: Int) -> Bool {
+        if id <= DC_MSG_ID_LAST_SPECIAL {
+            return false
+        } else {
+            let messagePointer = dc_get_msg(contextPointer, UInt32(id))
+            let exists = messagePointer != nil && dc_msg_get_chat_id(messagePointer) != DC_CHAT_ID_TRASH
+            dc_msg_unref(messagePointer)
+            return exists
+        }
+    }
+
     public func getMessage(id: Int) -> DcMsg {
         let messagePointer = dc_get_msg(contextPointer, UInt32(id))
         return DcMsg(pointer: messagePointer)
     }
 
-    public func sendMessage(chatId: Int, message: DcMsg) {
-        dc_send_msg(contextPointer, UInt32(chatId), message.messagePointer)
+    public func sendMessage(chatId: Int, message: DcMsg) -> Int {
+        return Int(dc_send_msg(contextPointer, UInt32(chatId), message.messagePointer))
     }
 
     public func downloadFullMessage(id: Int) {
@@ -601,6 +612,72 @@ public class DcContext {
         dc_set_location(contextPointer, latitude, longitude, accuracy)
     }
 
+    public func getLocations(chatId: Int, timestampBegin: Int64, timestampEnd: Int64, lastLocationId: Int) -> (String, Int) {
+        var names = [Int: String]()
+        var colors = [Int: String]()
+        var maxLocationId = 0
+
+        let jsonEncoder = JSONEncoder()
+        var json: String
+        json = "["
+            let array = dc_get_locations(contextPointer, UInt32(chatId), 0, timestampBegin, timestampEnd)
+            let arrayCnt = dc_array_get_cnt(array)
+            for i in (0 ..< arrayCnt).reversed() { // most recent position is reported last
+                let locationId = Int(dc_array_get_id(array, i))
+                if locationId > lastLocationId {
+                    maxLocationId = max(maxLocationId, locationId)
+                    if json != "[" {
+                        json += "," // JSON is picky about commas after the last element
+                    }
+
+                    let contactId = Int(dc_array_get_contact_id(array, i))
+                    if names[contactId] == nil {
+                        let contact = getContact(id: contactId)
+                        names[contactId] = contact.displayName
+                        colors[contactId] = contact.color.hexValue
+                    }
+
+                    let isIndependet = dc_array_is_independent(array, i) != 0
+                    var label: String = ""
+                    var name: String = names[contactId] ?? "ErrName"
+                    if isIndependet {
+                        if let cString = dc_array_get_marker(array, i) {
+                            label = String(cString: cString) // get_marker() returns one-char labels only
+                            dc_str_unref(cString)
+                        } else {
+                            let msgId = Int(dc_array_get_msg_id(array, i))
+                            if msgId != 0 {
+                                label = String((getMessage(id: msgId).text ?? "").prefix(256))
+                            }
+                        }
+                    }
+
+                    let jsonName = (try? String(data: jsonEncoder.encode(name), encoding: .utf8) ?? "\"\"")  ?? "\"\""
+                    let jsonLabel = (try? String(data: jsonEncoder.encode(label), encoding: .utf8) ?? "\"\"")  ?? "\"\""
+                    json += """
+                        {
+                            "payload": {
+                                "action": "pos",
+                                "contactId": \(contactId),
+                                "lat": \(dc_array_get_latitude(array, i)),
+                                "lng": \(dc_array_get_longitude(array, i)),
+                                "independent": \(isIndependet),
+                                "timestamp": \(dc_array_get_timestamp(array, i)),
+                                "label": \(jsonLabel),
+                                "name": \(jsonName),
+                                "color": "\(colors[contactId] ?? "#ff0000")"
+                            },
+                            "serial": \(locationId),
+                            "max_serial": \(locationId)
+                        }
+                    """
+                }
+            }
+            dc_array_unref(array)
+        json += "]"
+        return (json, maxLocationId)
+    }
+
     public func searchMessages(chatId: Int = 0, searchText: String) -> [Int] {
         let start = CFAbsoluteTimeGetCurrent()
         guard let arrayPointer = dc_search_msgs(contextPointer, UInt32(chatId), searchText) else {
@@ -1219,6 +1296,10 @@ public class DcMsg {
         dc_msg_set_dimension(messagePointer, Int32(width), Int32(height))
     }
 
+    public func setLocation(lat: Double, lng: Double) {
+        dc_msg_set_location(messagePointer, lat, lng)
+    }
+
     public var filesize: Int {
         return Int(dc_msg_get_filebytes(messagePointer))
     }

+ 17 - 0
DcCore/DcCore/DC/events.swift

@@ -13,6 +13,7 @@ public let dcEphemeralTimerModified =  Notification.Name(rawValue: "dcEphemeralT
 public let dcMsgsNoticed = Notification.Name(rawValue: "dcMsgsNoticed")
 public let dcNotificationConnectivityChanged = Notification.Name(rawValue: "dcNotificationConnectivityChanged")
 public let dcNotificationWebxdcUpdate = Notification.Name(rawValue: "dcNotificationWebxdcUpdate")
+public let dcNotificationLocationChanged = Notification.Name(rawValue: "dcNotificationLocationChanged")
 
 public class DcEventHandler {
     let dcAccounts: DcAccounts
@@ -247,6 +248,22 @@ public class DcEventHandler {
                 )
             }
 
+        case DC_EVENT_LOCATION_CHANGED:
+            if dcContext.id != dcAccounts.getSelected().id {
+                return
+            }
+            dcContext.logger?.info("location changed for contact \(data1)")
+            DispatchQueue.main.async {
+                let nc = NotificationCenter.default
+                nc.post(
+                    name: dcNotificationLocationChanged,
+                    object: nil,
+                    userInfo: [
+                        "contact_id": Int(data1),
+                    ]
+                )
+            }
+
         default:
             dcContext.logger?.warning("unknown event: \(id)")
         }

+ 12 - 0
DcCore/DcCore/Extensions/UIColor+Extensions.swift

@@ -64,4 +64,16 @@ public extension UIColor {
         return UIColor(red: red / 255, green: green / 255, blue: blue / 255, alpha: 1)
     }
 
+    var hexValue: String {
+        var color = self
+        if color.cgColor.numberOfComponents < 4 {
+            let c = color.cgColor.components!
+            color = UIColor(red: c[0], green: c[0], blue: c[0], alpha: c[1])
+        }
+        if color.cgColor.colorSpace!.model != .rgb {
+            return "#FFFFFF"
+        }
+        let c = color.cgColor.components!
+        return String(format: "#%02X%02X%02X", Int(c[0]*255.0), Int(c[1]*255.0), Int(c[2]*255.0))
+    }
 }

+ 4 - 0
deltachat-ios.xcodeproj/project.pbxproj

@@ -205,6 +205,7 @@
 		B26B3BC7236DC3DC008ED35A /* SwitchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B26B3BC6236DC3DC008ED35A /* SwitchCell.swift */; };
 		B2C42570265C325C00B95377 /* MultilineLabelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C4256F265C325C00B95377 /* MultilineLabelCell.swift */; };
 		B2D4B63B29C38D1900B47DA8 /* ChatsAndMediaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D4B63A29C38D1900B47DA8 /* ChatsAndMediaViewController.swift */; };
+		B2EE33F02A0FB86A00AAC762 /* MapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2EE33EF2A0FB86A00AAC762 /* MapViewController.swift */; };
 		B2F899E129F96A67003797D5 /* AllMediaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2F899E029F96A67003797D5 /* AllMediaViewController.swift */; };
 /* End PBXBuildFile section */
 
@@ -561,6 +562,7 @@
 		B2D729E927C57B9000A4E0BE /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
 		B2D729EA27C57B9000A4E0BE /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		B2D729EB27C57B9000A4E0BE /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
+		B2EE33EF2A0FB86A00AAC762 /* MapViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapViewController.swift; sourceTree = "<group>"; };
 		B2F899E029F96A67003797D5 /* AllMediaViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllMediaViewController.swift; sourceTree = "<group>"; };
 		B9CDCE77DAE9389E205F094C /* Pods-DcShare.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DcShare.release.xcconfig"; path = "Target Support Files/Pods-DcShare/Pods-DcShare.release.xcconfig"; sourceTree = "<group>"; };
 		D30610767F4AF8040B739987 /* Pods-deltachat-ios.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-deltachat-ios.debug.xcconfig"; path = "Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios.debug.xcconfig"; sourceTree = "<group>"; };
@@ -908,6 +910,7 @@
 				B28D25882913CE8600B9067F /* Settings */,
 				AE18F28B228C17630007B1BE /* AccountSetup */,
 				B2F899E029F96A67003797D5 /* AllMediaViewController.swift */,
+				B2EE33EF2A0FB86A00AAC762 /* MapViewController.swift */,
 				B259D64229B771D5008FB706 /* BackupTransferViewController.swift */,
 				30DDCBEA28FCA21800465D22 /* AccountSwitchViewController.swift */,
 				30DDCBE828FCA1F900465D22 /* PartialScreenPresentationController.swift */,
@@ -1427,6 +1430,7 @@
 				AEE6EC3F2282C59C00EDC689 /* GroupMembersViewController.swift in Sources */,
 				B26B3BC7236DC3DC008ED35A /* SwitchCell.swift in Sources */,
 				AEE700252438E0E500D6992E /* ProgressAlertHandler.swift in Sources */,
+				B2EE33F02A0FB86A00AAC762 /* MapViewController.swift in Sources */,
 				30E348E524F6647D005C93D1 /* FileTextCell.swift in Sources */,
 				30238CFD28A5028300EF14AC /* WebxdcGridCell.swift in Sources */,
 				3080A036277DE30100E74565 /* NSMutableAttributedString+Extensions.swift in Sources */,

BIN
deltachat-ios/Assets/maps.xdc


+ 17 - 1
deltachat-ios/Controller/AllMediaViewController.swift

@@ -47,6 +47,14 @@ class AllMediaViewController: UIPageViewController {
         return control
     }()
 
+    private lazy var mapButton: UIBarButtonItem = {
+        if #available(iOS 13.0, *) {
+            return UIBarButtonItem(image: UIImage(systemName: "map"), style: .plain, target: self, action: #selector(showMap))
+        } else {
+            return UIBarButtonItem(title: String.localized("tab_map"), style: .plain, target: self, action: #selector(showMap))
+        }
+    }()
+
     init(dcContext: DcContext, chatId: Int = 0) {
         self.dcContext = dcContext
         self.chatId = chatId
@@ -65,7 +73,6 @@ class AllMediaViewController: UIPageViewController {
         delegate = self
         navigationItem.titleView = segmentControl
 
-
         setViewControllers(
             [makeViewController(pages[0])],
             direction: .forward,
@@ -78,6 +85,11 @@ class AllMediaViewController: UIPageViewController {
         }
     }
 
+    override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+        navigationItem.rightBarButtonItem = chatId == 0 && UserDefaults.standard.bool(forKey: "location_streaming") ? mapButton : nil
+    }
+
     // MARK: - actions
     @objc private func segmentControlChanged(_ sender: UISegmentedControl) {
         if sender.selectedSegmentIndex < pages.count {
@@ -88,6 +100,10 @@ class AllMediaViewController: UIPageViewController {
         }
     }
 
+    @objc private func showMap() {
+        navigationController?.pushViewController(MapViewController(dcContext: dcContext, chatId: chatId), animated: true)
+    }
+
     // MARK: - factory
     private func makeViewController(_ page: Page) -> UIViewController {
         if page.type1 == DC_MSG_IMAGE {

+ 22 - 0
deltachat-ios/Controller/ContactDetailViewController.swift

@@ -90,6 +90,20 @@ class ContactDetailViewController: UITableViewController {
         return cell
     }()
 
+    private lazy var locationsCell: UITableViewCell = {
+        let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
+        cell.textLabel?.text = String.localized("locations")
+        if #available(iOS 13.0, *) {
+            cell.imageView?.image = UIImage(systemName: "map") // added in ios13
+        }
+        cell.accessoryType = .disclosureIndicator
+        if viewModel.chatId == 0 {
+            cell.isUserInteractionEnabled = false
+            cell.textLabel?.isEnabled = false
+        }
+        return cell
+    }()
+
     private lazy var statusCell: MultilineLabelCell = {
         let cell = MultilineLabelCell()
         cell.multilineDelegate = self
@@ -172,6 +186,8 @@ class ContactDetailViewController: UITableViewController {
             switch viewModel.chatOptionFor(row: row) {
             case .allMedia:
                 return allMediaCell
+            case .locations:
+                return locationsCell
             case .ephemeralMessages:
                 return ephemeralMessagesCell
             case .startChat:
@@ -341,6 +357,8 @@ class ContactDetailViewController: UITableViewController {
         switch action {
         case .allMedia:
             showAllMedia()
+        case .locations:
+            showLocations()
         case .ephemeralMessages:
             showEphemeralMessagesController()
         case .startChat:
@@ -491,6 +509,10 @@ class ContactDetailViewController: UITableViewController {
         navigationController?.pushViewController(AllMediaViewController(dcContext: viewModel.context, chatId: viewModel.chatId), animated: true)
     }
 
+    private func showLocations() {
+        navigationController?.pushViewController(MapViewController(dcContext: viewModel.context, chatId: viewModel.chatId), animated: true)
+    }
+
     private func showSearch() {
         if let chatViewController = navigationController?.viewControllers.last(where: {
             $0 is ChatViewController

+ 25 - 4
deltachat-ios/Controller/GroupChatDetailViewController.swift

@@ -13,6 +13,7 @@ class GroupChatDetailViewController: UIViewController {
 
     enum ChatOption {
         case allMedia
+        case locations
         case ephemeralMessages
     }
 
@@ -134,6 +135,16 @@ class GroupChatDetailViewController: UIViewController {
         return cell
     }()
 
+    private lazy var locationsCell: UITableViewCell = {
+        let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
+        cell.textLabel?.text = String.localized("locations")
+        if #available(iOS 13.0, *) {
+            cell.imageView?.image = UIImage(systemName: "map") // added in ios13
+        }
+        cell.accessoryType = .disclosureIndicator
+        return cell
+    }()
+
     init(chatId: Int, dcContext: DcContext) {
         self.dcContext = dcContext
         self.chatId = chatId
@@ -271,23 +282,25 @@ class GroupChatDetailViewController: UIViewController {
     private func updateOptions() {
         self.editBarButtonItem.isEnabled = chat.isMailinglist || chat.canSend
 
+        self.chatOptions = [.allMedia]
+        if UserDefaults.standard.bool(forKey: "location_streaming") {
+            self.chatOptions.append(.locations)
+        }
+
         if chat.isMailinglist {
-            self.chatOptions = [.allMedia]
             self.memberManagementRows = 0
             self.chatActions = [.archiveChat, .copyToClipboard, .clearChat, .deleteChat]
             self.groupHeader.showMuteButton(show: true)
         } else if chat.isBroadcast {
-            self.chatOptions = [.allMedia]
             self.memberManagementRows = 1
             self.chatActions = [.archiveChat, .clearChat, .deleteChat]
             self.groupHeader.showMuteButton(show: false)
         } else if chat.canSend {
-            self.chatOptions = [.allMedia, .ephemeralMessages]
+            self.chatOptions.append(.ephemeralMessages)
             self.memberManagementRows = 2
             self.chatActions = [.archiveChat, .leaveGroup, .clearChat, .deleteChat]
             self.groupHeader.showMuteButton(show: true)
         } else {
-            self.chatOptions = [.allMedia]
             self.memberManagementRows = 0
             self.chatActions = [.archiveChat, .clearChat, .deleteChat]
             self.groupHeader.showMuteButton(show: true)
@@ -408,6 +421,10 @@ class GroupChatDetailViewController: UIViewController {
         navigationController?.pushViewController(AllMediaViewController(dcContext: dcContext, chatId: chatId), animated: true)
     }
 
+    private func showLocations() {
+        navigationController?.pushViewController(MapViewController(dcContext: dcContext, chatId: chatId), animated: true)
+    }
+
     private func showSearch() {
         if let chatViewController = navigationController?.viewControllers.last(where: {
             $0 is ChatViewController
@@ -470,6 +487,8 @@ extension GroupChatDetailViewController: UITableViewDelegate, UITableViewDataSou
             switch chatOptions[row] {
             case .allMedia:
                 return allMediaCell
+            case .locations:
+                return locationsCell
             case .ephemeralMessages:
                 return ephemeralMessagesCell
             }
@@ -528,6 +547,8 @@ extension GroupChatDetailViewController: UITableViewDelegate, UITableViewDataSou
             switch chatOptions[row] {
             case .allMedia:
                 showAllMedia()
+            case .locations:
+                showLocations()
             case .ephemeralMessages:
                 showEphemeralMessagesController()
             }

+ 82 - 0
deltachat-ios/Controller/MapViewController.swift

@@ -0,0 +1,82 @@
+import UIKit
+import WebKit
+import DcCore
+
+class MapViewController: WebxdcViewController {
+    private let chatId: Int
+    private var locationChangedObserver: NSObjectProtocol?
+    private var lastLocationId: Int = 0
+
+    init(dcContext: DcContext, chatId: Int) {
+        self.chatId = chatId
+        var msgId = UserDefaults.standard.integer(forKey: "maps_webxdc_msg_id16")
+        if !dcContext.msgExists(id: msgId) {
+            if let path = Bundle.main.url(forResource: "maps", withExtension: "xdc", subdirectory: "Assets") {
+                let chatId = dcContext.createChatByContactId(contactId: Int(DC_CONTACT_ID_SELF))
+                let msg = dcContext.newMessage(viewType: DC_MSG_WEBXDC)
+                msg.setFile(filepath: path.path)
+                msgId = dcContext.sendMessage(chatId: chatId, message: msg) // TODO: this should be hidden by core somehow
+                UserDefaults.standard.setValue(msgId, forKey: "maps_webxdc_msg_id16")
+            }
+        }
+        super.init(dcContext: dcContext, messageId: msgId)
+    }
+
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        title = String.localized(chatId == 0 ? "menu_show_global_map" : "locations")
+        navigationItem.rightBarButtonItem = nil
+    }
+
+    override func willMove(toParent parent: UIViewController?) {
+        super.willMove(toParent: parent)
+        if parent == nil {
+            removeObservers()
+        } else {
+            addObservers()
+        }
+    }
+
+    // MARK: - setup
+
+    private func addObservers() {
+        locationChangedObserver = NotificationCenter.default.addObserver(forName: dcNotificationLocationChanged, object: nil, queue: nil) { [weak self]_ in
+            self?.updateWebxdc()
+        }
+    }
+
+    private func removeObservers() {
+        if let locationChangedObserver = self.locationChangedObserver {
+            NotificationCenter.default.removeObserver(locationChangedObserver)
+        }
+    }
+
+
+    // MARK: - handle updates
+
+    override func sendWebxdcStatusUpdate(payload: String, description: String) -> Bool {
+        guard let data: Data = payload.data(using: .utf8),
+              let dict = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String: AnyObject],
+              let payload = dict["payload"] as? [String: AnyObject] else {
+           return false
+        }
+
+        let msg = dcContext.newMessage(viewType: DC_MSG_TEXT)
+        msg.text = payload["text"] as? String ?? "ErrText"
+        msg.setLocation(lat: payload["lat"] as? Double ?? 0.0, lng: payload["lng"] as? Double ?? 0.0)
+        return dcContext.sendMessage(chatId: chatId == 0 ? dcContext.createChatByContactId(contactId: Int(DC_CONTACT_ID_SELF)) : chatId, message: msg) != 0
+    }
+
+    override func getWebxdcStatusUpdates(lastKnownSerial: Int) -> String {
+        let end = Int64(Date().timeIntervalSince1970)
+        let begin = end - 24*60*60
+        let (json, maxLocationId) = dcContext.getLocations(chatId: chatId, timestampBegin: begin, timestampEnd: 0, lastLocationId: lastLocationId)
+        lastLocationId = max(maxLocationId, lastLocationId)
+        UIPasteboard.general.string = json // TODO: remove this line, useful for debugging to get JSON out
+        return json
+    }
+}

+ 11 - 4
deltachat-ios/Controller/WebxdcViewController.swift

@@ -384,7 +384,7 @@ class WebxdcViewController: WebViewViewController {
         }
     }
 
-    private func updateWebxdc() {
+    func updateWebxdc() {
         webView.evaluateJavaScript("window.__webxdcUpdate()", completionHandler: nil)
     }
 
@@ -418,6 +418,14 @@ class WebxdcViewController: WebViewViewController {
             UIApplication.shared.open(url)
         }
     }
+
+    func sendWebxdcStatusUpdate(payload: String, description: String) -> Bool {
+        return dcContext.sendWebxdcStatusUpdate(msgId: messageId, payload: payload, description: description)
+    }
+
+    func getWebxdcStatusUpdates(lastKnownSerial: Int) -> String {
+        return dcContext.getWebxdcStatusUpdates(msgId: messageId, lastKnownSerial: lastKnownSerial)
+    }
 }
 
 extension WebxdcViewController: WKScriptMessageHandler {
@@ -440,7 +448,7 @@ extension WebxdcViewController: WKScriptMessageHandler {
                       logger.error("Failed to parse status update parameters \(message.body)")
                       return
                   }
-            _ = dcContext.sendWebxdcStatusUpdate(msgId: messageId, payload: payloadString, description: description)
+            _ = sendWebxdcStatusUpdate(payload: payloadString, description: description)
 
         case .sendToChat:
             if let dict = message.body as? [String: AnyObject] {
@@ -481,8 +489,7 @@ extension WebxdcViewController: WKURLSchemeHandler {
             let statusCode: Int
             if url.path == "/webxdc-update.json" || url.path == "webxdc-update.json" {
                 let lastKnownSerial = Int(url.query ?? "0") ?? 0
-                data = Data(
-                    dcContext.getWebxdcStatusUpdates(msgId: messageId, lastKnownSerial: lastKnownSerial).utf8)
+                data = Data(getWebxdcStatusUpdates(lastKnownSerial: lastKnownSerial).utf8)
                 mimeType = "application/json; charset=utf-8"
                 statusCode = 200
             } else {

+ 7 - 2
deltachat-ios/ViewModel/ContactDetailViewModel.swift

@@ -14,6 +14,7 @@ class ContactDetailViewModel {
 
     enum ChatOption {
         case allMedia
+        case locations
         case ephemeralMessages
         case startChat
     }
@@ -70,8 +71,12 @@ class ContactDetailViewModel {
         }
         sections.append(.chatActions)
 
+        chatOptions = [.allMedia]
+        if UserDefaults.standard.bool(forKey: "location_streaming") {
+            chatOptions.append(.locations)
+        }
+
         if chatId != 0 {
-            chatOptions = [.allMedia]
             if !isDeviceTalk {
                 chatOptions.append(.ephemeralMessages)
             }
@@ -88,7 +93,7 @@ class ContactDetailViewModel {
             chatActions.append(.clearChat)
             chatActions.append(.deleteChat)
         } else {
-            chatOptions = [.allMedia, .startChat]
+            chatOptions = [.startChat]
             chatActions = [.showEncrInfo, .copyToClipboard, .blockContact]
         }
     }