Fix primary navigation editing
This commit is contained in:
20
TESTING.md
20
TESTING.md
@@ -590,16 +590,18 @@ source update are published, and installs or updates Gotcha through AltStore PAL
|
|||||||
## Settings, accessibility, and lifecycle
|
## Settings, accessibility, and lifecycle
|
||||||
|
|
||||||
- [ ] Settings opens from the gear button on Home and is not a tab.
|
- [ ] Settings opens from the gear button on Home and is not a tab.
|
||||||
- [ ] Home, Issues, Repositories, Pull Requests, Milestones, Actions, and Server
|
- [ ] Home, Issues, Repositories, Pull Requests, Milestones, and Actions use the
|
||||||
Activity use the destination name as the primary navigation title and the
|
destination name as the primary navigation title and the selected server
|
||||||
selected server as the smaller subtitle; changing servers updates both.
|
as the smaller subtitle; changing servers updates both.
|
||||||
- [ ] Primary Navigation always keeps Home first and allows up to four ordered,
|
- [ ] Primary Navigation always keeps Home first and allows up to four ordered,
|
||||||
unique choices from Issues, Repos, Pulls, Milestones, Actions, and Server
|
unique choices from Issues, Repos, Pulls, Milestones, and Actions. Server
|
||||||
Activity. Add, remove, and reorder destinations with native table
|
Activity remains only the **All users** Home timeline. Outside Edit mode,
|
||||||
controls; tab order updates immediately, omitted destinations remain on
|
rows cannot add, remove, or reorder destinations. In Edit mode, native
|
||||||
Home, and the configuration survives relaunch and server changes. An
|
insert, delete, and reorder controls perform all three operations; tab
|
||||||
upgrade from the previous build starts with Issues, Repos, Pulls, and
|
order updates immediately, omitted destinations remain on Home, and the
|
||||||
Milestones.
|
configuration survives relaunch and server changes. Existing saved
|
||||||
|
Server Activity tabs are removed during migration. An upgrade from the
|
||||||
|
previous build otherwise preserves its destination order.
|
||||||
- [ ] Appearance changes between Auto, Light, and Dark immediately; Auto follows
|
- [ ] Appearance changes between Auto, Light, and Dark immediately; Auto follows
|
||||||
the simulator system appearance.
|
the simulator system appearance.
|
||||||
- [ ] Icon and appearance settings remain selected after relaunch.
|
- [ ] Icon and appearance settings remain selected after relaunch.
|
||||||
|
|||||||
@@ -110,7 +110,10 @@ pub fn normalize_primary_destinations(destinations: &mut Vec<crate::PrimaryDesti
|
|||||||
let original = destinations.clone();
|
let original = destinations.clone();
|
||||||
let mut unique = Vec::with_capacity(destinations.len().min(4));
|
let mut unique = Vec::with_capacity(destinations.len().min(4));
|
||||||
for destination in destinations.drain(..) {
|
for destination in destinations.drain(..) {
|
||||||
if !unique.contains(&destination) && unique.len() < 4 {
|
if destination != crate::PrimaryDestination::ServerActivity
|
||||||
|
&& !unique.contains(&destination)
|
||||||
|
&& unique.len() < 4
|
||||||
|
{
|
||||||
unique.push(destination);
|
unique.push(destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,6 +259,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut destinations = vec![
|
let mut destinations = vec![
|
||||||
|
crate::PrimaryDestination::ServerActivity,
|
||||||
crate::PrimaryDestination::Actions,
|
crate::PrimaryDestination::Actions,
|
||||||
crate::PrimaryDestination::Actions,
|
crate::PrimaryDestination::Actions,
|
||||||
crate::PrimaryDestination::Issues,
|
crate::PrimaryDestination::Issues,
|
||||||
@@ -273,5 +277,6 @@ mod tests {
|
|||||||
crate::PrimaryDestination::PullRequests,
|
crate::PrimaryDestination::PullRequests,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
assert!(!destinations.contains(&crate::PrimaryDestination::ServerActivity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ final class AppContext {
|
|||||||
|
|
||||||
extension PrimaryDestination: CaseIterable {
|
extension PrimaryDestination: CaseIterable {
|
||||||
public static var allCases: [PrimaryDestination] {
|
public static var allCases: [PrimaryDestination] {
|
||||||
[.issues, .repositories, .pullRequests, .milestones, .actions, .serverActivity]
|
[.issues, .repositories, .pullRequests, .milestones, .actions]
|
||||||
}
|
}
|
||||||
|
|
||||||
var title: String {
|
var title: String {
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ final class NavigationSettingsViewController: UITableViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||||
section == 0 ? "Shown After Home" : "Available on Home"
|
section == 0 ? "Shown After Home" : "Available Destinations"
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||||
section == 0
|
section == 0
|
||||||
? "Choose up to four destinations. Tap Edit to reorder them. Home is always first."
|
? "Tap Edit to add, remove, or reorder up to four destinations. Home is always first."
|
||||||
: "Destinations not in the tab bar remain available as buttons on Home."
|
: "Destinations not in the tab bar remain available as buttons on Home."
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,19 +49,18 @@ final class NavigationSettingsViewController: UITableViewController {
|
|||||||
if indexPath.section == 1 && selected.count == 4 {
|
if indexPath.section == 1 && selected.count == 4 {
|
||||||
content.textProperties.color = .secondaryLabel
|
content.textProperties.color = .secondaryLabel
|
||||||
content.imageProperties.tintColor = .tertiaryLabel
|
content.imageProperties.tintColor = .tertiaryLabel
|
||||||
cell.selectionStyle = .none
|
|
||||||
} else if indexPath.section == 1 {
|
|
||||||
let add = UIImageView(image: UIImage(systemName: "plus.circle.fill"))
|
|
||||||
add.tintColor = .tintColor
|
|
||||||
cell.accessoryView = add
|
|
||||||
cell.accessibilityHint = "Adds this destination to the tab bar"
|
|
||||||
}
|
}
|
||||||
|
cell.selectionStyle = .none
|
||||||
cell.contentConfiguration = content
|
cell.contentConfiguration = content
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||||
|
tableView.isEditing && (indexPath.section == 0 || selected.count < 4)
|
||||||
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
|
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
|
||||||
indexPath.section == 0
|
tableView.isEditing && indexPath.section == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(
|
override func tableView(
|
||||||
@@ -93,7 +92,8 @@ final class NavigationSettingsViewController: UITableViewController {
|
|||||||
_ tableView: UITableView,
|
_ tableView: UITableView,
|
||||||
editingStyleForRowAt indexPath: IndexPath
|
editingStyleForRowAt indexPath: IndexPath
|
||||||
) -> UITableViewCell.EditingStyle {
|
) -> UITableViewCell.EditingStyle {
|
||||||
indexPath.section == 0 ? .delete : .none
|
if indexPath.section == 0 { return .delete }
|
||||||
|
return selected.count < 4 ? .insert : .none
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(
|
override func tableView(
|
||||||
@@ -101,18 +101,20 @@ final class NavigationSettingsViewController: UITableViewController {
|
|||||||
commit editingStyle: UITableViewCell.EditingStyle,
|
commit editingStyle: UITableViewCell.EditingStyle,
|
||||||
forRowAt indexPath: IndexPath
|
forRowAt indexPath: IndexPath
|
||||||
) {
|
) {
|
||||||
guard editingStyle == .delete, indexPath.section == 0 else { return }
|
switch (editingStyle, indexPath.section) {
|
||||||
|
case (.delete, 0):
|
||||||
selected.remove(at: indexPath.row)
|
selected.remove(at: indexPath.row)
|
||||||
|
case (.insert, 1) where selected.count < 4:
|
||||||
|
selected.append(available[indexPath.row])
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
save()
|
save()
|
||||||
tableView.reloadData()
|
tableView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
tableView.deselectRow(at: indexPath, animated: true)
|
tableView.deselectRow(at: indexPath, animated: true)
|
||||||
guard indexPath.section == 1, selected.count < 4 else { return }
|
|
||||||
selected.append(available[indexPath.row])
|
|
||||||
save()
|
|
||||||
tableView.reloadData()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func save() {
|
private func save() {
|
||||||
|
|||||||
Reference in New Issue
Block a user