mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Merge pull request #754 from omnivore-app/fix/ios-web-prefs-fixes
iOS Font Switching
This commit is contained in:
commit
043cb25c32
12 changed files with 317 additions and 203 deletions
|
|
@ -13,12 +13,10 @@ import WebKit
|
|||
let webViewActionHandler: (WKScriptMessage, WKScriptMessageReplyHandler?) -> Void
|
||||
let navBarVisibilityRatioUpdater: (Double) -> Void
|
||||
|
||||
@Binding var increaseFontActionID: UUID?
|
||||
@Binding var decreaseFontActionID: UUID?
|
||||
@Binding var increaseMarginActionID: UUID?
|
||||
@Binding var decreaseMarginActionID: UUID?
|
||||
@Binding var increaseLineHeightActionID: UUID?
|
||||
@Binding var decreaseLineHeightActionID: UUID?
|
||||
@Binding var updateFontFamilyActionID: UUID?
|
||||
@Binding var updateFontActionID: UUID?
|
||||
@Binding var updateMarginActionID: UUID?
|
||||
@Binding var updateLineHeightActionID: UUID?
|
||||
@Binding var annotationSaveTransactionID: UUID?
|
||||
@Binding var showNavBarActionID: UUID?
|
||||
@Binding var shareActionID: UUID?
|
||||
|
|
@ -78,37 +76,27 @@ import WebKit
|
|||
func updateUIView(_ webView: WKWebView, context: Context) {
|
||||
if annotationSaveTransactionID != context.coordinator.lastSavedAnnotationID {
|
||||
context.coordinator.lastSavedAnnotationID = annotationSaveTransactionID
|
||||
(webView as? WebView)?.saveAnnotation(annotation: annotation)
|
||||
(webView as? WebView)?.dispatchEvent(.saveAnnotation(annotation: annotation))
|
||||
}
|
||||
|
||||
if increaseFontActionID != context.coordinator.previousIncreaseFontActionID {
|
||||
context.coordinator.previousIncreaseFontActionID = increaseFontActionID
|
||||
(webView as? WebView)?.increaseFontSize()
|
||||
if updateFontFamilyActionID != context.coordinator.previousUpdateFontFamilyActionID {
|
||||
context.coordinator.previousUpdateFontFamilyActionID = updateFontFamilyActionID
|
||||
(webView as? WebView)?.updateFontFamily()
|
||||
}
|
||||
|
||||
if decreaseFontActionID != context.coordinator.previousDecreaseFontActionID {
|
||||
context.coordinator.previousDecreaseFontActionID = decreaseFontActionID
|
||||
(webView as? WebView)?.decreaseFontSize()
|
||||
if updateFontActionID != context.coordinator.previousUpdateFontActionID {
|
||||
context.coordinator.previousUpdateFontActionID = updateFontActionID
|
||||
(webView as? WebView)?.updateFontSize()
|
||||
}
|
||||
|
||||
if increaseMarginActionID != context.coordinator.previousIncreaseMarginActionID {
|
||||
context.coordinator.previousIncreaseMarginActionID = increaseMarginActionID
|
||||
(webView as? WebView)?.increaseMargin()
|
||||
if updateMarginActionID != context.coordinator.previousUpdateMarginActionID {
|
||||
context.coordinator.previousUpdateMarginActionID = updateMarginActionID
|
||||
(webView as? WebView)?.updateMargin()
|
||||
}
|
||||
|
||||
if decreaseMarginActionID != context.coordinator.previousDecreaseMarginActionID {
|
||||
context.coordinator.previousDecreaseMarginActionID = decreaseMarginActionID
|
||||
(webView as? WebView)?.decreaseMargin()
|
||||
}
|
||||
|
||||
if increaseLineHeightActionID != context.coordinator.previousIncreaseLineHeightActionID {
|
||||
context.coordinator.previousIncreaseLineHeightActionID = increaseLineHeightActionID
|
||||
(webView as? WebView)?.increaseLineHeight()
|
||||
}
|
||||
|
||||
if decreaseLineHeightActionID != context.coordinator.previousDecreaseLineHeightActionID {
|
||||
context.coordinator.previousDecreaseLineHeightActionID = decreaseLineHeightActionID
|
||||
(webView as? WebView)?.decreaseLineHeight()
|
||||
if updateLineHeightActionID != context.coordinator.previousUpdateLineHeightActionID {
|
||||
context.coordinator.previousUpdateLineHeightActionID = updateLineHeightActionID
|
||||
(webView as? WebView)?.updateLineHeight()
|
||||
}
|
||||
|
||||
if showNavBarActionID != context.coordinator.previousShowNavBarActionID {
|
||||
|
|
@ -144,6 +132,9 @@ import WebKit
|
|||
}
|
||||
|
||||
func loadContent(webView: WKWebView) {
|
||||
let fontFamilyValue = UserDefaults.standard.string(forKey: UserDefaultKey.preferredWebFont.rawValue)
|
||||
let fontFamily = fontFamilyValue.flatMap { WebFont(rawValue: $0) } ?? .inter
|
||||
|
||||
webView.loadHTMLString(
|
||||
WebReaderContent(
|
||||
htmlContent: htmlContent,
|
||||
|
|
@ -152,7 +143,8 @@ import WebKit
|
|||
isDark: UITraitCollection.current.userInterfaceStyle == .dark,
|
||||
fontSize: fontSize(),
|
||||
lineHeight: lineHeight(),
|
||||
margin: margin()
|
||||
margin: margin(),
|
||||
fontFamily: fontFamily
|
||||
)
|
||||
.styledContent,
|
||||
baseURL: ViewsPackage.bundleURL
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@ import WebKit
|
|||
@State private var navBarVisibilityRatio = 1.0
|
||||
@State private var showDeleteConfirmation = false
|
||||
@State private var progressViewOpacity = 0.0
|
||||
@State var increaseFontActionID: UUID?
|
||||
@State var decreaseFontActionID: UUID?
|
||||
@State var increaseMarginActionID: UUID?
|
||||
@State var decreaseMarginActionID: UUID?
|
||||
@State var increaseLineHeightActionID: UUID?
|
||||
@State var decreaseLineHeightActionID: UUID?
|
||||
@State var updateFontFamilyActionID: UUID?
|
||||
@State var updateFontActionID: UUID?
|
||||
@State var updateMarginActionID: UUID?
|
||||
@State var updateLineHeightActionID: UUID?
|
||||
@State var annotationSaveTransactionID: UUID?
|
||||
@State var showNavBarActionID: UUID?
|
||||
@State var shareActionID: UUID?
|
||||
|
|
@ -149,12 +147,10 @@ import WebKit
|
|||
navBarVisibilityRatioUpdater: {
|
||||
navBarVisibilityRatio = $0
|
||||
},
|
||||
increaseFontActionID: $increaseFontActionID,
|
||||
decreaseFontActionID: $decreaseFontActionID,
|
||||
increaseMarginActionID: $increaseMarginActionID,
|
||||
decreaseMarginActionID: $decreaseMarginActionID,
|
||||
increaseLineHeightActionID: $increaseLineHeightActionID,
|
||||
decreaseLineHeightActionID: $decreaseLineHeightActionID,
|
||||
updateFontFamilyActionID: $updateFontFamilyActionID,
|
||||
updateFontActionID: $updateFontActionID,
|
||||
updateMarginActionID: $updateMarginActionID,
|
||||
updateLineHeightActionID: $updateLineHeightActionID,
|
||||
annotationSaveTransactionID: $annotationSaveTransactionID,
|
||||
showNavBarActionID: $showNavBarActionID,
|
||||
shareActionID: $shareActionID,
|
||||
|
|
@ -202,12 +198,10 @@ import WebKit
|
|||
}
|
||||
.formSheet(isPresented: $showPreferencesPopover) {
|
||||
WebPreferencesPopoverView(
|
||||
increaseFontAction: { increaseFontActionID = UUID() },
|
||||
decreaseFontAction: { decreaseFontActionID = UUID() },
|
||||
increaseMarginAction: { increaseMarginActionID = UUID() },
|
||||
decreaseMarginAction: { decreaseMarginActionID = UUID() },
|
||||
increaseLineHeightAction: { increaseLineHeightActionID = UUID() },
|
||||
decreaseLineHeightAction: { decreaseLineHeightActionID = UUID() },
|
||||
updateFontFamilyAction: { updateFontFamilyActionID = UUID() },
|
||||
updateFontAction: { updateFontActionID = UUID() },
|
||||
updateMarginAction: { updateMarginActionID = UUID() },
|
||||
updateLineHeightAction: { updateLineHeightActionID = UUID() },
|
||||
dismissAction: { showPreferencesPopover = false }
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Foundation
|
||||
import Models
|
||||
import Utils
|
||||
import Views
|
||||
|
||||
struct WebReaderContent {
|
||||
let textFontSize: Int
|
||||
|
|
@ -10,6 +11,7 @@ struct WebReaderContent {
|
|||
let highlightsJSONString: String
|
||||
let item: LinkedItem
|
||||
let themeKey: String
|
||||
let fontFamily: WebFont
|
||||
|
||||
init(
|
||||
htmlContent: String,
|
||||
|
|
@ -18,7 +20,8 @@ struct WebReaderContent {
|
|||
isDark: Bool,
|
||||
fontSize: Int,
|
||||
lineHeight: Int,
|
||||
margin: Int
|
||||
margin: Int,
|
||||
fontFamily: WebFont
|
||||
) {
|
||||
self.textFontSize = fontSize
|
||||
self.lineHeight = lineHeight
|
||||
|
|
@ -27,6 +30,7 @@ struct WebReaderContent {
|
|||
self.highlightsJSONString = highlightsJSONString
|
||||
self.item = item
|
||||
self.themeKey = isDark ? "Gray" : "LightGray"
|
||||
self.fontFamily = fontFamily
|
||||
}
|
||||
|
||||
// swiftlint:disable line_length
|
||||
|
|
@ -77,6 +81,7 @@ struct WebReaderContent {
|
|||
}
|
||||
|
||||
window.fontSize = \(textFontSize)
|
||||
window.fontFamily = "\(fontFamily.rawValue)"
|
||||
window.margin = \(margin)
|
||||
window.lineHeight = \(lineHeight)
|
||||
window.localStorage.setItem("theme", "\(themeKey)")
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@ final class WebReaderCoordinator: NSObject {
|
|||
var linkHandler: (URL) -> Void = { _ in }
|
||||
var needsReload = false
|
||||
var lastSavedAnnotationID: UUID?
|
||||
var previousIncreaseFontActionID: UUID?
|
||||
var previousDecreaseFontActionID: UUID?
|
||||
var previousIncreaseMarginActionID: UUID?
|
||||
var previousDecreaseMarginActionID: UUID?
|
||||
var previousIncreaseLineHeightActionID: UUID?
|
||||
var previousDecreaseLineHeightActionID: UUID?
|
||||
var previousUpdateFontFamilyActionID: UUID?
|
||||
var previousUpdateFontActionID: UUID?
|
||||
var previousUpdateMarginActionID: UUID?
|
||||
var previousUpdateLineHeightActionID: UUID?
|
||||
var previousShowNavBarActionID: UUID?
|
||||
var previousShareActionID: UUID?
|
||||
var updateNavBarVisibilityRatio: (Double) -> Void = { _ in }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Foundation
|
||||
|
||||
public enum UserDefaultKey: String {
|
||||
case preferredWebFont
|
||||
case preferredWebFontSize
|
||||
case preferredWebLineSpacing
|
||||
case preferredWebMargin
|
||||
|
|
|
|||
|
|
@ -95,17 +95,17 @@ public enum WebViewManager {
|
|||
|
||||
if annotationSaveTransactionID != context.coordinator.lastSavedAnnotationID {
|
||||
context.coordinator.lastSavedAnnotationID = annotationSaveTransactionID
|
||||
(webView as? WebView)?.saveAnnotation(annotation: annotation)
|
||||
(webView as? WebView)?.dispatchEvent(.saveAnnotation(annotation: annotation))
|
||||
}
|
||||
|
||||
if sendIncreaseFontSignal {
|
||||
sendIncreaseFontSignal = false
|
||||
(webView as? WebView)?.increaseFontSize()
|
||||
(webView as? WebView)?.updateFontSize()
|
||||
}
|
||||
|
||||
if sendDecreaseFontSignal {
|
||||
sendDecreaseFontSignal = false
|
||||
(webView as? WebView)?.decreaseFontSize()
|
||||
(webView as? WebView)?.updateFontSize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import Utils
|
||||
import WebKit
|
||||
|
||||
/// Describes actions that can be sent from the WebView back to native views.
|
||||
|
|
@ -26,41 +27,36 @@ public final class WebView: WKWebView {
|
|||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func increaseFontSize() {
|
||||
dispatchEvent("increaseFontSize")
|
||||
public func updateFontFamily() {
|
||||
if let fontFamily = UserDefaults.standard.value(forKey: UserDefaultKey.preferredWebFont.rawValue) as? String {
|
||||
dispatchEvent(.updateFontFamily(family: fontFamily))
|
||||
}
|
||||
}
|
||||
|
||||
public func decreaseFontSize() {
|
||||
dispatchEvent("decreaseFontSize")
|
||||
public func updateFontSize() {
|
||||
if let fontSize = UserDefaults.standard.value(forKey: UserDefaultKey.preferredWebFontSize.rawValue) as? Int {
|
||||
dispatchEvent(.updateFontSize(size: fontSize))
|
||||
}
|
||||
}
|
||||
|
||||
public func increaseMargin() {
|
||||
print("increase margin")
|
||||
dispatchEvent("increaseMargin")
|
||||
public func updateMargin() {
|
||||
if let margin = UserDefaults.standard.value(forKey: UserDefaultKey.preferredWebMargin.rawValue) as? Int {
|
||||
dispatchEvent(.updateMargin(width: margin))
|
||||
}
|
||||
}
|
||||
|
||||
public func decreaseMargin() {
|
||||
print("decrease margin")
|
||||
dispatchEvent("decreaseMargin")
|
||||
}
|
||||
|
||||
public func increaseLineHeight() {
|
||||
print("increase line height")
|
||||
dispatchEvent("increaseLineHeight")
|
||||
}
|
||||
|
||||
public func decreaseLineHeight() {
|
||||
print("decrease line height")
|
||||
dispatchEvent("decreaseLineHeight")
|
||||
public func updateLineHeight() {
|
||||
if let height = UserDefaults.standard.value(forKey: UserDefaultKey.preferredWebLineSpacing.rawValue) as? Int {
|
||||
dispatchEvent(.updateLineHeight(height: height))
|
||||
}
|
||||
}
|
||||
|
||||
public func shareOriginalItem() {
|
||||
dispatchEvent("share")
|
||||
dispatchEvent(.share)
|
||||
}
|
||||
|
||||
func dispatchEvent(_ name: String) {
|
||||
let dispatch = "document.dispatchEvent(new Event('\(name)'));"
|
||||
evaluateJavaScript(dispatch) { obj, err in
|
||||
public func dispatchEvent(_ event: WebViewDispatchEvent) {
|
||||
evaluateJavaScript(event.script) { obj, err in
|
||||
if let err = err { print(err) }
|
||||
if let obj = obj { print(obj) }
|
||||
}
|
||||
|
|
@ -70,12 +66,7 @@ public final class WebView: WKWebView {
|
|||
override public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||
super.traitCollectionDidChange(previousTraitCollection)
|
||||
guard previousTraitCollection?.userInterfaceStyle != traitCollection.userInterfaceStyle else { return }
|
||||
|
||||
if traitCollection.userInterfaceStyle == .dark {
|
||||
dispatchEvent("switchToDarkMode")
|
||||
} else {
|
||||
dispatchEvent("switchToLightMode")
|
||||
}
|
||||
dispatchEvent(.updateColorMode(isDark: traitCollection.userInterfaceStyle == .dark))
|
||||
}
|
||||
|
||||
#elseif os(macOS)
|
||||
|
|
@ -169,28 +160,28 @@ public final class WebView: WKWebView {
|
|||
}
|
||||
|
||||
@objc private func annotateSelection() {
|
||||
dispatchEvent("annotate")
|
||||
dispatchEvent(.annotate)
|
||||
hideMenu()
|
||||
}
|
||||
|
||||
@objc private func highlightSelection() {
|
||||
dispatchEvent("highlight")
|
||||
dispatchEvent(.highlight)
|
||||
hideMenu()
|
||||
}
|
||||
|
||||
@objc private func shareSelection() {
|
||||
dispatchEvent("share")
|
||||
dispatchEvent(.share)
|
||||
hideMenu()
|
||||
}
|
||||
|
||||
@objc private func removeSelection() {
|
||||
dispatchEvent("remove")
|
||||
dispatchEvent(.remove)
|
||||
hideMenu()
|
||||
}
|
||||
|
||||
@objc override public func copy(_ sender: Any?) {
|
||||
super.copy(sender)
|
||||
dispatchEvent("copyHighlight")
|
||||
dispatchEvent(.copyHighlight)
|
||||
hideMenu()
|
||||
}
|
||||
|
||||
|
|
@ -209,7 +200,7 @@ public final class WebView: WKWebView {
|
|||
|
||||
private func hideMenuAndDismissHighlight() {
|
||||
hideMenu()
|
||||
dispatchEvent("dismissHighlight")
|
||||
dispatchEvent(.dismissHighlight)
|
||||
}
|
||||
|
||||
private func showHighlightMenu(_ rect: CGRect) {
|
||||
|
|
@ -233,14 +224,72 @@ public final class WebView: WKWebView {
|
|||
|
||||
UIMenuController.shared.showMenu(from: self, rect: rect)
|
||||
}
|
||||
|
||||
public func saveAnnotation(annotation: String) {
|
||||
// swiftlint:disable:next line_length
|
||||
let dispatch = "var event = new Event('saveAnnotation');event.annotation = '\(annotation)';document.dispatchEvent(event);"
|
||||
evaluateJavaScript(dispatch) { obj, err in
|
||||
if let err = err { print(err) }
|
||||
if let obj = obj { print(obj) }
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public enum WebViewDispatchEvent {
|
||||
case updateLineHeight(height: Int)
|
||||
case updateMargin(width: Int)
|
||||
case updateFontSize(size: Int)
|
||||
case updateColorMode(isDark: Bool)
|
||||
case updateFontFamily(family: String)
|
||||
case saveAnnotation(annotation: String)
|
||||
case annotate
|
||||
case highlight
|
||||
case share
|
||||
case remove
|
||||
case copyHighlight
|
||||
case dismissHighlight
|
||||
|
||||
var script: String {
|
||||
"var event = new Event('\(eventName)');\(scriptPropertyLine)document.dispatchEvent(event);"
|
||||
}
|
||||
|
||||
private var eventName: String {
|
||||
switch self {
|
||||
case .updateLineHeight:
|
||||
return "updateLineHeight"
|
||||
case .updateMargin:
|
||||
return "updateMargin"
|
||||
case .updateFontSize:
|
||||
return "updateFontSize"
|
||||
case .updateColorMode:
|
||||
return "updateColorMode"
|
||||
case .updateFontFamily:
|
||||
return "updateFontFamily"
|
||||
case .saveAnnotation:
|
||||
return "saveAnnotation"
|
||||
case .annotate:
|
||||
return "annotate"
|
||||
case .highlight:
|
||||
return "highlight"
|
||||
case .share:
|
||||
return "share"
|
||||
case .remove:
|
||||
return "remove"
|
||||
case .copyHighlight:
|
||||
return "copyHighlight"
|
||||
case .dismissHighlight:
|
||||
return "dismissHighlight"
|
||||
}
|
||||
}
|
||||
|
||||
private var scriptPropertyLine: String {
|
||||
switch self {
|
||||
case let .updateLineHeight(height: height):
|
||||
return "event.lineHeight = '\(height)';"
|
||||
case let .updateMargin(width: width):
|
||||
return "event.margin = '\(width)';"
|
||||
case let .updateFontSize(size: size):
|
||||
return "event.fontSize = '\(size)';"
|
||||
case let .updateColorMode(isDark: isDark):
|
||||
return "event.isDarkMode = '\(isDark)';"
|
||||
case let .updateFontFamily(family: family):
|
||||
return "event.fontFamily = '\(family)';"
|
||||
case let .saveAnnotation(annotation: annotation):
|
||||
return "event.annotation = '\(annotation)';"
|
||||
case .annotate, .highlight, .share, .remove, .copyHighlight, .dismissHighlight:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
import SwiftUI
|
||||
import Utils
|
||||
|
||||
public enum WebFont: String, CaseIterable {
|
||||
case inter = "Inter"
|
||||
case merriweather = "Merriweather"
|
||||
case lyon = "Lyon"
|
||||
case sfmono = "SF Mono"
|
||||
case tisa = "Tisa"
|
||||
}
|
||||
|
||||
public struct WebPreferencesPopoverView: View {
|
||||
let increaseFontAction: () -> Void
|
||||
let decreaseFontAction: () -> Void
|
||||
let increaseMarginAction: () -> Void
|
||||
let decreaseMarginAction: () -> Void
|
||||
let increaseLineHeightAction: () -> Void
|
||||
let decreaseLineHeightAction: () -> Void
|
||||
let updateFontFamilyAction: () -> Void
|
||||
let updateFontAction: () -> Void
|
||||
let updateMarginAction: () -> Void
|
||||
let updateLineHeightAction: () -> Void
|
||||
let dismissAction: () -> Void
|
||||
|
||||
static let preferredWebFontSizeKey = UserDefaultKey.preferredWebFontSize.rawValue
|
||||
|
|
@ -19,29 +25,26 @@ public struct WebPreferencesPopoverView: View {
|
|||
|
||||
@AppStorage(UserDefaultKey.preferredWebLineSpacing.rawValue) var storedLineSpacing = 150
|
||||
@AppStorage(UserDefaultKey.preferredWebMargin.rawValue) var storedMargin = 360
|
||||
@AppStorage(UserDefaultKey.preferredWebFont.rawValue) var preferredFont = WebFont.inter.rawValue
|
||||
|
||||
public init(
|
||||
increaseFontAction: @escaping () -> Void,
|
||||
decreaseFontAction: @escaping () -> Void,
|
||||
increaseMarginAction: @escaping () -> Void,
|
||||
decreaseMarginAction: @escaping () -> Void,
|
||||
increaseLineHeightAction: @escaping () -> Void,
|
||||
decreaseLineHeightAction: @escaping () -> Void,
|
||||
updateFontFamilyAction: @escaping () -> Void,
|
||||
updateFontAction: @escaping () -> Void,
|
||||
updateMarginAction: @escaping () -> Void,
|
||||
updateLineHeightAction: @escaping () -> Void,
|
||||
dismissAction: @escaping () -> Void
|
||||
) {
|
||||
self.increaseFontAction = increaseFontAction
|
||||
self.decreaseFontAction = decreaseFontAction
|
||||
self.increaseMarginAction = increaseMarginAction
|
||||
self.decreaseMarginAction = decreaseMarginAction
|
||||
self.increaseLineHeightAction = increaseLineHeightAction
|
||||
self.decreaseLineHeightAction = decreaseLineHeightAction
|
||||
self.updateFontFamilyAction = updateFontFamilyAction
|
||||
self.updateFontAction = updateFontAction
|
||||
self.updateMarginAction = updateMarginAction
|
||||
self.updateLineHeightAction = updateLineHeightAction
|
||||
self.dismissAction = dismissAction
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
VStack(alignment: .center) {
|
||||
ZStack {
|
||||
Text("Preferences").font(.appTitleTwo)
|
||||
Text("Preferences").font(.appTitleThree)
|
||||
HStack {
|
||||
Spacer()
|
||||
Button(
|
||||
|
|
@ -50,47 +53,67 @@ public struct WebPreferencesPopoverView: View {
|
|||
)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
|
||||
LabelledStepper(
|
||||
labelText: "Font Size:",
|
||||
onIncrement: {
|
||||
storedFontSize = min(storedFontSize + 2, 28)
|
||||
increaseFontAction()
|
||||
},
|
||||
onDecrement: {
|
||||
storedFontSize = max(storedFontSize - 2, 10)
|
||||
decreaseFontAction()
|
||||
}
|
||||
)
|
||||
List {
|
||||
Section("Sizing") {
|
||||
LabelledStepper(
|
||||
labelText: "Font Size:",
|
||||
onIncrement: {
|
||||
storedFontSize = min(storedFontSize + 2, 28)
|
||||
updateFontAction()
|
||||
},
|
||||
onDecrement: {
|
||||
storedFontSize = max(storedFontSize - 2, 10)
|
||||
updateFontAction()
|
||||
}
|
||||
)
|
||||
|
||||
if UIDevice.isIPad {
|
||||
LabelledStepper(
|
||||
labelText: "Margin:",
|
||||
onIncrement: {
|
||||
storedMargin = min(storedMargin + 45, 560)
|
||||
increaseMarginAction()
|
||||
},
|
||||
onDecrement: {
|
||||
storedMargin = max(storedMargin - 45, 200)
|
||||
decreaseMarginAction()
|
||||
if UIDevice.isIPad {
|
||||
LabelledStepper(
|
||||
labelText: "Margin:",
|
||||
onIncrement: {
|
||||
storedMargin = min(storedMargin + 45, 560)
|
||||
updateMarginAction()
|
||||
},
|
||||
onDecrement: {
|
||||
storedMargin = max(storedMargin - 45, 200)
|
||||
updateMarginAction()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
LabelledStepper(
|
||||
labelText: "Line Spacing:",
|
||||
onIncrement: {
|
||||
storedLineSpacing = min(storedLineSpacing + 25, 300)
|
||||
increaseLineHeightAction()
|
||||
},
|
||||
onDecrement: {
|
||||
storedLineSpacing = max(storedLineSpacing - 25, 100)
|
||||
decreaseLineHeightAction()
|
||||
LabelledStepper(
|
||||
labelText: "Line Spacing:",
|
||||
onIncrement: {
|
||||
storedLineSpacing = min(storedLineSpacing + 25, 300)
|
||||
updateLineHeightAction()
|
||||
},
|
||||
onDecrement: {
|
||||
storedLineSpacing = max(storedLineSpacing - 25, 100)
|
||||
updateLineHeightAction()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
Spacer()
|
||||
Section("Font Family") {
|
||||
ForEach(WebFont.allCases, id: \.self) { font in
|
||||
Button(
|
||||
action: {
|
||||
preferredFont = font.rawValue
|
||||
updateFontFamilyAction()
|
||||
},
|
||||
label: {
|
||||
HStack {
|
||||
Text(font.rawValue).foregroundColor(.appGrayTextContrast)
|
||||
Spacer()
|
||||
if font.rawValue == preferredFont {
|
||||
Image(systemName: "checkmark").foregroundColor(.appGrayTextContrast)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import SwiftUI
|
|||
|
||||
func show() {
|
||||
guard hostVC == nil else { return }
|
||||
// WIP: use subclass to control a max height we pass in for iphone
|
||||
// let controller = FormSheetHostingController(rootView: content(), height: 100)
|
||||
let controller = UIHostingController(rootView: content())
|
||||
|
||||
if controller.traitCollection.userInterfaceIdiom == .phone {
|
||||
|
|
@ -94,9 +96,51 @@ import SwiftUI
|
|||
modalSize: CGSize = CGSize(width: 320, height: 320),
|
||||
@ViewBuilder content: @escaping () -> Content
|
||||
) -> some View {
|
||||
background(FormSheet(show: isPresented,
|
||||
modalSize: modalSize,
|
||||
content: content))
|
||||
background(
|
||||
FormSheet(
|
||||
show: isPresented,
|
||||
modalSize: modalSize,
|
||||
content: content
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
final class FormSheetHostingController<Content: View>: UIHostingController<Content> {
|
||||
let height: CGFloat
|
||||
|
||||
init(rootView: Content, height: CGFloat) {
|
||||
self.height = height
|
||||
super.init(rootView: rootView)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
@MainActor dynamic required init?(coder _: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func updateViewConstraints() {
|
||||
view.frame.size.height = UIScreen.main.bounds.height - height
|
||||
view.frame.origin.y = height
|
||||
view.roundCorners(corners: [.topLeft, .topRight], radius: 16.0)
|
||||
super.updateViewConstraints()
|
||||
}
|
||||
}
|
||||
|
||||
extension UIView {
|
||||
func roundCorners(corners: UIRectCorner, radius: CGFloat) {
|
||||
let path = UIBezierPath(
|
||||
roundedRect: bounds,
|
||||
byRoundingCorners: corners,
|
||||
cornerRadii:
|
||||
CGSize(
|
||||
width: radius,
|
||||
height: radius
|
||||
)
|
||||
)
|
||||
let mask = CAShapeLayer()
|
||||
mask.path = path.cgPath
|
||||
layer.mask = mask
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -41,6 +41,7 @@ const App = () => {
|
|||
highlightBarDisabled={true}
|
||||
highlightsBaseURL="https://example.com"
|
||||
fontSize={window.fontSize ?? 18}
|
||||
fontFamily={window.fontFamily ?? 'inter'}
|
||||
margin={window.margin}
|
||||
lineHeight={window.lineHeight}
|
||||
articleMutations={{
|
||||
|
|
|
|||
|
|
@ -84,44 +84,57 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
|
|||
|
||||
// Listen for preference change events sent from host apps (ios, macos...)
|
||||
useEffect(() => {
|
||||
const increaseLineHeight = () => {
|
||||
setLineHeightOverride(
|
||||
Math.min((lineHeightOverride ?? props.lineHeight ?? 150) + 25, 300)
|
||||
)
|
||||
interface UpdateLineHeightEvent extends Event {
|
||||
lineHeight?: number
|
||||
}
|
||||
|
||||
const decreaseLineHeight = () => {
|
||||
setLineHeightOverride(
|
||||
Math.max((lineHeightOverride ?? props.lineHeight ?? 150) - 25, 100)
|
||||
)
|
||||
const updateLineHeight = (event: UpdateLineHeightEvent) => {
|
||||
const newLineHeight = event.lineHeight ?? lineHeightOverride ?? 150
|
||||
if (newLineHeight >= 100 && newLineHeight <= 300) {
|
||||
setLineHeightOverride(newLineHeight)
|
||||
}
|
||||
}
|
||||
|
||||
const increaseMargin = () => {
|
||||
setMarginOverride(
|
||||
Math.min((marginOverride ?? props.margin ?? 360) + 45, 560)
|
||||
)
|
||||
interface UpdateMarginEvent extends Event {
|
||||
margin?: number
|
||||
}
|
||||
|
||||
const decreaseMargin = () => {
|
||||
setMarginOverride(
|
||||
Math.max((marginOverride ?? props.margin ?? 360) - 45, 200)
|
||||
)
|
||||
const updateMargin = (event: UpdateMarginEvent) => {
|
||||
const newMargin = event.margin ?? marginOverride ?? 360
|
||||
if (newMargin >= 200 && newMargin <= 560) {
|
||||
setMarginOverride(newMargin)
|
||||
}
|
||||
}
|
||||
|
||||
const increaseFontSize = async () => {
|
||||
await updateFontSize(Math.min(fontSize + 2, 28))
|
||||
interface UpdateFontFamilyEvent extends Event {
|
||||
fontFamily?: string
|
||||
}
|
||||
|
||||
const decreaseFontSize = async () => {
|
||||
await updateFontSize(Math.max(fontSize - 2, 10))
|
||||
const updateFontFamily = (event: UpdateFontFamilyEvent) => {
|
||||
const newFontFamily =
|
||||
event.fontFamily ?? fontFamilyOverride ?? props.fontFamily ?? 'inter'
|
||||
console.log('setting font fam to', event.fontFamily)
|
||||
setFontFamilyOverride(newFontFamily)
|
||||
}
|
||||
|
||||
const switchToDarkMode = () => {
|
||||
updateThemeLocally(ThemeId.Dark)
|
||||
interface UpdateFontSizeEvent extends Event {
|
||||
fontSize?: number
|
||||
}
|
||||
|
||||
const switchToLightMode = () => {
|
||||
updateThemeLocally(ThemeId.Light)
|
||||
const handleFontSizeChange = async (event: UpdateFontSizeEvent) => {
|
||||
const newFontSize = event.fontSize ?? 18
|
||||
if (newFontSize >= 10 && newFontSize <= 28) {
|
||||
updateFontSize(newFontSize)
|
||||
}
|
||||
}
|
||||
|
||||
interface UpdateColorModeEvent extends Event {
|
||||
isDark?: boolean
|
||||
}
|
||||
|
||||
const updateColorMode = (event: UpdateColorModeEvent) => {
|
||||
const isDark = event.isDark ?? false
|
||||
updateThemeLocally(isDark ? ThemeId.Dark : ThemeId.Light)
|
||||
}
|
||||
|
||||
const share = () => {
|
||||
|
|
@ -133,25 +146,19 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
|
|||
}
|
||||
}
|
||||
|
||||
document.addEventListener('increaseLineHeight', increaseLineHeight)
|
||||
document.addEventListener('decreaseLineHeight', decreaseLineHeight)
|
||||
document.addEventListener('increaseMargin', increaseMargin)
|
||||
document.addEventListener('decreaseMargin', decreaseMargin)
|
||||
document.addEventListener('increaseFontSize', increaseFontSize)
|
||||
document.addEventListener('decreaseFontSize', decreaseFontSize)
|
||||
document.addEventListener('switchToDarkMode', switchToDarkMode)
|
||||
document.addEventListener('switchToLightMode', switchToLightMode)
|
||||
document.addEventListener('updateFontFamily', updateFontFamily)
|
||||
document.addEventListener('updateLineHeight', updateLineHeight)
|
||||
document.addEventListener('updateMargin', updateMargin)
|
||||
document.addEventListener('updateFontSize', handleFontSizeChange)
|
||||
document.addEventListener('updateColorMode', updateColorMode)
|
||||
document.addEventListener('share', share)
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('increaseLineHeight', increaseLineHeight)
|
||||
document.removeEventListener('decreaseLineHeight', decreaseLineHeight)
|
||||
document.removeEventListener('increaseMargin', increaseMargin)
|
||||
document.removeEventListener('decreaseMargin', decreaseMargin)
|
||||
document.removeEventListener('increaseFontSize', increaseFontSize)
|
||||
document.removeEventListener('decreaseFontSize', decreaseFontSize)
|
||||
document.removeEventListener('switchToDarkMode', switchToDarkMode)
|
||||
document.removeEventListener('switchToLightMode', switchToLightMode)
|
||||
document.removeEventListener('updateFontFamily', updateFontFamily)
|
||||
document.removeEventListener('updateLineHeight', updateLineHeight)
|
||||
document.removeEventListener('updateMargin', updateMargin)
|
||||
document.removeEventListener('updateFontSize', handleFontSizeChange)
|
||||
document.removeEventListener('updateColorMode', updateColorMode)
|
||||
document.removeEventListener('share', share)
|
||||
}
|
||||
})
|
||||
|
|
@ -173,7 +180,7 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
|
|||
id="article-container"
|
||||
css={{
|
||||
padding: '16px',
|
||||
maxWidth: '100%',
|
||||
maxWidth: props.isAppleAppEmbed ? 1024 - styles.margin : '100%',
|
||||
background: props.isAppleAppEmbed
|
||||
? 'unset'
|
||||
: theme.colors.grayBg.toString(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue