VMConfigSharingViewController.m 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. //
  2. // Copyright © 2019 osy. All rights reserved.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #import <MobileCoreServices/MobileCoreServices.h>
  17. #import "UIViewController+Extensions.h"
  18. #import "VMConfigSharingViewController.h"
  19. #import "UTMQemuConfiguration.h"
  20. #import "UTMQemuConfiguration+Sharing.h"
  21. #import "UTMLogging.h"
  22. #import "VMConfigSwitch.h"
  23. #import "VMConfigDirectoryPickerViewController.h"
  24. @interface VMConfigSharingViewController ()
  25. @property (nonatomic) NSURL *shareDirectory;
  26. @end
  27. @implementation VMConfigSharingViewController
  28. - (void)viewWillAppear:(BOOL)animated {
  29. [super viewWillAppear:animated];
  30. [self showShareDirectoryOptions:self.shareDirectoryEnabledSwitch.on animated:NO];
  31. if (self.configuration.shareDirectoryEnabled) {
  32. [self refreshBookmark];
  33. }
  34. }
  35. - (void)showShareDirectoryOptions:(BOOL)visible animated:(BOOL)animated {
  36. [self cells:self.directorySharingCells setHidden:!visible];
  37. if (self.configuration.shareDirectoryName.length == 0) {
  38. self.selectDirectoryCell.detailTextLabel.text = NSLocalizedString(@"Browse...", @"VMConfigSharingViewController");
  39. }
  40. [self reloadDataAnimated:animated];
  41. }
  42. - (IBAction)configSwitchChanged:(VMConfigSwitch *)sender {
  43. if (sender == self.shareDirectoryEnabledSwitch) {
  44. [self showShareDirectoryOptions:sender.on animated:YES];
  45. if (!sender.on) {
  46. self.configuration.shareDirectoryName = @"";
  47. self.configuration.shareDirectoryBookmark = [NSData data];
  48. }
  49. }
  50. [super configSwitchChanged:sender];
  51. }
  52. #pragma mark - Shared Directory
  53. - (void)selectDirectory {
  54. UIDocumentPickerViewController *picker =
  55. [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[ (__bridge NSString *)kUTTypeFolder ]
  56. inMode:UIDocumentPickerModeOpen];
  57. picker.delegate = self;
  58. [self presentViewController:picker animated:YES completion:nil];
  59. }
  60. - (void)refreshBookmark {
  61. BOOL stale;
  62. NSError *err;
  63. NSData *data = self.configuration.shareDirectoryBookmark;
  64. NSURL *bookmark = [NSURL URLByResolvingBookmarkData:data
  65. options:0
  66. relativeToURL:nil
  67. bookmarkDataIsStale:&stale
  68. error:&err];
  69. if (!bookmark) {
  70. UTMLog(@"bookmark invalid: %@", err);
  71. [self showAlert:NSLocalizedString(@"Shared path is no longer valid. Please re-choose.", @"VMConfigSharingViewController") actions:nil completion:nil];
  72. self.configuration.shareDirectoryBookmark = [NSData data];
  73. self.configuration.shareDirectoryName = @"";
  74. } else if (stale) {
  75. UTMLog(@"bookmark stale");
  76. if ([bookmark startAccessingSecurityScopedResource]) {
  77. data = [bookmark bookmarkDataWithOptions:NSURLBookmarkCreationMinimalBookmark
  78. includingResourceValuesForKeys:nil
  79. relativeToURL:nil
  80. error:&err];
  81. [bookmark stopAccessingSecurityScopedResource];
  82. if (!data) {
  83. UTMLog(@"cannot recreate bookmark: %@", err);
  84. [self showAlert:NSLocalizedString(@"Shared path has moved. Please re-choose.", @"VMConfigSharingViewController") actions:nil completion:nil];
  85. self.configuration.shareDirectoryBookmark = [NSData data];
  86. self.configuration.shareDirectoryName = @"";
  87. } else {
  88. self.configuration.shareDirectoryBookmark = data;
  89. }
  90. }
  91. }
  92. self.shareDirectory = bookmark;
  93. }
  94. - (void)selectURL:(NSURL *)url {
  95. NSError *err;
  96. NSData *bookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationMinimalBookmark
  97. includingResourceValuesForKeys:nil
  98. relativeToURL:nil
  99. error:&err];
  100. if (!bookmark) {
  101. [self showAlert:err.localizedDescription actions:nil completion:nil];
  102. } else {
  103. UTMLog(@"Saving bookmark for %@", url);
  104. self.configuration.shareDirectoryBookmark = bookmark;
  105. self.configuration.shareDirectoryName = url.lastPathComponent;
  106. }
  107. self.shareDirectory = url;
  108. }
  109. - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
  110. NSAssert(urls.count == 1, @"Invalid picker result");
  111. [self selectURL:urls[0]];
  112. }
  113. - (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
  114. }
  115. #pragma mark - Directory picker (sandboxed)
  116. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  117. if ([segue.identifier isEqualToString:@"selectDirectorySegue"]) {
  118. NSAssert([segue.destinationViewController isKindOfClass:[VMConfigDirectoryPickerViewController class]], @"Invalid segue destination");
  119. VMConfigDirectoryPickerViewController *destination = (VMConfigDirectoryPickerViewController *)segue.destinationViewController;
  120. destination.selectedDirectory = self.shareDirectory;
  121. }
  122. }
  123. - (IBAction)unwindToShareViewFromDirectoryPicker:(UIStoryboardSegue*)sender {
  124. NSAssert([sender.sourceViewController isKindOfClass:[VMConfigDirectoryPickerViewController class]], @"Invalid segue destination");
  125. VMConfigDirectoryPickerViewController *source = (VMConfigDirectoryPickerViewController *)sender.sourceViewController;
  126. [self selectURL:source.selectedDirectory];
  127. }
  128. @end