Skip to content

Commit 2954296

Browse files
authored
Merge pull request #61 from opendocument-app/development
v1.18
2 parents 9ed125d + ad25558 commit 2954296

28 files changed

Lines changed: 674 additions & 408 deletions

OpenDocument.core

OpenDocumentReader.xcodeproj/project.pbxproj

Lines changed: 54 additions & 76 deletions
Large diffs are not rendered by default.

OpenDocumentReader/AppDelegate.swift

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
1515
var window: UIWindow?
1616

1717
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18-
FirebaseApp.configure()
18+
19+
if ConfigurationManager.manager.configuration == .lite {
20+
let filePath = Bundle.main.path(forResource: "GoogleService-Info-Lite", ofType: "plist")!
21+
let options = FirebaseOptions(contentsOfFile: filePath)
22+
FirebaseApp.configure(options: options!)
23+
} else {
24+
FirebaseApp.configure()
25+
}
1926

2027
StoreReviewHelper.incrementAppOpenedCount()
2128

@@ -51,22 +58,29 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
5158
return false
5259
}
5360

54-
documentBrowserViewController.revealDocument(at: inputURL, importIfNeeded: true) { (revealedDocumentURL, error) in
55-
56-
guard error == nil else {
57-
Crashlytics.crashlytics().record(error: error!)
58-
fatalError("error is not null")
59-
60-
return
61-
}
62-
63-
guard let url = revealedDocumentURL else {
64-
fatalError("revealedDocumentURL is null")
61+
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
62+
let inboxUrl = documentsUrl.appendingPathComponent("Inbox")
63+
64+
let destinationUrl: URL
65+
if (inputURL.absoluteString.contains(inboxUrl.absoluteString)) {
66+
do {
67+
destinationUrl = documentsUrl.appendingPathComponent(inputURL.lastPathComponent)
68+
69+
try FileManager.default.moveItem(at: inputURL, to: destinationUrl)
70+
} catch {
71+
print(error)
72+
fatalError("copying from Inbox failed")
6573

66-
return
74+
return false
6775
}
76+
} else {
77+
destinationUrl = inputURL
78+
}
79+
80+
documentBrowserViewController.revealDocument(at: destinationUrl, importIfNeeded: true) { (revealedDocumentURL, error) in
81+
// ignoring errors because they should pop up in failedToImportDocumentAt too
6882

69-
documentBrowserViewController.presentDocument(at: url)
83+
documentBrowserViewController.presentDocument(at: revealedDocumentURL!)
7084
}
7185

7286
return true

OpenDocumentReader/CoreWrapper.mm

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ - (bool)translate:(NSString *)inputPath into:(NSString *)outputPath at:(NSNumber
3232
return false;
3333
}
3434

35-
const auto meta = translator->meta();
35+
auto meta = translator->meta();
3636

3737
bool decrypted = !meta.encrypted;
3838
if (password != nil) {
3939
decrypted = translator->decrypt([password cStringUsingEncoding:NSUTF8StringEncoding]);
40+
41+
meta = translator->meta();
4042
}
4143

4244
if (!decrypted) {
@@ -45,14 +47,17 @@ - (bool)translate:(NSString *)inputPath into:(NSString *)outputPath at:(NSNumber
4547
}
4648

4749
NSMutableArray *pageNames = [[NSMutableArray alloc] init];
48-
if (meta.type == odr::FileType::OPENDOCUMENT_TEXT) {
50+
if (meta.type == odr::FileType::OPENDOCUMENT_TEXT || meta.type == odr::FileType::OPENDOCUMENT_GRAPHICS) {
4951
[pageNames addObject:@"Text document"];
50-
} else {
52+
} else if (meta.type == odr::FileType::OPENDOCUMENT_SPREADSHEET || meta.type == odr::FileType::OPENDOCUMENT_PRESENTATION) {
5153
for (auto page = meta.entries.begin(); page != meta.entries.end(); page++) {
5254
auto pageName = page->name;
5355

5456
[pageNames addObject:[NSString stringWithCString:pageName.c_str() encoding:[NSString defaultCStringEncoding]]];
5557
}
58+
} else {
59+
_errorCode = @(-5);
60+
return false;
5661
}
5762
_pageNames = pageNames;
5863

OpenDocumentReader/DocumentBrowserViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class DocumentBrowserViewController: UIDocumentBrowserViewController, UIDocument
4747
func documentBrowser(_ controller: UIDocumentBrowserViewController, failedToImportDocumentAt documentURL: URL, error: Error?) {
4848
let alert = UIAlertController(
4949
title: "",
50-
message: NSLocalizedString("alert_error_generic", comment: ""),
50+
message: NSLocalizedString("toast_error_generic", comment: ""),
5151
preferredStyle: .alert)
5252

5353
let action = UIAlertAction(

OpenDocumentReader/DocumentViewController.swift

Lines changed: 125 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Firebase
1313
import GoogleMobileAds
1414

1515
// taken from: https://developer.apple.com/documentation/uikit/view_controllers/building_a_document_browser-based_app
16-
class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewDelegate {
16+
class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewDelegate, UISearchBarDelegate {
1717

1818
private var browserTransition: DocumentBrowserTransitioningDelegate?
1919
public var transitionController: UIDocumentBrowserTransitionController? {
@@ -33,6 +33,8 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
3333

3434
private var EXTENSION_WHITELIST = ["pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "rtf", "rtfd.zip", "csv", "txt", "jpg", "jpeg", "png", "gif", "svg", "pages", "pages.zip", "numbers", "numbers.zip", "key", "key.zip", "mp3", "mp4", "flv", "mkv", "3gp", "aac", "bmp", "css", "htm", "html", "js", "json", "mpeg", "oga", "ogv", "sh", "tif", "tiff", "weba", "webm", "webp", "xhtml", "xml"]
3535

36+
@IBOutlet weak var toolBar: UIToolbar!
37+
@IBOutlet weak var searchBar: UISearchBar!
3638
@IBOutlet weak var segmentedControl: ScrollableSegmentedControl!
3739
private var initialSelect = false
3840

@@ -41,7 +43,11 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
4143
@IBOutlet weak var menuButton: UIBarButtonItem!
4244
@IBOutlet weak var bannerView: GADBannerView!
4345
@IBOutlet weak var bannerViewHeight: NSLayoutConstraint!
46+
@IBOutlet weak var barButtonItem: UIBarButtonItem!
4447

48+
private var searchBarHeightWhenShown: NSLayoutConstraint?
49+
private var searchBarHeightWhenHidden: NSLayoutConstraint?
50+
4551
private var isFullscreen = false
4652

4753
public var document: Document? {
@@ -54,6 +60,17 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
5460

5561
override func viewWillAppear(_ animated: Bool) {
5662
super.viewWillAppear(animated)
63+
64+
searchBar.delegate = self
65+
searchBar.showsCancelButton = true
66+
67+
searchBarHeightWhenShown = searchBar.heightAnchor.constraint(equalToConstant: 56)
68+
searchBarHeightWhenHidden = searchBar.heightAnchor.constraint(equalToConstant: 0)
69+
70+
setVCconstraints()
71+
hideSearchBar()
72+
73+
barButtonItem.title = NSLocalizedString("back_to_documents", comment: "")
5774

5875
segmentedControl.segmentStyle = .textOnly
5976
segmentedControl.underlineSelected = true
@@ -65,12 +82,37 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
6582
document?.webview = self.webview
6683

6784
bannerView.delegate = self
68-
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
85+
bannerView.adUnitID = "ca-app-pub-8161473686436957/8123543897"
6986
bannerView.rootViewController = self
7087

7188
loadBannerAd()
7289
}
7390

91+
func setVCconstraints() {
92+
searchBar.translatesAutoresizingMaskIntoConstraints = false
93+
bannerView.translatesAutoresizingMaskIntoConstraints = false
94+
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
95+
webview.translatesAutoresizingMaskIntoConstraints = false
96+
97+
searchBar.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
98+
searchBar.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
99+
searchBar.topAnchor.constraint(equalTo: toolBar.bottomAnchor).isActive = true
100+
101+
bannerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
102+
bannerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
103+
bannerView.topAnchor.constraint(equalTo: searchBar.bottomAnchor).isActive = true
104+
bannerView.heightAnchor.constraint(equalToConstant: 50).isActive = true
105+
106+
segmentedControl.topAnchor.constraint(equalTo: bannerView.bottomAnchor).isActive = true
107+
segmentedControl.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
108+
segmentedControl.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
109+
110+
webview.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor).isActive = true
111+
webview.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
112+
webview.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
113+
webview.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
114+
}
115+
74116
func loadBannerAd() {
75117
if ConfigurationManager.manager.configuration == .lite {
76118
let frame = { () -> CGRect in
@@ -142,6 +184,58 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
142184
return isFullscreen
143185
}
144186

187+
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
188+
hideSearchBar()
189+
}
190+
191+
func searchBarResultsListButtonClicked(_ searchBar: UISearchBar) {
192+
if let searchText = searchBar.text {
193+
findNext(searchText: searchText)
194+
}
195+
}
196+
197+
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
198+
findAll(searchText: searchText)
199+
}
200+
201+
@IBAction func searchButton(_ sender: UIBarButtonItem) {
202+
showSearchBar()
203+
}
204+
205+
private func showSearchBar() {
206+
searchBar.becomeFirstResponder()
207+
searchBar.isHidden = false
208+
searchBarHeightWhenHidden?.isActive = false
209+
searchBarHeightWhenShown?.isActive = true
210+
}
211+
212+
private func hideSearchBar() {
213+
searchBar.text = ""
214+
searchBar.isHidden = true
215+
searchBarHeightWhenHidden?.isActive = true
216+
searchBarHeightWhenShown?.isActive = false
217+
218+
self.view.endEditing(true)
219+
}
220+
221+
private func findNext(searchText: String) {
222+
webview?.evaluateJavaScript("odr.searchNext(\"" + searchText + "\")", completionHandler: { (value: Any!, error: Error!) -> Void in
223+
if error != nil {
224+
Crashlytics.crashlytics().record(error: error)
225+
fatalError("search failed")
226+
}
227+
})
228+
}
229+
230+
private func findAll(searchText: String) {
231+
webview?.evaluateJavaScript("odr.search(\"" + searchText + "\")", completionHandler: { (value: Any!, error: Error!) -> Void in
232+
if error != nil {
233+
Crashlytics.crashlytics().record(error: error)
234+
fatalError("search failed")
235+
}
236+
})
237+
}
238+
145239
@IBAction func returnToDocuments(_ sender: Any) {
146240
guard let doc = document else {
147241
fatalError("document is null")
@@ -160,8 +254,11 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
160254
alert.addAction(UIAlertAction(title: NSLocalizedString("yes", comment: ""), style: .default, handler: { (_) in
161255
Analytics.logEvent("alert_unsaved_changes_yes", parameters: nil)
162256

163-
self.saveContent()
164-
self.closeCurrentDocument()
257+
self.saveContent() { (success) -> () in
258+
if (success) {
259+
self.closeCurrentDocument()
260+
}
261+
}
165262
}))
166263

167264
self.present(alert, animated: true, completion: nil)
@@ -193,8 +290,8 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
193290
}
194291

195292
if document?.edit ?? false {
196-
alert.addAction(UIAlertAction(title: NSLocalizedString("menu_save", comment: ""), style: .default, handler: { (_) in
197-
self.saveContent()
293+
alert.addAction(UIAlertAction(title: NSLocalizedString("action_edit_save", comment: ""), style: .default, handler: { (_) in
294+
self.saveContent(completion: nil)
198295
}))
199296

200297
alert.addAction(UIAlertAction(title: NSLocalizedString("menu_discard_changes", comment: ""), style: .default, handler: { (_) in
@@ -208,7 +305,7 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
208305
alert.addAction(UIAlertAction(title: NSLocalizedString("menu_cloud_print", comment: ""), style: .default, handler: { (_) in
209306
self.printDocument()
210307
}))
211-
alert.addAction(UIAlertAction(title: NSLocalizedString("menu_help", comment: ""), style: .default, handler: { (_) in
308+
alert.addAction(UIAlertAction(title: NSLocalizedString("action_edit_help", comment: ""), style: .default, handler: { (_) in
212309
self.showWebsite()
213310
}))
214311
alert.addAction(UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .cancel, handler: nil))
@@ -229,7 +326,7 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
229326
doc.edit = true
230327
}
231328

232-
func saveContent() {
329+
func saveContent(completion: ((Bool) -> ())?) {
233330
Analytics.logEvent("menu_edit_save", parameters: nil)
234331

235332
guard let doc = document else {
@@ -242,14 +339,16 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
242339
let message: String
243340
let color: UIColor
244341
if success {
245-
message = NSLocalizedString("alert_document_saved", comment: "")
342+
message = NSLocalizedString("toast_edit_status_saved", comment: "")
246343
color = .green
247344
} else {
248-
message = NSLocalizedString("alert_error_save_failed", comment: "")
345+
message = NSLocalizedString("toast_error_save_failed", comment: "")
249346
color = .red
250347
}
251348

252-
self.showToast(controller: self, message: message, seconds: 1.5, color: color)
349+
self.showToast(controller: self, message: message, seconds: 1.5, color: color) {
350+
completion?(success)
351+
}
253352
}
254353
}
255354

@@ -297,7 +396,7 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
297396

298397
func documentUpdateContent(_ doc: Document) {
299398
guard let path = document?.result else {
300-
self.webview.loadHTMLString("<html><h1>Loading</h1></html>", baseURL: nil)
399+
self.webview.loadHTMLString("<html><h1>\(NSLocalizedString("loading", comment: ""))</h1></html>", baseURL: nil)
301400

302401
return
303402
}
@@ -315,7 +414,7 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
315414
})
316415
}
317416

318-
let alert = UIAlertController(title: NSLocalizedString("alert_error_password_protected", comment: ""), message: NSLocalizedString("alert_enter_password", comment: ""), preferredStyle: .alert)
417+
let alert = UIAlertController(title: NSLocalizedString("toast_error_password_protected", comment: ""), message: "", preferredStyle: .alert)
319418
alert.addTextField { (textField) in
320419
textField.text = ""
321420
}
@@ -332,9 +431,12 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
332431
}
333432

334433
func documentLoadingError(_ doc: Document, errorCode: Int) {
434+
// attention: wrong for extensions like ".pages.zip"
335435
let fileType = doc.fileURL.pathExtension.lowercased()
436+
437+
let fileName = doc.fileURL.absoluteString.lowercased()
336438
for type in EXTENSION_WHITELIST {
337-
if (!fileType.starts(with: type)) {
439+
if (!fileName.hasSuffix(type)) {
338440
continue
339441
}
340442

@@ -350,7 +452,7 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
350452
return;
351453
}
352454

353-
self.webview.loadHTMLString("<html><h1>Error</h1>Failed to load given document. Please try another one while we are working hard to support as many documents as possible. Feel free to contact us via support@opendocument.app for further questions.</html>", baseURL: nil)
455+
self.webview.loadHTMLString("<html><h1>\(NSLocalizedString("error", comment: ""))</h1>\(NSLocalizedString("toast_error_generic", comment: ""))</html>", baseURL: nil)
354456

355457
Analytics.logEvent(
356458
"load_error",
@@ -390,8 +492,14 @@ class DocumentViewController: UIViewController, DocumentDelegate, GADBannerViewD
390492

391493
i += 1
392494
}
393-
394-
segmentedControl.isHidden = i <= 1
495+
496+
if i <= 1 {
497+
segmentedControl.heightAnchor.constraint(equalToConstant: 0).isActive = true
498+
segmentedControl.isHidden = true
499+
} else {
500+
segmentedControl.heightAnchor.constraint(equalToConstant: 40).isActive = true
501+
segmentedControl.isHidden = false
502+
}
395503

396504
initialSelect = true
397505
segmentedControl.selectedSegmentIndex = 0

0 commit comments

Comments
 (0)