fix(dropbox): Address code review comments.

This commit is contained in:
hristoterezov 2018-08-15 14:51:51 -05:00 committed by yanas
parent 62544188bd
commit 2704b2f822
13 changed files with 138 additions and 144 deletions

View File

@ -4,7 +4,6 @@
.recording-dialog {
.authorization-panel {
align-items: center;
border-bottom: 2px solid rgba(0, 0, 0, 0.3);
display: flex;
flex-direction: column;
@ -12,18 +11,23 @@
padding-bottom: 10px;
.dropbox-sign-in {
background-color: #4285f4;
align-items: center;
border: 1px solid #4285f4;
background-color: white;
border-radius: 2px;
cursor: pointer;
display: inline-flex;
padding: 1px;
padding: 10px;
font-size: 18px;
font-weight: 600;
margin: 10px 0px;
color: #4285f4;
.dropbox-logo {
background-color: white;
border-radius: 2px;
display: inline-block;
padding: 8px;
padding-right: 5px;
height: 18px;
}
}

View File

@ -456,10 +456,11 @@
"on": "Recording",
"pending": "Preparing to record the meeting...",
"rec": "REC",
"authDropboxText": "To start the recording you need to first authorize our Dropbox recording app. After the recording is finished the file will be uploaded to your Dropbox account.",
"authDropboxCompletedText": "Our Dropbox app has been authorized successfully. You should see the recorded file in your Dropbox account shortly after the recording has finished.",
"authDropboxText": "Upload your recording to Dropbox.",
"authDropboxCompletedText": "Your recording file will appear in your Dropbox shortly after the recording has finished.",
"serviceName": "Recording service",
"signOut": "Sign Out",
"signIn": "sign in",
"loggedIn": "Logged in as __userName__",
"availableSpace": "Available space: __spaceLeft__ MB (approximately __duration__ minutes of recording)",
"startRecordingBody": "Are you sure you would like to start recording?",

View File

@ -1,29 +0,0 @@
// @flow
import { getJitsiMeetGlobalNS } from '../util';
/**
* Executes the oauth flow.
*
* @param {string} authUrl - The URL to oauth service.
* @returns {Promise<string>} - The URL with the authorization details.
*/
export function authorize(authUrl: string): Promise<string> {
const windowName = `oauth${Date.now()}`;
const gloabalNS = getJitsiMeetGlobalNS();
gloabalNS.oauthCallbacks = gloabalNS.oauthCallbacks || {};
return new Promise(resolve => {
const popup = window.open(authUrl, windowName);
gloabalNS.oauthCallbacks[windowName] = () => {
const returnURL = popup.location.href;
popup.close();
delete gloabalNS.oauthCallbacks.windowName;
resolve(returnURL);
};
});
}

View File

@ -1,38 +0,0 @@
// @flow
import { ReducerRegistry } from '../redux';
import { PersistenceRegistry } from '../storage';
import { UPDATE_DROPBOX_TOKEN } from './actionTypes';
/**
* The default state.
*/
const DEFAULT_STATE = {
dropbox: {}
};
/**
* The redux subtree of this feature.
*/
const STORE_NAME = 'features/base/oauth';
/**
* Sets up the persistence of the feature {@code oauth}.
*/
PersistenceRegistry.register(STORE_NAME);
ReducerRegistry.register('features/base/oauth',
(state = DEFAULT_STATE, action) => {
switch (action.type) {
case UPDATE_DROPBOX_TOKEN:
return {
...state,
dropbox: {
token: action.token
}
};
default:
return state;
}
});

View File

@ -2,12 +2,40 @@
import { Dropbox } from 'dropbox';
import { getLocationContextRoot, parseStandardURIString } from '../util';
import { parseURLParams } from '../config';
import {
getJitsiMeetGlobalNS,
getLocationContextRoot,
parseStandardURIString
} from '../base/util';
import { parseURLParams } from '../base/config';
import { authorize } from './functions';
import { UPDATE_DROPBOX_TOKEN } from './actionTypes';
/**
* Executes the oauth flow.
*
* @param {string} authUrl - The URL to oauth service.
* @returns {Promise<string>} - The URL with the authorization details.
*/
function authorize(authUrl: string): Promise<string> {
const windowName = `oauth${Date.now()}`;
const gloabalNS = getJitsiMeetGlobalNS();
gloabalNS.oauthCallbacks = gloabalNS.oauthCallbacks || {};
return new Promise(resolve => {
const popup = window.open(authUrl, windowName);
gloabalNS.oauthCallbacks[windowName] = () => {
const returnURL = popup.location.href;
popup.close();
delete gloabalNS.oauthCallbacks.windowName;
resolve(returnURL);
};
});
}
/**
* Action to authorize the Jitsi Recording app in dropbox.
*

View File

@ -0,0 +1,39 @@
// @flow
import { Dropbox } from 'dropbox';
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* Fetches information about the user's dropbox account.
*
* @param {string} token - The dropbox access token.
* @param {string} clientId - The Jitsi Recorder dropbox app ID.
* @returns {Promise<Object|undefined>}
*/
export function getDropboxData(
token: string,
clientId: string
): Promise<?Object> {
const dropboxAPI = new Dropbox({
accessToken: token,
clientId
});
return Promise.all(
[ dropboxAPI.usersGetCurrentAccount(), dropboxAPI.usersGetSpaceUsage() ]
).then(([ account, space ]) => {
const { allocation, used } = space;
const { allocated } = allocation;
return {
userName: account.name.display_name,
spaceLeft: Math.floor((allocated - used) / 1048576)// 1MiB=1048576B
};
}, error => {
logger.error(error);
return undefined;
});
}

View File

@ -1,3 +1,4 @@
export * from './actions';
export * from './functions';
import './reducer';

View File

@ -0,0 +1,28 @@
// @flow
import { ReducerRegistry } from '../base/redux';
import { PersistenceRegistry } from '../base/storage';
import { UPDATE_DROPBOX_TOKEN } from './actionTypes';
/**
* The redux subtree of this feature.
*/
const STORE_NAME = 'features/dropbox';
/**
* Sets up the persistence of the feature {@code dropbox}.
*/
PersistenceRegistry.register(STORE_NAME);
ReducerRegistry.register(STORE_NAME, (state = {}, action) => {
switch (action.type) {
case UPDATE_DROPBOX_TOKEN:
return {
...state,
token: action.token
};
default:
return state;
}
});

View File

@ -11,7 +11,7 @@ import { Dialog } from '../../../base/dialog';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import StartRecordingDialogContent from './StartRecordingDialogContent';
import { getDropboxData } from '../../functions';
import { getDropboxData } from '../../../dropbox';
type Props = {
@ -41,7 +41,6 @@ type Props = {
t: Function
}
type State = {
/**
@ -54,15 +53,15 @@ type State = {
*/
isValidating: boolean,
/**
* The display name of the user's Dropbox account.
*/
userName: ?string,
/**
* Number of MiB of available space in user's Dropbox account.
*/
spaceLeft: ?number
spaceLeft: ?number,
/**
* The display name of the user's Dropbox account.
*/
userName: ?string
};
/**
@ -217,14 +216,16 @@ class StartRecordingDialog extends Component<Props, State> {
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _conference: JitsiConference
* _clientId: string,
* _conference: JitsiConference,
* _token: string
* }}
*/
function mapStateToProps(state: Object) {
return {
_clientId: state['features/base/config'].dropbox.clientId,
_conference: state['features/base/conference'].conference,
_token: state['features/base/oauth'].dropbox.token,
_clientId: state['features/base/config'].dropbox.clientId
_token: state['features/dropbox'].token
};
}

View File

@ -9,7 +9,7 @@ import {
sendAnalytics
} from '../../../analytics';
import { translate } from '../../../base/i18n';
import { authorizeDropbox, updateDropboxToken } from '../../../base/oauth';
import { authorizeDropbox, updateDropboxToken } from '../../../dropbox';
type Props = {
@ -111,17 +111,21 @@ class StartRecordingDialogContent extends Component<Props> {
* @returns {React$Component}
*/
_renderSignIn() {
const { t } = this.props;
return (
<div>
<div>{ this.props.t('recording.authDropboxText') }</div>
<div>{ t('recording.authDropboxText') }</div>
<div
className = 'dropbox-sign-in'
onClick = { this._onSignInClick }>
<img
className = 'dropbox-logo'
src = 'images/dropboxLogo.svg' />
<span>{ t('recording.signIn') }</span>
</div>
</div>);
</div>
);
}
/**
@ -135,7 +139,7 @@ class StartRecordingDialogContent extends Component<Props> {
return (
<div>
<div>{ t('recording.authDropboxCompletedText') }</div>
<div className = 'logged-in-pannel'>
<div className = 'logged-in-panel'>
<div>
{ t('recording.loggedIn', { userName }) }&nbsp;(&nbsp;
<a onClick = { this._onSignOutClick }>
@ -154,7 +158,8 @@ class StartRecordingDialogContent extends Component<Props> {
}
</div>
</div>
</div>);
</div>
);
}
_onSignInClick: () => {};

View File

@ -1,11 +1,7 @@
// @flow
import { Dropbox } from 'dropbox';
import { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* Searches in the passed in redux state for an active recording session of the
* passed in mode.
@ -35,37 +31,3 @@ export function getSessionById(state: Object, id: string) {
return state['features/recording'].sessionDatas.find(
sessionData => sessionData.id === id);
}
/**
* Fetches information about the user's dropbox account.
*
* @param {string} token - The dropbox access token.
* @param {string} clientId - The Jitsi Recorder dropbox app ID.
* @returns {Promise<Object|undefined>}
*/
export function getDropboxData(
token: string,
clientId: string
): Promise<?Object> {
const dropboxAPI = new Dropbox({
accessToken: token,
clientId
});
return Promise.all(
[ dropboxAPI.usersGetCurrentAccount(), dropboxAPI.usersGetSpaceUsage() ]
).then(([ account, space ]) => {
const { allocation, used } = space;
const { allocated } = allocation;
return {
userName: account.name.display_name,
spaceLeft: Math.floor((allocated - used) / 1048576)// 1MiB=1048576B
};
}, error => {
logger.error(error);
return undefined;
});
}

View File

@ -6,7 +6,7 @@
<!--#include virtual="/base.html" -->
<!--#include virtual="/title.html" -->
<script>
function getParentWindowCallback() {
(function() {
var windowName = window.name;
var parentWindow = window.opener;
if (parentWindow
@ -16,20 +16,12 @@
if (globalNS.oauthCallbacks
&& typeof globalNS.oauthCallbacks[windowName]
=== 'function') {
return globalNS.oauthCallbacks[windowName];
globalNS.oauthCallbacks[windowName]();
}
}
return undefined;
}
var callback = getParentWindowCallback();
if (typeof callback === 'function') {
callback();
} else {
alert('Something went wrong!');
}
})();
</script>
</head>
<body />
<body>
</body>
</html>