receiving sharing intent

This commit is contained in:
balzack 2023-04-21 23:34:04 -07:00
parent 98f5b572a0
commit 781b57f903
16 changed files with 754 additions and 4 deletions

View File

@ -1,5 +1,5 @@
import 'react-native-gesture-handler';
import React from 'react';
import { useEffect, useState } from 'react';
import { NativeRouter } from "react-router-native";
import { Routes, Route } from 'react-router-dom';
import { StoreContextProvider } from 'context/StoreContext';
@ -17,12 +17,31 @@ import { Root } from 'src/root/Root';
import { Access } from 'src/access/Access';
import { Dashboard } from 'src/dashboard/Dashboard';
import { Session } from 'src/session/Session';
import ReceiveSharingIntent from 'react-native-receive-sharing-intent';
// silence warning: Sending `onAnimatedValueUpdate` with no listeners registered
//LogBox.ignoreLogs(['Sending']);
export default function App() {
const [sharing, setSharing] = useState();
useEffect(() => {
ReceiveSharingIntent.getReceivedFiles(files => {
setSharing(files);
},
(error) =>{
console.log(error);
},
'org.coredb.databag'
);
}, []);
const clearSharing = () => {
setSharing(null);
ReceiveSharingIntent.clearReceivedFiles();
};
return (
<StoreContextProvider>
<UploadContextProvider>
@ -42,7 +61,7 @@ export default function App() {
<Route path="/login" element={ <Access mode="login" /> } />
<Route path="/reset" element={ <Access mode="reset" /> } />
<Route path="/create" element={ <Access mode="create" /> } />
<Route path="/session" element={ <Session /> } />
<Route path="/session" element={ <Session sharing={sharing} clearSharing={clearSharing} /> } />
</Routes>
</NativeRouter>
</SafeAreaProvider>

View File

@ -13,6 +13,9 @@
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
46D8108CBA031189090AFC14 /* Pods_Databag_DatabagTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1181227D40684F18A9414840 /* Pods_Databag_DatabagTests.framework */; };
7B13A774299E21170048D0DD /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7B13A773299E21170048D0DD /* GoogleService-Info.plist */; };
7B4A533D29F39E250036F3ED /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4A533C29F39E250036F3ED /* ShareViewController.swift */; };
7B4A534029F39E250036F3ED /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7B4A533E29F39E250036F3ED /* MainInterface.storyboard */; };
7B4A534429F39E250036F3ED /* Sharing.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 7B4A533A29F39E250036F3ED /* Sharing.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
A0B1EC4533FCFC5940B5FD7F /* Pods_Databag.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9462C028F47F083241BB7941 /* Pods_Databag.framework */; };
/* End PBXBuildFile section */
@ -25,8 +28,29 @@
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
remoteInfo = Databag;
};
7B4A534229F39E250036F3ED /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 7B4A533929F39E250036F3ED;
remoteInfo = Sharing;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
7B4A534529F39E250036F3ED /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
7B4A534429F39E250036F3ED /* Sharing.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
00E356EE1AD99517003FC87E /* DatabagTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DatabagTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -42,6 +66,11 @@
5709B34CF0A7D63546082F79 /* Pods-Databag.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag.release.xcconfig"; path = "Target Support Files/Pods-Databag/Pods-Databag.release.xcconfig"; sourceTree = "<group>"; };
5B7EB9410499542E8C5724F5 /* Pods-Databag-DatabagTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag-DatabagTests.debug.xcconfig"; path = "Target Support Files/Pods-Databag-DatabagTests/Pods-Databag-DatabagTests.debug.xcconfig"; sourceTree = "<group>"; };
7B13A773299E21170048D0DD /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
7B4A533A29F39E250036F3ED /* Sharing.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Sharing.appex; sourceTree = BUILT_PRODUCTS_DIR; };
7B4A533C29F39E250036F3ED /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
7B4A533F29F39E250036F3ED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
7B4A534129F39E250036F3ED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7B4A534929F39ED90036F3ED /* Sharing.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Sharing.entitlements; sourceTree = "<group>"; };
7B6135A429B68A7B0094A6E7 /* Databag.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Databag.entitlements; path = Databag/Databag.entitlements; sourceTree = "<group>"; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = Databag/LaunchScreen.storyboard; sourceTree = "<group>"; };
89C6BE57DB24E9ADA2F236DE /* Pods-Databag-DatabagTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag-DatabagTests.release.xcconfig"; path = "Target Support Files/Pods-Databag-DatabagTests/Pods-Databag-DatabagTests.release.xcconfig"; sourceTree = "<group>"; };
@ -66,6 +95,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
7B4A533729F39E250036F3ED /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@ -110,6 +146,17 @@
name = Frameworks;
sourceTree = "<group>";
};
7B4A533B29F39E250036F3ED /* Sharing */ = {
isa = PBXGroup;
children = (
7B4A534929F39ED90036F3ED /* Sharing.entitlements */,
7B4A533C29F39E250036F3ED /* ShareViewController.swift */,
7B4A533E29F39E250036F3ED /* MainInterface.storyboard */,
7B4A534129F39E250036F3ED /* Info.plist */,
);
path = Sharing;
sourceTree = "<group>";
};
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
@ -124,6 +171,7 @@
13B07FAE1A68108700A75B9A /* Databag */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* DatabagTests */,
7B4A533B29F39E250036F3ED /* Sharing */,
83CBBA001A601CBA00E9B192 /* Products */,
2D16E6871FA4F8E400B85C8A /* Frameworks */,
BBD78D7AC51CEA395F1C20DB /* Pods */,
@ -138,6 +186,7 @@
children = (
13B07F961A680F5B00A75B9A /* Databag.app */,
00E356EE1AD99517003FC87E /* DatabagTests.xctest */,
7B4A533A29F39E250036F3ED /* Sharing.appex */,
);
name = Products;
sourceTree = "<group>";
@ -190,22 +239,42 @@
00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */,
E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
D347E695755653CE8D39CFDD /* [CP-User] [RNFB] Core Configuration */,
7B4A534529F39E250036F3ED /* Embed Foundation Extensions */,
);
buildRules = (
);
dependencies = (
7B4A534329F39E250036F3ED /* PBXTargetDependency */,
);
name = Databag;
productName = Databag;
productReference = 13B07F961A680F5B00A75B9A /* Databag.app */;
productType = "com.apple.product-type.application";
};
7B4A533929F39E250036F3ED /* Sharing */ = {
isa = PBXNativeTarget;
buildConfigurationList = 7B4A534829F39E250036F3ED /* Build configuration list for PBXNativeTarget "Sharing" */;
buildPhases = (
7B4A533629F39E250036F3ED /* Sources */,
7B4A533729F39E250036F3ED /* Frameworks */,
7B4A533829F39E250036F3ED /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Sharing;
productName = Sharing;
productReference = 7B4A533A29F39E250036F3ED /* Sharing.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1410;
LastUpgradeCheck = 1210;
ORGANIZATIONNAME = CoreDB;
TargetAttributes = {
@ -216,6 +285,9 @@
13B07F861A680F5B00A75B9A = {
LastSwiftMigration = 1120;
};
7B4A533929F39E250036F3ED = {
CreatedOnToolsVersion = 14.1;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Databag" */;
@ -233,6 +305,7 @@
targets = (
13B07F861A680F5B00A75B9A /* Databag */,
00E356ED1AD99517003FC87E /* DatabagTests */,
7B4A533929F39E250036F3ED /* Sharing */,
);
};
/* End PBXProject section */
@ -255,6 +328,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
7B4A533829F39E250036F3ED /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
7B4A534029F39E250036F3ED /* MainInterface.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@ -438,6 +519,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
7B4A533629F39E250036F3ED /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
7B4A533D29F39E250036F3ED /* ShareViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@ -446,8 +535,24 @@
target = 13B07F861A680F5B00A75B9A /* Databag */;
targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
};
7B4A534329F39E250036F3ED /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 7B4A533929F39E250036F3ED /* Sharing */;
targetProxy = 7B4A534229F39E250036F3ED /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
7B4A533E29F39E250036F3ED /* MainInterface.storyboard */ = {
isa = PBXVariantGroup;
children = (
7B4A533F29F39E250036F3ED /* Base */,
);
name = MainInterface.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
00E356F61AD99517003FC87E /* Debug */ = {
isa = XCBuildConfiguration;
@ -504,6 +609,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-Databag.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Databag/Databag.entitlements;
@ -538,6 +644,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-Databag.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Databag/Databag.entitlements;
@ -566,6 +673,84 @@
};
name = Release;
};
7B4A534629F39E250036F3ED /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = Sharing/Sharing.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 3P65PQ7SUR;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Sharing/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Sharing;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 CoreDB. All rights reserved.";
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.coredb.databag.Sharing;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
7B4A534729F39E250036F3ED /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = Sharing/Sharing.entitlements;
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 3P65PQ7SUR;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Sharing/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Sharing;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 CoreDB. All rights reserved.";
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.coredb.databag.Sharing;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -724,6 +909,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
7B4A534829F39E250036F3ED /* Build configuration list for PBXNativeTarget "Sharing" */ = {
isa = XCConfigurationList;
buildConfigurations = (
7B4A534629F39E250036F3ED /* Debug */,
7B4A534729F39E250036F3ED /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Databag" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -1,6 +1,7 @@
#import "AppDelegate.h"
#import <Firebase.h>
#import <React/RCTLinkingManager.h>
#import <React/RCTBundleURLProvider.h>
@implementation AppDelegate
@ -35,4 +36,11 @@
return true;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}
@end

View File

@ -4,5 +4,9 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.coredb.databag</string>
</array>
</dict>
</plist>

View File

@ -88,5 +88,19 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>org.coredb.databag</string>
</array>
</dict>
<dict/>
</array>
</dict>
</plist>

View File

@ -325,6 +325,8 @@ PODS:
- React-Core
- react-native-keep-awake (1.1.0):
- React-Core
- react-native-receive-sharing-intent (2.0.0):
- React-Core
- react-native-rsa-native (2.0.5):
- React
- react-native-safe-area-context (4.5.0):
@ -516,6 +518,7 @@ DEPENDENCIES:
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
- "react-native-keep-awake (from `../node_modules/@sayem314/react-native-keep-awake`)"
- react-native-receive-sharing-intent (from `../node_modules/react-native-receive-sharing-intent`)
- react-native-rsa-native (from `../node_modules/react-native-rsa-native`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- react-native-sqlite-storage (from `../node_modules/react-native-sqlite-storage`)
@ -610,6 +613,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-document-picker"
react-native-keep-awake:
:path: "../node_modules/@sayem314/react-native-keep-awake"
react-native-receive-sharing-intent:
:path: "../node_modules/react-native-receive-sharing-intent"
react-native-rsa-native:
:path: "../node_modules/react-native-rsa-native"
react-native-safe-area-context:
@ -709,6 +714,7 @@ SPEC CHECKSUMS:
React-logger: 957e5dc96d9dbffc6e0f15e0ee4d2b42829ff207
react-native-document-picker: 958e2bc82e128be69055be261aeac8d872c8d34c
react-native-keep-awake: acbee258db16483744910f0da3ace39eb9ab47fd
react-native-receive-sharing-intent: 62ab28c50e6ae56d32b9e841d7452091312a0bc7
react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
react-native-sqlite-storage: f6d515e1c446d1e6d026aa5352908a25d4de3261

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Share View Controller-->
<scene sceneID="ceB-am-kn3">
<objects>
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,46 @@
<?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>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<string>TRUEPREDICATE</string>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>PHSupportedMediaTypes</key>
<array>
<string>Video</string>
<string>Image</string>
</array>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsText</key>
<true/>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>1</integer>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>100</integer>
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
<integer>100</integer>
</dict>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,338 @@
import UIKit
import Social
import MobileCoreServices
import Photos
class ShareViewController: SLComposeServiceViewController {
let hostAppBundleIdentifier = "org.coredb.databag"
let shareProtocol = "org.coredb.databag"
let sharedKey = "ShareKey"
var sharedMedia: [SharedMediaFile] = []
var sharedText: [String] = []
let imageContentType = kUTTypeImage as String
let videoContentType = kUTTypeMovie as String
let textContentType = kUTTypeText as String
let urlContentType = kUTTypeURL as String
let fileURLType = kUTTypeFileURL as String;
override func isContentValid() -> Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad();
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let content = extensionContext!.inputItems[0] as? NSExtensionItem {
if let contents = content.attachments {
for (index, attachment) in (contents).enumerated() {
if attachment.hasItemConformingToTypeIdentifier(imageContentType) {
handleImages(content: content, attachment: attachment, index: index)
} else if attachment.hasItemConformingToTypeIdentifier(textContentType) {
handleText(content: content, attachment: attachment, index: index)
} else if attachment.hasItemConformingToTypeIdentifier(fileURLType) {
handleFiles(content: content, attachment: attachment, index: index)
} else if attachment.hasItemConformingToTypeIdentifier(urlContentType) {
handleUrl(content: content, attachment: attachment, index: index)
} else if attachment.hasItemConformingToTypeIdentifier(videoContentType) {
handleVideos(content: content, attachment: attachment, index: index)
}
}
}
}
}
override func didSelectPost() {
print("didSelectPost");
}
override func configurationItems() -> [Any]! {
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
return []
}
private func handleText (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: textContentType, options: nil) { [weak self] data, error in
if error == nil, let item = data as? String, let this = self {
this.sharedText.append(item)
// If this is the last item, save imagesData in userDefaults and redirect to host app
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.sharedText, forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .text)
}
} else {
self?.dismissWithError()
}
}
}
private func handleUrl (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: urlContentType, options: nil) { [weak self] data, error in
if error == nil, let item = data as? URL, let this = self {
this.sharedText.append(item.absoluteString)
// If this is the last item, save imagesData in userDefaults and redirect to host app
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.sharedText, forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .text)
}
} else {
self?.dismissWithError()
}
}
}
private func handleImages (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: imageContentType, options: nil) { [weak self] data, error in
if error == nil, let url = data as? URL, let this = self {
// this.redirectToHostApp(type: .media)
// Always copy
let fileExtension = this.getExtension(from: url, type: .video)
let newName = UUID().uuidString
let newPath = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
.appendingPathComponent("\(newName).\(fileExtension)")
let copied = this.copyFile(at: url, to: newPath)
if(copied) {
this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .image))
}
// If this is the last item, save imagesData in userDefaults and redirect to host app
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .media)
}
} else {
self?.dismissWithError()
}
}
}
private func handleVideos (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: videoContentType, options:nil) { [weak self] data, error in
if error == nil, let url = data as? URL, let this = self {
// Always copy
let fileExtension = this.getExtension(from: url, type: .video)
let newName = UUID().uuidString
let newPath = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
.appendingPathComponent("\(newName).\(fileExtension)")
let copied = this.copyFile(at: url, to: newPath)
if(copied) {
guard let sharedFile = this.getSharedMediaFile(forVideo: newPath) else {
return
}
this.sharedMedia.append(sharedFile)
}
// If this is the last item, save imagesData in userDefaults and redirect to host app
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .media)
}
} else {
self?.dismissWithError()
}
}
}
private func handleFiles (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: fileURLType, options: nil) { [weak self] data, error in
if error == nil, let url = data as? URL, let this = self {
// Always copy
let newName = this.getFileName(from :url)
let newPath = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
.appendingPathComponent("\(newName)")
let copied = this.copyFile(at: url, to: newPath)
if (copied) {
this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .file))
}
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .file)
}
} else {
self?.dismissWithError()
}
}
}
private func dismissWithError() {
print("[ERROR] Error loading data!")
let alert = UIAlertController(title: "Error", message: "Error loading data", preferredStyle: .alert)
let action = UIAlertAction(title: "Error", style: .cancel) { _ in
self.dismiss(animated: true, completion: nil)
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
private func redirectToHostApp(type: RedirectType) {
let url = URL(string: "\(shareProtocol)://dataUrl=\(sharedKey)#\(type)")
var responder = self as UIResponder?
let selectorOpenURL = sel_registerName("openURL:")
while (responder != nil) {
if (responder?.responds(to: selectorOpenURL))! {
let _ = responder?.perform(selectorOpenURL, with: url)
}
responder = responder!.next
}
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
enum RedirectType {
case media
case text
case file
}
func getExtension(from url: URL, type: SharedMediaType) -> String {
let parts = url.lastPathComponent.components(separatedBy: ".")
var ex: String? = nil
if (parts.count > 1) {
ex = parts.last
}
if (ex == nil) {
switch type {
case .image:
ex = "PNG"
case .video:
ex = "MP4"
case .file:
ex = "TXT"
}
}
return ex ?? "Unknown"
}
func getFileName(from url: URL) -> String {
var name = url.lastPathComponent
if (name == "") {
name = UUID().uuidString + "." + getExtension(from: url, type: .file)
}
return name
}
func copyFile(at srcURL: URL, to dstURL: URL) -> Bool {
do {
if FileManager.default.fileExists(atPath: dstURL.path) {
try FileManager.default.removeItem(at: dstURL)
}
try FileManager.default.copyItem(at: srcURL, to: dstURL)
} catch (let error) {
print("Cannot copy item at \(srcURL) to \(dstURL): \(error)")
return false
}
return true
}
private func getSharedMediaFile(forVideo: URL) -> SharedMediaFile? {
let asset = AVAsset(url: forVideo)
let duration = (CMTimeGetSeconds(asset.duration) * 1000).rounded()
let thumbnailPath = getThumbnailPath(for: forVideo)
if FileManager.default.fileExists(atPath: thumbnailPath.path) {
return SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video)
}
var saved = false
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
// let scale = UIScreen.main.scale
assetImgGenerate.maximumSize = CGSize(width: 360, height: 360)
do {
let img = try assetImgGenerate.copyCGImage(at: CMTimeMakeWithSeconds(600, preferredTimescale: Int32(1.0)), actualTime: nil)
try UIImage.pngData(UIImage(cgImage: img))()?.write(to: thumbnailPath)
saved = true
} catch {
saved = false
}
return saved ? SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video) : nil
}
private func getThumbnailPath(for url: URL) -> URL {
let fileName = Data(url.lastPathComponent.utf8).base64EncodedString().replacingOccurrences(of: "==", with: "")
let path = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(hostAppBundleIdentifier)")!
.appendingPathComponent("\(fileName).jpg")
return path
}
class SharedMediaFile: Codable {
var path: String; // can be image, video or url path. It can also be text content
var thumbnail: String?; // video thumbnail
var duration: Double?; // video duration in milliseconds
var type: SharedMediaType;
init(path: String, thumbnail: String?, duration: Double?, type: SharedMediaType) {
self.path = path
self.thumbnail = thumbnail
self.duration = duration
self.type = type
}
// Debug method to print out SharedMediaFile details in the console
func toString() {
print("[SharedMediaFile] \n\tpath: \(self.path)\n\tthumbnail: \(self.thumbnail)\n\tduration: \(self.duration)\n\ttype: \(self.type)")
}
}
enum SharedMediaType: Int, Codable {
case image
case video
case file
}
func toData(data: [SharedMediaFile]) -> Data {
let encodedData = try? JSONEncoder().encode(data)
return encodedData!
}
}
extension Array {
subscript (safe index: UInt) -> Element? {
return Int(index) < count ? self[Int(index)] : nil
}
}

View File

@ -0,0 +1,10 @@
<?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.security.application-groups</key>
<array>
<string>group.org.coredb.databag</string>
</array>
</dict>
</plist>

View File

@ -34,6 +34,7 @@
"react-native-incall-manager": "^4.0.1",
"react-native-reanimated": "^2.14.4",
"react-native-reanimated-carousel": "^3.3.0",
"react-native-receive-sharing-intent": "^2.0.0",
"react-native-rsa-native": "^2.0.5",
"react-native-safe-area-context": "^4.5.0",
"react-native-screens": "^3.20.0",

View File

@ -25,7 +25,9 @@ import { ProfileIcon } from './profileIcon/ProfileIcon';
import { CardsIcon } from './cardsIcon/CardsIcon';
import { Logo } from 'utils/Logo';
import { Call } from './call/Call';
import { Sharing } from './sharing/Sharing';
import splash from 'images/session.png';
import { useNavigate } from 'react-router-dom';
const ConversationStack = createStackNavigator();
const ProfileStack = createStackNavigator();
@ -314,11 +316,13 @@ function DetailDrawerScreen({ navParams }) {
);
}
export function Session() {
export function Session({ sharing, clearSharing }) {
const [intent, setIntent] = useState(sharing)
const [ringing, setRinging] = useState([]);
const { state, actions } = useSession();
const drawerParams = { drawerPosition: 'right', headerShown: false, swipeEnabled: false, drawerType: 'front' };
const navigate = useNavigate();
const [ dmChannel, setDmChannel ] = useState(null);
const addChannel = async (cardId) => {
@ -326,6 +330,22 @@ export function Session() {
setDmChannel({ id });
};
const setShare = async (cardId, channelId) => {
console.log("SET SHARE CHANNEL");
clearSharing();
}
const clearShare = async () => {
console.log("CLEAR SHARE CHANNEL");
clearSharing();
}
useEffect(() => {
console.log("COMPARE", sharing, intent);
if (sharing != intent && sharing != null) {
navigate('/');
}
}, [sharing, intent, navigate])
useEffect(() => {
let incoming = [];
for (let i = 0; i < state.ringing.length; i++) {
@ -440,7 +460,15 @@ export function Session() {
supportedOrientations={['portrait', 'landscape']}
>
<Call />
</Modal>
</Modal>
<Modal
animationType="fade"
transparent={true}
visible={intent != null}
supportedOrientations={['portrait', 'landscape']}
>
<Sharing select={setShare} cancel={clearShare} />
</Modal>
</NavigationContainer>
);
}

View File

@ -0,0 +1,16 @@
import { Text, View } from 'react-native';
import { useSharing } from './useSharing.hook';
import { styles } from './Sharing.styled';
export function Sharing({ setShare, clearShare }) {
const { state, actions } = useSharing();
return (
<View style={styles.sharingBase}>
<View style={styles.sharingFrame}>
<Text>SHARING</Text>
</View>
</View>
)
}

View File

@ -0,0 +1,21 @@
import { StyleSheet } from 'react-native';
import { Colors } from 'constants/Colors';
export const styles = StyleSheet.create({
sharingBase: {
display: 'flex',
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(52, 52, 52, 0.8)'
},
sharingFrame: {
backgroundColor: Colors.formBackground,
padding: 8,
borderRadius: 4,
display: 'flex',
alignItems: 'center',
},
});

View File

@ -0,0 +1,16 @@
import { useState } from 'react';
export function useSharing() {
const [state, setState] = useState({
});
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
const actions = {
};
return { state, actions };
}

View File

@ -6366,6 +6366,11 @@ react-native-reanimated@^2.14.4:
setimmediate "^1.0.5"
string-hash-64 "^1.0.3"
react-native-receive-sharing-intent@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/react-native-receive-sharing-intent/-/react-native-receive-sharing-intent-2.0.0.tgz#0d835387976e2343f85f0172522e83233a09c0d9"
integrity sha512-JFSO8mZm/hU0EJQYhC5z2m1iiMwJhD9CQ/hYQ8t1UQ9mQynoS/yo+hjX2T6hFXa8mtzlwO/BFwKZjBaVNPdWuw==
react-native-rsa-native@^2.0.5:
version "2.0.5"
resolved "https://registry.npmjs.org/react-native-rsa-native/-/react-native-rsa-native-2.0.5.tgz"