MM-34811 Add plugin oauth support (#5395)

* Add plugin oauth support

* Fix types

* Switch go to screen by show modal

* Add content width metadata to show correctly the sites

* Remove unneeded metadata

* Fix tsc

* Fix lint

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
This commit is contained in:
Daniel Espino García 2021-09-27 18:17:56 +02:00 committed by GitHub
parent a2ed6ba3bd
commit 3668cb62d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 104 additions and 5 deletions

View file

@ -9,7 +9,7 @@ import {intlShape} from 'react-intl';
import {Alert, Text} from 'react-native';
import urlParse from 'url-parse';
import {dismissAllModals, popToRoot} from '@actions/navigation';
import {dismissAllModals, popToRoot, showModal} from '@actions/navigation';
import Config from '@assets/config';
import {DeepLinkTypes} from '@constants';
import {getCurrentServerUrl} from '@init/credentials';
@ -59,13 +59,20 @@ export default class MarkdownLink extends PureComponent {
const match = matchDeepLink(url, serverURL, siteURL);
if (match) {
if (match.type === DeepLinkTypes.CHANNEL) {
switch (match.type) {
case DeepLinkTypes.CHANNEL:
await handleSelectChannelByName(match.channelName, match.teamName, errorBadChannel, intl);
await dismissAllModals();
await popToRoot();
} else if (match.type === DeepLinkTypes.PERMALINK) {
break;
case DeepLinkTypes.PERMALINK: {
const teamName = match.teamName === PERMALINK_GENERIC_TEAM_NAME_REDIRECT ? currentTeamName : match.teamName;
showPermalink(intl, teamName, match.postId);
break;
}
case DeepLinkTypes.PLUGIN:
showModal('PluginInternal', match.id, {link: url});
break;
}
} else {
const onError = () => {

View file

@ -297,10 +297,10 @@ const PostList = ({
if (match) {
if (match.type === DeepLinkTypes.CHANNEL) {
handleSelectChannelByName(match.channelName!, match.teamName, errorBadChannel, intl);
handleSelectChannelByName(match.channelName!, match.teamName!, errorBadChannel, intl);
} else if (match.type === DeepLinkTypes.PERMALINK) {
const teamName = match.teamName === PERMALINK_GENERIC_TEAM_NAME_REDIRECT ? currentTeamName : match.teamName;
onPermalinkPress(match.postId!, teamName);
onPermalinkPress(match.postId!, teamName!);
}
} else {
badDeepLink(intl);

View file

@ -7,4 +7,5 @@ export default {
GROUPCHANNEL: 'groupchannel',
PERMALINK: 'permalink',
OTHER: 'other',
PLUGIN: 'plugin',
};

View file

@ -4,6 +4,7 @@
import {intlShape} from 'react-intl';
import {Alert} from 'react-native';
import {showModal} from '@actions/navigation';
import {handleSelectChannel, handleSelectChannelByName, loadChannelsByTeamName} from '@actions/views/channel';
import {makeDirectChannel} from '@actions/views/more_dms';
import {showPermalink} from '@actions/views/permalink';
@ -146,6 +147,9 @@ export function handleGotoLocation(href: string, intl: typeof intlShape): Action
dispatch(makeGroupMessageVisibleIfNecessary(match.id));
dispatch(handleSelectChannel(match.id));
break;
case DeepLinkTypes.PLUGIN:
showModal('PluginInternal', match.id, {link: url});
break;
}
} else {
const {formatMessage} = intl;

View file

@ -218,6 +218,9 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case 'UserProfile':
screen = require('@screens/user_profile').default;
break;
case 'PluginInternal':
screen = require('@screens/plugin').default;
break;
case 'SlideUp':
screen = require('@screens/slide_up').default;
break;

View file

@ -0,0 +1,79 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {SafeAreaView} from 'react-native-safe-area-context';
import {WebView} from 'react-native-webview';
import {shallowEqual, useSelector} from 'react-redux';
import StatusBar from '@components/status_bar';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import type {GlobalState} from '@mm-redux/types/store';
import type {Theme} from '@mm-redux/types/theme';
const HEADERS = {
'X-Mobile-App': 'mattermost',
};
interface PluginProps {
link: string;
}
function Plugin({link}: PluginProps) {
const [theme] = useSelector((state: GlobalState) => ([
getTheme(state),
]), shallowEqual);
const style = getStyleSheet(theme);
const renderWebView = () => {
const userAgent = 'Mozilla/5.0 (Linux; Android 10; Android SDK built for x86 Build/LMY48X) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/81.0.4044.117 Mobile Safari/608.2.11';
return (
<WebView
automaticallyAdjustContentInsets={false}
cacheEnabled={false}
javaScriptEnabled={true}
injectedJavaScript={'const meta = document.createElement(\'meta\'); meta.setAttribute(\'content\', \'width=device-width, initial-scale=1\'); meta.setAttribute(\'name\', \'viewport\'); document.getElementsByTagName(\'head\')[0].appendChild(meta); '}
onShouldStartLoadWithRequest={() => true}
source={{uri: link, headers: HEADERS}}
startInLoadingState={true}
userAgent={userAgent}
useSharedProcessPool={false}
/>
);
};
return (
<SafeAreaView
style={style.container}
testID='plugin.webview'
>
<StatusBar/>
{renderWebView()}
</SafeAreaView>
);
}
export default Plugin;
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
return {
container: {
flex: 1,
},
errorContainer: {
alignItems: 'center',
flex: 1,
marginTop: 40,
},
errorText: {
color: changeOpacity(theme.centerChannelColor, 0.4),
fontSize: 16,
fontWeight: '400',
lineHeight: 23,
paddingHorizontal: 30,
},
};
});

View file

@ -143,6 +143,11 @@ export function matchDeepLink(url, serverURL, siteURL) {
return {type: DeepLinkTypes.GROUPCHANNEL, teamName: match[1], id: match[2]};
}
match = new RegExp(linkRoot + '\\/plugins\\/([^\\/]+)\\/(\\S+)').exec(urlToMatch);
if (match) {
return {type: DeepLinkTypes.PLUGIN, id: match[1]};
}
return null;
}