add PullUpToMarkAsReadTableViewController

This commit is contained in:
everhardt
2021-11-24 22:33:16 +01:00
parent 89e899c5d7
commit 8964fe5744
3 changed files with 156 additions and 1 deletions

View File

@@ -463,6 +463,7 @@
51FE10092346739D0056195D /* ActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D87EE02311D34700E63F03 /* ActivityType.swift */; };
51FE100A234673A00056195D /* ActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CCD2310792F006127BE /* ActivityManager.swift */; };
51FFF0C4235EE8E5002762AA /* VibrantButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FFF0C3235EE8E5002762AA /* VibrantButton.swift */; };
540F420A2745A63B00F639C1 /* PullUpToMarkAsReadTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 540F42092745A63B00F639C1 /* PullUpToMarkAsReadTableViewController.swift */; };
55E15BCB229D65A900D6602A /* AccountsReaderAPI.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55E15BC1229D65A900D6602A /* AccountsReaderAPI.xib */; };
55E15BCC229D65A900D6602A /* AccountsReaderAPIWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E15BCA229D65A900D6602A /* AccountsReaderAPIWindowController.swift */; };
5F323809231DF9F000706F6B /* VibrantTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F323808231DF9F000706F6B /* VibrantTableViewCell.swift */; };
@@ -1390,6 +1391,7 @@
51FD413A2342BD0500880194 /* MasterTimelineUnreadCountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterTimelineUnreadCountView.swift; sourceTree = "<group>"; };
51FE10022345529D0056195D /* UserNotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationManager.swift; sourceTree = "<group>"; };
51FFF0C3235EE8E5002762AA /* VibrantButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VibrantButton.swift; sourceTree = "<group>"; };
540F42092745A63B00F639C1 /* PullUpToMarkAsReadTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PullUpToMarkAsReadTableViewController.swift; sourceTree = "<group>"; };
55E15BC1229D65A900D6602A /* AccountsReaderAPI.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsReaderAPI.xib; sourceTree = "<group>"; };
55E15BCA229D65A900D6602A /* AccountsReaderAPIWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsReaderAPIWindowController.swift; sourceTree = "<group>"; };
5F323808231DF9F000706F6B /* VibrantTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VibrantTableViewCell.swift; sourceTree = "<group>"; };
@@ -2105,6 +2107,7 @@
children = (
51C4526E2265091600C03939 /* MasterTimelineViewController.swift */,
51D6A5BB23199C85001C27D8 /* MasterTimelineDataSource.swift */,
540F42092745A63B00F639C1 /* PullUpToMarkAsReadTableViewController.swift */,
5148F4542336DB7000F8CD8B /* MasterTimelineTitleView.swift */,
5148F44A2336DB4700F8CD8B /* MasterTimelineTitleView.xib */,
51FD413A2342BD0500880194 /* MasterTimelineUnreadCountView.swift */,
@@ -4173,6 +4176,7 @@
512AF9C2236ED52C0066F8BE /* ImageHeaderView.swift in Sources */,
512392C124E33A3C00F11704 /* RedditSelectTypeTableViewController.swift in Sources */,
515A5181243E90260089E588 /* ExtensionPointIdentifer.swift in Sources */,
540F420A2745A63B00F639C1 /* PullUpToMarkAsReadTableViewController.swift in Sources */,
51A1699F235E10D700EB091F /* AboutViewController.swift in Sources */,
51C45290226509C100C03939 /* PseudoFeed.swift in Sources */,
512392C624E3451400F11704 /* TwitterSelectAccountTableViewController.swift in Sources */,

View File

@@ -11,7 +11,7 @@ import RSCore
import Account
import Articles
class MasterTimelineViewController: UITableViewController, UndoableCommandRunner {
class MasterTimelineViewController: PullUpToMarkAsReadTableViewController, UndoableCommandRunner {
private var numberOfTextLines = 0
private var iconSize = IconSize.medium
@@ -418,6 +418,8 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
super.scrollViewDidScroll(scrollView)
if scrollView.isTracking {
scrollPositionQueue.add(self, #selector(scrollPositionDidChange))
}

View File

@@ -0,0 +1,149 @@
//
// PullUpToMarkAsReadTableViewController.swift
// NetNewsWire-iOS
//
// Created by Rob Everhardt on 17-11-2021.
// Copyright © 2021 Ranchero Software. All rights reserved.
//
import UIKit
class PullUpToMarkAsReadTableViewController: UITableViewController {
private let textPull = "Pull up to mark as read"
private let textRelease = "Release to mark as read"
private let textMarkingAsRead = "Marking as read..."
private let pullUpToMarkAsReadFooterHeight = 52.0
public var isMarkingAsRead = false
public var isDragging = false
private var textLabel: UILabel?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
addPullUpToMarkAsReadFooter()
}
func addPullUpToMarkAsReadFooter() {
let markAsReadFooterView = UIView.init(frame: CGRect(
x: 0.0,
y: view.frame.size.height - view.safeAreaInsets.bottom - pullUpToMarkAsReadFooterHeight,
width: view.frame.size.width,
height: pullUpToMarkAsReadFooterHeight
))
markAsReadFooterView.backgroundColor = UIColor.clear
let label = UILabel.init(frame: CGRect(
x: 0.0,
y: 0.0,
width: view.frame.size.width,
height: pullUpToMarkAsReadFooterHeight
))
label.backgroundColor = UIColor.clear
label.font = UIFont.boldSystemFont(ofSize: 12)
label.textAlignment = NSTextAlignment.center
textLabel = label
markAsReadFooterView.addSubview(label)
// self.tableView.addSubview(markAsReadFooterView)
let backgroundView = UIView()
backgroundView.addSubview(markAsReadFooterView)
self.tableView.backgroundView = backgroundView
}
override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
if (isMarkingAsRead) {
return
}
isDragging = true
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let label = textLabel else {
return
}
let visibleHeight = view.frame.size.height -
view.safeAreaInsets.top
- view.safeAreaInsets.bottom
let currentOffset = scrollView.contentOffset.y + view.safeAreaInsets.top
let scrolledOutOfViewWhenBottomIsReached = max(scrollView.contentSize.height - visibleHeight,0)
let pullUpVisibleHeight = max(currentOffset - scrolledOutOfViewWhenBottomIsReached,0)
if (isMarkingAsRead) {
// Update the content inset, good for section headers
if (pullUpVisibleHeight < pullUpToMarkAsReadFooterHeight) {
self.tableView.contentInset = UIEdgeInsets.init(
top: 0,
left: 0,
bottom: pullUpVisibleHeight,
right: 0
);
}
} else if (isDragging && scrollView.contentOffset.y > 0) {
// Update the label
UIView.animate(withDuration: 0.25) {
if (pullUpVisibleHeight > self.pullUpToMarkAsReadFooterHeight) {
// User is scrolling above the header
label.text = self.textRelease;
} else {
// User is scrolling somewhere within the header
label.text = self.textPull;
}
}
}
}
override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if (isMarkingAsRead) {
return
}
isDragging = false
let visibleHeight = view.frame.size.height -
view.safeAreaInsets.top
- view.safeAreaInsets.bottom
let currentOffset = scrollView.contentOffset.y + view.safeAreaInsets.top
let scrolledOutOfViewWhenBottomIsReached = max(scrollView.contentSize.height - visibleHeight,0)
let pullUpVisibleHeight = max(currentOffset - scrolledOutOfViewWhenBottomIsReached,0)
if (pullUpVisibleHeight > pullUpToMarkAsReadFooterHeight) {
startMarkingAsRead()
}
}
func startMarkingAsRead() {
isMarkingAsRead = true
UIView.animate(withDuration: 0.25) {
self.tableView.contentInset = UIEdgeInsets.init(
top: 0,
left: 0,
bottom: self.pullUpToMarkAsReadFooterHeight,
right: 0
);
if let label = self.textLabel {
label.text = self.textMarkingAsRead
}
}
markAsRead()
}
func stopMarkingAsRead() {
isMarkingAsRead = false
if let label = textLabel {
label.text = textPull
}
self.tableView.contentInset = UIEdgeInsets.zero
}
func markAsRead() {
// to override by implementation, which should also call stopMarkingAsRead when done
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.stopMarkingAsRead()
}
}
}