Remove Share Extensions (#6238)

This commit is contained in:
Elias Nahum 2022-05-06 08:32:04 -04:00 committed by GitHub
parent 40e3ae525d
commit 0c1e9a4812
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 1 additions and 1818 deletions

View file

@ -71,23 +71,5 @@
android:resizeableActivity="true"
android:exported="true"
/>
<activity
android:name="com.mattermost.share.ShareActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme"
android:taskAffinity="com.mattermost.share"
android:launchMode="singleInstance"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<!-- for sharing-->
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
</manifest>

View file

@ -14,7 +14,6 @@ import java.util.Map;
import com.airbnb.android.react.lottie.LottiePackage;
import com.mattermost.helpers.RealPathUtil;
import com.mattermost.share.ShareModule;
import com.wix.reactnativenotifications.RNNotificationsPackage;
import com.reactnativenavigation.NavigationApplication;
@ -73,8 +72,6 @@ public class MainApplication extends NavigationApplication implements INotificat
switch (name) {
case "MattermostManaged":
return MattermostManagedModule.getInstance(reactContext);
case "MattermostShare":
return new ShareModule(instance, reactContext);
case "NotificationPreferences":
return NotificationPreferencesModule.getInstance(instance, reactContext);
default:
@ -87,7 +84,6 @@ public class MainApplication extends NavigationApplication implements INotificat
return () -> {
Map<String, ReactModuleInfo> map = new HashMap<>();
map.put("MattermostManaged", new ReactModuleInfo("MattermostManaged", "com.mattermost.rnbeta.MattermostManagedModule", false, false, false, false, false));
map.put("MattermostShare", new ReactModuleInfo("MattermostShare", "com.mattermost.share.ShareModule", false, false, true, false, false));
map.put("NotificationPreferences", new ReactModuleInfo("NotificationPreferences", "com.mattermost.rnbeta.NotificationPreferencesModule", false, false, false, false, false));
return map;
};

View file

@ -1,20 +0,0 @@
package com.mattermost.share;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
import com.mattermost.rnbeta.MainApplication;
public class ShareActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "MattermostShare";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainApplication app = (MainApplication) this.getApplication();
app.sharedExtensionIsOpened = true;
}
}

View file

@ -1,263 +0,0 @@
package com.mattermost.share;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.Arguments;
import com.mattermost.rnbeta.MainApplication;
import com.mattermost.helpers.RealPathUtil;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import java.io.File;
import java.util.ArrayList;
import javax.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.Response;
public class ShareModule extends ReactContextBaseJavaModule {
private final OkHttpClient client = new OkHttpClient();
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private final MainApplication mApplication;
public ShareModule(MainApplication application, ReactApplicationContext reactContext) {
super(reactContext);
mApplication = application;
}
private File tempFolder;
@Override
public String getName() {
return "MattermostShare";
}
@ReactMethod
public void clear() {
Activity currentActivity = getCurrentActivity();
if (currentActivity != null) {
Intent intent = currentActivity.getIntent();
intent.setAction("");
intent.removeExtra(Intent.EXTRA_TEXT);
intent.removeExtra(Intent.EXTRA_STREAM);
}
}
@Nullable
@Override
public Map<String, Object> getConstants() {
HashMap<String, Object> constants = new HashMap<>(1);
constants.put("cacheDirName", RealPathUtil.CACHE_DIR_NAME);
constants.put("isOpened", mApplication.sharedExtensionIsOpened);
mApplication.sharedExtensionIsOpened = false;
return constants;
}
@ReactMethod
public void close(ReadableMap data) {
this.clear();
Activity currentActivity = getCurrentActivity();
if (currentActivity != null) {
currentActivity.finishAndRemoveTask();
}
if (data != null && data.hasKey("url")) {
ReadableArray files = data.getArray("files");
String serverUrl = data.getString("url");
String token = data.getString("token");
JSONObject postData = buildPostObject(data);
if (files.size() > 0) {
uploadFiles(serverUrl, token, files, postData);
} else {
try {
post(serverUrl, token, postData);
} catch (IOException e) {
e.printStackTrace();
}
}
}
RealPathUtil.deleteTempFiles(this.tempFolder);
}
@ReactMethod
public void data(Promise promise) {
promise.resolve(processIntent());
}
@ReactMethod
public void getFilePath(String filePath, Promise promise) {
Activity currentActivity = getCurrentActivity();
WritableMap map = Arguments.createMap();
if (currentActivity != null) {
Uri uri = Uri.parse(filePath);
String path = RealPathUtil.getRealPathFromURI(currentActivity, uri);
if (path != null) {
String text = "file://" + path;
map.putString("filePath", text);
}
}
promise.resolve(map);
}
public WritableArray processIntent() {
WritableMap map = Arguments.createMap();
WritableArray items = Arguments.createArray();
String text = "";
String type = "";
String action = "";
Activity currentActivity = getCurrentActivity();
if (currentActivity != null) {
this.tempFolder = new File(currentActivity.getCacheDir(), RealPathUtil.CACHE_DIR_NAME);
Intent intent = currentActivity.getIntent();
action = intent.getAction();
type = intent.getType();
if (type == null) {
type = "";
}
if (Intent.ACTION_SEND.equals(action) && "text/plain".equals(type)) {
text = intent.getStringExtra(Intent.EXTRA_TEXT);
map.putString("value", text);
map.putString("type", type);
items.pushMap(map);
} else if (Intent.ACTION_SEND.equals(action)) {
Uri uri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (uri != null) {
text = "file://" + RealPathUtil.getRealPathFromURI(currentActivity, uri);
map.putString("value", text);
if (type.equals("image/*")) {
type = "image/jpeg";
} else if (type.equals("video/*")) {
type = "video/mp4";
}
map.putString("type", type);
items.pushMap(map);
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
ArrayList<Uri> uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
for (Uri uri : uris) {
String filePath = RealPathUtil.getRealPathFromURI(currentActivity, uri);
map = Arguments.createMap();
text = "file://" + filePath;
map.putString("value", text);
type = RealPathUtil.getMimeTypeFromUri(currentActivity, uri);
if (type != null) {
if (type.equals("image/*")) {
type = "image/jpeg";
} else if (type.equals("video/*")) {
type = "video/mp4";
}
} else {
type = "application/octet-stream";
}
map.putString("type", type);
items.pushMap(map);
}
}
}
return items;
}
private JSONObject buildPostObject(ReadableMap data) {
JSONObject json = new JSONObject();
try {
json.put("user_id", data.getString("currentUserId"));
if (data.hasKey("channelId")) {
json.put("channel_id", data.getString("channelId"));
}
if (data.hasKey("value")) {
json.put("message", data.getString("value"));
}
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
private void post(String serverUrl, String token, JSONObject postData) throws IOException {
RequestBody body = RequestBody.create(JSON, postData.toString());
Request request = new Request.Builder()
.header("Authorization", "BEARER " + token)
.url(serverUrl + "/api/v4/posts")
.post(body)
.build();
Response response = client.newCall(request).execute();
}
private void uploadFiles(String serverUrl, String token, ReadableArray files, JSONObject postData) {
try {
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
for(int i = 0 ; i < files.size() ; i++) {
ReadableMap file = files.getMap(i);
String filePath = file.getString("fullPath").replaceFirst("file://", "");
File fileInfo = new File(filePath);
if (fileInfo.exists()) {
final MediaType MEDIA_TYPE = MediaType.parse(file.getString("mimeType"));
builder.addFormDataPart("files", file.getString("filename"), RequestBody.create(MEDIA_TYPE, fileInfo));
}
}
builder.addFormDataPart("channel_id", postData.getString("channel_id"));
RequestBody body = builder.build();
Request request = new Request.Builder()
.header("Authorization", "BEARER " + token)
.url(serverUrl + "/api/v4/files")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
String responseData = response.body().string();
JSONObject responseJson = new JSONObject(responseData);
JSONArray fileInfoArray = responseJson.getJSONArray("file_infos");
JSONArray file_ids = new JSONArray();
for(int i = 0 ; i < fileInfoArray.length() ; i++) {
JSONObject fileInfo = fileInfoArray.getJSONObject(i);
file_ids.put(fileInfo.getString("id"));
}
postData.put("file_ids", file_ids);
post(serverUrl, token, postData);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}

View file

@ -403,20 +403,6 @@ platform :ios do
new_string: notification_bundle_id
)
# Set the share extension bundle identifier
extension_bundle_id = ENV['EXTENSION_APP_IDENTIFIER'] || 'com.mattermost.rnbeta.MattermostShare'
update_app_identifier(
xcodeproj: './ios/Mattermost.xcodeproj',
plist_path: 'MattermostShare/Info.plist',
app_identifier: extension_bundle_id
)
find_replace_string(
path_to_file: './ios/Mattermost.xcodeproj/project.pbxproj',
old_string: 'com.mattermost.rnbeta.MattermostShare',
new_string: extension_bundle_id
)
# Set the app bundle id
app_bundle_id = ENV['MAIN_APP_IDENTIFIER'] || 'com.mattermost.rnbeta'
update_app_identifier(
@ -473,19 +459,6 @@ platform :ios do
end
)
update_app_group_identifiers(
entitlements_file: './ios/MattermostShare/MattermostShare.entitlements',
app_group_identifiers: [app_group_id]
)
update_info_plist(
xcodeproj: './ios/Mattermost.xcodeproj',
plist_path: 'MattermostShare/Info.plist',
block: proc do |plist|
plist["AppGroupIdentifier"] = app_group_id
end
)
update_app_group_identifiers(
entitlements_file: './ios/NotificationService/NotificationService.entitlements',
app_group_identifiers: [app_group_id]
@ -547,8 +520,6 @@ platform :ios do
target = 'Mattermost'
if id.include? 'NotificationService'
target = 'NotificationService'
elsif id.include? 'MattermostShare'
target = 'MattermostShare'
end
profile = "sigh_#{id}_#{ENV['MATCH_TYPE']}"
@ -677,14 +648,6 @@ platform :android do
)
end
Dir.glob('../android/app/src/main/java/com/mattermost/share/*.java') do |item|
find_replace_string(
path_to_file: item[1..-1],
old_string: 'import com.mattermost.rnbeta.MainApplication;',
new_string: "import #{package_id}.MainApplication;"
)
end
Dir.glob('../android/app/src/main/java/com/mattermost/helpers/*.java') do |item|
find_replace_string(
path_to_file: item[1..-1],

View file

@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {DeviceEventEmitter, LogBox, Platform} from 'react-native';
import {DeviceEventEmitter, LogBox} from 'react-native';
import {RUNNING_E2E} from 'react-native-dotenv';
import 'react-native-gesture-handler';
import {ComponentDidAppearEvent, ComponentDidDisappearEvent, Navigation} from 'react-native-navigation';
@ -52,12 +52,6 @@ if (global.HermesInternal) {
require('@formatjs/intl-datetimeformat/add-golden-tz');
}
if (Platform.OS === 'android') {
const ShareExtension = require('share_extension/index.tsx').default;
const AppRegistry = require('react-native/Libraries/ReactNative/AppRegistry');
AppRegistry.registerComponent('MattermostShare', () => ShareExtension);
}
let alreadyInitialized = false;
Navigation.events().registerAppLaunchedListener(async () => {
// See caution in the library doc https://wix.github.io/react-native-navigation/docs/app-launch#android

View file

@ -12,32 +12,19 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
4953BF602368AE8600593328 /* SwimeProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4953BF5F2368AE8600593328 /* SwimeProxy.swift */; };
49AE36FF26D4455800EF4E52 /* Gekidou in Frameworks */ = {isa = PBXBuildFile; productRef = 49AE36FE26D4455800EF4E52 /* Gekidou */; };
49AE370126D4455D00EF4E52 /* Gekidou in Frameworks */ = {isa = PBXBuildFile; productRef = 49AE370026D4455D00EF4E52 /* Gekidou */; };
49B4C050230C981C006E919E /* libUploadAttachments.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FABE04522137F2A00D0F595 /* libUploadAttachments.a */; };
531BEBC72513E93C00BC05B1 /* compass-icons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 531BEBC52513E93C00BC05B1 /* compass-icons.ttf */; };
536CC6C323E79287002C478C /* RNNotificationEventHandler+HandleReplyAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 536CC6C123E79287002C478C /* RNNotificationEventHandler+HandleReplyAction.m */; };
58495E36BF1A4EAB93609E57 /* Metropolis-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 54956DEFEBB74EF78C3A6AE5 /* Metropolis-SemiBold.ttf */; };
6C9B1EFD6561083917AF06CF /* libPods-Mattermost.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DEEFB3ED6175724A2653247 /* libPods-Mattermost.a */; };
7F0F4B0A24BA173900E14C60 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F0F4B0924BA173900E14C60 /* LaunchScreen.storyboard */; };
7F151D3E221B062700FAD8F3 /* RuntimeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F151D3D221B062700FAD8F3 /* RuntimeUtils.swift */; };
7F1EB88527FDE361002E7EEC /* GekidouWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F1EB88427FDE361002E7EEC /* GekidouWrapper.swift */; };
7F240A1C220D3A2300637665 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F240A1B220D3A2300637665 /* ShareViewController.swift */; };
7F240A1F220D3A2300637665 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F240A1D220D3A2300637665 /* MainInterface.storyboard */; };
7F240A23220D3A2300637665 /* MattermostShare.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7F240A19220D3A2300637665 /* MattermostShare.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
7F240ADB220E089300637665 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F240ADA220E089300637665 /* Item.swift */; };
7F240ADD220E094A00637665 /* TeamsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F240ADC220E094A00637665 /* TeamsViewController.swift */; };
7F292A711E8AB73400A450A3 /* SplashScreenResource in Resources */ = {isa = PBXBuildFile; fileRef = 7F292A701E8AB73400A450A3 /* SplashScreenResource */; };
7F581D35221ED5C60099E66B /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F581D34221ED5C60099E66B /* NotificationService.swift */; };
7F581D39221ED5C60099E66B /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7F581D32221ED5C60099E66B /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
7F581F78221EEA7C0099E66B /* libUploadAttachments.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FABE04522137F2A00D0F595 /* libUploadAttachments.a */; };
7F72F2EE2211220500F98FFF /* GenericPreview.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7F72F2ED2211220500F98FFF /* GenericPreview.xib */; };
7F72F2F0221123E200F98FFF /* GenericPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F72F2EF221123E200F98FFF /* GenericPreview.swift */; };
7F72F2F322112EC700F98FFF /* generic.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F72F2F222112EC700F98FFF /* generic.png */; };
7F98836227FD46A9001C9BFC /* Gekidou in Frameworks */ = {isa = PBXBuildFile; productRef = 7F98836127FD46A9001C9BFC /* Gekidou */; };
7FABDFC22211A39000D0F595 /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FABDFC12211A39000D0F595 /* Section.swift */; };
7FABE00A2212650600D0F595 /* ChannelsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FABE0092212650600D0F595 /* ChannelsViewController.swift */; };
7FABE0562213884700D0F595 /* libUploadAttachments.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FABE04522137F2A00D0F595 /* libUploadAttachments.a */; };
7FB31F812710995B0032E2E5 /* Metropolis-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F25B626270F666D00F32373 /* Metropolis-Light.ttf */; };
7FB31F822710996D0032E2E5 /* Metropolis-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F25B628270F666D00F32373 /* Metropolis-Regular.ttf */; };
7FB31F842710996D0032E2E5 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D4B1B363C2414DA19C1AC521 /* OpenSans-Bold.ttf */; };
@ -51,18 +38,10 @@
7FB31F8E2710996D0032E2E5 /* compass-icons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 531BEBC52513E93C00BC05B1 /* compass-icons.ttf */; };
7FCEFB9326B7934F006DC1DE /* SDWebImageDownloaderOperation+Swizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FCEFB9226B7934F006DC1DE /* SDWebImageDownloaderOperation+Swizzle.m */; };
7FEB109D1F61019C0039A015 /* MattermostManaged.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FEB109A1F61019C0039A015 /* MattermostManaged.m */; };
84E3264B229834C30055068A /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E325FF229834C30055068A /* Config.swift */; };
A94508A396424B2DB778AFE9 /* OpenSans-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E5C16B14E1CE4868886A1A00 /* OpenSans-SemiBold.ttf */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
7F240A21220D3A2300637665 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 7F240A18220D3A2300637665;
remoteInfo = MattermostShare;
};
7F581D37221ED5C60099E66B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
@ -70,13 +49,6 @@
remoteGlobalIDString = 7F581D31221ED5C60099E66B;
remoteInfo = NotificationService;
};
7FAB4570222DD0DA00EBFFC8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 7FABE04022137F2900D0F595 /* UploadAttachments.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 7FABE03522137F2900D0F595;
remoteInfo = UploadAttachments;
};
7FAB45B9222DD0E300EBFFC8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 7FABE04022137F2900D0F595 /* UploadAttachments.xcodeproj */;
@ -117,7 +89,6 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
7F240A23220D3A2300637665 /* MattermostShare.appex in Embed App Extensions */,
7F581D39221ED5C60099E66B /* NotificationService.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
@ -157,16 +128,8 @@
6BAF8296411D4657B5A0E8F8 /* libRNReactNativeDocViewer.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNReactNativeDocViewer.a; sourceTree = "<group>"; };
7F0F4B0924BA173900E14C60 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = SplashScreenResource/LaunchScreen.storyboard; sourceTree = "<group>"; };
7F151D3D221B062700FAD8F3 /* RuntimeUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RuntimeUtils.swift; path = Mattermost/RuntimeUtils.swift; sourceTree = "<group>"; };
7F151D42221B07F700FAD8F3 /* MattermostShare-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MattermostShare-Bridging-Header.h"; sourceTree = "<group>"; };
7F151D43221B082A00FAD8F3 /* Mattermost-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Mattermost-Bridging-Header.h"; path = "Mattermost/Mattermost-Bridging-Header.h"; sourceTree = "<group>"; };
7F1EB88427FDE361002E7EEC /* GekidouWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GekidouWrapper.swift; sourceTree = "<group>"; };
7F240A19220D3A2300637665 /* MattermostShare.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = MattermostShare.appex; sourceTree = BUILT_PRODUCTS_DIR; };
7F240A1B220D3A2300637665 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
7F240A1E220D3A2300637665 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
7F240A20220D3A2300637665 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7F240A27220D3A7E00637665 /* MattermostShare.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MattermostShare.entitlements; sourceTree = "<group>"; };
7F240ADA220E089300637665 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
7F240ADC220E094A00637665 /* TeamsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeamsViewController.swift; sourceTree = "<group>"; };
7F25B626270F666D00F32373 /* Metropolis-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Metropolis-Light.ttf"; path = "../assets/fonts/Metropolis-Light.ttf"; sourceTree = "<group>"; };
7F25B628270F666D00F32373 /* Metropolis-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Metropolis-Regular.ttf"; path = "../assets/fonts/Metropolis-Regular.ttf"; sourceTree = "<group>"; };
7F292A701E8AB73400A450A3 /* SplashScreenResource */ = {isa = PBXFileReference; lastKnownFileType = folder; path = SplashScreenResource; sourceTree = "<group>"; };
@ -177,11 +140,6 @@
7F581D36221ED5C60099E66B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7F581F77221EEA5A0099E66B /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = "<group>"; };
7F63D2C21E6DD98A001FAE12 /* Mattermost.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Mattermost.entitlements; path = Mattermost/Mattermost.entitlements; sourceTree = "<group>"; };
7F72F2ED2211220500F98FFF /* GenericPreview.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GenericPreview.xib; sourceTree = "<group>"; };
7F72F2EF221123E200F98FFF /* GenericPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericPreview.swift; sourceTree = "<group>"; };
7F72F2F222112EC700F98FFF /* generic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = generic.png; sourceTree = "<group>"; };
7FABDFC12211A39000D0F595 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = "<group>"; };
7FABE0092212650600D0F595 /* ChannelsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelsViewController.swift; sourceTree = "<group>"; };
7FABE04022137F2900D0F595 /* UploadAttachments.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UploadAttachments.xcodeproj; path = UploadAttachments/UploadAttachments.xcodeproj; sourceTree = "<group>"; };
7FCEFB9126B7934F006DC1DE /* SDWebImageDownloaderOperation+Swizzle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SDWebImageDownloaderOperation+Swizzle.h"; path = "Mattermost/SDWebImageDownloaderOperation+Swizzle.h"; sourceTree = "<group>"; };
7FCEFB9226B7934F006DC1DE /* SDWebImageDownloaderOperation+Swizzle.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "SDWebImageDownloaderOperation+Swizzle.m"; path = "Mattermost/SDWebImageDownloaderOperation+Swizzle.m"; sourceTree = "<group>"; };
@ -199,7 +157,6 @@
7FFE32BE1FD9CCAA0038C7A0 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7FFE32BF1FD9CCAA0038C7A0 /* Sentry.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Sentry.framework; sourceTree = BUILT_PRODUCTS_DIR; };
81061F4CBB31484A94D5A8EE /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
84E325FF229834C30055068A /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = "<group>"; };
8DEEFB3ED6175724A2653247 /* libPods-Mattermost.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Mattermost.a"; sourceTree = BUILT_PRODUCTS_DIR; };
BC977883E2624E05975CA65B /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-Regular.ttf"; path = "../assets/fonts/OpenSans-Regular.ttf"; sourceTree = "<group>"; };
BE17F630DB5D41FD93F32D22 /* OpenSans-LightItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-LightItalic.ttf"; path = "../assets/fonts/OpenSans-LightItalic.ttf"; sourceTree = "<group>"; };
@ -221,15 +178,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
7F240A16220D3A2300637665 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
49AE36FF26D4455800EF4E52 /* Gekidou in Frameworks */,
7FABE0562213884700D0F595 /* libUploadAttachments.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
7F581D2F221ED5C60099E66B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -351,26 +299,6 @@
name = Frameworks;
sourceTree = "<group>";
};
7F240A1A220D3A2300637665 /* MattermostShare */ = {
isa = PBXGroup;
children = (
84E325FF229834C30055068A /* Config.swift */,
7F72F2E4221113DF00F98FFF /* Images */,
7F240A20220D3A2300637665 /* Info.plist */,
7F240A27220D3A7E00637665 /* MattermostShare.entitlements */,
7F240A1D220D3A2300637665 /* MainInterface.storyboard */,
7F151D42221B07F700FAD8F3 /* MattermostShare-Bridging-Header.h */,
7F240ADA220E089300637665 /* Item.swift */,
7FABE0092212650600D0F595 /* ChannelsViewController.swift */,
7F240A1B220D3A2300637665 /* ShareViewController.swift */,
7F240ADC220E094A00637665 /* TeamsViewController.swift */,
7F72F2ED2211220500F98FFF /* GenericPreview.xib */,
7F72F2EF221123E200F98FFF /* GenericPreview.swift */,
7FABDFC12211A39000D0F595 /* Section.swift */,
);
path = MattermostShare;
sourceTree = "<group>";
};
7F581D33221ED5C60099E66B /* NotificationService */ = {
isa = PBXGroup;
children = (
@ -381,14 +309,6 @@
path = NotificationService;
sourceTree = "<group>";
};
7F72F2E4221113DF00F98FFF /* Images */ = {
isa = PBXGroup;
children = (
7F72F2F222112EC700F98FFF /* generic.png */,
);
path = Images;
sourceTree = "<group>";
};
7FABE04122137F2900D0F595 /* Products */ = {
isa = PBXGroup;
children = (
@ -411,7 +331,6 @@
children = (
4953BF5F2368AE8600593328 /* SwimeProxy.swift */,
13B07FAE1A68108700A75B9A /* Mattermost */,
7F240A1A220D3A2300637665 /* MattermostShare */,
7F581D33221ED5C60099E66B /* NotificationService */,
7F292A701E8AB73400A450A3 /* SplashScreenResource */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
@ -430,7 +349,6 @@
isa = PBXGroup;
children = (
13B07F961A680F5B00A75B9A /* Mattermost.app */,
7F240A19220D3A2300637665 /* MattermostShare.appex */,
7F581D32221ED5C60099E66B /* NotificationService.appex */,
);
name = Products;
@ -458,7 +376,6 @@
);
dependencies = (
7FAB45BA222DD0E300EBFFC8 /* PBXTargetDependency */,
7F240A22220D3A2300637665 /* PBXTargetDependency */,
7F581D38221ED5C60099E66B /* PBXTargetDependency */,
);
name = Mattermost;
@ -469,27 +386,6 @@
productReference = 13B07F961A680F5B00A75B9A /* Mattermost.app */;
productType = "com.apple.product-type.application";
};
7F240A18220D3A2300637665 /* MattermostShare */ = {
isa = PBXNativeTarget;
buildConfigurationList = 7F240A24220D3A2300637665 /* Build configuration list for PBXNativeTarget "MattermostShare" */;
buildPhases = (
7F240A15220D3A2300637665 /* Sources */,
7F240A16220D3A2300637665 /* Frameworks */,
7F240A17220D3A2300637665 /* Resources */,
);
buildRules = (
);
dependencies = (
7FAB4571222DD0DA00EBFFC8 /* PBXTargetDependency */,
);
name = MattermostShare;
packageProductDependencies = (
49AE36FE26D4455800EF4E52 /* Gekidou */,
);
productName = MattermostShare;
productReference = 7F240A19220D3A2300637665 /* MattermostShare.appex */;
productType = "com.apple.product-type.app-extension";
};
7F581D31221ED5C60099E66B /* NotificationService */ = {
isa = PBXNativeTarget;
buildConfigurationList = 7F581D82221ED5C60099E66B /* Build configuration list for PBXNativeTarget "NotificationService" */;
@ -543,16 +439,6 @@
};
};
};
7F240A18220D3A2300637665 = {
CreatedOnToolsVersion = 10.1;
DevelopmentTeam = UQ8HT4Q2XM;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.ApplicationGroups.iOS = {
enabled = 1;
};
};
};
7F581D31221ED5C60099E66B = {
CreatedOnToolsVersion = 10.1;
DevelopmentTeam = UQ8HT4Q2XM;
@ -586,7 +472,6 @@
projectRoot = "";
targets = (
13B07F861A680F5B00A75B9A /* Mattermost */,
7F240A18220D3A2300637665 /* MattermostShare */,
7F581D31221ED5C60099E66B /* NotificationService */,
);
};
@ -627,17 +512,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
7F240A17220D3A2300637665 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
531BEBC72513E93C00BC05B1 /* compass-icons.ttf in Resources */,
7F240A1F220D3A2300637665 /* MainInterface.storyboard in Resources */,
7F72F2EE2211220500F98FFF /* GenericPreview.xib in Resources */,
7F72F2F322112EC700F98FFF /* generic.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
7F581D30221ED5C60099E66B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -794,20 +668,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
7F240A15220D3A2300637665 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
7F72F2F0221123E200F98FFF /* GenericPreview.swift in Sources */,
7F240ADB220E089300637665 /* Item.swift in Sources */,
7F240A1C220D3A2300637665 /* ShareViewController.swift in Sources */,
7FABDFC22211A39000D0F595 /* Section.swift in Sources */,
84E3264B229834C30055068A /* Config.swift in Sources */,
7FABE00A2212650600D0F595 /* ChannelsViewController.swift in Sources */,
7F240ADD220E094A00637665 /* TeamsViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
7F581D2E221ED5C60099E66B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -819,21 +679,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
7F240A22220D3A2300637665 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 7F240A18220D3A2300637665 /* MattermostShare */;
targetProxy = 7F240A21220D3A2300637665 /* PBXContainerItemProxy */;
};
7F581D38221ED5C60099E66B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 7F581D31221ED5C60099E66B /* NotificationService */;
targetProxy = 7F581D37221ED5C60099E66B /* PBXContainerItemProxy */;
};
7FAB4571222DD0DA00EBFFC8 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = UploadAttachments;
targetProxy = 7FAB4570222DD0DA00EBFFC8 /* PBXContainerItemProxy */;
};
7FAB45BA222DD0E300EBFFC8 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = UploadAttachments;
@ -846,17 +696,6 @@
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
7F240A1D220D3A2300637665 /* MainInterface.storyboard */ = {
isa = PBXVariantGroup;
children = (
7F240A1E220D3A2300637665 /* Base */,
);
name = MainInterface.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
@ -942,101 +781,6 @@
};
name = Release;
};
7F240A25220D3A2300637665 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = MattermostShare/MattermostShare.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
GCC_C_LANGUAGE_STANDARD = gnu11;
HEADER_SEARCH_PATHS = "$(SRCROOT)/UploadAttachments/UploadAttachments";
INFOPLIST_FILE = MattermostShare/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
OTHER_CFLAGS = (
"$(inherited)",
"-DFB_SONARKIT_ENABLED=1",
);
PRODUCT_BUNDLE_IDENTIFIER = com.mattermost.rnbeta.MattermostShare;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "MattermostShare/MattermostShare-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
7F240A26220D3A2300637665 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = MattermostShare/MattermostShare.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
GCC_C_LANGUAGE_STANDARD = gnu11;
HEADER_SEARCH_PATHS = "$(SRCROOT)/UploadAttachments/UploadAttachments";
INFOPLIST_FILE = MattermostShare/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_FAST_MATH = YES;
OTHER_CFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = com.mattermost.rnbeta.MattermostShare;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OBJC_BRIDGING_HEADER = "MattermostShare/MattermostShare-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
7F581D3A221ED5C60099E66B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1226,15 +970,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
7F240A24220D3A2300637665 /* Build configuration list for PBXNativeTarget "MattermostShare" */ = {
isa = XCConfigurationList;
buildConfigurations = (
7F240A25220D3A2300637665 /* Debug */,
7F240A26220D3A2300637665 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
7F581D82221ED5C60099E66B /* Build configuration list for PBXNativeTarget "NotificationService" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@ -1256,10 +991,6 @@
/* End XCConfigurationList section */
/* Begin XCSwiftPackageProductDependency section */
49AE36FE26D4455800EF4E52 /* Gekidou */ = {
isa = XCSwiftPackageProductDependency;
productName = Gekidou;
};
49AE370026D4455D00EF4E52 /* Gekidou */ = {
isa = XCSwiftPackageProductDependency;
productName = Gekidou;

View file

@ -1,94 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1010"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7F240A18220D3A2300637665"
BuildableName = "MattermostShare.appex"
BlueprintName = "MattermostShare"
ReferencedContainer = "container:Mattermost.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7F240A18220D3A2300637665"
BuildableName = "MattermostShare.appex"
BlueprintName = "MattermostShare"
ReferencedContainer = "container:Mattermost.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<RemoteRunnable
runnableDebuggingMode = "1"
BundleIdentifier = "com.apple.mobileslideshow"
RemotePath = "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/Applications/MobileSlideShow.app">
</RemoteRunnable>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7F240A18220D3A2300637665"
BuildableName = "MattermostShare.appex"
BlueprintName = "MattermostShare"
ReferencedContainer = "container:Mattermost.xcodeproj">
</BuildableReference>
</MacroExpansion>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
launchAutomaticallySubstyle = "2">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7F240A18220D3A2300637665"
BuildableName = "MattermostShare.appex"
BlueprintName = "MattermostShare"
ReferencedContainer = "container:Mattermost.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -1,24 +0,0 @@
<?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

@ -1,175 +0,0 @@
import UIKit
class ChannelsViewController: UIViewController {
let searchController = UISearchController(searchResultsController: nil)
lazy var tableView: UITableView = {
let tableView = UITableView(frame: self.view.frame)
tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
tableView.dataSource = self
tableView.delegate = self
tableView.backgroundColor = .clear
tableView.register(UITableViewCell.self, forCellReuseIdentifier: Identifiers.ChannelCell)
return tableView
}()
var navbarTitle: String? = "Channels"
var channelDecks = [Section]()
var filteredDecks: [Section]?
weak var delegate: ChannelsViewControllerDelegate?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if #available(iOS 11.0, *) {
navigationItem.hidesSearchBarWhenScrolling = false
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if #available(iOS 11.0, *) {
navigationItem.hidesSearchBarWhenScrolling = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
filteredDecks = channelDecks
title = navbarTitle
configureSearchBar()
view.addSubview(tableView)
}
func configureSearchBar() {
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.searchBarStyle = .minimal
searchController.searchBar.autocapitalizationType = .none
searchController.searchBar.delegate = self
self.definesPresentationContext = true
if #available(iOS 11.0, *) {
// For iOS 11 and later, place the search bar in the navigation bar.
// Give space at the top so provide a better look and feel
let offset = UIOffset(horizontal: 0.0, vertical: 6.0)
searchController.searchBar.searchFieldBackgroundPositionAdjustment = offset
navigationItem.searchController = searchController
} else {
// For iOS 10 and earlier, place the search controller's search bar in the table view's header.
tableView.tableHeaderView = searchController.searchBar
}
}
}
private extension ChannelsViewController {
struct Identifiers {
static let ChannelCell = "channelCell"
}
}
extension ChannelsViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return filteredDecks?.count ?? 0
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let sec = filteredDecks?[section]
if (sec?.items.count)! > 0 {
return sec?.title
}
return nil
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredDecks?[section].items.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let section = filteredDecks?[indexPath.section]
let cell = tableView.dequeueReusableCell(withIdentifier: Identifiers.ChannelCell, for: indexPath)
let item = section?.items[indexPath.row]
cell.textLabel?.text = item?.title
if item?.selected ?? false {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
cell.backgroundColor = .clear
return cell
}
}
protocol ChannelsViewControllerDelegate: class {
func selectedChannel(deck: Item)
}
extension ChannelsViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let section = filteredDecks?[indexPath.section]
if (section?.items != nil) {
delegate?.selectedChannel(deck: (section?.items[indexPath.row])!)
}
}
}
extension ChannelsViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
if let searchText = searchController.searchBar.text, !searchText.isEmpty {
filteredDecks = channelDecks.map {section in
let s = section.copy() as! Section
let items = section.items.filter{($0.title?.lowercased().contains(searchText.lowercased()))!}
s.items = items
return s
}
} else {
filteredDecks = channelDecks
}
tableView.reloadData()
}
}
extension ChannelsViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.showsCancelButton = false
searchBar.text = ""
searchBar.resignFirstResponder()
tableView.reloadData()
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchBar.showsCancelButton = true
// Center the Cancel Button
if #available(iOS 11.0, *) {
searchBar.cancelButton?.titleEdgeInsets = UIEdgeInsets(top: 12.0, left: 0, bottom: 0, right: 0)
}
}
}
// get the cancel button of the Search Bar
extension UISearchBar {
var cancelButton : UIButton? {
let topView: UIView = self.subviews[0] as UIView
if let pvtClass = NSClassFromString("UINavigationButton") {
for v in topView.subviews {
if v.isKind(of: pvtClass) {
return v as? UIButton
}
}
}
return nil
}
}

View file

@ -1,6 +0,0 @@
let configurationKey = "com.apple.configuration.managed"
func getManagedConfig() -> [String : Any] {
let appGroupId = Bundle.main.infoDictionary!["AppGroupIdentifier"] as! String
return UserDefaults.init(suiteName: appGroupId)?.dictionary(forKey: configurationKey) ?? [:]
}

View file

@ -1,25 +0,0 @@
import UIKit
class GenericPreview: UIView {
@IBOutlet var contentView: UIView!
@IBOutlet weak var mainLabel: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
Bundle.main.loadNibNamed("GenericPreview", owner: self, options: nil)
addSubview(contentView)
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
}

View file

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment version="4144" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="GenericPreview" customModule="MattermostShare">
<connections>
<outlet property="contentView" destination="iN0-l3-epB" id="zsU-gT-pKk"/>
<outlet property="mainLabel" destination="VCO-Fr-5i7" id="kIN-uo-sj1"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view userInteractionEnabled="NO" contentMode="scaleAspectFit" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="70" height="80"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="generic.png" translatesAutoresizingMaskIntoConstraints="NO" id="TSh-2S-BCu">
<rect key="frame" x="0.0" y="0.0" width="70" height="60"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
</accessibility>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VCO-Fr-5i7">
<rect key="frame" x="0.0" y="80" width="70" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" notEnabled="YES"/>
</accessibility>
<constraints>
<constraint firstItem="TSh-2S-BCu" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="5B6-O1-NR2"/>
<constraint firstItem="VCO-Fr-5i7" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="aFc-0b-hsh"/>
<constraint firstItem="TSh-2S-BCu" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="cce-KU-XTm"/>
<constraint firstAttribute="bottom" secondItem="TSh-2S-BCu" secondAttribute="bottom" constant="20" id="lHP-mg-Ogd"/>
<constraint firstAttribute="trailing" secondItem="TSh-2S-BCu" secondAttribute="trailing" id="q2A-Bm-uko"/>
<constraint firstAttribute="bottom" secondItem="VCO-Fr-5i7" secondAttribute="bottom" id="rpf-k7-OZN"/>
<constraint firstItem="VCO-Fr-5i7" firstAttribute="trailing" secondItem="iN0-l3-epB" secondAttribute="trailingMargin" constant="16" id="thO-W2-G2h"/>
</constraints>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="-387.19999999999999" y="-305.84707646176912"/>
</view>
</objects>
<resources>
<image name="generic.png" width="512" height="512"/>
</resources>
</document>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View file

@ -1,56 +0,0 @@
<?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>AppGroupIdentifier</key>
<string>group.com.mattermost.rnbeta</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Mattermost</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.mattermost.rnbeta.MattermostShare</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<key>CFBundleVersion</key>
<string>393</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsAttachmentsWithMaxCount</key>
<integer>5</integer>
<key>NSExtensionActivationSupportsFileWithMaxCount</key>
<integer>5</integer>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>5</integer>
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
<integer>5</integer>
<key>NSExtensionActivationSupportsText</key>
<true/>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>1</integer>
</dict>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
</dict>
</plist>

View file

@ -1,7 +0,0 @@
import Foundation
final class Item {
var id: String?
var title: String?
var selected: Bool = false
}

View file

@ -1,6 +0,0 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "MMMConstants.h"
#import "StoreManager.h"

View file

@ -1,10 +0,0 @@
<?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.com.mattermost.rnbeta</string>
</array>
</dict>
</plist>

View file

@ -1,13 +0,0 @@
import Foundation
class Section: NSObject, NSCopying {
var title: String?
var items: [Item] = []
func copy(with zone: NSZone? = nil) -> Any {
let copy = Section()
copy.title = title
copy.items = items
return copy
}
}

View file

@ -1,559 +0,0 @@
import UIKit
import Social
import MobileCoreServices
import UploadAttachments
import Gekidou
import LocalAuthentication
extension Bundle {
var displayName: String? {
return object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
}
}
class ShareViewController: SLComposeServiceViewController {
private var dispatchGroup = DispatchGroup()
private var attachments = AttachmentArray<AttachmentItem>()
private var store = StoreManager.shared() as StoreManager
private var entities: [AnyHashable:Any]? = nil
private var sessionToken: String?
private var serverUrl: String?
private var message: String?
private var publicUrl: String?
private var maxPostAlertShown: Bool = false
private var tempContainerUrl: URL? = UploadSessionManager.shared.tempContainerUrl() as URL?
fileprivate var selectedChannel: Item?
fileprivate var selectedTeam: Item?
private var channelsVC: ChannelsViewController = ChannelsViewController()
private var teamsVC: TeamsViewController = TeamsViewController()
private var maxMessageSize: Int = 0
private var canUploadFiles: Bool = true
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
entities = store.getEntities(true) as [AnyHashable:Any]?
// TODO: If we don't have a single server then we'll need the user to
// select the server from a dropdown. Once the server is selected we
// can fetch its token.
serverUrl = try? Database.default.getOnlyServerUrl()
if (serverUrl != nil), let token = try? Keychain.default.getToken(for: serverUrl!) {
sessionToken = token
}
maxMessageSize = Int(store.getMaxPostSize())
canUploadFiles = store.getCanUploadFiles()
}
// MARK: - Lifecycle methods
override func viewDidLoad() {
super.viewDidLoad()
title = Bundle.main.displayName
placeholder = "Write a message..."
let config = getManagedConfig()
if let inAppPinCode = config["inAppPinCode"] as? String, inAppPinCode == "true" {
self.auth(vendor: config["vendor"] as? String)
} else {
self.loadData()
}
}
func auth(vendor: String?) {
let context = LAContext()
var error: NSError?
if !context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
if let error = error, error.code == kLAErrorPasscodeNotSet {
var message = "This device must be secured with a passcode to use Mattermost.\n\nGo to Settings > Touch ID & Passcode."
if #available(iOS 11.0, *) {
if (context.biometryType == LABiometryType.faceID) {
message = "This device must be secured with a passcode to use Mattermost.\n\nGo to Settings > Face ID & Passcode."
}
}
self.showErrorMessage(
title: "",
message: message,
VC: self
)
} else {
self.showErrorMessage(title: "", message: "Unable to authenticate device owner for Mattermost", VC: self)
}
return
}
let reason = "Secured by " + (vendor ?? "Mattermost")
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, error in
if success {
self.loadData()
} else {
self.showErrorMessage(title: "", message: "Unable to authenticate device owner for Mattermost", VC: self)
}
}
}
func loadData() {
if sessionToken == nil || serverUrl == nil {
showErrorMessage(title: "", message: "Authentication required: Please first login using the app.", VC: self)
} else if store.getCurrentTeamId() == "" || store.getMyTeams().count == 0 {
showErrorMessage(title: "", message: "You must belong to a team before you can share files.", VC: self)
} else if !canUploadFiles {
showErrorMessage(title: "", message: "File uploads from mobile are disabled. Please contact your System Admin for more details.", VC: self)
} else {
extractDataFromContext()
}
}
override func isContentValid() -> Bool {
if let currentMessage = contentText {
let contentCount = currentMessage.count
if #available(iOS 13, *) {} else {
let remaining = (maxMessageSize - contentCount) as NSNumber
// this is causing the extension to run OOM on iOS 13
charactersRemaining = remaining
}
//Check content text size is not above max
if (contentCount > maxMessageSize) {
if !maxPostAlertShown {
maxPostAlertShown = true
showErrorMessageAndStayOpen(title: "", message: "Content text shared in Mattermost must be less than \(maxMessageSize+1) characters.", VC: self)
}
return false
} else if (attachments.count > 0) { // Do validation of contentText and/or NSExtensionContext attachments here
let maxImagePixels = store.getMaxImagePixels()
if attachments.hasImageLargerThan(pixels: maxImagePixels) {
let readableMaxImagePixels = formatImagePixels(pixels: maxImagePixels)
showErrorMessage(title: "", message: "Image attachments shared in Mattermost must be less than \(readableMaxImagePixels).", VC: self)
}
let maxFileSize = store.getMaxFileSize()
if attachments.hasAttachementLargerThan(fileSize: maxFileSize) {
let readableMaxFileSize = formatFileSize(fileSize: maxFileSize)
showErrorMessage(title: "", message: "File attachments shared in Mattermost must be less than \(readableMaxFileSize).", VC: self)
}
}
}
return serverUrl != nil &&
sessionToken != nil &&
attachmentsCount() == attachments.count &&
selectedTeam != nil &&
selectedChannel != nil
}
override func didSelectCancel() {
UploadSessionManager.shared.clearTempDirectory()
super.didSelectCancel()
}
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
if publicUrl != nil {
self.message = "\(contentText!)\n\n\(publicUrl!)"
} else {
self.message = contentText
}
UploadManager.shared.uploadFiles(baseUrl: serverUrl!, token: sessionToken!, channelId: selectedChannel!.id!, message: message, attachments: attachments, callback: {
// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
})
}
override func loadPreviewView() -> UIView! {
if attachments.findBy(type: kUTTypeFileURL as String) {
let genericPreview = GenericPreview()
genericPreview.contentMode = .scaleAspectFit
genericPreview.clipsToBounds = true
genericPreview.isUserInteractionEnabled = false
genericPreview.addConstraints([
NSLayoutConstraint(item: genericPreview, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: 70),
NSLayoutConstraint(item: genericPreview, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: 70)
])
if attachments.count > 1 {
genericPreview.mainLabel.text = "\(attachments.count) Items"
}
return genericPreview
}
return super.loadPreviewView();
}
override func configurationItems() -> [Any]! {
var items: [SLComposeSheetConfigurationItem] = []
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
let teamDecks = getTeamItems()
if let teams = SLComposeSheetConfigurationItem() {
teams.title = "Team"
teams.value = selectedTeam?.title
teams.tapHandler = {
self.teamsVC.teamDecks = teamDecks
self.teamsVC.delegate = self
self.pushConfigurationViewController(self.teamsVC)
}
items.append(teams)
}
let channelDecks = getChannelItems(forTeamId: selectedTeam?.id)
if let channels = SLComposeSheetConfigurationItem() {
channels.title = "Channels"
channels.value = selectedChannel?.title
channels.valuePending = channelDecks == nil
channels.tapHandler = {
self.channelsVC.channelDecks = channelDecks!
self.channelsVC.navbarTitle = self.selectedTeam?.title
self.channelsVC.delegate = self
self.pushConfigurationViewController(self.channelsVC)
}
items.append(channels)
}
validateContent()
return items
}
// MARK: - Extension Builder
func attachmentsCount() -> Int {
var count = 0
for item in extensionContext?.inputItems as! [NSExtensionItem] {
guard let attachments = item.attachments else {return 0}
for itemProvider in attachments {
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeMovie as String) ||
itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) ||
itemProvider.hasItemConformingToTypeIdentifier(kUTTypeFileURL as String) {
count = count + 1
}
}
}
return count
}
func buildChannelSection(channels: NSArray, currentChannelId: String, key: String, title:String) -> Section {
let section = Section()
section.title = title
for channel in channels as! [NSDictionary] {
let item = Item()
let id = channel.object(forKey: "id") as? String
item.id = id
item.title = channel.object(forKey: "display_name") as? String
if id == currentChannelId {
item.selected = true
selectedChannel = item
if #available(iOS 13, *) {} else {
// this is causing the extension to run OOM on iOS 13
self.placeholder = "Write to \(item.title!)"
}
}
section.items.append(item)
}
return section
}
func getImagePixels(imageUrl: URL) -> UInt64 {
guard let imageData = try? Data(contentsOf: imageUrl) else {
return 0
}
guard let image = UIImage.init(data: imageData) else {
return 0
}
return getImagePixels(image: image)
}
func getImagePixels(image: UIImage) -> UInt64 {
guard let cgImage = image.cgImage else {
return 0
}
return UInt64(cgImage.width * cgImage.height)
}
func extractDataFromContext() {
for item in extensionContext?.inputItems as! [NSExtensionItem] {
guard let attachments = item.attachments else {continue}
for itemProvider in attachments {
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeMovie as String) {
dispatchGroup.enter()
itemProvider.loadItem(forTypeIdentifier: kUTTypeMovie as String, options: nil, completionHandler: ({item, error in
if error == nil {
if let url = item as? URL {
let attachment = self.saveAttachment(url: url)
if (attachment != nil) {
attachment?.type = kUTTypeMovie as String
self.attachments.append(attachment!)
}
}
}
self.dispatchGroup.leave()
}))
} else if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
dispatchGroup.enter()
itemProvider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil, completionHandler: ({item, error in
if error == nil {
if let url = item as? URL {
let attachment = self.saveAttachment(url: url)
if (attachment != nil) {
attachment?.type = kUTTypeImage as String
attachment?.imagePixels = self.getImagePixels(imageUrl: url)
self.attachments.append(attachment!)
}
} else if let image = item as? UIImage {
if let data = image.pngData() {
let tempImageUrl = self.tempContainerUrl?
.appendingPathComponent(UUID().uuidString)
.appendingPathExtension(".png")
if (try? data.write(to: tempImageUrl!)) != nil {
let attachment = self.saveAttachment(url: tempImageUrl!)
if (attachment != nil) {
attachment?.type = kUTTypeImage as String
attachment?.imagePixels = self.getImagePixels(image: image)
self.attachments.append(attachment!)
}
}
}
}
}
self.dispatchGroup.leave()
}))
} else if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeFileURL as String) {
dispatchGroup.enter()
itemProvider.loadItem(forTypeIdentifier: kUTTypeFileURL as String, options: nil, completionHandler: ({item, error in
if error == nil {
if let url = item as? URL {
let attachment = self.saveAttachment(url: url)
if (attachment != nil) {
attachment?.type = kUTTypeFileURL as String
self.attachments.append(attachment!)
}
}
}
self.dispatchGroup.leave()
}))
} else if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeURL as String) {
itemProvider.loadItem(forTypeIdentifier: kUTTypeURL as String, options: nil, completionHandler: ({item, error in
if let url = item as? URL {
self.publicUrl = url.absoluteString
}
}))
}
}
}
dispatchGroup.notify(queue: DispatchQueue.main) {
self.validateContent()
}
}
func getChannelsFromServerAndReload(forTeamId: String) {
var currentChannel = store.getCurrentChannel() as NSDictionary?
if currentChannel?.object(forKey: "team_id") as! String != forTeamId {
currentChannel = store.getDefaultChannel(forTeamId) as NSDictionary?
}
// If currentChannel is nil it means we don't have the channels for this team
if (currentChannel == nil) {
let urlString = "\(serverUrl!)/api/v4/users/me/teams/\(forTeamId)/channels"
let url = URL(string: urlString)
var request = URLRequest(url: url!)
let auth = "Bearer \(sessionToken!)" as String
request.setValue(auth, forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return
}
do{
//here dataResponse received from a network request
let jsonArray = try JSONSerialization.jsonObject(with: dataResponse, options: []) as! NSArray
let channels = jsonArray.filter {element in
let channel = element as! NSDictionary
let type = channel.object(forKey: "type") as! String
return type == "O" || type == "P"
}
let ent = self.store.getEntities(false)! as NSDictionary
let mutableEntities = ent.mutableCopy() as! NSMutableDictionary
let entitiesChannels = NSDictionary(dictionary: mutableEntities.object(forKey: "channels") as! NSMutableDictionary)
.object(forKey: "channels") as! NSMutableDictionary
for item in channels {
let channel = item as! NSDictionary
entitiesChannels.setValue(channel, forKey: channel.object(forKey: "id") as! String)
}
if let entitiesData: NSData = try? JSONSerialization.data(withJSONObject: ent, options: JSONSerialization.WritingOptions.prettyPrinted) as NSData {
let jsonString = String(data: entitiesData as Data, encoding: String.Encoding.utf8)! as String
self.store.updateEntities(jsonString)
self.store.getEntities(true)
self.reloadConfigurationItems()
self.view.setNeedsDisplay()
}
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
}
func getChannelItems(forTeamId: String?) -> [Section]? {
var channelDecks = [Section]()
var currentChannel = store.getCurrentChannel() as NSDictionary?
if currentChannel?.object(forKey: "team_id") as? String != forTeamId {
currentChannel = store.getDefaultChannel(forTeamId) as NSDictionary?
}
if currentChannel == nil {
return nil
}
let channelsInTeamBySections = store.getChannelsBySections(forTeamId, excludeArchived: true) as NSDictionary
channelDecks.append(buildChannelSection(
channels: channelsInTeamBySections.object(forKey: "public") as! NSArray,
currentChannelId: selectedChannel?.id ?? currentChannel?.object(forKey: "id") as! String,
key: "public",
title: "Public Channels"
))
channelDecks.append(buildChannelSection(
channels: channelsInTeamBySections.object(forKey: "private") as! NSArray,
currentChannelId: selectedChannel?.id ?? currentChannel?.object(forKey: "id") as! String,
key: "private",
title: "Private Channels"
))
channelDecks.append(buildChannelSection(
channels: channelsInTeamBySections.object(forKey: "direct") as! NSArray,
currentChannelId: selectedChannel?.id ?? currentChannel?.object(forKey: "id") as! String,
key: "direct",
title: "Direct Channels"
))
return channelDecks
}
func getTeamItems() -> [Item] {
var teamDecks = [Item]()
let currentTeamId = store.getCurrentTeamId()
let teams = store.getMyTeams() as NSArray?
for case let team as NSDictionary in teams! {
let item = Item()
item.title = team.object(forKey: "display_name") as! String?
item.id = team.object(forKey: "id") as! String?
item.selected = false
if (item.id == (selectedTeam?.id ?? currentTeamId)) {
item.selected = true
selectedTeam = item
}
teamDecks.append(item)
}
return teamDecks
}
func saveAttachment(url: URL) -> AttachmentItem? {
let fileMgr = FileManager.default
let fileName = url.lastPathComponent
let tempFileUrl = tempContainerUrl?.appendingPathComponent(fileName)
do {
if (tempFileUrl != url) {
try? FileManager.default.removeItem(at: tempFileUrl!)
try fileMgr.copyItem(at: url, to: tempFileUrl!)
}
let attr = try fileMgr.attributesOfItem(atPath: (tempFileUrl?.path)!) as NSDictionary
let attachment = AttachmentItem()
attachment.fileName = fileName
attachment.fileUrl = tempFileUrl
attachment.fileSize = attr.fileSize()
return attachment
} catch {
return nil
}
}
// MARK: - Utiilities
func showErrorMessage(title: String, message: String, VC: UIViewController) {
let alert: UIAlertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default) {
UIAlertAction in
self.cancel()
}
alert.addAction(okAction)
VC.present(alert, animated: true, completion: nil)
}
func showErrorMessageAndStayOpen(title: String, message: String, VC: UIViewController) {
let alert: UIAlertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default)
alert.addAction(okAction)
VC.present(alert, animated: true, completion: nil)
}
func formatImagePixels(pixels: UInt64) -> String {
let suffixes = ["pixels", "KP", "MP", "GP", "TP", "PP", "EP", "ZP", "YP"]
let k: Double = 1000
return formatSize(size: Double(pixels), k: k, suffixes: suffixes)
}
func formatFileSize(fileSize: UInt64) -> String {
let suffixes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
let k: Double = 1024
return formatSize(size: Double(fileSize), k: k, suffixes: suffixes)
}
func formatSize(size: Double, k: Double, suffixes: Array<String>) -> String {
guard size > 0 else {
return "0 \(suffixes[0])"
}
// Adapted from http://stackoverflow.com/a/18650828
let i = floor(log(size) / log(k))
// Format number with thousands separator and everything below 1 giga with no decimal places.
let numberFormatter = NumberFormatter()
numberFormatter.maximumFractionDigits = i < 3 ? 0 : 1
numberFormatter.numberStyle = .decimal
let numberString = numberFormatter.string(from: NSNumber(value: size / pow(k, i))) ?? "Unknown"
let suffix = suffixes[Int(i)]
return "\(numberString) \(suffix)"
}
}
extension ShareViewController: TeamsViewControllerDelegate {
func selectedTeam(deck: Item) {
selectedTeam = deck
selectedChannel = nil
self.getChannelsFromServerAndReload(forTeamId: deck.id!)
reloadConfigurationItems()
popConfigurationViewController()
}
}
extension ShareViewController: ChannelsViewControllerDelegate {
func selectedChannel(deck: Item) {
selectedChannel = deck
reloadConfigurationItems()
popConfigurationViewController()
}
}

View file

@ -1,57 +0,0 @@
import UIKit
class TeamsViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView(frame: self.view.frame)
tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
tableView.dataSource = self
tableView.delegate = self
tableView.backgroundColor = .clear
tableView.register(UITableViewCell.self, forCellReuseIdentifier: Identifiers.TeamCell)
return tableView
}()
var teamDecks = [Item]()
weak var delegate: TeamsViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
title = "Team"
view.addSubview(tableView)
}
}
private extension TeamsViewController {
struct Identifiers {
static let TeamCell = "teamCell"
}
}
extension TeamsViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return teamDecks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Identifiers.TeamCell, for: indexPath)
cell.textLabel?.text = teamDecks[indexPath.row].title
if teamDecks[indexPath.row].selected {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
cell.backgroundColor = .clear
return cell
}
}
protocol TeamsViewControllerDelegate: class {
func selectedTeam(deck: Item)
}
extension TeamsViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.selectedTeam(deck: teamDecks[indexPath.row])
}
}

View file

@ -1,111 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
StatusBar,
} from 'react-native';
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
declare const global: {HermesInternal: null | {}};
const Channel = () => {
return (
<>
<StatusBar barStyle='dark-content'/>
<SafeAreaView>
<ScrollView
contentInsetAdjustmentBehavior='automatic'
style={styles.scrollView}
>
<Header/>
{global.HermesInternal == null ? null : (
<View style={styles.engine}>
<Text style={styles.footer}>{'Engine: Hermes'}</Text>
</View>
)}
<View style={styles.body}>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>{'Step One'}</Text>
<Text style={styles.sectionDescription}>
{'Edit '}<Text style={styles.highlight}>{'/share_extension/index.tsx'}</Text>{' to change this'}
{'screen and then come back to see your edits.'}
</Text>
</View>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>{'See Your Changes'}</Text>
<Text style={styles.sectionDescription}>
<ReloadInstructions/>
</Text>
</View>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>{'Debug'}</Text>
<Text style={styles.sectionDescription}>
<DebugInstructions/>
</Text>
</View>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>{'Learn More'}</Text>
<Text style={styles.sectionDescription}>
{'Read the docs to discover what to do next:'}
</Text>
</View>
<LearnMoreLinks/>
</View>
</ScrollView>
</SafeAreaView>
</>
);
};
const styles = StyleSheet.create({
scrollView: {
backgroundColor: Colors.lighter,
},
engine: {
position: 'absolute',
right: 0,
},
body: {
backgroundColor: Colors.white,
},
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontFamily: 'OpenSans-SemiBold',
color: Colors.black,
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
color: Colors.dark,
},
highlight: {
fontFamily: 'OpenSans-Bold',
},
footer: {
color: Colors.dark,
fontSize: 12,
fontWeight: '600',
padding: 4,
paddingRight: 12,
textAlign: 'right',
},
});
export default Channel;