单词列表页导航栏新增刷新按钮,支持随机重排单词顺序
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ struct WordCategory: Codable, Identifiable, Hashable {
|
||||
|
||||
struct Subcategory: Codable, Hashable {
|
||||
let name: String
|
||||
let words: [Word]
|
||||
var words: [Word]
|
||||
}
|
||||
|
||||
struct Word: Codable, Identifiable, Hashable {
|
||||
|
||||
@@ -3,14 +3,22 @@ import UIKit
|
||||
final class WordListViewController: UIViewController {
|
||||
private let category: WordCategory
|
||||
private let colorIndex: Int
|
||||
private var words: [Word]
|
||||
private var subcategories: [Subcategory]?
|
||||
private let tableView = UITableView(frame: .zero, style: .plain)
|
||||
private let ctaBackground = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial))
|
||||
private let quizButton = UIButton(type: .system)
|
||||
private var speechObserver: NSObjectProtocol?
|
||||
|
||||
private var displaySubcategories: [Subcategory]? {
|
||||
subcategories.flatMap { $0.isEmpty ? nil : $0 }
|
||||
}
|
||||
|
||||
init(category: WordCategory, colorIndex: Int) {
|
||||
self.category = category
|
||||
self.colorIndex = colorIndex
|
||||
self.words = category.words
|
||||
self.subcategories = category.subcategories
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
@@ -27,6 +35,12 @@ final class WordListViewController: UIViewController {
|
||||
super.viewDidLoad()
|
||||
title = category.name
|
||||
navigationItem.largeTitleDisplayMode = .never
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(
|
||||
image: UIImage(systemName: "arrow.triangle.2.circlepath"),
|
||||
style: .plain,
|
||||
target: self,
|
||||
action: #selector(shuffleWords)
|
||||
)
|
||||
view.backgroundColor = .systemBackground
|
||||
|
||||
tableView.dataSource = self
|
||||
@@ -119,16 +133,31 @@ final class WordListViewController: UIViewController {
|
||||
|
||||
private func startQuiz() {
|
||||
Haptics.selection()
|
||||
let words: [Word]
|
||||
let quizWords: [Word]
|
||||
if category.id == "numbers" {
|
||||
words = NumberWords.randomWords(count: 50)
|
||||
quizWords = NumberWords.randomWords(count: 50)
|
||||
} else {
|
||||
words = category.words
|
||||
quizWords = words
|
||||
}
|
||||
let request = QuizSetupRequest(words: words)
|
||||
let request = QuizSetupRequest(words: quizWords)
|
||||
navigationController?.pushViewController(QuizSetupViewController(request: request), animated: true)
|
||||
}
|
||||
|
||||
@objc private func shuffleWords() {
|
||||
Haptics.selection()
|
||||
if var subs = subcategories {
|
||||
subs = subs.map { sub in
|
||||
var s = sub
|
||||
s.words = sub.words.shuffled()
|
||||
return s
|
||||
}
|
||||
subcategories = subs
|
||||
} else {
|
||||
words.shuffle()
|
||||
}
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
private func updateVisibleSpeakers() {
|
||||
for cell in tableView.visibleCells.compactMap({ $0 as? WordCardCell }) {
|
||||
cell.updateSpeakerState()
|
||||
@@ -137,32 +166,28 @@ final class WordListViewController: UIViewController {
|
||||
}
|
||||
|
||||
extension WordListViewController: UITableViewDataSource, UITableViewDelegate {
|
||||
private var sections: [Subcategory]? {
|
||||
category.subcategories.flatMap { $0.isEmpty ? nil : $0 }
|
||||
}
|
||||
|
||||
func numberOfSections(in tableView: UITableView) -> Int {
|
||||
sections?.count ?? 1
|
||||
displaySubcategories?.count ?? 1
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
sections?[section].name
|
||||
displaySubcategories?[section].name
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if let sections {
|
||||
return sections[section].words.count
|
||||
if let subs = displaySubcategories {
|
||||
return subs[section].words.count
|
||||
}
|
||||
return category.words.count
|
||||
return words.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! WordCardCell
|
||||
let word: Word
|
||||
if let sections {
|
||||
word = sections[indexPath.section].words[indexPath.row]
|
||||
if let subs = displaySubcategories {
|
||||
word = subs[indexPath.section].words[indexPath.row]
|
||||
} else {
|
||||
word = category.words[indexPath.row]
|
||||
word = words[indexPath.row]
|
||||
}
|
||||
cell.configure(with: word)
|
||||
cell.onSpeak = { word in
|
||||
@@ -179,10 +204,10 @@ extension WordListViewController: UITableViewDataSource, UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
Haptics.selection()
|
||||
let word: Word
|
||||
if let sections {
|
||||
word = sections[indexPath.section].words[indexPath.row]
|
||||
if let subs = displaySubcategories {
|
||||
word = subs[indexPath.section].words[indexPath.row]
|
||||
} else {
|
||||
word = category.words[indexPath.row]
|
||||
word = words[indexPath.row]
|
||||
}
|
||||
let detail = WordDetailViewController(word: word, categoryName: category.name)
|
||||
navigationController?.pushViewController(detail, animated: true)
|
||||
|
||||
Reference in New Issue
Block a user