Skip to content

Commit

Permalink
Added the sort command
Browse files Browse the repository at this point in the history
  • Loading branch information
vincode-io committed Sep 14, 2024
1 parent 0418daa commit 52b47cb
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 7 deletions.
48 changes: 48 additions & 0 deletions VinOutlineKit/Sources/VinOutlineKit/Commands/SortRowsCommand.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// Created by Maurice Parker on 9/14/24.
//

import Foundation

public final class SortRowsCommand: OutlineCommand {

var rowMoves = [Outline.RowMove]()
var restoreMoves = [Outline.RowMove]()

public init(actionName: String,
undoManager: UndoManager,
delegate: OutlineCommandDelegate,
outline: Outline,
rows: [Row]) {

let displayOrderRows = rows.sortedByDisplayOrder()

for row in displayOrderRows {
guard let parent = row.parent, let index = parent.firstIndexOfRow(row) else { continue }
restoreMoves.append(Outline.RowMove(row: row, toParent: parent, toChildIndex: index))
}

let sortedRows = rows.sorted { left, right in
return (left.topic?.string ?? "").caseInsensitiveCompare(right.topic?.string ?? "") == .orderedAscending
}

let startIndex = displayOrderRows.first!.parent!.firstIndexOfRow(displayOrderRows.first!) ?? 0

for i in 0..<sortedRows.count {
let row = sortedRows[i]
guard let parent = row.parent else { continue }
rowMoves.append(Outline.RowMove(row: row, toParent: parent, toChildIndex: startIndex + i))
}

super.init(actionName: actionName, undoManager: undoManager, delegate: delegate, outline: outline)
}

public override func perform() {
outline.moveRows(rowMoves, rowStrings: nil)
}

public override func undo() {
outline.moveRows(restoreMoves, rowStrings: nil)
}

}
33 changes: 28 additions & 5 deletions VinOutlineKit/Sources/VinOutlineKit/Outline.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1565,14 +1565,37 @@ public final class Outline: RowContainer, Identifiable, Equatable, Hashable {
}

public func isGroupRowsUnavailable(rows: [Row]) -> Bool {
guard let parent = rows.first?.parent else { return true }
return !areRowsContiguous(rows: rows)
}

for row in rows {
if !parent.containsRow(row) {
return true
public func isSortRowsUnavailable(rows: [Row]) -> Bool {
guard rows.count > 1 else { return true }
return !areRowsContiguous(rows: rows)
}

func areRowsContiguous(rows: [Row]) -> Bool {
let sortedRows = rows.sortedByDisplayOrder()

guard let firstRow = sortedRows.first,
let parent = firstRow.parent,
let firstIndex = parent.firstIndexOfRow(firstRow) else {
return false
}

for i in 0..<sortedRows.count {
let row = sortedRows[i]
guard let index = parent.firstIndexOfRow(row) else {
return false
}

if index == firstIndex + i {
continue
} else {
return false
}
}
return false

return true
}

func createRow(_ row: Row, beforeRow: Row, rowStrings: RowStrings? = nil, moveCursor: Bool) {
Expand Down
3 changes: 3 additions & 0 deletions Zavala/AppAssets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ extension UIImage {

static let settings = UIImage(systemName: "gear")!
static let share = UIImage(systemName: "square.and.arrow.up")!
static let sortRows = UIImage(systemName: "arrow.up.arrow.down")!
static let sync = UIImage(systemName: "arrow.clockwise")!

static let topicFont = UIImage(systemName: "textformat.size.larger")!
Expand Down Expand Up @@ -350,6 +351,8 @@ extension String {
static let shareControlLabel = String(localized: "Share", comment: "Control Label: Share")
static let shareEllipsisControlLabel = String(localized: "Share…", comment: "Control Label: Share…")
static let smallControlLabel = String(localized: "Small", comment: "Control Label: Small")
static let sortRowControlLabel = String(localized: "Sort Row", comment: "Control Label: Sort Row")
static let sortRowsControlLabel = String(localized: "Sort Rows", comment: "Control Label: Sort Rows")
static let splitRowControlLabel = String(localized: "Split Row", comment: "Control Label: Split Row")
static let statisticsControlLabel = String(localized: "Statistics", comment: "Control Label: Statistics")
static let syncControlLabel = String(localized: "Sync", comment: "Control Label: Sync")
Expand Down
8 changes: 7 additions & 1 deletion Zavala/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate, FileActionResponder {

let groupCurrentRowsCommand = UIKeyCommand(title: .groupRowsControlLabel,
action: .groupCurrentRows,
input: "g",
input: "g",
modifierFlags: [.alternate, .command])

let sortCurrentRowsCommand = UIKeyCommand(title: .sortRowsControlLabel,
action: .sortCurrentRows,
input: "s",
modifierFlags: [.alternate, .command])

let duplicateRowsCommand = UIKeyCommand(title: .duplicateRowsControlLabel,
action: .duplicateCurrentRows,
input: "r",
Expand Down Expand Up @@ -560,6 +565,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, FileActionResponder {
createRowOutsideCommand,
duplicateRowsCommand,
groupCurrentRowsCommand,
sortCurrentRowsCommand,
deleteCurrentRowsCommand
])
let moveRowMenu = UIMenu(title: "", options: .displayInline, children: [moveRowsLeftCommand, moveRowsRightCommand, moveRowsUpCommand, moveRowsDownCommand])
Expand Down
41 changes: 40 additions & 1 deletion Zavala/Editor/EditorViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ extension Selector {
static let duplicateCurrentRows = #selector(EditorViewController.duplicateCurrentRows(_:))
static let deleteCurrentRows = #selector(EditorViewController.deleteCurrentRows(_:))
static let groupCurrentRows = #selector(EditorViewController.groupCurrentRows(_:))
static let sortCurrentRows = #selector(EditorViewController.sortCurrentRows(_:))
static let moveCurrentRowsLeft = #selector(EditorViewController.moveCurrentRowsLeft(_:))
static let moveCurrentRowsRight = #selector(EditorViewController.moveCurrentRowsRight(_:))
static let moveCurrentRowsUp = #selector(EditorViewController.moveCurrentRowsUp(_:))
Expand Down Expand Up @@ -610,6 +611,12 @@ class EditorViewController: UIViewController, DocumentsActivityItemsConfiguratio
} else {
return false
}
case .sortCurrentRows:
if let outline, let currentRows, !outline.isSortRowsUnavailable(rows: currentRows) {
return true
} else {
return false
}
case .moveCurrentRowsLeft:
if let outline, let currentRows, !outline.isMoveRowsLeftUnavailable(rows: currentRows) {
return true
Expand Down Expand Up @@ -665,6 +672,12 @@ class EditorViewController: UIViewController, DocumentsActivityItemsConfiguratio
} else {
command.title = .groupRowControlLabel
}
case .sortCurrentRows:
if currentRows?.count ?? 0 > 1 {
command.title = .sortRowsControlLabel
} else {
command.title = .sortRowControlLabel
}
case .deleteCurrentRows:
if currentRows?.count ?? 0 > 1 {
command.title = .deleteRowsControlLabel
Expand Down Expand Up @@ -1299,6 +1312,11 @@ class EditorViewController: UIViewController, DocumentsActivityItemsConfiguratio
groupRows(rows)
}

@objc func sortCurrentRows(_ sender: Any?) {
guard let rows = currentRows else { return }
sortRows(rows)
}

@objc func toggleCompleteRows(_ sender: Any?) {
guard let outline, let rows = currentRows else { return }
if !outline.isCompleteUnavailable(rows: rows) {
Expand Down Expand Up @@ -2811,7 +2829,10 @@ private extension EditorViewController {
}
if !outline.isGroupRowsUnavailable(rows: rows) {
outlineActions.append(self.groupAction(rows: rows))
6 }
}
if !outline.isSortRowsUnavailable(rows: rows) {
outlineActions.append(self.sortAction(rows: rows))
}
menuItems.append(UIMenu(title: "", options: .displayInline, children: outlineActions))

var viewActions = [UIAction]()
Expand Down Expand Up @@ -2941,6 +2962,13 @@ private extension EditorViewController {
}
}

func sortAction(rows: [Row]) -> UIAction {
let title = rows.count == 1 ? String.sortRowControlLabel : String.sortRowsControlLabel
return UIAction(title: title, image: .sortRows) { [weak self] action in
self?.sortCurrentRows(rows)
}
}

func moveCursorTo(row: Row) {
guard let shadowTableIndex = row.shadowTableIndex else {
return
Expand Down Expand Up @@ -3489,6 +3517,17 @@ private extension EditorViewController {
command.execute()
}

func sortRows(_ rows: [Row]) {
guard let undoManager, let outline else { return }

let command = SortRowsCommand(actionName: .groupRowsControlLabel,
undoManager: undoManager,
delegate: self,
outline: outline,
rows: rows)

command.execute()
}

func completeRows(_ rows: [Row], rowStrings: RowStrings? = nil) {
guard let undoManager, let outline else { return }
Expand Down
6 changes: 6 additions & 0 deletions Zavala/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,12 @@
"Small" : {
"comment" : "Control Label: Small"
},
"Sort Row" : {
"comment" : "Control Label: Sort Row"
},
"Sort Rows" : {
"comment" : "Control Label: Sort Rows"
},
"Split Row" : {
"comment" : "Control Label: Split Row"
},
Expand Down

0 comments on commit 52b47cb

Please sign in to comment.