Make already selected option in dropdown greyed out, and fixes for settings/defaults. #33

Merged
vegardbm merged 1 commits from mark-selected into master 2026-07-30 23:44:00 +02:00
+120 -57
View File
@@ -48,6 +48,7 @@ struct GlobalState: Codable {
struct LocalState: Codable {
var progress: ReadProgress
var backgroundColor: String?
var useDefaultPageTurnMode: Bool
}
struct Settings: Codable {
@@ -73,9 +74,10 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
var imageView = UIImageView()
var mode = PageTurnMode.leftToRight
var useDefaultPageTurnMode = true
var useDefaultBackgroundColor = true
var metadataList: [URL: Metadata] = [:]
var metadata: Metadata!
var currentPage: Int!
var progress = ProgressIndices(v: 0, c: 0, i: 0)
var currentPath: URL!
var lastLayoutSize: CGSize = .zero
@@ -331,29 +333,25 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
}
func convertColorToString(_ color: UIColor) -> String {
let r: String!
switch color {
case .white: r = "White"
case .gray: r = "Gray"
case .black: r = "Black"
case .red: r = "Red"
case .blue: r = "Blue"
default: r = "Black"
case .white: return "White"
case .gray: return "Gray"
case .black: return "Black"
case .red: return "Red"
case .blue: return "Blue"
default: return "Black"
}
return r
}
func convertStringToColor(_ str: String) -> UIColor {
let r: UIColor!
switch str.lowercased() {
case "white": r = .white
case "gray": r = .gray
case "black": r = .black
case "red": r = .red
case "blue": r = .blue
default: r = .black
case "white": return .white
case "gray": return .gray
case "black": return .black
case "red": return .red
case "blue": return .blue
default: return .black
}
return r
}
func imageSize(at url: URL) -> CGSize? {
@@ -786,7 +784,8 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
do {
try JSONEncoder().encode(
LocalState(
progress: newProgress, backgroundColor: self.convertColorToString(color)
progress: newProgress, backgroundColor: self.convertColorToString(color),
useDefaultPageTurnMode: self.useDefaultPageTurnMode
)
).write(
to: self.currentPath.appendingPathComponent("state.json")
@@ -802,22 +801,23 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
let path = currentPath.appendingPathComponent("state.json").path
if !fileManager.fileExists(atPath: path) {
progress = ProgressIndices(v: 0, c: 0, i: 0)
mode = .leftToRight
mode = settings.defaultPageTurnMode
return
}
let json = try Data(String(contentsOfFile: path).utf8)
let local = try JSONDecoder().decode(LocalState.self, from: json)
useDefaultPageTurnMode = local.useDefaultPageTurnMode
switch local.progress {
case let .leftToRight(volumeIndex, chapterIndex, imageIndex):
progress.v = volumeIndex
progress.c = chapterIndex
progress.i = imageIndex
mode = .leftToRight
mode = useDefaultPageTurnMode ? settings.defaultPageTurnMode : .leftToRight
case let .rightToLeft(volumeIndex, chapterIndex, imageIndex):
progress.v = volumeIndex
progress.c = chapterIndex
progress.i = imageIndex
mode = .rightToLeft
mode = useDefaultPageTurnMode ? settings.defaultPageTurnMode : .rightToLeft
case let .scroll(point):
if scrollPos == nil {
scrollPos = point
@@ -836,12 +836,14 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
progress = theProgress
}
}
mode = .scroll
mode = useDefaultPageTurnMode ? settings.defaultPageTurnMode : .scroll
}
if let color = local.backgroundColor {
readerView.backgroundColor = convertStringToColor(color)
useDefaultBackgroundColor = false
} else {
readerView.backgroundColor = convertStringToColor(settings.defaultReadingBackgroundColor)
useDefaultBackgroundColor = true
}
} catch let decodingError as DecodingError {
print(decodingError.errorDescription!)
@@ -2046,6 +2048,7 @@ struct SettingsMenuItem {
let title: String
let children: [SettingsMenuItem]? // non-nil = pushes another menu
let action: (() -> Void)? // non-nil = leaf, performs an action
let selected: (() -> Bool)?
}
class SettingsMenuViewController: UITableViewController {
@@ -2065,7 +2068,12 @@ class SettingsMenuViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
preferredContentSize = CGSize(width: 220, height: items.count * 44)
preferredContentSize = CGSize(width: 330, height: items.count * 44)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
override func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
@@ -2078,9 +2086,25 @@ class SettingsMenuViewController: UITableViewController {
cell.textLabel?.text = item.title
cell.accessoryType = item.children != nil ? .disclosureIndicator : .none
let isCurrent = item.selected?() ?? false
if isCurrent {
cell.textLabel?.textColor = .gray
cell.accessoryType = .checkmark
cell.selectionStyle = .none
} else {
cell.accessoryType = item.children != nil ? .disclosureIndicator : .none
cell.selectionStyle = .default
}
return cell
}
override func tableView(_: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
let item = items[indexPath.row]
return (item.selected?() == true) ? nil : indexPath
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = items[indexPath.row]
if let children = item.children {
@@ -2093,52 +2117,88 @@ class SettingsMenuViewController: UITableViewController {
}
}
func convertPageTurnModeToString(_ pageTurnMode: PageTurnMode) -> String {
switch pageTurnMode {
case .leftToRight: return "Left to Right"
case .rightToLeft: return "Right to Left"
case .scroll: return "Scroll"
}
}
extension ViewController {
private func colorItems(applyTo colorHandler: @escaping (UIColor) -> Void) -> [SettingsMenuItem] {
let items: [(String, UIColor)] = [("Black", .black), ("White", .white), ("Red", .red), ("Blue", .blue)]
return items.map { name, color in
SettingsMenuItem(title: name, children: nil, action: { [weak self] in
let items: [UIColor] = [.black, .white, .red, .blue]
return items.map { color in
SettingsMenuItem(title: convertColorToString(color), children: nil, action: { [weak self] in
colorHandler(color)
self?.dismiss(animated: false)
})
},
selected: { [weak self] in self?.readerView.backgroundColor == color })
}
}
private func colorDefaultItems(applyTo colorHandler: @escaping (UIColor) -> Void) -> [SettingsMenuItem] {
let items: [(String, UIColor)] = [
("Black", .black), ("White", .white), ("Red", .red), ("Blue", .blue),
("Default", convertStringToColor(settings.defaultReadingBackgroundColor)),
]
return items.map { name, color in
SettingsMenuItem(title: name, children: nil, action: { [weak self] in
colorHandler(color)
self?.dismiss(animated: false)
})
let items: [UIColor?] = [.black, .white, .red, .blue, nil]
return items.map { color in
var title = ""
if let color = color {
title = convertColorToString(color)
} else {
title = "Default (\(settings.defaultReadingBackgroundColor))"
}
return SettingsMenuItem(
title: title,
children: nil, action: { [self] in
self.useDefaultBackgroundColor = color == nil
colorHandler(color ?? self.convertStringToColor(settings.defaultReadingBackgroundColor))
self.dismiss(animated: false)
}, selected: { [self] in
if self.useDefaultBackgroundColor { return color == nil }
return color == self.readerView.backgroundColor && color != nil
}
)
}
}
private func pageTurnItems(applyTo pageTurnHandler: @escaping (PageTurnMode) -> Void) -> [SettingsMenuItem] {
let items: [(String, PageTurnMode)] = [
("Left to right", .leftToRight), ("Right to left", .rightToLeft), ("Scroll", .scroll),
]
return items.map { name, pageTurnMode in
SettingsMenuItem(title: name, children: nil, action: { [weak self] in
pageTurnHandler(pageTurnMode)
self?.dismiss(animated: false)
})
let items: [PageTurnMode] = [.leftToRight, .rightToLeft, .scroll]
return items.map { pageTurnMode in
SettingsMenuItem(
title: convertPageTurnModeToString(pageTurnMode),
children: nil,
action: { [self] in
pageTurnHandler(pageTurnMode)
self.dismiss(animated: false)
},
selected: { [self] in
return self.mode == pageTurnMode
}
)
}
}
private func pageTurnDefaultItems(applyTo pageTurnHandler: @escaping (PageTurnMode) -> Void) -> [SettingsMenuItem] {
let items: [(String, PageTurnMode)] = [
("Left to right", .leftToRight), ("Right to left", .rightToLeft), ("Scroll", .scroll),
("Default", settings.defaultPageTurnMode),
]
return items.map { name, pageTurnMode in
SettingsMenuItem(title: name, children: nil, action: { [weak self] in
pageTurnHandler(pageTurnMode)
self?.dismiss(animated: false)
})
let items: [PageTurnMode?] = [.leftToRight, .rightToLeft, .scroll, nil]
return items.map { pageTurnMode in
var title = ""
if let mode = pageTurnMode {
title = convertPageTurnModeToString(mode)
} else {
title = "Default (\(convertPageTurnModeToString(settings.defaultPageTurnMode)))"
}
return SettingsMenuItem(
title: title,
children: nil, action: { [self] in
self.useDefaultPageTurnMode = pageTurnMode == nil
let mode = pageTurnMode ?? self.settings.defaultPageTurnMode
pageTurnHandler(mode)
self.dismiss(animated: false)
},
selected: { [self] in
if self.useDefaultPageTurnMode { return pageTurnMode == nil }
return self.mode == pageTurnMode && pageTurnMode != nil
}
)
}
}
@@ -2161,12 +2221,14 @@ extension ViewController {
SettingsMenuItem(
title: "Background Reading",
children: defaultReadingBackgroundColor,
action: nil
action: nil,
selected: nil
),
SettingsMenuItem(title: "Background Home", children: backgroundColors, action: nil),
], action: nil)
SettingsMenuItem(title: "Background Home", children: backgroundColors, action: nil, selected: nil),
], action: nil, selected: nil)
let pageTurnMenu = SettingsMenuItem(title: "Page Turn Mode", children: defaultPageTurnMode, action: nil)
let pageTurnMenu = SettingsMenuItem(title: "Page Turn Mode",
children: defaultPageTurnMode, action: nil, selected: nil)
return [colorsMenu, pageTurnMenu]
}
@@ -2201,6 +2263,7 @@ extension ViewController {
private func makeBackgroundColorTree() -> [SettingsMenuItem] {
return colorDefaultItems { [weak self] color in
self?.readerView.backgroundColor = color
self?.saveLocalState()
}
}
}