Add file provider init code

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
This commit is contained in:
Claudio Cambra 2022-03-29 15:00:59 +02:00 committed by Claudio Cambra
parent 9b77da6569
commit 9a86bb2be3
No known key found for this signature in database
GPG Key ID: C839200C384636B0
15 changed files with 571 additions and 4 deletions

1
.gitignore vendored
View File

@ -88,6 +88,7 @@ dlldata.c
# macOS specific
xcuserdata/
**/.DS_Store
**/Carthage/
# Visual C++ cache files
ipch/

View File

@ -15,12 +15,26 @@ if(APPLE)
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
COMMENT building Mac Overlay icons
VERBATIM)
add_dependencies(mac_overlayplugin nextcloud) # for the ownCloud.icns to be generated
add_custom_target( mac_fileproviderplugin ALL
xcodebuild ARCHS=${CMAKE_OSX_ARCHITECTURES} ONLY_ACTIVE_ARCH=NO
-project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
-target FileProviderExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
"OC_APPLICATION_NAME=${APPLICATION_NAME}"
"OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
COMMENT building macOS File Provider extension
VERBATIM)
add_dependencies(mac_overlayplugin mac_fileproviderplugin nextcloud) # for the ownCloud.icns to be generated
if (BUILD_OWNCLOUD_OSX_BUNDLE)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
USE_SOURCE_PERMISSIONS)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FileProviderExt.appex
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
USE_SOURCE_PERMISSIONS)
endif()
endif()

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
import FileProvider
class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
private let enumeratedItemIdentifier: NSFileProviderItemIdentifier
private let anchor = NSFileProviderSyncAnchor("an anchor".data(using: .utf8)!)
init(enumeratedItemIdentifier: NSFileProviderItemIdentifier) {
self.enumeratedItemIdentifier = enumeratedItemIdentifier
super.init()
}
func invalidate() {
// TODO: perform invalidation of server connection if necessary
}
func enumerateItems(for observer: NSFileProviderEnumerationObserver, startingAt page: NSFileProviderPage) {
/* TODO:
- inspect the page to determine whether this is an initial or a follow-up request
If this is an enumerator for a directory, the root container or all directories:
- perform a server request to fetch directory contents
If this is an enumerator for the active set:
- perform a server request to update your local database
- fetch the active set from your local database
- inform the observer about the items returned by the server (possibly multiple times)
- inform the observer that you are finished with this page
*/
observer.didEnumerate([FileProviderItem(identifier: NSFileProviderItemIdentifier("a file"))])
observer.finishEnumerating(upTo: nil)
}
func enumerateChanges(for observer: NSFileProviderChangeObserver, from anchor: NSFileProviderSyncAnchor) {
/* TODO:
- query the server for updates since the passed-in sync anchor
If this is an enumerator for the active set:
- note the changes in your local database
- inform the observer about item deletions and updates (modifications + insertions)
- inform the observer when you have finished enumerating up to a subsequent sync anchor
*/
observer.finishEnumeratingChanges(upTo: anchor, moreComing: false)
}
func currentSyncAnchor(completionHandler: @escaping (NSFileProviderSyncAnchor?) -> Void) {
completionHandler(anchor)
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>$(AppIdentifierPrefix)$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
import FileProvider
class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension {
required init(domain: NSFileProviderDomain) {
// TODO: The containing application must create a domain using `NSFileProviderManager.add(_:, completionHandler:)`. The system will then launch the application extension process, call `FileProviderExtension.init(domain:)` to instantiate the extension for that domain, and call methods on the instance.
super.init()
}
func invalidate() {
// TODO: cleanup any resources
}
func item(for identifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) -> Progress {
// resolve the given identifier to a record in the model
// TODO: implement the actual lookup
completionHandler(FileProviderItem(identifier: identifier), nil)
return Progress()
}
func fetchContents(for itemIdentifier: NSFileProviderItemIdentifier, version requestedVersion: NSFileProviderItemVersion?, request: NSFileProviderRequest, completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void) -> Progress {
// TODO: implement fetching of the contents for the itemIdentifier at the specified version
completionHandler(nil, nil, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:]))
return Progress()
}
func createItem(basedOn itemTemplate: NSFileProviderItem, fields: NSFileProviderItemFields, contents url: URL?, options: NSFileProviderCreateItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
// TODO: a new item was created on disk, process the item's creation
completionHandler(itemTemplate, [], false, nil)
return Progress()
}
func modifyItem(_ item: NSFileProviderItem, baseVersion version: NSFileProviderItemVersion, changedFields: NSFileProviderItemFields, contents newContents: URL?, options: NSFileProviderModifyItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
// TODO: an item was modified on disk, process the item's modification
completionHandler(nil, [], false, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:]))
return Progress()
}
func deleteItem(identifier: NSFileProviderItemIdentifier, baseVersion version: NSFileProviderItemVersion, options: NSFileProviderDeleteItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (Error?) -> Void) -> Progress {
// TODO: an item was deleted on disk, process the item's deletion
completionHandler(NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:]))
return Progress()
}
func enumerator(for containerItemIdentifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest) throws -> NSFileProviderEnumerator {
return FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier)
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
import FileProvider
import UniformTypeIdentifiers
class FileProviderItem: NSObject, NSFileProviderItem {
// TODO: implement an initializer to create an item from your extension's backing model
// TODO: implement the accessors to return the values from your extension's backing model
private let identifier: NSFileProviderItemIdentifier
init(identifier: NSFileProviderItemIdentifier) {
self.identifier = identifier
}
var itemIdentifier: NSFileProviderItemIdentifier {
return identifier
}
var parentItemIdentifier: NSFileProviderItemIdentifier {
return .rootContainer
}
var capabilities: NSFileProviderItemCapabilities {
return [.allowsReading, .allowsWriting, .allowsRenaming, .allowsReparenting, .allowsTrashing, .allowsDeleting]
}
var itemVersion: NSFileProviderItemVersion {
NSFileProviderItemVersion(contentVersion: "a content version".data(using: .utf8)!, metadataVersion: "a metadata version".data(using: .utf8)!)
}
var filename: String {
return identifier.rawValue
}
var contentType: UTType {
return identifier == NSFileProviderItemIdentifier.rootContainer ? .folder : .plainText
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionFileProviderDocumentGroup</key>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
<key>NSExtensionFileProviderSupportsEnumeration</key>
<true/>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.fileprovider-nonui</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).FileProviderExtension</string>
</dict>
</dict>
</plist>

View File

@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SocketApiPrefix</key>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
@ -39,5 +37,7 @@
</dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>SocketApiPrefix</key>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
</dict>
</plist>

View File

@ -7,6 +7,11 @@
objects = {
/* Begin PBXBuildFile section */
538E396A27F4765000FA63D5 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 538E396927F4765000FA63D5 /* UniformTypeIdentifiers.framework */; };
538E396D27F4765000FA63D5 /* FileProviderExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E396C27F4765000FA63D5 /* FileProviderExtension.swift */; };
538E396F27F4765000FA63D5 /* FileProviderItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E396E27F4765000FA63D5 /* FileProviderItem.swift */; };
538E397127F4765000FA63D5 /* FileProviderEnumerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */; };
538E397627F4765000FA63D5 /* FileProviderExt.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 538E396727F4765000FA63D5 /* FileProviderExt.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
539158AC27BE71A900816F56 /* LineProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158AB27BE71A900816F56 /* LineProcessor.m */; };
539158B327BEC98A00816F56 /* LocalSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158B227BEC98A00816F56 /* LocalSocketClient.m */; };
C2B573BA1B1CD91E00303B36 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; };
@ -21,6 +26,13 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
538E397427F4765000FA63D5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C2B573951B1CD88000303B36 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 538E396627F4765000FA63D5;
remoteInfo = FileProviderExt;
};
C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C2B573951B1CD88000303B36 /* Project object */;
@ -38,6 +50,7 @@
dstSubfolderSpec = 13;
files = (
C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */,
538E397627F4765000FA63D5 /* FileProviderExt.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 1;
@ -45,6 +58,13 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
538E396727F4765000FA63D5 /* FileProviderExt.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = FileProviderExt.appex; sourceTree = BUILT_PRODUCTS_DIR; };
538E396927F4765000FA63D5 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
538E396C27F4765000FA63D5 /* FileProviderExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderExtension.swift; sourceTree = "<group>"; };
538E396E27F4765000FA63D5 /* FileProviderItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderItem.swift; sourceTree = "<group>"; };
538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderEnumerator.swift; sourceTree = "<group>"; };
538E397227F4765000FA63D5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
538E397327F4765000FA63D5 /* FileProviderExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FileProviderExt.entitlements; sourceTree = "<group>"; };
539158A927BE606500816F56 /* LineProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LineProcessor.h; sourceTree = "<group>"; };
539158AA27BE67CC00816F56 /* SyncClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SyncClient.h; sourceTree = "<group>"; };
539158AB27BE71A900816F56 /* LineProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LineProcessor.m; sourceTree = "<group>"; };
@ -66,6 +86,14 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
538E396427F4765000FA63D5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
538E396A27F4765000FA63D5 /* UniformTypeIdentifiers.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C2B573AE1B1CD91E00303B36 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -83,11 +111,33 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
538E396827F4765000FA63D5 /* Frameworks */ = {
isa = PBXGroup;
children = (
538E396927F4765000FA63D5 /* UniformTypeIdentifiers.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
538E396B27F4765000FA63D5 /* FileProviderExt */ = {
isa = PBXGroup;
children = (
538E396C27F4765000FA63D5 /* FileProviderExtension.swift */,
538E396E27F4765000FA63D5 /* FileProviderItem.swift */,
538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */,
538E397227F4765000FA63D5 /* Info.plist */,
538E397327F4765000FA63D5 /* FileProviderExt.entitlements */,
);
path = FileProviderExt;
sourceTree = "<group>";
};
C2B573941B1CD88000303B36 = {
isa = PBXGroup;
children = (
C2B573B31B1CD91E00303B36 /* desktopclient */,
C2B573D81B1CD9CE00303B36 /* FinderSyncExt */,
538E396B27F4765000FA63D5 /* FileProviderExt */,
538E396827F4765000FA63D5 /* Frameworks */,
C2B573B21B1CD91E00303B36 /* Products */,
);
sourceTree = "<group>";
@ -97,6 +147,7 @@
children = (
C2B573B11B1CD91E00303B36 /* desktopclient.app */,
C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */,
538E396727F4765000FA63D5 /* FileProviderExt.appex */,
);
name = Products;
sourceTree = "<group>";
@ -150,6 +201,25 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
538E396627F4765000FA63D5 /* FileProviderExt */ = {
isa = PBXNativeTarget;
buildConfigurationList = 538E397927F4765000FA63D5 /* Build configuration list for PBXNativeTarget "FileProviderExt" */;
buildPhases = (
538E396327F4765000FA63D5 /* Sources */,
538E396427F4765000FA63D5 /* Frameworks */,
538E396527F4765000FA63D5 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = FileProviderExt;
packageProductDependencies = (
);
productName = FileProviderExt;
productReference = 538E396727F4765000FA63D5 /* FileProviderExt.appex */;
productType = "com.apple.product-type.app-extension";
};
C2B573B01B1CD91E00303B36 /* desktopclient */ = {
isa = PBXNativeTarget;
buildConfigurationList = C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */;
@ -163,6 +233,7 @@
);
dependencies = (
C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */,
538E397527F4765000FA63D5 /* PBXTargetDependency */,
);
name = desktopclient;
productName = desktopclient;
@ -193,8 +264,13 @@
C2B573951B1CD88000303B36 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1330;
LastUpgradeCheck = 1240;
TargetAttributes = {
538E396627F4765000FA63D5 = {
CreatedOnToolsVersion = 13.3;
ProvisioningStyle = Manual;
};
C2B573B01B1CD91E00303B36 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = 9B5WD74GWJ;
@ -222,17 +298,27 @@
Base,
);
mainGroup = C2B573941B1CD88000303B36;
packageReferences = (
);
productRefGroup = C2B573B21B1CD91E00303B36 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
C2B573B01B1CD91E00303B36 /* desktopclient */,
C2B573D61B1CD9CE00303B36 /* FinderSyncExt */,
538E396627F4765000FA63D5 /* FileProviderExt */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
538E396527F4765000FA63D5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C2B573AF1B1CD91E00303B36 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -273,6 +359,16 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
538E396327F4765000FA63D5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
538E396D27F4765000FA63D5 /* FileProviderExtension.swift in Sources */,
538E396F27F4765000FA63D5 /* FileProviderItem.swift in Sources */,
538E397127F4765000FA63D5 /* FileProviderEnumerator.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C2B573AD1B1CD91E00303B36 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -294,6 +390,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
538E397527F4765000FA63D5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 538E396627F4765000FA63D5 /* FileProviderExt */;
targetProxy = 538E397427F4765000FA63D5 /* PBXContainerItemProxy */;
};
C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C2B573D61B1CD9CE00303B36 /* FinderSyncExt */;
@ -302,6 +403,103 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
538E397727F4765000FA63D5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = FileProviderExt/FileProviderExt.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = FileProviderExt/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = FileProviderExt;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 12.3;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.owncloud.desktopclient.FileProviderExt;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
538E397827F4765000FA63D5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = FileProviderExt/FileProviderExt.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = FileProviderExt/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = FileProviderExt;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 12.3;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.owncloud.desktopclient.FileProviderExt;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 5.0;
};
name = Release;
};
C2B573991B1CD88000303B36 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -370,6 +568,7 @@
C2B573CD1B1CD91E00303B36 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
@ -414,12 +613,16 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
SWIFT_OBJC_BRIDGING_HEADER = "desktopclient/desktopclient-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
C2B573CE1B1CD91E00303B36 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
@ -457,6 +660,8 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
SWIFT_OBJC_BRIDGING_HEADER = "desktopclient/desktopclient-Bridging-Header.h";
SWIFT_VERSION = 5.0;
};
name = Release;
};
@ -567,6 +772,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
538E397927F4765000FA63D5 /* Build configuration list for PBXNativeTarget "FileProviderExt" */ = {
isa = XCConfigurationList;
buildConfigurations = (
538E397727F4765000FA63D5 /* Debug */,
538E397827F4765000FA63D5 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "OwnCloudFinderSync" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -280,6 +280,7 @@ endif()
IF( APPLE )
list(APPEND client_SRCS cocoainitializer_mac.mm)
list(APPEND client_SRCS systray.mm)
list(APPEND client_SRCS fileprovider_mac.mm)
if(SPARKLE_FOUND AND BUILD_UPDATER)
# Define this, we need to check in updater.cpp
@ -653,7 +654,7 @@ endif()
if (APPLE)
find_package(Qt5 COMPONENTS MacExtras)
target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras "-framework UserNotifications")
target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras "-framework UserNotifications FileProvider")
endif()
if(WITH_CRASHREPORTER)

35
src/gui/fileprovider.h Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright (C) by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef FILEPROVIDER_H
#define FILEPROVIDER_H
namespace OCC {
namespace Mac {
class FileProviderInitializer
{
public:
FileProviderInitializer();
~FileProviderInitializer();
private:
class Private;
Private *d;
};
} // namespace Mac
} // namespace OCC
#endif

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#import <Foundation/Foundation.h>
#import <FileProvider/FileProvider.h>
#include "application.h"
#include "fileprovider.h"
namespace OCC {
namespace Mac {
class FileProviderInitializer::Private {
public:
Private() {
domainIdentifier = @APPLICATION_REV_DOMAIN;
name = @APPLICATION_NAME;
fileProviderDomain = [[NSFileProviderDomain alloc] initWithIdentifier:domainIdentifier displayName:name];
setupFileProvider();
}
~Private() = default;
void setupFileProvider() {
[NSFileProviderManager addDomain:fileProviderDomain completionHandler:^(NSError *error) {
if(error) {
NSLog(@"Add file provider domain: %i %@", [error code], [error localizedDescription]);
}
}];
}
void removeFileProvider() {
[NSFileProviderManager removeDomain:fileProviderDomain completionHandler:^(NSError *error) {
if(error) {
NSLog(@"Remove file provider domain: %i %@", [error code], [error localizedDescription]);
}
}];
}
NSFileProviderDomainIdentifier domainIdentifier;
NSString *name;
NSFileProviderDomain *fileProviderDomain;
};
FileProviderInitializer::FileProviderInitializer() {
d = new FileProviderInitializer::Private();
d->setupFileProvider();
}
FileProviderInitializer::~FileProviderInitializer() {
d->removeFileProvider();
delete d;
}
} // namespace Mac
} // namespace OCC

View File

@ -22,6 +22,10 @@
#include <sys/resource.h>
#endif
#ifdef Q_OS_MACOS
#include "fileprovider.h"
#endif
#include "application.h"
#include "cocoainitializer.h"
#include "theme.h"
@ -74,6 +78,7 @@ int main(int argc, char **argv)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
#ifdef Q_OS_MAC
Mac::CocoaInitializer cocoaInit; // RIIA
Mac::FileProviderInitializer fileProviderInit;
#endif
auto surfaceFormat = QSurfaceFormat::defaultFormat();