Selaa lähdekoodia

added time label

nayooti 5 vuotta sitten
vanhempi
commit
7c4d97ba06

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

@@ -150,6 +150,7 @@
 		AE76E5EE242BF2EA003CF461 /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE76E5ED242BF2EA003CF461 /* WelcomeViewController.swift */; };
 		AE77838D23E32ED20093EABD /* ContactDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE77838C23E32ED20093EABD /* ContactDetailViewModel.swift */; };
 		AE77838F23E4276D0093EABD /* ContactCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE77838E23E4276D0093EABD /* ContactCellViewModel.swift */; };
+		AE83F53A2487D6F900DDDA04 /* GalleryTimeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE83F5392487D6F900DDDA04 /* GalleryTimeLabel.swift */; };
 		AE8519EA2272FDCA00ED86F0 /* DeviceContactsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE8519E92272FDCA00ED86F0 /* DeviceContactsHandler.swift */; };
 		AE851A04227AECDE00ED86F0 /* deltachat_iosTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851A03227AECDE00ED86F0 /* deltachat_iosTests.swift */; };
 		AE851AC5227C755A00ED86F0 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851AC4227C755A00ED86F0 /* Protocols.swift */; };
@@ -434,6 +435,7 @@
 		AE76E5ED242BF2EA003CF461 /* WelcomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WelcomeViewController.swift; sourceTree = "<group>"; };
 		AE77838C23E32ED20093EABD /* ContactDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactDetailViewModel.swift; sourceTree = "<group>"; };
 		AE77838E23E4276D0093EABD /* ContactCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactCellViewModel.swift; sourceTree = "<group>"; };
+		AE83F5392487D6F900DDDA04 /* GalleryTimeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryTimeLabel.swift; sourceTree = "<group>"; };
 		AE8519E92272FDCA00ED86F0 /* DeviceContactsHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceContactsHandler.swift; sourceTree = "<group>"; };
 		AE851A01227AECDE00ED86F0 /* deltachat-iosTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "deltachat-iosTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		AE851A03227AECDE00ED86F0 /* deltachat_iosTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = deltachat_iosTests.swift; sourceTree = "<group>"; };
@@ -965,6 +967,7 @@
 				AEB54C7E246DBA610004624C /* FlexLabel.swift */,
 				AED62BCD247687E6009E220D /* LocationStreamingIndicator.swift */,
 				AE0AA9532478010D00D42A7F /* GallerySectionHeader.swift */,
+				AE83F5392487D6F900DDDA04 /* GalleryTimeLabel.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -1480,6 +1483,7 @@
 				AE9DAF0D22C1215D004C9591 /* EditContactController.swift in Sources */,
 				305961FC2346125100C80F33 /* MessageContainerView.swift in Sources */,
 				305961D42346125100C80F33 /* MessagesViewController.swift in Sources */,
+				AE83F53A2487D6F900DDDA04 /* GalleryTimeLabel.swift in Sources */,
 				785BE16821E247F1003BE98C /* MessageInfoViewController.swift in Sources */,
 				AE851AC5227C755A00ED86F0 /* Protocols.swift in Sources */,
 				AE728F15229D5C390047565B /* PhotoPickerAlertAction.swift in Sources */,

+ 33 - 57
deltachat-ios/Controller/GalleryViewController.swift

@@ -3,17 +3,8 @@ import DcCore
 
 class GalleryViewController: UIViewController {
 
-    private struct GallerySection {
-        var headerTitle: String {
-            return String.localized(timeBucket.translationKey)
-        }
-        let timeBucket: TimeBucket
-        let msgIds: [Int]
-    }
-
     // MARK: - data
     private let mediaMessageIds: [Int]
-    private var gridSections: [GallerySection] = []
 
     // MARK: - subview specs
     private lazy var gridLayout: GridCollectionViewFlowLayout = {
@@ -29,23 +20,23 @@ class GalleryViewController: UIViewController {
         collection.dataSource = self
         collection.delegate = self
         collection.register(GalleryCell.self, forCellWithReuseIdentifier: GalleryCell.reuseIdentifier)
-        collection.register(
-            GalleryGridSectionHeader.self,
-            forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
-            withReuseIdentifier: GalleryGridSectionHeader.reuseIdentifier
-        )
         collection.contentInset = UIEdgeInsets(top: 0, left: gridInsets, bottom: 0, right: gridInsets)
         collection.backgroundColor = .white
         collection.delaysContentTouches = false
         return collection
     }()
 
+    private lazy var floatingTimeLabel: GalleryTimeLabel = {
+        let view = GalleryTimeLabel()
+        view.hide(animated: false)
+        return view
+    }()
+
     private let gridInsets: CGFloat = 10
 
     init(mediaMessageIds: [Int]) {
-        self.mediaMessageIds = mediaMessageIds
+        self.mediaMessageIds = mediaMessageIds.reversed()
         super.init(nibName: nil, bundle: nil)
-        self.gridSections = processData(msgIds: mediaMessageIds)
     }
 
     required init?(coder: NSCoder) {
@@ -76,34 +67,19 @@ class GalleryViewController: UIViewController {
         grid.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
         grid.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
         grid.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
-    }
 
-    // MARK: - data processing + update
-    private func processData(msgIds: [Int]) -> [GallerySection] {
-
-        var buckets: [TimeBucket: [Int]] = [:]
+        view.addSubview(floatingTimeLabel)
+        floatingTimeLabel.translatesAutoresizingMaskIntoConstraints = false
+        floatingTimeLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10).isActive = true
+        floatingTimeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
+    }
 
-        msgIds.forEach { msgId in
+    private func updateFloatingTimeLabel() {
+        if let indexPath = grid.indexPathsForVisibleItems.min() {
+            let msgId = mediaMessageIds[indexPath.row]
             let msg = DcMsg(id: msgId)
-            let date: Date = msg.sentDate
-            let msgBucket = TimeBucket.bucket(for: date)
-
-            if buckets[msgBucket] != nil {
-                buckets[msgBucket]?.append(msgId)
-            } else {
-                buckets[msgBucket] = [msgId]
-            }
+            floatingTimeLabel.update(date: msg.sentDate)
         }
-
-        var sections: [GallerySection] = []
-        TimeBucket.allCases.forEach { bucket in
-            if let msgIds = buckets[bucket] {
-                sections.append(
-                    GallerySection(timeBucket: bucket, msgIds: msgIds)
-                )
-            }
-        }
-        return sections
     }
 }
 
@@ -111,11 +87,11 @@ class GalleryViewController: UIViewController {
 extension GalleryViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
 
     func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return gridSections.count
+        return 1
     }
 
     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return gridSections[section].msgIds.count
+        return mediaMessageIds.count
     }
 
     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
@@ -124,33 +100,33 @@ extension GalleryViewController: UICollectionViewDataSource, UICollectionViewDel
             for: indexPath) as? GalleryCell else {
             return UICollectionViewCell()
         }
-        let msgId = gridSections[indexPath.section].msgIds[indexPath.row]
+        let msgId = mediaMessageIds[indexPath.row]
         let msg = DcMsg(id: msgId)
         mediaCell.update(msg: msg)
         return mediaCell
     }
 
-    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
-        if let header = collectionView.dequeueReusableSupplementaryView(
-            ofKind: kind,
-            withReuseIdentifier: GalleryGridSectionHeader.reuseIdentifier,
-            for: indexPath
-            ) as? GalleryGridSectionHeader {
-            header.text = gridSections[indexPath.section].headerTitle
-            header.leadingMargin = gridInsets // to have grid and header equally aligned
-            return header
-        }
-        return UICollectionReusableView()
-    }
-
     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
         return CGSize(width: collectionView.frame.width - 2 * gridInsets, height: 36)
     }
 
     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        let msgId = gridSections[indexPath.section].msgIds[indexPath.row]
+        let msgId = mediaMessageIds[indexPath.row]
         showPreview(msgId: msgId)
     }
+
+    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
+        updateFloatingTimeLabel()
+        floatingTimeLabel.show(animated: true)
+    }
+
+    func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        updateFloatingTimeLabel()
+    }
+
+    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
+        floatingTimeLabel.hide(animated: true)
+    }
 }
 
 // MARK: - update layout

+ 52 - 0
deltachat-ios/View/GalleryTimeLabel.swift

@@ -0,0 +1,52 @@
+import UIKit
+import DcCore
+
+class GalleryTimeLabel: UIView {
+
+    private lazy var label: UILabel = {
+        let label = UILabel()
+        label.textColor = .white
+        return label
+    }()
+
+    init() {
+        super.init(frame: .zero)
+        setupSubviews()
+        backgroundColor = DcColors.primary.withAlphaComponent(0.8)
+        layer.cornerRadius = 4
+        clipsToBounds = true
+    }
+
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    private func setupSubviews() {
+        addSubview(label)
+        label.translatesAutoresizingMaskIntoConstraints = false
+        label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8).isActive = true
+        label.topAnchor.constraint(equalTo: topAnchor, constant: 2).isActive = true
+        label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8).isActive = true
+        label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -2).isActive = true
+    }
+
+    func update(date: Date) {
+        let localizedDescription = date.galleryLocalizedDescription
+        if label.text != localizedDescription {
+            label.text = localizedDescription
+            setNeedsLayout() // TOODO: test if this is actually needed
+        }
+    }
+
+    func show(animated: Bool) {
+        UIView.animate(withDuration: animated ? 0 : 0.2) {
+            self.alpha = 1
+        }
+    }
+
+    func hide(animated: Bool) {
+        UIView.animate(withDuration: animated ? 0 : 0.2) {
+            self.alpha = 0
+        }
+    }
+}