66//
77
88import UIKit
9+ import SwiftUI
910
1011class FileDetailsViewController : BaseViewController < FilePreviewViewModel > {
1112 override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
@@ -112,24 +113,84 @@ class FileDetailsViewController: BaseViewController<FilePreviewViewModel> {
112113 }
113114
114115 @objc func showShareMenu( _ sender: Any ) {
115- var menuItems : [ FileMenuViewController . MenuItem ] = [ ]
116+ var menuItems : [ FileMenuViewModel . MenuItem ] = [ ]
116117
117- menuItems. append ( FileMenuViewController . MenuItem ( type: . shareToAnotherApp, action: { [ self ] in
118- shareWithOtherApps ( )
119- } ) )
118+ // Share to Permanent - only for files with ownership
119+ if file. permissions. contains ( . ownership) {
120+ menuItems. append ( FileMenuViewModel . MenuItem ( type: . shareToPermanent, action: nil ) )
121+ }
122+
123+ // Share to another app - for files with share permission (not folders)
124+ if file. permissions. contains ( . share) && file. type. isFolder == false {
125+ menuItems. append ( FileMenuViewModel . MenuItem ( type: . shareToAnotherApp, action: { [ self ] in
126+ shareWithOtherApps ( )
127+ } ) )
128+ }
129+
130+ // Publish on the web - for files with delete permission
131+ if file. permissions. contains ( . delete) {
132+ menuItems. append ( FileMenuViewModel . MenuItem ( type: . publish, action: { [ self ] in
133+ publishAction ( )
134+ } ) )
135+ }
120136
121- if let publicURL = viewModel? . publicURL {
122- menuItems. append ( FileMenuViewController . MenuItem ( type: . getLink, action: { [ self ] in
123- share ( url: publicURL)
137+ // Download - for files with read permission (not folders)
138+ if file. permissions. contains ( . read) && file. type. isFolder == false {
139+ menuItems. append ( FileMenuViewModel . MenuItem ( type: . download, action: { [ weak self] in
140+ guard let self = self else { return }
141+ // Store the file reference before dismissing
142+ let fileToDownload = self . file!
143+
144+ // First dismiss the menu
145+ if let menuHostingController = self . presentedViewController {
146+ menuHostingController. dismiss ( animated: true ) {
147+ // Then dismiss the preview and notify delegate
148+ self . navigationController? . dismiss ( animated: true ) {
149+ // Use delegate to request download from MainViewController
150+ self . delegate? . filePreviewNavigationControllerRequestsDownload ( self , file: fileToDownload)
151+ }
152+ }
153+ }
124154 } ) )
125- } else if self . file. permissions. contains ( . ownership) {
126- menuItems. append ( FileMenuViewController . MenuItem ( type: . shareToPermanent, action: nil ) )
127155 }
156+
157+ let swiftUIView = FileMoreMenuView (
158+ fileViewModel: file,
159+ menuItems: menuItems,
160+ onDismiss: { [ weak self] in
161+ // Only dismiss the menu overlay, not the details view
162+ self ? . presentedViewController? . dismiss ( animated: true )
163+ } ,
164+ onShareManagementRequested: { [ weak self] file in
165+ // Don't dismiss the details view - just dismiss the menu and present share management on top
166+ if let hostingController = self ? . presentedViewController {
167+ hostingController. dismiss ( animated: true ) {
168+ self ? . presentShareManagement ( for: file)
169+ }
170+ }
171+ } ,
172+ downloadHandler: nil
173+ )
174+
175+ let hostingController = UIHostingController ( rootView: swiftUIView)
176+ hostingController. modalPresentationStyle = UIModalPresentationStyle . overFullScreen
177+ hostingController. modalTransitionStyle = UIModalTransitionStyle . crossDissolve
178+ hostingController. view. backgroundColor = UIColor . clear
179+
180+ present ( hostingController, animated: true )
181+ }
128182
129- let vc = FileMenuViewController ( )
130- vc. fileViewModel = file
131- vc. menuItems = menuItems
132- present ( vc, animated: true )
183+ private func presentShareManagement( for file: FileModel ) {
184+ let shareContainerView = ShareContainerView ( fileModel: file)
185+ let hostingController = UIHostingController ( rootView: shareContainerView)
186+ hostingController. modalPresentationStyle = UIModalPresentationStyle . pageSheet
187+ if #available( iOS 15 . 0 , * ) {
188+ if let sheet = hostingController. sheetPresentationController {
189+ sheet. detents = [ . large( ) ]
190+ sheet. prefersGrabberVisible = true
191+ }
192+ }
193+ present ( hostingController, animated: true )
133194 }
134195
135196 @objc func closeButtonAction( _ sender: Any ) {
@@ -178,13 +239,16 @@ class FileDetailsViewController: BaseViewController<FilePreviewViewModel> {
178239 }
179240
180241 private func share( url: URL ) {
181- // For now, dismiss the menu in case another one opens so we avoid crash.
182- documentInteractionController. dismissMenu ( animated: true )
242+ let activityViewController = UIActivityViewController ( activityItems: [ url] , applicationActivities: nil )
243+
244+ // For iPad support
245+ if let popover = activityViewController. popoverPresentationController {
246+ popover. sourceView = view
247+ popover. sourceRect = CGRect ( x: view. bounds. midX, y: view. bounds. midY, width: 0 , height: 0 )
248+ popover. permittedArrowDirections = [ ]
249+ }
183250
184- documentInteractionController. url = url
185- documentInteractionController. uti = url. typeIdentifier ?? " public.data, public.content "
186- documentInteractionController. name = url. localizedName ?? url. lastPathComponent
187- documentInteractionController. presentOptionsMenu ( from: . zero, in: view, animated: true )
251+ present ( activityViewController, animated: true )
188252 }
189253
190254 private func segmentedControlChangedAction( ) -> ( ( FileDetailsMenuCollectionViewCell ) -> Void ) {
@@ -216,8 +280,11 @@ class FileDetailsViewController: BaseViewController<FilePreviewViewModel> {
216280 }
217281
218282 func shareWithOtherApps( ) {
219- if let fileName = self . viewModel? . fileName ( ) ,
220- let localURL = fileHelper. url ( forFileNamed: fileName) {
283+ // Check for file using displayName + extension (matches DownloadManagerGCD naming)
284+ let fileExtension = ( file. uploadFileName as NSString ) . pathExtension
285+ let fileName = !fileExtension. isEmpty ? " \( file. name) . \( fileExtension) " : file. name
286+
287+ if let localURL = fileHelper. url ( forFileNamed: fileName) {
221288 share ( url: localURL)
222289 } else {
223290 let preparingAlert = UIAlertController ( title: " Preparing File.. " . localized ( ) , message: nil , preferredStyle: . alert)
@@ -240,6 +307,70 @@ class FileDetailsViewController: BaseViewController<FilePreviewViewModel> {
240307 }
241308 }
242309 }
310+
311+ func publishAction( ) {
312+ let title = String ( format: " \( String . publish) \" %@ \" ? " , file. name)
313+ showActionDialog (
314+ styled: . simpleWithDescription,
315+ withTitle: title,
316+ description: . publishDescription,
317+ positiveButtonTitle: . publish,
318+ positiveAction: { [ weak self] in
319+ self ? . actionDialog? . dismiss ( )
320+ self ? . publish ( )
321+ } ,
322+ overlayView: nil
323+ )
324+ }
325+
326+ private func publish( ) {
327+ showSpinner ( )
328+
329+ // Get the current archive number
330+ guard let archiveNbr = AuthenticationManager . shared. session? . selectedArchive? . archiveNbr else {
331+ hideSpinner ( )
332+ showErrorAlert ( message: " Unable to publish file " )
333+ return
334+ }
335+
336+ // First, get the public root folder
337+ let filesRepository = FilesRepository ( )
338+ filesRepository. getPublicRoot ( archiveNbr: archiveNbr) { [ weak self] ( folder, error) in
339+ guard let self = self else { return }
340+
341+ if let error = error {
342+ self . hideSpinner ( )
343+ self . showErrorAlert ( message: error. localizedDescription)
344+ return
345+ }
346+
347+ guard let publicRootFolder = folder else {
348+ self . hideSpinner ( )
349+ self . showErrorAlert ( message: " Unable to get public folder " )
350+ return
351+ }
352+
353+ // Now relocate (copy) the file to the public folder
354+ filesRepository. relocate (
355+ files: [ self . file] ,
356+ folderLinkId: publicRootFolder. folderLinkId,
357+ isCopy: true
358+ ) { error in
359+ self . hideSpinner ( )
360+
361+ if let error = error {
362+ self . showErrorAlert ( message: error. localizedDescription)
363+ } else {
364+ if self . file. type. isFolder {
365+ self . view. showNotificationBanner ( height: Constants . Design. bannerHeight, title: " Folder published successfully " . localized ( ) )
366+ } else {
367+ self . view. showNotificationBanner ( height: Constants . Design. bannerHeight, title: " File published successfully " . localized ( ) )
368+ }
369+ }
370+ }
371+ }
372+ }
373+
243374}
244375
245376// MARK: - UICollectionViewDataSource
0 commit comments