diff --git a/CHANGELOG.md b/CHANGELOG.md
index e18cc6069..f6bf0923b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,25 @@
+Changelog for ownCloud iOS Client [12.0.1] (2023-06-15)
+=======================================
+The following sections list the changes in ownCloud iOS Client 12.0.1 relevant to
+ownCloud admins and users.
+
+[12.0.1]: https://github.com/owncloud/ios-app/compare/milestone/12.0.0...milestone/12.0.1
+
+Summary
+-------
+
+* Bugfix - Several Bug Fixes: [#1220](https://github.com/owncloud/ios-app/pull/1220)
+
+Details
+-------
+
+* Bugfix - Several Bug Fixes: [#1220](https://github.com/owncloud/ios-app/pull/1220)
+
+ Fixed keyboard, media streaming, full screen mode, offline indicator, duplicated sharing
+ option, and UI issues.
+
+ https://github.com/owncloud/ios-app/pull/1220
+
Changelog for ownCloud iOS Client [12.0.0] (2023-06-12)
=======================================
The following sections list the changes in ownCloud iOS Client 12.0.0 relevant to
diff --git a/changelog/12.0.1_2023-06-15/1220 b/changelog/12.0.1_2023-06-15/1220
new file mode 100644
index 000000000..7f70d45dd
--- /dev/null
+++ b/changelog/12.0.1_2023-06-15/1220
@@ -0,0 +1,5 @@
+Bugfix: Several Bug Fixes
+
+Fixed keyboard, media streaming, full screen mode, offline indicator, duplicated sharing option, and UI issues.
+
+https://github.com/owncloud/ios-app/pull/1220
diff --git a/fastlane/metadata-emm/en-US/release_notes.txt b/fastlane/metadata-emm/en-US/release_notes.txt
index 741fea434..84555fb29 100644
--- a/fastlane/metadata-emm/en-US/release_notes.txt
+++ b/fastlane/metadata-emm/en-US/release_notes.txt
@@ -1,26 +1,3 @@
-• Version 12 Major Release
-Rearchitectured for iOS 15 and later.
+• Bug Fixes
+Fixed keyboard, media streaming, full screen mode, offline indicator, duplicated sharing option, and UI issues.
-• ownCloud Infinite Scale support
-Support for Spaces, Authenticated WebFinger and other new oCIS features.
-
-• New Search Capabilities
-Powerful new search UI, saved searches and search templates.
-
-• New Navigation
-Navigate via the new sidebar, breadcrumbs and browser controls.
-
-• Role-based Sharing Interface
-The new role-based sharing user interface makes creating and editing shares and links even easier.
-
-• Grid View Modes
-Switch between list and several, different grid modes to display your folder's contents in new ways.
-
-• App Provider support
-Create and edit new documents through app providers on servers that support them.
-
-• Improved Theming
-The updated dark and light themes make use of a new, CSS-based theming system.
-
-• MDM Enhancements
-Many new MDM parameters.
diff --git a/fastlane/metadata-owncloud-online/en-US/release_notes.txt b/fastlane/metadata-owncloud-online/en-US/release_notes.txt
index 741fea434..84555fb29 100644
--- a/fastlane/metadata-owncloud-online/en-US/release_notes.txt
+++ b/fastlane/metadata-owncloud-online/en-US/release_notes.txt
@@ -1,26 +1,3 @@
-• Version 12 Major Release
-Rearchitectured for iOS 15 and later.
+• Bug Fixes
+Fixed keyboard, media streaming, full screen mode, offline indicator, duplicated sharing option, and UI issues.
-• ownCloud Infinite Scale support
-Support for Spaces, Authenticated WebFinger and other new oCIS features.
-
-• New Search Capabilities
-Powerful new search UI, saved searches and search templates.
-
-• New Navigation
-Navigate via the new sidebar, breadcrumbs and browser controls.
-
-• Role-based Sharing Interface
-The new role-based sharing user interface makes creating and editing shares and links even easier.
-
-• Grid View Modes
-Switch between list and several, different grid modes to display your folder's contents in new ways.
-
-• App Provider support
-Create and edit new documents through app providers on servers that support them.
-
-• Improved Theming
-The updated dark and light themes make use of a new, CSS-based theming system.
-
-• MDM Enhancements
-Many new MDM parameters.
diff --git a/fastlane/metadata/en-US/release_notes.txt b/fastlane/metadata/en-US/release_notes.txt
index 741fea434..84555fb29 100644
--- a/fastlane/metadata/en-US/release_notes.txt
+++ b/fastlane/metadata/en-US/release_notes.txt
@@ -1,26 +1,3 @@
-• Version 12 Major Release
-Rearchitectured for iOS 15 and later.
+• Bug Fixes
+Fixed keyboard, media streaming, full screen mode, offline indicator, duplicated sharing option, and UI issues.
-• ownCloud Infinite Scale support
-Support for Spaces, Authenticated WebFinger and other new oCIS features.
-
-• New Search Capabilities
-Powerful new search UI, saved searches and search templates.
-
-• New Navigation
-Navigate via the new sidebar, breadcrumbs and browser controls.
-
-• Role-based Sharing Interface
-The new role-based sharing user interface makes creating and editing shares and links even easier.
-
-• Grid View Modes
-Switch between list and several, different grid modes to display your folder's contents in new ways.
-
-• App Provider support
-Create and edit new documents through app providers on servers that support them.
-
-• Improved Theming
-The updated dark and light themes make use of a new, CSS-based theming system.
-
-• MDM Enhancements
-Many new MDM parameters.
diff --git a/ownCloud File Provider UI/Info.plist b/ownCloud File Provider UI/Info.plist
index 718845e3d..8df1972b8 100644
--- a/ownCloud File Provider UI/Info.plist
+++ b/ownCloud File Provider UI/Info.plist
@@ -30,7 +30,7 @@
NSExtensionFileProviderActionIdentifier
com.owncloud.FileProviderUI.Share
NSExtensionFileProviderActionName
- Share
+ Share by cloud
NSExtensionMainStoryboard
diff --git a/ownCloud.xcodeproj/project.pbxproj b/ownCloud.xcodeproj/project.pbxproj
index 987a6995e..a17ff7387 100644
--- a/ownCloud.xcodeproj/project.pbxproj
+++ b/ownCloud.xcodeproj/project.pbxproj
@@ -5137,8 +5137,8 @@
APP_BUILD_FLAGS = "$(inherited)";
APP_BUILD_FLAGS_SWIFT = "$(APP_BUILD_FLAGS)";
APP_PRODUCT_NAME = ownCloud;
- APP_SHORT_VERSION = 12.0;
- APP_VERSION = 267;
+ APP_SHORT_VERSION = 12.0.1;
+ APP_VERSION = 268;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
@@ -5207,8 +5207,8 @@
APP_BUILD_FLAGS = "$(inherited)";
APP_BUILD_FLAGS_SWIFT = "$(APP_BUILD_FLAGS)";
APP_PRODUCT_NAME = ownCloud;
- APP_SHORT_VERSION = 12.0;
- APP_VERSION = 267;
+ APP_SHORT_VERSION = 12.0.1;
+ APP_VERSION = 268;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
diff --git a/ownCloud/Client/Viewer/Media/MediaDisplayViewController.swift b/ownCloud/Client/Viewer/Media/MediaDisplayViewController.swift
index 0d648e43d..60bae6581 100644
--- a/ownCloud/Client/Viewer/Media/MediaDisplayViewController.swift
+++ b/ownCloud/Client/Viewer/Media/MediaDisplayViewController.swift
@@ -71,25 +71,43 @@ class MediaDisplayViewController : DisplayViewController {
NotificationCenter.default.removeObserver(self, name: Notification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
}
- override func viewDidLoad() {
- super.viewDidLoad()
-
- playerViewController = AVPlayerViewController()
-
- guard let playerViewController = playerViewController else { return }
-
- addChild(playerViewController)
- self.view.addSubview(playerViewController.view)
- playerViewController.didMove(toParent: self)
+ var showLoadingIndicator: Bool = false {
+ didSet {
+ if oldValue != showLoadingIndicator {
+ if showLoadingIndicator {
+ // Show loading indicator
+ let indeterminateProgress: Progress = .indeterminate()
+ indeterminateProgress.isCancellable = false
+
+ let messageView = ComposedMessageView.infoBox(additionalElements: [
+ .spacing(25),
+ .progressCircle(with: indeterminateProgress),
+ .spacing(25),
+ .title("Loading…".localized, alignment: .centered)
+ ], withRoundedBackgroundView: true)
+
+ loadingIndicator = messageView
+ } else {
+ // Remove loading indicator
+ loadingIndicator = nil
+ }
+ }
+ }
+ }
- playerViewController.view.translatesAutoresizingMaskIntoConstraints = false
+ private var loadingIndicator: ComposedMessageView? {
+ willSet {
+ loadingIndicator?.removeFromSuperview()
+ }
+ didSet {
+ if let loadingIndicator {
+ view.embed(centered: loadingIndicator)
+ }
+ }
+ }
- NSLayoutConstraint.activate([
- playerViewController.view.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
- playerViewController.view.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
- playerViewController.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
- playerViewController.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
- ])
+ override func viewDidLoad() {
+ super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(handleDidEnterBackgroundNotification), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleWillEnterForegroundNotification), name: UIApplication.willEnterForegroundNotification, object: nil)
@@ -131,7 +149,28 @@ class MediaDisplayViewController : DisplayViewController {
return (OCAppIdentity.shared.userDefaults?.downloadMediaFiles ?? false)
}
+ private var timeControlStatusObservation: NSKeyValueObservation?
+
override func renderItem(completion: @escaping (Bool) -> Void) {
+ if playerViewController == nil {
+ playerViewController = AVPlayerViewController()
+
+ if let playerViewController {
+ addChild(playerViewController)
+ self.view.addSubview(playerViewController.view)
+ playerViewController.didMove(toParent: self)
+
+ playerViewController.view.translatesAutoresizingMaskIntoConstraints = false
+
+ NSLayoutConstraint.activate([
+ playerViewController.view.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
+ playerViewController.view.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
+ playerViewController.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
+ playerViewController.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
+ ])
+ }
+ }
+
if let directURL = itemDirectURL {
playerItemStatusObservation?.invalidate()
playerItemStatusObservation = nil
@@ -149,7 +188,7 @@ class MediaDisplayViewController : DisplayViewController {
if player == nil {
player = AVPlayer(playerItem: playerItem)
player?.allowsExternalPlayback = true
- if let playerViewController = self.playerViewController {
+ if let playerViewController {
playerViewController.updatesNowPlayingInfoCenter = false
if UIApplication.shared.applicationState == .active {
@@ -157,42 +196,18 @@ class MediaDisplayViewController : DisplayViewController {
}
}
- // Add artwork to the player overlay if corresponding meta data item is available in the asset
- if !(player?.isVideoAvailable ?? false), let artworkMetadataItem = asset.commonMetadata.filter({$0.commonKey == AVMetadataKey.commonKeyArtwork}).first,
- let imageData = artworkMetadataItem.dataValue,
- let overlayView = playerViewController?.contentOverlayView {
-
- if let artworkImage = UIImage(data: imageData) {
-
- // Construct image view overlay for AVPlayerViewController
- let imageView = UIImageView(image: artworkImage)
- imageView.translatesAutoresizingMaskIntoConstraints = false
- imageView.contentMode = .scaleAspectFit
- playerViewController?.contentOverlayView?.addSubview(imageView)
-
- NSLayoutConstraint.activate([
- imageView.leadingAnchor.constraint(equalTo: overlayView.leadingAnchor),
- imageView.trailingAnchor.constraint(equalTo: overlayView.trailingAnchor),
- imageView.topAnchor.constraint(equalTo: overlayView.topAnchor),
- imageView.bottomAnchor.constraint(equalTo: overlayView.bottomAnchor)
- ])
-
- // Create MPMediaItemArtwork to be shown in 'now playing' in the lock screen
- mediaItemArtwork = MPMediaItemArtwork(boundsSize: artworkImage.size, requestHandler: { (_) -> UIImage in
- return artworkImage
- })
- }
- }
-
- // Extract title meta-data item
- mediaItemTitle = asset.commonMetadata.filter({$0.commonKey == AVMetadataKey.commonKeyTitle}).first?.value as? String
+ // Start with the loading indicator active
+ showLoadingIndicator = true
- // Extract artist meta-data item
- mediaItemArtist = asset.commonMetadata.filter({$0.commonKey == AVMetadataKey.commonKeyArtist}).first?.value as? String
+ // .. it will be updated as soon as the player starts playing ..
+ timeControlStatusObservation = player?.observe(\AVPlayer.timeControlStatus, changeHandler: { [weak self] player, change in
+ self?.updateLoadingIndicator()
+ })
// Setup player status observation handler
playerStatusObservation = player!.observe(\AVPlayer.status, options: [.initial, .new], changeHandler: { [weak self] (player, _) in
if player.status == .readyToPlay {
+ self?.updateMediaMetadata()
self?.setupRemoteTransportControls()
@@ -200,7 +215,11 @@ class MediaDisplayViewController : DisplayViewController {
try? AVAudioSession.sharedInstance().setActive(true)
if (self?.hasFocus)! {
+ // .. with playback starting here.
self?.player?.play()
+ } else {
+ // .. or the loading indicator being updated when the file is ready to play, here.
+ self?.updateLoadingIndicator()
}
self?.updateNowPlayingInfoCenter()
@@ -218,6 +237,55 @@ class MediaDisplayViewController : DisplayViewController {
}
}
+ private func updateLoadingIndicator() {
+ if let player {
+ let showLoadingIndicator = (player.timeControlStatus == .waitingToPlayAtSpecifiedRate)
+
+ OnMainThread(inline: true) {
+ self.showLoadingIndicator = showLoadingIndicator
+ }
+ }
+ }
+
+ private func updateMediaMetadata() {
+ guard let asset = playerItem?.asset else { return }
+
+ // Add artwork to the player overlay if corresponding meta data item is available in the asset
+ if !(player?.isVideoAvailable ?? false), let artworkMetadataItem = asset.commonMetadata.filter({$0.commonKey == AVMetadataKey.commonKeyArtwork}).first,
+ let imageData = artworkMetadataItem.dataValue,
+ let overlayView = playerViewController?.contentOverlayView {
+
+ if let artworkImage = UIImage(data: imageData) {
+
+ // Construct image view overlay for AVPlayerViewController
+ OnMainThread(inline: true) { [weak self] in
+ let imageView = UIImageView(image: artworkImage)
+ imageView.translatesAutoresizingMaskIntoConstraints = false
+ imageView.contentMode = .scaleAspectFit
+ self?.playerViewController?.contentOverlayView?.addSubview(imageView)
+
+ NSLayoutConstraint.activate([
+ imageView.leadingAnchor.constraint(equalTo: overlayView.leadingAnchor),
+ imageView.trailingAnchor.constraint(equalTo: overlayView.trailingAnchor),
+ imageView.topAnchor.constraint(equalTo: overlayView.topAnchor),
+ imageView.bottomAnchor.constraint(equalTo: overlayView.bottomAnchor)
+ ])
+ }
+
+ // Create MPMediaItemArtwork to be shown in 'now playing' in the lock screen
+ mediaItemArtwork = MPMediaItemArtwork(boundsSize: artworkImage.size, requestHandler: { (_) -> UIImage in
+ return artworkImage
+ })
+ }
+ }
+
+ // Extract title meta-data item
+ mediaItemTitle = asset.commonMetadata.filter({$0.commonKey == AVMetadataKey.commonKeyTitle}).first?.value as? String
+
+ // Extract artist meta-data item
+ mediaItemArtist = asset.commonMetadata.filter({$0.commonKey == AVMetadataKey.commonKeyArtist}).first?.value as? String
+ }
+
private func present(error:Error?) {
guard let error = error else { return }
@@ -230,12 +298,18 @@ class MediaDisplayViewController : DisplayViewController {
}
}
+ private var isInBackground: Bool = false {
+ didSet {
+ playerViewController?.player = isInBackground ? nil : player
+ }
+ }
+
@objc private func handleDidEnterBackgroundNotification() {
- playerViewController?.player = nil
+ isInBackground = true
}
@objc private func handleWillEnterForegroundNotification() {
- playerViewController?.player = player
+ isInBackground = false
}
@objc private func handleAVPlayerItem(notification:Notification) {
diff --git a/ownCloud/Client/Viewer/PDF/PDFViewerViewController.swift b/ownCloud/Client/Viewer/PDF/PDFViewerViewController.swift
index 7e3b0bf12..ea8f5db47 100644
--- a/ownCloud/Client/Viewer/PDF/PDFViewerViewController.swift
+++ b/ownCloud/Client/Viewer/PDF/PDFViewerViewController.swift
@@ -116,7 +116,7 @@ class PDFViewerViewController: DisplayViewController, DisplayExtension, UIPopove
private var fullScreen: Bool = false {
didSet {
- self.navigationController?.setNavigationBarHidden(fullScreen, animated: true)
+ browserNavigationViewController?.setNavigationBarHidden(fullScreen, animated: true)
isFullScreenModeEnabled = fullScreen
pageCountButton.isHidden = fullScreen
pageCountContainerView.isHidden = fullScreen
diff --git a/ownCloud/Release Notes/ReleaseNotes.plist b/ownCloud/Release Notes/ReleaseNotes.plist
index 8d0f8d53d..5e3ad11b0 100644
--- a/ownCloud/Release Notes/ReleaseNotes.plist
+++ b/ownCloud/Release Notes/ReleaseNotes.plist
@@ -1669,7 +1669,7 @@ Added an optional "Wait for completion" option to the "Save File&
Title
Grid View Modes
Subtitle
- Switch between list and several, different grid modes to display your folder's contents in new ways.
+ Switch between list and several, different grid modes to display your folder's contents in new ways.
Type
New
ImageName
@@ -1707,6 +1707,23 @@ Added an optional "Wait for completion" option to the "Save File&
+
+ Version
+ 12.0.1
+ ReleaseNotes
+
+
+ Title
+ Bug Fixes
+ Subtitle
+ Fixed keyboard, media streaming, full screen mode, offline indicator, duplicated sharing option, and UI issues.
+ Type
+ Fix
+ ImageName
+ wrench
+
+
+
diff --git a/ownCloudAppFramework/Resources/de.lproj/Localizable.strings b/ownCloudAppFramework/Resources/de.lproj/Localizable.strings
index d3c3daaab..c5ab8c4bb 100644
--- a/ownCloudAppFramework/Resources/de.lproj/Localizable.strings
+++ b/ownCloudAppFramework/Resources/de.lproj/Localizable.strings
@@ -116,7 +116,7 @@
"Before last week" = "Vor letzter Woche";
">%d weeks ago" = "Vor >%d Wochen";
"This week" = "Diese Woche";
-"Since last week" = "Seit letzter WOche";
+"Since last week" = "Seit letzter Woche";
"Last %d weeks" = "Letzte %d Wochen";
"Before this month" = "Vor diesem Monat";
diff --git a/ownCloudAppShared/Branding/Branding+App.swift b/ownCloudAppShared/Branding/Branding+App.swift
index ae75df02a..4f3668a6d 100644
--- a/ownCloudAppShared/Branding/Branding+App.swift
+++ b/ownCloudAppShared/Branding/Branding+App.swift
@@ -372,8 +372,8 @@ extension Branding {
return url(forClassSettingsKey: .profileHelpURL) ?? nil
}
- public var sidebarLinks: Array? {
- if let values = computedValue(forClassSettingsKey: .sidebarLinks) as? Array> {
+ public var sidebarLinks: [SidebarLink]? {
+ if let values = computedValue(forClassSettingsKey: .sidebarLinks) as? [[String:String]] {
return values.compactMap { link in
if let title = link["title"], let urlString = link["url"], let url = URL(string: urlString) {
return SidebarLink(title: title, symbol: link["symbol"], image: link["image"], url: url)
diff --git a/ownCloudAppShared/Client/Account/Connection/Authentication Error Handling/AccountConnectionAuthErrorConsumer.swift b/ownCloudAppShared/Client/Account/Connection/Authentication Error Handling/AccountConnectionAuthErrorConsumer.swift
index 702895d11..a2b00916b 100644
--- a/ownCloudAppShared/Client/Account/Connection/Authentication Error Handling/AccountConnectionAuthErrorConsumer.swift
+++ b/ownCloudAppShared/Client/Account/Connection/Authentication Error Handling/AccountConnectionAuthErrorConsumer.swift
@@ -234,6 +234,7 @@ class AccountConnectionAuthErrorConsumer: AccountConnectionConsumer, AccountConn
OCSynchronized(self) {
self.skipAuthorizationFailure = false // Auth failure fixed -> allow new failures to prompt for sign in again
}
+ self.connection?.updateConnectionStatusSummary() // Trigger status summary update to clear connection._authFailureStatus
} else if let nsError = error as NSError?, !nsError.isOCError(withCode: .authorizationCancelled) {
// Error updating authentication -> inform the user and provide option to retry
context.alertQueue?.async { [weak self] (queueCompletionHandler) in
diff --git a/ownCloudAppShared/Client/Collection Views/CollectionViewController.swift b/ownCloudAppShared/Client/Collection Views/CollectionViewController.swift
index 6f052bd35..b9d428724 100644
--- a/ownCloudAppShared/Client/Collection Views/CollectionViewController.swift
+++ b/ownCloudAppShared/Client/Collection Views/CollectionViewController.swift
@@ -31,13 +31,16 @@ open class CollectionViewController: UIViewController, UICollectionViewDelegate,
var didHighlightItemReference: Bool = false
var hideNavigationBar: Bool?
+ var compressForKeyboard: Bool
+
var emptyCellRegistration: UICollectionView.CellRegistration?
- public init(context inContext: ClientContext?, sections inSections: [CollectionViewSection]?, useStackViewRoot: Bool = false, hierarchic: Bool = false, useWrappedIdentifiers: Bool = false, highlightItemReference: OCDataItemReference? = nil) {
+ public init(context inContext: ClientContext?, sections inSections: [CollectionViewSection]?, useStackViewRoot: Bool = false, hierarchic: Bool = false, compressForKeyboard: Bool = false, useWrappedIdentifiers: Bool = false, highlightItemReference: OCDataItemReference? = nil) {
supportsHierarchicContent = hierarchic
usesStackViewRoot = useStackViewRoot
self.useWrappedIdentifiers = hierarchic ? hierarchic : useWrappedIdentifiers
self.highlightItemReference = highlightItemReference
+ self.compressForKeyboard = compressForKeyboard
super.init(nibName: nil, bundle: nil)
@@ -166,8 +169,8 @@ open class CollectionViewController: UIViewController, UICollectionViewDelegate,
if usesStackViewRoot {
createStackView()
- if let stackView = stackView {
- view.embed(toFillWith: stackView, enclosingAnchors: view.defaultAnchorSet)
+ if let stackView {
+ view.embed(toFillWith: stackView, enclosingAnchors: compressForKeyboard ? view.safeAreaWithKeyboardAnchorSet : view.safeAreaAnchorSet)
}
}
}
diff --git a/ownCloudAppShared/Client/Sharing/ShareViewController.swift b/ownCloudAppShared/Client/Sharing/ShareViewController.swift
index 3af47fa10..332cc7ee6 100644
--- a/ownCloudAppShared/Client/Sharing/ShareViewController.swift
+++ b/ownCloudAppShared/Client/Sharing/ShareViewController.swift
@@ -198,7 +198,7 @@ open class ShareViewController: CollectionViewController, SearchViewControllerDe
sections.append(optionsSection)
}
- super.init(context: shareControllerContext, sections: sections, useStackViewRoot: true)
+ super.init(context: shareControllerContext, sections: sections, useStackViewRoot: true, compressForKeyboard: true)
self.cssSelector = .grouped
diff --git a/ownCloudAppShared/Client/User Interface/BottomButtonBar.swift b/ownCloudAppShared/Client/User Interface/BottomButtonBar.swift
index 96042c674..84e3b000a 100644
--- a/ownCloudAppShared/Client/User Interface/BottomButtonBar.swift
+++ b/ownCloudAppShared/Client/User Interface/BottomButtonBar.swift
@@ -129,7 +129,7 @@ open class BottomButtonBar: ThemeCSSView {
constraints.append(contentsOf: [
promptLabel.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: 20),
promptLabel.trailingAnchor.constraint(lessThanOrEqualTo: leadingButtonAnchor, constant: -20),
- promptLabel.centerYAnchor.constraint(equalTo: safeAreaLayoutGuide.centerYAnchor),
+ promptLabel.centerYAnchor.constraint(equalTo: selectButton.centerYAnchor),
selectButton.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -20),
selectButton.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 20),
diff --git a/ownCloudAppShared/Client/User Interface/ComposedMessageView.swift b/ownCloudAppShared/Client/User Interface/ComposedMessageView.swift
index c5398ba2b..398e32c44 100644
--- a/ownCloudAppShared/Client/User Interface/ComposedMessageView.swift
+++ b/ownCloudAppShared/Client/User Interface/ComposedMessageView.swift
@@ -557,7 +557,7 @@ public extension ComposedMessageView {
static func infoBox(image: UIImage? = nil, title: String? = nil, subtitle: String? = nil, additionalElements: [ComposedMessageElement]? = nil, withRoundedBackgroundView: Bool = true) -> ComposedMessageView {
var elements: [ComposedMessageElement] = []
- if let image = image {
+ if let image {
let imageElement: ComposedMessageElement = .image(image, size: CGSize(width: 48, height: 48), alignment: .centered, cssSelectors: [.icon])
imageElement.insets = NSDirectionalEdgeInsets(top: 0, leading: 10, bottom: 10, trailing: 10)
elements.append(imageElement)
diff --git a/ownCloudAppShared/Client/View Controllers/ClientItemViewController.swift b/ownCloudAppShared/Client/View Controllers/ClientItemViewController.swift
index e320c9743..a1d190b35 100644
--- a/ownCloudAppShared/Client/View Controllers/ClientItemViewController.swift
+++ b/ownCloudAppShared/Client/View Controllers/ClientItemViewController.swift
@@ -211,7 +211,7 @@ open class ClientItemViewController: CollectionViewController, SortBarDelegate,
emptySection = CollectionViewSection(identifier: "empty", dataSource: emptySectionDataSource, cellStyle: .init(with: .fillSpace), cellLayout: .fullWidth(itemHeightDimension: .estimated(54), groupHeightDimension: .estimated(54), edgeSpacing: NSCollectionLayoutEdgeSpacing(leading: .fixed(0), top: .fixed(10), trailing: .fixed(0), bottom: .fixed(10)), contentInsets: NSDirectionalEdgeInsets(top: 10, leading: 20, bottom: 10, trailing: 20)), clientContext: itemControllerContext)
sections.append(emptySection!)
- super.init(context: itemControllerContext, sections: sections, useStackViewRoot: true, highlightItemReference: highlightItemReference)
+ super.init(context: itemControllerContext, sections: sections, useStackViewRoot: true, compressForKeyboard: true, highlightItemReference: highlightItemReference)
// Track query state and recompute content state when it changes
stateObservation = itemsListDataSource?.observe(\OCDataSource.state, options: [], changeHandler: { [weak self] query, change in
diff --git a/ownCloudAppShared/Client/View Controllers/Location Picker/ClientLocationPicker.swift b/ownCloudAppShared/Client/View Controllers/Location Picker/ClientLocationPicker.swift
index 491cb6601..a4b413cbf 100644
--- a/ownCloudAppShared/Client/View Controllers/Location Picker/ClientLocationPicker.swift
+++ b/ownCloudAppShared/Client/View Controllers/Location Picker/ClientLocationPicker.swift
@@ -303,7 +303,7 @@ public class ClientLocationPicker : NSObject {
context.add(permissionHandler: { [weak self] context, dataItemRecord, checkInteraction, viewController in
return self?.checkPermission(context: context, dataItemRecord: dataItemRecord, interaction: checkInteraction, viewController: viewController) ?? false
})
- context.viewControllerPusher = nil
+ context.viewControllerPusher = self
context.browserController = nil
context.navigationController = navigationController
context.permissions = [ .selection ]
@@ -382,6 +382,30 @@ public class ClientLocationPicker : NSObject {
}
}
+// MARK: - ViewControllerPusher
+// Implemented solely to disable .compressForKeyboard for the collection views in the picker, as the usage of the keyboardLayoutGuide
+// inexplicably leads to a bogus BottomBar layout when pushing the first "Files" view controller
+extension ClientLocationPicker : ViewControllerPusher {
+ public func pushViewController(context: ClientContext?, provider: (ClientContext) -> UIViewController?, push: Bool, animated: Bool) -> UIViewController? {
+ if let context {
+ let viewController = provider(context)
+
+ if let collectionViewController = viewController as? CollectionViewController {
+ // Disable .compressForKeyboard for CollectionViewController
+ collectionViewController.compressForKeyboard = false
+ }
+
+ if push, let viewController {
+ context.navigationController?.pushViewController(viewController, animated: animated)
+ }
+
+ return viewController
+ }
+
+ return nil
+ }
+}
+
extension ThemeCSSSelector {
static let accountList = ThemeCSSSelector(rawValue: "accountList")
}
diff --git a/ownCloudAppShared/User Interface/Browser Navigation Controller/BrowserNavigationViewController.swift b/ownCloudAppShared/User Interface/Browser Navigation Controller/BrowserNavigationViewController.swift
index bc0631725..3f46c603b 100644
--- a/ownCloudAppShared/User Interface/Browser Navigation Controller/BrowserNavigationViewController.swift
+++ b/ownCloudAppShared/User Interface/Browser Navigation Controller/BrowserNavigationViewController.swift
@@ -85,6 +85,8 @@ open class BrowserNavigationViewController: EmbeddingViewController, Themeable,
sideBarSeperatorView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(sideBarSeperatorView)
+ navigationBarTopConstraint = navigationBarTopConstraint(for: navigationBarHidden)
+
NSLayoutConstraint.activate([
contentContainerView.topAnchor.constraint(equalTo: view.topAnchor),
contentContainerView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
@@ -101,7 +103,7 @@ open class BrowserNavigationViewController: EmbeddingViewController, Themeable,
sideBarSeperatorView.leadingAnchor.constraint(equalTo: contentContainerView.leadingAnchor, constant: -1),
sideBarSeperatorView.widthAnchor.constraint(equalToConstant: 1),
- navigationView.topAnchor.constraint(equalTo: contentContainerView.safeAreaLayoutGuide.topAnchor),
+ navigationBarTopConstraint!,
navigationView.leadingAnchor.constraint(equalTo: contentContainerView.safeAreaLayoutGuide.leadingAnchor),
navigationView.trailingAnchor.constraint(equalTo: contentContainerView.safeAreaLayoutGuide.trailingAnchor)
])
@@ -124,6 +126,39 @@ open class BrowserNavigationViewController: EmbeddingViewController, Themeable,
navigationController?.isNavigationBarHidden = true
}
+ // MARK: - Navigation Bar
+ private var navigationBarTopConstraint: NSLayoutConstraint?
+ private func navigationBarTopConstraint(for hidden: Bool) -> NSLayoutConstraint {
+ if hidden {
+ return navigationView.bottomAnchor.constraint(equalTo: contentContainerView.topAnchor)
+ }
+
+ return navigationView.topAnchor.constraint(equalTo: contentContainerView.safeAreaLayoutGuide.topAnchor)
+ }
+
+ open var navigationBarHidden: Bool = false
+ open func setNavigationBarHidden(_ hidden: Bool, animated: Bool, completion: (() -> Void)? = nil) {
+ let updateLayout = {
+ self.navigationBarTopConstraint?.isActive = false
+ self.navigationBarTopConstraint = self.navigationBarTopConstraint(for: hidden)
+ self.navigationBarTopConstraint?.isActive = true
+ }
+
+ OnMainThread(inline: true) {
+ if animated {
+ UIView.animate(withDuration: 0.3, animations: {
+ updateLayout()
+ self.view.layoutIfNeeded()
+ }, completion: { _ in
+ completion?()
+ })
+ } else {
+ updateLayout()
+ completion?()
+ }
+ }
+ }
+
// MARK: - Push & Navigation
open func push(viewController: UIViewController, completion: BrowserNavigationHistory.CompletionHandler? = nil) {
push(item: BrowserNavigationItem(viewController: viewController), completion: completion)
@@ -519,3 +554,19 @@ extension BrowserNavigationViewController: UINavigationBarDelegate {
return .topAttached
}
}
+
+public extension UIViewController {
+ var browserNavigationViewController: BrowserNavigationViewController? {
+ var viewController: UIViewController? = self
+
+ while viewController != nil {
+ if let browserNavigationViewController = viewController as? BrowserNavigationViewController {
+ return browserNavigationViewController
+ }
+
+ viewController = viewController?.parent
+ }
+
+ return nil
+ }
+}
diff --git a/ownCloudAppShared/User Interface/SegmentView/UIView+EmbedAndLayout.swift b/ownCloudAppShared/User Interface/SegmentView/UIView+EmbedAndLayout.swift
index 36b64c171..4a74781d6 100644
--- a/ownCloudAppShared/User Interface/SegmentView/UIView+EmbedAndLayout.swift
+++ b/ownCloudAppShared/User Interface/SegmentView/UIView+EmbedAndLayout.swift
@@ -46,6 +46,10 @@ public extension UIView {
return AnchorSet(leadingAnchor: safeAreaLayoutGuide.leadingAnchor, trailingAnchor: safeAreaLayoutGuide.trailingAnchor, topAnchor: safeAreaLayoutGuide.topAnchor, bottomAnchor: safeAreaLayoutGuide.bottomAnchor, centerXAnchor: safeAreaLayoutGuide.centerXAnchor, centerYAnchor: safeAreaLayoutGuide.centerYAnchor)
}
+ var safeAreaWithKeyboardAnchorSet : AnchorSet {
+ return AnchorSet(leadingAnchor: safeAreaLayoutGuide.leadingAnchor, trailingAnchor: safeAreaLayoutGuide.trailingAnchor, topAnchor: safeAreaLayoutGuide.topAnchor, bottomAnchor: keyboardLayoutGuide.topAnchor, centerXAnchor: safeAreaLayoutGuide.centerXAnchor, centerYAnchor: safeAreaLayoutGuide.centerYAnchor)
+ }
+
@discardableResult func embedHorizontally(views: [UIView], insets: NSDirectionalEdgeInsets, enclosingAnchors: AnchorSet? = nil, limitHeight: Bool = false, spacingProvider: SpacingProvider? = nil, constraintsModifier: ConstraintsModifier? = nil) -> ConstraintSet {
var viewIdx : Int = 0
var previousView: UIView?