Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Migrate mobile app modal component #19409

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import MobileAppModalGraphqlContainer from './mobile-app-modal-graphql/component';

import MobileAppModal from './component';

const MobileAppModalContainer = (props) => <MobileAppModal {...props} />;

export default withTracker(() => {})(MobileAppModalContainer);
withTracker(() => {})(MobileAppModalContainer);

export default MobileAppModalGraphqlContainer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import React, { useEffect, useState } from 'react';
import { Meteor } from 'meteor/meteor';
import { useReactiveVar } from '@apollo/client';
import { defineMessages, useIntl } from 'react-intl';
import useMeeting from '/imports/ui/core/hooks/useMeeting';
import Auth from '/imports/ui/services/auth';
import ModalSimple from '/imports/ui/components/common/modal/simple/component';
import Button from '/imports/ui/components/common/button/component';
import Styled from './styles';

const BBB_TABLET_APP_CONFIG = Meteor.settings.public.app.bbbTabletApp;

const intlMessages = defineMessages({
title: {
id: 'app.mobileAppModal.title',
description: 'App modal title',
},
description: {
id: 'app.mobileAppModal.description',
description: 'App modal description',
},
openStore: {
id: 'app.mobileAppModal.openStore',
defaultMessage: new Date().getFullYear().toString(),
description: 'Open Store button label',
},
openApp: {
id: 'app.mobileAppModal.openApp',
description: 'Open App button label',
},
obtainUrlMsg: {
id: 'app.mobileAppModal.obtainUrlMsg',
description: 'Obtain URL message',
},
obtainUrlErrorMsg: {
id: 'app.mobileAppModal.obtainUrlErrorMsg',
description: 'Obtain URL error message',
},
dismissLabel: {
id: 'app.mobileAppModal.dismissLabel',
description: 'Dismiss button label',
},
dismissDesc: {
id: 'app.mobileAppModal.dismissDesc',
description: 'adds descriptive context to dissmissLabel',
},
});

interface MobileAppModalGraphqlContainerProps {
isOpen: boolean,
onRequestClose: () => void,
priority: string,
}

interface MobileAppModalGraphqlProps extends MobileAppModalGraphqlContainerProps {
meetingName: string;
sessionToken: string;
}

const MobileAppModalGraphql: React.FC<MobileAppModalGraphqlProps> = (props) => {
const {
meetingName,
sessionToken,
isOpen,
onRequestClose,
priority,
} = props;
const [url, setUrl] = useState('');
const [urlMessage, setUrlMessage] = useState('');
const intl = useIntl();

useEffect(() => {
const url = `/bigbluebutton/api/getJoinUrl?sessionToken=${sessionToken}`;
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
};
setUrlMessage(intl.formatMessage(intlMessages.obtainUrlMsg));
fetch(url, options)
.then((response) => {
if (!response.ok) {
return Promise.reject();
}
return response.json();
})
.then((messages) => {
setUrl(messages.response.url);
setUrlMessage('');
})
.catch(() => {
setUrlMessage(intl.formatMessage(intlMessages.obtainUrlErrorMsg));
});
}, []);

return (
<ModalSimple
title={intl.formatMessage(intlMessages.title)}
dismiss={{
label: intl.formatMessage(intlMessages.dismissLabel),
description: intl.formatMessage(intlMessages.dismissDesc),
}}
{...{
isOpen,
onRequestClose,
priority,
}}
>
<Styled.Center>
{`${intl.formatMessage(intlMessages.description)}`}

<Styled.ButtonContainer>
<Button
color="primary"
disabled={url === ''}
label={intl.formatMessage(intlMessages.openApp)}
onClick={() => {
window.open(
`${
BBB_TABLET_APP_CONFIG.iosAppUrlScheme
}://${encodeURIComponent(meetingName)}/${encodeURIComponent(
url,
)}`,
'_blank',
);
}}
role="button"
size="lg"
/>
{urlMessage !== '' ? (
<Styled.UrlMessage>{urlMessage}</Styled.UrlMessage>
) : null}
</Styled.ButtonContainer>

{BBB_TABLET_APP_CONFIG.iosAppStoreUrl === '' ? null : (
<Styled.ButtonContainer>
<Button
color="default"
label={intl.formatMessage(intlMessages.openStore)}
onClick={() => window.open(`${BBB_TABLET_APP_CONFIG.iosAppStoreUrl}`, '_blank')}
role="button"
size="lg"
/>
</Styled.ButtonContainer>
)}
</Styled.Center>
</ModalSimple>
);
};

const MobileAppModalGraphqlContainer: React.FC<MobileAppModalGraphqlContainerProps> = ({
isOpen,
onRequestClose,
priority,
}) => {
/* eslint no-underscore-dangle: "off" */
// @ts-ignore Due to Meteor legacy reasons
const sessionToken = useReactiveVar(Auth._sessionToken) as string;
const { loading, data: currentMeeting } = useMeeting((m) => {
return {
name: m.name,
};
});

if (loading || !currentMeeting) {
return null;
}

return (
<MobileAppModalGraphql
meetingName={currentMeeting.name ?? ''}
sessionToken={sessionToken}
isOpen={isOpen}
onRequestClose={onRequestClose}
priority={priority}
/>
);
};

export default MobileAppModalGraphqlContainer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import styled from 'styled-components';

const Center = styled.div`
text-align: center;
padding-top: 1rem;
padding-bottom: 1rem;
`;

const ButtonContainer = styled.div`
margin-top: 1rem;
`;

const UrlMessage = styled.div`
font-style: italic;
font-size: 1.0rem;
`;

export default {
Center,
ButtonContainer,
UrlMessage,
};
18 changes: 14 additions & 4 deletions bigbluebutton-html5/imports/ui/services/auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Storage from '/imports/ui/services/storage/session';
import allowRedirectToLogoutURL from '/imports/ui/components/meeting-ended/service';
import { ValidationStates } from '/imports/api/auth-token-validation';
import logger from '/imports/startup/client/logger';
import { makeVar } from '@apollo/client';

const CONNECTION_TIMEOUT = Meteor.settings.public.app.connectionTimeout;

Expand All @@ -22,10 +23,11 @@ class Auth {
return;
}


this._meetingID = Storage.getItem('meetingID');
this._userID = Storage.getItem('userID');
this._authToken = Storage.getItem('authToken');
this._sessionToken = Storage.getItem('sessionToken');
this._sessionToken = makeVar(Storage.getItem('sessionToken'));
this._logoutURL = Storage.getItem('logoutURL');
this._confname = Storage.getItem('confname');
this._externUserID = Storage.getItem('externUserID');
Expand All @@ -48,12 +50,20 @@ class Auth {
}

get sessionToken() {
return this._sessionToken;
try {
return this._sessionToken();
} catch {
return null;
}
}

set sessionToken(sessionToken) {
this._sessionToken = sessionToken;
Storage.setItem('sessionToken', this._sessionToken);
if (this._sessionToken) {
this._sessionToken(sessionToken);
} else {
this._sessionToken = makeVar(sessionToken);
}
Storage.setItem('sessionToken', this._sessionToken());
}

get userID() {
Expand Down