Compare commits
6 Commits
1f37a5e7eb
...
e0d97cd2a8
Author | SHA1 | Date |
---|---|---|
Shadowfacts | e0d97cd2a8 | |
Shadowfacts | 8b718ce50b | |
Shadowfacts | ce708e2d16 | |
Shadowfacts | 01467574d0 | |
Shadowfacts | 97a2278634 | |
Shadowfacts | 4b2a263889 |
|
@ -298,9 +298,9 @@ public class Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Notifications
|
// MARK: - Notifications
|
||||||
public static func getNotifications(excludeTypes: [Notification.Kind], range: RequestRange = .default) -> Request<[Notification]> {
|
public static func getNotifications(allowedTypes: [Notification.Kind], range: RequestRange = .default) -> Request<[Notification]> {
|
||||||
var request = Request<[Notification]>(method: .get, path: "/api/v1/notifications", queryParameters:
|
var request = Request<[Notification]>(method: .get, path: "/api/v1/notifications", queryParameters:
|
||||||
"exclude_types" => excludeTypes.map { $0.rawValue }
|
"types" => allowedTypes.map { $0.rawValue }
|
||||||
)
|
)
|
||||||
request.range = range
|
request.range = range
|
||||||
return request
|
return request
|
||||||
|
|
|
@ -45,9 +45,12 @@ class Filterer {
|
||||||
var htmlConverter = HTMLConverter()
|
var htmlConverter = HTMLConverter()
|
||||||
private var hasSetup = false
|
private var hasSetup = false
|
||||||
private var matchers = [(NSRegularExpression, Result)]()
|
private var matchers = [(NSRegularExpression, Result)]()
|
||||||
private var allFiltersObserver: AnyCancellable?
|
private var cancellables = Set<AnyCancellable>()
|
||||||
private var filterObservers = Set<AnyCancellable>()
|
private var filterObservers = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
private var hideReblogsInTimelines: Bool
|
||||||
|
private var hideRepliesInTimelines: Bool
|
||||||
|
|
||||||
// the generation is incremented when the matchers change, to indicate that older cached FilterStates
|
// the generation is incremented when the matchers change, to indicate that older cached FilterStates
|
||||||
// are no longer valid, without needing to go through and update each of them
|
// are no longer valid, without needing to go through and update each of them
|
||||||
private var generation = 0
|
private var generation = 0
|
||||||
|
@ -55,13 +58,37 @@ class Filterer {
|
||||||
init(mastodonController: MastodonController, context: FilterV1.Context) {
|
init(mastodonController: MastodonController, context: FilterV1.Context) {
|
||||||
self.mastodonController = mastodonController
|
self.mastodonController = mastodonController
|
||||||
self.context = context
|
self.context = context
|
||||||
|
self.hideReblogsInTimelines = Preferences.shared.hideReblogsInTimelines
|
||||||
|
self.hideRepliesInTimelines = Preferences.shared.hideRepliesInTimelines
|
||||||
|
|
||||||
allFiltersObserver = mastodonController.$filters
|
mastodonController.$filters
|
||||||
.sink { [unowned self] in
|
.sink { [unowned self] in
|
||||||
if self.hasSetup {
|
if self.hasSetup {
|
||||||
self.setupFilters(filters: $0)
|
self.setupFilters(filters: $0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
if context == .home {
|
||||||
|
Preferences.shared.$hideReblogsInTimelines
|
||||||
|
.sink { [unowned self] newValue in
|
||||||
|
if newValue != hideReblogsInTimelines {
|
||||||
|
self.hideReblogsInTimelines = newValue
|
||||||
|
self.generation += 1
|
||||||
|
self.filtersChanged?(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
Preferences.shared.$hideRepliesInTimelines
|
||||||
|
.sink { [unowned self] newValue in
|
||||||
|
if newValue != hideRepliesInTimelines {
|
||||||
|
self.hideRepliesInTimelines = newValue
|
||||||
|
self.generation += 1
|
||||||
|
self.filtersChanged?(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupFilters(filters: [FilterMO]) {
|
private func setupFilters(filters: [FilterMO]) {
|
||||||
|
@ -86,7 +113,7 @@ class Filterer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasSetup {
|
if hasSetup {
|
||||||
var allMatch: Bool = false
|
var allMatch: Bool = true
|
||||||
var actionsChanged: Bool = false
|
var actionsChanged: Bool = false
|
||||||
if matchers.count != oldMatchers.count {
|
if matchers.count != oldMatchers.count {
|
||||||
allMatch = false
|
allMatch = false
|
||||||
|
@ -114,12 +141,13 @@ class Filterer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a closure for the status in case the result is cached and we don't need to look it up
|
// Use a closure for the status in case the result is cached and we don't need to look it up
|
||||||
func resolve(state: FilterState, status: () -> StatusMO) -> (Filterer.Result, NSAttributedString?) {
|
func resolve(state: FilterState, status: () -> (StatusMO, Bool)) -> (Filterer.Result, NSAttributedString?) {
|
||||||
switch state.state {
|
switch state.state {
|
||||||
case .known(_, generation: let knownGen) where knownGen < generation:
|
case .known(_, generation: let knownGen) where knownGen < generation:
|
||||||
fallthrough
|
fallthrough
|
||||||
case .unknown:
|
case .unknown:
|
||||||
let (result, attributedString) = doResolve(status: status())
|
let (status, isReblog) = status()
|
||||||
|
let (result, attributedString) = doResolve(status: status, isReblog: isReblog)
|
||||||
state.state = .known(result, generation: generation)
|
state.state = .known(result, generation: generation)
|
||||||
return (result, attributedString)
|
return (result, attributedString)
|
||||||
case .known(let result, _):
|
case .known(let result, _):
|
||||||
|
@ -140,10 +168,19 @@ class Filterer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func doResolve(status: StatusMO) -> (Result, NSAttributedString?) {
|
private func doResolve(status: StatusMO, isReblog: Bool) -> (Result, NSAttributedString?) {
|
||||||
if !hasSetup {
|
if !hasSetup {
|
||||||
setupFilters(filters: mastodonController.filters)
|
setupFilters(filters: mastodonController.filters)
|
||||||
}
|
}
|
||||||
|
if context == .home {
|
||||||
|
if hideReblogsInTimelines,
|
||||||
|
isReblog {
|
||||||
|
return (.hide, nil)
|
||||||
|
} else if hideRepliesInTimelines,
|
||||||
|
status.inReplyToID != nil {
|
||||||
|
return (.hide, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
if matchers.isEmpty {
|
if matchers.isEmpty {
|
||||||
return (.allow, nil)
|
return (.allow, nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,8 @@ class Preferences: Codable, ObservableObject {
|
||||||
self.oppositeCollapseKeywords = try container.decodeIfPresent([String].self, forKey: .oppositeCollapseKeywords) ?? []
|
self.oppositeCollapseKeywords = try container.decodeIfPresent([String].self, forKey: .oppositeCollapseKeywords) ?? []
|
||||||
self.confirmBeforeReblog = try container.decodeIfPresent(Bool.self, forKey: .confirmBeforeReblog) ?? false
|
self.confirmBeforeReblog = try container.decodeIfPresent(Bool.self, forKey: .confirmBeforeReblog) ?? false
|
||||||
self.timelineStateRestoration = try container.decodeIfPresent(Bool.self, forKey: .timelineStateRestoration) ?? true
|
self.timelineStateRestoration = try container.decodeIfPresent(Bool.self, forKey: .timelineStateRestoration) ?? true
|
||||||
|
self.hideReblogsInTimelines = try container.decodeIfPresent(Bool.self, forKey: .hideReblogsInTimelines) ?? false
|
||||||
|
self.hideRepliesInTimelines = try container.decodeIfPresent(Bool.self, forKey: .hideRepliesInTimelines) ?? false
|
||||||
|
|
||||||
self.showFavoriteAndReblogCounts = try container.decode(Bool.self, forKey: .showFavoriteAndReblogCounts)
|
self.showFavoriteAndReblogCounts = try container.decode(Bool.self, forKey: .showFavoriteAndReblogCounts)
|
||||||
self.defaultNotificationsMode = try container.decode(NotificationsMode.self, forKey: .defaultNotificationsType)
|
self.defaultNotificationsMode = try container.decode(NotificationsMode.self, forKey: .defaultNotificationsType)
|
||||||
|
@ -115,6 +117,8 @@ class Preferences: Codable, ObservableObject {
|
||||||
try container.encode(oppositeCollapseKeywords, forKey: .oppositeCollapseKeywords)
|
try container.encode(oppositeCollapseKeywords, forKey: .oppositeCollapseKeywords)
|
||||||
try container.encode(confirmBeforeReblog, forKey: .confirmBeforeReblog)
|
try container.encode(confirmBeforeReblog, forKey: .confirmBeforeReblog)
|
||||||
try container.encode(timelineStateRestoration, forKey: .timelineStateRestoration)
|
try container.encode(timelineStateRestoration, forKey: .timelineStateRestoration)
|
||||||
|
try container.encode(hideReblogsInTimelines, forKey: .hideReblogsInTimelines)
|
||||||
|
try container.encode(hideRepliesInTimelines, forKey: .hideRepliesInTimelines)
|
||||||
|
|
||||||
try container.encode(showFavoriteAndReblogCounts, forKey: .showFavoriteAndReblogCounts)
|
try container.encode(showFavoriteAndReblogCounts, forKey: .showFavoriteAndReblogCounts)
|
||||||
try container.encode(defaultNotificationsMode, forKey: .defaultNotificationsType)
|
try container.encode(defaultNotificationsMode, forKey: .defaultNotificationsType)
|
||||||
|
@ -169,6 +173,8 @@ class Preferences: Codable, ObservableObject {
|
||||||
@Published var oppositeCollapseKeywords: [String] = []
|
@Published var oppositeCollapseKeywords: [String] = []
|
||||||
@Published var confirmBeforeReblog = false
|
@Published var confirmBeforeReblog = false
|
||||||
@Published var timelineStateRestoration = true
|
@Published var timelineStateRestoration = true
|
||||||
|
@Published var hideReblogsInTimelines = false
|
||||||
|
@Published var hideRepliesInTimelines = false
|
||||||
|
|
||||||
// MARK: Digital Wellness
|
// MARK: Digital Wellness
|
||||||
@Published var showFavoriteAndReblogCounts = true
|
@Published var showFavoriteAndReblogCounts = true
|
||||||
|
@ -216,6 +222,8 @@ class Preferences: Codable, ObservableObject {
|
||||||
case oppositeCollapseKeywords
|
case oppositeCollapseKeywords
|
||||||
case confirmBeforeReblog
|
case confirmBeforeReblog
|
||||||
case timelineStateRestoration
|
case timelineStateRestoration
|
||||||
|
case hideReblogsInTimelines
|
||||||
|
case hideRepliesInTimelines
|
||||||
|
|
||||||
case showFavoriteAndReblogCounts
|
case showFavoriteAndReblogCounts
|
||||||
case defaultNotificationsType
|
case defaultNotificationsType
|
||||||
|
|
|
@ -74,6 +74,8 @@ protocol StatusSwipeActionContainer: UIView {
|
||||||
var navigationDelegate: any TuskerNavigationDelegate { get }
|
var navigationDelegate: any TuskerNavigationDelegate { get }
|
||||||
var toastableViewController: ToastableViewController? { get }
|
var toastableViewController: ToastableViewController? { get }
|
||||||
|
|
||||||
|
var canReblog: Bool { get }
|
||||||
|
|
||||||
// necessary b/c the reblog-handling logic only exists in the cells
|
// necessary b/c the reblog-handling logic only exists in the cells
|
||||||
func performReplyAction()
|
func performReplyAction()
|
||||||
}
|
}
|
||||||
|
@ -108,7 +110,8 @@ private func createFavoriteAction(status: StatusMO, container: StatusSwipeAction
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createReblogAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
|
private func createReblogAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
|
||||||
guard container.mastodonController.loggedIn else {
|
guard container.mastodonController.loggedIn,
|
||||||
|
container.canReblog else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let title = status.reblogged ? "Unreblog" : "Reblog"
|
let title = status.reblogged ? "Unreblog" : "Reblog"
|
||||||
|
|
|
@ -125,7 +125,7 @@ class ConversationTableViewController: EnhancedTableViewController {
|
||||||
})
|
})
|
||||||
|
|
||||||
visibilityBarButtonItem = UIBarButtonItem(image: ConversationTableViewController.showPostsImage, style: .plain, target: self, action: #selector(toggleVisibilityButtonPressed))
|
visibilityBarButtonItem = UIBarButtonItem(image: ConversationTableViewController.showPostsImage, style: .plain, target: self, action: #selector(toggleVisibilityButtonPressed))
|
||||||
visibilityBarButtonItem.isSelected = showStatusesAutomatically
|
updateVisibilityBarButtonItem()
|
||||||
navigationItem.rightBarButtonItem = visibilityBarButtonItem
|
navigationItem.rightBarButtonItem = visibilityBarButtonItem
|
||||||
// disable transparent background when scroll to top because it looks weird when items earlier in the thread load in
|
// disable transparent background when scroll to top because it looks weird when items earlier in the thread load in
|
||||||
// (it remains transparent slightly too long, resulting in a flash of the content under the transparent bar)
|
// (it remains transparent slightly too long, resulting in a flash of the content under the transparent bar)
|
||||||
|
@ -138,6 +138,11 @@ class ConversationTableViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func updateVisibilityBarButtonItem() {
|
||||||
|
visibilityBarButtonItem.isSelected = showStatusesAutomatically
|
||||||
|
visibilityBarButtonItem.accessibilityLabel = showStatusesAutomatically ? "Collapse All" : "Expand All"
|
||||||
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
private func loadMainStatus() async {
|
private func loadMainStatus() async {
|
||||||
guard loadingState == .unloaded else { return }
|
guard loadingState == .unloaded else { return }
|
||||||
|
@ -391,7 +396,7 @@ class ConversationTableViewController: EnhancedTableViewController {
|
||||||
tableView.beginUpdates()
|
tableView.beginUpdates()
|
||||||
tableView.endUpdates()
|
tableView.endUpdates()
|
||||||
|
|
||||||
visibilityBarButtonItem.isSelected = showStatusesAutomatically
|
updateVisibilityBarButtonItem()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ class TrendingStatusesViewController: UIViewController {
|
||||||
return UICollectionViewDiffableDataSource(collectionView: collectionView) { [unowned self] collectionView, indexPath, itemIdentifier in
|
return UICollectionViewDiffableDataSource(collectionView: collectionView) { [unowned self] collectionView, indexPath, itemIdentifier in
|
||||||
switch itemIdentifier {
|
switch itemIdentifier {
|
||||||
case .status(id: let id, let collapseState, let filterState):
|
case .status(id: let id, let collapseState, let filterState):
|
||||||
let (result, attributedString) = self.filterer.resolve(state: filterState, status: { mastodonController.persistentContainer.status(for: id)! })
|
let (result, attributedString) = self.filterer.resolve(state: filterState, status: { (mastodonController.persistentContainer.status(for: id)!, false) })
|
||||||
switch result {
|
switch result {
|
||||||
case .allow, .warn(_):
|
case .allow, .warn(_):
|
||||||
return collectionView.dequeueConfiguredReusableCell(using: statusCell, for: indexPath, item: (id, collapseState, result, attributedString))
|
return collectionView.dequeueConfiguredReusableCell(using: statusCell, for: indexPath, item: (id, collapseState, result, attributedString))
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct FiltersView: View {
|
||||||
|
|
||||||
struct FiltersList: View {
|
struct FiltersList: View {
|
||||||
@EnvironmentObject private var mastodonController: MastodonController
|
@EnvironmentObject private var mastodonController: MastodonController
|
||||||
|
@ObservedObject private var preferences = Preferences.shared
|
||||||
@FetchRequest(sortDescriptors: []) private var filters: FetchedResults<FilterMO>
|
@FetchRequest(sortDescriptors: []) private var filters: FetchedResults<FilterMO>
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
@State private var deletionError: (any Error)?
|
@State private var deletionError: (any Error)?
|
||||||
|
@ -49,6 +50,17 @@ struct FiltersList: View {
|
||||||
|
|
||||||
private var navigationBody: some View {
|
private var navigationBody: some View {
|
||||||
List {
|
List {
|
||||||
|
Section {
|
||||||
|
Toggle(isOn: $preferences.hideReblogsInTimelines) {
|
||||||
|
Text("Hide Reblogs")
|
||||||
|
}
|
||||||
|
Toggle(isOn: $preferences.hideRepliesInTimelines) {
|
||||||
|
Text("Hide Replies")
|
||||||
|
}
|
||||||
|
} header: {
|
||||||
|
Text("Home Timeline")
|
||||||
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
NavigationLink {
|
NavigationLink {
|
||||||
EditFilterView(filter: EditedFilter(), create: true, originallyExpired: false)
|
EditFilterView(filter: EditedFilter(), create: true, originallyExpired: false)
|
||||||
|
|
|
@ -20,7 +20,7 @@ class LargeImageInteractionController: UIPercentDrivenInteractiveTransition {
|
||||||
super.init()
|
super.init()
|
||||||
self.viewController = viewController
|
self.viewController = viewController
|
||||||
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handleGesture(_:)))
|
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handleGesture(_:)))
|
||||||
panRecognizer.allowedScrollTypesMask = .all
|
panRecognizer.allowedScrollTypesMask = .continuous
|
||||||
viewController.view.addGestureRecognizer(panRecognizer)
|
viewController.view.addGestureRecognizer(panRecognizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,14 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController<
|
||||||
|
|
||||||
weak var mastodonController: MastodonController!
|
weak var mastodonController: MastodonController!
|
||||||
|
|
||||||
private let excludedTypes: [Pachyderm.Notification.Kind]
|
private let allowedTypes: [Pachyderm.Notification.Kind]
|
||||||
private let groupTypes = [Pachyderm.Notification.Kind.favourite, .reblog, .follow]
|
private let groupTypes = [Pachyderm.Notification.Kind.favourite, .reblog, .follow]
|
||||||
|
|
||||||
private var newer: RequestRange?
|
private var newer: RequestRange?
|
||||||
private var older: RequestRange?
|
private var older: RequestRange?
|
||||||
|
|
||||||
init(allowedTypes: [Pachyderm.Notification.Kind], mastodonController: MastodonController) {
|
init(allowedTypes: [Pachyderm.Notification.Kind], mastodonController: MastodonController) {
|
||||||
self.excludedTypes = Array(Set(Pachyderm.Notification.Kind.allCases).subtracting(allowedTypes))
|
self.allowedTypes = allowedTypes
|
||||||
self.mastodonController = mastodonController
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
@ -140,7 +140,7 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController<
|
||||||
}
|
}
|
||||||
|
|
||||||
override func loadInitialItems(completion: @escaping (LoadResult) -> Void) {
|
override func loadInitialItems(completion: @escaping (LoadResult) -> Void) {
|
||||||
let request = Client.getNotifications(excludeTypes: excludedTypes)
|
let request = Client.getNotifications(allowedTypes: allowedTypes)
|
||||||
mastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
switch response {
|
switch response {
|
||||||
case let .failure(error):
|
case let .failure(error):
|
||||||
|
@ -171,7 +171,7 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController<
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = Client.getNotifications(excludeTypes: excludedTypes, range: older)
|
let request = Client.getNotifications(allowedTypes: allowedTypes, range: older)
|
||||||
mastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
switch response {
|
switch response {
|
||||||
case let .failure(error):
|
case let .failure(error):
|
||||||
|
@ -203,7 +203,7 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController<
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = Client.getNotifications(excludeTypes: excludedTypes, range: newer)
|
let request = Client.getNotifications(allowedTypes: allowedTypes, range: newer)
|
||||||
mastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
switch response {
|
switch response {
|
||||||
case let .failure(error):
|
case let .failure(error):
|
||||||
|
|
|
@ -35,6 +35,12 @@ struct BehaviorPrefsView: View {
|
||||||
Toggle(isOn: $preferences.timelineStateRestoration) {
|
Toggle(isOn: $preferences.timelineStateRestoration) {
|
||||||
Text("Maintain Position Across App Launches")
|
Text("Maintain Position Across App Launches")
|
||||||
}
|
}
|
||||||
|
Toggle(isOn: $preferences.hideReblogsInTimelines) {
|
||||||
|
Text("Hide Reblogs")
|
||||||
|
}
|
||||||
|
Toggle(isOn: $preferences.hideRepliesInTimelines) {
|
||||||
|
Text("Hide Replies")
|
||||||
|
}
|
||||||
} header: {
|
} header: {
|
||||||
Text("Timeline")
|
Text("Timeline")
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,7 +261,11 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
|
||||||
let status = {
|
let status = {
|
||||||
let status = self.mastodonController.persistentContainer.status(for: statusID)!
|
let status = self.mastodonController.persistentContainer.status(for: statusID)!
|
||||||
// if the status is a reblog of another one, filter based on that one
|
// if the status is a reblog of another one, filter based on that one
|
||||||
return status.reblog ?? status
|
if let reblogged = status.reblog {
|
||||||
|
return (reblogged, true)
|
||||||
|
} else {
|
||||||
|
return (status, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return filterer.resolve(state: state, status: status)
|
return filterer.resolve(state: state, status: status)
|
||||||
}
|
}
|
||||||
|
|
|
@ -354,7 +354,11 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
|
||||||
let status = {
|
let status = {
|
||||||
let status = self.mastodonController.persistentContainer.status(for: statusID)!
|
let status = self.mastodonController.persistentContainer.status(for: statusID)!
|
||||||
// if the status is a reblog of another one, filter based on that one
|
// if the status is a reblog of another one, filter based on that one
|
||||||
return status.reblog ?? status
|
if let reblogged = status.reblog {
|
||||||
|
return (reblogged, true)
|
||||||
|
} else {
|
||||||
|
return (status, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return filterer.resolve(state: state, status: status)
|
return filterer.resolve(state: state, status: status)
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,9 @@ extension ContentTextView: UITextViewDelegate {
|
||||||
} else {
|
} else {
|
||||||
// otherwise, regular taps are handled by the gesture recognizer, but the accessibility interaction to select links with the rotor goes through here
|
// otherwise, regular taps are handled by the gesture recognizer, but the accessibility interaction to select links with the rotor goes through here
|
||||||
// and this seems to be the only way of overriding what it does
|
// and this seems to be the only way of overriding what it does
|
||||||
|
if interaction == .invokeDefaultAction {
|
||||||
handleLinkTapped(url: URL, text: (text as NSString).substring(with: characterRange))
|
handleLinkTapped(url: URL, text: (text as NSString).substring(with: characterRange))
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -822,6 +822,10 @@ extension TimelineStatusCollectionViewCell: StatusSwipeActionContainer {
|
||||||
var navigationDelegate: TuskerNavigationDelegate { delegate! }
|
var navigationDelegate: TuskerNavigationDelegate { delegate! }
|
||||||
var toastableViewController: ToastableViewController? { delegate }
|
var toastableViewController: ToastableViewController? { delegate }
|
||||||
|
|
||||||
|
var canReblog: Bool {
|
||||||
|
reblogButton.isEnabled
|
||||||
|
}
|
||||||
|
|
||||||
func performReplyAction() {
|
func performReplyAction() {
|
||||||
self.replyPressed()
|
self.replyPressed()
|
||||||
}
|
}
|
||||||
|
|
|
@ -445,6 +445,10 @@ extension TimelineStatusTableViewCell: StatusSwipeActionContainer {
|
||||||
var navigationDelegate: TuskerNavigationDelegate { delegate! }
|
var navigationDelegate: TuskerNavigationDelegate { delegate! }
|
||||||
var toastableViewController: ToastableViewController? { delegate }
|
var toastableViewController: ToastableViewController? { delegate }
|
||||||
|
|
||||||
|
var canReblog: Bool {
|
||||||
|
reblogButton.isEnabled
|
||||||
|
}
|
||||||
|
|
||||||
func performReplyAction() {
|
func performReplyAction() {
|
||||||
self.replyPressed()
|
self.replyPressed()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue