瀏覽代碼

implement empty states (no messages) #428

cyberta 5 年之前
父節點
當前提交
c04d9f0dc6

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

@@ -84,6 +84,7 @@
 		3059620C2346125100C80F33 /* MessageSizeCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305961CB2346125100C80F33 /* MessageSizeCalculator.swift */; };
 		3059620E234614E700C80F33 /* DcContact+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3059620D234614E700C80F33 /* DcContact+Extension.swift */; };
 		305962102346154D00C80F33 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3059620F2346154D00C80F33 /* String+Extension.swift */; };
+		305FE03623A81B4C0053BE90 /* PaddingLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305FE03523A81B4C0053BE90 /* PaddingLabel.swift */; };
 		3060119C22DDE24000C1CE6F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3060119E22DDE24000C1CE6F /* Localizable.strings */; };
 		306011B622E5E7FB00C1CE6F /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 306011B422E5E7FB00C1CE6F /* Localizable.stringsdict */; };
 		3095A351237DD1F700AB07F7 /* MediaPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3095A350237DD1F700AB07F7 /* MediaPicker.swift */; };
@@ -258,6 +259,7 @@
 		305961CB2346125100C80F33 /* MessageSizeCalculator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageSizeCalculator.swift; sourceTree = "<group>"; };
 		3059620D234614E700C80F33 /* DcContact+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DcContact+Extension.swift"; sourceTree = "<group>"; };
 		3059620F2346154D00C80F33 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = "<group>"; };
+		305FE03523A81B4C0053BE90 /* PaddingLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaddingLabel.swift; sourceTree = "<group>"; };
 		3060119D22DDE24000C1CE6F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
 		3060119F22DDE24500C1CE6F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
 		306011A022DDE24700C1CE6F /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -729,6 +731,7 @@
 				AE52EA18229EB53C00C586C9 /* ContactDetailHeader.swift */,
 				AE9DAF0E22C278C6004C9591 /* ChatTitleView.swift */,
 				30F9B9EB235F2116006E7ACF /* MessageCounter.swift */,
+				305FE03523A81B4C0053BE90 /* PaddingLabel.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -1093,6 +1096,7 @@
 				AEE56D80225504DB007DC082 /* Extensions.swift in Sources */,
 				7A0052C81FBE6CB40048C3BF /* NewContactController.swift in Sources */,
 				AEE56D762253431E007DC082 /* AccountSetupController.swift in Sources */,
+				305FE03623A81B4C0053BE90 /* PaddingLabel.swift in Sources */,
 				AEACE2DD1FB323CA00DCDD78 /* ChatViewController.swift in Sources */,
 				AEE6EC412282DF5700EDC689 /* MailboxViewController.swift in Sources */,
 				AEE6EC482283045D00EDC689 /* EditSettingsController.swift in Sources */,

+ 47 - 0
deltachat-ios/Controller/ChatViewController.swift

@@ -60,6 +60,13 @@ class ChatViewController: MessagesViewController {
     var previewView: UIView?
     var previewController: PreviewController?
 
+    var emptyStateView: PaddingLabel = {
+        let view =  PaddingLabel()
+        view.backgroundColor = DcColors.systemMessageBackgroundColor
+        view.textColor = DcColors.defaultTextColor
+        return view
+    }()
+
     override var inputAccessoryView: UIView? {
         if disableWriting {
             return nil
@@ -89,6 +96,7 @@ class ChatViewController: MessagesViewController {
             return
         }
         configureMessageCollectionView()
+        configureEmptyStateView()
 
         if !disableWriting {
             configureMessageInputBar()
@@ -99,6 +107,14 @@ class ChatViewController: MessagesViewController {
         loadFirstMessages()
     }
 
+    private func configureEmptyStateView() {
+        view.addSubview(emptyStateView)
+        view.addConstraints([emptyStateView.constraintCenterYTo(view),
+                             emptyStateView.constraintCenterXTo(view),
+                             emptyStateView.constraintAlignLeadingTo(view, paddingLeading: 40),
+                             emptyStateView.constraintAlignTrailingTo(view, paddingTrailing: 40)])
+    }
+
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
         // this will be removed in viewWillDisappear
@@ -236,6 +252,7 @@ class ChatViewController: MessagesViewController {
                 if self.isLastSectionVisible() {
                     self.messagesCollectionView.scrollToBottom(animated: true)
                 }
+                self.showEmptyStateView(self.messageList.isEmpty)
             }
         }
     }
@@ -247,7 +264,36 @@ class ChatViewController: MessagesViewController {
                 self.messagesCollectionView.reloadData()
                 self.refreshControl.endRefreshing()
                 self.messagesCollectionView.scrollToBottom(animated: false)
+                self.showEmptyStateView(self.messageList.isEmpty)
+            }
+        }
+    }
+
+    private func showEmptyStateView(_ show: Bool) {
+        if show {
+            let dcChat = DcChat(id: chatId)
+            if chatId == DC_CHAT_ID_DEADDROP {
+                if DcConfig.showEmails != DC_SHOW_EMAILS_ALL {
+                    emptyStateView.text = String.localized("chat_no_contact_requests")
+                } else {
+                    emptyStateView.text = String.localized("chat_no_messages")
+                }
+            } else if dcChat.isGroup {
+                if dcChat.isUnpromoted {
+                    emptyStateView.text = String.localized("chat_new_group_hint")
+                } else {
+                    emptyStateView.text = String.localized("chat_no_messages")
+                }
+            } else if dcChat.isSelfTalk {
+                emptyStateView.text = String.localized("saved_messages_explain")
+            } else if dcChat.isDeviceTalk {
+                emptyStateView.text = String.localized("device_talk_explain")
+            } else {
+                emptyStateView.text = String.localizedStringWithFormat(String.localized("chat_no_messages_hint"), dcChat.name, dcChat.name)
             }
+            emptyStateView.isHidden = false
+        } else {
+            emptyStateView.isHidden = true
         }
     }
 
@@ -769,6 +815,7 @@ extension ChatViewController: MessagesDataSource {
     func insertMessage(_ message: DcMsg) {
         dc_markseen_msgs(mailboxPointer, UnsafePointer([UInt32(message.id)]), 1)
         messageList.append(message)
+        emptyStateView.isHidden = true
         // Reload last section to update header/footer labels and insert a new one
         messagesCollectionView.performBatchUpdates({
             messagesCollectionView.insertSections([messageList.count - 1])

+ 4 - 0
deltachat-ios/DC/Wrapper.swift

@@ -447,6 +447,10 @@ class DcChat {
         return UIColor(netHex: Int(dc_chat_get_color(chatPointer)))
     }
 
+    var isUnpromoted: Bool {
+        return Int(dc_chat_is_unpromoted(chatPointer)) != 0
+    }
+
     var isGroup: Bool {
         let type = Int(dc_chat_get_type(chatPointer))
         return type == DC_CHAT_TYPE_GROUP || type == DC_CHAT_TYPE_VERIFIED_GROUP

+ 37 - 0
deltachat-ios/View/PaddingLabel.swift

@@ -0,0 +1,37 @@
+import UIKit
+
+class PaddingLabel: UILabel {
+
+    var topInset: CGFloat = 16
+    var bottomInset: CGFloat = 16
+    var leftInset: CGFloat = 16
+    var rightInset: CGFloat = 16
+
+    required init() {
+        super.init(frame: CGRect.zero)
+        numberOfLines = 0
+
+        sizeToFit()
+        layer.cornerRadius = 16
+        clipsToBounds = true
+        self.translatesAutoresizingMaskIntoConstraints = false
+    }
+
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    override func drawText(in rect: CGRect) {
+        let insets = UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
+        super.drawText(in: rect.inset(by: insets))
+    }
+
+    override var intrinsicContentSize: CGSize {
+        get {
+            var contentSize = super.intrinsicContentSize
+            contentSize.height += topInset + bottomInset
+            contentSize.width += leftInset + rightInset
+            return contentSize
+        }
+    }
+}