Swift format

This commit is contained in:
Thomas Ricouard 2023-01-30 07:27:06 +01:00
parent 5871d13eee
commit 16636b12a9
26 changed files with 191 additions and 187 deletions

View file

@ -12,9 +12,9 @@ import Timeline
@main @main
struct IceCubesApp: App { struct IceCubesApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate @UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@StateObject private var appAccountsManager = AppAccountsManager.shared @StateObject private var appAccountsManager = AppAccountsManager.shared
@StateObject private var currentInstance = CurrentInstance.shared @StateObject private var currentInstance = CurrentInstance.shared
@StateObject private var currentAccount = CurrentAccount.shared @StateObject private var currentAccount = CurrentAccount.shared
@ -23,18 +23,18 @@ struct IceCubesApp: App {
@StateObject private var quickLook = QuickLook() @StateObject private var quickLook = QuickLook()
@StateObject private var theme = Theme.shared @StateObject private var theme = Theme.shared
@StateObject private var sidebarRouterPath = RouterPath() @StateObject private var sidebarRouterPath = RouterPath()
@State private var selectedTab: Tab = .timeline @State private var selectedTab: Tab = .timeline
@State private var selectSidebarItem: Tab? = .timeline @State private var selectSidebarItem: Tab? = .timeline
@State private var popToRootTab: Tab = .other @State private var popToRootTab: Tab = .other
@State private var sideBarLoadedTabs: Set<Tab> = Set() @State private var sideBarLoadedTabs: Set<Tab> = Set()
private let feedbackGenerator = UISelectionFeedbackGenerator() private let feedbackGenerator = UISelectionFeedbackGenerator()
private var availableTabs: [Tab] { private var availableTabs: [Tab] {
appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab() appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab()
} }
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
appView appView
@ -72,7 +72,7 @@ struct IceCubesApp: App {
} }
} }
} }
@ViewBuilder @ViewBuilder
private var appView: some View { private var appView: some View {
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac { if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
@ -81,14 +81,14 @@ struct IceCubesApp: App {
tabBarView tabBarView
} }
} }
private func badgeFor(tab: Tab) -> Int { private func badgeFor(tab: Tab) -> Int {
if tab == .notifications && selectedTab != tab { if tab == .notifications && selectedTab != tab {
return watcher.unreadNotificationsCount + userPreferences.pushNotificationsCount return watcher.unreadNotificationsCount + userPreferences.pushNotificationsCount
} }
return 0 return 0
} }
private var sidebarView: some View { private var sidebarView: some View {
SideBarView(selectedTab: $selectedTab, SideBarView(selectedTab: $selectedTab,
popToRootTab: $popToRootTab, popToRootTab: $popToRootTab,
@ -116,7 +116,8 @@ struct IceCubesApp: App {
} }
} }
if proxy.frame(in: .global).width > (.maxColumnWidth + .secondaryColumnWidth), if proxy.frame(in: .global).width > (.maxColumnWidth + .secondaryColumnWidth),
currentAccount.account?.id != nil { currentAccount.account?.id != nil
{
Divider().edgesIgnoringSafeArea(.all) Divider().edgesIgnoringSafeArea(.all)
NotificationsTab(popToRootTab: $popToRootTab, lockedType: nil) NotificationsTab(popToRootTab: $popToRootTab, lockedType: nil)
.environment(\.isSecondaryColumn, true) .environment(\.isSecondaryColumn, true)
@ -128,7 +129,7 @@ struct IceCubesApp: App {
sideBarLoadedTabs.removeAll() sideBarLoadedTabs.removeAll()
} }
} }
private var tabBarView: some View { private var tabBarView: some View {
TabView(selection: .init(get: { TabView(selection: .init(get: {
selectedTab selectedTab
@ -154,14 +155,14 @@ struct IceCubesApp: App {
} }
} }
} }
private func setNewClientsInEnv(client: Client) { private func setNewClientsInEnv(client: Client) {
currentAccount.setClient(client: client) currentAccount.setClient(client: client)
currentInstance.setClient(client: client) currentInstance.setClient(client: client)
userPreferences.setClient(client: client) userPreferences.setClient(client: client)
watcher.setClient(client: client) watcher.setClient(client: client)
} }
private func handleScenePhase(scenePhase: ScenePhase) { private func handleScenePhase(scenePhase: ScenePhase) {
switch scenePhase { switch scenePhase {
case .background: case .background:
@ -178,16 +179,16 @@ struct IceCubesApp: App {
break break
} }
} }
private func setupRevenueCat() { private func setupRevenueCat() {
Purchases.logLevel = .error Purchases.logLevel = .error
Purchases.configure(withAPIKey: "appl_JXmiRckOzXXTsHKitQiicXCvMQi") Purchases.configure(withAPIKey: "appl_JXmiRckOzXXTsHKitQiicXCvMQi")
} }
private func refreshPushSubs() { private func refreshPushSubs() {
PushNotificationsService.shared.requestPushNotifications() PushNotificationsService.shared.requestPushNotifications()
} }
@CommandsBuilder @CommandsBuilder
private var appMenu: some Commands { private var appMenu: some Commands {
CommandGroup(replacing: .newItem) { CommandGroup(replacing: .newItem) {
@ -214,14 +215,14 @@ struct IceCubesApp: App {
class AppDelegate: NSObject, UIApplicationDelegate { class AppDelegate: NSObject, UIApplicationDelegate {
let themeObserver = ThemeObserverViewController(nibName: nil, bundle: nil) let themeObserver = ThemeObserverViewController(nibName: nil, bundle: nil)
func application(_: UIApplication, func application(_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool
{ {
try? AVAudioSession.sharedInstance().setCategory(.ambient, options: .mixWithOthers) try? AVAudioSession.sharedInstance().setCategory(.ambient, options: .mixWithOthers)
return true return true
} }
func application(_: UIApplication, func application(_: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{ {
@ -231,9 +232,9 @@ class AppDelegate: NSObject, UIApplicationDelegate {
await PushNotificationsService.shared.updateSubscriptions(forceCreate: false) await PushNotificationsService.shared.updateSubscriptions(forceCreate: false)
} }
} }
func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError _: Error) {} func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError _: Error) {}
func application(_: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options _: UIScene.ConnectionOptions) -> UISceneConfiguration { func application(_: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options _: UIScene.ConnectionOptions) -> UISceneConfiguration {
let configuration = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role) let configuration = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
if connectingSceneSession.role == .windowApplication { if connectingSceneSession.role == .windowApplication {
@ -246,7 +247,7 @@ class AppDelegate: NSObject, UIApplicationDelegate {
class ThemeObserverViewController: UIViewController { class ThemeObserverViewController: UIViewController {
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection) super.traitCollectionDidChange(previousTraitCollection)
print(traitCollection.userInterfaceStyle.rawValue) print(traitCollection.userInterfaceStyle.rawValue)
} }
} }

View file

@ -12,7 +12,7 @@ struct QuickLookPreview: UIViewControllerRepresentable {
let selectedURL: URL let selectedURL: URL
let urls: [URL] let urls: [URL]
func makeUIViewController(context: Context) -> UIViewController { func makeUIViewController(context _: Context) -> UIViewController {
return AppQLPreviewController(selectedURL: selectedURL, urls: urls) return AppQLPreviewController(selectedURL: selectedURL, urls: urls)
} }
@ -24,65 +24,65 @@ struct QuickLookPreview: UIViewControllerRepresentable {
class AppQLPreviewController: UIViewController { class AppQLPreviewController: UIViewController {
let selectedURL: URL let selectedURL: URL
let urls: [URL] let urls: [URL]
var qlController : QLPreviewController? var qlController: QLPreviewController?
init(selectedURL: URL, urls: [URL]) { init(selectedURL: URL, urls: [URL]) {
self.selectedURL = selectedURL self.selectedURL = selectedURL
self.urls = urls self.urls = urls
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
} }
required init?(coder: NSCoder) { @available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
if self.qlController == nil { if qlController == nil {
self.qlController = QLPreviewController() qlController = QLPreviewController()
self.qlController?.dataSource = self qlController?.dataSource = self
self.qlController?.delegate = self qlController?.delegate = self
self.qlController?.currentPreviewItemIndex = urls.firstIndex(of: selectedURL) ?? 0 qlController?.currentPreviewItemIndex = urls.firstIndex(of: selectedURL) ?? 0
self.present(self.qlController!, animated: true) present(qlController!, animated: true)
} }
} }
} }
extension AppQLPreviewController : QLPreviewControllerDataSource { extension AppQLPreviewController: QLPreviewControllerDataSource {
func numberOfPreviewItems(in _: QLPreviewController) -> Int { func numberOfPreviewItems(in _: QLPreviewController) -> Int {
return self.urls.count return urls.count
} }
func previewController(_: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem { func previewController(_: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
return self.urls[index] as QLPreviewItem return urls[index] as QLPreviewItem
} }
} }
extension AppQLPreviewController : QLPreviewControllerDelegate { extension AppQLPreviewController: QLPreviewControllerDelegate {
func previewController(_: QLPreviewController, editingModeFor _: QLPreviewItem) -> QLPreviewItemEditingMode { func previewController(_: QLPreviewController, editingModeFor _: QLPreviewItem) -> QLPreviewItemEditingMode {
.createCopy .createCopy
} }
func previewControllerWillDismiss(_ controller: QLPreviewController) { func previewControllerWillDismiss(_: QLPreviewController) {
self.dismiss(animated: true) dismiss(animated: true)
} }
} }
struct TransparentBackground: UIViewControllerRepresentable { struct TransparentBackground: UIViewControllerRepresentable {
public func makeUIViewController(context: Context) -> UIViewController { public func makeUIViewController(context _: Context) -> UIViewController {
return TransparentController() return TransparentController()
} }
public func updateUIViewController(_ uiViewController: UIViewController, context: Context) { public func updateUIViewController(_: UIViewController, context _: Context) {}
}
class TransparentController: UIViewController { class TransparentController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
view.backgroundColor = .clear view.backgroundColor = .clear
} }
override func willMove(toParent parent: UIViewController?) { override func willMove(toParent parent: UIViewController?) {
super.willMove(toParent: parent) super.willMove(toParent: parent)
parent?.view?.backgroundColor = .clear parent?.view?.backgroundColor = .clear

View file

@ -9,7 +9,7 @@ import Timeline
struct NotificationsTab: View { struct NotificationsTab: View {
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool @Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var watcher: StreamWatcher @EnvironmentObject private var watcher: StreamWatcher

View file

@ -5,13 +5,13 @@ import Status
import SwiftUI import SwiftUI
struct DisplaySettingsView: View { struct DisplaySettingsView: View {
typealias FontState = Theme.FontState typealias FontState = Theme.FontState
@Environment(\.colorScheme) private var colorScheme @Environment(\.colorScheme) private var colorScheme
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@EnvironmentObject private var userPreferences: UserPreferences @EnvironmentObject private var userPreferences: UserPreferences
@State private var isFontSelectorPresented = false @State private var isFontSelectorPresented = false
var body: some View { var body: some View {
Form { Form {
@ -35,21 +35,21 @@ struct DisplaySettingsView: View {
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
Section("settings.display.section.display") { Section("settings.display.section.display") {
Picker("settings.display.font", selection: .init(get: { Picker("settings.display.font", selection: .init(get: {
userPreferences.chosenFontData != nil ? FontState.custom : FontState.system userPreferences.chosenFontData != nil ? FontState.custom : FontState.system
}, set: { newValue in }, set: { newValue in
switch newValue { switch newValue {
case .system: case .system:
userPreferences.chosenFont = nil userPreferences.chosenFont = nil
case .custom: case .custom:
isFontSelectorPresented = true isFontSelectorPresented = true
}
})) {
ForEach(FontState.allCases, id: \.rawValue) { fontState in
Text(fontState.title).tag(fontState)
}
} }
.navigationDestination(isPresented: $isFontSelectorPresented, destination: { FontPicker() }) })) {
ForEach(FontState.allCases, id: \.rawValue) { fontState in
Text(fontState.title).tag(fontState)
}
}
.navigationDestination(isPresented: $isFontSelectorPresented, destination: { FontPicker() })
Picker("settings.display.avatar.position", selection: $theme.avatarPosition) { Picker("settings.display.avatar.position", selection: $theme.avatarPosition) {
ForEach(Theme.AvatarPosition.allCases, id: \.rawValue) { position in ForEach(Theme.AvatarPosition.allCases, id: \.rawValue) { position in
Text(position.description).tag(position) Text(position.description).tag(position)

View file

@ -20,13 +20,13 @@ struct IconSelectorView: View {
case alt9, alt10, alt11, alt12, alt13, alt14 case alt9, alt10, alt11, alt12, alt13, alt14
case alt15, alt16, alt17, alt18, alt19, alt20, alt21 case alt15, alt16, alt17, alt18, alt19, alt20, alt21
case alt22, alt23, alt24 case alt22, alt23, alt24
static var officialIcons: [Icon] { static var officialIcons: [Icon] {
[.primary, .alt1, .alt2, .alt3, .alt4, .alt5, .alt6, .alt7, .alt8, [.primary, .alt1, .alt2, .alt3, .alt4, .alt5, .alt6, .alt7, .alt8,
.alt9, .alt10, .alt11, .alt12, .alt13, .alt14, .alt9, .alt10, .alt11, .alt12, .alt13, .alt14,
.alt15, .alt16, .alt17, .alt18, .alt19] .alt15, .alt16, .alt17, .alt18, .alt19]
} }
static var albertKinngIcons: [Icon] { static var albertKinngIcons: [Icon] {
[.alt20, .alt21, .alt22, .alt23, .alt24] [.alt20, .alt21, .alt22, .alt23, .alt24]
} }
@ -59,7 +59,7 @@ struct IconSelectorView: View {
Text("Official icons") Text("Official icons")
.font(.scaledHeadline) .font(.scaledHeadline)
} }
Section { Section {
makeIconGridView(icons: Icon.albertKinngIcons) makeIconGridView(icons: Icon.albertKinngIcons)
} header: { } header: {
@ -72,7 +72,7 @@ struct IconSelectorView: View {
} }
.background(theme.primaryBackgroundColor) .background(theme.primaryBackgroundColor)
} }
private func makeIconGridView(icons: [Icon]) -> some View { private func makeIconGridView(icons: [Icon]) -> some View {
LazyVGrid(columns: columns, spacing: 6) { LazyVGrid(columns: columns, spacing: 6) {
ForEach(icons) { icon in ForEach(icons) { icon in

View file

@ -37,14 +37,14 @@ class ShareViewController: UIViewController {
childView.view.frame = self.view.bounds childView.view.frame = self.view.bounds
self.view.addSubview(childView.view) self.view.addSubview(childView.view)
childView.didMove(toParent: self) childView.didMove(toParent: self)
childView.view.translatesAutoresizingMaskIntoConstraints = false childView.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
childView.view.topAnchor.constraint(equalTo: self.view.topAnchor), childView.view.topAnchor.constraint(equalTo: self.view.topAnchor),
childView.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), childView.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
childView.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), childView.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
childView.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor) childView.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
]) ])
} }
} }

View file

@ -28,7 +28,7 @@ struct AccountDetailHeaderView: View {
Rectangle() Rectangle()
.frame(height: 200) .frame(height: 200)
.overlay { .overlay {
headerImageView headerImageView
} }
accountInfoView accountInfoView
} }

View file

@ -10,18 +10,18 @@ public struct ConversationsListView: View {
@EnvironmentObject private var watcher: StreamWatcher @EnvironmentObject private var watcher: StreamWatcher
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@StateObject private var viewModel = ConversationsListViewModel() @StateObject private var viewModel = ConversationsListViewModel()
public init() {} public init() {}
private var conversations: [Conversation] { private var conversations: [Conversation] {
if viewModel.isLoadingFirstPage { if viewModel.isLoadingFirstPage {
return Conversation.placeholders() return Conversation.placeholders()
} }
return viewModel.conversations return viewModel.conversations
} }
public var body: some View { public var body: some View {
ScrollView { ScrollView {
LazyVStack { LazyVStack {
@ -52,7 +52,7 @@ public struct ConversationsListView: View {
} }
} }
} }
if viewModel.nextPage != nil { if viewModel.nextPage != nil {
HStack { HStack {
Spacer() Spacer()

View file

@ -13,59 +13,59 @@ public extension Font {
private static let footnote = onMac ? 15.0 : 13.0 private static let footnote = onMac ? 15.0 : 13.0
private static let caption = onMac ? 14.0 : 12.0 private static let caption = onMac ? 14.0 : 12.0
private static let onMac = ProcessInfo.processInfo.isiOSAppOnMac private static let onMac = ProcessInfo.processInfo.isiOSAppOnMac
private static func customFont(size: CGFloat, relativeTo textStyle: TextStyle) -> Font { private static func customFont(size: CGFloat, relativeTo textStyle: TextStyle) -> Font {
if let chosenFont = UserPreferences.shared.chosenFont { if let chosenFont = UserPreferences.shared.chosenFont {
return .custom(chosenFont.fontName, size: size, relativeTo: textStyle) return .custom(chosenFont.fontName, size: size, relativeTo: textStyle)
} }
return onMac ? .system(size: size) : .system(textStyle) return onMac ? .system(size: size) : .system(textStyle)
} }
private static func customUIFont(size: CGFloat) -> UIFont { private static func customUIFont(size: CGFloat) -> UIFont {
if let chosenFont = UserPreferences.shared.chosenFont { if let chosenFont = UserPreferences.shared.chosenFont {
return chosenFont.withSize(size) return chosenFont.withSize(size)
} }
return .systemFont(ofSize: size) return .systemFont(ofSize: size)
} }
private static func userScaledFontSize(baseSize: CGFloat) -> CGFloat { private static func userScaledFontSize(baseSize: CGFloat) -> CGFloat {
if onMac { if onMac {
return UIFontMetrics.default.scaledValue(for: baseSize * UserPreferences.shared.fontSizeScale) return UIFontMetrics.default.scaledValue(for: baseSize * UserPreferences.shared.fontSizeScale)
} }
return baseSize return baseSize
} }
static var scaledTitle: Font { static var scaledTitle: Font {
customFont(size: userScaledFontSize(baseSize: title), relativeTo: .title) customFont(size: userScaledFontSize(baseSize: title), relativeTo: .title)
} }
static var scaledHeadline: Font { static var scaledHeadline: Font {
customFont(size: userScaledFontSize(baseSize: headline), relativeTo: .headline).weight(.semibold) customFont(size: userScaledFontSize(baseSize: headline), relativeTo: .headline).weight(.semibold)
} }
static var scaledBody: Font { static var scaledBody: Font {
customFont(size: userScaledFontSize(baseSize: body), relativeTo: .body) customFont(size: userScaledFontSize(baseSize: body), relativeTo: .body)
} }
static var scaledBodyUIFont: UIFont { static var scaledBodyUIFont: UIFont {
customUIFont(size: userScaledFontSize(baseSize: body)) customUIFont(size: userScaledFontSize(baseSize: body))
} }
static var scaledCallout: Font { static var scaledCallout: Font {
customFont(size: userScaledFontSize(baseSize: callout), relativeTo: .callout) customFont(size: userScaledFontSize(baseSize: callout), relativeTo: .callout)
} }
static var scaledSubheadline: Font { static var scaledSubheadline: Font {
customFont(size: userScaledFontSize(baseSize: subheadline), relativeTo: .subheadline) customFont(size: userScaledFontSize(baseSize: subheadline), relativeTo: .subheadline)
} }
static var scaledFootnote: Font { static var scaledFootnote: Font {
customFont(size: userScaledFontSize(baseSize: footnote), relativeTo: .footnote) customFont(size: userScaledFontSize(baseSize: footnote), relativeTo: .footnote)
} }
static var scaledCaption: Font { static var scaledCaption: Font {
customFont(size: userScaledFontSize(baseSize: caption), relativeTo: .caption) customFont(size: userScaledFontSize(baseSize: caption), relativeTo: .caption)
} }

View file

@ -2,36 +2,36 @@ import Env
import SwiftUI import SwiftUI
public struct FontPicker: UIViewControllerRepresentable { public struct FontPicker: UIViewControllerRepresentable {
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
public class Coordinator: NSObject, UIFontPickerViewControllerDelegate { public class Coordinator: NSObject, UIFontPickerViewControllerDelegate {
private let dismiss: DismissAction private let dismiss: DismissAction
public init(dismiss: DismissAction) { public init(dismiss: DismissAction) {
self.dismiss = dismiss self.dismiss = dismiss
}
public func fontPickerViewControllerDidCancel(_ viewController: UIFontPickerViewController) {
dismiss()
}
public func fontPickerViewControllerDidPickFont(_ viewController: UIFontPickerViewController) {
UserPreferences.shared.chosenFont = UIFont(descriptor: viewController.selectedFontDescriptor!, size: 0)
dismiss()
}
} }
public init() {} public func fontPickerViewControllerDidCancel(_: UIFontPickerViewController) {
dismiss()
public func makeCoordinator() -> Coordinator {
Coordinator(dismiss: dismiss)
} }
public func makeUIViewController(context: Context) -> UIFontPickerViewController { public func fontPickerViewControllerDidPickFont(_ viewController: UIFontPickerViewController) {
let controller = UIFontPickerViewController() UserPreferences.shared.chosenFont = UIFont(descriptor: viewController.selectedFontDescriptor!, size: 0)
controller.delegate = context.coordinator dismiss()
return controller
} }
}
public func updateUIViewController(_ viewController: UIFontPickerViewController, context: Context) {}
public init() {}
public func makeCoordinator() -> Coordinator {
Coordinator(dismiss: dismiss)
}
public func makeUIViewController(context: Context) -> UIFontPickerViewController {
let controller = UIFontPickerViewController()
controller.delegate = context.coordinator
return controller
}
public func updateUIViewController(_: UIFontPickerViewController, context _: Context) {}
} }

View file

@ -8,21 +8,21 @@ public class Theme: ObservableObject {
case selectedSet, selectedScheme case selectedSet, selectedScheme
case followSystemColorSchme case followSystemColorSchme
} }
public enum FontState: Int, CaseIterable { public enum FontState: Int, CaseIterable {
case system case system
case custom case custom
@MainActor @MainActor
public var title: LocalizedStringKey { public var title: LocalizedStringKey {
switch self { switch self {
case .system: case .system:
return "settings.display.font.system" return "settings.display.font.system"
case .custom: case .custom:
return "settings.display.font.custom" return "settings.display.font.custom"
} }
}
} }
}
public enum AvatarPosition: String, CaseIterable { public enum AvatarPosition: String, CaseIterable {
case leading, top case leading, top

View file

@ -48,7 +48,7 @@ struct ThemeApplier: ViewModifier {
setBarsColor(newValue) setBarsColor(newValue)
} }
.onChange(of: theme.selectedScheme) { newValue in .onChange(of: theme.selectedScheme) { newValue in
setWindowUserInterfaceStyle(from: newValue) setWindowUserInterfaceStyle(from: newValue)
} }
.onChange(of: colorScheme) { newColorScheme in .onChange(of: colorScheme) { newColorScheme in
if theme.followSystemColorScheme, if theme.followSystemColorScheme,
@ -64,8 +64,8 @@ struct ThemeApplier: ViewModifier {
#if canImport(UIKit) #if canImport(UIKit)
private func setWindowUserInterfaceStyle(from colorScheme: ColorScheme) { private func setWindowUserInterfaceStyle(from colorScheme: ColorScheme) {
guard !theme.followSystemColorScheme else { guard !theme.followSystemColorScheme else {
setWindowUserInterfaceStyle(.unspecified) setWindowUserInterfaceStyle(.unspecified)
return return
} }
switch colorScheme { switch colorScheme {
case .dark: case .dark:
@ -74,14 +74,14 @@ struct ThemeApplier: ViewModifier {
setWindowUserInterfaceStyle(.light) setWindowUserInterfaceStyle(.light)
} }
} }
private func setWindowUserInterfaceStyle(_ userInterfaceStyle: UIUserInterfaceStyle) { private func setWindowUserInterfaceStyle(_ userInterfaceStyle: UIUserInterfaceStyle) {
allWindows() allWindows()
.forEach { .forEach {
$0.overrideUserInterfaceStyle = userInterfaceStyle $0.overrideUserInterfaceStyle = userInterfaceStyle
} }
} }
private func setWindowTint(_ color: Color) { private func setWindowTint(_ color: Color) {
allWindows() allWindows()
.forEach { .forEach {

View file

@ -5,8 +5,8 @@ private struct SecondaryColumnKey: EnvironmentKey {
static let defaultValue = false static let defaultValue = false
} }
extension EnvironmentValues { public extension EnvironmentValues {
public var isSecondaryColumn: Bool { var isSecondaryColumn: Bool {
get { self[SecondaryColumnKey.self] } get { self[SecondaryColumnKey.self] }
set { self[SecondaryColumnKey.self] = newValue } set { self[SecondaryColumnKey.self] = newValue }
} }

View file

@ -33,7 +33,7 @@ public class QuickLook: ObservableObject {
paths.append(path) paths.append(path)
} }
return paths.sorted { url1, url2 in return paths.sorted { url1, url2 in
return pathOrderMap[url1.lastPathComponent] ?? 0 < pathOrderMap[url2.lastPathComponent] ?? 0 pathOrderMap[url1.lastPathComponent] ?? 0 < pathOrderMap[url2.lastPathComponent] ?? 0
} }
}) })
withTransaction(transaction) { withTransaction(transaction) {

View file

@ -26,7 +26,7 @@ public class UserPreferences: ObservableObject {
@AppStorage("app_default_post_visibility") public var appDefaultPostVisibility: Models.Visibility = .pub @AppStorage("app_default_post_visibility") public var appDefaultPostVisibility: Models.Visibility = .pub
@AppStorage("app_default_posts_sensitive") public var appDefaultPostsSensitive = false @AppStorage("app_default_posts_sensitive") public var appDefaultPostsSensitive = false
@AppStorage("autoplay_video") public var autoPlayVideo = true @AppStorage("autoplay_video") public var autoPlayVideo = true
@AppStorage("chosen_font") public private(set) var chosenFontData: Data? @AppStorage("chosen_font") public private(set) var chosenFontData: Data?
public var postVisibility: Models.Visibility { public var postVisibility: Models.Visibility {
if useInstanceContentSettings { if useInstanceContentSettings {
@ -68,23 +68,24 @@ public class UserPreferences: ObservableObject {
Self.sharedDefault?.set(newValue, forKey: "push_notifications_count") Self.sharedDefault?.set(newValue, forKey: "push_notifications_count")
} }
} }
public var chosenFont: UIFont? { public var chosenFont: UIFont? {
get { get {
guard let chosenFontData, guard let chosenFontData,
let font = try? NSKeyedUnarchiver.unarchivedObject(ofClass: UIFont.self, from: chosenFontData) else { return nil } let font = try? NSKeyedUnarchiver.unarchivedObject(ofClass: UIFont.self, from: chosenFontData) else { return nil }
return font return font
}
set {
if let font = newValue,
let data = try? NSKeyedArchiver.archivedData(withRootObject: font, requiringSecureCoding: false) {
chosenFontData = data
} else {
chosenFontData = nil
}
}
} }
set {
if let font = newValue,
let data = try? NSKeyedArchiver.archivedData(withRootObject: font, requiringSecureCoding: false)
{
chosenFontData = data
} else {
chosenFontData = nil
}
}
}
@Published public var serverPreferences: ServerPreferences? @Published public var serverPreferences: ServerPreferences?

View file

@ -24,9 +24,9 @@ public struct HTMLString: Decodable, Equatable, Hashable {
// other characters the markdown parser used picks up // other characters the markdown parser used picks up
// when it renders to attributed text // when it renders to attributed text
if let regex = try? NSRegularExpression(pattern: "([\\_\\`\\[\\\\])", options: .caseInsensitive) { if let regex = try? NSRegularExpression(pattern: "([\\_\\`\\[\\\\])", options: .caseInsensitive) {
htmlValue = regex.stringByReplacingMatches(in: htmlValue, options: [], range: NSRange(location: 0, length: htmlValue.count), withTemplate: "\\\\$1") htmlValue = regex.stringByReplacingMatches(in: htmlValue, options: [], range: NSRange(location: 0, length: htmlValue.count), withTemplate: "\\\\$1")
} }
do { do {
asMarkdown = try HTMLParser().parse(html: htmlValue) asMarkdown = try HTMLParser().parse(html: htmlValue)
.toMarkdown() .toMarkdown()

View file

@ -32,8 +32,8 @@ struct NotificationRowView: View {
} }
} }
} }
.alignmentGuide(.listRowSeparatorLeading) { viewDimensions in .alignmentGuide(.listRowSeparatorLeading) { _ in
return -100 -100
} }
} }

View file

@ -1,6 +1,6 @@
import DesignSystem
import Models import Models
import SwiftUI import SwiftUI
import DesignSystem
extension Models.Notification.NotificationType { extension Models.Notification.NotificationType {
func label(count: Int) -> LocalizedStringKey { func label(count: Int) -> LocalizedStringKey {
@ -42,7 +42,7 @@ extension Models.Notification.NotificationType {
return "pencil.line" return "pencil.line"
} }
} }
func tintColor() -> Color { func tintColor() -> Color {
switch self { switch self {
case .status, .mention, .update, .poll: case .status, .mention, .update, .poll:

View file

@ -103,7 +103,7 @@ public struct NotificationsListView: View {
bottom: 12, bottom: 12,
trailing: .layoutPadding)) trailing: .layoutPadding))
.listRowBackground(notification.type == .mention && lockedType != .mention ? .listRowBackground(notification.type == .mention && lockedType != .mention ?
theme.secondaryBackgroundColor : theme.primaryBackgroundColor) theme.secondaryBackgroundColor : theme.primaryBackgroundColor)
} }
} }
@ -144,9 +144,9 @@ public struct NotificationsListView: View {
trailing: .layoutPadding)) trailing: .layoutPadding))
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
} }
private var topPaddingView: some View { private var topPaddingView: some View {
HStack { } HStack {}
.listRowBackground(Color.clear) .listRowBackground(Color.clear)
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
.listRowInsets(.init()) .listRowInsets(.init())

View file

@ -14,15 +14,15 @@ public struct StatusDetailView: View {
@Environment(\.openURL) private var openURL @Environment(\.openURL) private var openURL
@StateObject private var viewModel: StatusDetailViewModel @StateObject private var viewModel: StatusDetailViewModel
@State private var isLoaded: Bool = false @State private var isLoaded: Bool = false
public init(statusId: String) { public init(statusId: String) {
_viewModel = StateObject(wrappedValue: .init(statusId: statusId)) _viewModel = StateObject(wrappedValue: .init(statusId: statusId))
} }
public init(remoteStatusURL: URL) { public init(remoteStatusURL: URL) {
_viewModel = StateObject(wrappedValue: .init(remoteStatusURL: remoteStatusURL)) _viewModel = StateObject(wrappedValue: .init(remoteStatusURL: remoteStatusURL))
} }
public var body: some View { public var body: some View {
ScrollViewReader { proxy in ScrollViewReader { proxy in
ZStack { ZStack {
@ -51,8 +51,8 @@ public struct StatusDetailView: View {
StatusRowView(viewModel: .init(status: status, StatusRowView(viewModel: .init(status: status,
isCompact: false, isCompact: false,
isFocused: true)) isFocused: true))
.padding(.horizontal, .layoutPadding) .padding(.horizontal, .layoutPadding)
.id(status.id) .id(status.id)
Divider() Divider()
.padding(.bottom, .dividerPadding * 2) .padding(.bottom, .dividerPadding * 2)
if !context.descendants.isEmpty { if !context.descendants.isEmpty {
@ -63,7 +63,7 @@ public struct StatusDetailView: View {
.padding(.vertical, .dividerPadding) .padding(.vertical, .dividerPadding)
} }
} }
case .error: case .error:
ErrorView(title: "status.error.title", ErrorView(title: "status.error.title",
message: "status.error.message", message: "status.error.message",

View file

@ -78,7 +78,7 @@ struct StatusEditorAccessoryView: View {
Image(systemName: "globe") Image(systemName: "globe")
} }
} }
if preferences.isOpenAIEnabled { if preferences.isOpenAIEnabled {
AIMenu.disabled(!viewModel.canPost) AIMenu.disabled(!viewModel.canPost)
} }
@ -115,7 +115,7 @@ struct StatusEditorAccessoryView: View {
Text(isoCode.uppercased()) Text(isoCode.uppercased())
} }
} }
private var AIMenu: some View { private var AIMenu: some View {
Menu { Menu {
ForEach(StatusEditorAIPrompts.allCases, id: \.self) { prompt in ForEach(StatusEditorAIPrompts.allCases, id: \.self) { prompt in

View file

@ -1,6 +1,6 @@
import AVKit import AVKit
import SwiftUI
import Env import Env
import SwiftUI
class VideoPlayerViewModel: ObservableObject { class VideoPlayerViewModel: ObservableObject {
@Published var player: AVPlayer? @Published var player: AVPlayer?
@ -41,7 +41,7 @@ class VideoPlayerViewModel: ObservableObject {
struct VideoPlayerView: View { struct VideoPlayerView: View {
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@StateObject var viewModel: VideoPlayerViewModel @StateObject var viewModel: VideoPlayerViewModel
var body: some View { var body: some View {

View file

@ -87,7 +87,7 @@ struct StatusActionsView: View {
} }
.buttonStyle(.borderless) .buttonStyle(.borderless)
.disabled(action == .boost && .disabled(action == .boost &&
(viewModel.status.visibility == .direct || viewModel.status.visibility == .priv)) (viewModel.status.visibility == .direct || viewModel.status.visibility == .priv))
Spacer() Spacer()
} }
} }

View file

@ -86,7 +86,8 @@ struct StatusRowContextMenu: View {
} }
} label: { } label: {
if let statusLanguage = viewModel.status.language, if let statusLanguage = viewModel.status.language,
let lanugageName = Locale.current.localizedString(forLanguageCode: statusLanguage) { let lanugageName = Locale.current.localizedString(forLanguageCode: statusLanguage)
{
Label("status.action.translate-from-\(lanugageName)", systemImage: "captions.bubble") Label("status.action.translate-from-\(lanugageName)", systemImage: "captions.bubble")
} else { } else {
Label("status.action.translate", systemImage: "captions.bubble") Label("status.action.translate", systemImage: "captions.bubble")

View file

@ -317,7 +317,8 @@ public struct StatusRowView: View {
ProgressView() ProgressView()
} else { } else {
if let statusLanguage = status.language, if let statusLanguage = status.language,
let lanugageName = Locale.current.localizedString(forLanguageCode: statusLanguage) { let lanugageName = Locale.current.localizedString(forLanguageCode: statusLanguage)
{
Text("status.action.translate-from-\(lanugageName)") Text("status.action.translate-from-\(lanugageName)")
} else { } else {
Text("status.action.translate") Text("status.action.translate")
@ -389,7 +390,7 @@ public struct StatusRowView: View {
} }
} }
} }
private var remoteContentLoadingView: some View { private var remoteContentLoadingView: some View {
ZStack(alignment: .center) { ZStack(alignment: .center) {
VStack { VStack {

View file

@ -71,7 +71,7 @@ public class StatusRowViewModel: ObservableObject {
routerPath.navigate(to: .statusDetail(id: status.reblog?.id ?? status.id)) routerPath.navigate(to: .statusDetail(id: status.reblog?.id ?? status.id))
} }
} }
func navigateToAccountDetail(account: Account, routerPath: RouterPath) { func navigateToAccountDetail(account: Account, routerPath: RouterPath) {
if isRemote, let url = account.url { if isRemote, let url = account.url {
withAnimation { withAnimation {
@ -85,7 +85,7 @@ public class StatusRowViewModel: ObservableObject {
routerPath.navigate(to: .accountDetailWithAccount(account: account)) routerPath.navigate(to: .accountDetailWithAccount(account: account))
} }
} }
func navigateToMention(mention: Mention, routerPath: RouterPath) { func navigateToMention(mention: Mention, routerPath: RouterPath) {
if isRemote { if isRemote {
withAnimation { withAnimation {