Skip to content

Commit

Permalink
Fix the share database button in debug settings (#918)
Browse files Browse the repository at this point in the history
* Fix the share database button in debug settings

* Update CHANGELOG

* Fix changelog

* Update CHANGELOG
  • Loading branch information
mplorentz authored Oct 21, 2022
1 parent 4c9ae44 commit b303497
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 67 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Improved background syncing #833
- Update to Xcode 14. #839
- Fixed the Share Database button in the debug settings. #918
- Fixed incorrect aspect ratio of avatar images. #753
- Added a button to delete the SQL database in the debug settings. #738


## [1.3.5] 2022-10-03
Expand Down
87 changes: 55 additions & 32 deletions Shared/Extensions/UIViewController+Alert.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,20 @@ protocol AlertRouter {

extension UIViewController: AlertRouter {

@MainActor
func alert(error: Error) {
let controller = UIAlertController(title: Localized.error.text,
message: error.localizedDescription,
preferredStyle: .alert)
let controller = UIAlertController(
title: Localized.error.text,
message: error.localizedDescription,
preferredStyle: .alert
)
controller.view.tintColor = UIColor.tint.system

let cancelAction = UIAlertAction(title: Localized.cancel.text,
style: .cancel) { _ in
controller.dismiss(animated: true)
let cancelAction = UIAlertAction(
title: Localized.cancel.text,
style: .cancel
) { _ in
controller.dismiss(animated: true)
}
controller.addAction(cancelAction)

Expand All @@ -45,11 +50,14 @@ extension UIViewController: AlertRouter {
/// - message: A description shown below the title.
/// - cancelTitle: A button that closes the alert.
/// - cancelClosure: A closure that will be called with the alert is dismissed.
func alert(from sourceView: AnyObject? = nil,
title: String? = nil,
message: String,
cancelTitle: String = Localized.cancel.text,
cancelClosure: (() -> Void)? = nil) {
@MainActor
func alert(
from sourceView: AnyObject? = nil,
title: String? = nil,
message: String,
cancelTitle: String = Localized.cancel.text,
cancelClosure: (() -> Void)? = nil
) {

let cancel = UIAlertAction(title: cancelTitle, style: .cancel) { _ in
cancelClosure?()
Expand All @@ -61,6 +69,7 @@ extension UIViewController: AlertRouter {
/// An async alternative to `alert(from:title:message:cancelTitle:cancelClosure)`.
/// It's name includes async because otherwise Swift gets confused and thinks calls to the completion handler
/// version are calls to the async version.
@MainActor
func showAsyncAlert(
from sourceView: AnyObject? = nil,
title: String? = nil,
Expand Down Expand Up @@ -88,17 +97,22 @@ extension UIViewController: AlertRouter {
/// - cancelClosure: A closure that will be performed if the cancel button is pressed.
/// - confirmTitle: The title of the confirmation button.
/// - confirmClosure: A closure that will be performed if the confirmation button is pressed.
func confirm(from sourceView: UIView? = nil,
title: String? = nil,
message: String,
isDestructive: Bool = false,
cancelTitle: String = Localized.cancel.text,
cancelClosure: (() -> Void)? = nil,
confirmTitle: String = Localized.ok.text,
confirmClosure: @escaping (() -> Void)) {
@MainActor
func confirm(
from sourceView: UIView? = nil,
title: String? = nil,
message: String,
isDestructive: Bool = false,
cancelTitle: String = Localized.cancel.text,
cancelClosure: (() -> Void)? = nil,
confirmTitle: String = Localized.ok.text,
confirmClosure: @escaping (() -> Void)
) {

let confirm = UIAlertAction(title: confirmTitle,
style: isDestructive ? .destructive : .default) { _ in
let confirm = UIAlertAction(
title: confirmTitle,
style: isDestructive ? .destructive : .default
) { _ in
confirmClosure()
}

Expand Down Expand Up @@ -150,15 +164,20 @@ extension UIViewController: AlertRouter {
/// - sourceView: The view that the popover arrow should point to on large devices if you would like to display
/// the choices as an `.actionSheet`. If this parameter is nil the choices will be displayed in a `.alert`
/// style. Should be a subclass of either `UIView` or `UIBarButtonItem`.
func choose(from actions: [UIAlertAction],
title: String? = nil,
message: String? = nil,
sourceView: AnyObject? = nil) {
@MainActor
func choose(
from actions: [UIAlertAction],
title: String? = nil,
message: String? = nil,
sourceView: AnyObject? = nil
) {

let style: UIAlertController.Style = sourceView != nil ? .actionSheet : .alert
let controller = UIAlertController(title: title,
message: message,
preferredStyle: style)
let controller = UIAlertController(
title: title,
message: message,
preferredStyle: style
)
controller.view.tintColor = UIColor.tint.system
for action in actions { controller.addAction(action) }
self.present(alertController: controller, sourceView: sourceView)
Expand All @@ -174,10 +193,13 @@ extension UIViewController: AlertRouter {
/// - sourceRect: The rectangle in the coordinate space of sourceView that the popover should point at. This
/// property is ignored if sourceView is a `UIBarButtonItem`.
/// - animated: Whether or not the transition should be animated.
func present(alertController controller: UIAlertController,
sourceView: AnyObject? = nil,
sourceRect: CGRect? = nil,
animated: Bool = true) {
@MainActor
func present(
alertController controller: UIAlertController,
sourceView: AnyObject? = nil,
sourceRect: CGRect? = nil,
animated: Bool = true
) {

if controller.preferredStyle == .actionSheet && sourceView == nil {
let errorMessage = "sourceView is required to present a popover controller"
Expand All @@ -195,6 +217,7 @@ extension UIViewController: AlertRouter {
/// `UIView` or `UIBarButtonItem`
/// - Parameter rect: The rectangle in the coordinate space of sourceView that the popover should point at. This
/// property is ignored if sourceView is a `UIBarButtonItem`.
@MainActor
func configurePopover(from sourceView: AnyObject?, rect: CGRect? = nil) {
guard let popover = self.popoverPresentationController,
let sourceView = sourceView else {
Expand Down
66 changes: 31 additions & 35 deletions Source/Debug/DebugViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,8 @@ class DebugViewController: DebugTableViewController {
title: "Export database",
cellReuseIdentifier: DebugValueTableViewCell.className,
valueClosure: nil,
actionClosure: { [weak self] _ in
Task {
self?.shareDatabase(cell:)
}
actionClosure: { cell in
Task { await self.shareDatabase(cell: cell) }
}
)
]
Expand Down Expand Up @@ -467,8 +465,10 @@ class DebugViewController: DebugTableViewController {

/// Allows the user to export the go-ssb log and SQLite database in a zip file. This function will zip up the files
/// and present a share sheet as a popover on the given cell.
private func shareDatabase(cell: UITableViewCell) async {
@MainActor
func shareDatabase(cell: UITableViewCell) async {
cell.showActivityIndicator()
cell.isUserInteractionEnabled = false

let presentShareSheet = { [weak self] (activityItems: [Any]) in
let activityController = UIActivityViewController(
Expand All @@ -481,40 +481,36 @@ class DebugViewController: DebugTableViewController {
self?.present(activityController, animated: true)
}

let databaseDirectory = URL(fileURLWithPath: await Bots.current.statistics().repo.path).deletingLastPathComponent()
let databasePath = await Bots.current.statistics().repo.path
let databaseDirectory = URL(fileURLWithPath: databasePath).deletingLastPathComponent()
let temporaryDirectory = URL(fileURLWithPath: NSTemporaryDirectory())
let url = temporaryDirectory.appendingPathComponent(UUID().uuidString)
DispatchQueue.global(qos: .background).async { [weak self] in
defer {
DispatchQueue.main.sync {
cell.hideActivityIndicator()
}
}
do {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: false)
let zipFileURL = temporaryDirectory.appendingPathComponent("\(UUID().uuidString).zip")
let destFileURL = url.appendingPathComponent(databaseDirectory.lastPathComponent)
try FileManager.default.copyItem(at: databaseDirectory, to: destFileURL)

let coord = NSFileCoordinator()
var readError: NSError?
coord.coordinate(readingItemAt: url, options: .forUploading, error: &readError) { (zippedURL: URL) -> Void in
do {
try FileManager.default.copyItem(at: zippedURL, to: zipFileURL)
} catch {
DispatchQueue.main.async { [weak self] in
self?.alert(error: error)
}
}
DispatchQueue.main.async {
presentShareSheet([zipFileURL])
}
}
} catch {
DispatchQueue.main.async { [weak self] in
self?.alert(error: error)
defer {
cell.hideActivityIndicator()
cell.isUserInteractionEnabled = false
}
do {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: false)
let zipFileURL = temporaryDirectory.appendingPathComponent("\(UUID().uuidString).zip")
let destFileURL = url.appendingPathComponent(databaseDirectory.lastPathComponent)
try FileManager.default.copyItem(at: databaseDirectory, to: destFileURL)

let coord = NSFileCoordinator()
var readError: NSError?
coord.coordinate(
readingItemAt: url,
options: .forUploading,
error: &readError
) { (zippedURL: URL) -> Void in
do {
try FileManager.default.copyItem(at: zippedURL, to: zipFileURL)
} catch {
self.alert(error: error)
}
presentShareSheet([zipFileURL])
}
} catch {
self.alert(error: error)
}
}

Expand Down

0 comments on commit b303497

Please sign in to comment.