Skip to content

Commit

Permalink
Implemented proper appearance support
Browse files Browse the repository at this point in the history
  • Loading branch information
michalrentka committed Feb 21, 2025
1 parent e8a774d commit 401bc37
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 15 deletions.
1 change: 0 additions & 1 deletion Zotero.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -4404,7 +4404,6 @@
B3593F142668D37900FA4BB2 /* Bundle Styles */,
B34A85AC243CB1E4003D5638 /* Bundle Translators */,
B3A1D03D2BA321B30040FEE9 /* Bundle Note Editor */,
61975C432D3A84F5005BB41A /* Fetch Bundled Fonts */,
B3052A912C412E12008C8596 /* Bundle Reader */,
B337A5AD244F229400AFD13D /* SwiftGen */,
B30D59512206F60400884C4A /* Sources */,
Expand Down
13 changes: 13 additions & 0 deletions Zotero/Models/Appearance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,17 @@ enum Appearance {
return .sepia
}
}

var htmlEpubValue: String {
switch self {
case .dark:
return "dark"

case .light:
return "light"

case .sepia:
return "sepia"
}
}
}
4 changes: 3 additions & 1 deletion Zotero/Scenes/Detail/HTML:EPUB/HtmlEpubCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ final class HtmlEpubCoordinator: ReaderCoordinator {
let parentNavigationController = parentCoordinator?.navigationController
else { return }

let settings = Defaults.shared.htmlEpubSettings
let handler = HtmlEpubReaderActionHandler(
dbStorage: dbStorage,
schemaController: controllers.schemaController,
Expand All @@ -81,7 +82,8 @@ final class HtmlEpubCoordinator: ReaderCoordinator {
settings: Defaults.shared.htmlEpubSettings,
libraryId: libraryId,
userId: userId,
username: username
username: username,
interfaceStyle: settings.appearance == .automatic ? parentNavigationController.view.traitCollection.userInterfaceStyle : settings.appearance.userInterfaceStyle
)
let controller = HtmlEpubReaderViewController(
viewModel: ViewModel(initialState: state, handler: handler),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ enum HtmlEpubReaderAction {
case showAnnotationPopover(key: String, rect: CGRect)
case toggleTool(AnnotationTool)
case updateAnnotationProperties(key: String, color: String, lineWidth: CGFloat, pageLabel: String, updateSubsequentLabels: Bool, highlightText: NSAttributedString)
case userInterfaceStyleChanged(UIUserInterfaceStyle)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct HtmlEpubReaderState: ViewModelState {
static let md5 = Changes(rawValue: 1 << 11)
static let library = Changes(rawValue: 1 << 12)
static let outline = Changes(rawValue: 1 << 13)
static let appearance = Changes(rawValue: 1 << 14)
}

struct DocumentData {
Expand Down Expand Up @@ -137,8 +138,9 @@ struct HtmlEpubReaderState: ViewModelState {
var deletionEnabled: Bool
var outlines: [Outline]
var outlineSearch: String
var interfaceStyle: UIUserInterfaceStyle

init(url: URL, key: String, parentKey: String?, title: String?, settings: HtmlEpubSettings, libraryId: LibraryIdentifier, userId: Int, username: String) {
init(url: URL, key: String, parentKey: String?, title: String?, settings: HtmlEpubSettings, libraryId: LibraryIdentifier, userId: Int, username: String, interfaceStyle: UIUserInterfaceStyle) {
let originalFile = Files.file(from: url)
let temporaryDirectory = Files.tmpReaderDirectory
self.originalFile = originalFile
Expand All @@ -150,6 +152,7 @@ struct HtmlEpubReaderState: ViewModelState {
self.settings = settings
self.userId = userId
self.username = username
self.interfaceStyle = interfaceStyle
sortedKeys = []
annotations = [:]
comments = [:]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ final class HtmlEpubReaderActionHandler: ViewModelActionHandler, BackgroundDbPro
case .setSettings(let settings):
set(settings: settings, in: viewModel)

case .userInterfaceStyleChanged(let userInterface):
userInterfaceChanged(interfaceStyle: userInterface, in: viewModel)

case .changeIdleTimerDisabled(let disabled):
if disabled {
idleTimerController.startCustomIdleTimer()
Expand Down Expand Up @@ -191,12 +194,26 @@ final class HtmlEpubReaderActionHandler: ViewModelActionHandler, BackgroundDbPro

private func set(settings: HtmlEpubSettings, in viewModel: ViewModel<HtmlEpubReaderActionHandler>) {
update(viewModel: viewModel) { state in
if state.settings.appearance != settings.appearance {
state.changes = .appearance
}
state.settings = settings
state.changes = .settings
state.changes.insert(.settings)
}
Defaults.shared.htmlEpubSettings = settings
}

private func userInterfaceChanged(interfaceStyle: UIUserInterfaceStyle, in viewModel: ViewModel<HtmlEpubReaderActionHandler>) {
// Always update interface style so that we have current value when `automatic` is selected
update(viewModel: viewModel) { state in
state.interfaceStyle = interfaceStyle
}
guard viewModel.state.settings.appearance == .automatic else { return }
update(viewModel: viewModel) { state in
state.changes = .appearance
}
}

private func removeAnnotation(key: String, in viewModel: ViewModel<HtmlEpubReaderActionHandler>) {
if viewModel.state.selectedAnnotationKey == key {
update(viewModel: viewModel) { state in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ class HtmlEpubDocumentViewController: UIViewController {
}
}

if state.changes.contains(.appearance) {
updateInterface(to: state.settings.appearance, userInterfaceStyle: state.interfaceStyle)
}

func search(term: String) {
webViewHandler.call(javascript: "search({ term: \(WebViewEncoder.encodeForJavascript(term.data(using: .utf8))) });")
.observe(on: MainScheduler.instance)
Expand Down Expand Up @@ -187,6 +191,21 @@ class HtmlEpubDocumentViewController: UIViewController {
}
}

private func updateInterface(to appearanceMode: ReaderSettingsState.Appearance, userInterfaceStyle: UIUserInterfaceStyle) {
switch appearanceMode {
case .automatic:
webView.overrideUserInterfaceStyle = userInterfaceStyle

case .light, .sepia:
webView.overrideUserInterfaceStyle = .light

case .dark:
webView.overrideUserInterfaceStyle = .dark
}
let appearanceString = Appearance.from(appearanceMode: appearanceMode, interfaceStyle: userInterfaceStyle).htmlEpubValue
webView.call(javascript: "window._view.setColorScheme('\(appearanceString)');").subscribe().disposed(by: disposeBag)
}

private func set(tool data: (AnnotationTool, UIColor)?) {
guard let (tool, color) = data else {
webViewHandler.call(javascript: "clearTool();").subscribe().disposed(by: disposeBag)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class HtmlEpubReaderViewController: UIViewController, ParentWithSidebarControlle
setupNavigationBar()
setupSearch()
setupViews()
navigationController?.overrideUserInterfaceStyle = viewModel.state.settings.appearance.userInterfaceStyle
updateInterface(to: viewModel.state.settings)
navigationItem.rightBarButtonItems = createRightBarButtonItems()

func observeViewModel() {
Expand Down Expand Up @@ -293,8 +293,8 @@ class HtmlEpubReaderViewController: UIViewController, ParentWithSidebarControlle
select(activeTool: state.activeTool)
}

if state.changes.contains(.settings) {
navigationController?.overrideUserInterfaceStyle = state.settings.appearance.userInterfaceStyle
if state.changes.contains(.appearance) {
updateInterface(to: state.settings)
}

if state.changes.contains(.md5) {
Expand Down Expand Up @@ -388,6 +388,19 @@ class HtmlEpubReaderViewController: UIViewController, ParentWithSidebarControlle

// MARK: - Actions

private func updateInterface(to settings: HtmlEpubSettings) {
switch settings.appearance {
case .automatic:
navigationController?.overrideUserInterfaceStyle = .unspecified

case .light, .sepia:
navigationController?.overrideUserInterfaceStyle = .light

case .dark:
navigationController?.overrideUserInterfaceStyle = .dark
}
}

private func toggleSidebar(animated: Bool) {
toggleSidebar(animated: animated, sidebarButtonTag: NavigationBarButton.sidebar.rawValue)
}
Expand Down
2 changes: 1 addition & 1 deletion Zotero/Scenes/Detail/PDF/Models/PDFReaderAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ enum PDFReaderAction {
case export(includeAnnotations: Bool)
case clearTmpData
case setSidebarEditingEnabled(Bool)
case setSettings(settings: PDFSettings, parentUserInterfaceStyle: UIUserInterfaceStyle)
case setSettings(settings: PDFSettings)
case changeIdleTimerDisabled(Bool)
case changeFilter(AnnotationsFilter?)
case submitPendingPage(Int)
Expand Down
11 changes: 7 additions & 4 deletions Zotero/Scenes/Detail/PDF/ViewModels/PDFReaderActionHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ final class PDFReaderActionHandler: ViewModelActionHandler, BackgroundDbProcessi
// Clear page thumbnails
pdfThumbnailController.deleteAll(forKey: viewModel.state.key, libraryId: viewModel.state.library.identifier)

case .setSettings(let settings, let userInterfaceStyle):
update(settings: settings, parentInterfaceStyle: userInterfaceStyle, in: viewModel)
case .setSettings(let settings):
update(settings: settings, in: viewModel)

case .changeIdleTimerDisabled(let disabled):
changeIdleTimer(disabled: disabled)
Expand All @@ -273,10 +273,13 @@ final class PDFReaderActionHandler: ViewModelActionHandler, BackgroundDbProcessi
// MARK: - Appearance changes

private func userInterfaceChanged(interfaceStyle: UIUserInterfaceStyle, in viewModel: ViewModel<PDFReaderActionHandler>) {
// Always update interface style so that we have current value when `automatic` is selected
update(viewModel: viewModel) { state in
state.interfaceStyle = interfaceStyle
}
guard viewModel.state.settings.appearanceMode == .automatic else { return }
updateAnnotations(to: .from(appearanceMode: .automatic, interfaceStyle: interfaceStyle), in: viewModel)
update(viewModel: viewModel) { state in
state.interfaceStyle = interfaceStyle
state.changes = .appearance
}
}
Expand Down Expand Up @@ -488,7 +491,7 @@ final class PDFReaderActionHandler: ViewModelActionHandler, BackgroundDbProcessi
}
}

private func update(settings: PDFSettings, parentInterfaceStyle: UIUserInterfaceStyle, in viewModel: ViewModel<PDFReaderActionHandler>) {
private func update(settings: PDFSettings, in viewModel: ViewModel<PDFReaderActionHandler>) {
let appearanceDidChange = settings.appearanceMode != viewModel.state.settings.appearanceMode
// Update local state
update(viewModel: viewModel) { state in
Expand Down
4 changes: 2 additions & 2 deletions Zotero/Scenes/Detail/PDF/Views/PDFReaderViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ class PDFReaderViewController: UIViewController, ParentWithSidebarController {
settingsViewModel.stateObservable
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] state in
guard let self, let interfaceStyle = presentingViewController?.traitCollection.userInterfaceStyle else { return }
guard let self else { return }
let settings = PDFSettings(
transition: state.transition,
pageMode: state.pageMode,
Expand All @@ -589,7 +589,7 @@ class PDFReaderViewController: UIViewController, ParentWithSidebarController {
appearanceMode: state.appearance,
isFirstPageAlwaysSingle: state.isFirstPageAlwaysSingle
)
viewModel.process(action: .setSettings(settings: settings, parentUserInterfaceStyle: interfaceStyle))
viewModel.process(action: .setSettings(settings: settings))
})
.disposed(by: disposeBag)
}
Expand Down
2 changes: 1 addition & 1 deletion reader

0 comments on commit 401bc37

Please sign in to comment.