forked from shadowfacts/Tusker
More preferences reorganizing
This commit is contained in:
parent
c7a56a9f61
commit
4665df228d
|
@ -169,7 +169,6 @@
|
|||
D67C57AD21E265FC00C3118B /* LargeAccountDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D67C57AC21E265FC00C3118B /* LargeAccountDetailView.swift */; };
|
||||
D67C57AF21E28EAD00C3118B /* Array+Uniques.swift in Sources */ = {isa = PBXBuildFile; fileRef = D67C57AE21E28EAD00C3118B /* Array+Uniques.swift */; };
|
||||
D68015402401A6BA00D6103B /* ComposingPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D680153F2401A6BA00D6103B /* ComposingPrefsView.swift */; };
|
||||
D68015422401A74600D6103B /* MediaPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68015412401A74600D6103B /* MediaPrefsView.swift */; };
|
||||
D681E4D7246E32290053414F /* StatusActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D681E4D6246E32290053414F /* StatusActivityItemSource.swift */; };
|
||||
D681E4D9246E346E0053414F /* AccountActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D681E4D8246E346E0053414F /* AccountActivityItemSource.swift */; };
|
||||
D68232F72464F4FD00325FB8 /* ComposeDrawingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68232F62464F4FD00325FB8 /* ComposeDrawingViewController.swift */; };
|
||||
|
@ -592,7 +591,6 @@
|
|||
D67C57AC21E265FC00C3118B /* LargeAccountDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeAccountDetailView.swift; sourceTree = "<group>"; };
|
||||
D67C57AE21E28EAD00C3118B /* Array+Uniques.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Uniques.swift"; sourceTree = "<group>"; };
|
||||
D680153F2401A6BA00D6103B /* ComposingPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposingPrefsView.swift; sourceTree = "<group>"; };
|
||||
D68015412401A74600D6103B /* MediaPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPrefsView.swift; sourceTree = "<group>"; };
|
||||
D681E4D6246E32290053414F /* StatusActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusActivityItemSource.swift; sourceTree = "<group>"; };
|
||||
D681E4D8246E346E0053414F /* AccountActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountActivityItemSource.swift; sourceTree = "<group>"; };
|
||||
D68232F62464F4FD00325FB8 /* ComposeDrawingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeDrawingViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -1172,12 +1170,9 @@
|
|||
D63661BF2381C144004B9E16 /* PreferencesNavigationController.swift */,
|
||||
04586B4022B2FFB10021BD04 /* PreferencesView.swift */,
|
||||
D64B96802BC3279D002C8990 /* PrefsAccountView.swift */,
|
||||
D61F75892932E1FC00C0B37F /* SwipeActionsPrefsView.swift */,
|
||||
D6958F3C2AA383D90062FE52 /* WidescreenNavigationPrefsView.swift */,
|
||||
0427033722B30F5F000D31B6 /* BehaviorPrefsView.swift */,
|
||||
D6B17254254F88B800128392 /* OppositeCollapseKeywordsView.swift */,
|
||||
D680153F2401A6BA00D6103B /* ComposingPrefsView.swift */,
|
||||
D68015412401A74600D6103B /* MediaPrefsView.swift */,
|
||||
D6BC9DB2232D4C07002CA326 /* WellnessPrefsView.swift */,
|
||||
0427033922B31269000D31B6 /* AdvancedPrefsView.swift */,
|
||||
D67895BF246870DE00D4CD9E /* LocalAccountAvatarView.swift */,
|
||||
|
@ -1492,6 +1487,8 @@
|
|||
children = (
|
||||
D6C4532C2BCB86AC00E26A0E /* AppearancePrefsView.swift */,
|
||||
D6C4532E2BCB873400E26A0E /* MockStatusView.swift */,
|
||||
D6958F3C2AA383D90062FE52 /* WidescreenNavigationPrefsView.swift */,
|
||||
D61F75892932E1FC00C0B37F /* SwipeActionsPrefsView.swift */,
|
||||
);
|
||||
path = Appearance;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2348,7 +2345,6 @@
|
|||
D61AC1D5232E9FA600C54D2D /* InstanceSelectorTableViewController.swift in Sources */,
|
||||
D6CF5B892AC9BA6E00F15D83 /* MastodonSearchController.swift in Sources */,
|
||||
D681E4D9246E346E0053414F /* AccountActivityItemSource.swift in Sources */,
|
||||
D68015422401A74600D6103B /* MediaPrefsView.swift in Sources */,
|
||||
D6093F9B25BDD4B9004811E6 /* HashtagSearchResultsViewController.swift in Sources */,
|
||||
D6E77D09286D25FA00D8B732 /* TrendingHashtagCollectionViewCell.swift in Sources */,
|
||||
D6D79F292A0D596B00AB2315 /* StatusEditHistoryViewController.swift in Sources */,
|
||||
|
|
|
@ -7,18 +7,49 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
import TuskerPreferences
|
||||
|
||||
struct AppearancePrefsView: View {
|
||||
@ObservedObject private var preferences = Preferences.shared
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
private var appearanceChangePublisher: some Publisher<Void, Never> {
|
||||
preferences.$theme
|
||||
.map { _ in () }
|
||||
.merge(with: preferences.$pureBlackDarkMode.map { _ in () },
|
||||
preferences.$accentColor.map { _ in () }
|
||||
)
|
||||
// the prefrence publishers are all willSet, but want to notify after the change, so wait one runloop iteration
|
||||
.receive(on: DispatchQueue.main)
|
||||
}
|
||||
|
||||
private static let accentColorsAndImages: [(AccentColor, UIImage?)] = AccentColor.allCases.map { color in
|
||||
var image: UIImage?
|
||||
if let color = color.color {
|
||||
if #available(iOS 16.0, *) {
|
||||
image = UIImage(systemName: "circle.fill")!.withTintColor(color, renderingMode: .alwaysTemplate).withRenderingMode(.alwaysOriginal)
|
||||
} else {
|
||||
image = UIGraphicsImageRenderer(size: CGSize(width: 20, height: 20)).image { context in
|
||||
color.setFill()
|
||||
context.cgContext.fillEllipse(in: CGRect(x: 0, y: 0, width: 20, height: 20))
|
||||
}
|
||||
}
|
||||
}
|
||||
return (color, image)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
themeSection
|
||||
interfaceSection
|
||||
|
||||
Section("Post Preview") {
|
||||
MockStatusView()
|
||||
.padding(.top, 8)
|
||||
.padding(.horizontal, UIDevice.current.userInterfaceIdiom == .pad ? 8 : 4)
|
||||
}
|
||||
.appGroupedListRowBackground()
|
||||
.listRowBackground(preferences.pureBlackDarkMode ? colorScheme == .dark ? Color.black : Color.white : Color.appBackground)
|
||||
|
||||
accountsSection
|
||||
postsSection
|
||||
|
@ -29,6 +60,53 @@ struct AppearancePrefsView: View {
|
|||
.navigationTitle("Appearance")
|
||||
}
|
||||
|
||||
private var themeSection: some View {
|
||||
Section {
|
||||
#if !os(visionOS)
|
||||
Picker(selection: $preferences.theme, label: Text("Theme")) {
|
||||
Text("Use System Theme").tag(Theme.unspecified)
|
||||
Text("Light").tag(Theme.light)
|
||||
Text("Dark").tag(Theme.dark)
|
||||
}
|
||||
|
||||
// macOS system dark mode isn't pure black, so this isn't necessary
|
||||
if !ProcessInfo.processInfo.isMacCatalystApp && !ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
Toggle(isOn: $preferences.pureBlackDarkMode) {
|
||||
Text("Pure Black Dark Mode")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Picker(selection: $preferences.accentColor, label: Text("Accent Color")) {
|
||||
ForEach(Self.accentColorsAndImages, id: \.0.rawValue) { (color, image) in
|
||||
HStack {
|
||||
Text(color.name)
|
||||
if let image {
|
||||
Spacer()
|
||||
Image(uiImage: image)
|
||||
}
|
||||
}
|
||||
.tag(color)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onReceive(appearanceChangePublisher) { _ in
|
||||
NotificationCenter.default.post(name: .themePreferenceChanged, object: nil)
|
||||
}
|
||||
.appGroupedListRowBackground()
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var interfaceSection: some View {
|
||||
let visionIdiom = UIUserInterfaceIdiom(rawValue: 6)
|
||||
if [visionIdiom, .pad, .mac].contains(UIDevice.current.userInterfaceIdiom) {
|
||||
Section(header: Text("Interface")) {
|
||||
WidescreenNavigationPrefsView()
|
||||
}
|
||||
.appGroupedListRowBackground()
|
||||
}
|
||||
}
|
||||
|
||||
private var accountsSection: some View {
|
||||
Section("Accounts") {
|
||||
Toggle(isOn: Binding(get: {
|
||||
|
@ -65,15 +143,16 @@ struct AppearancePrefsView: View {
|
|||
Toggle(isOn: $preferences.underlineTextLinks) {
|
||||
Text("Underline Links")
|
||||
}
|
||||
// NavigationLink("Leading Swipe Actions") {
|
||||
// SwipeActionsPrefsView(selection: $preferences.leadingStatusSwipeActions)
|
||||
// .edgesIgnoringSafeArea(.all)
|
||||
// .navigationTitle("Leading Swipe Actions")
|
||||
// }
|
||||
// NavigationLink("Trailing Swipe Actions") {
|
||||
// SwipeActionsPrefsView(selection: $preferences.trailingStatusSwipeActions)
|
||||
// .edgesIgnoringSafeArea(.all)
|
||||
// .navigationTitle("Trailing Swipe Actions")
|
||||
NavigationLink("Leading Swipe Actions") {
|
||||
SwipeActionsPrefsView(selection: $preferences.leadingStatusSwipeActions)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.navigationTitle("Leading Swipe Actions")
|
||||
}
|
||||
NavigationLink("Trailing Swipe Actions") {
|
||||
SwipeActionsPrefsView(selection: $preferences.trailingStatusSwipeActions)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.navigationTitle("Trailing Swipe Actions")
|
||||
}
|
||||
}
|
||||
.appGroupedListRowBackground()
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ private actor MockAttachmentsGenerator {
|
|||
return attachmentURLs
|
||||
}
|
||||
|
||||
let size = CGSize(width: 100, height: 100)
|
||||
let size = CGSize(width: 200, height: 200)
|
||||
let bounds = CGRect(origin: .zero, size: size)
|
||||
let format = UIGraphicsImageRendererFormat()
|
||||
format.scale = displayScale
|
||||
|
@ -171,24 +171,24 @@ private actor MockAttachmentsGenerator {
|
|||
UIColor(red: 0x56 / 255, green: 0x03 / 255, blue: 0xad / 255, alpha: 1).setFill()
|
||||
ctx.fill(bounds)
|
||||
ctx.cgContext.concatenate(CGAffineTransform(1, 0, -0.5, 1, 0, 0))
|
||||
for minX in stride(from: 0, through: 100, by: 30) {
|
||||
for x in 0..<9 {
|
||||
UIColor(red: 0x83 / 255, green: 0x67 / 255, blue: 0xc7 / 255, alpha: 1).setFill()
|
||||
ctx.fill(CGRect(x: minX + 20, y: 0, width: 15, height: 100))
|
||||
ctx.fill(CGRect(x: CGFloat(x) * 30 + 20, y: 0, width: 15, height: bounds.height))
|
||||
}
|
||||
}
|
||||
let secondImage = renderer.image { ctx in
|
||||
UIColor(red: 0x00 / 255, green: 0x43 / 255, blue: 0x85 / 255, alpha: 1).setFill()
|
||||
ctx.fill(bounds)
|
||||
UIColor(red: 0x05 / 255, green: 0xb2 / 255, blue: 0xdc / 255, alpha: 1).setFill()
|
||||
for y in 0..<2 {
|
||||
for x in 0..<4 {
|
||||
for y in 0..<4 {
|
||||
for x in 0..<5 {
|
||||
let rect = CGRect(x: x * 45 - 5, y: y * 50 + 15, width: 20, height: 20)
|
||||
ctx.cgContext.fillEllipse(in: rect)
|
||||
}
|
||||
}
|
||||
UIColor(red: 0x08 / 255, green: 0x7c / 255, blue: 0xa7 / 255, alpha: 1).setFill()
|
||||
for y in 0..<3 {
|
||||
for x in 0..<2 {
|
||||
for y in 0..<5 {
|
||||
for x in 0..<4 {
|
||||
let rect = CGRect(x: CGFloat(x) * 45 + 22.5, y: CGFloat(y) * 50 - 5, width: 10, height: 10)
|
||||
ctx.cgContext.fillEllipse(in: rect)
|
||||
}
|
||||
|
|
|
@ -12,26 +12,32 @@ import TuskerPreferences
|
|||
|
||||
struct WidescreenNavigationPrefsView: View {
|
||||
@ObservedObject private var preferences = Preferences.shared
|
||||
@State private var startAnimation = PassthroughSubject<Void, Never>()
|
||||
@State private var startAnimation = CurrentValueSubject<Bool, Never>(false)
|
||||
|
||||
private var startAnimationSignal: some Publisher<Void, Never> {
|
||||
startAnimation.filter { $0 }.removeDuplicates().map { _ in () }
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Spacer()
|
||||
|
||||
OptionView<StackNavigationPreview>(
|
||||
OptionView(
|
||||
content: StackNavigationPreview.self,
|
||||
value: .stack,
|
||||
selection: $preferences.widescreenNavigationMode,
|
||||
startAnimation: startAnimation
|
||||
startAnimation: startAnimationSignal
|
||||
) {
|
||||
Text("Stack")
|
||||
}
|
||||
|
||||
Spacer(minLength: 32)
|
||||
|
||||
OptionView<SplitNavigationPreview>(
|
||||
OptionView(
|
||||
content: SplitNavigationPreview.self,
|
||||
value: .splitScreen,
|
||||
selection: $preferences.widescreenNavigationMode,
|
||||
startAnimation: startAnimation
|
||||
startAnimation: startAnimationSignal
|
||||
) {
|
||||
Text("Split Screen")
|
||||
}
|
||||
|
@ -39,10 +45,11 @@ struct WidescreenNavigationPrefsView: View {
|
|||
if preferences.hasFeatureFlag(.iPadMultiColumn) {
|
||||
Spacer(minLength: 32)
|
||||
|
||||
OptionView<MultiColumnNavigationPreview>(
|
||||
OptionView(
|
||||
content: MultiColumnNavigationPreview.self,
|
||||
value: .multiColumn,
|
||||
selection: $preferences.widescreenNavigationMode,
|
||||
startAnimation: startAnimation
|
||||
startAnimation: startAnimationSignal
|
||||
) {
|
||||
Text("Multi-Column")
|
||||
}
|
||||
|
@ -53,19 +60,26 @@ struct WidescreenNavigationPrefsView: View {
|
|||
.frame(height: 100)
|
||||
.onAppear {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
|
||||
startAnimation.send()
|
||||
startAnimation.send(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct OptionView<Content: NavigationModePreview>: View {
|
||||
private struct OptionView<Content: NavigationModePreview, P: Publisher<Void, Never>>: View {
|
||||
let value: WidescreenNavigationMode
|
||||
@Binding var selection: WidescreenNavigationMode
|
||||
let startAnimation: PassthroughSubject<Void, Never>
|
||||
@ViewBuilder let label: Text
|
||||
let startAnimation: P
|
||||
let label: Text
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
init(content _: Content.Type, value: WidescreenNavigationMode, selection: Binding<WidescreenNavigationMode>, startAnimation: P, @ViewBuilder label: () -> Text) {
|
||||
self.value = value
|
||||
self._selection = selection
|
||||
self.startAnimation = startAnimation
|
||||
self.label = label()
|
||||
}
|
||||
|
||||
private var selected: Bool {
|
||||
selection == value
|
||||
}
|
||||
|
@ -84,7 +98,7 @@ private struct OptionView<Content: NavigationModePreview>: View {
|
|||
}
|
||||
|
||||
private var preview: some View {
|
||||
NavigationModeRepresentable<Content>(startAnimation: startAnimation)
|
||||
NavigationModeRepresentable(content: Content.self, startAnimation: startAnimation)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 12.5, style: .continuous))
|
||||
.overlay {
|
||||
RoundedRectangle(cornerRadius: 12.5, style: .continuous)
|
||||
|
@ -106,11 +120,15 @@ private struct WideCapsule: Shape {
|
|||
|
||||
@MainActor
|
||||
private protocol NavigationModePreview: UIView {
|
||||
init(startAnimation: PassthroughSubject<Void, Never>)
|
||||
init(startAnimation: some Publisher<Void, Never>)
|
||||
}
|
||||
|
||||
private struct NavigationModeRepresentable<UIViewType: NavigationModePreview>: UIViewRepresentable {
|
||||
let startAnimation: PassthroughSubject<Void, Never>
|
||||
private struct NavigationModeRepresentable<UIViewType: NavigationModePreview, P: Publisher<Void, Never>>: UIViewRepresentable {
|
||||
let startAnimation: P
|
||||
|
||||
init(content _: UIViewType.Type, startAnimation: P) {
|
||||
self.startAnimation = startAnimation
|
||||
}
|
||||
|
||||
func makeUIView(context: Context) -> UIViewType {
|
||||
UIViewType(startAnimation: startAnimation)
|
||||
|
@ -128,7 +146,7 @@ private final class StackNavigationPreview: UIView, NavigationModePreview {
|
|||
private let destinationView = UIView()
|
||||
private var cancellable: AnyCancellable?
|
||||
|
||||
init(startAnimation: PassthroughSubject<Void, Never>) {
|
||||
init(startAnimation: some Publisher<Void, Never>) {
|
||||
super.init(frame: .zero)
|
||||
|
||||
backgroundColor = .appBackground
|
||||
|
@ -203,7 +221,7 @@ private final class SplitNavigationPreview: UIView, NavigationModePreview {
|
|||
private var cellStackTrailingConstraint: NSLayoutConstraint!
|
||||
private var cancellable: AnyCancellable?
|
||||
|
||||
init(startAnimation: PassthroughSubject<Void, Never>) {
|
||||
init(startAnimation: some Publisher<Void, Never>) {
|
||||
super.init(frame: .zero)
|
||||
|
||||
backgroundColor = .appBackground
|
||||
|
@ -297,7 +315,7 @@ private final class MultiColumnNavigationPreview: UIView, NavigationModePreview
|
|||
|
||||
private var startedAnimation = false
|
||||
|
||||
init(startAnimation: PassthroughSubject<Void, Never>) {
|
||||
init(startAnimation: some Publisher<Void, Never>) {
|
||||
super.init(frame: .zero)
|
||||
|
||||
backgroundColor = .appSecondaryBackground
|
|
@ -1,64 +0,0 @@
|
|||
//
|
||||
// MediaPrefsView.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 2/22/20.
|
||||
// Copyright © 2020 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import TuskerPreferences
|
||||
|
||||
struct MediaPrefsView: View {
|
||||
@ObservedObject var preferences = Preferences.shared
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
viewingSection
|
||||
}
|
||||
.listStyle(.insetGrouped)
|
||||
.appGroupedListBackground(container: PreferencesNavigationController.self)
|
||||
.navigationBarTitle("Media")
|
||||
}
|
||||
|
||||
var viewingSection: some View {
|
||||
Section(header: Text("Viewing")) {
|
||||
Picker(selection: $preferences.attachmentBlurMode) {
|
||||
ForEach(AttachmentBlurMode.allCases, id: \.self) { mode in
|
||||
Text(mode.displayName).tag(mode)
|
||||
}
|
||||
} label: {
|
||||
Text("Blur Media")
|
||||
}
|
||||
|
||||
Toggle(isOn: $preferences.blurMediaBehindContentWarning) {
|
||||
Text("Blur Media Behind Content Warning")
|
||||
}
|
||||
.disabled(preferences.attachmentBlurMode != .useStatusSetting)
|
||||
|
||||
Toggle(isOn: $preferences.automaticallyPlayGifs) {
|
||||
Text("Automatically Play GIFs")
|
||||
}
|
||||
|
||||
Toggle(isOn: $preferences.showUncroppedMediaInline) {
|
||||
Text("Show Uncropped Media Inline")
|
||||
}
|
||||
|
||||
Toggle(isOn: $preferences.showAttachmentBadges) {
|
||||
Text("Show GIF/\(Text("Alt").font(.body.lowercaseSmallCaps())) Badges")
|
||||
}
|
||||
|
||||
Toggle(isOn: $preferences.attachmentAltBadgeInverted) {
|
||||
Text("Show Badge when Missing \(Text("Alt").font(.body.lowercaseSmallCaps()))")
|
||||
}
|
||||
.disabled(!preferences.showAttachmentBadges)
|
||||
}
|
||||
.appGroupedListRowBackground()
|
||||
}
|
||||
}
|
||||
|
||||
struct MediaPrefsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
MediaPrefsView()
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@ struct PreferencesView: View {
|
|||
var body: some View {
|
||||
List {
|
||||
accountsSection
|
||||
notificationsSection
|
||||
preferencesSection
|
||||
aboutSection
|
||||
}
|
||||
|
@ -92,31 +91,22 @@ struct PreferencesView: View {
|
|||
.appGroupedListRowBackground()
|
||||
}
|
||||
|
||||
private var notificationsSection: some View {
|
||||
Section {
|
||||
NavigationLink(isActive: $navigationState.showNotificationPreferences) {
|
||||
NotificationsPrefsView()
|
||||
} label: {
|
||||
Text("Notifications")
|
||||
}
|
||||
}
|
||||
.appGroupedListRowBackground()
|
||||
}
|
||||
|
||||
private var preferencesSection: some View {
|
||||
Section {
|
||||
NavigationLink(destination: AppearancePrefsView()) {
|
||||
Text("Appearance")
|
||||
}
|
||||
NavigationLink(destination: ComposingPrefsView()) {
|
||||
Text("Composing")
|
||||
}
|
||||
NavigationLink(destination: MediaPrefsView()) {
|
||||
Text("Media")
|
||||
}
|
||||
NavigationLink(destination: BehaviorPrefsView()) {
|
||||
Text("Behavior")
|
||||
}
|
||||
NavigationLink(isActive: $navigationState.showNotificationPreferences) {
|
||||
NotificationsPrefsView()
|
||||
} label: {
|
||||
Text("Notifications")
|
||||
}
|
||||
NavigationLink(destination: ComposingPrefsView()) {
|
||||
Text("Composing")
|
||||
}
|
||||
NavigationLink(destination: WellnessPrefsView()) {
|
||||
Text("Digital Wellness")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue