Skip to content

Commit

Permalink
SwiftUIify Settings screen and fix app icon picker (#1179)
Browse files Browse the repository at this point in the history
* Expand AwfulSwift into AwfulExtensions and move SDK/stdlib extensions in so we can use them from other packages
* Move settings (including codegen) into new AwfulSettings package
* Replace Sourcery and custom UserDefaults stuff with Foil and other custom UserDefaults stuff
* Make a SwiftUI SettingsView
* Move (user defaults) settings migration into AwfulSettings module
    * Also start AwfulModelTypes package for tagged identifier types.
* Delete unsupported setting custom_base_URL
* Move Theme into new AwfulTheming package
    * Would be nice to move .css files over, but they're generated from .less files, and pulling that generation into a Swift package build plugin is more effort than it's worth right now.
* Theme the SettingsView
    * Slowly figuring out how to bring themes into SwiftUI. The environment key and view modifier seem like a good step. Manually having to set everything is annoying, but let's try it out on a few different views before trying anything drastic.
    * Also split AwfulSettingsUI into its own package to fix a dependency cycle between AwfulSettings and AwfulTheming. AwfulTheming needs to read some Settings values to do its job, but AwfulSettingsUI needs to theme itself. Maybe there's a smarter breakdown here. Or maybe AwfulSettingsUI can pull its weight if we move the other Settings tab screens over.
* Delete old settings view controller, Settings.plist, and SettingsBinding
* Quarantine remaining Objective-C code in packages, drop bridging header, and add missing imports previously covered up by the bridging header
* Move forum-specific themes and theme picker view controllers into AwfulSettingsUI
* Move acknowledgements screen to SwiftUI
* Update build settings for Xcode 15.2 and add new test targets to test plan
  • Loading branch information
nolanw committed Feb 27, 2024
1 parent 12d190b commit e5926dc
Show file tree
Hide file tree
Showing 208 changed files with 4,267 additions and 6,793 deletions.
13 changes: 9 additions & 4 deletions App/Composition/ComposeTextViewController.swift
Expand Up @@ -2,9 +2,14 @@
//
// Copyright 2016 Awful Contributors. CC BY-NC-SA 3.0 US https://github.com/Awful/Awful.app

import AwfulSettings
import AwfulTheming
import MRProgress
import UIKit

class ComposeTextViewController: ViewController {
@FoilDefaultStorage(Settings.enableHaptics) private var enableHaptics

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
navigationItem.leftBarButtonItem = cancelButtonItem
Expand Down Expand Up @@ -199,10 +204,10 @@ class ComposeTextViewController: ViewController {

switch error {
case let error as LocalizedError where error.failureReason != nil:
alert = UIAlertController(title: error.localizedDescription, message: error.failureReason ?? "")
alert = UIAlertController(title: error.localizedDescription, message: error.failureReason ?? "", alertActions: [.ok()])

case let error as LocalizedError:
alert = UIAlertController(title: LocalizedString("image-upload.generic-error-title"), message: error.localizedDescription)
alert = UIAlertController(title: LocalizedString("image-upload.generic-error-title"), message: error.localizedDescription, alertActions: [.ok()])

case let error:
alert = UIAlertController(title: LocalizedString("image-upload.generic-error-title"), error: error)
Expand Down Expand Up @@ -255,7 +260,7 @@ class ComposeTextViewController: ViewController {
}

@objc fileprivate func didTapSubmit() {
if UserDefaults.standard.enableHaptics {
if enableHaptics {
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
}
disableEverythingButTheCancelButton()
Expand All @@ -274,7 +279,7 @@ class ComposeTextViewController: ViewController {
}

@objc fileprivate func didTapCancel() {
if UserDefaults.standard.enableHaptics {
if enableHaptics {
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
}
if let progress = imageUploadProgress {
Expand Down
6 changes: 4 additions & 2 deletions App/Composition/CompositionMenuTree.swift
Expand Up @@ -4,13 +4,15 @@

import MobileCoreServices
import Photos
import PSMenuItem
import UIKit

private let Log = Logger.get()

/// Can take over UIMenuController to show a tree of composition-related items on behalf of a text view.
// This classes exists to expose the struct-defined menu to Objective-C and to act as an image picker delegate.
final class CompositionMenuTree: NSObject {
// This class exists to expose the struct-defined menu to Objective-C and to act as an image picker delegate.

let textView: UITextView

/// The textView's class will have some responder chain methods swizzled.
Expand Down Expand Up @@ -133,7 +135,7 @@ extension CompositionMenuTree: UIImagePickerControllerDelegate, UINavigationCont
) {
guard let image = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage else {
Log.e("could not find image among image picker info")
let alert = UIAlertController(title: "Could Not Find Image", message: "The chosen image could not be found")
let alert = UIAlertController(title: "Could Not Find Image", message: "The chosen image could not be found", alertActions: [.ok()])
textView.nearestViewController?.present(alert, animated: true)
return
}
Expand Down
13 changes: 10 additions & 3 deletions App/Composition/CompositionViewController.swift
Expand Up @@ -2,7 +2,14 @@
//
// Copyright 2014 Awful Contributors. CC BY-NC-SA 3.0 US https://github.com/Awful/Awful.app

import AwfulSettings
import AwfulTheming
import UIKit

final class CompositionViewController: ViewController {

@FoilDefaultStorage(Settings.enableHaptics) private var enableHaptics

override init(nibName: String?, bundle: Bundle?) {
super.init(nibName: nil, bundle: nil)
restorationClass = type(of: self)
Expand All @@ -20,10 +27,10 @@ final class CompositionViewController: ViewController {
}

@objc fileprivate func didTapCancel() {
if UserDefaults.standard.enableHaptics {
if enableHaptics {
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
}
dismiss(animated: true, completion: nil)
dismiss(animated: true)
}

@objc func cancel(_ sender: UIKeyCommand) {
Expand Down Expand Up @@ -88,7 +95,7 @@ final class CompositionViewController: ViewController {

override var keyCommands: [UIKeyCommand]? {
return [
UIKeyCommand.make(input: UIKeyCommand.inputEscape, action: #selector(cancel(_:)), discoverabilityTitle: "Cancel"),
UIKeyCommand(action: #selector(cancel(_:)), input: UIKeyCommand.inputEscape, discoverabilityTitle: "Cancel"),
]
}
}
Expand Down
8 changes: 5 additions & 3 deletions App/Composition/SelfHostingAttachmentInterpolator.swift
Expand Up @@ -2,12 +2,14 @@
//
// Copyright 2016 Awful Contributors. CC BY-NC-SA 3.0 US https://github.com/Awful/Awful.app

import Foundation
import AwfulSettings
import UIKit

/// Hosts image data via the `awful-image` URL protocol so it can be shown from a UIWebView.
final class SelfHostingAttachmentInterpolator: NSObject {
@FoilDefaultStorage(Settings.automaticTimg) private var automaticTimg
fileprivate var URLs: [URL] = []

func interpolateImagesInString(_ string: NSAttributedString) -> String {
let basePath = "/\(UUID().uuidString)" as NSString
let mutableString = string.mutableCopy() as! NSMutableAttributedString
Expand All @@ -20,7 +22,7 @@ final class SelfHostingAttachmentInterpolator: NSObject {
self.URLs.append(URL)

let imageSize = attachment.image?.size ?? .zero
let requiresThumbnailing = UserDefaults.standard.postLargeImagesAsThumbnails
let requiresThumbnailing = automaticTimg
&& (imageSize.width > TextAttachment.requiresThumbnailImageSize.width
|| imageSize.height > TextAttachment.requiresThumbnailImageSize.height)
let t = requiresThumbnailing ? "t" : ""
Expand Down
7 changes: 4 additions & 3 deletions App/Composition/UploadImageAttachments.swift
Expand Up @@ -2,9 +2,11 @@
//
// Copyright 2014 Awful Contributors. CC BY-NC-SA 3.0 US https://github.com/Awful/Awful.app

import AwfulSettings
import Foundation
import ImgurAnonymousAPI
import Photos
import UIKit

private let Log = Logger.get()

Expand Down Expand Up @@ -151,10 +153,9 @@ private struct ImageTag {

func BBcode(_ url: URL) -> String {
let t: String
if
UserDefaults.standard.postLargeImagesAsThumbnails &&
if FoilDefaultStorage(Settings.automaticTimg).wrappedValue &&
(size.width > TextAttachment.requiresThumbnailImageSize.width ||
size.height > TextAttachment.requiresThumbnailImageSize.height)
size.height > TextAttachment.requiresThumbnailImageSize.height)
{
t = "t"
} else {
Expand Down
7 changes: 4 additions & 3 deletions App/Data Sources/ForumListDataSource.swift
Expand Up @@ -3,6 +3,7 @@
// Copyright 2017 Awful Contributors. CC BY-NC-SA 3.0 US https://github.com/Awful/Awful.app

import AwfulCore
import AwfulTheming
import CoreData
import UIKit

Expand Down Expand Up @@ -424,7 +425,7 @@ extension ForumListDataSource: UITableViewDataSource {
favoriteStarTintColor: theme["favoriteStarTintColor"]!,
forumName: NSAttributedString(string: announcement.title, attributes: [
.font: UIFont.preferredFontForTextStyle(.body, fontName: theme["listFontName"], weight: .regular),
.foregroundColor: theme[color: "listTextColor"]!]),
.foregroundColor: theme[uicolor: "listTextColor"]!]),
indentationLevel: 0,
selectedBackgroundColor: theme["listSelectedBackgroundColor"]!)

Expand All @@ -437,7 +438,7 @@ extension ForumListDataSource: UITableViewDataSource {
favoriteStarTintColor: theme["favoriteStarTintColor"]!,
forumName: NSAttributedString(string: forum.name ?? "", attributes: [
.font: UIFont.preferredFontForTextStyle(.body, fontName: theme["listFontName"], weight: .regular),
.foregroundColor: theme[color: "listTextColor"]!]),
.foregroundColor: theme[uicolor: "listTextColor"]!]),
indentationLevel: 0,
selectedBackgroundColor: theme["listSelectedBackgroundColor"]!)

Expand All @@ -460,7 +461,7 @@ extension ForumListDataSource: UITableViewDataSource {
favoriteStarTintColor: theme["favoriteStarTintColor"]!,
forumName: NSAttributedString(string: forum.name ?? "", attributes: [
.font: UIFont.preferredFontForTextStyle(.body, fontName: theme["listFontName"], weight: .regular),
.foregroundColor: theme[color: "listTextColor"]!]),
.foregroundColor: theme[uicolor: "listTextColor"]!]),
indentationLevel: forum.ancestors.reduce(0) { i, _ in i + 1 },
selectedBackgroundColor: theme["listSelectedBackgroundColor"]!)

Expand Down
9 changes: 5 additions & 4 deletions App/Data Sources/MessageListDataSource.swift
Expand Up @@ -3,6 +3,7 @@
// Copyright 2018 Awful Contributors. CC BY-NC-SA 3.0 US https://github.com/Awful/Awful.app

import AwfulCore
import AwfulTheming
import CoreData
import UIKit

Expand Down Expand Up @@ -102,17 +103,17 @@ extension MessageListDataSource: UITableViewDataSource {
selectedBackgroundColor: theme["listSelectedBackgroundColor"]!,
sender: NSAttributedString(string: message.fromUsername ?? "", attributes: [
.font: UIFont.preferredFontForTextStyle(.body, fontName: nil, sizeAdjustment: theme[double: "messageListSenderFontSizeAdjustment"]!, weight: .semibold),
.foregroundColor: theme[color: "listSecondaryTextColor"]!]),
.foregroundColor: theme[uicolor: "listSecondaryTextColor"]!]),
sentDate: message.sentDate ?? .distantPast,
sentDateAttributes: [
.font: UIFont.preferredFontForTextStyle(.body, fontName: nil, sizeAdjustment: theme[double: "messageListSentDateFontSizeAdjustment"]!, weight: .semibold),
.foregroundColor: theme[color: "listTextColor"]!],
.foregroundColor: theme[uicolor: "listTextColor"]!],
sentDateRaw: NSAttributedString(string: sentDateFormatter.string(from: message.sentDate!), attributes: [
.font: UIFont.preferredFontForTextStyle(.body, fontName: nil, sizeAdjustment: theme[double: "messageListSentDateFontSizeAdjustment"]!, weight: .semibold),
.foregroundColor: theme[color: "listSecondaryTextColor"]!]),
.foregroundColor: theme[uicolor: "listSecondaryTextColor"]!]),
subject: NSAttributedString(string: message.subject ?? "", attributes: [
.font: UIFont.preferredFontForTextStyle(.body, fontName: nil, sizeAdjustment: theme[double: "messageListSubjectFontSizeAdjustment"]!, weight: .regular),
.foregroundColor: theme[color: "listTextColor"]!]),
.foregroundColor: theme[uicolor: "listTextColor"]!]),
tagImage: .image(name: message.threadTag?.imageName, placeholder: .privateMessage),
tagOverlayImage: {
if message.replied {
Expand Down
10 changes: 6 additions & 4 deletions App/Data Sources/ThreadListDataSource.swift
Expand Up @@ -3,6 +3,8 @@
// Copyright 2018 Awful Contributors. CC BY-NC-SA 3.0 US https://github.com/Awful/Awful.app

import AwfulCore
import AwfulModelTypes
import AwfulTheming
import CoreData
import UIKit

Expand Down Expand Up @@ -145,13 +147,13 @@ extension ThreadListDataSource: UITableViewDataSource {
private func viewModelForCell(at indexPath: IndexPath) -> ThreadListCell.ViewModel {
let thread = resultsController.object(at: indexPath)
let theme = delegate?.themeForItem(at: indexPath, in: self) ?? .defaultTheme()
let tweaks = thread.forum.flatMap { ForumTweaks(forumID: $0.forumID) }
let tweaks = thread.forum.flatMap { ForumTweaks(ForumID($0.forumID)) }

return ThreadListCell.ViewModel(
backgroundColor: theme["listBackgroundColor"]!,
pageCount: NSAttributedString(string: "\(thread.numberOfPages)", attributes: [
.font: UIFont.preferredFontForTextStyle(.footnote, fontName: theme["listFontName"], sizeAdjustment: 0, weight: .semibold),
.foregroundColor: theme[color: "listSecondaryTextColor"]!]),
.foregroundColor: theme[uicolor: "listSecondaryTextColor"]!]),
pageIconColor: theme["threadListPageIconColor"]!,
postInfo: {
let text: String
Expand All @@ -163,7 +165,7 @@ extension ThreadListDataSource: UITableViewDataSource {
}
return NSAttributedString(string: text, attributes: [
.font: UIFont.preferredFontForTextStyle(.footnote, fontName: theme["listFontName"], sizeAdjustment: 0, weight: .semibold),
.foregroundColor: theme[color: "listSecondaryTextColor"]!])
.foregroundColor: theme[uicolor: "listSecondaryTextColor"]!])
}(),
ratingImage: {
if !showsTagAndRating {
Expand Down Expand Up @@ -205,7 +207,7 @@ extension ThreadListDataSource: UITableViewDataSource {
}(),
title: NSAttributedString(string: thread.title ?? "", attributes: [
.font: UIFont.preferredFontForTextStyle(.body, fontName: theme["listFontName"], sizeAdjustment: 0, weight: .regular),
.foregroundColor: theme[color: thread.closed ? "listSecondaryTextColor" : "listTextColor"]!]),
.foregroundColor: theme[uicolor: thread.closed ? "listSecondaryTextColor" : "listTextColor"]!]),
unreadCount: {
guard thread.beenSeen else { return NSAttributedString() }
let color: UIColor
Expand Down
11 changes: 0 additions & 11 deletions App/Extensions/CGRect+Center.swift

This file was deleted.

36 changes: 0 additions & 36 deletions App/Extensions/CoreAnimation.swift

This file was deleted.

0 comments on commit e5926dc

Please sign in to comment.