Compare commits

..

No commits in common. "99127b617b1e7895df3977b366f652cf01381850" and "9f0176350c86eacaeef112c756e9f9fc2ca3361d" have entirely different histories.

82 changed files with 106 additions and 708 deletions

View File

@ -171,7 +171,7 @@ extension Account: CustomDebugStringConvertible {
} }
extension Account { extension Account {
public struct Field: Codable, Equatable { public struct Field: Codable {
public let name: String public let name: String
public let value: String public let value: String
public let verifiedAt: Date? public let verifiedAt: Date?

View File

@ -299,7 +299,6 @@
D6C3F4F7298ED7F70009FCFF /* FavoritesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3F4F6298ED7F70009FCFF /* FavoritesViewController.swift */; }; D6C3F4F7298ED7F70009FCFF /* FavoritesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3F4F6298ED7F70009FCFF /* FavoritesViewController.swift */; };
D6C3F4F9298EDBF20009FCFF /* ConversationTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3F4F8298EDBF20009FCFF /* ConversationTree.swift */; }; D6C3F4F9298EDBF20009FCFF /* ConversationTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3F4F8298EDBF20009FCFF /* ConversationTree.swift */; };
D6C3F4FB299035650009FCFF /* TrendsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3F4FA299035650009FCFF /* TrendsViewController.swift */; }; D6C3F4FB299035650009FCFF /* TrendsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3F4FA299035650009FCFF /* TrendsViewController.swift */; };
D6C3F5172991C1A00009FCFF /* View+AppListStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3F5162991C1A00009FCFF /* View+AppListStyle.swift */; };
D6C693EF216192C2007D6A6D /* TuskerNavigationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */; }; D6C693EF216192C2007D6A6D /* TuskerNavigationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */; };
D6C693FC2162FE6F007D6A6D /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693FB2162FE6F007D6A6D /* LoadingViewController.swift */; }; D6C693FC2162FE6F007D6A6D /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693FB2162FE6F007D6A6D /* LoadingViewController.swift */; };
D6C693FE2162FEEA007D6A6D /* UIViewController+Children.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693FD2162FEEA007D6A6D /* UIViewController+Children.swift */; }; D6C693FE2162FEEA007D6A6D /* UIViewController+Children.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693FD2162FEEA007D6A6D /* UIViewController+Children.swift */; };
@ -326,8 +325,6 @@
D6D4DDF0212518A200E1C4BB /* TuskerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDEF212518A200E1C4BB /* TuskerUITests.swift */; }; D6D4DDF0212518A200E1C4BB /* TuskerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDEF212518A200E1C4BB /* TuskerUITests.swift */; };
D6D706A029466649000827ED /* ScrollingSegmentedControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D7069F29466649000827ED /* ScrollingSegmentedControl.swift */; }; D6D706A029466649000827ED /* ScrollingSegmentedControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D7069F29466649000827ED /* ScrollingSegmentedControl.swift */; };
D6D706A72948D4D0000827ED /* TimlineState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D706A62948D4D0000827ED /* TimlineState.swift */; }; D6D706A72948D4D0000827ED /* TimlineState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D706A62948D4D0000827ED /* TimlineState.swift */; };
D6D94955298963A900C59229 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D94954298963A900C59229 /* Colors.swift */; };
D6D9498D298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D9498C298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift */; };
D6D9498F298EB79400C59229 /* CopyableLable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D9498E298EB79400C59229 /* CopyableLable.swift */; }; D6D9498F298EB79400C59229 /* CopyableLable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D9498E298EB79400C59229 /* CopyableLable.swift */; };
D6DD2A3F273C1F4900386A6C /* ComposeAttachmentImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD2A3E273C1F4900386A6C /* ComposeAttachmentImage.swift */; }; D6DD2A3F273C1F4900386A6C /* ComposeAttachmentImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD2A3E273C1F4900386A6C /* ComposeAttachmentImage.swift */; };
D6DD2A45273D6C5700386A6C /* GIFImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD2A44273D6C5700386A6C /* GIFImageView.swift */; }; D6DD2A45273D6C5700386A6C /* GIFImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD2A44273D6C5700386A6C /* GIFImageView.swift */; };
@ -713,7 +710,6 @@
D6C3F4F6298ED7F70009FCFF /* FavoritesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesViewController.swift; sourceTree = "<group>"; }; D6C3F4F6298ED7F70009FCFF /* FavoritesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesViewController.swift; sourceTree = "<group>"; };
D6C3F4F8298EDBF20009FCFF /* ConversationTree.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationTree.swift; sourceTree = "<group>"; }; D6C3F4F8298EDBF20009FCFF /* ConversationTree.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationTree.swift; sourceTree = "<group>"; };
D6C3F4FA299035650009FCFF /* TrendsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendsViewController.swift; sourceTree = "<group>"; }; D6C3F4FA299035650009FCFF /* TrendsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendsViewController.swift; sourceTree = "<group>"; };
D6C3F5162991C1A00009FCFF /* View+AppListStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+AppListStyle.swift"; sourceTree = "<group>"; };
D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerNavigationDelegate.swift; sourceTree = "<group>"; }; D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerNavigationDelegate.swift; sourceTree = "<group>"; };
D6C693FB2162FE6F007D6A6D /* LoadingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewController.swift; sourceTree = "<group>"; }; D6C693FB2162FE6F007D6A6D /* LoadingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewController.swift; sourceTree = "<group>"; };
D6C693FD2162FEEA007D6A6D /* UIViewController+Children.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Children.swift"; sourceTree = "<group>"; }; D6C693FD2162FEEA007D6A6D /* UIViewController+Children.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Children.swift"; sourceTree = "<group>"; };
@ -747,8 +743,6 @@
D6D7069F29466649000827ED /* ScrollingSegmentedControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollingSegmentedControl.swift; sourceTree = "<group>"; }; D6D7069F29466649000827ED /* ScrollingSegmentedControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollingSegmentedControl.swift; sourceTree = "<group>"; };
D6D706A62948D4D0000827ED /* TimlineState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimlineState.swift; sourceTree = "<group>"; }; D6D706A62948D4D0000827ED /* TimlineState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimlineState.swift; sourceTree = "<group>"; };
D6D706A829498C82000827ED /* Tusker.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Tusker.xcconfig; sourceTree = "<group>"; }; D6D706A829498C82000827ED /* Tusker.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Tusker.xcconfig; sourceTree = "<group>"; };
D6D94954298963A900C59229 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; };
D6D9498C298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingStatusCollectionViewCell.swift; sourceTree = "<group>"; };
D6D9498E298EB79400C59229 /* CopyableLable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLable.swift; sourceTree = "<group>"; }; D6D9498E298EB79400C59229 /* CopyableLable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLable.swift; sourceTree = "<group>"; };
D6DD2A3E273C1F4900386A6C /* ComposeAttachmentImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAttachmentImage.swift; sourceTree = "<group>"; }; D6DD2A3E273C1F4900386A6C /* ComposeAttachmentImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAttachmentImage.swift; sourceTree = "<group>"; };
D6DD2A44273D6C5700386A6C /* GIFImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GIFImageView.swift; sourceTree = "<group>"; }; D6DD2A44273D6C5700386A6C /* GIFImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GIFImageView.swift; sourceTree = "<group>"; };
@ -1187,7 +1181,6 @@
D6ADB6E928E91C30009924AB /* TimelineStatusCollectionViewCell.swift */, D6ADB6E928E91C30009924AB /* TimelineStatusCollectionViewCell.swift */,
D601FA60297B539E00A8E8B5 /* ConversationMainStatusCollectionViewCell.swift */, D601FA60297B539E00A8E8B5 /* ConversationMainStatusCollectionViewCell.swift */,
D6ADB6EB28EA73CB009924AB /* StatusContentContainer.swift */, D6ADB6EB28EA73CB009924AB /* StatusContentContainer.swift */,
D6D9498C298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift */,
); );
path = Status; path = Status;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1281,7 +1274,6 @@
D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */, D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */,
D6BC9DB4232D4CE3002CA326 /* NotificationsMode.swift */, D6BC9DB4232D4CE3002CA326 /* NotificationsMode.swift */,
D61F75872932DB6000C0B37F /* StatusSwipeAction.swift */, D61F75872932DB6000C0B37F /* StatusSwipeAction.swift */,
D6D94954298963A900C59229 /* Colors.swift */,
); );
path = Preferences; path = Preferences;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1311,7 +1303,6 @@
D63CC70F2911F1E4000E19DE /* UIScrollView+Top.swift */, D63CC70F2911F1E4000E19DE /* UIScrollView+Top.swift */,
D61F758F29353B4300C0B37F /* FileManager+Size.swift */, D61F758F29353B4300C0B37F /* FileManager+Size.swift */,
D61F75AC293AF39000C0B37F /* Filter+Helpers.swift */, D61F75AC293AF39000C0B37F /* Filter+Helpers.swift */,
D6C3F5162991C1A00009FCFF /* View+AppListStyle.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2011,7 +2002,6 @@
D6AC956723C4347E008C9946 /* MainSceneDelegate.swift in Sources */, D6AC956723C4347E008C9946 /* MainSceneDelegate.swift in Sources */,
D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */, D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */,
D6BC9DD7232D7811002CA326 /* TimelinesPageViewController.swift in Sources */, D6BC9DD7232D7811002CA326 /* TimelinesPageViewController.swift in Sources */,
D6D9498D298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift in Sources */,
D60E2F2E244248BF005F8713 /* MastodonCachePersistentStore.swift in Sources */, D60E2F2E244248BF005F8713 /* MastodonCachePersistentStore.swift in Sources */,
D620483623D38075008A63EF /* ContentTextView.swift in Sources */, D620483623D38075008A63EF /* ContentTextView.swift in Sources */,
D651C5B42915B00400236EF6 /* ProfileFieldsView.swift in Sources */, D651C5B42915B00400236EF6 /* ProfileFieldsView.swift in Sources */,
@ -2021,7 +2011,6 @@
D6A3BC802321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift in Sources */, D6A3BC802321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift in Sources */,
D627944D23A9A03D00D38C68 /* ListTimelineViewController.swift in Sources */, D627944D23A9A03D00D38C68 /* ListTimelineViewController.swift in Sources */,
D6D12B2F2925D66500D528E1 /* TimelineGapCollectionViewCell.swift in Sources */, D6D12B2F2925D66500D528E1 /* TimelineGapCollectionViewCell.swift in Sources */,
D6D94955298963A900C59229 /* Colors.swift in Sources */,
D6945C3823AC739F005C403C /* InstanceTimelineViewController.swift in Sources */, D6945C3823AC739F005C403C /* InstanceTimelineViewController.swift in Sources */,
D625E4822588262A0074BB2B /* DraggableTableViewCell.swift in Sources */, D625E4822588262A0074BB2B /* DraggableTableViewCell.swift in Sources */,
D68E525B24A3D77E0054355A /* TuskerRootViewController.swift in Sources */, D68E525B24A3D77E0054355A /* TuskerRootViewController.swift in Sources */,
@ -2249,7 +2238,6 @@
D6E426B325337C7000C02E1C /* CustomEmojiImageView.swift in Sources */, D6E426B325337C7000C02E1C /* CustomEmojiImageView.swift in Sources */,
D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */, D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */,
D61F75B3293BD89C00C0B37F /* UpdateFilterService.swift in Sources */, D61F75B3293BD89C00C0B37F /* UpdateFilterService.swift in Sources */,
D6C3F5172991C1A00009FCFF /* View+AppListStyle.swift in Sources */,
D65B4B6A297777D900DABDFB /* StatusNotFoundView.swift in Sources */, D65B4B6A297777D900DABDFB /* StatusNotFoundView.swift in Sources */,
D6412B0924B0291E00F5412E /* MyProfileViewController.swift in Sources */, D6412B0924B0291E00F5412E /* MyProfileViewController.swift in Sources */,
D601FA5D297B2E6F00A8E8B5 /* ConversationCollectionViewController.swift in Sources */, D601FA5D297B2E6F00A8E8B5 /* ConversationCollectionViewController.swift in Sources */,

View File

@ -20,7 +20,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
configureSentry() configureSentry()
swizzleStatusBar() swizzleStatusBar()
swizzlePresentationController()
AppShortcutItem.createItems(for: application) AppShortcutItem.createItems(for: application)
@ -155,24 +154,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
Logging.general.error("Unable to swizzle status bar manager") Logging.general.error("Unable to swizzle status bar manager")
} }
} }
private func swizzlePresentationController() {
var originalIMP: IMP?
let imp = imp_implementationWithBlock({ (self: UIPresentationController) in
let new = UITraitCollection(pureBlackDarkMode: self.presentingViewController.traitCollection.pureBlackDarkMode)
if let existing = self.overrideTraitCollection {
self.overrideTraitCollection = UITraitCollection(traitsFrom: [existing, new])
} else {
self.overrideTraitCollection = new
}
let original = unsafeBitCast(originalIMP!, to: (@convention(c) (UIPresentationController) -> Void).self)
original(self)
} as (@convention(block) (UIPresentationController) -> Void))
let sel = Selector(["Necessary", "If", "Traits", "update", "_"].reversed().joined())
originalIMP = class_replaceMethod(UIPresentationController.self, sel, imp, "v@:")
if originalIMP == nil {
Logging.general.error("Unable to swizzle presentation controller")
}
}
} }

View File

@ -1,48 +0,0 @@
//
// View+AppListStyle.swift
// Tusker
//
// Created by Shadowfacts on 2/6/23.
// Copyright © 2023 Shadowfacts. All rights reserved.
//
import SwiftUI
import Combine
extension View {
@ViewBuilder
func appGroupedListBackground(container: UIAppearanceContainer.Type, applyBackground: Bool = true) -> some View {
if #available(iOS 16.0, *) {
if applyBackground {
self
.scrollContentBackground(.hidden)
.background(Color.appGroupedBackground.edgesIgnoringSafeArea(.all))
} else {
self
.scrollContentBackground(.hidden)
}
} else {
self
.onAppear {
UITableView.appearance(whenContainedInInstancesOf: [container]).backgroundColor = .appGroupedBackground
}
}
}
func appGroupedListRowBackground() -> some View {
self.modifier(AppGroupedListRowBackground())
}
}
private struct AppGroupedListRowBackground: ViewModifier {
@Environment(\.colorScheme) private var colorScheme
func body(content: Content) -> some View {
if colorScheme == .dark, !Preferences.shared.pureBlackDarkMode {
content
.listRowBackground(Color.appGroupedCellBackground)
} else {
content
}
}
}

View File

@ -1,104 +0,0 @@
//
// Colors.swift
// Tusker
//
// Created by Shadowfacts on 1/31/23.
// Copyright © 2023 Shadowfacts. All rights reserved.
//
import UIKit
import SwiftUI
extension UIColor {
static let appBackground = UIColor { traitCollection in
if case .dark = traitCollection.userInterfaceStyle,
!traitCollection.pureBlackDarkMode {
return UIColor(hue: 230/360, saturation: 23/100, brightness: 10/100, alpha: 1)
} else {
return .systemBackground
}
}
static let appSecondaryBackground = UIColor { traitCollection in
if case .dark = traitCollection.userInterfaceStyle,
!traitCollection.pureBlackDarkMode {
if traitCollection.userInterfaceLevel == .elevated {
return UIColor(hue: 230/360, saturation: 23/100, brightness: 10/100, alpha: 1)
} else {
return UIColor(hue: 230/360, saturation: 23/100, brightness: 5/100, alpha: 1)
}
} else {
return .secondarySystemBackground
}
}
static let appGroupedBackground = UIColor { traitCollection in
if case .dark = traitCollection.userInterfaceStyle,
!traitCollection.pureBlackDarkMode {
return .appSecondaryBackground
} else {
return .systemGroupedBackground
}
}
static let appSelectedCellBackground = UIColor { traitCollection in
if case .dark = traitCollection.userInterfaceStyle,
!traitCollection.pureBlackDarkMode {
return UIColor(hue: 230/360, saturation: 20/100, brightness: 27/100, alpha: 1)
} else {
return .systemFill
}
}
static let appGroupedCellBackground = UIColor { traitCollection in
if case .dark = traitCollection.userInterfaceStyle {
if traitCollection.pureBlackDarkMode {
return .secondarySystemBackground
} else {
return .appFill
}
} else {
return .systemBackground
}
}
static let appFill = UIColor { traitCollection in
if case .dark = traitCollection.userInterfaceStyle,
!traitCollection.pureBlackDarkMode {
return UIColor(hue: 230/360, saturation: 20/100, brightness: 17/100, alpha: 1)
} else {
return .systemFill
}
}
}
extension Color {
static let appBackground = Color(uiColor: .appBackground)
static let appGroupedBackground = Color(uiColor: .appGroupedBackground)
static let appSecondaryBackground = Color(uiColor: .appSecondaryBackground)
static let appSelectedCellBackground = Color(uiColor: .appGroupedCellBackground)
static let appGroupedCellBackground = Color(uiColor: .appGroupedCellBackground)
static let appFill = Color(uiColor: .appFill)
}
private let traitsKey: String = ["Traits", "Defined", "client", "_"].reversed().joined()
private let key = "tusker_usePureBlackDarkMode"
extension UITraitCollection {
var pureBlackDarkMode: Bool {
get {
// default to true to mach OS behavior
(value(forKey: traitsKey) as? [String: Any])?[key] as? Bool ?? true
}
set {
var dict = value(forKey: traitsKey) as? [String: Any] ?? [:]
dict[key] = newValue
setValue(dict, forKey: traitsKey)
}
}
convenience init(pureBlackDarkMode: Bool) {
self.init()
self.pureBlackDarkMode = pureBlackDarkMode
}
}

View File

@ -38,7 +38,6 @@ class Preferences: Codable, ObservableObject {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
self.theme = try container.decode(UIUserInterfaceStyle.self, forKey: .theme) self.theme = try container.decode(UIUserInterfaceStyle.self, forKey: .theme)
self.pureBlackDarkMode = try container.decodeIfPresent(Bool.self, forKey: .pureBlackDarkMode) ?? true
self.accentColor = try container.decodeIfPresent(AccentColor.self, forKey: .accentColor) ?? .default self.accentColor = try container.decodeIfPresent(AccentColor.self, forKey: .accentColor) ?? .default
self.avatarStyle = try container.decode(AvatarStyle.self, forKey: .avatarStyle) self.avatarStyle = try container.decode(AvatarStyle.self, forKey: .avatarStyle)
self.hideCustomEmojiInUsernames = try container.decode(Bool.self, forKey: .hideCustomEmojiInUsernames) self.hideCustomEmojiInUsernames = try container.decode(Bool.self, forKey: .hideCustomEmojiInUsernames)
@ -93,7 +92,6 @@ class Preferences: Codable, ObservableObject {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(theme, forKey: .theme) try container.encode(theme, forKey: .theme)
try container.encode(pureBlackDarkMode, forKey: .pureBlackDarkMode)
try container.encode(accentColor, forKey: .accentColor) try container.encode(accentColor, forKey: .accentColor)
try container.encode(avatarStyle, forKey: .avatarStyle) try container.encode(avatarStyle, forKey: .avatarStyle)
try container.encode(hideCustomEmojiInUsernames, forKey: .hideCustomEmojiInUsernames) try container.encode(hideCustomEmojiInUsernames, forKey: .hideCustomEmojiInUsernames)
@ -142,7 +140,6 @@ class Preferences: Codable, ObservableObject {
// MARK: Appearance // MARK: Appearance
@Published var theme = UIUserInterfaceStyle.unspecified @Published var theme = UIUserInterfaceStyle.unspecified
@Published var pureBlackDarkMode = true
@Published var accentColor = AccentColor.default @Published var accentColor = AccentColor.default
@Published var avatarStyle = AvatarStyle.roundRect @Published var avatarStyle = AvatarStyle.roundRect
@Published var hideCustomEmojiInUsernames = false @Published var hideCustomEmojiInUsernames = false
@ -205,7 +202,6 @@ class Preferences: Codable, ObservableObject {
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case theme case theme
case pureBlackDarkMode
case accentColor case accentColor
case avatarStyle case avatarStyle
case hideCustomEmojiInUsernames case hideCustomEmojiInUsernames

View File

@ -243,13 +243,8 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate, TuskerSceneDelegate
} }
@objc func themePrefChanged() { @objc func themePrefChanged() {
guard let window else { return } window?.overrideUserInterfaceStyle = Preferences.shared.theme
window.overrideUserInterfaceStyle = Preferences.shared.theme window?.tintColor = Preferences.shared.accentColor.color
window.tintColor = Preferences.shared.accentColor.color
let key = ["Controller", "Presentation", "root", "_"].reversed().joined()
if let rootPresentationController = window.value(forKey: key) as? UIPresentationController {
rootPresentationController.overrideTraitCollection = UITraitCollection(pureBlackDarkMode: Preferences.shared.pureBlackDarkMode)
}
} }
func showAddAccount() { func showAddAccount() {

View File

@ -41,8 +41,7 @@ class AccountFollowsListViewController: UIViewController, CollectionViewControll
} }
override func loadView() { override func loadView() {
var config = UICollectionLayoutListConfiguration(appearance: .plain) var config = UICollectionLayoutListConfiguration(appearance: .grouped)
config.backgroundColor = .appBackground
config.itemSeparatorHandler = { [unowned self] indexPath, sectionConfig in config.itemSeparatorHandler = { [unowned self] indexPath, sectionConfig in
guard let item = self.dataSource.itemIdentifier(for: indexPath) else { guard let item = self.dataSource.itemIdentifier(for: indexPath) else {
return sectionConfig return sectionConfig
@ -66,16 +65,6 @@ class AccountFollowsListViewController: UIViewController, CollectionViewControll
let accountCell = UICollectionView.CellRegistration<AccountCollectionViewCell, String> { [unowned self] cell, indexPath, item in let accountCell = UICollectionView.CellRegistration<AccountCollectionViewCell, String> { [unowned self] cell, indexPath, item in
cell.delegate = self cell.delegate = self
cell.updateUI(accountID: item) cell.updateUI(accountID: item)
cell.configurationUpdateHandler = { cell, state in
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
cell.backgroundConfiguration = config
}
} }
let loadingCell = UICollectionView.CellRegistration<LoadingCollectionViewCell, Void> { cell, indexPath, item in let loadingCell = UICollectionView.CellRegistration<LoadingCollectionViewCell, Void> { cell, indexPath, item in
cell.indicator.startAnimating() cell.indicator.startAnimating()

View File

@ -31,8 +31,7 @@ class AccountListViewController: UIViewController, CollectionViewController {
} }
override func loadView() { override func loadView() {
var config = UICollectionLayoutListConfiguration(appearance: .grouped) let config = UICollectionLayoutListConfiguration(appearance: .grouped)
config.backgroundColor = .appGroupedBackground
let layout = UICollectionViewCompositionalLayout.list(using: config) let layout = UICollectionViewCompositionalLayout.list(using: config)
view = UICollectionView(frame: .zero, collectionViewLayout: layout) view = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.delegate = self collectionView.delegate = self

View File

@ -72,8 +72,7 @@ class AssetCollectionViewController: UIViewController, UICollectionViewDelegate
// bottom ignores safe area because we want cells to underflow bottom of the screen on notched iPhones // bottom ignores safe area because we want cells to underflow bottom of the screen on notched iPhones
view.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor), view.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor),
]) ])
view.backgroundColor = .appBackground view.backgroundColor = .systemBackground
collectionView.backgroundColor = .appBackground
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed)) navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed))

View File

@ -34,7 +34,6 @@ class AssetCollectionsListViewController: UITableViewController {
tableView.register(UINib(nibName: "AlbumTableViewCell", bundle: .main), forCellReuseIdentifier: "albumCell") tableView.register(UINib(nibName: "AlbumTableViewCell", bundle: .main), forCellReuseIdentifier: "albumCell")
tableView.allowsFocus = true tableView.allowsFocus = true
tableView.backgroundColor = .appGroupedBackground
dataSource = DataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in dataSource = DataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in
switch item { switch item {

View File

@ -112,7 +112,7 @@ struct ComposeAttachmentsList: View {
self.isShowingAssetPickerPopover = false self.isShowingAssetPickerPopover = false
} }
// on iPadOS 16, this is necessary to show the dark color in the popover arrow // on iPadOS 16, this is necessary to show the dark color in the popover arrow
.background(Color(.appBackground)) .background(Color(.systemBackground))
.environment(\.colorScheme, .dark) .environment(\.colorScheme, .dark)
.edgesIgnoringSafeArea(.bottom) .edgesIgnoringSafeArea(.bottom)
.withSheetDetentsIfAvailable() .withSheetDetentsIfAvailable()

View File

@ -111,7 +111,7 @@ struct ComposePollView: View {
private var backgroundColor: Color { private var backgroundColor: Color {
// in light mode, .secondarySystemBackground has a blue-ish hue, which we don't want // in light mode, .secondarySystemBackground has a blue-ish hue, which we don't want
colorScheme == .dark ? Color.appFill : Color(white: 0.95) colorScheme == .dark ? Color(UIColor.secondarySystemBackground) : Color(white: 0.95)
} }
private var buttonBackgroundColor: Color { private var buttonBackgroundColor: Color {
@ -191,7 +191,7 @@ struct ComposePollOption: View {
private var textField: some View { private var textField: some View {
var field = ComposeEmojiTextField(text: $option.text, placeholder: "Option \(optionIndex + 1)", maxLength: mastodonController.instance?.pollsConfiguration?.maxCharactersPerOption) var field = ComposeEmojiTextField(text: $option.text, placeholder: "Option \(optionIndex + 1)", maxLength: mastodonController.instance?.pollsConfiguration?.maxCharactersPerOption)
return field.backgroundColor(.appBackground) return field.backgroundColor(.systemBackground)
} }
private func removeOption() { private func removeOption() {
@ -216,7 +216,7 @@ struct ComposePollOption: View {
.cornerRadius(radiusFraction * size) .cornerRadius(radiusFraction * size)
Rectangle() Rectangle()
.foregroundColor(Color(UIColor.appBackground)) .foregroundColor(Color(UIColor.systemBackground))
.frame(width: innerSize, height: innerSize) .frame(width: innerSize, height: innerSize)
.cornerRadius(radiusFraction * innerSize) .cornerRadius(radiusFraction * innerSize)
} }

View File

@ -94,9 +94,6 @@ struct ComposeView: View {
var body: some View { var body: some View {
ZStack(alignment: .top) { ZStack(alignment: .top) {
// just using .background doesn't work; for some reason it gets inset immediately after the software keyboard is dismissed
Color.appBackground
mainList mainList
.scrollDismissesKeyboardInteractivelyIfAvailable() .scrollDismissesKeyboardInteractivelyIfAvailable()
@ -172,13 +169,11 @@ struct ComposeView: View {
) )
.listRowInsets(EdgeInsets(top: 8, leading: 8, bottom: 4, trailing: 8)) .listRowInsets(EdgeInsets(top: 8, leading: 8, bottom: 4, trailing: 8))
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
.listRowBackground(Color.appBackground)
} }
header header
.listRowInsets(EdgeInsets(top: draft.inReplyToID == nil ? 8 : 4, leading: 8, bottom: 4, trailing: 8)) .listRowInsets(EdgeInsets(top: draft.inReplyToID == nil ? 8 : 4, leading: 8, bottom: 4, trailing: 8))
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
.listRowBackground(Color.appBackground)
if uiState.draft.contentWarningEnabled { if uiState.draft.contentWarningEnabled {
ComposeEmojiTextField( ComposeEmojiTextField(
@ -189,7 +184,6 @@ struct ComposeView: View {
) )
.listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8)) .listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
.listRowBackground(Color.appBackground)
} }
MainComposeTextView( MainComposeTextView(
@ -198,20 +192,17 @@ struct ComposeView: View {
) )
.listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8)) .listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
.listRowBackground(Color.appBackground)
if let poll = draft.poll { if let poll = draft.poll {
ComposePollView(draft: draft, poll: poll) ComposePollView(draft: draft, poll: poll)
.listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8)) .listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
.listRowBackground(Color.appBackground)
} }
ComposeAttachmentsList( ComposeAttachmentsList(
draft: draft draft: draft
) )
.listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 8, trailing: 8)) .listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 8, trailing: 8))
.listRowBackground(Color.appBackground)
} }
.animation(.default, value: draft.poll?.options.count) .animation(.default, value: draft.poll?.options.count)
.scrollDismissesKeyboardInteractivelyIfAvailable() .scrollDismissesKeyboardInteractivelyIfAvailable()
@ -328,7 +319,7 @@ struct ComposeView: View {
} }
} }
extension View { private extension View {
@available(iOS, obsoleted: 16.0) @available(iOS, obsoleted: 16.0)
@ViewBuilder @ViewBuilder
func scrollDismissesKeyboardInteractivelyIfAvailable() -> some View { func scrollDismissesKeyboardInteractivelyIfAvailable() -> some View {

View File

@ -38,11 +38,10 @@ struct MainComposeTextView: View {
@Binding var becomeFirstResponder: Bool @Binding var becomeFirstResponder: Bool
@State private var hasFirstAppeared = false @State private var hasFirstAppeared = false
@ScaledMetric private var fontSize = 20 @ScaledMetric private var fontSize = 20
@Environment(\.colorScheme) private var colorScheme
var body: some View { var body: some View {
ZStack(alignment: .topLeading) { ZStack(alignment: .topLeading) {
colorScheme == .dark ? Color.appFill : Color(uiColor: .secondarySystemBackground) Color(UIColor.secondarySystemBackground)
if draft.text.isEmpty { if draft.text.isEmpty {
placeholder placeholder

View File

@ -37,7 +37,7 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont
override func loadView() { override func loadView() {
var config = UICollectionLayoutListConfiguration(appearance: .plain) var config = UICollectionLayoutListConfiguration(appearance: .plain)
config.backgroundColor = .appSecondaryBackground config.backgroundColor = .secondarySystemBackground
config.leadingSwipeActionsConfigurationProvider = { [unowned self] in config.leadingSwipeActionsConfigurationProvider = { [unowned self] in
(collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions() (collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions()
} }
@ -59,7 +59,7 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont
} }
// we're not using contenetInsetsReference = .readableContent here because it always insets the cells even if // we're not using contenetInsetsReference = .readableContent here because it always insets the cells even if
// the collection view's actual width is narrow enough to fit in the readable width, resulting in a bit of the // the collection view's actual width is narrow enough to fit in the readable width, resulting in a bit of the
// background color always peeking through the edges // background color always peaking through the edges
let layout = UICollectionViewCompositionalLayout.list(using: config) let layout = UICollectionViewCompositionalLayout.list(using: config)
view = UICollectionView(frame: .zero, collectionViewLayout: layout) view = UICollectionView(frame: .zero, collectionViewLayout: layout)
// something about the autoresizing mask breaks resizing the vc // something about the autoresizing mask breaks resizing the vc

View File

@ -94,7 +94,7 @@ class ConversationViewController: UIViewController {
title = NSLocalizedString("Conversation", comment: "conversation screen title") title = NSLocalizedString("Conversation", comment: "conversation screen title")
view.backgroundColor = .appSecondaryBackground view.backgroundColor = .secondarySystemBackground
collapseBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "eye.fill")!, style: .plain, target: self, action: #selector(toggleCollapseButtonPressed)) collapseBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "eye.fill")!, style: .plain, target: self, action: #selector(toggleCollapseButtonPressed))
updateVisibilityBarButtonItem() updateVisibilityBarButtonItem()

View File

@ -141,13 +141,18 @@ class ExpandThreadCollectionViewCell: UICollectionViewListCell {
} }
override func updateConfiguration(using state: UICellConfigurationState) { override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state) var config = UIBackgroundConfiguration.listPlainCell()
if state.isSelected || state.isHighlighted { if state.isSelected || state.isHighlighted {
config.backgroundColor = .appSelectedCellBackground var hue: CGFloat = 0
var saturation: CGFloat = 0
var brightness: CGFloat = 0
UIColor.secondarySystemBackground.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil)
let sign: CGFloat = traitCollection.userInterfaceStyle == .dark ? 1 : -1
config.backgroundColor = UIColor(hue: hue, saturation: saturation, brightness: max(0, brightness + sign * 0.1), alpha: 1)
} else { } else {
config.backgroundColor = .appSecondaryBackground config.backgroundColor = .secondarySystemBackground
} }
backgroundConfiguration = config backgroundConfiguration = config.updated(for: state)
} }
} }

View File

@ -9,20 +9,6 @@
import SwiftUI import SwiftUI
import Pachyderm import Pachyderm
@available(iOS, obsoleted: 16.0)
struct AddHashtagPinnedTimelineRepresentable: UIViewControllerRepresentable {
typealias UIViewControllerType = UIHostingController<AddHashtagPinnedTimelineView>
@Binding var pinnedTimelines: [PinnedTimeline]
func makeUIViewController(context: Context) -> UIHostingController<AddHashtagPinnedTimelineView> {
return UIHostingController(rootView: AddHashtagPinnedTimelineView(pinnedTimelines: $pinnedTimelines))
}
func updateUIViewController(_ uiViewController: UIHostingController<AddHashtagPinnedTimelineView>, context: Context) {
}
}
struct AddHashtagPinnedTimelineView: View { struct AddHashtagPinnedTimelineView: View {
@EnvironmentObject private var mastodonController: MastodonController @EnvironmentObject private var mastodonController: MastodonController
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@ -48,8 +34,6 @@ struct AddHashtagPinnedTimelineView: View {
var body: some View { var body: some View {
NavigationView { NavigationView {
list list
.listStyle(.grouped)
.appGroupedListBackground(container: AddHashtagPinnedTimelineRepresentable.UIViewControllerType.self)
.navigationTitle("Add Hashtag") .navigationTitle("Add Hashtag")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.searchable(text: $viewModel.searchQuery, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("Search for hashtags")) .searchable(text: $viewModel.searchQuery, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("Search for hashtags"))
@ -73,9 +57,8 @@ struct AddHashtagPinnedTimelineView: View {
}) })
} }
@ViewBuilder
private var list: some View { private var list: some View {
let list = List { List {
Section { Section {
if viewModel.searchQuery.isEmpty { if viewModel.searchQuery.isEmpty {
forEachTag(savedAndFollowedHashtags) forEachTag(savedAndFollowedHashtags)
@ -90,17 +73,8 @@ struct AddHashtagPinnedTimelineView: View {
.listRowBackground(EmptyView()) .listRowBackground(EmptyView())
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
} }
.appGroupedListRowBackground()
} }
.listStyle(.grouped) .listStyle(.grouped)
if #available(iOS 16.0, *) {
list
.scrollContentBackground(.hidden)
.background(Color.appGroupedBackground)
} else {
list
}
} }
private func forEachTag(_ tags: [String]) -> some View { private func forEachTag(_ tags: [String]) -> some View {

View File

@ -51,7 +51,6 @@ struct CustomizeTimelinesList: View {
private var navigationBody: some View { private var navigationBody: some View {
List { List {
PinnedTimelinesView(accountPreferences: mastodonController.accountPreferences) PinnedTimelinesView(accountPreferences: mastodonController.accountPreferences)
.appGroupedListRowBackground()
Section { Section {
Toggle(isOn: $preferences.hideReblogsInTimelines) { Toggle(isOn: $preferences.hideReblogsInTimelines) {
@ -63,7 +62,6 @@ struct CustomizeTimelinesList: View {
} header: { } header: {
Text("Home Timeline") Text("Home Timeline")
} }
.appGroupedListRowBackground()
Section { Section {
filtersForEach(unexpiredFilters) filtersForEach(unexpiredFilters)
@ -77,7 +75,6 @@ struct CustomizeTimelinesList: View {
} header: { } header: {
Text("Active Filters") Text("Active Filters")
} }
.appGroupedListRowBackground()
if !expiredFilters.isEmpty { if !expiredFilters.isEmpty {
Section { Section {
@ -85,11 +82,8 @@ struct CustomizeTimelinesList: View {
} header: { } header: {
Text("Expired Filters") Text("Expired Filters")
} }
.appGroupedListRowBackground()
} }
} }
.listStyle(.insetGrouped)
.appGroupedListBackground(container: UIHostingController<CustomizeTimelinesList>.self)
.navigationTitle(Text("Customize Timelines")) .navigationTitle(Text("Customize Timelines"))
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbar { .toolbar {

View File

@ -72,7 +72,6 @@ struct EditFilterView: View {
filter.title = newValue filter.title = newValue
})) }))
} }
.appGroupedListRowBackground()
} }
Section { Section {
@ -97,7 +96,6 @@ struct EditFilterView: View {
} }
} }
} }
.appGroupedListRowBackground()
Section { Section {
if mastodonController.instanceFeatures.filtersV2 { if mastodonController.instanceFeatures.filtersV2 {
@ -122,7 +120,6 @@ struct EditFilterView: View {
} }
} }
} }
.appGroupedListRowBackground()
Section { Section {
ForEach(FilterV1.Context.allCases, id: \.rawValue) { context in ForEach(FilterV1.Context.allCases, id: \.rawValue) { context in
@ -144,10 +141,7 @@ struct EditFilterView: View {
} header: { } header: {
Text("Contexts") Text("Contexts")
} }
.appGroupedListRowBackground()
} }
.appGroupedListBackground(container: UIHostingController<CustomizeTimelinesList>.self)
.scrollDismissesKeyboardInteractivelyIfAvailable()
.navigationTitle(create ? "Add Filter" : "Edit Filter") .navigationTitle(create ? "Add Filter" : "Edit Filter")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbar { .toolbar {

View File

@ -111,13 +111,7 @@ struct PinnedTimelinesView: View {
Text("Pinned Timelines") Text("Pinned Timelines")
} }
.sheet(isPresented: $isShowingAddHashtagSheet, content: { .sheet(isPresented: $isShowingAddHashtagSheet, content: {
if #available(iOS 16.0, *) { AddHashtagPinnedTimelineView(pinnedTimelines: $pinnedTimelines)
AddHashtagPinnedTimelineView(pinnedTimelines: $pinnedTimelines)
.edgesIgnoringSafeArea(.bottom)
} else {
AddHashtagPinnedTimelineRepresentable(pinnedTimelines: $pinnedTimelines)
.edgesIgnoringSafeArea(.bottom)
}
}) })
.sheet(isPresented: $isShowingAddInstanceSheet, content: { .sheet(isPresented: $isShowingAddInstanceSheet, content: {
AddInstancePinnedTimelineView(pinnedTimelines: $pinnedTimelines) AddInstancePinnedTimelineView(pinnedTimelines: $pinnedTimelines)

View File

@ -34,15 +34,15 @@ class AddSavedHashtagViewController: UIViewController {
title = NSLocalizedString("Search", comment: "search screen title") title = NSLocalizedString("Search", comment: "search screen title")
view.backgroundColor = .systemGroupedBackground
var config = UICollectionLayoutListConfiguration(appearance: .grouped) var config = UICollectionLayoutListConfiguration(appearance: .grouped)
config.backgroundColor = .appGroupedBackground
config.headerMode = .supplementary config.headerMode = .supplementary
let layout = UICollectionViewCompositionalLayout.list(using: config) let layout = UICollectionViewCompositionalLayout.list(using: config)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout) collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight] collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.delegate = self collectionView.delegate = self
collectionView.allowsFocus = true collectionView.allowsFocus = true
collectionView.backgroundColor = .appGroupedBackground
view.addSubview(collectionView) view.addSubview(collectionView)
let sectionHeaderCell = UICollectionView.SupplementaryRegistration<UICollectionViewListCell>(elementKind: UICollectionView.elementKindSectionHeader) { (headerView, collectionView, indexPath) in let sectionHeaderCell = UICollectionView.SupplementaryRegistration<UICollectionViewListCell>(elementKind: UICollectionView.elementKindSectionHeader) { (headerView, collectionView, indexPath) in

View File

@ -43,8 +43,7 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate, Collect
super.viewDidLoad() super.viewDidLoad()
var configuration = UICollectionLayoutListConfiguration(appearance: .insetGrouped) var configuration = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
configuration.backgroundColor = .appGroupedBackground configuration.trailingSwipeActionsConfigurationProvider = self.trailingSwipeActionsForCell(at:)
configuration.trailingSwipeActionsConfigurationProvider = { [unowned self] in self.trailingSwipeActionsForCell(at: $0) }
configuration.headerMode = .supplementary configuration.headerMode = .supplementary
let layout = UICollectionViewCompositionalLayout.list(using: configuration) let layout = UICollectionViewCompositionalLayout.list(using: configuration)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout) collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
@ -131,16 +130,6 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate, Collect
config.image = item.image config.image = item.image
cell.contentConfiguration = config cell.contentConfiguration = config
cell.configurationUpdateHandler = { cell, state in
var config = UIBackgroundConfiguration.listGroupedCell()
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
cell.backgroundConfiguration = config
}
switch item { switch item {
case .addList, .addSavedHashtag, .findInstance: case .addList, .addSavedHashtag, .findInstance:
cell.accessories = [] cell.accessories = []

View File

@ -39,7 +39,6 @@ class FeaturedProfileCollectionViewCell: UICollectionViewCell {
noteTextView.textContainerInset = UIEdgeInsets(top: 16, left: 4, bottom: 16, right: 4) noteTextView.textContainerInset = UIEdgeInsets(top: 16, left: 4, bottom: 16, right: 4)
backgroundColor = .clear backgroundColor = .clear
clippingView.backgroundColor = .appBackground
clippingView.layer.cornerRadius = 5 clippingView.layer.cornerRadius = 5
clippingView.layer.borderWidth = 1 clippingView.layer.borderWidth = 1
clippingView.layer.masksToBounds = true clippingView.layer.masksToBounds = true

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/> <device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@ -55,6 +55,7 @@
</label> </label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" userInteractionEnabled="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="749" scrollEnabled="NO" editable="NO" textAlignment="natural" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bvj-F0-ggC" customClass="StatusContentTextView" customModule="Tusker" customModuleProvider="target"> <textView clipsSubviews="YES" multipleTouchEnabled="YES" userInteractionEnabled="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="749" scrollEnabled="NO" editable="NO" textAlignment="natural" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bvj-F0-ggC" customClass="StatusContentTextView" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="8" y="102" width="384" height="98"/> <rect key="frame" x="8" y="102" width="384" height="98"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string> <string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<color key="textColor" systemColor="labelColor"/> <color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/> <fontDescription key="fontDescription" type="system" pointSize="14"/>
@ -101,7 +102,7 @@
</objects> </objects>
<resources> <resources>
<systemColor name="labelColor"> <systemColor name="labelColor">
<color red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor> </systemColor>
<systemColor name="systemBackgroundColor"> <systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>

View File

@ -64,7 +64,7 @@ class ProfileDirectoryViewController: UIViewController {
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout) collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight] collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.backgroundColor = .appSecondaryBackground collectionView.backgroundColor = .secondarySystemBackground
collectionView.register(UINib(nibName: "FeaturedProfileCollectionViewCell", bundle: .main), forCellWithReuseIdentifier: "featuredProfileCell") collectionView.register(UINib(nibName: "FeaturedProfileCollectionViewCell", bundle: .main), forCellWithReuseIdentifier: "featuredProfileCell")
collectionView.delegate = self collectionView.delegate = self
collectionView.dragDelegate = self collectionView.dragDelegate = self

View File

@ -36,7 +36,6 @@ class SuggestedProfileCardCollectionViewCell: UICollectionViewCell {
layer.shadowOffset = .zero layer.shadowOffset = .zero
layer.masksToBounds = false layer.masksToBounds = false
contentView.layer.cornerRadius = 12.5 contentView.layer.cornerRadius = 12.5
contentView.backgroundColor = .appGroupedCellBackground
updateLayerColors() updateLayerColors()
headerImageView.cache = .headers headerImageView.cache = .headers

View File

@ -34,7 +34,6 @@ class TrendingLinkCardCollectionViewCell: UICollectionViewCell {
layer.shadowOffset = .zero layer.shadowOffset = .zero
layer.masksToBounds = false layer.masksToBounds = false
contentView.layer.cornerRadius = 12.5 contentView.layer.cornerRadius = 12.5
contentView.backgroundColor = .appGroupedCellBackground
updateLayerColors() updateLayerColors()
addGestureRecognizer(UIHoverGestureRecognizer(target: self, action: #selector(hoverRecognized))) addGestureRecognizer(UIHoverGestureRecognizer(target: self, action: #selector(hoverRecognized)))

View File

@ -80,16 +80,6 @@ class TrendingLinkTableViewCell: UITableViewCell {
thumbnailView.layer.cornerRadius = 0.05 * thumbnailView.bounds.width thumbnailView.layer.cornerRadius = 0.05 * thumbnailView.bounds.width
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
backgroundConfiguration = config
}
func updateUI(card: Card) { func updateUI(card: Card) {
self.card = card self.card = card
self.thumbnailView.image = nil self.thumbnailView.image = nil

View File

@ -37,7 +37,6 @@ class TrendingLinksViewController: EnhancedTableViewController {
tableView.register(TrendingLinkTableViewCell.self, forCellReuseIdentifier: "trendingLinkCell") tableView.register(TrendingLinkTableViewCell.self, forCellReuseIdentifier: "trendingLinkCell")
tableView.estimatedRowHeight = 100 tableView.estimatedRowHeight = 100
tableView.allowsFocus = true tableView.allowsFocus = true
tableView.backgroundColor = .appGroupedBackground
dataSource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { tableView, indexPath, item in dataSource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { tableView, indexPath, item in
let cell = tableView.dequeueReusableCell(withIdentifier: "trendingLinkCell", for: indexPath) as! TrendingLinkTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: "trendingLinkCell", for: indexPath) as! TrendingLinkTableViewCell

View File

@ -45,7 +45,6 @@ class TrendsViewController: UIViewController, CollectionViewController {
case .trendingHashtags: case .trendingHashtags:
var listConfig = UICollectionLayoutListConfiguration(appearance: .grouped) var listConfig = UICollectionLayoutListConfiguration(appearance: .grouped)
listConfig.headerMode = .supplementary listConfig.headerMode = .supplementary
listConfig.backgroundColor = .appGroupedBackground
return .list(using: listConfig, layoutEnvironment: environment) return .list(using: listConfig, layoutEnvironment: environment)
case .trendingLinks: case .trendingLinks:
@ -79,7 +78,6 @@ class TrendsViewController: UIViewController, CollectionViewController {
case .trendingStatuses: case .trendingStatuses:
var listConfig = UICollectionLayoutListConfiguration(appearance: .grouped) var listConfig = UICollectionLayoutListConfiguration(appearance: .grouped)
listConfig.headerMode = .supplementary listConfig.headerMode = .supplementary
listConfig.backgroundColor = .appGroupedBackground
return .list(using: listConfig, layoutEnvironment: environment) return .list(using: listConfig, layoutEnvironment: environment)
} }
} }
@ -87,7 +85,7 @@ class TrendsViewController: UIViewController, CollectionViewController {
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight] collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.delegate = self collectionView.delegate = self
collectionView.dragDelegate = self collectionView.dragDelegate = self
collectionView.backgroundColor = .appGroupedBackground collectionView.backgroundColor = .secondarySystemBackground
collectionView.allowsFocus = true collectionView.allowsFocus = true
view.addSubview(collectionView) view.addSubview(collectionView)
@ -110,7 +108,7 @@ class TrendsViewController: UIViewController, CollectionViewController {
let trendingLinkCell = UICollectionView.CellRegistration<TrendingLinkCardCollectionViewCell, Card>(cellNib: UINib(nibName: "TrendingLinkCardCollectionViewCell", bundle: .main)) { (cell, indexPath, card) in let trendingLinkCell = UICollectionView.CellRegistration<TrendingLinkCardCollectionViewCell, Card>(cellNib: UINib(nibName: "TrendingLinkCardCollectionViewCell", bundle: .main)) { (cell, indexPath, card) in
cell.updateUI(card: card) cell.updateUI(card: card)
} }
let statusCell = UICollectionView.CellRegistration<TrendingStatusCollectionViewCell, (String, CollapseState)> { [unowned self] cell, indexPath, item in let statusCell = UICollectionView.CellRegistration<TimelineStatusCollectionViewCell, (String, CollapseState)> { [unowned self] cell, indexPath, item in
cell.delegate = self cell.delegate = self
// TODO: filter trends // TODO: filter trends
cell.updateUI(statusID: item.0, state: item.1, filterResult: .allow, precomputedContent: nil) cell.updateUI(statusID: item.0, state: item.1, filterResult: .allow, precomputedContent: nil)

View File

@ -54,7 +54,6 @@ class EditListAccountsViewController: EnhancedTableViewController {
tableView.rowHeight = UITableView.automaticDimension tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 66 tableView.estimatedRowHeight = 66
tableView.allowsSelection = false tableView.allowsSelection = false
tableView.backgroundColor = .appGroupedBackground
dataSource = DataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in dataSource = DataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in
guard case let .account(id) = item else { fatalError() } guard case let .account(id) = item else { fatalError() }
@ -62,15 +61,6 @@ class EditListAccountsViewController: EnhancedTableViewController {
let cell = tableView.dequeueReusableCell(withIdentifier: "accountCell", for: indexPath) as! AccountTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: "accountCell", for: indexPath) as! AccountTableViewCell
cell.delegate = self cell.delegate = self
cell.updateUI(accountID: id) cell.updateUI(accountID: id)
cell.configurationUpdateHandler = { cell, state in
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
cell.backgroundConfiguration = config
}
return cell return cell
}) })
dataSource.editListAccountsController = self dataSource.editListAccountsController = self

View File

@ -45,7 +45,6 @@ class LocalPredicateStatusesViewController: UIViewController, CollectionViewCont
override func loadView() { override func loadView() {
var config = UICollectionLayoutListConfiguration(appearance: .plain) var config = UICollectionLayoutListConfiguration(appearance: .plain)
config.backgroundColor = .appBackground
config.leadingSwipeActionsConfigurationProvider = { [unowned self] in config.leadingSwipeActionsConfigurationProvider = { [unowned self] in
(collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions() (collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions()
} }

View File

@ -85,7 +85,6 @@ struct MuteAccountView: View {
Text("This user's posts will be hidden from your timeline. You can still receive notifications from them.") Text("This user's posts will be hidden from your timeline. You can still receive notifications from them.")
} }
} }
.appGroupedListRowBackground()
Section { Section {
Picker(selection: $duration) { Picker(selection: $duration) {
@ -100,7 +99,6 @@ struct MuteAccountView: View {
Text("The mute will automatically be removed after the selected time.") Text("The mute will automatically be removed after the selected time.")
} }
} }
.appGroupedListRowBackground()
Button(action: self.mute) { Button(action: self.mute) {
if isMuting { if isMuting {
@ -115,9 +113,7 @@ struct MuteAccountView: View {
} }
} }
.disabled(isMuting) .disabled(isMuting)
.appGroupedListRowBackground()
} }
.appGroupedListBackground(container: UIHostingController<MuteAccountView>.self)
.alertWithData("Erorr Muting", data: $error, actions: { error in .alertWithData("Erorr Muting", data: $error, actions: { error in
Button("OK") {} Button("OK") {}
}, message: { error in }, message: { error in

View File

@ -58,7 +58,6 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController<
tableView.cellLayoutMarginsFollowReadableWidth = UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac tableView.cellLayoutMarginsFollowReadableWidth = UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac
tableView.allowsFocus = true tableView.allowsFocus = true
tableView.backgroundColor = .appBackground
NotificationCenter.default.addObserver(self, selector: #selector(handleStatusDeleted), name: .statusDeleted, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleStatusDeleted), name: .statusDeleted, object: nil)
} }

View File

@ -63,7 +63,6 @@ class InstanceSelectorTableViewController: UITableViewController {
appearance.configureWithDefaultBackground() appearance.configureWithDefaultBackground()
navigationItem.scrollEdgeAppearance = appearance navigationItem.scrollEdgeAppearance = appearance
tableView.backgroundColor = .appGroupedBackground
tableView.keyboardDismissMode = .interactive tableView.keyboardDismissMode = .interactive
tableView.register(UINib(nibName: "InstanceTableViewCell", bundle: .main), forCellReuseIdentifier: instanceCell) tableView.register(UINib(nibName: "InstanceTableViewCell", bundle: .main), forCellReuseIdentifier: instanceCell)
tableView.rowHeight = UITableView.automaticDimension tableView.rowHeight = UITableView.automaticDimension
@ -108,10 +107,6 @@ class InstanceSelectorTableViewController: UITableViewController {
} }
.debounce(for: .seconds(1), scheduler: RunLoop.main) .debounce(for: .seconds(1), scheduler: RunLoop.main)
.sink { [weak self] in self?.updateSpecificInstance(domain: $0) } .sink { [weak self] in self?.updateSpecificInstance(domain: $0) }
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadRecommendedInstances() loadRecommendedInstances()
} }
@ -208,7 +203,7 @@ class InstanceSelectorTableViewController: UITableViewController {
private func createActivityIndicatorHeader() { private func createActivityIndicatorHeader() {
let header = UITableViewHeaderFooterView() let header = UITableViewHeaderFooterView()
header.translatesAutoresizingMaskIntoConstraints = false header.translatesAutoresizingMaskIntoConstraints = false
header.contentView.backgroundColor = .appGroupedBackground header.contentView.backgroundColor = .systemGroupedBackground
activityIndicator = UIActivityIndicatorView(style: .large) activityIndicator = UIActivityIndicatorView(style: .large)
activityIndicator.translatesAutoresizingMaskIntoConstraints = false activityIndicator.translatesAutoresizingMaskIntoConstraints = false

View File

@ -42,7 +42,6 @@ struct AboutView: View {
} }
} }
} }
.appGroupedListRowBackground()
Section { Section {
Link("Website", destination: URL(string: "https://vaccor.space/tusker")!) Link("Website", destination: URL(string: "https://vaccor.space/tusker")!)
@ -68,10 +67,7 @@ struct AboutView: View {
Link("Source Code", destination: URL(string: "https://git.shadowfacts.net/shadowfacts/Tusker")!) Link("Source Code", destination: URL(string: "https://git.shadowfacts.net/shadowfacts/Tusker")!)
Link("Issue Tracker", destination: URL(string: "https://git.shadowfacts.net/shadowfacts/Tusker/issues")!) Link("Issue Tracker", destination: URL(string: "https://git.shadowfacts.net/shadowfacts/Tusker/issues")!)
} }
.appGroupedListRowBackground()
} }
.listStyle(.insetGrouped)
.appGroupedListBackground(container: PreferencesNavigationController.self)
.sheet(isPresented: $isShowingMailSheet) { .sheet(isPresented: $isShowingMailSheet) {
MailSheet(logData: logData) MailSheet(logData: logData)
} }

View File

@ -14,7 +14,6 @@ struct AcknowledgementsView: View {
Text(text) Text(text)
.padding(.horizontal, 16) .padding(.horizontal, 16)
} }
.appGroupedListBackground(container: PreferencesNavigationController.self)
.navigationTitle("Acknowledgements") .navigationTitle("Acknowledgements")
} }

View File

@ -23,8 +23,7 @@ struct AdvancedPrefsView : View {
errorReportingSection errorReportingSection
cachingSection cachingSection
} }
.listStyle(.insetGrouped) .listStyle(InsetGroupedListStyle())
.appGroupedListBackground(container: PreferencesNavigationController.self)
.navigationBarTitle(Text("Advanced")) .navigationBarTitle(Text("Advanced"))
} }
@ -51,7 +50,6 @@ struct AdvancedPrefsView : View {
// see FB6838291 // see FB6838291
} }
} }
.appGroupedListRowBackground()
} }
var cloudKitSection: some View { var cloudKitSection: some View {
@ -76,9 +74,7 @@ struct AdvancedPrefsView : View {
Text(String(describing: cloudKitStatus!)) Text(String(describing: cloudKitStatus!))
} }
} }
} }.task {
.appGroupedListRowBackground()
.task {
CKContainer.default().accountStatus { status, error in CKContainer.default().accountStatus { status, error in
if let error { if let error {
Logging.general.error("Unable to get CloudKit status: \(String(describing: error))") Logging.general.error("Unable to get CloudKit status: \(String(describing: error))")
@ -103,7 +99,6 @@ struct AdvancedPrefsView : View {
.lineLimit(nil) .lineLimit(nil)
} }
} }
.appGroupedListRowBackground()
} }
var cachingSection: some View { var cachingSection: some View {
@ -125,9 +120,7 @@ struct AdvancedPrefsView : View {
s += AttributedString("\nMastodon cache size: \(ByteCountFormatter().string(fromByteCount: mastodonCacheSize))") s += AttributedString("\nMastodon cache size: \(ByteCountFormatter().string(fromByteCount: mastodonCacheSize))")
} }
return Text(s) return Text(s)
} }.task {
.appGroupedListRowBackground()
.task {
imageCacheSize = [ imageCacheSize = [
ImageCache.avatars, ImageCache.avatars,
.headers, .headers,

View File

@ -6,19 +6,21 @@
// //
import SwiftUI import SwiftUI
import Combine
struct AppearancePrefsView : View { struct AppearancePrefsView : View {
@ObservedObject var preferences = Preferences.shared @ObservedObject var preferences = Preferences.shared
private var appearanceChangePublisher: some Publisher<Void, Never> { private var theme: Binding<UIUserInterfaceStyle> = Binding(get: {
preferences.$theme Preferences.shared.theme
.map { _ in () } }, set: {
.merge(with: preferences.$pureBlackDarkMode.map { _ in () }, Preferences.shared.theme = $0
preferences.$accentColor.map { _ in () } NotificationCenter.default.post(name: .themePreferenceChanged, object: nil)
) })
// the prefrence publishers are all willSet, but want to notify after the change, so wait one runloop iteration private var accentColor: Binding<Preferences.AccentColor> = Binding {
.receive(on: DispatchQueue.main) Preferences.shared.accentColor
} set: {
Preferences.shared.accentColor = $0
NotificationCenter.default.post(name: .themePreferenceChanged, object: nil)
} }
private var useCircularAvatars: Binding<Bool> = Binding(get: { private var useCircularAvatars: Binding<Bool> = Binding(get: {
@ -48,27 +50,19 @@ struct AppearancePrefsView : View {
accountsSection accountsSection
postsSection postsSection
} }
.listStyle(.insetGrouped) .listStyle(InsetGroupedListStyle())
.appGroupedListBackground(container: PreferencesNavigationController.self)
.navigationBarTitle(Text("Appearance")) .navigationBarTitle(Text("Appearance"))
} }
private var themeSection: some View { private var themeSection: some View {
Section { Section {
Picker(selection: $preferences.theme, label: Text("Theme")) { Picker(selection: theme, label: Text("Theme")) {
Text("Use System Theme").tag(UIUserInterfaceStyle.unspecified) Text("Use System Theme").tag(UIUserInterfaceStyle.unspecified)
Text("Light").tag(UIUserInterfaceStyle.light) Text("Light").tag(UIUserInterfaceStyle.light)
Text("Dark").tag(UIUserInterfaceStyle.dark) Text("Dark").tag(UIUserInterfaceStyle.dark)
} }
// macOS system dark mode isn't pure black, so this isn't necessary Picker(selection: accentColor, label: Text("Accent Color")) {
if !ProcessInfo.processInfo.isMacCatalystApp && !ProcessInfo.processInfo.isiOSAppOnMac {
Toggle(isOn: $preferences.pureBlackDarkMode) {
Text("Pure Black Dark Mode")
}
}
Picker(selection: $preferences.accentColor, label: Text("Accent Color")) {
ForEach(accentColorsAndImages, id: \.0.rawValue) { (color, image) in ForEach(accentColorsAndImages, id: \.0.rawValue) { (color, image) in
HStack { HStack {
Text(color.name) Text(color.name)
@ -81,10 +75,6 @@ struct AppearancePrefsView : View {
} }
} }
} }
.onReceive(appearanceChangePublisher) { _ in
NotificationCenter.default.post(name: .themePreferenceChanged, object: nil)
}
.appGroupedListRowBackground()
} }
private var accountsSection: some View { private var accountsSection: some View {
@ -96,7 +86,6 @@ struct AppearancePrefsView : View {
Text("Hide Custom Emoji in Usernames") Text("Hide Custom Emoji in Usernames")
} }
} }
.appGroupedListRowBackground()
} }
private var postsSection: some View { private var postsSection: some View {
@ -124,7 +113,6 @@ struct AppearancePrefsView : View {
.navigationTitle("Trailing Swipe Actions") .navigationTitle("Trailing Swipe Actions")
} }
} }
.appGroupedListRowBackground()
} }
} }

View File

@ -18,8 +18,7 @@ struct BehaviorPrefsView: View {
linksSection linksSection
contentWarningsSection contentWarningsSection
} }
.listStyle(.insetGrouped) .listStyle(InsetGroupedListStyle())
.appGroupedListBackground(container: PreferencesNavigationController.self)
.navigationBarTitle(Text("Behavior")) .navigationBarTitle(Text("Behavior"))
} }
@ -29,7 +28,6 @@ struct BehaviorPrefsView: View {
Text("Require Confirmation Before Reblogging") Text("Require Confirmation Before Reblogging")
} }
} }
.appGroupedListRowBackground()
} }
private var timelineSection: some View { private var timelineSection: some View {
@ -40,7 +38,6 @@ struct BehaviorPrefsView: View {
} header: { } header: {
Text("Timeline") Text("Timeline")
} }
.appGroupedListRowBackground()
} }
private var linksSection: some View { private var linksSection: some View {
@ -55,7 +52,6 @@ struct BehaviorPrefsView: View {
Text("Always Use Reader Mode in In-App Safari") Text("Always Use Reader Mode in In-App Safari")
}.disabled(!preferences.useInAppSafari) }.disabled(!preferences.useInAppSafari)
} }
.appGroupedListRowBackground()
} }
private var contentWarningsSection: some View { private var contentWarningsSection: some View {
@ -72,7 +68,6 @@ struct BehaviorPrefsView: View {
Text(preferences.expandAllContentWarnings ? "Collapse Posts with Keywords in CWs" : "Expand Posts with Keywords in CWs") Text(preferences.expandAllContentWarnings ? "Collapse Posts with Keywords in CWs" : "Expand Posts with Keywords in CWs")
} }
} }
.appGroupedListRowBackground()
} }
} }

View File

@ -19,8 +19,7 @@ struct ComposingPrefsView: View {
replyingSection replyingSection
writingSection writingSection
} }
.listStyle(.insetGrouped) .listStyle(InsetGroupedListStyle())
.appGroupedListBackground(container: PreferencesNavigationController.self)
.navigationBarTitle("Composing") .navigationBarTitle("Composing")
} }
@ -52,7 +51,6 @@ struct ComposingPrefsView: View {
} footer: { } footer: {
Text("When starting a reply, Tusker will use your preferred visibility or the visibility of the post to which you're replying, whichever is narrower.") Text("When starting a reply, Tusker will use your preferred visibility or the visibility of the post to which you're replying, whichever is narrower.")
} }
.appGroupedListRowBackground()
} }
var composingSection: some View { var composingSection: some View {
@ -64,7 +62,6 @@ struct ComposingPrefsView: View {
Text("Require Attachment Descriptions") Text("Require Attachment Descriptions")
} }
} }
.appGroupedListRowBackground()
} }
var replyingSection: some View { var replyingSection: some View {
@ -78,7 +75,6 @@ struct ComposingPrefsView: View {
Text("Mention Reblogger") Text("Mention Reblogger")
} }
} }
.appGroupedListRowBackground()
} }
var writingSection: some View { var writingSection: some View {
@ -87,7 +83,6 @@ struct ComposingPrefsView: View {
Text("Show @ and # on Keyboard") Text("Show @ and # on Keyboard")
} }
} }
.appGroupedListRowBackground()
} }
} }

View File

@ -15,8 +15,7 @@ struct MediaPrefsView: View {
List { List {
viewingSection viewingSection
} }
.listStyle(.insetGrouped) .listStyle(InsetGroupedListStyle())
.appGroupedListBackground(container: PreferencesNavigationController.self)
.navigationBarTitle("Media") .navigationBarTitle("Media")
} }
@ -43,7 +42,6 @@ struct MediaPrefsView: View {
Text("Show Uncropped Media Inline") Text("Show Uncropped Media Inline")
} }
} }
.appGroupedListRowBackground()
} }
} }

View File

@ -23,8 +23,8 @@ struct OppositeCollapseKeywordsView: View {
ZStack { ZStack {
// the background from the grouped ListStyle clips to the safe area, so when the keyboard is hiding/showing // the background from the grouped ListStyle clips to the safe area, so when the keyboard is hiding/showing
// the color behind it can be seen, which looks odd // the color behind it can be seen, which looks odd
// Color(UIColor.secondarySystemBackground) Color(UIColor.secondarySystemBackground)
// .edgesIgnoringSafeArea(.bottom) .edgesIgnoringSafeArea(.bottom)
List { List {
Section(footer: Text("A post matches if its content warning contains the text of a keyword, ignoring case.")) { Section(footer: Text("A post matches if its content warning contains the text of a keyword, ignoring case.")) {
@ -37,11 +37,9 @@ struct OppositeCollapseKeywordsView: View {
FocusableTextField(placeholder: "Add Keyword", text: $valueToAdd, becomeFirstResponder: $makeAddFieldFirstResponder, onCommit: self.addKeyword) FocusableTextField(placeholder: "Add Keyword", text: $valueToAdd, becomeFirstResponder: $makeAddFieldFirstResponder, onCommit: self.addKeyword)
} }
.appGroupedListRowBackground()
} }
.animation(.default, value: keywords.map(\.id)) .animation(.default, value: keywords.map(\.id))
.listStyle(.grouped) .listStyle(GroupedListStyle())
.appGroupedListBackground(container: PreferencesNavigationController.self)
} }
.onAppear(perform: updateAppearance) .onAppear(perform: updateAppearance)
.navigationBarTitle(preferences.expandAllContentWarnings ? "Collapse Post CW Keywords" : "Expand Post CW Keywords") .navigationBarTitle(preferences.expandAllContentWarnings ? "Collapse Post CW Keywords" : "Expand Post CW Keywords")

View File

@ -24,7 +24,6 @@ struct PreferencesView: View {
aboutSection aboutSection
} }
.listStyle(.insetGrouped) .listStyle(.insetGrouped)
.appGroupedListBackground(container: PreferencesNavigationController.self)
.navigationBarTitle("Preferences") .navigationBarTitle("Preferences")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
} }
@ -85,7 +84,6 @@ struct PreferencesView: View {
} header: { } header: {
Text("Accounts") Text("Accounts")
} }
.appGroupedListRowBackground()
} }
private var preferencesSection: some View { private var preferencesSection: some View {
@ -109,7 +107,6 @@ struct PreferencesView: View {
Text("Advanced") Text("Advanced")
} }
} }
.appGroupedListRowBackground()
} }
private var aboutSection: some View { private var aboutSection: some View {
@ -124,7 +121,6 @@ struct PreferencesView: View {
AcknowledgementsView() AcknowledgementsView()
} }
} }
.appGroupedListRowBackground()
} }
func logoutPressed() { func logoutPressed() {

View File

@ -42,7 +42,6 @@ class SwipeActionsPrefsViewController: UIViewController, UICollectionViewDelegat
override func loadView() { override func loadView() {
let layout = UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in let layout = UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in
var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped) var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
config.backgroundColor = .appGroupedBackground
if dataSource.sectionIdentifier(for: sectionIndex) == .selected { if dataSource.sectionIdentifier(for: sectionIndex) == .selected {
config.headerMode = .supplementary config.headerMode = .supplementary
} }
@ -60,15 +59,6 @@ class SwipeActionsPrefsViewController: UIViewController, UICollectionViewDelegat
config.image = UIImage(systemName: item.systemImageName) config.image = UIImage(systemName: item.systemImageName)
cell.contentConfiguration = config cell.contentConfiguration = config
cell.accessories = [.reorder(displayed: .always)] cell.accessories = [.reorder(displayed: .always)]
cell.configurationUpdateHandler = { cell, state in
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
cell.backgroundConfiguration = config
}
} }
let dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in let dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: itemIdentifier) return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: itemIdentifier)

View File

@ -26,12 +26,8 @@ struct TipJarView: View {
@StateObject private var observer = UbiquitousKeyValueStoreObserver() @StateObject private var observer = UbiquitousKeyValueStoreObserver()
var body: some View { var body: some View {
ZStack { productsView
Color.appGroupedBackground .overlay {
.edgesIgnoringSafeArea(.all)
productsView
if showConfetti { if showConfetti {
ConfettiView() ConfettiView()
.transition(.opacity.animation(.default)) .transition(.opacity.animation(.default))

View File

@ -19,8 +19,7 @@ struct WellnessPrefsView: View {
disableInfiniteScrolling disableInfiniteScrolling
hideTrends hideTrends
} }
.listStyle(.insetGrouped) .listStyle(InsetGroupedListStyle())
.appGroupedListBackground(container: PreferencesNavigationController.self)
.navigationBarTitle(Text("Digital Wellness")) .navigationBarTitle(Text("Digital Wellness"))
} }
@ -30,7 +29,6 @@ struct WellnessPrefsView: View {
Text("Favorite and Reblog Counts in Conversations") Text("Favorite and Reblog Counts in Conversations")
} }
} }
.appGroupedListRowBackground()
} }
private var notificationsMode: some View { private var notificationsMode: some View {
@ -41,7 +39,6 @@ struct WellnessPrefsView: View {
} }
} }
} }
.appGroupedListRowBackground()
} }
private var grayscaleImages: some View { private var grayscaleImages: some View {
@ -50,7 +47,6 @@ struct WellnessPrefsView: View {
Text("Grayscale Images") Text("Grayscale Images")
} }
} }
.appGroupedListRowBackground()
} }
private var disableInfiniteScrolling: some View { private var disableInfiniteScrolling: some View {
@ -59,7 +55,6 @@ struct WellnessPrefsView: View {
Text("Disable Infinite Scrolling") Text("Disable Infinite Scrolling")
} }
} }
.appGroupedListRowBackground()
} }
private var hideTrends: some View { private var hideTrends: some View {
@ -68,7 +63,6 @@ struct WellnessPrefsView: View {
Text("Hide Trends") Text("Hide Trends")
} }
} }
.appGroupedListRowBackground()
} }
} }

View File

@ -23,7 +23,7 @@ class ProfileHeaderCollectionViewCell: UICollectionViewCell {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
contentView.backgroundColor = .appBackground contentView.backgroundColor = .systemBackground
isOpaque = true isOpaque = true
contentView.isOpaque = true contentView.isOpaque = true
} }

View File

@ -56,7 +56,6 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
override func loadView() { override func loadView() {
var config = UICollectionLayoutListConfiguration(appearance: .plain) var config = UICollectionLayoutListConfiguration(appearance: .plain)
config.backgroundColor = .appBackground
config.leadingSwipeActionsConfigurationProvider = { [unowned self] in config.leadingSwipeActionsConfigurationProvider = { [unowned self] in
(collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions() (collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions()
} }
@ -83,9 +82,7 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
} }
let layout = UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in let layout = UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in
if case .header = dataSource.sectionIdentifier(for: sectionIndex) { if case .header = dataSource.sectionIdentifier(for: sectionIndex) {
var config = UICollectionLayoutListConfiguration(appearance: .plain) return .list(using: .init(appearance: .plain), layoutEnvironment: environment)
config.backgroundColor = .appBackground
return .list(using: config, layoutEnvironment: environment)
} else { } else {
let section = NSCollectionLayoutSection.list(using: config, layoutEnvironment: environment) let section = NSCollectionLayoutSection.list(using: config, layoutEnvironment: environment)
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac { if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {

View File

@ -68,7 +68,7 @@ class ProfileViewController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
view.backgroundColor = .appBackground view.backgroundColor = .systemBackground
for pageController in pageControllers { for pageController in pageControllers {
pageController.profileHeaderDelegate = self pageController.profileHeaderDelegate = self

View File

@ -34,57 +34,25 @@ struct ReportAddStatusView: View {
ReportStatusView(status: status, mastodonController: mastodonController) ReportStatusView(status: status, mastodonController: mastodonController)
} }
} }
.appGroupedListRowBackground()
} }
.modifier(ScrollBackgroundModifier())
} else { } else {
ZStack { ProgressView()
// because the background needs to fill the entire screen .progressViewStyle(.circular)
Color.appGroupedBackground .alertWithData("Error Loading Posts", data: $error, actions: { _ in
.edgesIgnoringSafeArea(.all) Button("OK") {}
}, message: { error in
ProgressView() Text(error.localizedDescription)
.progressViewStyle(.circular) })
.alertWithData("Error Loading Posts", data: $error, actions: { _ in .task { @MainActor in
Button("OK") {} do {
}, message: { error in let req = Account.getStatuses(report.accountID, range: .count(40), excludeReplies: false, excludeReblogs: true)
Text(error.localizedDescription) let (statuses, _) = try await mastodonController.run(req)
}) await mastodonController.persistentContainer.addAll(statuses: statuses)
.task { @MainActor in self.statuses = statuses.compactMap { mastodonController.persistentContainer.status(for: $0.id) }
do { } catch {
let req = Account.getStatuses(report.accountID, range: .count(40), excludeReplies: false, excludeReblogs: true) self.error = error
let (statuses, _) = try await mastodonController.run(req)
await mastodonController.persistentContainer.addAll(statuses: statuses)
self.statuses = statuses.compactMap { mastodonController.persistentContainer.status(for: $0.id) }
} catch {
self.error = error
}
} }
}
}
}
}
private struct ScrollBackgroundModifier: ViewModifier {
@Environment(\.colorScheme) private var colorScheme
func body(content: Content) -> some View {
if #available(iOS 16.0, *) {
content
.scrollContentBackground(.hidden)
.background {
// otherwise the pureBlackDarkMode isn't propagated, for some reason?
// even though it is for ReportSelectRulesView??
let traits: UITraitCollection = {
let t = UITraitCollection(userInterfaceStyle: colorScheme == .dark ? .dark : .light)
t.pureBlackDarkMode = true
return t
}()
Color(uiColor: .appGroupedBackground.resolvedColor(with: traits))
.edgesIgnoringSafeArea(.all)
} }
} else {
content
} }
} }
} }

View File

@ -47,27 +47,11 @@ struct ReportSelectRulesView: View {
.foregroundColor(selectedRuleIDs.contains(rule.id) ? .accentColor : .clear) .foregroundColor(selectedRuleIDs.contains(rule.id) ? .accentColor : .clear)
} }
} }
.appGroupedListRowBackground()
} }
.withAppBackgroundIfAvailable()
.navigationTitle("Rules") .navigationTitle("Rules")
} }
} }
private extension View {
@available(iOS, obsoleted: 16.0)
@ViewBuilder
func withAppBackgroundIfAvailable() -> some View {
if #available(iOS 16.0, *) {
self
.scrollContentBackground(.hidden)
.background(Color.appGroupedBackground)
} else {
self
}
}
}
//struct ReportSelectRulesView_Previews: PreviewProvider { //struct ReportSelectRulesView_Previews: PreviewProvider {
// static var previews: some View { // static var previews: some View {
// ReportSelectRulesView() // ReportSelectRulesView()

View File

@ -32,7 +32,6 @@ struct ReportView: View {
if #available(iOS 16.0, *) { if #available(iOS 16.0, *) {
NavigationStack { NavigationStack {
navigationViewContent navigationViewContent
.scrollDismissesKeyboard(.interactively)
} }
} else { } else {
NavigationView { NavigationView {
@ -94,14 +93,12 @@ struct ReportView: View {
} header: { } header: {
Text("Reason") Text("Reason")
} }
.appGroupedListRowBackground()
Section { Section {
ComposeTextView(text: $report.comment, placeholder: Text("Add any additional comments")) ComposeTextView(text: $report.comment, placeholder: Text("Add any additional comments"))
.backgroundColor(.clear) .backgroundColor(.clear)
.listRowInsets(EdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8)) .listRowInsets(EdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8))
} }
.appGroupedListRowBackground()
Section { Section {
ForEach(report.statusIDs, id: \.self) { id in ForEach(report.statusIDs, id: \.self) { id in
@ -119,14 +116,12 @@ struct ReportView: View {
} footer: { } footer: {
Text("Attach posts to your report to provide additional context for moderators.") Text("Attach posts to your report to provide additional context for moderators.")
} }
.appGroupedListRowBackground()
Section { Section {
Toggle("Forward", isOn: $report.forward) Toggle("Forward", isOn: $report.forward)
} footer: { } footer: {
Text("You can choose to anonymously forward your report to the moderators of **\(account.url.host!)**.") Text("You can choose to anonymously forward your report to the moderators of **\(account.url.host!)**.")
} }
.appGroupedListRowBackground()
Button(action: self.sendReport) { Button(action: self.sendReport) {
if isReporting { if isReporting {
@ -139,10 +134,7 @@ struct ReportView: View {
} }
} }
.disabled(isReporting) .disabled(isReporting)
.appGroupedListRowBackground()
} }
.listStyle(.insetGrouped)
.appGroupedListBackground(container: UIHostingController<ReportView>.self, applyBackground: true)
.alertWithData("Error Reporting", data: $error, actions: { error in .alertWithData("Error Reporting", data: $error, actions: { error in
Button("OK") {} Button("OK") {}
}, message: { error in }, message: { error in

View File

@ -84,37 +84,25 @@ class SearchResultsViewController: EnhancedTableViewController {
tableView.register(UINib(nibName: "HashtagTableViewCell", bundle: .main), forCellReuseIdentifier: hashtagCell) tableView.register(UINib(nibName: "HashtagTableViewCell", bundle: .main), forCellReuseIdentifier: hashtagCell)
tableView.allowsFocus = true tableView.allowsFocus = true
tableView.backgroundColor = .appGroupedBackground
dataSource = DataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in dataSource = DataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in
let cell: UITableViewCell
switch item { switch item {
case let .account(id): case let .account(id):
let accountCell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as! AccountTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as! AccountTableViewCell
accountCell.delegate = self cell.delegate = self
accountCell.updateUI(accountID: id) cell.updateUI(accountID: id)
cell = accountCell return cell
case let .hashtag(tag): case let .hashtag(tag):
let hashtagCell = tableView.dequeueReusableCell(withIdentifier: hashtagCell, for: indexPath) as! HashtagTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: hashtagCell, for: indexPath) as! HashtagTableViewCell
hashtagCell.delegate = self cell.delegate = self
hashtagCell.updateUI(hashtag: tag) cell.updateUI(hashtag: tag)
cell = hashtagCell return cell
case let .status(id, state): case let .status(id, state):
let statusCell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as! TimelineStatusTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as! TimelineStatusTableViewCell
statusCell.delegate = self cell.delegate = self
statusCell.updateUI(statusID: id, state: state) cell.updateUI(statusID: id, state: state)
cell = statusCell return cell
} }
cell.configurationUpdateHandler = { cell, state in
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
cell.backgroundConfiguration = config
}
return cell
}) })
activityIndicator = UIActivityIndicatorView(style: .large) activityIndicator = UIActivityIndicatorView(style: .large)

View File

@ -86,30 +86,10 @@ class StatusActionAccountListCollectionViewController: UIViewController, Collect
let statusCell = UICollectionView.CellRegistration<TimelineStatusCollectionViewCell, (String, CollapseState)> { [unowned self] cell, indexPath, item in let statusCell = UICollectionView.CellRegistration<TimelineStatusCollectionViewCell, (String, CollapseState)> { [unowned self] cell, indexPath, item in
cell.delegate = self cell.delegate = self
cell.updateUI(statusID: item.0, state: item.1, filterResult: .allow, precomputedContent: nil) cell.updateUI(statusID: item.0, state: item.1, filterResult: .allow, precomputedContent: nil)
cell.configurationUpdateHandler = { cell, state in
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
cell.backgroundConfiguration = config
}
} }
let accountCell = UICollectionView.CellRegistration<AccountCollectionViewCell, String> { [unowned self] cell, indexPath, item in let accountCell = UICollectionView.CellRegistration<AccountCollectionViewCell, String> { [unowned self] cell, indexPath, item in
cell.delegate = self cell.delegate = self
cell.updateUI(accountID: item) cell.updateUI(accountID: item)
cell.configurationUpdateHandler = { cell, state in
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
cell.backgroundConfiguration = config
}
} }
let loadingCell = UICollectionView.CellRegistration<LoadingCollectionViewCell, Void> { cell, indexPath, item in let loadingCell = UICollectionView.CellRegistration<LoadingCollectionViewCell, Void> { cell, indexPath, item in
cell.indicator.startAnimating() cell.indicator.startAnimating()

View File

@ -88,7 +88,7 @@ class StatusActionAccountListViewController: UIViewController {
title = NSLocalizedString("Reblogged By", comment: "status reblogged by accounts list title") title = NSLocalizedString("Reblogged By", comment: "status reblogged by accounts list title")
} }
view.backgroundColor = .appBackground view.backgroundColor = .systemBackground
NotificationCenter.default.addObserver(self, selector: #selector(handleStatusDeleted), name: .statusDeleted, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleStatusDeleted), name: .statusDeleted, object: nil)
} }

View File

@ -102,7 +102,7 @@ class InstanceTimelineViewController: TimelineViewController {
} }
collectionView.isHidden = true collectionView.isHidden = true
view.backgroundColor = .appBackground view.backgroundColor = .systemBackground
let image = UIImageView(image: UIImage(systemName: "lock.fill")) let image = UIImageView(image: UIImage(systemName: "lock.fill"))
image.tintColor = .secondaryLabel image.tintColor = .secondaryLabel

View File

@ -19,7 +19,7 @@ class TimelineGapCollectionViewCell: UICollectionViewCell {
override var isHighlighted: Bool { override var isHighlighted: Bool {
didSet { didSet {
backgroundColor = isHighlighted ? .appFill : .appGroupedBackground backgroundColor = isHighlighted ? .systemFill : .systemGroupedBackground
} }
} }
@ -38,7 +38,7 @@ class TimelineGapCollectionViewCell: UICollectionViewCell {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
backgroundColor = .appGroupedBackground backgroundColor = .systemGroupedBackground
indicator.isHidden = true indicator.isHidden = true
indicator.color = .tintColor indicator.color = .tintColor

View File

@ -63,7 +63,6 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
super.viewDidLoad() super.viewDidLoad()
var config = UICollectionLayoutListConfiguration(appearance: .plain) var config = UICollectionLayoutListConfiguration(appearance: .plain)
config.backgroundColor = .appBackground
config.leadingSwipeActionsConfigurationProvider = { [unowned self] in config.leadingSwipeActionsConfigurationProvider = { [unowned self] in
(collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions() (collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions()
} }
@ -100,7 +99,6 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
collectionView.delegate = self collectionView.delegate = self
collectionView.dragDelegate = self collectionView.dragDelegate = self
collectionView.allowsFocus = true collectionView.allowsFocus = true
collectionView.backgroundColor = .appBackground
collectionView.translatesAutoresizingMaskIntoConstraints = false collectionView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(collectionView) view.addSubview(collectionView)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([

View File

@ -47,7 +47,7 @@ class CustomAlertController: UIViewController {
blurView = UIVisualEffectView(effect: UIBlurEffect(style: .systemChromeMaterial)) blurView = UIVisualEffectView(effect: UIBlurEffect(style: .systemChromeMaterial))
blurView.backgroundColor = .appBackground blurView.backgroundColor = .systemBackground
blurView.layer.cornerRadius = 15 blurView.layer.cornerRadius = 15
blurView.layer.cornerCurve = .continuous blurView.layer.cornerCurve = .continuous
blurView.layer.masksToBounds = true blurView.layer.masksToBounds = true

View File

@ -79,7 +79,7 @@ class SegmentedPageViewController<Page: SegmentedPageViewControllerPage>: UIView
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
view.backgroundColor = .appBackground view.backgroundColor = .systemBackground
selectPage(initialPage, animated: false) selectPage(initialPage, animated: false)

View File

@ -21,16 +21,6 @@ class AlbumTableViewCell: UITableViewCell {
thumbnailImageView.layer.cornerRadius = 0.05 * thumbnailImageView.bounds.width thumbnailImageView.layer.cornerRadius = 0.05 * thumbnailImageView.bounds.width
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
backgroundConfiguration = config
}
func updateUI(album: PHAssetCollection) { func updateUI(album: PHAssetCollection) {
albumTitleLabel.text = album.localizedTitle albumTitleLabel.text = album.localizedTitle

View File

@ -34,14 +34,4 @@ class AllPhotosTableViewCell: UITableViewCell {
} }
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
backgroundConfiguration = config
}
} }

View File

@ -324,7 +324,7 @@ extension ContentTextView: UIContextMenuInteractionDelegate {
// Create a dummy containerview for the snapshot view, since using a view with a CALayer mask and UIPreviewParameters(textLineRects:) // Create a dummy containerview for the snapshot view, since using a view with a CALayer mask and UIPreviewParameters(textLineRects:)
// causes the mask to be ignored. See FB7832297 // causes the mask to be ignored. See FB7832297
let snapshotContainer = UIView(frame: snapshot.bounds) let snapshotContainer = UIView(frame: snapshot.bounds)
snapshotContainer.backgroundColor = .appBackground snapshotContainer.backgroundColor = .systemBackground
snapshotContainer.addSubview(snapshot) snapshotContainer.addSubview(snapshot)
let preview = UITargetedPreview(view: snapshotContainer, parameters: parameters, target: target) let preview = UITargetedPreview(view: snapshotContainer, parameters: parameters, target: target)

View File

@ -18,6 +18,8 @@ class TrendingHashtagCollectionViewCell: UICollectionViewCell {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
backgroundColor = .systemBackground
hashtagLabel.font = .preferredFont(forTextStyle: .title2) hashtagLabel.font = .preferredFont(forTextStyle: .title2)
hashtagLabel.adjustsFontForContentSizeCategory = true hashtagLabel.adjustsFontForContentSizeCategory = true
peopleTodayLabel.font = .preferredFont(forTextStyle: .caption1) peopleTodayLabel.font = .preferredFont(forTextStyle: .caption1)
@ -58,16 +60,6 @@ class TrendingHashtagCollectionViewCell: UICollectionViewCell {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
backgroundConfiguration = config
}
func updateUI(hashtag: Hashtag) { func updateUI(hashtag: Hashtag) {
hashtagLabel.text = "#\(hashtag.name)" hashtagLabel.text = "#\(hashtag.name)"
historyView.setHistory(hashtag.history) historyView.setHistory(hashtag.history)

View File

@ -39,16 +39,6 @@ class InstanceTableViewCell: UITableViewCell {
descriptionTextView.adjustsFontForContentSizeCategory = true descriptionTextView.adjustsFontForContentSizeCategory = true
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listGroupedCell()
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
backgroundConfiguration = config
}
func updateUI(instance: InstanceSelector.Instance) { func updateUI(instance: InstanceSelector.Instance) {
self.selectorInstance = instance self.selectorInstance = instance
self.instance = nil self.instance = nil

View File

@ -14,8 +14,6 @@ class LoadingTableViewCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier) super.init(style: style, reuseIdentifier: reuseIdentifier)
backgroundColor = .appBackground
indicator.translatesAutoresizingMaskIntoConstraints = false indicator.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(indicator) contentView.addSubview(indicator)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([

View File

@ -48,16 +48,6 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil)
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
backgroundConfiguration = config
}
@objc func updateUIForPreferences() { @objc func updateUIForPreferences() {
for case let imageView as UIImageView in actionAvatarStackView.arrangedSubviews { for case let imageView as UIImageView in actionAvatarStackView.arrangedSubviews {
imageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: imageView) imageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: imageView)

View File

@ -43,16 +43,6 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil)
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
backgroundConfiguration = config
}
@objc func updateUIForPreferences() { @objc func updateUIForPreferences() {
for case let imageView as UIImageView in avatarStackView.arrangedSubviews { for case let imageView as UIImageView in avatarStackView.arrangedSubviews {
imageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: imageView) imageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: imageView)

View File

@ -49,16 +49,6 @@ class FollowRequestNotificationTableViewCell: UITableViewCell {
updateUIForPreferences() updateUIForPreferences()
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
backgroundConfiguration = config
}
@objc func updateUIForPreferences() { @objc func updateUIForPreferences() {
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * 30 avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * 30

View File

@ -38,16 +38,6 @@ class PollFinishedTableViewCell: UITableViewCell {
displayNameLabel.adjustsFontForContentSizeCategory = true displayNameLabel.adjustsFontForContentSizeCategory = true
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
backgroundConfiguration = config
}
func updateUI(notification: Pachyderm.Notification) { func updateUI(notification: Pachyderm.Notification) {
guard let statusID = notification.status?.id, guard let statusID = notification.status?.id,
let status = delegate?.apiController.persistentContainer.status(for: statusID), let status = delegate?.apiController.persistentContainer.status(for: statusID),

View File

@ -35,16 +35,6 @@ class StatusUpdatedNotificationTableViewCell: UITableViewCell {
displayNameLabel.adjustsFontForContentSizeCategory = true displayNameLabel.adjustsFontForContentSizeCategory = true
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
backgroundConfiguration = config
}
func updateUI(notification: Pachyderm.Notification) { func updateUI(notification: Pachyderm.Notification) {
guard notification.kind == .update, guard notification.kind == .update,
let status = notification.status else { let status = notification.status else {

View File

@ -14,8 +14,6 @@ class ProfileFieldsView: UIView {
weak var delegate: ProfileHeaderViewDelegate? weak var delegate: ProfileHeaderViewDelegate?
private var fields = [Account.Field]()
private let stack = UIStackView() private let stack = UIStackView()
private var fieldViews: [(EmojiLabel, ProfileFieldValueView)] = [] private var fieldViews: [(EmojiLabel, ProfileFieldValueView)] = []
private var fieldConstraints: [NSLayoutConstraint] = [] private var fieldConstraints: [NSLayoutConstraint] = []
@ -64,11 +62,9 @@ class ProfileFieldsView: UIView {
func updateUI(account: AccountMO) { func updateUI(account: AccountMO) {
isHidden = account.fields.isEmpty isHidden = account.fields.isEmpty
guard !account.fields.isEmpty, guard !account.fields.isEmpty else {
fields != account.fields else {
return return
} }
fields = account.fields
for (name, value) in fieldViews { for (name, value) in fieldViews {
name.removeFromSuperview() name.removeFromSuperview()
@ -187,7 +183,6 @@ private class ProfileFieldValueView: UIView {
super.init(frame: .zero) super.init(frame: .zero)
textView.isSelectable = false textView.isSelectable = false
textView.backgroundColor = .clear
textView.defaultFont = .preferredFont(forTextStyle: .body) textView.defaultFont = .preferredFont(forTextStyle: .body)
textView.monospaceFont = UIFontMetrics.default.scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular)) textView.monospaceFont = UIFontMetrics.default.scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular))
textView.adjustsFontForContentSizeCategory = true textView.adjustsFontForContentSizeCategory = true
@ -226,6 +221,7 @@ private class ProfileFieldValueView: UIView {
textView.topAnchor.constraint(equalTo: topAnchor), textView.topAnchor.constraint(equalTo: topAnchor),
textView.bottomAnchor.constraint(equalTo: bottomAnchor), textView.bottomAnchor.constraint(equalTo: bottomAnchor),
]) ])
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {

View File

@ -61,9 +61,6 @@ class ProfileHeaderView: UIView {
override func awakeFromNib() { override func awakeFromNib() {
super.awakeFromNib() super.awakeFromNib()
backgroundColor = .appBackground
avatarContainerView.backgroundColor = .appBackground
avatarContainerView.layer.masksToBounds = true avatarContainerView.layer.masksToBounds = true
avatarImageView.layer.masksToBounds = true avatarImageView.layer.masksToBounds = true
avatarImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(avatarPressed))) avatarImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(avatarPressed)))

View File

@ -79,6 +79,7 @@
</textView> </textView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vKC-m1-Sbs" customClass="ProfileFieldsView" customModule="Tusker" customModuleProvider="target"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vKC-m1-Sbs" customClass="ProfileFieldsView" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="0.0" y="263.5" width="398" height="128"/> <rect key="frame" x="0.0" y="263.5" width="398" height="128"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="128" placeholder="YES" id="xbR-M6-H0I"/> <constraint firstAttribute="height" constant="128" placeholder="YES" id="xbR-M6-H0I"/>
</constraints> </constraints>

View File

@ -317,12 +317,6 @@ class ConversationMainStatusCollectionViewCell: UICollectionViewListCell, Status
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
config.backgroundColor = .appBackground
backgroundConfiguration = config
}
// MARK: Configure UI // MARK: Configure UI
func updateUI(statusID: String, state: CollapseState) { func updateUI(statusID: String, state: CollapseState) {

View File

@ -351,16 +351,6 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
} }
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
backgroundConfiguration = config
}
// MARK: Accessibility // MARK: Accessibility
override var isAccessibilityElement: Bool { override var isAccessibilityElement: Bool {

View File

@ -93,16 +93,6 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
updateActionsVisibility() updateActionsVisibility()
} }
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appBackground
}
backgroundConfiguration = config
}
override func createObserversIfNecessary() { override func createObserversIfNecessary() {
super.createObserversIfNecessary() super.createObserversIfNecessary()

View File

@ -1,21 +0,0 @@
//
// TrendingStatusCollectionViewCell.swift
// Tusker
//
// Created by Shadowfacts on 2/2/23.
// Copyright © 2023 Shadowfacts. All rights reserved.
//
import UIKit
class TrendingStatusCollectionViewCell: TimelineStatusCollectionViewCell {
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
if state.isHighlighted || state.isSelected {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appGroupedCellBackground
}
backgroundConfiguration = config
}
}

View File

@ -16,7 +16,7 @@ class TrendHistoryView: UIView {
private let curveRadius: CGFloat = 10 private let curveRadius: CGFloat = 10
/// The base background color used for the graph fill. /// The base background color used for the graph fill.
var effectiveBackgroundColor = UIColor.appBackground var effectiveBackgroundColor = UIColor.systemBackground
override func layoutSubviews() { override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()