Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ once the version tag exists.
for a pdf page as it does for a document.
- The search button leaves the tool bar when the page cannot be searched,
rather than greying out - the same as the edit button.
- The pencil turns into a save button while editing, as on Android. Saving from
the bar ends the edit and shows what was written; a save that failed stays in
it. Saving has left the menu; discarding is still there and now leaves edit
mode.

### Known issues

- Tapping a document sets no cursor, so edit mode cannot be typed into. The
cause is in odrcore; `EditWorkflowTests` pins it until the fix ships.

### Fixed

Expand Down
4 changes: 4 additions & 0 deletions OpenDocumentReader.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
E26C39392250DC6E009C484A /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E26C39382250DC6E009C484A /* WebKit.framework */; };
E2A17B0400000000000000A4 /* PageTabBarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2A17B0300000000000000A3 /* PageTabBarTests.swift */; };
E2A17B0500000000000000A5 /* DeclaredDocumentTypesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2A17B0600000000000000A6 /* DeclaredDocumentTypesTests.swift */; };
E2A17B0700000000000000A7 /* EditWorkflowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2A17B0800000000000000A8 /* EditWorkflowTests.swift */; };
E2A17B1000000000000000B0 /* test.ods in Resources */ = {isa = PBXBuildFile; fileRef = E2A17B1200000000000000B2 /* test.ods */; };
E2A17B1100000000000000B1 /* test.odp in Resources */ = {isa = PBXBuildFile; fileRef = E2A17B1300000000000000B3 /* test.odp */; };
E2A17B1400000000000000B4 /* test.csv in Resources */ = {isa = PBXBuildFile; fileRef = E2A17B1500000000000000B5 /* test.csv */; };
Expand Down Expand Up @@ -66,6 +67,7 @@
E26C39382250DC6E009C484A /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
E2A17B0300000000000000A3 /* PageTabBarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageTabBarTests.swift; sourceTree = "<group>"; };
E2A17B0600000000000000A6 /* DeclaredDocumentTypesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeclaredDocumentTypesTests.swift; sourceTree = "<group>"; };
E2A17B0800000000000000A8 /* EditWorkflowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditWorkflowTests.swift; sourceTree = "<group>"; };
E2A17B1200000000000000B2 /* test.ods */ = {isa = PBXFileReference; lastKnownFileType = file; path = test.ods; sourceTree = "<group>"; };
E2A17B1300000000000000B3 /* test.odp */ = {isa = PBXFileReference; lastKnownFileType = file; path = test.odp; sourceTree = "<group>"; };
E2A17B1500000000000000B5 /* test.csv */ = {isa = PBXFileReference; lastKnownFileType = text; path = test.csv; sourceTree = "<group>"; };
Expand Down Expand Up @@ -174,6 +176,7 @@
E22B252E2557F0E2001D0C52 /* OpenDocumentReaderTests.swift */,
E2A17B0300000000000000A3 /* PageTabBarTests.swift */,
E2A17B0600000000000000A6 /* DeclaredDocumentTypesTests.swift */,
E2A17B0800000000000000A8 /* EditWorkflowTests.swift */,
E22B25302557F0E2001D0C52 /* Info.plist */,
);
path = OpenDocumentReaderTests;
Expand Down Expand Up @@ -392,6 +395,7 @@
E22B252F2557F0E2001D0C52 /* OpenDocumentReaderTests.swift in Sources */,
E2A17B0400000000000000A4 /* PageTabBarTests.swift in Sources */,
E2A17B0500000000000000A5 /* DeclaredDocumentTypesTests.swift in Sources */,
E2A17B0700000000000000A7 /* EditWorkflowTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
53 changes: 37 additions & 16 deletions OpenDocumentReader/DocumentViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ class DocumentViewController: UIViewController, DocumentDelegate, UISearchBarDel
/// Whether the document on screen can be edited and searched. Neither button
/// stays in the bar when it cannot be used.
private var canEdit = false { didSet { updateToolBar() } }
/// The same slot the pencil sits in, showing the way out of the edit it
/// started — as on OpenDocument.droid, where edit mode replaces the bar
/// rather than emptying it.
private var isEditingDocument = false { didSet { updateEditButtonRole() } }
private var canSearch = false {
didSet {
updateToolBar()
Expand Down Expand Up @@ -176,7 +180,7 @@ class DocumentViewController: UIViewController, DocumentDelegate, UISearchBarDel
// the chevron says where it goes; the words are for VoiceOver, which is
// the one reader a glyph is no shorter for
barButtonItem.accessibilityLabel = NSLocalizedString("back_to_documents", comment: "")
editButton.accessibilityLabel = NSLocalizedString("menu_edit", comment: "")
updateEditButtonRole()

// nothing is editable or searchable until a page says so
updateToolBar()
Expand Down Expand Up @@ -413,8 +417,21 @@ class DocumentViewController: UIViewController, DocumentDelegate, UISearchBarDel
findAll(searchText: searchText)
}

@IBAction func editButton(_ sender: UIBarButtonItem) {
editDocument()
/// One button, both ways: the pencil starts an edit and the save glyph ends
/// it. See ``updateEditButtonRole()``.
@IBAction func editOrSave(_ sender: UIBarButtonItem) {
if isEditingDocument {
// the file holds the edit once it is written, so leaving edit mode
// reads back what was saved. A save that failed stays in the edit,
// which is the only place that text still exists.
saveContent { success in
guard success else { return }

self.document?.edit = false
}
} else {
editDocument()
}
}

private func updateToolBar() {
Expand All @@ -430,10 +447,19 @@ class DocumentViewController: UIViewController, DocumentDelegate, UISearchBarDel
}
}

/// Offered for the documents that can be edited, and only while they are not
/// being edited already.
/// Offered for the documents that can be edited, whether or not one is being
/// edited right now — the button is the way both into an edit and out of it.
private func updateEditButton() {
canEdit = (document?.isEditable ?? false) && !(document?.edit ?? false)
canEdit = document?.isEditable ?? false
isEditingDocument = document?.edit ?? false
}

/// A pencil to start an edit, and the save glyph to write one. The label goes
/// with it: VoiceOver reads that, not the glyph.
private func updateEditButtonRole() {
editButton.image = UIImage(systemName: isEditingDocument ? "square.and.arrow.down" : "pencil")
editButton.accessibilityLabel = NSLocalizedString(
isEditingDocument ? "action_edit_save" : "menu_edit", comment: "")
}

/// Asked of the page rather than guessed from the format: odrcore writes the
Expand Down Expand Up @@ -545,19 +571,12 @@ class DocumentViewController: UIViewController, DocumentDelegate, UISearchBarDel
@IBAction func showMenu(_ sender: Any) {
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

// editing is not in here: it is the pencil in the bar
// neither editing nor saving is in here: both are the one button in the bar

if document?.edit ?? false {
alert.addAction(
UIAlertAction(
title: NSLocalizedString("action_edit_save", comment: ""), style: .default,
handler: { (_) in
self.saveContent(completion: nil)
}))

alert.addAction(
UIAlertAction(
title: NSLocalizedString("menu_discard_changes", comment: ""), style: .default,
title: NSLocalizedString("menu_discard_changes", comment: ""), style: .destructive,
handler: { (_) in
self.discardChanges()
}))
Expand Down Expand Up @@ -587,10 +606,12 @@ class DocumentViewController: UIViewController, DocumentDelegate, UISearchBarDel
self.present(alert, animated: true, completion: nil)
}

/// Reads the document off disk again, which drops the edit, and leaves edit
/// mode with it — the only way back to reading without saving.
func discardChanges() {
AnalyticsManager.shared.report("menu_edit_discard")

document?.edit = true
document?.edit = false
}

func saveContent(completion: ((Bool) -> Void)?) {
Expand Down
2 changes: 1 addition & 1 deletion OpenDocumentReader/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<barButtonItem style="plain" systemItem="flexibleSpace" id="lgr-dX-fUO"/>
<barButtonItem image="pencil" catalog="system" id="Ed1-tP-enc">
<connections>
<action selector="editButton:" destination="M2k-L8-Olo" id="Ed2-tP-enc"/>
<action selector="editOrSave:" destination="M2k-L8-Olo" id="Ed2-tP-enc"/>
</connections>
</barButtonItem>
<barButtonItem width="10" style="plain" systemItem="fixedSpace" id="Ed4-tP-enc"/>
Expand Down
Loading