mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
add PullUpToMarkAsReadTableViewController
This commit is contained in:
@@ -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 */,
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
149
iOS/MasterTimeline/PullUpToMarkAsReadTableViewController.swift
Normal file
149
iOS/MasterTimeline/PullUpToMarkAsReadTableViewController.swift
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user