Skip to content

Commit

Permalink
[feature/multiple-windows] Multiple window support for iPadOS (#498)
Browse files Browse the repository at this point in the history
* Naming improvements based on latest SDK:
- uploads use new OCCoreOptionAutomaticConflictResolutionNameStyle option to automatically resolve naming conflicts during upload
- Duplicate action uses the new OCCore name suggestion API to
	- determine naming conflicts and resolve them automatically
	- match the name style of the file to duplicate, f.ex.
		- duplicating "File copy.jpg" will create "File copy 2.jpg"
		- duplicating "File (1).jpg" will create "File (2).jpg"
		- duplicating "File Kopie 2.jpg" will create "File Kopie 3.jpg"
- folder creation uses the new OCCore name suggestion API to
	- detect naming conflicts beforehand
	- pre-fill the new folder name name with an unused name directly

* #393 added an activity indicator which will be shown, if offline copies will be deleted to give the user a UI feedback

* - Change SDK branch to master

* #76 user can import files using the iOS share sheet. all file types are accepted.

* - using new SDK with fixes for requesting core
- minor code fixes

* - Log device, version and locale information at the beginning of every log file using new SDK protocol
- Show SDK commit hash in Settings

* fixed crash, changed bookmark name to shortname

* changed UIAlertViewController for account selection to CardViewController style for testing

* fixed icon badge creation for fastlane lane In-House Enterprise IPA generation

* install librsvg for fastlane via sh

* moved import file code to own class

* added option to automatically resolve name conflicts, if file name already exists

* Changed app version to 1.1.0

* enabled beta build and warning

*  Keep the gallery alive after doing some action over an item (#447)

* Rename updates the currently visible file in the gallery

* Keeping gallery alive fix

- Don’t pop to the root view controller on destructive action by default
- Only pop to the root if all items have been deleted
- Select next item upon deletion of the current ones
- Update UIPageViewController data source if number of items changes due e.g. to duplication or deletion

* Small fixes

* Fixed review findings

* Media player implemented using AVKit (#429)

* Media player implemented using AVKit

* Added possibility to stream audio / video

* Improved error handling

* Fixed review finding

* Added background audio, airplay and PiP mode

* Propagating safe area to the main view of AVPlayerViewController

* Another fix for safe area considering layout of AVPlayerViewController

* Updated to latest develop version of SDK

* Display error message in case file couldn’t be preview e.g. due to file corruption (#427)

* Fixed UI test for creating folder, need to return a fixed name, because suggestion is not working in tests

* added a description header and changed typo

* - fixed showing the directory picker controller, after the card view was dismissed
- use the current development SDK

* Version Bump to 126

* - create local copy of import file, if needed
- fixed create folder action
- delete local copy, if needed
- code review changes

* - improved duplicate item deletion behaviour
	- add additional safeguard so duplicate files are only deleted if they were actually duplicated (previously non-duplicate files could be removed if duplication or folder creation failed)
	- remove temporary container folder, too
- add 2 second delay before returning the core to give the core an opportunity to schedule the upload on a NSURLSession

* Version Bump to 127

* changed back signing identity

* Version Bump to 128

* added required CFBundleTypeName key

* Version Bump to 129

* updated changelog

* use formSheet presentation style for the iPad when showing the document picker

* Fix for images not being displayed in the gallery

* Version Bump to 130

* Version Bump to 131

* [fix/sharing-search] Fixed min length for searching sharing users (#455)

* #454 used correct comparator for sharingSearchMinLength and set a new default value, if capability does not exists

* added a constant for defaultSharingSearchMinLength value

* - Update ios-sdk to address finding (1) in ios-app #446

* Preventing updating UI in DisplayViewController while item is being changed

- Not calling present(item:) while meta data of OCItem is being updated
- Elliminated an assumption in MediaDisplayViewController that render renderSpecificView() can be called only once.
- Making sure that AVPlayer is not re-created upon changes in OCItem but that rather AVPlayerItem is replaced.

* Fixed a small warning

* Tried to improve gallery logic concerning items modification

- Watch out if the modification does still includes the item with local ID of the currently visible item.
- Take care of failed move but watching out for reappearing items

* Added a setting allowing to decide user if media files shall be streamed

* - Add debug output to Display*ViewController
- Fix SwiftLint warnings

* Fixed handling of deleted / moved item in the gallery

* Another small fix for handling of failed item move

* Version Bump to 132

* Added LSSupportsOpeningDocumentsInPlace key to Info.plist

* Fixed Info.plist and added LSHandlerRank property

* Fix for #455 issue: no search request triggered

* show always the account selection sheet and added a note, that only one file can be imported at once

* use securtiy scoped file operation for importing a file

* Fix for the PR #447 (keep gallery alive) (#465)

* Keeping track of individual OCItems in DisplayViewController instances

But loading the list of items in the gallery only once and not reacting to any changes (moving, deleting)

* Removed query stop call in DisplayHostViewController

Since this query is not created there but just passed from the parent view.

* Removing more button if the currently viewed file got moved or deleted

* Fixed updating UI after renaming current item

* Fixed a warning

* Fixed issues in the gallery

* - Minor fixes

* first draft for supporting multiple windows

* implemented opening an account in a new window

* added row action

* - open account, now opens file list
- implemented open account from table view edit action
- implemented contextual menu for account row

* Starting implementing state restoration

* Implemented UI restoration state for window scenes

* Implemented UI state restoration for opening a OCItem

* - only show close window item on iPad
- fixed icons for location

* - only show "Open in new Window" on iPad
- better view restoration
- deselect row

* - added new menu item to open a new window
- fixed tint color for icons

* - added missing localization strings
- removed no longer needed class

* - fixed code review findings
- code refactoring

* - moved creating file list stack code into ClientRootViewController class
- added iOS 13 available query

* fixed merge error

* fixed drag and drop between accounts (when dragging items from one window to the other window on iPad)

* prevent dragging folders from one account to an other account
  • Loading branch information
hosy authored Oct 29, 2019
1 parent 0112b8d commit 4e47f9b
Show file tree
Hide file tree
Showing 17 changed files with 655 additions and 97 deletions.
24 changes: 24 additions & 0 deletions ownCloud.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,15 @@
3913213822946E5E00EF88F4 /* FileListTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3913213722946E5E00EF88F4 /* FileListTableViewController.swift */; };
3913214D22956D5700EF88F4 /* LibraryTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3913214A22956D5700EF88F4 /* LibraryTableViewController.swift */; };
394804DA225CBDBA00AA8183 /* BreadCrumbTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 394804D9225CBDBA00AA8183 /* BreadCrumbTableViewController.swift */; };
394E200C233E477F009D2897 /* OpenItemUserActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 394E200B233E477F009D2897 /* OpenItemUserActivity.swift */; };
39607CBC2225D480007B386D /* UITableViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39607CBB2225D480007B386D /* UITableViewController+Extension.swift */; };
3961281622F8730A0087BD3A /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3961281522F8730A0087BD3A /* SceneDelegate.swift */; };
396BE4C32288A84C00B254A9 /* PendingSharesTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396BE4C22288A84C00B254A9 /* PendingSharesTableViewController.swift */; };
396BE4CA2289500E00B254A9 /* RoundedLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396BE4C92289500E00B254A9 /* RoundedLabel.swift */; };
396D7C6523224A53002380C1 /* DiscardSceneAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396D7C5F23224A53002380C1 /* DiscardSceneAction.swift */; };
3971B48F221B23FE006FB441 /* ThemeableColoredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3971B48E221B23FE006FB441 /* ThemeableColoredView.swift */; };
397328EF22D606AC006CFAA4 /* ImportFilesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 397328EE22D606AC006CFAA4 /* ImportFilesController.swift */; };
397754F82327A33500119FCB /* OpenSceneAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 397754F22327A33500119FCB /* OpenSceneAction.swift */; };
39878B7421FB1DE800DBF693 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39878B7321FB1DE800DBF693 /* UINavigationController+Extension.swift */; };
3998F5CC2240CD8300B66713 /* RoundedInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3998F5CB2240CD8300B66713 /* RoundedInfoView.swift */; };
3998F5D3224102FE00B66713 /* UITableView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3998F5D2224102FE00B66713 /* UITableView+Extension.swift */; };
Expand Down Expand Up @@ -615,11 +619,15 @@
3913213722946E5E00EF88F4 /* FileListTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileListTableViewController.swift; sourceTree = "<group>"; };
3913214A22956D5700EF88F4 /* LibraryTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LibraryTableViewController.swift; sourceTree = "<group>"; };
394804D9225CBDBA00AA8183 /* BreadCrumbTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadCrumbTableViewController.swift; sourceTree = "<group>"; };
394E200B233E477F009D2897 /* OpenItemUserActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenItemUserActivity.swift; sourceTree = "<group>"; };
39607CBB2225D480007B386D /* UITableViewController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableViewController+Extension.swift"; sourceTree = "<group>"; };
3961281522F8730A0087BD3A /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
396BE4C22288A84C00B254A9 /* PendingSharesTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingSharesTableViewController.swift; sourceTree = "<group>"; };
396BE4C92289500E00B254A9 /* RoundedLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedLabel.swift; sourceTree = "<group>"; };
396D7C5F23224A53002380C1 /* DiscardSceneAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiscardSceneAction.swift; sourceTree = "<group>"; };
3971B48E221B23FE006FB441 /* ThemeableColoredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeableColoredView.swift; sourceTree = "<group>"; };
397328EE22D606AC006CFAA4 /* ImportFilesController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportFilesController.swift; sourceTree = "<group>"; };
397754F22327A33500119FCB /* OpenSceneAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenSceneAction.swift; sourceTree = "<group>"; };
39878B7321FB1DE800DBF693 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
39880BAA233B5236006EA539 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Localizable.strings; sourceTree = "<group>"; };
39880BB0233B524B006EA539 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/InfoPlist.strings; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1041,6 +1049,7 @@
isa = PBXGroup;
children = (
233BDE9F204FEFE500C06732 /* AppDelegate.swift */,
3961281522F8730A0087BD3A /* SceneDelegate.swift */,
397328E822D6067B006CFAA4 /* Import */,
DCF4F1612051925A00189B9A /* Bookmarks */,
DC29F09122974F8000F77349 /* FileLists */,
Expand All @@ -1049,6 +1058,7 @@
DC7DF17C205140F400189B9A /* Server List */,
DCF4F1802051A91500189B9A /* Settings */,
DC422448207CAED60006A2A6 /* Theming */,
394E2005233E4765009D2897 /* Window */,
DCF4F1622051927200189B9A /* UI Elements */,
239F1314205A69240029F186 /* UIKit Extensions */,
DCE5E8B62080D8B8005F60CE /* SDK Extensions */,
Expand Down Expand Up @@ -1185,6 +1195,14 @@
path = Library;
sourceTree = "<group>";
};
394E2005233E4765009D2897 /* Window */ = {
isa = PBXGroup;
children = (
394E200B233E477F009D2897 /* OpenItemUserActivity.swift */,
);
path = Window;
sourceTree = "<group>";
};
397328E822D6067B006CFAA4 /* Import */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1325,6 +1343,8 @@
6E586CF52199A70100F680C4 /* Actions+Extensions */ = {
isa = PBXGroup;
children = (
397754F22327A33500119FCB /* OpenSceneAction.swift */,
396D7C5F23224A53002380C1 /* DiscardSceneAction.swift */,
6E91F37D21ECA6FD009436D2 /* CopyAction.swift */,
6ED1B80A21A4004900E16C95 /* CreateFolderAction.swift */,
6E586CFF2199A78E00F680C4 /* DeleteAction.swift */,
Expand Down Expand Up @@ -2513,6 +2533,7 @@
DC42244A207CAFAA0006A2A6 /* Theme.swift in Sources */,
4C464BF52187AF1500D30602 /* PDFThumbnailsCollectionViewController.swift in Sources */,
4C464BF02187AF1500D30602 /* PDFTocTableViewController.swift in Sources */,
3961281622F8730A0087BD3A /* SceneDelegate.swift in Sources */,
DC4FEAEA209E48E800D4476B /* DispatchQueueTools.swift in Sources */,
6ED1B80B21A4004900E16C95 /* CreateFolderAction.swift in Sources */,
DC1B2708209CF0D3004715E1 /* IssuesPresentationAnimator.swift in Sources */,
Expand Down Expand Up @@ -2550,6 +2571,7 @@
DC297965226E4D1100E01BC7 /* PushTransitionDelegate.swift in Sources */,
396BE4C32288A84C00B254A9 /* PendingSharesTableViewController.swift in Sources */,
233E0FD82099F11D00C3D8D5 /* SecuritySettingsSection.swift in Sources */,
396D7C6523224A53002380C1 /* DiscardSceneAction.swift in Sources */,
DCF4F18B2052BA4C00189B9A /* Log.swift in Sources */,
DC8549382183B4CD00782BA8 /* ThemeStyle+Extensions.swift in Sources */,
4C82D07022C9387300835F0B /* MediaDisplayViewController.swift in Sources */,
Expand Down Expand Up @@ -2604,10 +2626,12 @@
DC3BE0DE2077CC14002A0AC0 /* ClientQueryViewController.swift in Sources */,
4C1561EF22232357009C4EF3 /* PhotoSelectionViewCell.swift in Sources */,
23C56538212167BE00BD4B47 /* CardTransitionDelegate.swift in Sources */,
397754F82327A33500119FCB /* OpenSceneAction.swift in Sources */,
4CAF783C2282FD40000C85CF /* FileManager+Extension.swift in Sources */,
6E3A104D219D6F0100F90C96 /* DuplicateAction.swift in Sources */,
DC1B270A209CF0D3004715E1 /* ConnectionIssueViewController.swift in Sources */,
DC0B37972051681600189B9A /* ThemeButton.swift in Sources */,
394E200C233E477F009D2897 /* OpenItemUserActivity.swift in Sources */,
DCF4F17B20519F9D00189B9A /* StaticTableViewSection.swift in Sources */,
DC243BFF2317B446004FBB5C /* ThemeWindow.swift in Sources */,
39D06BEC229BE8D8000D7FC9 /* SettingsSection.swift in Sources */,
Expand Down
16 changes: 16 additions & 0 deletions ownCloud/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

OCExtensionManager.shared.addExtension(BackgroundFetchUpdateTaskAction.taskExtension)
OCExtensionManager.shared.addExtension(InstantMediaUploadTaskExtension.taskExtension)
if #available(iOS 13.0, *), UIDevice.current.isIpad() {
OCExtensionManager.shared.addExtension(DiscardSceneAction.actionExtension)
OCExtensionManager.shared.addExtension(OpenSceneAction.actionExtension)
}

Theme.shared.activeCollection = ThemeCollection(with: ThemeStyle.preferredStyle)

Expand Down Expand Up @@ -126,4 +130,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

OCCoreManager.shared.handleEvents(forBackgroundURLSession: identifier, completionHandler: completionHandler)
}

// MARK: UISceneSession Lifecycle
@available(iOS 13.0, *)
func application(_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

@available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// DiscardSceneAction.swift
// ownCloud
//
// Created by Matthias Hühne on 06.09.19.
// Copyright © 2019 ownCloud GmbH. All rights reserved.
//

/*
* Copyright (C) 2019, ownCloud GmbH.
*
* This code is covered by the GNU Public License Version 3.
*
* For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/
* You should have received a copy of this license along with this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.en.html>.
*
*/

import UIKit
import ownCloudSDK
import MobileCoreServices

@available(iOS 13.0, *)
class DiscardSceneAction: Action {
override class var identifier : OCExtensionIdentifier? { return OCExtensionIdentifier("com.owncloud.action.discardscene") }
override class var category : ActionCategory? { return .normal }
override class var name : String { return "Close Window".localized }
override class var locations : [OCExtensionLocationIdentifier]? { return [.moreFolder] }

// MARK: - Extension matching
override class func applicablePosition(forContext: ActionContext) -> ActionPosition {

if UIDevice.current.isIpad() {
if let viewController = forContext.viewController, viewController.view.window?.windowScene?.userActivity != nil {
return .first
}
}

return .none
}

// MARK: - Action implementation
override func run() {
guard let viewController = context.viewController else {
self.completed(with: NSError(ocError: .insufficientParameters))
return
}

if UIDevice.current.isIpad() {
if let scene = viewController.view.window?.windowScene {
UIApplication.shared.requestSceneSessionDestruction(scene.session, options: nil) { (_) in
}
}
}
}

override class func iconForLocation(_ location: OCExtensionLocationIdentifier) -> UIImage? {
return UIImage(systemName: "xmark.square")?.tinted(with: Theme.shared.activeCollection.tintColor)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class OpenInAction: Action {
}

override class func iconForLocation(_ location: OCExtensionLocationIdentifier) -> UIImage? {
if location == .moreItem {
if location == .moreItem || location == .moreFolder {
return UIImage(named: "open-in")
}

Expand Down
60 changes: 60 additions & 0 deletions ownCloud/Client/Actions/Actions+Extensions/OpenSceneAction.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// OpenSceneAction.swift
// ownCloud
//
// Created by Matthias Hühne on 10.09.19.
// Copyright © 2019 ownCloud GmbH. All rights reserved.
//

/*
* Copyright (C) 2019, ownCloud GmbH.
*
* This code is covered by the GNU Public License Version 3.
*
* For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/
* You should have received a copy of this license along with this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.en.html>.
*
*/

import UIKit
import ownCloudSDK
import MobileCoreServices

@available(iOS 13.0, *)
class OpenSceneAction: Action {
override class var identifier : OCExtensionIdentifier? { return OCExtensionIdentifier("com.owncloud.action.openscene") }
override class var category : ActionCategory? { return .normal }
override class var name : String { return "Open in a new Window".localized }
override class var locations : [OCExtensionLocationIdentifier]? { return [.moreItem] }

// MARK: - Extension matching
override class func applicablePosition(forContext: ActionContext) -> ActionPosition {

if UIDevice.current.isIpad() {
if forContext.items.count == 1 {
return .first
}
}

return .none
}

// MARK: - Action implementation
override func run() {
guard let viewController = context.viewController else {
self.completed(with: NSError(ocError: .insufficientParameters))
return
}

if UIDevice.current.isIpad() {
if context.items.count == 1, let item = context.items.first, let tabBarController = viewController.tabBarController as? ClientRootViewController {
let activity = OpenItemUserActivity(detailItem: item, detailBookmark: tabBarController.bookmark)
UIApplication.shared.requestSceneSessionActivation(nil, userActivity: activity.openItemUserActivity, options: nil)
}
}
}

override class func iconForLocation(_ location: OCExtensionLocationIdentifier) -> UIImage? {
return UIImage(systemName: "uiwindow.split.2x1")?.tinted(with: Theme.shared.activeCollection.tintColor)
}
}
Loading

0 comments on commit 4e47f9b

Please sign in to comment.