浏览代码

Merge pull request #1300 from deltachat/connectivity_view

Connectivity view
cyBerta 4 年之前
父节点
当前提交
01690683b7

+ 15 - 0
DcCore/DcCore/DC/Wrapper.swift

@@ -47,6 +47,10 @@ public class DcAccounts {
         dc_accounts_maybe_network(accountsPointer)
     }
 
+    public func maybeNetworkLost() {
+        dc_accounts_maybe_network_lost(accountsPointer)
+    }
+
     public func maybeStartIo() {
         if getSelected().isConfigured() {
             dc_accounts_start_io(accountsPointer)
@@ -319,6 +323,17 @@ public class DcContext {
         return "ErrGetContactEncrInfo"
     }
 
+    public func getConnectivity() -> Int32 {
+        return dc_get_connectivity(contextPointer)
+    }
+
+    public func getConnectivityHtml() -> String {
+        guard let cString = dc_get_connectivity_html(contextPointer) else { return ""}
+        let swiftString = String(cString: cString)
+        dc_str_unref(cString)
+        return swiftString
+    }
+
     public func setStockTranslation(id: Int32, localizationKey: String) {
         dc_set_stock_translation(contextPointer, UInt32(id), String.localized(localizationKey))
     }

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

@@ -11,6 +11,7 @@ public let dcNotificationContactChanged = Notification.Name(rawValue: "MrEventCo
 public let dcNotificationChatModified = Notification.Name(rawValue: "dcNotificationChatModified")
 public let dcEphemeralTimerModified =  Notification.Name(rawValue: "dcEphemeralTimerModified")
 public let dcMsgsNoticed = Notification.Name(rawValue: "dcMsgsNoticed")
+public let dcNotificationConnectivityChanged = Notification.Name(rawValue: "dcNotificationConnectivityChanged")
 
 public class DcEventHandler {
     let dcAccounts: DcAccounts
@@ -225,6 +226,20 @@ public class DcEventHandler {
                 )
             }
 
+        case DC_EVENT_CONNECTIVITY_CHANGED:
+            if dcContext.id != dcAccounts.getSelected().id {
+                return
+            }
+            dcContext.logger?.info("network: DC_EVENT_CONNECTIVITY_CHANGED: \(dcContext.getConnectivity())")
+            DispatchQueue.main.async {
+                let nc = NotificationCenter.default
+                nc.post(
+                    name: dcNotificationConnectivityChanged,
+                    object: nil,
+                    userInfo: nil
+                )
+            }
+
         default:
             dcContext.logger?.warning("unknown event: \(id)")
         }

+ 12 - 0
DcCore/DcCore/Helper/DcUtils.swift

@@ -153,4 +153,16 @@ public struct DcUtils {
 		return image
 	}
 
+    public static func getConnectivityString(dcContext: DcContext, connectedString: String) -> String {
+        let connectivity = dcContext.getConnectivity()
+        if connectivity >= DC_CONNECTIVITY_CONNECTED {
+            return connectedString
+        } else if connectivity >= DC_CONNECTIVITY_WORKING {
+            return String.localized("connectivity_getting_new_msgs")
+        } else if connectivity >= DC_CONNECTIVITY_CONNECTING {
+          return String.localized("connectivity_connecting")
+        } else {
+          return String.localized("connectivity_not_connected")
+        }
+    }
 }

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

@@ -28,6 +28,7 @@
 		302D5450268B6B2300A8B271 /* MessageUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302D544F268B6B2300A8B271 /* MessageUtils.swift */; };
 		302D5454268B84CB00A8B271 /* SettingsVideoChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302D5453268B84CB00A8B271 /* SettingsVideoChatViewController.swift */; };
 		302E1BB4252B5AB4008F4264 /* PlayButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302E1BB3252B5AB4008F4264 /* PlayButtonView.swift */; };
+		302E592426A5CF4800DD4F58 /* ConnectivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302E592326A5CF4800DD4F58 /* ConnectivityViewController.swift */; };
 		30349291256441E200A523D0 /* QuotePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30349290256441E200A523D0 /* QuotePreview.swift */; };
 		303492952565AABC00A523D0 /* DraftModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 303492942565AABC00A523D0 /* DraftModel.swift */; };
 		3034929F25752FC800A523D0 /* MediaPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3034929E25752FC800A523D0 /* MediaPreview.swift */; };
@@ -243,6 +244,7 @@
 		302D544F268B6B2300A8B271 /* MessageUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageUtils.swift; sourceTree = "<group>"; };
 		302D5453268B84CB00A8B271 /* SettingsVideoChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsVideoChatViewController.swift; sourceTree = "<group>"; };
 		302E1BB3252B5AB4008F4264 /* PlayButtonView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PlayButtonView.swift; path = "deltachat-ios/Chat/Views/PlayButtonView.swift"; sourceTree = SOURCE_ROOT; };
+		302E592326A5CF4800DD4F58 /* ConnectivityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectivityViewController.swift; sourceTree = "<group>"; };
 		30349290256441E200A523D0 /* QuotePreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuotePreview.swift; sourceTree = "<group>"; };
 		303492942565AABC00A523D0 /* DraftModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftModel.swift; sourceTree = "<group>"; };
 		3034929E25752FC800A523D0 /* MediaPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreview.swift; sourceTree = "<group>"; };
@@ -784,6 +786,7 @@
 				AEE6EC472283045D00EDC689 /* EditSettingsController.swift */,
 				AE851ACF227DF50900ED86F0 /* GroupChatDetailViewController.swift */,
 				AEE6EC3E2282C59C00EDC689 /* GroupMembersViewController.swift */,
+				302E592326A5CF4800DD4F58 /* ConnectivityViewController.swift */,
 				AE19887423EB264000B4CD5F /* HelpViewController.swift */,
 				304F769425DD237B0094B5E2 /* WebViewViewController.swift */,
 				304F769825DD23D70094B5E2 /* FullMessageViewController.swift */,
@@ -1302,6 +1305,7 @@
 				303492952565AABC00A523D0 /* DraftModel.swift in Sources */,
 				78E45E3A21D3CFBC00D4B15E /* SettingsController.swift in Sources */,
 				AE8519EA2272FDCA00ED86F0 /* DeviceContactsHandler.swift in Sources */,
+				302E592426A5CF4800DD4F58 /* ConnectivityViewController.swift in Sources */,
 				78ED838321D5379000243125 /* TextFieldCell.swift in Sources */,
 				305702A124C6453700D84EFC /* TypeAlias.swift in Sources */,
 				AE19887523EB264000B4CD5F /* HelpViewController.swift in Sources */,

+ 3 - 0
deltachat-ios/AppDelegate.swift

@@ -95,6 +95,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
 
         reachability.whenUnreachable = { _ in
             logger.info("network: not reachable")
+            DispatchQueue.global(qos: .background).async { [weak self] in
+                self?.dcAccounts.maybeNetworkLost()
+            }
         }
 
         do {

+ 36 - 3
deltachat-ios/Controller/ChatListController.swift

@@ -12,9 +12,19 @@ class ChatListController: UITableViewController {
     private var msgChangedObserver: NSObjectProtocol?
     private var msgsNoticedObserver: NSObjectProtocol?
     private var incomingMsgObserver: NSObjectProtocol?
+    private var connectivityChangedObserver: NSObjectProtocol?
 
     private weak var timer: Timer?
 
+    private lazy var titleView: UILabel = {
+        let view = UILabel()
+        let navTapGesture = UITapGestureRecognizer(target: self, action: #selector(onNavigationTitleTapped))
+        view.addGestureRecognizer(navTapGesture)
+        view.isUserInteractionEnabled = true
+        view.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
+        return view
+    }()
+
     private lazy var searchController: UISearchController = {
         let searchController = UISearchController(searchResultsController: nil)
         searchController.searchResultsUpdater = viewModel
@@ -82,7 +92,9 @@ class ChatListController: UITableViewController {
         dcContext.addDeviceMessage(label: "update_1_20b_ios", msg: msg)
 
         // create view
+        navigationItem.titleView = titleView
         updateTitle()
+
         viewModel.refreshData()
 
         if RelayHelper.sharedInstance.isForwarding() {
@@ -113,6 +125,12 @@ class ChatListController: UITableViewController {
             queue: nil) { [weak self] _ in
                 self?.refreshInBg()
             }
+        connectivityChangedObserver = nc.addObserver(forName: dcNotificationConnectivityChanged,
+                                                     object: nil,
+                                                     queue: nil) { [weak self] _ in
+                                                        self?.updateTitle()
+                                                     }
+
         nc.addObserver(
             self,
             selector: #selector(applicationDidBecomeActive(_:)),
@@ -140,6 +158,9 @@ class ChatListController: UITableViewController {
         if let msgsNoticedObserver = self.msgsNoticedObserver {
             nc.removeObserver(msgsNoticedObserver)
         }
+        if let connectivityChangedObserver = self.connectivityChangedObserver {
+            nc.removeObserver(connectivityChangedObserver)
+        }
         // remove non-block observers
         NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
         NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
@@ -148,6 +169,14 @@ class ChatListController: UITableViewController {
     // MARK: - setup
     private func setupSubviews() {
         emptySearchStateLabel.addCenteredTo(parentView: view)
+        navigationItem.backButtonTitle = String.localized("pref_chats")
+    }
+
+    @objc
+    public func onNavigationTitleTapped() {
+        logger.debug("on navigation title tapped")
+        let connectivityViewController = ConnectivityViewController(dcContext: dcContext)
+        navigationController?.pushViewController(connectivityViewController, animated: true)
     }
 
     // MARK: - configuration
@@ -341,15 +370,19 @@ class ChatListController: UITableViewController {
     // MARK: updates
     private func updateTitle() {
         if RelayHelper.sharedInstance.isForwarding() {
-            title = String.localized("forward_to")
+            titleView.text = String.localized("forward_to")
             if !viewModel.isArchive {
                 navigationItem.setLeftBarButton(cancelButton, animated: true)
             }
+        } else if viewModel.isArchive {
+            titleView.text = String.localized("chat_archived_chats_title")
+            navigationItem.setLeftBarButton(nil, animated: true)
+           
         } else {
-            title = viewModel.isArchive ? String.localized("chat_archived_chats_title") :
-                String.localized("pref_chats")
+            titleView.text = DcUtils.getConnectivityString(dcContext: dcContext, connectedString: String.localized("pref_chats"))
             navigationItem.setLeftBarButton(nil, animated: true)
         }
+        titleView.sizeToFit()
     }
 
     func handleChatListUpdate() {

+ 63 - 0
deltachat-ios/Controller/ConnectivityViewController.swift

@@ -0,0 +1,63 @@
+import UIKit
+import DcCore
+
+class ConnectivityViewController: WebViewViewController {
+    private let dcContext: DcContext
+    private var connectivityChangedObserver: NSObjectProtocol?
+
+    init(dcContext: DcContext) {
+        self.dcContext = dcContext
+        super.init()
+    }
+
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        self.title = String.localized("connectivity")
+        loadHtml()
+    }
+
+    override func viewDidAppear(_ animated: Bool) {
+        connectivityChangedObserver = NotificationCenter.default.addObserver(forName: dcNotificationConnectivityChanged,
+                                                     object: nil,
+                                                     queue: nil) { [weak self] _ in
+                                                        self?.loadHtml()
+                                                     }
+    }
+
+    override func viewDidDisappear(_ animated: Bool) {
+        if let connectivityChangedObserver = self.connectivityChangedObserver {
+            NotificationCenter.default.removeObserver(connectivityChangedObserver)
+        }
+    }
+
+    private func loadHtml() {
+        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
+            guard let self = self else { return }
+            let html = self.dcContext.getConnectivityHtml()
+                .replacingOccurrences(of: "</style>", with:
+                    """
+                    body {
+                        font-size: 13pt;
+                        font-family: -apple-system, sans-serif;
+                        padding: 0 .5rem .5rem .5rem;
+                        -webkit-text-size-adjust: none;
+                    }
+
+                    @media (prefers-color-scheme: dark) {
+                      body {
+                        background-color: black !important;
+                        color: #eee;
+                      }
+                    }
+                    </style>
+                    """)
+            DispatchQueue.main.async {
+                self.webView.loadHTMLString(html, baseURL: nil)
+            }
+        }
+    }
+}

+ 31 - 2
deltachat-ios/Controller/SettingsController.swift

@@ -27,6 +27,7 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         case mediaQuality = 12
         case switchAccount = 13
         case videoChat = 14
+        case connectivity = 15
     }
 
     private var dcContext: DcContext
@@ -35,11 +36,14 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
     private let externalPathDescr = "File Sharing/Delta Chat"
 
     let documentInteractionController = UIDocumentInteractionController()
+
+    private var connectivityChangedObserver: NSObjectProtocol?
+
+    // MARK: - ProgressAlertHandler
     weak var progressAlert: UIAlertController?
     var progressObserver: NSObjectProtocol?
 
     // MARK: - cells
-
     private lazy var profileCell: ContactCell = {
         let cell = ContactCell(style: .default, reuseIdentifier: nil)
         let cellViewModel = ProfileViewModel(context: dcContext)
@@ -195,6 +199,14 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         return cell
     }()
 
+    private lazy var connectivityCell: UITableViewCell = {
+        let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
+        cell.tag = CellTags.connectivity.rawValue
+        cell.textLabel?.text = String.localized("connectivity")
+        cell.accessoryType = .disclosureIndicator
+        return cell
+    }()
+
     private lazy var sections: [SectionConfigs] = {
         var appNameAndVersion = "Delta Chat"
         if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
@@ -222,7 +234,7 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         let helpSection = SectionConfigs(
             headerTitle: nil,
             footerTitle: appNameAndVersion,
-            cells: [helpCell]
+            cells: [connectivityCell, helpCell]
         )
         return [profileSection, preferencesSection, autocryptSection, backupSection, helpSection]
     }()
@@ -258,6 +270,13 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
             guard let self = self else { return }
             self.progressAlert?.dismiss(animated: true, completion: nil)
         }
+        connectivityChangedObserver = NotificationCenter.default.addObserver(forName: dcNotificationConnectivityChanged,
+                                                                             object: nil,
+                                                                             queue: nil) { [weak self] _ in
+            guard let self = self else { return }
+            self.connectivityCell.detailTextLabel?.text = DcUtils.getConnectivityString(dcContext: self.dcContext,
+                                                                                        connectedString: String.localized("connectivity_connected"))
+        }
     }
 
     override func viewDidDisappear(_ animated: Bool) {
@@ -266,6 +285,9 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         if let backupProgressObserver = self.progressObserver {
             nc.removeObserver(backupProgressObserver)
         }
+        if let connectivityChangedObserver = self.connectivityChangedObserver {
+            NotificationCenter.default.removeObserver(connectivityChangedObserver)
+        }
     }
 
     // MARK: - UITableViewDelegate + UITableViewDatasource
@@ -314,6 +336,7 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         case .advanced: showAdvancedDialog()
         case .switchAccount: showSwitchAccountMenu()
         case .help: showHelp()
+        case .connectivity: showConnectivity()
         }
     }
 
@@ -522,6 +545,8 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         mediaQualityCell.detailTextLabel?.text = MediaQualityController.getValString(val: dcContext.getConfigInt("media_quality"))
         videoChatInstanceCell.detailTextLabel?.text = dcContext.getConfig("webrtc_instance")
         autodelCell.detailTextLabel?.text = autodelSummary()
+        connectivityCell.detailTextLabel?.text = DcUtils.getConnectivityString(dcContext: dcContext,
+                                                                               connectedString: String.localized("connectivity_connected"))
     }
 
     // MARK: - coordinator
@@ -564,6 +589,10 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         navigationController?.pushViewController(HelpViewController(), animated: true)
     }
 
+    private func showConnectivity() {
+        navigationController?.pushViewController(ConnectivityViewController(dcContext: dcContext), animated: true)
+    }
+
     public static func showDebugToolkit(dcContext: DcContext) {
         var info = ""
 

+ 6 - 0
deltachat-ios/Coordinator/AppCoordinator.swift

@@ -129,6 +129,12 @@ class AppCoordinator {
         } else {
             presentWelcomeController()
         }
+
+        // make sure, we use the same font in all titles,
+        // here and in the custom chatlist title
+        // (according to https://learnui.design/blog/ios-font-size-guidelines.html )
+        // (it would be a bit nicer, if we would query the system font and pass it to chatlist, but well :)
+        UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17, weight: .semibold)]
     }
 
     func presentWelcomeController() {