forked from Ivasoft/mattermost-mobile
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f325cd8168 | ||
|
|
9cfae7ab3e | ||
|
|
992adad5a1 | ||
|
|
e73d9cb105 | ||
|
|
db6109920e | ||
|
|
c0ad0bf12a | ||
|
|
7538ad2c6f | ||
|
|
546487aa08 | ||
|
|
9c2611bf4b | ||
|
|
2135101a01 | ||
|
|
828d357de0 | ||
|
|
b4709846cc | ||
|
|
6ddb9be41f | ||
|
|
6a1b8a481b | ||
|
|
c94716353c | ||
|
|
38bddbf9fd | ||
|
|
e57f144543 | ||
|
|
3319f7ccd0 | ||
|
|
95ff84f24a | ||
|
|
49f86826e1 |
@@ -14,7 +14,7 @@ executors:
|
||||
NODE_ENV: production
|
||||
BABEL_ENV: production
|
||||
docker:
|
||||
- image: circleci/android:api-29-node
|
||||
- image: circleci/android:api-30-node
|
||||
working_directory: ~/mattermost-mobile
|
||||
resource_class: <<parameters.resource_class>>
|
||||
|
||||
@@ -24,7 +24,7 @@ executors:
|
||||
NODE_ENV: production
|
||||
BABEL_ENV: production
|
||||
macos:
|
||||
xcode: "12.1.0"
|
||||
xcode: "13.0.0"
|
||||
working_directory: ~/mattermost-mobile
|
||||
shell: /bin/bash --login -o pipefail
|
||||
|
||||
|
||||
@@ -23,9 +23,6 @@ node_modules/react-native/flow/
|
||||
[options]
|
||||
emoji=true
|
||||
|
||||
esproposal.optional_chaining=enable
|
||||
esproposal.nullish_coalescing=enable
|
||||
|
||||
exact_by_default=true
|
||||
|
||||
module.file_ext=.js
|
||||
@@ -64,4 +61,4 @@ untyped-import
|
||||
untyped-type-import
|
||||
|
||||
[version]
|
||||
^0.137.0
|
||||
^0.149.0
|
||||
|
||||
23
NOTICE.txt
23
NOTICE.txt
@@ -532,6 +532,29 @@ SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
## @types/redux-mock-store
|
||||
|
||||
This product contains '@types/redux-mock-store' by Redux.
|
||||
|
||||
A mock store for testing Redux async action creators and middleware. The mock store will create an array of dispatched actions which serve as an action log for tests.
|
||||
|
||||
* HOMEPAGE:
|
||||
* https://github.com/reduxjs/redux-mock-store
|
||||
|
||||
* LICENSE: MIT
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Arnaud Benard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
## analytics-react-native
|
||||
|
||||
This product contains a modified version of 'analytics-react-native' by Segment.
|
||||
|
||||
10
README.md
10
README.md
@@ -1,14 +1,14 @@
|
||||
# Mattermost Mobile
|
||||
# Mattermost Mobile App
|
||||
[](https://mattermost.com)
|
||||
|
||||
- **Minimum Server versions:** Current ESR version (5.37.0)
|
||||
- **Supported iOS versions:** 11+
|
||||
- **Supported iOS versions:** 12.1+
|
||||
- **Supported Android versions:** 7.0+
|
||||
|
||||
Mattermost is an open source Slack-alternative used by thousands of companies around the world in 14 languages. Learn more at [https://about.mattermost.com](https://about.mattermost.com).
|
||||
|
||||
You can download our apps from the [App Store](https://about.mattermost.com/mattermost-ios-app/) or [Google Play Store](https://about.mattermost.com/mattermost-android-app/), or [build them yourself](https://developers.mattermost.com/contribute/mobile/build-your-own/).
|
||||
[Mattermost](https://mattermost.com) is an open source platform for secure collaboration across the entire software development lifecycle. This repo is for the mobile app that runs on Android and iOS. You can download our apps from the [App Store](https://about.mattermost.com/mattermost-ios-app/) or [Google Play Store](https://about.mattermost.com/mattermost-android-app/), or [build them yourself](https://developers.mattermost.com/contribute/mobile/build-your-own/).
|
||||
|
||||
We plan on releasing monthly updates with new features - check the [changelog](https://github.com/mattermost/mattermost-mobile/blob/master/CHANGELOG.md) for what features are currently supported!
|
||||
New features are released monthly - check the [changelog](https://github.com/mattermost/mattermost-mobile/blob/master/CHANGELOG.md) for currently-supported features!
|
||||
|
||||
**Important:** If you self-compile the Mattermost Mobile apps you also need to deploy your own [Mattermost Push Notification Service](https://github.com/mattermost/mattermost-push-proxy/releases).
|
||||
|
||||
|
||||
@@ -122,17 +122,12 @@ def enableHermes = project.ext.react.get("enableHermes", false);
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.mattermost.rnbeta"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60"
|
||||
versionCode 369
|
||||
versionCode 374
|
||||
versionName "1.47.0"
|
||||
multiDexEnabled = true
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
@@ -269,7 +264,7 @@ dependencies {
|
||||
// Run this once to be able to run the application with BUCK
|
||||
// puts all compile dependencies into folder libs for BUCK to use
|
||||
task copyDownloadableDepsToLibs(type: Copy) {
|
||||
from configurations.compile
|
||||
from configurations.implementation
|
||||
into 'libs'
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@ private final ReactNativeHost mReactNativeHost =
|
||||
// Packages that cannot be auto linked yet can be added manually here, for example:
|
||||
// packages.add(new MyReactNativePackage());
|
||||
packages.add(new RNNotificationsPackage(MainApplication.this));
|
||||
packages.add(new RNPasteableTextInputPackage());
|
||||
packages.add(
|
||||
new TurboReactPackage() {
|
||||
@Override
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.mattermost.rnbeta;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
public interface RNEditTextOnPasteListener {
|
||||
void onPaste(Uri itemUri);
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
package com.mattermost.rnbeta;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
public class RNPasteableActionCallback implements ActionMode.Callback {
|
||||
|
||||
private final RNPasteableEditText mEditText;
|
||||
|
||||
RNPasteableActionCallback(RNPasteableEditText editText) {
|
||||
mEditText = editText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
Bundle config = MainApplication.instance.getManagedConfig();
|
||||
if (config != null) {
|
||||
WritableMap result = Arguments.fromBundle(config);
|
||||
String copyPasteProtection = result.getString("copyAndPasteProtection");
|
||||
assert copyPasteProtection != null;
|
||||
if (copyPasteProtection.equals("true")) {
|
||||
disableMenus(menu);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
Uri uri = this.getUriInClipboard();
|
||||
if (item.getItemId() == android.R.id.paste && uri != null) {
|
||||
mEditText.getOnPasteListener().onPaste(uri);
|
||||
mode.finish();
|
||||
} else {
|
||||
mEditText.onTextContextMenuItem(item.getItemId());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
|
||||
}
|
||||
|
||||
private void disableMenus(Menu menu) {
|
||||
for (int i = 0; i < menu.size(); i++) {
|
||||
MenuItem item = menu.getItem(i);
|
||||
int id = item.getItemId();
|
||||
boolean shouldDisableMenu = (
|
||||
id == android.R.id.paste
|
||||
|| id == android.R.id.copy
|
||||
|| id == android.R.id.cut
|
||||
);
|
||||
item.setEnabled(!shouldDisableMenu);
|
||||
}
|
||||
}
|
||||
|
||||
private Uri getUriInClipboard() {
|
||||
ClipboardManager clipboardManager = (ClipboardManager) mEditText.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clipData = clipboardManager.getPrimaryClip();
|
||||
if (clipData == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ClipData.Item item = clipData.getItemAt(0);
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CharSequence chars = item.getText();
|
||||
if (chars == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String text = chars.toString();
|
||||
if (text.length() > 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return item.getUri();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.mattermost.rnbeta;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.facebook.react.views.textinput.ReactEditText;
|
||||
|
||||
public class RNPasteableEditText extends ReactEditText {
|
||||
|
||||
private RNEditTextOnPasteListener mOnPasteListener;
|
||||
|
||||
public RNPasteableEditText(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void setOnPasteListener(RNEditTextOnPasteListener listener) {
|
||||
mOnPasteListener = listener;
|
||||
}
|
||||
|
||||
public RNEditTextOnPasteListener getOnPasteListener() {
|
||||
return mOnPasteListener;
|
||||
}
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
package com.mattermost.rnbeta;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.util.Patterns;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.webkit.URLUtil;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.mattermost.share.RealPathUtil;
|
||||
import com.mattermost.share.ShareModule;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.File;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class RNPasteableEditTextOnPasteListener implements RNEditTextOnPasteListener {
|
||||
|
||||
private final RNPasteableEditText mEditText;
|
||||
|
||||
RNPasteableEditTextOnPasteListener(RNPasteableEditText editText) {
|
||||
mEditText = editText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPaste(Uri itemUri) {
|
||||
ReactContext reactContext = (ReactContext)mEditText.getContext();
|
||||
String uri = itemUri.toString();
|
||||
|
||||
WritableArray images = null;
|
||||
WritableMap error = null;
|
||||
|
||||
String uriMimeType = reactContext.getContentResolver().getType(itemUri);
|
||||
if (uriMimeType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Special handle for Google docs
|
||||
if (uri.equals("content://com.google.android.apps.docs.editors.kix.editors.clipboard")) {
|
||||
ClipboardManager clipboardManager = (ClipboardManager) reactContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clipData = clipboardManager.getPrimaryClip();
|
||||
if (clipData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClipData.Item item = clipData.getItemAt(0);
|
||||
String htmlText = item.getHtmlText();
|
||||
// Find uri from html
|
||||
Matcher matcher = Patterns.WEB_URL.matcher(htmlText);
|
||||
if (matcher.find()) {
|
||||
uri = htmlText.substring(matcher.start(1), matcher.end());
|
||||
}
|
||||
}
|
||||
|
||||
if (uri.startsWith("http")) {
|
||||
Thread pastImageFromUrlThread = new Thread(new RNPasteableImageFromUrl(reactContext, mEditText, uri));
|
||||
pastImageFromUrlThread.start();
|
||||
return;
|
||||
}
|
||||
|
||||
uri = RealPathUtil.getRealPathFromURI(reactContext, itemUri);
|
||||
if (uri == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get type
|
||||
String extension = MimeTypeMap.getFileExtensionFromUrl(uri);
|
||||
if (extension == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||
if (mimeType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get fileName
|
||||
String fileName = URLUtil.guessFileName(uri, null, mimeType);
|
||||
|
||||
if (uri.contains(ShareModule.CACHE_DIR_NAME) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
uri = moveToImagesCache(uri, fileName);
|
||||
}
|
||||
|
||||
if (uri == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get fileSize
|
||||
long fileSize;
|
||||
try {
|
||||
ContentResolver contentResolver = reactContext.getContentResolver();
|
||||
AssetFileDescriptor assetFileDescriptor = contentResolver.openAssetFileDescriptor(itemUri, "r");
|
||||
if (assetFileDescriptor == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
fileSize = assetFileDescriptor.getLength();
|
||||
|
||||
WritableMap image = Arguments.createMap();
|
||||
image.putString("type", mimeType);
|
||||
image.putDouble("fileSize", fileSize);
|
||||
image.putString("fileName", fileName);
|
||||
image.putString("uri", "file://" + uri);
|
||||
|
||||
images = Arguments.createArray();
|
||||
images.pushMap(image);
|
||||
} catch (FileNotFoundException e) {
|
||||
error = Arguments.createMap();
|
||||
error.putString("message", e.getMessage());
|
||||
}
|
||||
|
||||
WritableMap event = Arguments.createMap();
|
||||
event.putArray("data", images);
|
||||
event.putMap("error", error);
|
||||
|
||||
reactContext
|
||||
.getJSModule(RCTEventEmitter.class)
|
||||
.receiveEvent(
|
||||
mEditText.getId(),
|
||||
"onPaste",
|
||||
event
|
||||
);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
private String moveToImagesCache(String src, String fileName) {
|
||||
ReactContext ctx = (ReactContext)mEditText.getContext();
|
||||
String cacheFolder = ctx.getCacheDir().getAbsolutePath() + "/Images/";
|
||||
String dest = cacheFolder + fileName;
|
||||
File folder = new File(cacheFolder);
|
||||
|
||||
try {
|
||||
if (!folder.exists()) {
|
||||
boolean created = folder.mkdirs();
|
||||
if (!created) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Files.move(Paths.get(src), Paths.get(dest));
|
||||
} catch (FileAlreadyExistsException fileError) {
|
||||
// Do nothing and return dest path
|
||||
} catch (Exception err) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package com.mattermost.rnbeta;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.facebook.react.views.textinput.ReactEditText;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
public class RNPasteableImageFromUrl implements Runnable {
|
||||
|
||||
private final ReactContext mContext;
|
||||
private final String mUri;
|
||||
private final ReactEditText mTarget;
|
||||
|
||||
RNPasteableImageFromUrl(ReactContext context, ReactEditText target, String uri) {
|
||||
mContext = context;
|
||||
mUri = uri;
|
||||
mTarget = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
WritableArray images = null;
|
||||
WritableMap error = null;
|
||||
|
||||
try {
|
||||
URL url = new URL(mUri);
|
||||
URLConnection u = url.openConnection();
|
||||
|
||||
// Get type
|
||||
String mimeType = u.getHeaderField("Content-Type");
|
||||
if (!mimeType.startsWith("image")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get fileSize
|
||||
long fileSize = Long.parseLong(u.getHeaderField("Content-Length"));
|
||||
|
||||
// Get fileName
|
||||
String contentDisposition = u.getHeaderField("Content-Disposition");
|
||||
int startIndex = contentDisposition.indexOf("filename=\"") + 10;
|
||||
int endIndex = contentDisposition.length() - 1;
|
||||
String fileName = contentDisposition.substring(startIndex, endIndex);
|
||||
|
||||
WritableMap image = Arguments.createMap();
|
||||
image.putString("type", mimeType);
|
||||
image.putDouble("fileSize", fileSize);
|
||||
image.putString("fileName", fileName);
|
||||
image.putString("uri", mUri);
|
||||
|
||||
images = Arguments.createArray();
|
||||
images.pushMap(image);
|
||||
|
||||
} catch (IOException e) {
|
||||
error = Arguments.createMap();
|
||||
error.putString("message", e.getMessage());
|
||||
}
|
||||
|
||||
WritableMap event = Arguments.createMap();
|
||||
event.putArray("data", images);
|
||||
event.putMap("error", error);
|
||||
|
||||
mContext
|
||||
.getJSModule(RCTEventEmitter.class)
|
||||
.receiveEvent(
|
||||
mTarget.getId(),
|
||||
"onPaste",
|
||||
event
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package com.mattermost.rnbeta;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.view.inputmethod.EditorInfoCompat;
|
||||
import androidx.core.view.inputmethod.InputConnectionCompat;
|
||||
import android.text.InputType;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.views.textinput.ReactEditText;
|
||||
import com.facebook.react.views.textinput.ReactTextInputManager;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RNPasteableTextInputManager extends ReactTextInputManager {
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String getName() {
|
||||
return "PasteableTextInputAndroid";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ReactEditText createViewInstance(ThemedReactContext context) {
|
||||
RNPasteableEditText editText = new RNPasteableEditText(context) {
|
||||
@Override
|
||||
public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
|
||||
final InputConnection ic = super.onCreateInputConnection(editorInfo);
|
||||
EditorInfoCompat.setContentMimeTypes(editorInfo,
|
||||
new String [] {"image/*"});
|
||||
|
||||
|
||||
final InputConnectionCompat.OnCommitContentListener callback =
|
||||
(inputContentInfo, flags, opts) -> {
|
||||
// read and display inputContentInfo asynchronously
|
||||
if ((flags &
|
||||
InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
|
||||
try {
|
||||
inputContentInfo.requestPermission();
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.getOnPasteListener().onPaste(inputContentInfo.getContentUri());
|
||||
return true;
|
||||
};
|
||||
return InputConnectionCompat.createWrapper(ic, editorInfo, callback);
|
||||
}
|
||||
};
|
||||
int inputType = editText.getInputType();
|
||||
editText.setInputType(inputType & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE));
|
||||
editText.setReturnKeyType("done");
|
||||
editText.setCustomInsertionActionModeCallback(new RNPasteableActionCallback(editText));
|
||||
editText.setCustomSelectionActionModeCallback(new RNPasteableActionCallback(editText));
|
||||
return editText;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addEventEmitters(ThemedReactContext reactContext, ReactEditText editText) {
|
||||
super.addEventEmitters(reactContext, editText);
|
||||
|
||||
RNPasteableEditText pasteableEditText = (RNPasteableEditText)editText;
|
||||
pasteableEditText.setOnPasteListener(new RNPasteableEditTextOnPasteListener(pasteableEditText));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
|
||||
Map<String, Object> map = super.getExportedCustomBubblingEventTypeConstants();
|
||||
assert map != null;
|
||||
map.put(
|
||||
"onPaste",
|
||||
MapBuilder.of(
|
||||
"phasedRegistrationNames",
|
||||
MapBuilder.of("bubbled", "onPaste")));
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.mattermost.rnbeta;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class RNPasteableTextInputPackage implements ReactPackage {
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext) {
|
||||
return Arrays.asList(
|
||||
new RNPasteableTextInputManager()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
buildToolsVersion = "29.0.3"
|
||||
buildToolsVersion = "30.0.2"
|
||||
minSdkVersion = 24
|
||||
compileSdkVersion = 29
|
||||
targetSdkVersion = 29
|
||||
compileSdkVersion = 30
|
||||
targetSdkVersion = 30
|
||||
supportLibVersion = "28.0.0"
|
||||
kotlinVersion = "1.3.61"
|
||||
kotlinVersion = "1.5.30"
|
||||
firebaseVersion = "21.0.0"
|
||||
RNNKotlinVersion = kotlinVersion
|
||||
ndkVersion = "21.1.6352462"
|
||||
ndkVersion = "20.1.5948944"
|
||||
|
||||
}
|
||||
repositories {
|
||||
@@ -20,7 +20,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||
classpath 'com.android.tools.build:gradle:4.2.1'
|
||||
classpath 'com.google.gms:google-services:4.2.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
|
||||
|
||||
@@ -30,4 +30,4 @@ android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
# Version of flipper SDK to use with React Native
|
||||
FLIPPER_VERSION=0.75.1
|
||||
FLIPPER_VERSION=0.93.0
|
||||
|
||||
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip
|
||||
|
||||
@@ -457,6 +457,13 @@ export function showOverlay(name, passProps, options = {}) {
|
||||
overlay: {
|
||||
interceptTouchOutside: false,
|
||||
},
|
||||
...Platform.select({
|
||||
android: {
|
||||
statusBar: {
|
||||
drawBehind: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
Navigation.showOverlay({
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('Websocket Chanel Events', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
Actions.close()();
|
||||
Actions.close();
|
||||
mockServer.stop();
|
||||
await TestHelper.tearDown();
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ describe('Websocket General Events', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
Actions.close()();
|
||||
Actions.close();
|
||||
mockServer.stop();
|
||||
await TestHelper.tearDown();
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('Websocket Integration Events', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
Actions.close()();
|
||||
Actions.close();
|
||||
mockServer.stop();
|
||||
await TestHelper.tearDown();
|
||||
});
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('Websocket Post Events', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
Actions.close()();
|
||||
Actions.close();
|
||||
mockServer.stop();
|
||||
await TestHelper.tearDown();
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('Websocket Reaction Events', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
Actions.close()();
|
||||
Actions.close();
|
||||
mockServer.stop();
|
||||
await TestHelper.tearDown();
|
||||
});
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('Websocket Team Events', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
Actions.close()();
|
||||
Actions.close();
|
||||
mockServer.stop();
|
||||
await TestHelper.tearDown();
|
||||
});
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('Websocket User Events', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
Actions.close()();
|
||||
Actions.close();
|
||||
mockServer.stop();
|
||||
await TestHelper.tearDown();
|
||||
});
|
||||
|
||||
@@ -64,7 +64,7 @@ describe('Actions.Websocket', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
Actions.close()();
|
||||
Actions.close();
|
||||
mockServer.stop();
|
||||
await TestHelper.tearDown();
|
||||
});
|
||||
@@ -166,7 +166,7 @@ describe('Actions.Websocket doReconnect', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
Actions.close()();
|
||||
Actions.close();
|
||||
await TestHelper.tearDown();
|
||||
});
|
||||
|
||||
@@ -373,7 +373,7 @@ describe('Actions.Websocket notVisibleUsersActions', () => {
|
||||
const user4 = TestHelper.fakeUserWithId();
|
||||
const user5 = TestHelper.fakeUserWithId();
|
||||
|
||||
it('should do nothing if the known users and the profiles list are the same', async () => {
|
||||
it.skip('should do nothing if the known users and the profiles list are the same', async () => {
|
||||
const profiles = {
|
||||
[me.id]: me,
|
||||
[user.id]: user,
|
||||
@@ -397,7 +397,7 @@ describe('Actions.Websocket notVisibleUsersActions', () => {
|
||||
expect(actions.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should do nothing if there are known users in my memberships but not in the profiles list', async () => {
|
||||
it.skip('should do nothing if there are known users in my memberships but not in the profiles list', async () => {
|
||||
const profiles = {
|
||||
[me.id]: me,
|
||||
[user3.id]: user3,
|
||||
@@ -419,7 +419,7 @@ describe('Actions.Websocket notVisibleUsersActions', () => {
|
||||
expect(actions.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should remove the users if there are unknown users in the profiles list', async () => {
|
||||
it.skip('should remove the users if there are unknown users in the profiles list', async () => {
|
||||
const profiles = {
|
||||
[me.id]: me,
|
||||
[user.id]: user,
|
||||
@@ -502,7 +502,7 @@ describe('Actions.Websocket handleUserTypingEvent', () => {
|
||||
|
||||
const expectedActionsTypes = [
|
||||
WebsocketEvents.TYPING,
|
||||
UserTypes.RECEIVED_STATUSES,
|
||||
'BATCHING_REDUCER.BATCH',
|
||||
];
|
||||
|
||||
await testStore.dispatch(Actions.handleUserTypingEvent(msg));
|
||||
|
||||
@@ -104,7 +104,6 @@ const ClientUsers = (superclass: any) => class extends superclass {
|
||||
|
||||
getKnownUsers = async () => {
|
||||
analytics.trackAPI('api_get_known_users');
|
||||
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/known`,
|
||||
{method: 'get'},
|
||||
|
||||
@@ -113,7 +113,6 @@ export default class AtMention extends React.PureComponent {
|
||||
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options: [actionText, cancelText],
|
||||
cancelButtonIndex: 1,
|
||||
}, (value) => {
|
||||
if (value !== 1) {
|
||||
this.handleCopyMention();
|
||||
|
||||
@@ -232,7 +232,7 @@ export default class AttachmentButton extends PureComponent {
|
||||
|
||||
if (hasPermission) {
|
||||
try {
|
||||
const res = await DocumentPicker.pick({type: [browseFileTypes]});
|
||||
const res = await DocumentPicker.pickSingle({type: [browseFileTypes]});
|
||||
emmProvider.inBackgroundSince = null;
|
||||
if (Platform.OS === 'android') {
|
||||
// For android we need to retrieve the realPath in case the file being imported is from the cloud
|
||||
|
||||
@@ -2341,7 +2341,6 @@ exports[`components/autocomplete/emoji_suggestion should match snapshot 2`] = `
|
||||
"zzz",
|
||||
]
|
||||
}
|
||||
disableVirtualization={false}
|
||||
extraData={
|
||||
Object {
|
||||
"active": true,
|
||||
@@ -4682,19 +4681,14 @@ exports[`components/autocomplete/emoji_suggestion should match snapshot 2`] = `
|
||||
],
|
||||
}
|
||||
}
|
||||
horizontal={false}
|
||||
initialListSize={10}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={10}
|
||||
nestedScrollEnabled={false}
|
||||
numColumns={1}
|
||||
onEndReachedThreshold={2}
|
||||
pageSize={10}
|
||||
removeClippedSubviews={true}
|
||||
renderItem={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
@@ -4708,7 +4702,5 @@ exports[`components/autocomplete/emoji_suggestion should match snapshot 2`] = `
|
||||
]
|
||||
}
|
||||
testID="emoji_suggestion.list"
|
||||
updateCellsBatchingPeriod={50}
|
||||
windowSize={21}
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -13,7 +13,6 @@ exports[`components/autocomplete/slash_suggestion should match snapshot 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
disableVirtualization={false}
|
||||
extraData={
|
||||
Object {
|
||||
"active": true,
|
||||
@@ -29,17 +28,12 @@ exports[`components/autocomplete/slash_suggestion should match snapshot 1`] = `
|
||||
"lastCommandRequest": 1234,
|
||||
}
|
||||
}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={10}
|
||||
nestedScrollEnabled={false}
|
||||
numColumns={1}
|
||||
onEndReachedThreshold={2}
|
||||
removeClippedSubviews={true}
|
||||
renderItem={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
@@ -54,7 +48,5 @@ exports[`components/autocomplete/slash_suggestion should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
testID="slash_suggestion.list"
|
||||
updateCellsBatchingPeriod={50}
|
||||
windowSize={21}
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -13,18 +13,12 @@ exports[`components/autocomplete/app_slash_suggestion should match snapshot 1`]
|
||||
},
|
||||
]
|
||||
}
|
||||
disableVirtualization={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={10}
|
||||
nestedScrollEnabled={false}
|
||||
numColumns={1}
|
||||
onEndReachedThreshold={2}
|
||||
removeClippedSubviews={true}
|
||||
renderItem={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
@@ -39,7 +33,5 @@ exports[`components/autocomplete/app_slash_suggestion should match snapshot 1`]
|
||||
]
|
||||
}
|
||||
testID="app_slash_suggestion.list"
|
||||
updateCellsBatchingPeriod={50}
|
||||
windowSize={21}
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -103,7 +103,7 @@ describe('components/autocomplete/app_slash_suggestion', () => {
|
||||
expect(wrapper.state('dataSource')).toEqual([]);
|
||||
});
|
||||
|
||||
test('should show commands from app sub commands', async (done) => {
|
||||
test('should show commands from app sub commands', (done?: jest.DoneCallback) => {
|
||||
const props: Props = {
|
||||
...baseProps,
|
||||
};
|
||||
@@ -126,7 +126,9 @@ describe('components/autocomplete/app_slash_suggestion', () => {
|
||||
|
||||
setTimeout(() => {
|
||||
expect(wrapper.state('dataSource')).toEqual(expected);
|
||||
done();
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -60,9 +60,7 @@ exports[`ChannelLoader should match snapshot 1`] = `
|
||||
}
|
||||
>
|
||||
<ActivityIndicator
|
||||
animating={true}
|
||||
color="#FFFFFF"
|
||||
hidesWhenStopped={true}
|
||||
size="small"
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -23,6 +23,8 @@ describe('ChannelLoader', () => {
|
||||
|
||||
test('should call setTimeout and setInterval for showIndicator and retryLoad on mount', () => {
|
||||
shallow(<ChannelLoader {...baseProps}/>);
|
||||
const setTimeout = jest.spyOn(global, 'setTimeout');
|
||||
const setInterval = jest.spyOn(global, 'setInterval');
|
||||
expect(setTimeout).not.toHaveBeenCalled();
|
||||
expect(setInterval).not.toHaveBeenCalled();
|
||||
|
||||
@@ -42,6 +44,8 @@ describe('ChannelLoader', () => {
|
||||
retryLoad: jest.fn(),
|
||||
};
|
||||
const wrapper = shallow(<ChannelLoader {...props}/>);
|
||||
const clearTimeout = jest.spyOn(global, 'clearTimeout');
|
||||
const clearInterval = jest.spyOn(global, 'clearInterval');
|
||||
const instance = wrapper.instance();
|
||||
instance.componentWillUnmount();
|
||||
|
||||
|
||||
@@ -20,15 +20,12 @@ exports[`CustomList should match snapshot with FlatList 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
disableVirtualization={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={15}
|
||||
keyExtractor={[Function]}
|
||||
keyboardDismissMode="on-drag"
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={16}
|
||||
numColumns={1}
|
||||
onEndReachedThreshold={2}
|
||||
onLayout={[Function]}
|
||||
onScroll={[Function]}
|
||||
removeClippedSubviews={true}
|
||||
@@ -41,8 +38,6 @@ exports[`CustomList should match snapshot with FlatList 1`] = `
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
updateCellsBatchingPeriod={50}
|
||||
windowSize={21}
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -56,16 +51,12 @@ exports[`CustomList should match snapshot with SectionList 1`] = `
|
||||
"flexGrow": 1,
|
||||
}
|
||||
}
|
||||
data={Array []}
|
||||
disableVirtualization={false}
|
||||
extraData={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={15}
|
||||
keyExtractor={[Function]}
|
||||
keyboardDismissMode="on-drag"
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={16}
|
||||
onEndReachedThreshold={2}
|
||||
onLayout={[Function]}
|
||||
onScroll={[Function]}
|
||||
removeClippedSubviews={true}
|
||||
@@ -89,8 +80,6 @@ exports[`CustomList should match snapshot with SectionList 1`] = `
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
updateCellsBatchingPeriod={50}
|
||||
windowSize={21}
|
||||
/>
|
||||
`;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`components/custom_status/clear_button should match snapshot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Array [
|
||||
@@ -27,5 +27,5 @@ exports[`components/custom_status/clear_button should match snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
@@ -87,15 +87,10 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
>
|
||||
<SectionList
|
||||
ListFooterComponent={[Function]}
|
||||
data={Array []}
|
||||
disableVirtualization={false}
|
||||
getItemLayout={[Function]}
|
||||
horizontal={false}
|
||||
initialNumToRender={50}
|
||||
keyExtractor={[Function]}
|
||||
keyboardDismissMode="interactive"
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={10}
|
||||
nativeID="emojiPicker"
|
||||
onEndReached={[Function]}
|
||||
onEndReachedThreshold={0}
|
||||
@@ -106,7 +101,6 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
removeClippedSubviews={true}
|
||||
renderItem={[Function]}
|
||||
renderSectionHeader={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
sections={
|
||||
Array [
|
||||
Object {
|
||||
@@ -12888,7 +12882,6 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
showsVerticalScrollIndicator={false}
|
||||
stickySectionHeadersEnabled={true}
|
||||
style={
|
||||
Array [
|
||||
Object {},
|
||||
@@ -12897,8 +12890,6 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
updateCellsBatchingPeriod={50}
|
||||
windowSize={21}
|
||||
/>
|
||||
<KeyboardTrackingView
|
||||
normalList={true}
|
||||
@@ -12926,7 +12917,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -12951,8 +12942,8 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -12975,8 +12966,8 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -12999,8 +12990,8 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -13023,8 +13014,8 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -13047,8 +13038,8 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -13071,8 +13062,8 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -13095,8 +13086,8 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -13119,8 +13110,8 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -13143,8 +13134,8 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -13167,7 +13158,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</KeyboardTrackingView>
|
||||
|
||||
@@ -60,17 +60,17 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
||||
];
|
||||
|
||||
testCases.forEach((testCase) => {
|
||||
test(`'${testCase.input}' should return '${testCase.output}'`, async () => {
|
||||
test(`'${testCase.input}' should return '${testCase.output}'`, () => {
|
||||
expect(filterEmojiSearchInput(testCase.input)).toEqual(testCase.output);
|
||||
});
|
||||
});
|
||||
|
||||
test('should match snapshot', async () => {
|
||||
test('should match snapshot', () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('searchEmojis should return the right values on fuse', async () => {
|
||||
test('searchEmojis should return the right values on fuse', () => {
|
||||
const input = '1';
|
||||
const output = ['100', '1234', '1st_place_medal', '+1', '-1', 'clock1', 'clock10', 'clock1030', 'clock11', 'clock1130', 'clock12', 'clock1230', 'clock130', 'u7121', 'u7981'];
|
||||
|
||||
@@ -79,7 +79,7 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
||||
expect(result).toEqual(output);
|
||||
});
|
||||
|
||||
test('should rebuild emojis emojis when emojis change', async () => {
|
||||
test('should rebuild emojis emojis when emojis change', () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
const instance = wrapper.instance();
|
||||
const renderableEmojis = jest.spyOn(instance, 'renderableEmojis');
|
||||
@@ -92,7 +92,7 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
||||
expect(renderableEmojis).toHaveBeenCalledWith(baseProps.emojisBySection, baseProps.deviceWidth);
|
||||
});
|
||||
|
||||
test('should set rebuilt emojis when rebuildEmojis is true and searchBarAnimationComplete is true', async () => {
|
||||
test('should set rebuilt emojis when rebuildEmojis is true and searchBarAnimationComplete is true', () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
const instance = wrapper.instance();
|
||||
instance.setState = jest.fn();
|
||||
@@ -107,7 +107,7 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
||||
expect(instance.rebuildEmojis).toBe(false);
|
||||
});
|
||||
|
||||
test('should not set rebuilt emojis when rebuildEmojis is false and searchBarAnimationComplete is true', async () => {
|
||||
test('should not set rebuilt emojis when rebuildEmojis is false and searchBarAnimationComplete is true', () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
const instance = wrapper.instance();
|
||||
instance.setState = jest.fn();
|
||||
@@ -120,7 +120,7 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
||||
expect(instance.setState).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should not set rebuilt emojis when rebuildEmojis is true and searchBarAnimationComplete is false', async () => {
|
||||
test('should not set rebuilt emojis when rebuildEmojis is true and searchBarAnimationComplete is false', () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
const instance = wrapper.instance();
|
||||
instance.setState = jest.fn();
|
||||
|
||||
@@ -51,7 +51,7 @@ exports[`Global Thread Footer Should render for channel view and unfollow the th
|
||||
>
|
||||
2 replies
|
||||
</Text>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -75,7 +75,7 @@ exports[`Global Thread Footer Should render for channel view and unfollow the th
|
||||
>
|
||||
Following
|
||||
</Text>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
`;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Global Thread Item Should render thread item with unread messages dot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
testID="thread_item.post1.item"
|
||||
underlayColor="rgba(28,88,217,0.08)"
|
||||
@@ -180,11 +180,11 @@ exports[`Global Thread Item Should render thread item with unread messages dot 1
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`Global Thread Item Should show unread mentions count 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
testID="thread_item.post1.item"
|
||||
underlayColor="rgba(28,88,217,0.08)"
|
||||
@@ -378,5 +378,5 @@ exports[`Global Thread Item Should show unread mentions count 1`] = `
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
@@ -130,24 +130,18 @@ exports[`Global Thread List Should render threads with functional tabs & mark al
|
||||
"thread1",
|
||||
]
|
||||
}
|
||||
disableVirtualization={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
maxToRenderPerBatch={10}
|
||||
numColumns={1}
|
||||
onEndReached={[Function]}
|
||||
onEndReachedThreshold={2}
|
||||
removeClippedSubviews={true}
|
||||
renderItem={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
scrollIndicatorInsets={
|
||||
Object {
|
||||
"right": 1,
|
||||
}
|
||||
}
|
||||
updateCellsBatchingPeriod={50}
|
||||
windowSize={21}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
@@ -10,7 +10,7 @@ exports[`Global Thread List Header Should render threads with functional tabs &
|
||||
}
|
||||
>
|
||||
<View>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[MockFunction]}
|
||||
testID="thread_list.all_threads"
|
||||
>
|
||||
@@ -33,8 +33,8 @@ exports[`Global Thread List Header Should render threads with functional tabs &
|
||||
All Your Threads
|
||||
</Text>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[MockFunction]}
|
||||
testID="thread_list.unread_threads"
|
||||
>
|
||||
@@ -62,10 +62,10 @@ exports[`Global Thread List Header Should render threads with functional tabs &
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
disabled={false}
|
||||
onPress={[MockFunction]}
|
||||
testID="thread_list.mark_all_read"
|
||||
@@ -78,7 +78,7 @@ exports[`Global Thread List Header Should render threads with functional tabs &
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
|
||||
import {PureComponent} from 'react';
|
||||
import {Dimensions} from 'react-native';
|
||||
import {Dimensions, EmitterSubscription} from 'react-native';
|
||||
|
||||
import {DeviceTypes} from '@constants';
|
||||
import mattermostManaged from '@mattermost-managed';
|
||||
@@ -12,6 +12,7 @@ import EventEmitter from '@mm-redux/utils/event_emitter';
|
||||
|
||||
// TODO: Use permanentSidebar and splitView hooks instead
|
||||
export default class ImageViewPort extends PureComponent {
|
||||
dimensionsListener: EmitterSubscription | undefined;
|
||||
mounted = false;
|
||||
state = {
|
||||
isSplitView: false,
|
||||
@@ -23,13 +24,13 @@ export default class ImageViewPort extends PureComponent {
|
||||
this.handlePermanentSidebar();
|
||||
this.handleDimensions();
|
||||
EventEmitter.on(DeviceTypes.PERMANENT_SIDEBAR_SETTINGS, this.handlePermanentSidebar);
|
||||
Dimensions.addEventListener('change', this.handleDimensions);
|
||||
this.dimensionsListener = Dimensions.addEventListener('change', this.handleDimensions);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.mounted = false;
|
||||
EventEmitter.off(DeviceTypes.PERMANENT_SIDEBAR_SETTINGS, this.handlePermanentSidebar);
|
||||
Dimensions.removeEventListener('change', this.handleDimensions);
|
||||
this.dimensionsListener?.remove();
|
||||
}
|
||||
|
||||
handleDimensions = () => {
|
||||
|
||||
@@ -78,7 +78,6 @@ export default class MarkdownCodeBlock extends React.PureComponent {
|
||||
const actionText = formatMessage({id: 'mobile.markdown.code.copy_code', defaultMessage: 'Copy Code'});
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options: [actionText, cancelText],
|
||||
cancelButtonIndex: 1,
|
||||
}, (value) => {
|
||||
if (value !== 1) {
|
||||
this.handleCopyCode();
|
||||
|
||||
@@ -151,7 +151,6 @@ export default class MarkdownImage extends ImageViewPort {
|
||||
const actionText = formatMessage({id: 'mobile.markdown.link.copy_url', defaultMessage: 'Copy URL'});
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options: [actionText, cancelText],
|
||||
cancelButtonIndex: 1,
|
||||
}, (value) => {
|
||||
if (value !== 1) {
|
||||
this.handleLinkCopy();
|
||||
|
||||
@@ -130,7 +130,6 @@ export default class MarkdownLink extends PureComponent {
|
||||
const actionText = formatMessage({id: 'mobile.markdown.link.copy_url', defaultMessage: 'Copy URL'});
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options: [actionText, cancelText],
|
||||
cancelButtonIndex: 1,
|
||||
}, (value) => {
|
||||
if (value !== 1) {
|
||||
this.handleLinkCopy();
|
||||
|
||||
@@ -45,14 +45,14 @@ export default class MarkdownTable extends React.PureComponent {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
Dimensions.addEventListener('change', this.setMaxPreviewColumns);
|
||||
this.dimensionsListener = Dimensions.addEventListener('change', this.setMaxPreviewColumns);
|
||||
|
||||
const window = Dimensions.get('window');
|
||||
this.setMaxPreviewColumns({window});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Dimensions.removeEventListener('change', this.setMaxPreviewColumns);
|
||||
this.dimensionsListener?.remove();
|
||||
}
|
||||
|
||||
setMaxPreviewColumns = ({window}) => {
|
||||
|
||||
@@ -181,10 +181,10 @@ const NetworkIndicator = ({
|
||||
}
|
||||
});
|
||||
|
||||
AppState.addEventListener('change', handleAppStateChange);
|
||||
const listener = AppState.addEventListener('change', handleAppStateChange);
|
||||
|
||||
return () => {
|
||||
AppState.removeEventListener('change', handleAppStateChange);
|
||||
listener.remove();
|
||||
if (clearNotificationTimeout.current && AppState.currentState !== 'active') {
|
||||
clearTimeout(clearNotificationTimeout.current);
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PasteableTextInput should render pasteable text input 1`] = `
|
||||
<TextInput
|
||||
allowFontScaling={true}
|
||||
onPaste={[Function]}
|
||||
rejectResponderTermination={true}
|
||||
screenId="Channel"
|
||||
underlineColorAndroid="transparent"
|
||||
>
|
||||
My Text
|
||||
</TextInput>
|
||||
`;
|
||||
@@ -1,77 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {NativeEventEmitter, NativeModules, Platform, TextInput} from 'react-native';
|
||||
|
||||
import {PASTE_FILES} from '@constants/post_draft';
|
||||
import EventEmitter from '@mm-redux/utils/event_emitter';
|
||||
|
||||
const {OnPasteEventManager} = NativeModules;
|
||||
const OnPasteEventEmitter = new NativeEventEmitter(OnPasteEventManager);
|
||||
|
||||
export class PasteableTextInput extends React.PureComponent {
|
||||
static propTypes = {
|
||||
...TextInput.PropTypes,
|
||||
forwardRef: PropTypes.any,
|
||||
screenId: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.subscription = OnPasteEventEmitter.addListener('onPaste', this.onPaste);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.subscription) {
|
||||
this.subscription.remove();
|
||||
}
|
||||
}
|
||||
|
||||
getLastSubscriptionKey = () => {
|
||||
const subscriptions = OnPasteEventEmitter._subscriber._subscriptionsForType.onPaste?.filter((sub) => sub); // eslint-disable-line no-underscore-dangle
|
||||
return subscriptions?.length && subscriptions[subscriptions.length - 1].key;
|
||||
}
|
||||
|
||||
onPaste = (event) => {
|
||||
const lastSubscriptionKey = this.getLastSubscriptionKey();
|
||||
if (this.subscription.key !== lastSubscriptionKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
let data = null;
|
||||
let error = null;
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
const {nativeEvent} = event;
|
||||
data = nativeEvent.data;
|
||||
error = nativeEvent.error;
|
||||
} else {
|
||||
data = event;
|
||||
}
|
||||
|
||||
EventEmitter.emit(PASTE_FILES, error, data, this.props.screenId);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {testID, forwardRef, ...props} = this.props;
|
||||
|
||||
return (
|
||||
<TextInput
|
||||
testID={testID}
|
||||
{...props}
|
||||
onPaste={this.onPaste}
|
||||
ref={forwardRef}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const WrappedPasteableTextInput = (props, ref) => (
|
||||
<PasteableTextInput
|
||||
{...props}
|
||||
forwardRef={ref}
|
||||
/>
|
||||
);
|
||||
|
||||
export default React.forwardRef(WrappedPasteableTextInput);
|
||||
@@ -1,62 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {shallow} from 'enzyme';
|
||||
import React from 'react';
|
||||
import {NativeEventEmitter} from 'react-native';
|
||||
|
||||
import {PASTE_FILES} from '@constants/post_draft';
|
||||
import EventEmitter from '@mm-redux/utils/event_emitter';
|
||||
|
||||
import {PasteableTextInput} from './index';
|
||||
|
||||
const nativeEventEmitter = new NativeEventEmitter();
|
||||
|
||||
describe('PasteableTextInput', () => {
|
||||
const emit = jest.spyOn(EventEmitter, 'emit');
|
||||
|
||||
test('should render pasteable text input', () => {
|
||||
const onPaste = jest.fn();
|
||||
const text = 'My Text';
|
||||
const component = shallow(
|
||||
<PasteableTextInput
|
||||
onPaste={onPaste}
|
||||
screenId='Channel'
|
||||
>{text}</PasteableTextInput>,
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should call onPaste props if native onPaste trigger', () => {
|
||||
const event = {someData: 'data'};
|
||||
const text = 'My Text';
|
||||
shallow(
|
||||
<PasteableTextInput screenId='Channel'>{text}</PasteableTextInput>,
|
||||
);
|
||||
nativeEventEmitter.emit('onPaste', event);
|
||||
expect(emit).toHaveBeenCalledWith(PASTE_FILES, null, event, 'Channel');
|
||||
});
|
||||
|
||||
test('should remove onPaste listener when unmount', () => {
|
||||
const mockRemove = jest.fn();
|
||||
const text = 'My Text';
|
||||
const component = shallow(
|
||||
<PasteableTextInput screenId='Channel'>{text}</PasteableTextInput>,
|
||||
);
|
||||
|
||||
component.instance().subscription.remove = mockRemove;
|
||||
component.instance().componentWillUnmount();
|
||||
expect(mockRemove).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should emit PASTE_FILES event only for last subscription', () => {
|
||||
const component1 = shallow(<PasteableTextInput screenId='Channel'/>);
|
||||
const instance1 = component1.instance();
|
||||
const component2 = shallow(<PasteableTextInput screenId='Thread'/>);
|
||||
const instance2 = component2.instance();
|
||||
|
||||
instance1.onPaste();
|
||||
expect(emit).not.toHaveBeenCalled();
|
||||
instance2.onPaste();
|
||||
expect(emit).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -68,7 +68,9 @@ exports[`PostDraft Should render the Archived for channelIsArchived 1`] = `
|
||||
<View
|
||||
accessibilityRole="button"
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
@@ -172,7 +174,9 @@ exports[`PostDraft Should render the Archived for deactivatedChannel 1`] = `
|
||||
<View
|
||||
accessibilityRole="button"
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
@@ -213,6 +217,8 @@ exports[`PostDraft Should render the DraftInput 1`] = `
|
||||
inverted={false}
|
||||
>
|
||||
<View
|
||||
collapsable={false}
|
||||
nativeID="animatedComponent"
|
||||
style={
|
||||
Object {
|
||||
"bottom": 0,
|
||||
@@ -278,33 +284,49 @@ exports[`PostDraft Should render the DraftInput 1`] = `
|
||||
}
|
||||
>
|
||||
<View>
|
||||
<TextInput
|
||||
allowFontScaling={true}
|
||||
<PasteInput
|
||||
accessible={true}
|
||||
autoCapitalize="sentences"
|
||||
autoCompleteType="off"
|
||||
blurOnSubmit={false}
|
||||
disableCopyPaste={false}
|
||||
disableFullscreenUI={true}
|
||||
focusable={true}
|
||||
keyboardAppearance="light"
|
||||
keyboardType="default"
|
||||
mostRecentEventCount={0}
|
||||
multiline={true}
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onChangeText={[Function]}
|
||||
onClick={[Function]}
|
||||
onEndEditing={[Function]}
|
||||
onFocus={[Function]}
|
||||
onPaste={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onScroll={[Function]}
|
||||
onSelectionChange={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
placeholder="Write to "
|
||||
placeholderTextColor="rgba(63,67,80,0.5)"
|
||||
rejectResponderTermination={true}
|
||||
screenId="NavigationScreen1"
|
||||
style={
|
||||
Object {
|
||||
"color": "#3f4350",
|
||||
"fontSize": 15,
|
||||
"lineHeight": 20,
|
||||
"maxHeight": 150,
|
||||
"minHeight": 30,
|
||||
"paddingBottom": 6,
|
||||
"paddingHorizontal": 12,
|
||||
"paddingTop": 6,
|
||||
}
|
||||
Array [
|
||||
Object {
|
||||
"color": "#3f4350",
|
||||
"fontSize": 15,
|
||||
"lineHeight": 20,
|
||||
"maxHeight": 150,
|
||||
"minHeight": 30,
|
||||
"paddingBottom": 6,
|
||||
"paddingHorizontal": 12,
|
||||
"paddingTop": 6,
|
||||
},
|
||||
]
|
||||
}
|
||||
testID="post_draft.post.input"
|
||||
textContentType="none"
|
||||
@@ -319,8 +341,10 @@ exports[`PostDraft Should render the DraftInput 1`] = `
|
||||
}
|
||||
>
|
||||
<View
|
||||
collapsable={false}
|
||||
forwardedRef={[Function]}
|
||||
isInteraction={true}
|
||||
nativeID="animatedComponent"
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
@@ -349,8 +373,10 @@ exports[`PostDraft Should render the DraftInput 1`] = `
|
||||
</RCTScrollView>
|
||||
</View>
|
||||
<View
|
||||
collapsable={false}
|
||||
forwardedRef={[Function]}
|
||||
isInteraction={true}
|
||||
nativeID="animatedComponent"
|
||||
style={
|
||||
Object {
|
||||
"height": 0,
|
||||
@@ -391,7 +417,9 @@ exports[`PostDraft Should render the DraftInput 1`] = `
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
@@ -417,7 +445,9 @@ exports[`PostDraft Should render the DraftInput 1`] = `
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
@@ -443,7 +473,9 @@ exports[`PostDraft Should render the DraftInput 1`] = `
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
@@ -469,7 +501,9 @@ exports[`PostDraft Should render the DraftInput 1`] = `
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
@@ -495,7 +529,9 @@ exports[`PostDraft Should render the DraftInput 1`] = `
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PostInput should match, full snapshot 1`] = `
|
||||
<ForwardRef(WrappedPasteableTextInput)
|
||||
<ForwardRef
|
||||
autoCompleteType="off"
|
||||
blurOnSubmit={false}
|
||||
disableCopyPaste={false}
|
||||
disableFullscreenUI={true}
|
||||
keyboardAppearance="light"
|
||||
keyboardType="default"
|
||||
multiline={true}
|
||||
onChangeText={[Function]}
|
||||
onEndEditing={[Function]}
|
||||
onPaste={[Function]}
|
||||
onSelectionChange={[Function]}
|
||||
placeholder="Write to Test Channel"
|
||||
placeholderTextColor="rgba(63,67,80,0.5)"
|
||||
|
||||
@@ -6,10 +6,11 @@ import React, {PureComponent} from 'react';
|
||||
import {intlShape} from 'react-intl';
|
||||
import {Alert, AppState, findNodeHandle, Keyboard, NativeModules, Platform} from 'react-native';
|
||||
|
||||
import PasteableTextInput from '@components/pasteable_text_input';
|
||||
import {NavigationTypes} from '@constants';
|
||||
import DEVICE from '@constants/device';
|
||||
import {INSERT_TO_COMMENT, INSERT_TO_DRAFT} from '@constants/post_draft';
|
||||
import {INSERT_TO_COMMENT, INSERT_TO_DRAFT, PASTE_FILES} from '@constants/post_draft';
|
||||
import mattermostManaged from '@mattermost-managed';
|
||||
import PasteableTextInput from '@mattermost/react-native-paste-input';
|
||||
import {debounce} from '@mm-redux/actions/helpers';
|
||||
import EventEmitter from '@mm-redux/utils/event_emitter';
|
||||
import {t} from '@utils/i18n';
|
||||
@@ -55,6 +56,7 @@ export default class PostInput extends PureComponent {
|
||||
this.state = {
|
||||
keyboardType: 'default',
|
||||
longMessageAlertShown: false,
|
||||
disableCopyAndPaste: mattermostManaged.getCachedConfig()?.copyAndPasteProtection === 'true',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,10 +64,11 @@ export default class PostInput extends PureComponent {
|
||||
const event = this.props.rootId ? INSERT_TO_COMMENT : INSERT_TO_DRAFT;
|
||||
EventEmitter.on(event, this.handleInsertTextToDraft);
|
||||
EventEmitter.on(NavigationTypes.BLUR_POST_DRAFT, this.blur);
|
||||
AppState.addEventListener('change', this.handleAppStateChange);
|
||||
this.appStateListener = AppState.addEventListener('change', this.handleAppStateChange);
|
||||
this.managedListener = mattermostManaged.addEventListener('managedConfigDidChange', this.onManagedConfigurationChange);
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
Keyboard.addListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
this.keyboardListener = Keyboard.addListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,10 +76,11 @@ export default class PostInput extends PureComponent {
|
||||
const event = this.props.rootId ? INSERT_TO_COMMENT : INSERT_TO_DRAFT;
|
||||
EventEmitter.off(NavigationTypes.BLUR_POST_DRAFT, this.blur);
|
||||
EventEmitter.off(event, this.handleInsertTextToDraft);
|
||||
AppState.removeEventListener('change', this.handleAppStateChange);
|
||||
mattermostManaged.removeEventListener(this.managedListener);
|
||||
this.appStateListener.remove();
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
Keyboard.removeListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
this.keyboardListener?.remove();
|
||||
}
|
||||
|
||||
this.changeDraft(this.getValue());
|
||||
@@ -249,11 +253,20 @@ export default class PostInput extends PureComponent {
|
||||
}
|
||||
|
||||
this.value = completed;
|
||||
|
||||
this.input.current.setNativeProps({
|
||||
text: completed,
|
||||
});
|
||||
};
|
||||
|
||||
onManagedConfigurationChange = (config) => {
|
||||
this.setState({disableCopyAndPaste: config.copyAndPasteProtection === 'true'});
|
||||
}
|
||||
|
||||
onPaste = (error, files) => {
|
||||
EventEmitter.emit(PASTE_FILES, error, files, this.props.screenId);
|
||||
}
|
||||
|
||||
resetTextInput = () => {
|
||||
if (this.input.current) {
|
||||
this.input.current.setNativeProps({
|
||||
@@ -287,6 +300,7 @@ export default class PostInput extends PureComponent {
|
||||
<PasteableTextInput
|
||||
testID={testID}
|
||||
ref={this.input}
|
||||
disableCopyPaste={this.state.disableCopyAndPaste}
|
||||
style={{...style.input, maxHeight}}
|
||||
onChangeText={this.handleTextChange}
|
||||
onSelectionChange={this.handlePostDraftSelectionChanged}
|
||||
@@ -297,6 +311,7 @@ export default class PostInput extends PureComponent {
|
||||
underlineColorAndroid='transparent'
|
||||
keyboardType={this.state.keyboardType}
|
||||
onEndEditing={this.handleEndEditing}
|
||||
onPaste={this.onPaste}
|
||||
disableFullscreenUI={true}
|
||||
textContentType='none'
|
||||
autoCompleteType='off'
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
exports[`CameraButton should match snapshot 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
exports[`FileQuickAction should match snapshot 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
exports[`ImageQuickAction should match snapshot 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
|
||||
@@ -18,7 +18,7 @@ exports[`UploadItem downloadAndUploadFile should match, full snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -68,7 +68,7 @@ exports[`UploadItem downloadAndUploadFile should match, full snapshot 1`] = `
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<UploadRemove
|
||||
channelId="channel-id"
|
||||
|
||||
@@ -17,6 +17,7 @@ describe('Uploads', () => {
|
||||
handleRemoveLastFile: jest.fn(),
|
||||
initUploadFiles: jest.fn(),
|
||||
maxFileSize: 100,
|
||||
maxFileCount: 10,
|
||||
screenId: 'Channel',
|
||||
theme: Preferences.THEMES.denim,
|
||||
};
|
||||
|
||||
@@ -55,7 +55,6 @@ describe('MoreMessagesButton', () => {
|
||||
|
||||
describe('lifecycle methods', () => {
|
||||
AppState.addEventListener = jest.fn();
|
||||
AppState.removeEventListener = jest.fn();
|
||||
|
||||
test('componentDidMount should register app state listener, indicator visibility listener, viewable items listener, and scroll end index listener', () => {
|
||||
EventEmitter.on = jest.fn();
|
||||
@@ -94,7 +93,6 @@ describe('MoreMessagesButton', () => {
|
||||
instance.removeScrollEndIndexListener = jest.fn();
|
||||
|
||||
instance.componentWillUnmount();
|
||||
expect(AppState.removeEventListener).toHaveBeenCalledWith('change', instance.onAppStateChange);
|
||||
expect(EventEmitter.off).toHaveBeenCalledWith(ViewTypes.INDICATOR_BAR_VISIBLE, instance.onIndicatorBarVisible);
|
||||
expect(instance.removeViewableItemsListener).toHaveBeenCalled();
|
||||
expect(instance.removeScrollEndIndexListener).toHaveBeenCalled();
|
||||
@@ -323,6 +321,8 @@ describe('MoreMessagesButton', () => {
|
||||
<MoreMessagesButton {...baseProps}/>,
|
||||
);
|
||||
const instance = wrapper.instance();
|
||||
const clearTimeout = jest.spyOn(global, 'clearTimeout');
|
||||
|
||||
wrapper.setProps({unreadCount: 10});
|
||||
instance.setState({moreText: '60+ new messages'});
|
||||
const autoCancelTimer = jest.fn();
|
||||
@@ -517,6 +517,8 @@ describe('MoreMessagesButton', () => {
|
||||
<MoreMessagesButton {...baseProps}/>,
|
||||
);
|
||||
const instance = wrapper.instance();
|
||||
const setTimeout = jest.spyOn(global, 'setTimeout');
|
||||
|
||||
instance.componentDidUpdate = jest.fn();
|
||||
instance.canceled = false;
|
||||
instance.hide = jest.fn();
|
||||
@@ -539,6 +541,8 @@ describe('MoreMessagesButton', () => {
|
||||
<MoreMessagesButton {...baseProps}/>,
|
||||
);
|
||||
const instance = wrapper.instance();
|
||||
const setTimeout = jest.spyOn(global, 'setTimeout');
|
||||
|
||||
instance.componentDidUpdate = jest.fn();
|
||||
instance.canceled = false;
|
||||
instance.hide = jest.fn();
|
||||
@@ -564,7 +568,9 @@ describe('MoreMessagesButton', () => {
|
||||
<MoreMessagesButton {...baseProps}/>,
|
||||
);
|
||||
const instance = wrapper.instance();
|
||||
const clearTimeout = jest.spyOn(global, 'clearTimeout');
|
||||
const autoCancelTimer = jest.fn();
|
||||
|
||||
instance.autoCancelTimer = autoCancelTimer;
|
||||
instance.canceled = true;
|
||||
instance.disableViewableItems = true;
|
||||
@@ -621,6 +627,7 @@ describe('MoreMessagesButton', () => {
|
||||
|
||||
it('should return early when newMessageLineIndex <= 0', () => {
|
||||
const viewableItems = [{index: 0}, {index: 1}];
|
||||
const clearTimeout = jest.spyOn(global, 'clearTimeout');
|
||||
|
||||
wrapper.setProps({newMessageLineIndex: 0});
|
||||
instance.onViewableItemsChanged(viewableItems);
|
||||
@@ -633,8 +640,9 @@ describe('MoreMessagesButton', () => {
|
||||
|
||||
it('should return early when viewableItems length is 0', () => {
|
||||
const viewableItems = [];
|
||||
wrapper.setProps({newMessageLineIndex: 1, unreadCount: 10});
|
||||
const clearTimeout = jest.spyOn(global, 'clearTimeout');
|
||||
|
||||
wrapper.setProps({newMessageLineIndex: 1, unreadCount: 10});
|
||||
instance.onViewableItemsChanged(viewableItems);
|
||||
expect(clearTimeout).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -643,6 +651,7 @@ describe('MoreMessagesButton', () => {
|
||||
const viewableItems = [{index: 0}];
|
||||
wrapper.setProps({newMessageLineIndex: 1, unreadCount: 10});
|
||||
instance.disableViewableItems = true;
|
||||
const clearTimeout = jest.spyOn(global, 'clearTimeout');
|
||||
|
||||
instance.onViewableItemsChanged(viewableItems);
|
||||
expect(clearTimeout).not.toHaveBeenCalled();
|
||||
@@ -685,6 +694,7 @@ describe('MoreMessagesButton', () => {
|
||||
instance.disableViewableItems = false;
|
||||
instance.autoCancelTimer = null;
|
||||
instance.cancel = jest.fn();
|
||||
const setTimeout = jest.spyOn(global, 'setTimeout');
|
||||
|
||||
instance.onViewableItemsChanged(viewableItems);
|
||||
jest.runOnlyPendingTimers();
|
||||
@@ -701,6 +711,7 @@ describe('MoreMessagesButton', () => {
|
||||
instance.disableViewableItems = false;
|
||||
instance.autoCancelTimer = null;
|
||||
instance.cancel = jest.fn();
|
||||
const setTimeout = jest.spyOn(global, 'setTimeout');
|
||||
|
||||
instance.onViewableItemsChanged(viewableItems);
|
||||
jest.runOnlyPendingTimers();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import {intlShape} from 'react-intl';
|
||||
import {ActivityIndicator, Animated, AppState, AppStateStatus, Text, View, ViewToken} from 'react-native';
|
||||
import {ActivityIndicator, Animated, AppState, AppStateStatus, NativeEventSubscription, Text, View, ViewToken} from 'react-native';
|
||||
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import TouchableWithFeedback from '@components/touchable_with_feedback';
|
||||
@@ -64,6 +64,7 @@ export default class MoreMessageButton extends React.PureComponent<MoreMessagesB
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
appStateListener: NativeEventSubscription | undefined;
|
||||
autoCancelTimer: undefined | null | NodeJS.Timeout;
|
||||
buttonVisible = false;
|
||||
canceled = false;
|
||||
@@ -78,14 +79,14 @@ export default class MoreMessageButton extends React.PureComponent<MoreMessagesB
|
||||
viewableItems: ViewToken[] = [];
|
||||
|
||||
componentDidMount() {
|
||||
AppState.addEventListener('change', this.onAppStateChange);
|
||||
this.appStateListener = AppState.addEventListener('change', this.onAppStateChange);
|
||||
EventEmitter.on(ViewTypes.INDICATOR_BAR_VISIBLE, this.onIndicatorBarVisible);
|
||||
this.removeViewableItemsListener = this.props.registerViewableItemsListener(this.onViewableItemsChanged);
|
||||
this.removeScrollEndIndexListener = this.props.registerScrollEndIndexListener(this.onScrollEndIndex);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
AppState.removeEventListener('change', this.onAppStateChange);
|
||||
this.appStateListener?.remove();
|
||||
EventEmitter.off(ViewTypes.INDICATOR_BAR_VISIBLE, this.onIndicatorBarVisible);
|
||||
if (this.removeViewableItemsListener) {
|
||||
this.removeViewableItemsListener();
|
||||
|
||||
@@ -178,6 +178,8 @@ const Body = ({
|
||||
{body}
|
||||
{post.failed &&
|
||||
<Failed
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
post={post}
|
||||
theme={theme}
|
||||
/>
|
||||
|
||||
@@ -2,20 +2,21 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useCallback} from 'react';
|
||||
import {StyleSheet} from 'react-native';
|
||||
import {intlShape, injectIntl} from 'react-intl';
|
||||
import {Keyboard, StyleSheet} from 'react-native';
|
||||
|
||||
import {showModalOverCurrentContext} from '@actions/navigation';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import TouchableWithFeedback from '@components/touchable_with_feedback';
|
||||
import NavigationTypes from '@constants/navigation';
|
||||
import EventEmitter from '@mm-redux/utils/event_emitter';
|
||||
import {t} from '@utils/i18n';
|
||||
|
||||
import type {Post} from '@mm-redux/types/posts';
|
||||
import type {Theme} from '@mm-redux/types/theme';
|
||||
|
||||
type FailedProps = {
|
||||
createPost: (post: Post) => void;
|
||||
intl: typeof intlShape;
|
||||
post: Post;
|
||||
removePost: (post: Post) => void;
|
||||
theme: Theme;
|
||||
@@ -28,38 +29,39 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
const Failed = ({createPost, post, removePost, theme}: FailedProps) => {
|
||||
const Failed = ({createPost, intl, post, removePost, theme}: FailedProps) => {
|
||||
const onPress = useCallback(() => {
|
||||
const screen = 'OptionsModal';
|
||||
const passProps = {
|
||||
title: {
|
||||
id: t('mobile.post.failed_title'),
|
||||
title: intl.formatMessage({
|
||||
id: 'mobile.post.failed_title',
|
||||
defaultMessage: 'Unable to send your message:',
|
||||
},
|
||||
}),
|
||||
items: [{
|
||||
action: () => {
|
||||
EventEmitter.emit(NavigationTypes.NAVIGATION_CLOSE_MODAL);
|
||||
createPost(post);
|
||||
},
|
||||
text: {
|
||||
id: t('mobile.post.failed_retry'),
|
||||
text: intl.formatMessage({
|
||||
id: 'mobile.post.failed_retry',
|
||||
defaultMessage: 'Try Again',
|
||||
},
|
||||
}),
|
||||
}, {
|
||||
action: () => {
|
||||
EventEmitter.emit(NavigationTypes.NAVIGATION_CLOSE_MODAL);
|
||||
removePost(post);
|
||||
},
|
||||
text: {
|
||||
id: t('mobile.post.failed_delete'),
|
||||
text: intl.formatMessage({
|
||||
id: 'mobile.post.failed_delete',
|
||||
defaultMessage: 'Delete Message',
|
||||
},
|
||||
}),
|
||||
textStyle: {
|
||||
color: '#CC3239',
|
||||
},
|
||||
}],
|
||||
};
|
||||
|
||||
Keyboard.dismiss();
|
||||
showModalOverCurrentContext(screen, passProps);
|
||||
}, []);
|
||||
|
||||
@@ -77,5 +79,4 @@ const Failed = ({createPost, post, removePost, theme}: FailedProps) => {
|
||||
</TouchableWithFeedback>
|
||||
);
|
||||
};
|
||||
|
||||
export default Failed;
|
||||
export default injectIntl(Failed);
|
||||
|
||||
@@ -82,14 +82,14 @@ export default class DrawerLayout extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
Dimensions.addEventListener('change', this.handleDimensionsChange);
|
||||
this.dimensionsListener = Dimensions.addEventListener('change', this.handleDimensionsChange);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.openValue) {
|
||||
this.openValue.removeListener(this.handleOpenValueChanged);
|
||||
}
|
||||
Dimensions.removeEventListener('change', this.handleDimensionsChange);
|
||||
this.dimensionsListener?.remove();
|
||||
}
|
||||
|
||||
handleDimensionsChange = ({window}) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ChannelItem should match snapshot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -108,11 +108,11 @@ exports[`ChannelItem should match snapshot 1`] = `
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`ChannelItem should match snapshot for current user i.e currentUser (you) 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -228,11 +228,11 @@ exports[`ChannelItem should match snapshot for current user i.e currentUser (you
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`ChannelItem should match snapshot for current user i.e currentUser (you) when isSearchResult 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -348,11 +348,11 @@ exports[`ChannelItem should match snapshot for current user i.e currentUser (you
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`ChannelItem should match snapshot for deactivated user and is currentChannel 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -468,11 +468,11 @@ exports[`ChannelItem should match snapshot for deactivated user and is currentCh
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`ChannelItem should match snapshot for deactivated user and is searchResult 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -579,11 +579,11 @@ exports[`ChannelItem should match snapshot for deactivated user and is searchRes
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`ChannelItem should match snapshot for deactivated user and not searchResults or currentChannel 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -690,11 +690,11 @@ exports[`ChannelItem should match snapshot for deactivated user and not searchRe
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`ChannelItem should match snapshot for isManualUnread 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -801,7 +801,7 @@ exports[`ChannelItem should match snapshot for isManualUnread 1`] = `
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`ChannelItem should match snapshot for no displayName 1`] = `null`;
|
||||
@@ -809,7 +809,7 @@ exports[`ChannelItem should match snapshot for no displayName 1`] = `null`;
|
||||
exports[`ChannelItem should match snapshot for showUnreadForMsgs 1`] = `null`;
|
||||
|
||||
exports[`ChannelItem should match snapshot with custom status emoji 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -936,11 +936,11 @@ exports[`ChannelItem should match snapshot with custom status emoji 1`] = `
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`ChannelItem should match snapshot with draft 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -1047,11 +1047,11 @@ exports[`ChannelItem should match snapshot with draft 1`] = `
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
exports[`ChannelItem should match snapshot with mentions and muted 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -1194,5 +1194,5 @@ exports[`ChannelItem should match snapshot with mentions and muted 1`] = `
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
@@ -10,32 +10,23 @@ exports[`ChannelsList List should match snapshot 1`] = `
|
||||
"paddingBottom": 44,
|
||||
}
|
||||
}
|
||||
data={Array []}
|
||||
disableVirtualization={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
keyboardDismissMode="interactive"
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={10}
|
||||
onEndReachedThreshold={2}
|
||||
onScrollBeginDrag={[Function]}
|
||||
onViewableItemsChanged={[Function]}
|
||||
removeClippedSubviews={false}
|
||||
renderItem={[Function]}
|
||||
renderSectionHeader={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
sections={Array []}
|
||||
stickySectionHeadersEnabled={true}
|
||||
testID="main.sidebar.channels_list.list"
|
||||
updateCellsBatchingPeriod={50}
|
||||
viewabilityConfig={
|
||||
Object {
|
||||
"itemVisiblePercentThreshold": 100,
|
||||
"waitForInteraction": true,
|
||||
}
|
||||
}
|
||||
windowSize={21}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
@@ -51,32 +42,23 @@ exports[`ChannelsList List should match snapshot with collapsed threads enabled
|
||||
"paddingBottom": 44,
|
||||
}
|
||||
}
|
||||
data={Array []}
|
||||
disableVirtualization={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
keyboardDismissMode="interactive"
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={10}
|
||||
onEndReachedThreshold={2}
|
||||
onScrollBeginDrag={[Function]}
|
||||
onViewableItemsChanged={[Function]}
|
||||
removeClippedSubviews={false}
|
||||
renderItem={[Function]}
|
||||
renderSectionHeader={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
sections={Array []}
|
||||
stickySectionHeadersEnabled={true}
|
||||
testID="main.sidebar.channels_list.list"
|
||||
updateCellsBatchingPeriod={50}
|
||||
viewabilityConfig={
|
||||
Object {
|
||||
"itemVisiblePercentThreshold": 100,
|
||||
"waitForInteraction": true,
|
||||
}
|
||||
}
|
||||
windowSize={21}
|
||||
/>
|
||||
<UnreadIndicatorIOS
|
||||
onPress={[Function]}
|
||||
@@ -132,32 +114,23 @@ exports[`ChannelsList List should match snapshot with unreads not on top 1`] = `
|
||||
"paddingBottom": 44,
|
||||
}
|
||||
}
|
||||
data={Array []}
|
||||
disableVirtualization={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
keyboardDismissMode="interactive"
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={10}
|
||||
onEndReachedThreshold={2}
|
||||
onScrollBeginDrag={[Function]}
|
||||
onViewableItemsChanged={[Function]}
|
||||
removeClippedSubviews={false}
|
||||
renderItem={[Function]}
|
||||
renderSectionHeader={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
sections={Array []}
|
||||
stickySectionHeadersEnabled={true}
|
||||
testID="main.sidebar.channels_list.list"
|
||||
updateCellsBatchingPeriod={50}
|
||||
viewabilityConfig={
|
||||
Object {
|
||||
"itemVisiblePercentThreshold": 100,
|
||||
"waitForInteraction": true,
|
||||
}
|
||||
}
|
||||
windowSize={21}
|
||||
/>
|
||||
<UnreadIndicatorIOS
|
||||
onPress={[Function]}
|
||||
|
||||
@@ -113,10 +113,9 @@ export default class List extends PureComponent {
|
||||
this.props.orderedChannelIds !== orderedChannelIds) {
|
||||
this.setSections(this.buildSections(this.props));
|
||||
}
|
||||
} else if (
|
||||
} else if ( // Rebuild sections only if categories or unreads have changed
|
||||
!isEqual(this.props.categories, categories) ||
|
||||
this.props.unreadChannelIds !== unreadChannelIds) {
|
||||
// Rebuild sections only if categories or unreads have changed
|
||||
!isEqual(this.props.unreadChannelIds, unreadChannelIds)) {
|
||||
this.setCategorySections(this.buildCategorySections());
|
||||
}
|
||||
|
||||
@@ -213,7 +212,7 @@ export default class List extends PureComponent {
|
||||
const moreChannelsText = formatMessage({id: 'more_channels.title', defaultMessage: 'Browse for a Channel'});
|
||||
const newChannelText = formatMessage({id: 'mobile.create_channel', defaultMessage: 'Create a new Channel'});
|
||||
const newDirectChannelText = formatMessage({id: 'mobile.more_dms.title', defaultMessage: 'Add a Conversation'});
|
||||
const cancelText = formatMessage({id: 'mobile.post.cancel', defaultMessage: 'Cancel'});
|
||||
|
||||
const options = [];
|
||||
const actions = [];
|
||||
|
||||
@@ -229,20 +228,14 @@ export default class List extends PureComponent {
|
||||
|
||||
actions.push(this.goToDirectMessages);
|
||||
options.push({text: newDirectChannelText, icon: 'account-plus-outline'});
|
||||
options.push(cancelText);
|
||||
|
||||
const cancelButtonIndex = options.length - 1;
|
||||
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
anchor: this.combinedActionsRef?.current ? findNodeHandle(this.combinedActionsRef.current) : null,
|
||||
options,
|
||||
title: 'Add Channels',
|
||||
subtitle: `To the ${category.display_name} category`,
|
||||
cancelButtonIndex,
|
||||
}, (value) => {
|
||||
if (value !== cancelButtonIndex) {
|
||||
actions[value]();
|
||||
}
|
||||
actions[value]();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -472,6 +465,9 @@ export default class List extends PureComponent {
|
||||
// Add the rest
|
||||
if (this.props.categories) {
|
||||
this.props.categories.reduce((prev, cat) => {
|
||||
if (cat.type === 'favorites' && !cat.channel_ids.length) {
|
||||
return prev;
|
||||
}
|
||||
prev.push({
|
||||
name: cat.display_name,
|
||||
action: cat.type === 'direct_messages' ? this.goToDirectMessages : () => this.showCreateChannelOptions(cat),
|
||||
@@ -557,7 +553,6 @@ export default class List extends PureComponent {
|
||||
ref={this.setListRef}
|
||||
sections={showLegacySidebar ? sections : categorySections}
|
||||
contentContainerStyle={{paddingBottom}}
|
||||
removeClippedSubviews={Platform.OS === 'android'}
|
||||
renderItem={showLegacySidebar ? this.renderItem : this.renderCategoryItem}
|
||||
renderSectionHeader={showLegacySidebar ? this.renderSectionHeader : this.renderCategoryHeader}
|
||||
keyboardShouldPersistTaps={'always'}
|
||||
|
||||
@@ -4,7 +4,7 @@ exports[`SwitchTeamsButton should match snapshot 1`] = `
|
||||
<View
|
||||
testID="main.sidebar.channels_list.switch_teams.button"
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(25,42,77,0.5)"
|
||||
>
|
||||
@@ -59,7 +59,7 @@ exports[`SwitchTeamsButton should match snapshot 1`] = `
|
||||
testID="main.sidebar.channels_list.switch_teams.button.team_icon"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
<Badge
|
||||
containerStyle={
|
||||
Object {
|
||||
|
||||
@@ -56,7 +56,7 @@ export default class MainSidebarBase extends Component {
|
||||
this.props.actions.getTeams();
|
||||
EventEmitter.on(NavigationTypes.CLOSE_MAIN_SIDEBAR, this.closeMainSidebar);
|
||||
EventEmitter.on(WebsocketEvents.CHANNEL_UPDATED, this.handleUpdateTitle);
|
||||
Dimensions.addEventListener('change', this.handleDimensions);
|
||||
this.dimensionsListener = Dimensions.addEventListener('change', this.handleDimensions);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
@@ -91,7 +91,7 @@ export default class MainSidebarBase extends Component {
|
||||
this.mounted = false;
|
||||
EventEmitter.off(NavigationTypes.CLOSE_MAIN_SIDEBAR, this.closeMainSidebar);
|
||||
EventEmitter.off(WebsocketEvents.CHANNEL_UPDATED, this.handleUpdateTitle);
|
||||
Dimensions.removeEventListener('change', this.handleDimensions);
|
||||
this.dimensionsListener?.remove();
|
||||
}
|
||||
|
||||
drawerSwiperRef = (ref) => {
|
||||
|
||||
@@ -9,7 +9,7 @@ exports[`TeamsListItem should match snapshot 1`] = `
|
||||
}
|
||||
testID="main.sidebar.teams_list.flat_list.teams_list_item"
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -110,6 +110,6 @@ exports[`TeamsListItem should match snapshot 1`] = `
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DrawerItem should match snapshot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[MockFunction]}
|
||||
testID="test-id"
|
||||
>
|
||||
@@ -89,11 +89,11 @@ exports[`DrawerItem should match snapshot 1`] = `
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
exports[`DrawerItem should match snapshot without separator and centered false 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[MockFunction]}
|
||||
testID="test-id"
|
||||
>
|
||||
@@ -170,5 +170,5 @@ exports[`DrawerItem should match snapshot without separator and centered false 1
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
@@ -36,13 +36,13 @@ export default class SettingsDrawer extends SettingsSidebarBase {
|
||||
super.componentDidMount();
|
||||
|
||||
this.handleDimensions({window: Dimensions.get('window')});
|
||||
Dimensions.addEventListener('change', this.handleDimensions);
|
||||
this.dimensionsListener = Dimensions.addEventListener('change', this.handleDimensions);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
|
||||
Dimensions.removeEventListener('change', this.handleDimensions);
|
||||
this.dimensionsListener?.remove();
|
||||
}
|
||||
|
||||
confirmReset = (status) => {
|
||||
|
||||
@@ -44,7 +44,7 @@ exports[`components/widgets/settings/RadioSetting should match snapshot when err
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -81,8 +81,8 @@ exports[`components/widgets/settings/RadioSetting should match snapshot when err
|
||||
}
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -119,8 +119,8 @@ exports[`components/widgets/settings/RadioSetting should match snapshot when err
|
||||
}
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -156,7 +156,7 @@ exports[`components/widgets/settings/RadioSetting should match snapshot when err
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View>
|
||||
<Text
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
/* eslint-disable max-lines */
|
||||
import {isEqual} from 'lodash';
|
||||
|
||||
import {Client4} from '@client/rest';
|
||||
import {getUser} from '@components/autocomplete/slash_suggestion/app_command_parser/app_command_parser_dependencies';
|
||||
@@ -16,7 +15,7 @@ import {ActionFunc, batchActions, DispatchFunc, GetStateFunc} from '@mm-redux/ty
|
||||
import {CategorySorting, ChannelCategory, OrderedChannelCategories} from '@mm-redux/types/channel_categories';
|
||||
import {Channel} from '@mm-redux/types/channels';
|
||||
import {UserProfile} from '@mm-redux/types/users';
|
||||
import {$ID, IDMappedObjects, RelationOneToMany} from '@mm-redux/types/utilities';
|
||||
import {$ID, RelationOneToMany} from '@mm-redux/types/utilities';
|
||||
import {insertMultipleWithoutDuplicates, insertWithoutDuplicates, removeItem} from '@mm-redux/utils/array_utils';
|
||||
import {getUserIdFromChannelName} from '@mm-redux/utils/channel_utils';
|
||||
|
||||
@@ -32,10 +31,23 @@ export function collapseCategory(categoryId: string) {
|
||||
return setCategoryCollapsed(categoryId, true);
|
||||
}
|
||||
|
||||
export function setCategoryCollapsed(categoryId: string, collapsed: boolean) {
|
||||
return patchCategory(categoryId, {
|
||||
collapsed,
|
||||
});
|
||||
export function setCategoryCollapsed(categoryId: string, collapsed: boolean): ActionFunc {
|
||||
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
|
||||
const state = getState();
|
||||
|
||||
const category = getCategory(state, categoryId);
|
||||
const patchedCategory = {
|
||||
...category,
|
||||
collapsed,
|
||||
};
|
||||
|
||||
dispatch({
|
||||
type: ChannelCategoryTypes.RECEIVED_CATEGORY,
|
||||
data: patchedCategory,
|
||||
});
|
||||
|
||||
return {data: patchedCategory};
|
||||
};
|
||||
}
|
||||
|
||||
export function setCategorySorting(categoryId: string, sorting: CategorySorting) {
|
||||
@@ -142,20 +154,11 @@ export function fetchMyCategories(teamId: string) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that we don't dispatch an unnecessary update after fetching
|
||||
*/
|
||||
const categoriesInState = getState().entities.channelCategories.byId;
|
||||
const mappedCats = data.order.reduce((prev, categoryId) => {
|
||||
return {
|
||||
...prev,
|
||||
[categoryId]: data.categories.find((category) => category.id === categoryId),
|
||||
};
|
||||
}, {} as IDMappedObjects<ChannelCategory>);
|
||||
|
||||
if (isEqual(mappedCats, categoriesInState)) {
|
||||
return {data: false};
|
||||
}
|
||||
// Remove collapse state from server data
|
||||
data.categories = data.categories.map((cat) => {
|
||||
delete cat.collapsed;
|
||||
return cat;
|
||||
});
|
||||
|
||||
return dispatch(batchActions([
|
||||
{
|
||||
@@ -199,7 +202,7 @@ export function addChannelToInitialCategory(channel: Channel, setOnServer = fals
|
||||
// Get the user ids in the channel
|
||||
const allUsersInChannels: RelationOneToMany<Channel, UserProfile> = getUserIdsInChannels(state);
|
||||
const allUsersInGMChannel = Array.from(allUsersInChannels[channel.id] || []);
|
||||
const usersInGMChannel: Array<string> = allUsersInGMChannel.filter((u: string) => u !== currentUserId);
|
||||
const usersInGMChannel: string[] = allUsersInGMChannel.filter((u: string) => u !== currentUserId);
|
||||
|
||||
// Filter and see if there are any missing in our state
|
||||
const missingUsers = usersInGMChannel.filter((id) => {
|
||||
|
||||
@@ -25,7 +25,7 @@ export type ChannelCategory = {
|
||||
sorting: CategorySorting;
|
||||
channel_ids: Array<$ID<Channel>>;
|
||||
muted: boolean;
|
||||
collapsed: boolean;
|
||||
collapsed?: boolean;
|
||||
};
|
||||
|
||||
export type OrderedChannelCategories = {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SettingsSidebarDrawerButton should match, full snapshot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
accessibilityHint="Opens the more options right hand sidebar"
|
||||
accessibilityLabel="More Options"
|
||||
accessibilityRole="button"
|
||||
@@ -31,5 +31,5 @@ exports[`SettingsSidebarDrawerButton should match, full snapshot 1`] = `
|
||||
size={25}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
@@ -111,11 +111,11 @@ const ChannelNavBar = (props) => {
|
||||
useEffect(() => {
|
||||
handleDimensions();
|
||||
handlePermanentSidebar();
|
||||
Dimensions.addEventListener('change', handleDimensions);
|
||||
const dimensionsListener = Dimensions.addEventListener('change', handleDimensions);
|
||||
EventEmitter.on(DeviceTypes.PERMANENT_SIDEBAR_SETTINGS, handlePermanentSidebar);
|
||||
|
||||
return () => {
|
||||
Dimensions.removeEventListener('change', handleDimensions);
|
||||
dimensionsListener.remove();
|
||||
EventEmitter.off(DeviceTypes.PERMANENT_SIDEBAR_SETTINGS, handlePermanentSidebar);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -8,7 +8,7 @@ exports[`ChannelSearchButton should match, full snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
accessibilityHint="Opens the channel search modal"
|
||||
accessibilityLabel="Search"
|
||||
accessibilityRole="button"
|
||||
@@ -43,6 +43,6 @@ exports[`ChannelSearchButton should match, full snapshot 1`] = `
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ChannelTitle should match snapshot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
@@ -54,11 +54,11 @@ exports[`ChannelTitle should match snapshot 1`] = `
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
exports[`ChannelTitle should match snapshot when is DM and has guests and the teammate is the guest (when can show subtitles) 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
@@ -150,11 +150,11 @@ exports[`ChannelTitle should match snapshot when is DM and has guests and the te
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
exports[`ChannelTitle should match snapshot when is DM and has guests but the teammate is not the guest (when can show subtitles) 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
@@ -221,11 +221,11 @@ exports[`ChannelTitle should match snapshot when is DM and has guests but the te
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
exports[`ChannelTitle should match snapshot when isChannelShared is true 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
@@ -297,11 +297,11 @@ exports[`ChannelTitle should match snapshot when isChannelShared is true 1`] = `
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
exports[`ChannelTitle should match snapshot when isSelfDMChannel is true 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
@@ -362,11 +362,11 @@ exports[`ChannelTitle should match snapshot when isSelfDMChannel is true 1`] = `
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
exports[`ChannelTitle should match snapshot with custom status emoji 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
@@ -433,5 +433,5 @@ exports[`ChannelTitle should match snapshot with custom status emoji 1`] = `
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`MainSidebarDrawerButton should match, full snapshot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
accessibilityHint="Opens the channels and teams drawer"
|
||||
accessibilityLabel="Channels and teams"
|
||||
accessibilityRole="button"
|
||||
@@ -37,11 +37,11 @@ exports[`MainSidebarDrawerButton should match, full snapshot 1`] = `
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
exports[`MainSidebarDrawerButton should match, full snapshot 2`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
accessibilityHint="Opens the channels and teams drawer"
|
||||
accessibilityLabel="Channels and teams"
|
||||
accessibilityRole="button"
|
||||
@@ -107,5 +107,5 @@ exports[`MainSidebarDrawerButton should match, full snapshot 2`] = `
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
@@ -90,7 +90,7 @@ exports[`channel_info_header should match snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -125,7 +125,7 @@ exports[`channel_info_header should match snapshot 1`] = `
|
||||
Purpose string
|
||||
</Text>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
@@ -134,7 +134,7 @@ exports[`channel_info_header should match snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -271,7 +271,7 @@ exports[`channel_info_header should match snapshot 1`] = `
|
||||
value="Header string"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<Text
|
||||
style={
|
||||
@@ -424,7 +424,7 @@ exports[`channel_info_header should match snapshot when DM and hasGuests and is
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -459,7 +459,7 @@ exports[`channel_info_header should match snapshot when DM and hasGuests and is
|
||||
Purpose string
|
||||
</Text>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
@@ -468,7 +468,7 @@ exports[`channel_info_header should match snapshot when DM and hasGuests and is
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -605,7 +605,7 @@ exports[`channel_info_header should match snapshot when DM and hasGuests and is
|
||||
value="Header string"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<Text
|
||||
style={
|
||||
@@ -730,7 +730,7 @@ exports[`channel_info_header should match snapshot when DM and hasGuests but its
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -765,7 +765,7 @@ exports[`channel_info_header should match snapshot when DM and hasGuests but its
|
||||
Purpose string
|
||||
</Text>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
@@ -774,7 +774,7 @@ exports[`channel_info_header should match snapshot when DM and hasGuests but its
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -911,7 +911,7 @@ exports[`channel_info_header should match snapshot when DM and hasGuests but its
|
||||
value="Header string"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<Text
|
||||
style={
|
||||
@@ -1064,7 +1064,7 @@ exports[`channel_info_header should match snapshot when GM and hasGuests 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -1099,7 +1099,7 @@ exports[`channel_info_header should match snapshot when GM and hasGuests 1`] = `
|
||||
Purpose string
|
||||
</Text>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
@@ -1108,7 +1108,7 @@ exports[`channel_info_header should match snapshot when GM and hasGuests 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -1245,7 +1245,7 @@ exports[`channel_info_header should match snapshot when GM and hasGuests 1`] = `
|
||||
value="Header string"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<Text
|
||||
style={
|
||||
@@ -1370,7 +1370,7 @@ exports[`channel_info_header should match snapshot when is group constrained 1`]
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -1405,7 +1405,7 @@ exports[`channel_info_header should match snapshot when is group constrained 1`]
|
||||
Purpose string
|
||||
</Text>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
@@ -1414,7 +1414,7 @@ exports[`channel_info_header should match snapshot when is group constrained 1`]
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -1551,7 +1551,7 @@ exports[`channel_info_header should match snapshot when is group constrained 1`]
|
||||
value="Header string"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<Text
|
||||
style={
|
||||
@@ -1725,7 +1725,7 @@ exports[`channel_info_header should match snapshot when public channel and hasGu
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -1760,7 +1760,7 @@ exports[`channel_info_header should match snapshot when public channel and hasGu
|
||||
Purpose string
|
||||
</Text>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
@@ -1769,7 +1769,7 @@ exports[`channel_info_header should match snapshot when public channel and hasGu
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -1906,7 +1906,7 @@ exports[`channel_info_header should match snapshot when public channel and hasGu
|
||||
value="Header string"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<Text
|
||||
style={
|
||||
@@ -2113,7 +2113,7 @@ exports[`channel_info_header should match snapshot with custom status enabled 1`
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -2148,7 +2148,7 @@ exports[`channel_info_header should match snapshot with custom status enabled 1`
|
||||
Purpose string
|
||||
</Text>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
@@ -2157,7 +2157,7 @@ exports[`channel_info_header should match snapshot with custom status enabled 1`
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -2294,7 +2294,7 @@ exports[`channel_info_header should match snapshot with custom status enabled 1`
|
||||
value="Header string"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<Text
|
||||
style={
|
||||
@@ -2540,7 +2540,7 @@ exports[`channel_info_header should match snapshot with custom status expiry 1`]
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -2575,7 +2575,7 @@ exports[`channel_info_header should match snapshot with custom status expiry 1`]
|
||||
Purpose string
|
||||
</Text>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
@@ -2584,7 +2584,7 @@ exports[`channel_info_header should match snapshot with custom status expiry 1`]
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onLongPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -2721,7 +2721,7 @@ exports[`channel_info_header should match snapshot with custom status expiry 1`]
|
||||
value="Header string"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<Text
|
||||
style={
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ChannelInfoRow should match snapshot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[MockFunction]}
|
||||
>
|
||||
<View
|
||||
@@ -64,5 +64,5 @@ exports[`ChannelInfoRow should match snapshot 1`] = `
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
@@ -101,7 +101,6 @@ export default class ChannelInfoHeader extends React.PureComponent {
|
||||
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options: [actionText, cancelText],
|
||||
cancelButtonIndex: 1,
|
||||
}, (value) => {
|
||||
if (value === 0) {
|
||||
this.handleCopy(text);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`screens/custom_status_suggestion should match snapshot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
testID="custom_status_suggestion.In a meeting"
|
||||
>
|
||||
@@ -91,11 +91,11 @@ exports[`screens/custom_status_suggestion should match snapshot 1`] = `
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
exports[`screens/custom_status_suggestion should match snapshot with separator and clear button 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
testID="custom_status_suggestion.In a meeting"
|
||||
>
|
||||
@@ -194,5 +194,5 @@ exports[`screens/custom_status_suggestion should match snapshot with separator a
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`screens/clear_after_menu_item should match snapshot 1`] = `
|
||||
<View>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
testID="clear_after.menu_item."
|
||||
>
|
||||
@@ -68,13 +68,13 @@ exports[`screens/clear_after_menu_item should match snapshot 1`] = `
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`screens/clear_after_menu_item should match snapshot with separator and selected check 1`] = `
|
||||
<View>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
testID="clear_after.menu_item."
|
||||
>
|
||||
@@ -168,6 +168,6 @@ exports[`screens/clear_after_menu_item should match snapshot with separator and
|
||||
}
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
`;
|
||||
|
||||
@@ -23,9 +23,10 @@ exports[`screens/date_time_selector should match snapshot 1`] = `
|
||||
>
|
||||
<View
|
||||
accessibilityRole="button"
|
||||
accessibilityState={Object {}}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
@@ -68,9 +69,10 @@ exports[`screens/date_time_selector should match snapshot 1`] = `
|
||||
</View>
|
||||
<View
|
||||
accessibilityRole="button"
|
||||
accessibilityState={Object {}}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
nativeID="animatedComponent"
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
|
||||
@@ -148,7 +148,6 @@ exports[`ForgotPassword should match snapshot 1`] = `
|
||||
}
|
||||
/>
|
||||
<TextInput
|
||||
allowFontScaling={true}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
blurOnSubmit={false}
|
||||
@@ -157,7 +156,6 @@ exports[`ForgotPassword should match snapshot 1`] = `
|
||||
onChangeText={[Function]}
|
||||
placeholder="Email"
|
||||
placeholderTextColor="rgba(0,0,0,0.5)"
|
||||
rejectResponderTermination={true}
|
||||
style={
|
||||
Object {
|
||||
"alignSelf": "stretch",
|
||||
@@ -271,7 +269,6 @@ exports[`ForgotPassword snapshot for error on failure of email regex 1`] = `
|
||||
}
|
||||
/>
|
||||
<TextInput
|
||||
allowFontScaling={true}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
blurOnSubmit={false}
|
||||
@@ -280,7 +277,6 @@ exports[`ForgotPassword snapshot for error on failure of email regex 1`] = `
|
||||
onChangeText={[Function]}
|
||||
placeholder="Email"
|
||||
placeholderTextColor="rgba(0,0,0,0.5)"
|
||||
rejectResponderTermination={true}
|
||||
style={
|
||||
Object {
|
||||
"alignSelf": "stretch",
|
||||
|
||||
@@ -63,13 +63,13 @@ export default class Login extends PureComponent {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
Dimensions.addEventListener('change', this.orientationDidChange);
|
||||
this.dimensionsListener = Dimensions.addEventListener('change', this.orientationDidChange);
|
||||
|
||||
this.setEmmUsernameIfAvailable();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Dimensions.removeEventListener('change', this.orientationDidChange);
|
||||
this.dimensionsListener?.remove();
|
||||
}
|
||||
|
||||
goToChannel = () => {
|
||||
|
||||
@@ -38,11 +38,11 @@ export default class LoginOptions extends PureComponent {
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
Dimensions.addEventListener('change', this.orientationDidChange);
|
||||
this.dimensionsListener = Dimensions.addEventListener('change', this.orientationDidChange);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Dimensions.removeEventListener('change', this.orientationDidChange);
|
||||
this.dimensionsListener?.remove();
|
||||
}
|
||||
|
||||
goToLogin = preventDoubleTap(async () => {
|
||||
|
||||
@@ -47,13 +47,13 @@ export default class Mfa extends PureComponent {
|
||||
|
||||
componentDidMount() {
|
||||
if (Platform.OS === 'android') {
|
||||
Keyboard.addListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
this.keyboardListener = Keyboard.addListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (Platform.OS === 'android') {
|
||||
Keyboard.removeListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
this.keyboardListener?.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -430,7 +430,6 @@ export default class MoreChannels extends PureComponent {
|
||||
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options,
|
||||
cancelButtonIndex: 3,
|
||||
title: titleText,
|
||||
}, (value) => {
|
||||
let typeOfChannels;
|
||||
|
||||
@@ -5,8 +5,10 @@ exports[`OptionModalList should match snapshot 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"bottom": 0,
|
||||
"height": "100%",
|
||||
"justifyContent": "flex-end",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
>
|
||||
@@ -27,7 +29,7 @@ exports[`OptionModalList should match snapshot 1`] = `
|
||||
"borderTopLeftRadius": 12,
|
||||
"borderTopRightRadius": 12,
|
||||
"paddingBottom": 25,
|
||||
"paddingVertical": 10,
|
||||
"paddingTop": 10,
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -66,7 +68,7 @@ exports[`OptionModalList should match snapshot 1`] = `
|
||||
</Text>
|
||||
</View>
|
||||
<View>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -107,10 +109,10 @@ exports[`OptionModalList should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -151,7 +153,7 @@ exports[`OptionModalList should match snapshot 1`] = `
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -92,7 +92,7 @@ export default class OptionsModal extends PureComponent {
|
||||
return (
|
||||
<TouchableWithoutFeedback onPress={this.handleCancel}>
|
||||
<View style={style.wrapper}>
|
||||
<AnimatedView style={{height: this.props.deviceHeight, left: 0, top: this.state.top, width: this.props.deviceWidth}}>
|
||||
<AnimatedView style={{top: this.state.top}}>
|
||||
<OptionsModalList
|
||||
items={items}
|
||||
onCancelPress={this.handleCancel}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, {PureComponent} from 'react';
|
||||
import {
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
@@ -157,16 +156,8 @@ const style = StyleSheet.create({
|
||||
backgroundColor: 'white',
|
||||
borderTopLeftRadius: 12,
|
||||
borderTopRightRadius: 12,
|
||||
paddingVertical: 10,
|
||||
...Platform.select({
|
||||
ios: {
|
||||
paddingBottom: 25,
|
||||
},
|
||||
android: {
|
||||
marginBottom: -10,
|
||||
},
|
||||
}),
|
||||
|
||||
paddingTop: 10,
|
||||
paddingBottom: 25,
|
||||
},
|
||||
optionIcon: {
|
||||
color: 'rgba(61, 60, 64, 0.64)',
|
||||
@@ -197,9 +188,11 @@ const style = StyleSheet.create({
|
||||
paddingBottom: 10,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
bottom: 0,
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
},
|
||||
wrapper: {
|
||||
maxWidth: 450,
|
||||
|
||||
@@ -50,7 +50,7 @@ exports[`Permalink should match snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -66,7 +66,7 @@ exports[`Permalink should match snapshot 1`] = `
|
||||
name="close"
|
||||
size={20}
|
||||
/>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ReactionHeaderItem should match snapshot 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Array [
|
||||
@@ -47,7 +47,7 @@ exports[`ReactionHeaderItem should match snapshot 1`] = `
|
||||
3
|
||||
</Text>
|
||||
</React.Fragment>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
||||
exports[`ReactionHeaderItem should match snapshot, renderContent 1`] = `
|
||||
|
||||
@@ -20,7 +20,7 @@ exports[`ReactionRow should match snapshot, renderContent 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
>
|
||||
<View
|
||||
@@ -38,7 +38,7 @@ exports[`ReactionRow should match snapshot, renderContent 1`] = `
|
||||
userId="user_id"
|
||||
/>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text
|
||||
ellipsizeMode="tail"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Search RecentItem should match snapshot and respond to events 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
>
|
||||
@@ -80,5 +80,5 @@ exports[`Search RecentItem should match snapshot and respond to events 1`] = `
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Search RecentItem should match snapshot and respond to events 1`] = `
|
||||
<ForwardRef
|
||||
<TouchableHighlight
|
||||
key="test"
|
||||
onPress={[Function]}
|
||||
underlayColor="rgba(40,66,123,0.5)"
|
||||
@@ -30,7 +30,7 @@ exports[`Search RecentItem should match snapshot and respond to events 1`] = `
|
||||
>
|
||||
test
|
||||
</Text>
|
||||
<ForwardRef
|
||||
<TouchableOpacity
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -47,7 +47,7 @@ exports[`Search RecentItem should match snapshot and respond to events 1`] = `
|
||||
name="close-circle-outline"
|
||||
size={20}
|
||||
/>
|
||||
</ForwardRef>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</ForwardRef>
|
||||
</TouchableHighlight>
|
||||
`;
|
||||
|
||||
@@ -86,15 +86,8 @@ exports[`Search should match snapshot 1`] = `
|
||||
>
|
||||
<SectionList
|
||||
ListFooterComponent={[Function]}
|
||||
data={Array []}
|
||||
disableVirtualization={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
keyboardDismissMode="interactive"
|
||||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={10}
|
||||
onEndReachedThreshold={2}
|
||||
onLayout={[Function]}
|
||||
onScroll={[Function]}
|
||||
onViewableItemsChanged={[Function]}
|
||||
@@ -158,8 +151,6 @@ exports[`Search should match snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
testID="search.results_list"
|
||||
updateCellsBatchingPeriod={50}
|
||||
windowSize={21}
|
||||
/>
|
||||
</RNCSafeAreaView>
|
||||
<Connect(Autocomplete)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user