mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-06-02 04:57:45 +00:00
Compare commits
14 Commits
3080
...
emcho-patc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
917ef449ec | ||
|
|
3fdf944763 | ||
|
|
56100d0d5c | ||
|
|
486e8e35d9 | ||
|
|
554974a36d | ||
|
|
cd943319d6 | ||
|
|
837f496e8f | ||
|
|
c43f7c8979 | ||
|
|
c9c9f7eac0 | ||
|
|
5ccc397e47 | ||
|
|
00cd82d976 | ||
|
|
61deb74444 | ||
|
|
b30008e3a5 | ||
|
|
62b6737a3f |
@@ -130,7 +130,7 @@ equivalent to these of a direct one-to-one WebRTC call. This is what's unique to
|
||||
Jitsi Meet in terms of security.
|
||||
|
||||
The [meet.jit.si](https://meet.jit.si) service is maintained by the Jitsi team
|
||||
at [Atlassian](https://atlassian.com).
|
||||
at [8x8](https://8x8.com).
|
||||
|
||||
## Mobile app
|
||||
Jitsi Meet is also available as a React Native app for Android and iOS.
|
||||
|
||||
@@ -126,9 +126,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// The e2e rtt are not useful in GA, and there are too many of them.
|
||||
// We just filter them out for now.
|
||||
if (event.action === 'e2e_rtt') {
|
||||
const ignoredEvents
|
||||
= [ 'e2e_rtt', 'rtp.stats', 'rtt.by.region', 'available.device',
|
||||
'stream.switch.delay', 'ice.state.changed', 'ice.duration' ];
|
||||
|
||||
// Temporary removing some of the events that are too noisy.
|
||||
if (ignoredEvents.indexOf(event.action) !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,6 @@ var config = {
|
||||
// XMPP domain.
|
||||
domain: 'jitsi-meet.example.com',
|
||||
|
||||
// XMPP MUC domain. FIXME: use XEP-0030 to discover it.
|
||||
muc: 'conference.jitsi-meet.example.com'
|
||||
|
||||
// When using authentication, domain for guest users.
|
||||
// anonymousdomain: 'guest.example.com',
|
||||
|
||||
@@ -35,6 +32,9 @@ var config = {
|
||||
|
||||
// Focus component domain. Defaults to focus.<domain>.
|
||||
// focus: 'focus.jitsi-meet.example.com',
|
||||
|
||||
// XMPP MUC domain. FIXME: use XEP-0030 to discover it.
|
||||
muc: 'conference.jitsi-meet.example.com'
|
||||
},
|
||||
|
||||
// BOSH URL. FIXME: use XEP-0156 to discover it.
|
||||
|
||||
117
css/_meetings_list.scss
Normal file
117
css/_meetings_list.scss
Normal file
@@ -0,0 +1,117 @@
|
||||
.meetings-list {
|
||||
font-size: 14px;
|
||||
color: #253858;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
||||
.meetings-list-empty {
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
|
||||
.description {
|
||||
font-size: 16px;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
background: #0074E0;
|
||||
border-radius: 4px;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item {
|
||||
background: rgba(255,255,255,0.50);
|
||||
box-sizing: border-box;
|
||||
display: inline-flex;
|
||||
margin-top: 5px;
|
||||
min-height: 92px;
|
||||
width: 100%;
|
||||
word-break: break-word;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: left;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.left-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
flex-grow: 0;
|
||||
padding-left: 30px;
|
||||
padding-top: 25px;
|
||||
|
||||
.date {
|
||||
font-weight: bold;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.right-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding-left: 30px;
|
||||
padding-top: 25px;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-grow: 0;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
&.with-click-handler {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.with-click-handler:hover {
|
||||
background-color: #75A7E7;
|
||||
}
|
||||
|
||||
.add-button {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
i {
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.join-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover .join-button {
|
||||
display: block
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,7 @@ $watermarkHeight: 74px;
|
||||
/**
|
||||
* Welcome page variables.
|
||||
*/
|
||||
$welcomePageDescriptionColor: #E6EDFA;
|
||||
$welcomePageDescriptionColor: #fff;
|
||||
$welcomePageFontFamily: inherit;
|
||||
$welcomePageHeaderBackground: #1D69D4;
|
||||
$welcomePageHeaderBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
|
||||
$welcomePageTitleColor: #fff;
|
||||
|
||||
@@ -4,7 +4,7 @@ body.welcome-page {
|
||||
}
|
||||
|
||||
.welcome {
|
||||
background-color: $welcomePageHeaderBackground;
|
||||
background-image: $welcomePageHeaderBackground;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: $welcomePageFontFamily;
|
||||
@@ -24,8 +24,8 @@ body.welcome-page {
|
||||
.header-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: $watermarkHeight + 80;
|
||||
margin-bottom: 36px;
|
||||
margin-top: $watermarkHeight + 35;
|
||||
margin-bottom: 35px;
|
||||
max-width: calc(100% - 40px);
|
||||
width: 650px;
|
||||
z-index: $zindex2;
|
||||
@@ -35,7 +35,6 @@ body.welcome-page {
|
||||
color: $welcomePageTitleColor;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.18;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
@@ -49,41 +48,118 @@ body.welcome-page {
|
||||
}
|
||||
|
||||
#enter_room {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: calc(100% - 40px);
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
width: 650px;
|
||||
width: 680px;
|
||||
z-index: $zindex2;
|
||||
background-color: #fff;
|
||||
padding: 25px 30px;
|
||||
|
||||
.enter-room-input {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
.enter-room-input-container {
|
||||
width: 100%;
|
||||
padding-right: 8px;
|
||||
padding-bottom: 5px;
|
||||
text-align: left;
|
||||
color: #253858;
|
||||
height: fit-content;
|
||||
border-width: 0px 0px 2px 0px;
|
||||
border-style: solid;
|
||||
border-image: linear-gradient(to right, #dee1e6, #fff) 1;
|
||||
|
||||
.enter-room-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.enter-room-input {
|
||||
border: none;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
color: #253858;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.tab-container {
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
width: 650px;
|
||||
min-height: 354px;
|
||||
width: 710px;
|
||||
background: #75A7E7;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.tab-content{
|
||||
margin: 5px 0px;
|
||||
overflow: hidden;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
|
||||
> * {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-buttons {
|
||||
font-size: 18px;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
flex-grow: 0;
|
||||
flex-direction: row;
|
||||
min-height: 54px;
|
||||
width: 100%;
|
||||
|
||||
.tab {
|
||||
text-align: center;
|
||||
background: rgba(9,30,66,0.37);
|
||||
height: 55px;
|
||||
line-height: 54px;
|
||||
flex-grow: 1;
|
||||
cursor: pointer;
|
||||
|
||||
&.selected, &:hover {
|
||||
background: rgba(9,30,66,0.71);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.welcome-page-button {
|
||||
font-size: 16px;
|
||||
width: 51px;
|
||||
height: 35px;
|
||||
font-size: 14px;
|
||||
background: #0074E0;
|
||||
border-radius: 4px;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 35px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.welcome-page-settings {
|
||||
color: $welcomePageDescriptionColor;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 32px;
|
||||
right: 32px;
|
||||
z-index: $zindex2;
|
||||
|
||||
* {
|
||||
cursor: pointer;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
@import 'modals/invite/add-people';
|
||||
@import 'deep-linking/main';
|
||||
@import 'transcription-subtitles';
|
||||
@import '_meetings_list.scss';
|
||||
@import 'navigate_section_list';
|
||||
@import 'third-party-branding/google';
|
||||
@import 'third-party-branding/microsoft';
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
"calendar": "Calendar",
|
||||
"connectCalendarText": "Connect your calendar to view all your meetings in __app__. Plus, add __app__ meetings to your calendar and start them with one click.",
|
||||
"connectCalendarButton": "Connect your calendar",
|
||||
"enterRoomTitle": "Start a new meeting",
|
||||
"go": "GO",
|
||||
"join": "JOIN",
|
||||
"privacy": "Privacy",
|
||||
@@ -69,7 +70,7 @@
|
||||
"roomnameHint": "Enter the name or URL of the room you want to join. You may make a name up, just let the people you are meeting know it so that they enter the same name.",
|
||||
"sendFeedback": "Send feedback",
|
||||
"terms": "Terms",
|
||||
"title": "More secure, more flexible, and completely free video conferencing."
|
||||
"title": "Secure, fully featured, and completely free video conferencing"
|
||||
},
|
||||
"startupoverlay": {
|
||||
"policyText": " ",
|
||||
|
||||
55
modules/API/external/external_api.js
vendored
55
modules/API/external/external_api.js
vendored
@@ -462,55 +462,57 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
* the event and value - the listener.
|
||||
* Currently we support the following
|
||||
* events:
|
||||
* incomingMessage - receives event notifications about incoming
|
||||
* {@code incomingMessage} - receives event notifications about incoming
|
||||
* messages. The listener will receive object with the following structure:
|
||||
* {{
|
||||
* 'from': from,//JID of the user that sent the message
|
||||
* 'nick': nick,//the nickname of the user that sent the message
|
||||
* 'message': txt//the text of the message
|
||||
* }}
|
||||
* outgoingMessage - receives event notifications about outgoing
|
||||
* {@code outgoingMessage} - receives event notifications about outgoing
|
||||
* messages. The listener will receive object with the following structure:
|
||||
* {{
|
||||
* 'message': txt//the text of the message
|
||||
* }}
|
||||
* displayNameChanged - receives event notifications about display name
|
||||
* change. The listener will receive object with the following structure:
|
||||
* {@code displayNameChanged} - receives event notifications about display
|
||||
* name change. The listener will receive object with the following
|
||||
* structure:
|
||||
* {{
|
||||
* jid: jid,//the JID of the participant that changed his display name
|
||||
* displayname: displayName //the new display name
|
||||
* }}
|
||||
* participantJoined - receives event notifications about new participant.
|
||||
* {@code participantJoined} - receives event notifications about new
|
||||
* participant.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* jid: jid //the jid of the participant
|
||||
* }}
|
||||
* participantLeft - receives event notifications about the participant that
|
||||
* left the room.
|
||||
* {@code participantLeft} - receives event notifications about the
|
||||
* participant that left the room.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* jid: jid //the jid of the participant
|
||||
* }}
|
||||
* video-conference-joined - receives event notifications about the local
|
||||
* user has successfully joined the video conference.
|
||||
* {@code video-conference-joined} - receives event notifications about the
|
||||
* local user has successfully joined the video conference.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* roomName: room //the room name of the conference
|
||||
* }}
|
||||
* video-conference-left - receives event notifications about the local user
|
||||
* has left the video conference.
|
||||
* {@code video-conference-left} - receives event notifications about the
|
||||
* local user has left the video conference.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* roomName: room //the room name of the conference
|
||||
* }}
|
||||
* screenSharingStatusChanged - receives event notifications about
|
||||
* {@code screenSharingStatusChanged} - receives event notifications about
|
||||
* turning on/off the local user screen sharing.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* on: on //whether screen sharing is on
|
||||
* }}
|
||||
* readyToClose - all hangup operations are completed and Jitsi Meet is
|
||||
* ready to be disposed.
|
||||
* {@code readyToClose} - all hangup operations are completed and Jitsi Meet
|
||||
* is ready to be disposed.
|
||||
* @returns {void}
|
||||
*
|
||||
* @deprecated
|
||||
@@ -537,11 +539,12 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Executes command. The available commands are:
|
||||
* displayName - sets the display name of the local participant to the value
|
||||
* passed in the arguments array.
|
||||
* toggleAudio - mutes / unmutes audio with no arguments.
|
||||
* toggleVideo - mutes / unmutes video with no arguments.
|
||||
* toggleFilmStrip - hides / shows the filmstrip with no arguments.
|
||||
* {@code displayName} - Sets the display name of the local participant to
|
||||
* the value passed in the arguments array.
|
||||
* {@code toggleAudio} - Mutes / unmutes audio with no arguments.
|
||||
* {@code toggleVideo} - Mutes / unmutes video with no arguments.
|
||||
* {@code toggleFilmStrip} - Hides / shows the filmstrip with no arguments.
|
||||
*
|
||||
* If the command doesn't require any arguments the parameter should be set
|
||||
* to empty array or it may be omitted.
|
||||
*
|
||||
@@ -562,13 +565,13 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Executes commands. The available commands are:
|
||||
* displayName - sets the display name of the local participant to the value
|
||||
* passed in the arguments array.
|
||||
* toggleAudio - mutes / unmutes audio. no arguments
|
||||
* toggleVideo - mutes / unmutes video. no arguments
|
||||
* toggleFilmStrip - hides / shows the filmstrip. no arguments
|
||||
* toggleChat - hides / shows chat. no arguments.
|
||||
* toggleShareScreen - starts / stops screen sharing. no arguments.
|
||||
* {@code displayName} - Sets the display name of the local participant to
|
||||
* the value passed in the arguments array.
|
||||
* {@code toggleAudio} - Mutes / unmutes audio. No arguments.
|
||||
* {@code toggleVideo} - Mutes / unmutes video. No arguments.
|
||||
* {@code toggleFilmStrip} - Hides / shows the filmstrip. No arguments.
|
||||
* {@code toggleChat} - Hides / shows chat. No arguments.
|
||||
* {@code toggleShareScreen} - Starts / stops screen sharing. No arguments.
|
||||
*
|
||||
* @param {Object} commandList - The object with commands to be executed.
|
||||
* The keys of the object are the commands that will be executed and the
|
||||
|
||||
29
package-lock.json
generated
29
package-lock.json
generated
@@ -7460,9 +7460,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"hoist-non-react-statics": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz",
|
||||
"integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs="
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
|
||||
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
|
||||
},
|
||||
"home-or-tmp": {
|
||||
"version": "2.0.0",
|
||||
@@ -7534,6 +7534,14 @@
|
||||
"integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
|
||||
"dev": true
|
||||
},
|
||||
"html-parse-stringify2": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz",
|
||||
"integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=",
|
||||
"requires": {
|
||||
"void-elements": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
|
||||
@@ -11547,11 +11555,13 @@
|
||||
}
|
||||
},
|
||||
"react-i18next": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-4.8.0.tgz",
|
||||
"integrity": "sha1-kvDSgcXzmsjzw/OBVi1SPp2DAlQ=",
|
||||
"version": "7.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-7.13.0.tgz",
|
||||
"integrity": "sha512-35M+MZFPqHwVIas7tXWQKFrf+ozCJukNplUTiGqL8mczSk+VRBsHxxXuuQKRkz/4CcWkONGWbp/AzxfM6wZncg==",
|
||||
"requires": {
|
||||
"hoist-non-react-statics": "1.2.0"
|
||||
"hoist-non-react-statics": "^2.3.1",
|
||||
"html-parse-stringify2": "2.0.1",
|
||||
"prop-types": "^15.6.0"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
@@ -15145,6 +15155,11 @@
|
||||
"indexof": "0.0.1"
|
||||
}
|
||||
},
|
||||
"void-elements": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
|
||||
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
|
||||
},
|
||||
"walker": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"prop-types": "15.6.0",
|
||||
"react": "16.5.0",
|
||||
"react-dom": "16.5.0",
|
||||
"react-i18next": "4.8.0",
|
||||
"react-i18next": "7.13.0",
|
||||
"react-native": "0.57.1",
|
||||
"react-native-background-timer": "2.0.0",
|
||||
"react-native-calendar-events": "github:wmcmahan/react-native-calendar-events#cb2731db6684a49b4343e09de7f9c2fcc68bcd9b",
|
||||
|
||||
@@ -413,7 +413,7 @@ export function createRemoteVideoMenuButtonEvent(buttonName, attributes) {
|
||||
|
||||
/**
|
||||
* Creates an event indicating that an action related to screen sharing
|
||||
* occurred (e.g. it was started or stopped).
|
||||
* occurred (e.g. It was started or stopped).
|
||||
*
|
||||
* @param {string} action - The action which occurred.
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
@@ -466,7 +466,7 @@ export function createSharedVideoEvent(action, attributes = {}) {
|
||||
* Creates an event associated with a shortcut being pressed, released or
|
||||
* triggered. By convention, where appropriate an attribute named 'enable'
|
||||
* should be used to indicate the action which resulted by the shortcut being
|
||||
* pressed (e.g. whether screen sharing was enabled or disabled).
|
||||
* pressed (e.g. Whether screen sharing was enabled or disabled).
|
||||
*
|
||||
* @param {string} shortcut - The identifier of the shortcut which produced
|
||||
* an action.
|
||||
@@ -512,7 +512,7 @@ export function createStartAudioOnlyEvent(audioOnly) {
|
||||
*
|
||||
* @param {string} source - The source of the configuration, 'local' or
|
||||
* 'remote' depending on whether it comes from the static configuration (i.e.
|
||||
* config.js) or comes dynamically from Jicofo.
|
||||
* {@code config.js}) or comes dynamically from Jicofo.
|
||||
* @param {boolean} audioMute - Whether the configuration requests that audio
|
||||
* is muted.
|
||||
* @param {boolean} videoMute - Whether the configuration requests that video
|
||||
@@ -573,7 +573,7 @@ export function createSyncTrackStateEvent(mediaType, muted) {
|
||||
* Creates an event associated with a toolbar button being clicked/pressed. By
|
||||
* convention, where appropriate an attribute named 'enable' should be used to
|
||||
* indicate the action which resulted by the shortcut being pressed (e.g.
|
||||
* whether screen sharing was enabled or disabled).
|
||||
* Whether screen sharing was enabled or disabled).
|
||||
*
|
||||
* @param {string} buttonName - The identifier of the toolbar button which was
|
||||
* clicked/pressed.
|
||||
@@ -595,9 +595,9 @@ export function createToolbarEvent(buttonName, attributes = {}) {
|
||||
* Creates an event which indicates that a local track was muted.
|
||||
*
|
||||
* @param {string} mediaType - The track's media type ('audio' or 'video').
|
||||
* @param {string} reason - The reason the track was muted (e.g. it was
|
||||
* @param {string} reason - The reason the track was muted (e.g. It was
|
||||
* triggered by the "initial mute" option, or a previously muted track was
|
||||
* replaced (e.g. when a new device was used)).
|
||||
* replaced (e.g. When a new device was used)).
|
||||
* @param {boolean} muted - Whether the track was muted or unmuted.
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
|
||||
@@ -128,10 +128,10 @@ export class AbstractApp extends BaseApp<Props, *> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates this {@code AbstractApp} to (i.e. opens) a specific URL.
|
||||
* Navigates this {@code AbstractApp} to (i.e. Opens) a specific URL.
|
||||
*
|
||||
* @param {Object|string} url - The URL to navigate this {@code AbstractApp}
|
||||
* to (i.e. the URL to open).
|
||||
* to (i.e. The URL to open).
|
||||
* @protected
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
/**
|
||||
@@ -13,27 +14,24 @@ const AUDIO_LEVEL_DOTS = 5;
|
||||
*/
|
||||
const CENTER_DOT_INDEX = Math.floor(AUDIO_LEVEL_DOTS / 2);
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AudioLevelIndicator}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The current audio level to display. The value should be a number between
|
||||
* 0 and 1.
|
||||
*/
|
||||
audioLevel: number
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a ReactElement responsible for drawing audio levels.
|
||||
*
|
||||
* @extends {Component}
|
||||
*/
|
||||
class AudioLevelIndicator extends Component {
|
||||
/**
|
||||
* {@code AudioLevelIndicator}'s property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The current audio level to display. The value should be a number
|
||||
* between 0 and 1.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
audioLevel: PropTypes.number
|
||||
};
|
||||
|
||||
class AudioLevelIndicator extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -23,7 +23,7 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
* password + guest access configuration. Refer to {@link LoginDialog} for more
|
||||
* info.
|
||||
*
|
||||
* @param {string} id - The XMPP user's ID (e.g. user@domain.com).
|
||||
* @param {string} id - The XMPP user's ID (e.g. {@code user@domain.com}).
|
||||
* @param {string} password - The XMPP user's password.
|
||||
* @param {JitsiConference} conference - The conference for which the local
|
||||
* participant's role will be upgraded.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { Text, TextInput, View } from 'react-native';
|
||||
import { connect as reduxConnect } from 'react-redux';
|
||||
@@ -11,6 +12,65 @@ import { JitsiConnectionErrors } from '../../base/lib-jitsi-meet';
|
||||
import { authenticateAndUpgradeRole, cancelLogin } from '../actions';
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
* The type of the React {@link Component} props of {@link LoginDialog}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* {@link JitsiConference} that needs authentication - will hold a valid
|
||||
* value in XMPP login + guest access mode.
|
||||
*/
|
||||
_conference: Object,
|
||||
|
||||
/**
|
||||
* The server hosts specified in the global config.
|
||||
*/
|
||||
_configHosts: Object,
|
||||
|
||||
/**
|
||||
* Indicates if the dialog should display "connecting" status message.
|
||||
*/
|
||||
_connecting: boolean,
|
||||
|
||||
/**
|
||||
* The error which occurred during login/authentication.
|
||||
*/
|
||||
_error: Object,
|
||||
|
||||
/**
|
||||
* The progress in the floating range between 0 and 1 of the authenticating
|
||||
* and upgrading the role of the local participant/user.
|
||||
*/
|
||||
_progress: number,
|
||||
|
||||
/**
|
||||
* Redux store dispatch method.
|
||||
*/
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@link Component} state of {@link LoginDialog}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The user entered password for the conference.
|
||||
*/
|
||||
password: string,
|
||||
|
||||
/**
|
||||
* The user entered local participant name.
|
||||
*/
|
||||
username: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Dialog asks user for username and password.
|
||||
*
|
||||
@@ -38,58 +98,14 @@ import styles from './styles';
|
||||
* See {@link https://github.com/jitsi/jicofo#secure-domain} for a description
|
||||
* of the configuration parameters.
|
||||
*/
|
||||
class LoginDialog extends Component {
|
||||
/**
|
||||
* LoginDialog component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* {@link JitsiConference} that needs authentication - will hold a valid
|
||||
* value in XMPP login + guest access mode.
|
||||
*/
|
||||
_conference: PropTypes.object,
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
_configHosts: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Indicates if the dialog should display "connecting" status message.
|
||||
*/
|
||||
_connecting: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The error which occurred during login/authentication.
|
||||
*/
|
||||
_error: PropTypes.object,
|
||||
|
||||
/**
|
||||
* The progress in the floating range between 0 and 1 of the
|
||||
* authenticating and upgrading the role of the local participant/user.
|
||||
*/
|
||||
_progress: PropTypes.number,
|
||||
|
||||
/**
|
||||
* Redux store dispatch method.
|
||||
*/
|
||||
dispatch: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class LoginDialog extends Component<Props, State> {
|
||||
/**
|
||||
* Initializes a new LoginDialog instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@@ -119,7 +135,7 @@ class LoginDialog extends Component {
|
||||
} = this.props;
|
||||
|
||||
let messageKey;
|
||||
let messageOptions;
|
||||
const messageOptions = {};
|
||||
|
||||
if (progress && progress < 1) {
|
||||
messageKey = 'connection.FETCH_SESSION_ID';
|
||||
@@ -142,7 +158,6 @@ class LoginDialog extends Component {
|
||||
}
|
||||
} else if (name) {
|
||||
messageKey = 'dialog.connectErrorWithMsg';
|
||||
messageOptions || (messageOptions = {});
|
||||
messageOptions.msg = `${name} ${error.message}`;
|
||||
}
|
||||
}
|
||||
@@ -170,7 +185,7 @@ class LoginDialog extends Component {
|
||||
<Text style = { styles.dialogText }>
|
||||
{
|
||||
messageKey
|
||||
? t(messageKey, messageOptions || {})
|
||||
? t(messageKey, messageOptions)
|
||||
: connecting
|
||||
? t('connection.CONNECTING')
|
||||
: ''
|
||||
@@ -181,6 +196,8 @@ class LoginDialog extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onUsernameChange: (string) => void;
|
||||
|
||||
/**
|
||||
* Called when user edits the username.
|
||||
*
|
||||
@@ -194,6 +211,8 @@ class LoginDialog extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
_onPasswordChange: (string) => void;
|
||||
|
||||
/**
|
||||
* Called when user edits the password.
|
||||
*
|
||||
@@ -207,6 +226,8 @@ class LoginDialog extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
_onCancel: () => void;
|
||||
|
||||
/**
|
||||
* Notifies this LoginDialog that it has been dismissed by cancel.
|
||||
*
|
||||
@@ -217,6 +238,8 @@ class LoginDialog extends Component {
|
||||
this.props.dispatch(cancelLogin());
|
||||
}
|
||||
|
||||
_onLogin: () => void;
|
||||
|
||||
/**
|
||||
* Notifies this LoginDialog that the login button (OK) has been pressed by
|
||||
* the user.
|
||||
|
||||
@@ -198,8 +198,8 @@ export function getNearestReceiverVideoQualityLevel(availableHeight: number) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an error thrown by the backend (i.e. lib-jitsi-meet) while
|
||||
* manipulating a conference participant (e.g. pin or select participant).
|
||||
* Handle an error thrown by the backend (i.e. {@code lib-jitsi-meet}) while
|
||||
* manipulating a conference participant (e.g. Pin or select participant).
|
||||
*
|
||||
* @param {Error} err - The Error which was thrown by the backend while
|
||||
* manipulating a conference participant and which is to be handled.
|
||||
|
||||
@@ -71,7 +71,7 @@ export type ConnectionFailedError = {
|
||||
/**
|
||||
* Opens new connection.
|
||||
*
|
||||
* @param {string} [id] - The XMPP user's ID (e.g. user@server.com).
|
||||
* @param {string} [id] - The XMPP user's ID (e.g. {@code user@server.com}).
|
||||
* @param {string} [password] - The XMPP user's password.
|
||||
* @returns {Function}
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@ import { toState } from '../redux';
|
||||
|
||||
/**
|
||||
* Retrieves a simplified version of the conference/location URL stripped of URL
|
||||
* params (i.e. query/search and hash) which should be used for sending invites.
|
||||
* params (i.e. Query/search and hash) which should be used for sending invites.
|
||||
*
|
||||
* @param {Function|Object} stateOrGetState - The redux state or redux's
|
||||
* {@code getState} function.
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link DialogContainer}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The component to render.
|
||||
*/
|
||||
_component: Function,
|
||||
|
||||
/**
|
||||
* The props to pass to the component that will be rendered.
|
||||
*/
|
||||
_componentProps: Object,
|
||||
|
||||
/**
|
||||
* True if the UI is in a compact state where we don't show dialogs.
|
||||
*/
|
||||
_reducedUI: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a DialogContainer responsible for showing all dialogs. We will
|
||||
* need a separate container so we can handle multiple dialogs by showing them
|
||||
* simultaneously or queuing them.
|
||||
*/
|
||||
export class DialogContainer extends Component {
|
||||
/**
|
||||
* DialogContainer component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The component to render.
|
||||
*/
|
||||
_component: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The props to pass to the component that will be rendered.
|
||||
*/
|
||||
_componentProps: PropTypes.object,
|
||||
|
||||
/**
|
||||
* True if the UI is in a compact state where we don't show dialogs.
|
||||
*/
|
||||
_reducedUI: PropTypes.bool
|
||||
};
|
||||
|
||||
export class DialogContainer extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -32,7 +32,7 @@ const SOCK_STREAM = 1; /* stream socket */
|
||||
* The RTCPeerConnection provided by react-native-webrtc fires onaddstream
|
||||
* before it remembers remotedescription (and thus makes it available to API
|
||||
* clients). Because that appears to be a problem for lib-jitsi-meet which has
|
||||
* been successfully running on Chrome, Firefox, etc. for a very long
|
||||
* been successfully running on Chrome, Firefox and others for a very long
|
||||
* time, attempt to meet its expectations (by extending RTCPPeerConnection).
|
||||
*
|
||||
* @class
|
||||
|
||||
@@ -39,9 +39,10 @@ function _getCommonPrototype(a, b) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements an absolute minimum of the common logic of Document.querySelector
|
||||
* and Element.querySelector. Implements the most simple of selectors necessary
|
||||
* to satisfy the call sites at the time of this writing i.e. select by tagName.
|
||||
* Implements an absolute minimum of the common logic of
|
||||
* {@code Document.querySelector} and {@code Element.querySelector}. Implements
|
||||
* the most simple of selectors necessary to satisfy the call sites at the time
|
||||
* of this writing (i.e. Select by tagName).
|
||||
*
|
||||
* @param {Node} node - The Node which is the root of the tree to query.
|
||||
* @param {string} selectors - The group of CSS selectors to match on.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { trackVideoStarted } from '../../tracks';
|
||||
@@ -6,51 +7,71 @@ import { trackVideoStarted } from '../../tracks';
|
||||
import { shouldRenderVideoTrack } from '../functions';
|
||||
import { Video } from './_';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AbstractVideoTrack}.
|
||||
*/
|
||||
export type Props = {
|
||||
|
||||
/**
|
||||
* The Redux dispatch function.
|
||||
*/
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the {@link Video} of {@code AbstractVideoTrack}
|
||||
* is clicked/pressed.
|
||||
*/
|
||||
onPress?: Function,
|
||||
|
||||
/**
|
||||
* The Redux representation of the participant's video track.
|
||||
*/
|
||||
videoTrack?: Object,
|
||||
|
||||
/**
|
||||
* Whether or not video should be rendered after knowing video playback has
|
||||
* started.
|
||||
*/
|
||||
waitForVideoStarted?: boolean,
|
||||
|
||||
/**
|
||||
* The z-order of the Video of AbstractVideoTrack in the stacking space of
|
||||
* all Videos. For more details, refer to the zOrder property of the Video
|
||||
* class for React Native.
|
||||
*/
|
||||
zOrder?: number,
|
||||
|
||||
/**
|
||||
* Indicates whether zooming (pinch to zoom and/or drag) is enabled.
|
||||
*/
|
||||
zoomEnabled?: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link AbstractVideoTrack}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The Redux representation of the participant's video track.
|
||||
*/
|
||||
videoTrack: Object | null
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React {@link Component} that renders video element for a
|
||||
* specific video track.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
export default class AbstractVideoTrack extends Component {
|
||||
/**
|
||||
* AbstractVideoTrack component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the {@link Video} of
|
||||
* {@code AbstractVideoTrack} is clicked/pressed.
|
||||
*/
|
||||
onPress: PropTypes.func,
|
||||
|
||||
videoTrack: PropTypes.object,
|
||||
|
||||
waitForVideoStarted: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The z-order of the Video of AbstractVideoTrack in the stacking space
|
||||
* of all Videos. For more details, refer to the zOrder property of the
|
||||
* Video class for React Native.
|
||||
*/
|
||||
zOrder: PropTypes.number,
|
||||
|
||||
/**
|
||||
* Indicates whether zooming (pinch to zoom and/or drag) is enabled.
|
||||
*/
|
||||
zoomEnabled: PropTypes.bool
|
||||
};
|
||||
|
||||
export default class AbstractVideoTrack<P: Props> extends Component<P, State> {
|
||||
/**
|
||||
* Initializes a new AbstractVideoTrack instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: P) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@@ -69,7 +90,7 @@ export default class AbstractVideoTrack extends Component {
|
||||
* receive.
|
||||
* @returns {void}
|
||||
*/
|
||||
componentWillReceiveProps(nextProps) {
|
||||
componentWillReceiveProps(nextProps: P) {
|
||||
const oldValue = this.state.videoTrack;
|
||||
const newValue = _falsy2null(nextProps.videoTrack);
|
||||
|
||||
@@ -88,7 +109,7 @@ export default class AbstractVideoTrack extends Component {
|
||||
const { videoTrack } = this.state;
|
||||
let render;
|
||||
|
||||
if (this.props.waitForVideoStarted) {
|
||||
if (this.props.waitForVideoStarted && videoTrack) {
|
||||
// That's the complex case: we have to wait for onPlaying before we
|
||||
// render videoTrack. The complexity comes from the fact that
|
||||
// onPlaying will come after we render videoTrack.
|
||||
@@ -110,14 +131,15 @@ export default class AbstractVideoTrack extends Component {
|
||||
render = shouldRenderVideoTrack(videoTrack, false);
|
||||
}
|
||||
|
||||
const stream
|
||||
= render ? videoTrack.jitsiTrack.getOriginalStream() : null;
|
||||
const stream = render && videoTrack
|
||||
? videoTrack.jitsiTrack.getOriginalStream() : null;
|
||||
|
||||
// Actual zoom is currently only enabled if the stream is a desktop
|
||||
// stream.
|
||||
const zoomEnabled
|
||||
= this.props.zoomEnabled
|
||||
&& stream
|
||||
&& videoTrack
|
||||
&& videoTrack.videoType === 'desktop';
|
||||
|
||||
return (
|
||||
@@ -131,6 +153,8 @@ export default class AbstractVideoTrack extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onVideoPlaying: () => void;
|
||||
|
||||
/**
|
||||
* Handler for case when video starts to play.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { RTCView } from 'react-native-webrtc';
|
||||
|
||||
@@ -9,60 +8,58 @@ import { Pressable } from '../../../react';
|
||||
import styles from './styles';
|
||||
import VideoTransform from './VideoTransform';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Video}.
|
||||
*/
|
||||
type Props = {
|
||||
mirror: boolean,
|
||||
|
||||
onPlaying: Function,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the {@code Video} is clicked/pressed.
|
||||
*/
|
||||
onPress: Function,
|
||||
|
||||
stream: Object,
|
||||
|
||||
/**
|
||||
* Similarly to the CSS property z-index, specifies the z-order of this
|
||||
* Video in the stacking space of all Videos. When Videos overlap,
|
||||
* zOrder determines which one covers the other. A Video with a larger
|
||||
* zOrder generally covers a Video with a lower one.
|
||||
*
|
||||
* Non-overlapping Videos may safely share a z-order (because one does
|
||||
* not have to cover the other).
|
||||
*
|
||||
* The support for zOrder is platform-dependent and/or
|
||||
* implementation-specific. Thus, specifying a value for zOrder is to be
|
||||
* thought of as giving a hint rather than as imposing a requirement.
|
||||
* For example, video renderers such as Video are commonly implemented
|
||||
* using OpenGL and OpenGL views may have different numbers of layers in
|
||||
* their stacking space. Android has three: a layer bellow the window
|
||||
* (aka default), a layer bellow the window again but above the previous
|
||||
* layer (aka media overlay), and above the window. Consequently, it is
|
||||
* advisable to limit the number of utilized layers in the stacking
|
||||
* space to the minimum sufficient for the desired display. For example,
|
||||
* a video call application usually needs a maximum of two zOrder
|
||||
* values: 0 for the remote video(s) which appear in the background, and
|
||||
* 1 for the local video(s) which appear above the remote video(s).
|
||||
*/
|
||||
zOrder: number,
|
||||
|
||||
/**
|
||||
* Indicates whether zooming (pinch to zoom and/or drag) is enabled.
|
||||
*/
|
||||
zoomEnabled: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* The React Native {@link Component} which is similar to Web's
|
||||
* {@code HTMLVideoElement} and wraps around react-native-webrtc's
|
||||
* {@link RTCView}.
|
||||
*/
|
||||
export default class Video extends Component<*> {
|
||||
/**
|
||||
* {@code Video} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
mirror: PropTypes.bool,
|
||||
|
||||
onPlaying: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the {@code Video} is clicked/pressed.
|
||||
*/
|
||||
onPress: PropTypes.func,
|
||||
|
||||
stream: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Similarly to the CSS property z-index, specifies the z-order of this
|
||||
* Video in the stacking space of all Videos. When Videos overlap,
|
||||
* zOrder determines which one covers the other. A Video with a larger
|
||||
* zOrder generally covers a Video with a lower one.
|
||||
*
|
||||
* Non-overlapping Videos may safely share a z-order (because one does
|
||||
* not have to cover the other).
|
||||
*
|
||||
* The support for zOrder is platform-dependent and/or
|
||||
* implementation-specific. Thus, specifying a value for zOrder is to be
|
||||
* thought of as giving a hint rather than as imposing a requirement.
|
||||
* For example, video renderers such as Video are commonly implemented
|
||||
* using OpenGL and OpenGL views may have different numbers of layers in
|
||||
* their stacking space. Android has three: a layer bellow the window
|
||||
* (aka default), a layer bellow the window again but above the previous
|
||||
* layer (aka media overlay), and above the window. Consequently, it is
|
||||
* advisable to limit the number of utilized layers in the stacking
|
||||
* space to the minimum sufficient for the desired display. For example,
|
||||
* a video call application usually needs a maximum of two zOrder
|
||||
* values: 0 for the remote video(s) which appear in the background, and
|
||||
* 1 for the local video(s) which appear above the remote video(s).
|
||||
*/
|
||||
zOrder: PropTypes.number,
|
||||
|
||||
/**
|
||||
* Indicates whether zooming (pinch to zoom and/or drag) is enabled.
|
||||
*/
|
||||
zoomEnabled: PropTypes.bool
|
||||
};
|
||||
|
||||
export default class Video extends Component<Props> {
|
||||
/**
|
||||
* React Component method that executes once component is mounted.
|
||||
*
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import AbstractVideoTrack from '../AbstractVideoTrack';
|
||||
import type { Props } from '../AbstractVideoTrack';
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
@@ -10,14 +13,7 @@ import styles from './styles';
|
||||
*
|
||||
* @extends AbstractVideoTrack
|
||||
*/
|
||||
class VideoTrack extends AbstractVideoTrack {
|
||||
/**
|
||||
* VideoTrack component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = AbstractVideoTrack.propTypes
|
||||
|
||||
class VideoTrack extends AbstractVideoTrack<Props> {
|
||||
/**
|
||||
* Renders the video element for the associated video track.
|
||||
*
|
||||
|
||||
@@ -1,12 +1,42 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Video}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* CSS classes to add to the video element.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* The value of the id attribute of the video. Used by the torture tests to
|
||||
* locate video elements.
|
||||
*/
|
||||
id: string,
|
||||
|
||||
/**
|
||||
* Optional callback to invoke once the video starts playing.
|
||||
*/
|
||||
onVideoPlaying: Function,
|
||||
|
||||
/**
|
||||
* The JitsiLocalTrack to display.
|
||||
*/
|
||||
videoTrack: ?Object
|
||||
};
|
||||
|
||||
/**
|
||||
* Component that renders a video element for a passed in video track.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class Video extends Component {
|
||||
class Video extends Component<Props> {
|
||||
_videoElement: ?Object;
|
||||
|
||||
/**
|
||||
* Default values for {@code Video} component's properties.
|
||||
*
|
||||
@@ -18,41 +48,13 @@ class Video extends Component {
|
||||
id: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* {@code Video} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* CSS classes to add to the video element.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The value of the id attribute of the video. Used by the torture tests
|
||||
* to locate video elements.
|
||||
*/
|
||||
id: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Optional callback to invoke once the video starts playing.
|
||||
*/
|
||||
onVideoPlaying: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The JitsiLocalTrack to display.
|
||||
*/
|
||||
videoTrack: PropTypes.object
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes a new {@code Video} instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
/**
|
||||
@@ -78,8 +80,10 @@ class Video extends Component {
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidMount() {
|
||||
this._videoElement.volume = 0;
|
||||
this._videoElement.onplaying = this._onVideoPlaying;
|
||||
if (this._videoElement) {
|
||||
this._videoElement.volume = 0;
|
||||
this._videoElement.onplaying = this._onVideoPlaying;
|
||||
}
|
||||
|
||||
this._attachTrack(this.props.videoTrack);
|
||||
}
|
||||
@@ -98,13 +102,13 @@ class Video extends Component {
|
||||
/**
|
||||
* Updates the video display only if a new track is added. This component's
|
||||
* updating is blackboxed from React to prevent re-rendering of video
|
||||
* element, as the lib uses track.attach(videoElement) instead.
|
||||
* element, as the lib uses {@code track.attach(videoElement)} instead.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {boolean} - False is always returned to blackbox this component.
|
||||
* @returns {boolean} - False is always returned to blackbox this component
|
||||
* from React.
|
||||
*/
|
||||
shouldComponentUpdate(nextProps) {
|
||||
shouldComponentUpdate(nextProps: Props) {
|
||||
const currentJitsiTrack = this.props.videoTrack
|
||||
&& this.props.videoTrack.jitsiTrack;
|
||||
const nextJitsiTrack = nextProps.videoTrack
|
||||
@@ -167,6 +171,8 @@ class Video extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
_onVideoPlaying: () => void;
|
||||
|
||||
/**
|
||||
* Invokes the onvideoplaying callback if defined.
|
||||
*
|
||||
@@ -179,6 +185,8 @@ class Video extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
_setVideoElement: () => void;
|
||||
|
||||
/**
|
||||
* Sets an instance variable for the component's video element so it can be
|
||||
* referenced later for attaching and detaching a JitsiLocalTrack.
|
||||
|
||||
@@ -1,51 +1,49 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import AbstractVideoTrack from '../AbstractVideoTrack';
|
||||
import type { Props as AbstractVideoTrackProps } from '../AbstractVideoTrack';
|
||||
|
||||
import Video from './Video';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link VideoTrack}.
|
||||
*/
|
||||
type Props = {
|
||||
...AbstractVideoTrackProps,
|
||||
|
||||
/**
|
||||
* CSS classes to add to the video element.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* The value of the id attribute of the video. Used by the torture tests
|
||||
* to locate video elements.
|
||||
*/
|
||||
id: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Component that renders a video element for a passed in video track and
|
||||
* notifies the store when the video has started playing.
|
||||
*
|
||||
* @extends AbstractVideoTrack
|
||||
*/
|
||||
class VideoTrack extends AbstractVideoTrack {
|
||||
class VideoTrack extends AbstractVideoTrack<Props> {
|
||||
/**
|
||||
* Default values for {@code VideoTrack} component's properties.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static defaultProps = {
|
||||
...AbstractVideoTrack.defaultProps,
|
||||
|
||||
className: '',
|
||||
|
||||
id: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* {@code VideoTrack} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
...AbstractVideoTrack.propTypes,
|
||||
|
||||
/**
|
||||
* CSS classes to add to the video element.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The value of the id attribute of the video. Used by the torture tests
|
||||
* to locate video elements.
|
||||
*/
|
||||
id: PropTypes.string
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the video element.
|
||||
*
|
||||
@@ -62,6 +60,8 @@ class VideoTrack extends AbstractVideoTrack {
|
||||
videoTrack = { this.props.videoTrack } />
|
||||
);
|
||||
}
|
||||
|
||||
_onVideoPlaying: () => void;
|
||||
}
|
||||
|
||||
export default connect()(VideoTrack);
|
||||
|
||||
@@ -58,7 +58,7 @@ export function isVideoMutedByUser(stateful: Function | Object) {
|
||||
* otherwise, false.
|
||||
*/
|
||||
export function shouldRenderVideoTrack(
|
||||
videoTrack: { muted: boolean, videoStarted: boolean },
|
||||
videoTrack: ?{ muted: boolean, videoStarted: boolean },
|
||||
waitForVideoStarted: boolean) {
|
||||
return (
|
||||
videoTrack
|
||||
|
||||
@@ -146,11 +146,11 @@ export default class Avatar extends Component<Props, State> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this {@code Component} that it will be unmounted and destroyed
|
||||
* and, most importantly, that it should no longer call
|
||||
* {@link #setState(Object)}. {@code Avatar} needs it because it downloads
|
||||
* images via {@link ImageCache} which will asynchronously notify about
|
||||
* success.
|
||||
* Notifies this {@code Component} that it will be unmounted and destroyed,
|
||||
* and most importantly, that it should no longer call
|
||||
* {@link #setState(Object)}. The {@code Avatar} needs it because it
|
||||
* downloads images via {@link ImageCache} which will asynchronously notify
|
||||
* about success.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
|
||||
@@ -127,8 +127,9 @@ export function getParticipantCount(stateful: Object | Function) {
|
||||
|
||||
/**
|
||||
* Returns participant's display name.
|
||||
* FIXME: remove the hardcoded strings once interfaceConfig is stored in redux
|
||||
* and merge with a similarly named method in conference.js.
|
||||
*
|
||||
* FIXME: Remove the hardcoded strings once interfaceConfig is stored in redux
|
||||
* and merge with a similarly named method in {@code conference.js}.
|
||||
*
|
||||
* @param {(Function|Object)} stateful - The (whole) redux state, or redux's
|
||||
* {@code getState} function to be used to retrieve the state.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* @flow */
|
||||
|
||||
import InlineDialog from '@atlaskit/inline-dialog';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
/**
|
||||
@@ -28,13 +29,68 @@ function _mapPositionToPaddingClass(position = 'left') {
|
||||
return DIALOG_TO_PADDING_POSITION[position.split(' ')[0]];
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Popover}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* A child React Element to use as the trigger for showing the dialog.
|
||||
*/
|
||||
children: React$Node,
|
||||
|
||||
/**
|
||||
* Additional CSS classnames to apply to the root of the {@code Popover}
|
||||
* component.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* The ReactElement to display within the dialog.
|
||||
*/
|
||||
content: Object,
|
||||
|
||||
/**
|
||||
* Whether displaying of the popover should be prevented.
|
||||
*/
|
||||
disablePopover: boolean,
|
||||
|
||||
/**
|
||||
* An id attribute to apply to the root of the {@code Popover}
|
||||
* component.
|
||||
*/
|
||||
id: string,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the popover has opened.
|
||||
*/
|
||||
onPopoverOpen: Function,
|
||||
|
||||
/**
|
||||
* From which side of the dialog trigger the dialog should display. The
|
||||
* value will be passed to {@code InlineDialog}.
|
||||
*/
|
||||
position: string
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link Popover}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Whether or not the {@code InlineDialog} should be displayed.
|
||||
*/
|
||||
showDialog: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React {@code Component} for showing an {@code InlineDialog} on
|
||||
* mouseenter of the trigger and contents, and hiding the dialog on mouseleave.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class Popover extends Component {
|
||||
class Popover extends Component<Props, State> {
|
||||
/**
|
||||
* Default values for {@code Popover} component's properties.
|
||||
*
|
||||
@@ -45,66 +101,16 @@ class Popover extends Component {
|
||||
id: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* {@code Popover} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* A child React Element to use as the trigger for showing the dialog.
|
||||
*/
|
||||
children: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Additional CSS classnames to apply to the root of the {@code Popover}
|
||||
* component.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The ReactElement to display within the dialog.
|
||||
*/
|
||||
content: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Whether displaying of the popover should be prevented.
|
||||
*/
|
||||
disablePopover: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* An id attribute to apply to the root of the {@code Popover}
|
||||
* component.
|
||||
*/
|
||||
id: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the popover has opened.
|
||||
*/
|
||||
onPopoverOpen: PropTypes.func,
|
||||
|
||||
/**
|
||||
* From which side of the dialog trigger the dialog should display. The
|
||||
* value will be passed to {@code InlineDialog}.
|
||||
*/
|
||||
position: PropTypes.string
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes a new {@code Popover} instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
/**
|
||||
* Whether or not the {@code InlineDialog} should be displayed.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
showDialog: false
|
||||
};
|
||||
|
||||
@@ -136,6 +142,8 @@ class Popover extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onHideDialog: () => void;
|
||||
|
||||
/**
|
||||
* Stops displaying the {@code InlineDialog}.
|
||||
*
|
||||
@@ -146,6 +154,8 @@ class Popover extends Component {
|
||||
this.setState({ showDialog: false });
|
||||
}
|
||||
|
||||
_onShowDialog: () => void;
|
||||
|
||||
/**
|
||||
* Displays the {@code InlineDialog} and calls any registered onPopoverOpen
|
||||
* callbacks.
|
||||
|
||||
@@ -58,7 +58,6 @@ export type Props = {
|
||||
visible?: ?boolean
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Abstract (base) class for container of React {@link Component} children with
|
||||
* a style.
|
||||
|
||||
@@ -12,7 +12,7 @@ export default class AbstractPage<P> extends Component<P> {
|
||||
* content of the component.
|
||||
*
|
||||
* Note: It is a static method as the {@code Component} may not be
|
||||
* initialized yet when the UI invokes refresh (e.g. tab change).
|
||||
* initialized yet when the UI invokes refresh (e.g. Tab change).
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
@@ -91,8 +91,8 @@ class NavigateSectionList extends Component<Props> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's Component.render.
|
||||
* Note: we don't use the refreshing value yet, because refreshing of these
|
||||
* Implements React's {@code Component.render}.
|
||||
* Note: We don't use the refreshing value yet, because refreshing of these
|
||||
* lists is super quick, no need to complicate the code - yet.
|
||||
*
|
||||
* @inheritdoc
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { Linking } from 'react-native';
|
||||
|
||||
import Text from './Text';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Link}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The children to be displayed within this Link.
|
||||
*/
|
||||
children: React$Node,
|
||||
|
||||
/**
|
||||
* Notifies that this Link failed to open the URL associated with it.
|
||||
*/
|
||||
onLinkingOpenURLRejected: Function,
|
||||
|
||||
/**
|
||||
* The CSS style to be applied to this Link for the purposes of display.
|
||||
*/
|
||||
style: Object,
|
||||
|
||||
/**
|
||||
* The URL to be opened when this Link is clicked/pressed.
|
||||
*/
|
||||
url: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a (hyper)link to a URL in the fashion of the HTML anchor element
|
||||
* and its href attribute.
|
||||
*/
|
||||
export default class Link extends Component {
|
||||
/**
|
||||
* {@code Link} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The children to be displayed within this Link.
|
||||
*/
|
||||
children: PropTypes.node,
|
||||
|
||||
/**
|
||||
* Notifies that this Link failed to open the URL associated with it.
|
||||
*/
|
||||
onLinkingOpenURLRejected: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The CSS style to be applied to this Link for the purposes of display.
|
||||
*/
|
||||
style: PropTypes.object,
|
||||
|
||||
/**
|
||||
* The URL to be opened when this Link is clicked/pressed.
|
||||
*/
|
||||
url: PropTypes.string
|
||||
};
|
||||
|
||||
export default class Link extends Component<Props> {
|
||||
/**
|
||||
* Initializes a new Link instance.
|
||||
*
|
||||
* @param {Object} props - Component properties.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
@@ -77,6 +77,8 @@ export default class Link extends Component {
|
||||
onRejected && onRejected(reason);
|
||||
}
|
||||
|
||||
_onPress: () => void;
|
||||
|
||||
/**
|
||||
* Handles press on this Link. Opens the URL associated with this Link.
|
||||
*
|
||||
|
||||
@@ -9,13 +9,6 @@ import type { Props } from '../AbstractContainer';
|
||||
* @extends AbstractContainer
|
||||
*/
|
||||
export default class Container<P: Props> extends AbstractContainer<P> {
|
||||
/**
|
||||
* {@code Container} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = AbstractContainer.propTypes;
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,34 +1,32 @@
|
||||
/* @flow */
|
||||
|
||||
import Button from '@atlaskit/button';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../../i18n';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link InlineDialogFailure}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Allows to retry the call that previously didn't succeed.
|
||||
*/
|
||||
onRetry: Function,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* Inline dialog that represents a failure and allows a retry.
|
||||
*/
|
||||
class InlineDialogFailure extends Component<*> {
|
||||
/**
|
||||
* {@code InlineDialogFailure}'s property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Allows to retry the call that previously didn't succeed.
|
||||
*/
|
||||
onRetry: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class InlineDialogFailure extends Component<Props> {
|
||||
/**
|
||||
* Renders the content of this component.
|
||||
*
|
||||
|
||||
201
react/features/base/react/components/web/MeetingsList.js
Normal file
201
react/features/base/react/components/web/MeetingsList.js
Normal file
@@ -0,0 +1,201 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import {
|
||||
getLocalizedDateFormatter,
|
||||
getLocalizedDurationFormatter
|
||||
} from '../../../i18n';
|
||||
|
||||
import Container from './Container';
|
||||
import Text from './Text';
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Indicates if the list is disabled or not.
|
||||
*/
|
||||
disabled: boolean,
|
||||
|
||||
/**
|
||||
* Indicates if the URL should be hidden or not.
|
||||
*/
|
||||
hideURL: boolean,
|
||||
|
||||
/**
|
||||
* Function to be invoked when an item is pressed. The item's URL is passed.
|
||||
*/
|
||||
onPress: Function,
|
||||
|
||||
/**
|
||||
* Rendered when the list is empty. Should be a rendered element.
|
||||
*/
|
||||
listEmptyComponent: Object,
|
||||
|
||||
/**
|
||||
* An array of meetings.
|
||||
*/
|
||||
meetings: Array<Object>,
|
||||
|
||||
/**
|
||||
* Defines what happens when an item in the section list is clicked
|
||||
*/
|
||||
onItemClick: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a date string for a given date.
|
||||
*
|
||||
* @param {Object} date - The date.
|
||||
* @private
|
||||
* @returns {string}
|
||||
*/
|
||||
function _toDateString(date) {
|
||||
return getLocalizedDateFormatter(date).format('MMM Do, YYYY');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a time (interval) string for a given times.
|
||||
*
|
||||
* @param {Array<Date>} times - Array of times.
|
||||
* @private
|
||||
* @returns {string}
|
||||
*/
|
||||
function _toTimeString(times) {
|
||||
if (times && times.length > 0) {
|
||||
return (
|
||||
times
|
||||
.map(time => getLocalizedDateFormatter(time).format('LT'))
|
||||
.join(' - '));
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a React/Web {@link Component} for displaying a list with
|
||||
* meetings.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
export default class MeetingsList extends Component<Props> {
|
||||
/**
|
||||
* Constructor of the MeetingsList component.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this._onPress = this._onPress.bind(this);
|
||||
this._renderItem = this._renderItem.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the content of this component.
|
||||
*
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
render() {
|
||||
const { listEmptyComponent, meetings } = this.props;
|
||||
|
||||
/**
|
||||
* If there are no recent meetings we don't want to display anything
|
||||
*/
|
||||
if (meetings) {
|
||||
return (
|
||||
<Container
|
||||
className = 'meetings-list'>
|
||||
{
|
||||
meetings.length === 0
|
||||
? listEmptyComponent
|
||||
: meetings.map(this._renderItem)
|
||||
}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
_onPress: string => Function;
|
||||
|
||||
/**
|
||||
* Returns a function that is used in the onPress callback of the items.
|
||||
*
|
||||
* @param {string} url - The URL of the item to navigate to.
|
||||
* @private
|
||||
* @returns {Function}
|
||||
*/
|
||||
_onPress(url) {
|
||||
const { disabled, onPress } = this.props;
|
||||
|
||||
if (!disabled && url && typeof onPress === 'function') {
|
||||
return () => onPress(url);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
_renderItem: (Object, number) => React$Node;
|
||||
|
||||
/**
|
||||
* Renders an item for the list.
|
||||
*
|
||||
* @param {Object} meeting - Information about the meeting.
|
||||
* @param {number} index - The index of the item.
|
||||
* @returns {Node}
|
||||
*/
|
||||
_renderItem(meeting, index) {
|
||||
const {
|
||||
date,
|
||||
duration,
|
||||
elementAfter,
|
||||
time,
|
||||
title,
|
||||
url
|
||||
} = meeting;
|
||||
const { hideURL = false } = this.props;
|
||||
const onPress = this._onPress(url);
|
||||
const rootClassName
|
||||
= `item ${
|
||||
onPress ? 'with-click-handler' : 'without-click-handler'}`;
|
||||
|
||||
return (
|
||||
<Container
|
||||
className = { rootClassName }
|
||||
key = { index }
|
||||
onClick = { onPress }>
|
||||
<Container className = 'left-column'>
|
||||
<Text className = 'date'>
|
||||
{ _toDateString(date) }
|
||||
</Text>
|
||||
<Text>
|
||||
{ _toTimeString(time) }
|
||||
</Text>
|
||||
</Container>
|
||||
<Container className = 'right-column'>
|
||||
<Text className = 'title'>
|
||||
{ title }
|
||||
</Text>
|
||||
{
|
||||
hideURL || !url ? null : (
|
||||
<Text>
|
||||
{ url }
|
||||
</Text>)
|
||||
}
|
||||
{
|
||||
typeof duration === 'number' ? (
|
||||
<Text>
|
||||
{ getLocalizedDurationFormatter(duration) }
|
||||
</Text>) : null
|
||||
}
|
||||
</Container>
|
||||
<Container className = 'actions'>
|
||||
{ elementAfter || null }
|
||||
</Container>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
// @flow
|
||||
|
||||
import { MultiSelectStateless } from '@atlaskit/multi-select';
|
||||
import AKInlineDialog from '@atlaskit/inline-dialog';
|
||||
import _debounce from 'lodash/debounce';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import InlineDialogFailure from './InlineDialogFailure';
|
||||
@@ -9,118 +10,127 @@ import InlineDialogFailure from './InlineDialogFailure';
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
||||
/**
|
||||
* A MultiSelect that is also auto-completing.
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link MultiSelectAutocomplete}.
|
||||
*/
|
||||
class MultiSelectAutocomplete extends Component {
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* {@code MultiSelectAutocomplete} component's property types.
|
||||
*
|
||||
* @static
|
||||
* The default value of the selected item.
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The default value of the selected item.
|
||||
*/
|
||||
defaultValue: PropTypes.array,
|
||||
defaultValue: Array<Object>,
|
||||
|
||||
/**
|
||||
* Optional footer to show as a last element in the results.
|
||||
* Should be of type {content: <some content>}
|
||||
*/
|
||||
footer: PropTypes.object,
|
||||
/**
|
||||
* Optional footer to show as a last element in the results.
|
||||
* Should be of type {content: <some content>}
|
||||
*/
|
||||
footer: Object,
|
||||
|
||||
/**
|
||||
* Indicates if the component is disabled.
|
||||
*/
|
||||
isDisabled: PropTypes.bool,
|
||||
/**
|
||||
* Indicates if the component is disabled.
|
||||
*/
|
||||
isDisabled: boolean,
|
||||
|
||||
/**
|
||||
* Text to display while a query is executing.
|
||||
*/
|
||||
loadingMessage: PropTypes.string,
|
||||
/**
|
||||
* Text to display while a query is executing.
|
||||
*/
|
||||
loadingMessage: string,
|
||||
|
||||
/**
|
||||
* The text to show when no matches are found.
|
||||
*/
|
||||
noMatchesFound: PropTypes.string,
|
||||
/**
|
||||
* The text to show when no matches are found.
|
||||
*/
|
||||
noMatchesFound: string,
|
||||
|
||||
/**
|
||||
* The function called immediately before a selection has been actually
|
||||
* selected. Provides an opportunity to do any formatting.
|
||||
*/
|
||||
onItemSelected: PropTypes.func,
|
||||
/**
|
||||
* The function called immediately before a selection has been actually
|
||||
* selected. Provides an opportunity to do any formatting.
|
||||
*/
|
||||
onItemSelected: Function,
|
||||
|
||||
/**
|
||||
* The function called when the selection changes.
|
||||
*/
|
||||
onSelectionChange: PropTypes.func,
|
||||
/**
|
||||
* The function called when the selection changes.
|
||||
*/
|
||||
onSelectionChange: Function,
|
||||
|
||||
/**
|
||||
* The placeholder text of the input component.
|
||||
*/
|
||||
placeholder: PropTypes.string,
|
||||
/**
|
||||
* The placeholder text of the input component.
|
||||
*/
|
||||
placeholder: string,
|
||||
|
||||
/**
|
||||
* The service providing the search.
|
||||
*/
|
||||
resourceClient: PropTypes.shape({
|
||||
makeQuery: PropTypes.func,
|
||||
parseResults: PropTypes.func
|
||||
}).isRequired,
|
||||
/**
|
||||
* The service providing the search.
|
||||
*/
|
||||
resourceClient: { makeQuery: Function, parseResults: Function },
|
||||
|
||||
/**
|
||||
* Indicates if the component should fit the container.
|
||||
*/
|
||||
shouldFitContainer: PropTypes.bool,
|
||||
/**
|
||||
* Indicates if the component should fit the container.
|
||||
*/
|
||||
shouldFitContainer: boolean,
|
||||
|
||||
/**
|
||||
* Indicates if we should focus.
|
||||
*/
|
||||
shouldFocus: PropTypes.bool
|
||||
};
|
||||
/**
|
||||
* Indicates if we should focus.
|
||||
*/
|
||||
shouldFocus: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of
|
||||
* {@link MultiSelectAutocomplete}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Indicates if the dropdown is open.
|
||||
*/
|
||||
isOpen: boolean,
|
||||
|
||||
/**
|
||||
* The text that filters the query result of the search.
|
||||
*/
|
||||
filterValue: string,
|
||||
|
||||
/**
|
||||
* Indicates if the component is currently loading results.
|
||||
*/
|
||||
loading: boolean,
|
||||
|
||||
/**
|
||||
* Indicates if there was an error.
|
||||
*/
|
||||
error: boolean,
|
||||
|
||||
/**
|
||||
* The list of result items.
|
||||
*/
|
||||
items: Array<Object>,
|
||||
|
||||
/**
|
||||
* The list of selected items.
|
||||
*/
|
||||
selectedItems: Array<Object>
|
||||
};
|
||||
|
||||
/**
|
||||
* A MultiSelect that is also auto-completing.
|
||||
*/
|
||||
class MultiSelectAutocomplete extends Component<Props, State> {
|
||||
/**
|
||||
* Initializes a new {@code MultiSelectAutocomplete} instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
const defaultValue = this.props.defaultValue || [];
|
||||
|
||||
this.state = {
|
||||
/**
|
||||
* Indicates if the dropdown is open.
|
||||
*/
|
||||
isOpen: false,
|
||||
|
||||
/**
|
||||
* The text that filters the query result of the search.
|
||||
*/
|
||||
filterValue: '',
|
||||
|
||||
/**
|
||||
* Indicates if the component is currently loading results.
|
||||
*/
|
||||
loading: false,
|
||||
|
||||
|
||||
/**
|
||||
* Indicates if there was an error.
|
||||
*/
|
||||
error: false,
|
||||
|
||||
/**
|
||||
* The list of result items.
|
||||
*/
|
||||
items: [],
|
||||
|
||||
/**
|
||||
* The list of selected items.
|
||||
*/
|
||||
selectedItems: [ ...defaultValue ]
|
||||
};
|
||||
|
||||
@@ -137,7 +147,7 @@ class MultiSelectAutocomplete extends Component {
|
||||
* having been selected.
|
||||
* @returns {void}
|
||||
*/
|
||||
setSelectedItems(selectedItems = []) {
|
||||
setSelectedItems(selectedItems: Array<Object> = []) {
|
||||
this.setState({ selectedItems });
|
||||
}
|
||||
|
||||
@@ -177,6 +187,8 @@ class MultiSelectAutocomplete extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onFilterChange: (string) => void;
|
||||
|
||||
/**
|
||||
* Sets the state and sends a query on filter change.
|
||||
*
|
||||
@@ -198,6 +210,8 @@ class MultiSelectAutocomplete extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
_onRetry: () => void;
|
||||
|
||||
/**
|
||||
* Retries the query on retry.
|
||||
*
|
||||
@@ -208,6 +222,8 @@ class MultiSelectAutocomplete extends Component {
|
||||
this._sendQuery(this.state.filterValue);
|
||||
}
|
||||
|
||||
_onSelectionChange: (Object) => void;
|
||||
|
||||
/**
|
||||
* Updates the selected items when a selection event occurs.
|
||||
*
|
||||
@@ -258,6 +274,8 @@ class MultiSelectAutocomplete extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_sendQuery: (string) => void;
|
||||
|
||||
/**
|
||||
* Sends a query to the resourceClient.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -17,32 +16,71 @@ const _RIGHT_WATERMARK_STYLE = {
|
||||
backgroundImage: 'url(images/rightwatermark.png)'
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Watermarks}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Whether or not the current user is logged in through a JWT.
|
||||
*/
|
||||
_isGuest: boolean,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link Watermarks}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The url to open when clicking the brand watermark.
|
||||
*/
|
||||
brandWatermarkLink: string,
|
||||
|
||||
/**
|
||||
* The url to open when clicking the Jitsi watermark.
|
||||
*/
|
||||
jitsiWatermarkLink: string,
|
||||
|
||||
/**
|
||||
* Whether or not the brand watermark should be displayed.
|
||||
*/
|
||||
showBrandWatermark: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the Jitsi watermark should be displayed.
|
||||
*/
|
||||
showJitsiWatermark: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the Jitsi watermark should be displayed for users not
|
||||
* logged in through a JWT.
|
||||
*/
|
||||
showJitsiWatermarkForGuests: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the show the "powered by Jitsi.org" link.
|
||||
*/
|
||||
showPoweredBy: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* A Web Component which renders watermarks such as Jits, brand, powered by,
|
||||
* etc.
|
||||
*/
|
||||
class Watermarks extends Component<*, *> {
|
||||
static propTypes = {
|
||||
_isGuest: PropTypes.bool,
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
state = {
|
||||
brandWatermarkLink: String,
|
||||
jitsiWatermarkLink: String,
|
||||
showBrandWatermark: Boolean,
|
||||
showJitsiWatermark: Boolean,
|
||||
showJitsiWatermarkForGuests: Boolean,
|
||||
showPoweredBy: Boolean
|
||||
};
|
||||
|
||||
class Watermarks extends Component<Props, State> {
|
||||
/**
|
||||
* Initializes a new Watermarks instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props: Object) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
let showBrandWatermark;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export { default as Container } from './Container';
|
||||
export { default as LoadingIndicator } from './LoadingIndicator';
|
||||
export { default as MeetingsList } from './MeetingsList';
|
||||
export { default as MultiSelectAutocomplete } from './MultiSelectAutocomplete';
|
||||
export { default as NavigateSectionListEmptyComponent } from
|
||||
'./NavigateSectionListEmptyComponent';
|
||||
|
||||
@@ -113,7 +113,7 @@ function _set(
|
||||
|
||||
/**
|
||||
* Returns redux state from the specified {@code stateful} which is presumed to
|
||||
* be related to the redux state (e.g. the redux store, the redux
|
||||
* be related to the redux state (e.g. The redux store, the redux
|
||||
* {@code getState} function).
|
||||
*
|
||||
* @param {Function|Object} stateful - The entity such as the redux store or the
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
// @flow
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from '../constants';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AspectRatioAware}.
|
||||
*/
|
||||
type Props = {
|
||||
aspectRatio: ASPECT_RATIO_NARROW | ASPECT_RATIO_WIDE
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether a specific React {@code Component} decorated into an
|
||||
* {@link AspectRatioAware} has {@link ASPECT_RATIO_NARROW} as the value of its
|
||||
@@ -34,20 +40,7 @@ export function makeAspectRatioAware(
|
||||
/**
|
||||
* Renders {@code WrappedComponent} with the React prop {@code aspectRatio}.
|
||||
*/
|
||||
class AspectRatioAware extends Component<*> {
|
||||
/**
|
||||
* Properties of the aspect ratio aware wrapper.
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Either {@link ASPECT_RATIO_NARROW} or {@link ASPECT_RATIO_WIDE}.
|
||||
*/
|
||||
aspectRatio: PropTypes.oneOf([
|
||||
ASPECT_RATIO_NARROW,
|
||||
ASPECT_RATIO_WIDE
|
||||
])
|
||||
}
|
||||
|
||||
class AspectRatioAware extends Component<Props> {
|
||||
/**
|
||||
* Implement's React render method to wrap the nested component.
|
||||
*
|
||||
|
||||
@@ -57,7 +57,7 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
|
||||
* Retrieves the legacy profile values regardless of it's being in pre or
|
||||
* post-flattening format.
|
||||
*
|
||||
* FIXME: Let's remove this after a predefined time (e.g. by July 2018) to avoid
|
||||
* FIXME: Let's remove this after a predefined time (e.g. By July 2018) to avoid
|
||||
* garbage in the source.
|
||||
*
|
||||
* @private
|
||||
|
||||
@@ -73,7 +73,7 @@ export default class Storage {
|
||||
* Returns the value associated with a specific key in this {@code Storage}
|
||||
* in an async manner. The method is required for the cases where we need
|
||||
* the stored data but we're not sure yet whether this {@code Storage} is
|
||||
* already initialized (e.g. on app start).
|
||||
* already initialized (e.g. On app start).
|
||||
*
|
||||
* @param {string} key - The name of the key to retrieve the value of.
|
||||
* @returns {Promise}
|
||||
|
||||
@@ -418,7 +418,7 @@ function _addTracks(tracks) {
|
||||
* @returns {Promise} - A {@code Promise} resolved once all
|
||||
* {@code gumProcess.cancel()} {@code Promise}s are settled because all we care
|
||||
* about here is to be sure that the {@code getUserMedia} callbacks have
|
||||
* completed (i.e. returned from the native side).
|
||||
* completed (i.e. Returned from the native side).
|
||||
*/
|
||||
function _cancelGUMProcesses(getState) {
|
||||
const logError
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import Button from '@atlaskit/button';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import Tooltip from '@atlaskit/tooltip';
|
||||
@@ -65,12 +64,11 @@ class AddMeetingUrlButton extends Component<Props> {
|
||||
render() {
|
||||
return (
|
||||
<Tooltip content = { this.props.t('calendarSync.addMeetingURL') }>
|
||||
<Button
|
||||
appearance = 'primary'
|
||||
onClick = { this._onClick }
|
||||
type = 'button'>
|
||||
<div
|
||||
className = 'button add-button'
|
||||
onClick = { this._onClick }>
|
||||
<i className = { 'icon-add' } />
|
||||
</Button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
@@ -92,4 +90,3 @@ class AddMeetingUrlButton extends Component<Props> {
|
||||
}
|
||||
|
||||
export default translate(connect()(AddMeetingUrlButton));
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ class CalendarList extends AbstractPage<Props> {
|
||||
CalendarListContent
|
||||
? <CalendarListContent
|
||||
disabled = { disabled }
|
||||
renderListEmptyComponent
|
||||
listEmptyComponent
|
||||
= { this._getRenderListEmptyComponent() } />
|
||||
: null
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import Button from '@atlaskit/button';
|
||||
import Spinner from '@atlaskit/spinner';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
@@ -82,7 +81,7 @@ class CalendarList extends AbstractPage<Props> {
|
||||
CalendarListContent
|
||||
? <CalendarListContent
|
||||
disabled = { disabled }
|
||||
renderListEmptyComponent
|
||||
listEmptyComponent
|
||||
= { this._getRenderListEmptyComponent() } />
|
||||
: null
|
||||
);
|
||||
@@ -102,21 +101,18 @@ class CalendarList extends AbstractPage<Props> {
|
||||
|
||||
if (_hasIntegrationSelected && _hasLoadedEvents) {
|
||||
return (
|
||||
<div className = 'navigate-section-list-empty'>
|
||||
<div className = 'meetings-list-empty'>
|
||||
<div>{ t('calendarSync.noEvents') }</div>
|
||||
<Button
|
||||
appearance = 'primary'
|
||||
className = 'calendar-button'
|
||||
id = 'connect_calendar_button'
|
||||
onClick = { this._onRefreshEvents }
|
||||
type = 'button'>
|
||||
<div
|
||||
className = 'button'
|
||||
onClick = { this._onRefreshEvents }>
|
||||
{ t('calendarSync.refresh') }
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (_hasIntegrationSelected && !_hasLoadedEvents) {
|
||||
return (
|
||||
<div className = 'navigate-section-list-empty'>
|
||||
<div className = 'meetings-list-empty'>
|
||||
<Spinner
|
||||
invertColor = { true }
|
||||
isCompleting = { false }
|
||||
@@ -126,20 +122,17 @@ class CalendarList extends AbstractPage<Props> {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className = 'navigate-section-list-empty'>
|
||||
<p className = 'header-text-description'>
|
||||
<div className = 'meetings-list-empty'>
|
||||
<p className = 'description'>
|
||||
{ t('welcomepage.connectCalendarText', {
|
||||
app: interfaceConfig.APP_NAME
|
||||
}) }
|
||||
</p>
|
||||
<Button
|
||||
appearance = 'primary'
|
||||
className = 'calendar-button'
|
||||
id = 'connect_calendar_button'
|
||||
onClick = { this._onOpenSettings }
|
||||
type = 'button'>
|
||||
<div
|
||||
className = 'button'
|
||||
onClick = { this._onOpenSettings }>
|
||||
{ t('welcomepage.connectCalendarButton') }
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@ import { NavigateSectionList } from '../../base/react';
|
||||
import { refreshCalendar, openUpdateCalendarEventDialog } from '../actions';
|
||||
import { isCalendarEnabled } from '../functions';
|
||||
|
||||
import AddMeetingUrlButton from './AddMeetingUrlButton';
|
||||
import JoinButton from './JoinButton';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
@@ -42,7 +40,7 @@ type Props = {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
renderListEmptyComponent: Function,
|
||||
listEmptyComponent: React$Node,
|
||||
|
||||
/**
|
||||
* The translate function.
|
||||
@@ -70,7 +68,6 @@ class CalendarListContent extends Component<Props> {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
this._onJoinPress = this._onJoinPress.bind(this);
|
||||
this._onPress = this._onPress.bind(this);
|
||||
this._onRefresh = this._onRefresh.bind(this);
|
||||
this._onSecondaryAction = this._onSecondaryAction.bind(this);
|
||||
@@ -97,7 +94,7 @@ class CalendarListContent extends Component<Props> {
|
||||
* @inheritdoc
|
||||
*/
|
||||
render() {
|
||||
const { disabled, renderListEmptyComponent } = this.props;
|
||||
const { disabled, listEmptyComponent } = this.props;
|
||||
|
||||
return (
|
||||
<NavigateSectionList
|
||||
@@ -106,27 +103,11 @@ class CalendarListContent extends Component<Props> {
|
||||
onRefresh = { this._onRefresh }
|
||||
onSecondaryAction = { this._onSecondaryAction }
|
||||
renderListEmptyComponent
|
||||
= { renderListEmptyComponent }
|
||||
= { listEmptyComponent }
|
||||
sections = { this._toDisplayableList() } />
|
||||
);
|
||||
}
|
||||
|
||||
_onJoinPress: (Object, string) => Function;
|
||||
|
||||
/**
|
||||
* Handles the list's navigate action.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} event - The click event.
|
||||
* @param {string} url - The url string to navigate to.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onJoinPress(event, url) {
|
||||
event.stopPropagation();
|
||||
|
||||
this._onPress(url, 'calendar.meeting.join');
|
||||
}
|
||||
|
||||
_onPress: (string, string) => Function;
|
||||
|
||||
/**
|
||||
@@ -134,7 +115,7 @@ class CalendarListContent extends Component<Props> {
|
||||
*
|
||||
* @private
|
||||
* @param {string} url - The url string to navigate to.
|
||||
* @param {string} analyticsEventName - Тhe name of the analytics event.
|
||||
* @param {string} analyticsEventName - Тhe name of the analytics event
|
||||
* associated with this action.
|
||||
* @returns {void}
|
||||
*/
|
||||
@@ -197,13 +178,6 @@ class CalendarListContent extends Component<Props> {
|
||||
*/
|
||||
_toDisplayableItem(event) {
|
||||
return {
|
||||
elementAfter: event.url
|
||||
? <JoinButton
|
||||
onPress = { this._onJoinPress }
|
||||
url = { event.url } />
|
||||
: (<AddMeetingUrlButton
|
||||
calendarId = { event.calendarId }
|
||||
eventId = { event.id } />),
|
||||
id: event.id,
|
||||
key: `${event.id}-${event.startDate}`,
|
||||
lines: [
|
||||
@@ -0,0 +1,177 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { appNavigate } from '../../app';
|
||||
import {
|
||||
createCalendarClickedEvent,
|
||||
createCalendarSelectedEvent,
|
||||
sendAnalytics
|
||||
} from '../../analytics';
|
||||
import { MeetingsList } from '../../base/react';
|
||||
|
||||
import { isCalendarEnabled } from '../functions';
|
||||
|
||||
import AddMeetingUrlButton from './AddMeetingUrlButton';
|
||||
import JoinButton from './JoinButton';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link CalendarListContent}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The calendar event list.
|
||||
*/
|
||||
_eventList: Array<Object>,
|
||||
|
||||
/**
|
||||
* Indicates if the list is disabled or not.
|
||||
*/
|
||||
disabled: boolean,
|
||||
|
||||
/**
|
||||
* The Redux dispatch function.
|
||||
*/
|
||||
dispatch: Function,
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
listEmptyComponent: React$Node,
|
||||
};
|
||||
|
||||
/**
|
||||
* Component to display a list of events from a connected calendar.
|
||||
*/
|
||||
class CalendarListContent extends Component<Props> {
|
||||
/**
|
||||
* Default values for the component's props.
|
||||
*/
|
||||
static defaultProps = {
|
||||
_eventList: []
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes a new {@code CalendarListContent} instance.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
this._onJoinPress = this._onJoinPress.bind(this);
|
||||
this._onPress = this._onPress.bind(this);
|
||||
this._toDisplayableItem = this._toDisplayableItem.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#componentDidMount()}. Invoked
|
||||
* immediately after this component is mounted.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidMount() {
|
||||
sendAnalytics(createCalendarSelectedEvent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
render() {
|
||||
const { disabled, listEmptyComponent } = this.props;
|
||||
const { _eventList = [] } = this.props;
|
||||
const meetings = _eventList.map(this._toDisplayableItem);
|
||||
|
||||
return (
|
||||
<MeetingsList
|
||||
disabled = { disabled }
|
||||
listEmptyComponent = { listEmptyComponent }
|
||||
meetings = { meetings }
|
||||
onPress = { this._onPress } />
|
||||
);
|
||||
}
|
||||
|
||||
_onJoinPress: (Object, string) => Function;
|
||||
|
||||
/**
|
||||
* Handles the list's navigate action.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} event - The click event.
|
||||
* @param {string} url - The url string to navigate to.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onJoinPress(event, url) {
|
||||
event.stopPropagation();
|
||||
|
||||
this._onPress(url, 'calendar.meeting.join');
|
||||
}
|
||||
|
||||
_onPress: (string, string) => Function;
|
||||
|
||||
/**
|
||||
* Handles the list's navigate action.
|
||||
*
|
||||
* @private
|
||||
* @param {string} url - The url string to navigate to.
|
||||
* @param {string} analyticsEventName - Тhe name of the analytics event
|
||||
* associated with this action.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onPress(url, analyticsEventName = 'calendar.meeting.tile') {
|
||||
sendAnalytics(createCalendarClickedEvent(analyticsEventName));
|
||||
|
||||
this.props.dispatch(appNavigate(url));
|
||||
}
|
||||
|
||||
_toDisplayableItem: Object => Object;
|
||||
|
||||
/**
|
||||
* Creates a displayable object from an event.
|
||||
*
|
||||
* @param {Object} event - The calendar event.
|
||||
* @private
|
||||
* @returns {Object}
|
||||
*/
|
||||
_toDisplayableItem(event) {
|
||||
return {
|
||||
elementAfter: event.url
|
||||
? <JoinButton
|
||||
onPress = { this._onJoinPress }
|
||||
url = { event.url } />
|
||||
: (<AddMeetingUrlButton
|
||||
calendarId = { event.calendarId }
|
||||
eventId = { event.id } />),
|
||||
date: event.startDate,
|
||||
time: [ event.startDate, event.endDate ],
|
||||
description: event.url,
|
||||
title: event.title,
|
||||
url: event.url
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps redux state to component props.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {{
|
||||
* _eventList: Array<Object>
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state: Object) {
|
||||
return {
|
||||
_eventList: state['features/calendar-sync'].events
|
||||
};
|
||||
}
|
||||
|
||||
export default isCalendarEnabled()
|
||||
? connect(_mapStateToProps)(CalendarListContent)
|
||||
: undefined;
|
||||
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import Button from '@atlaskit/button';
|
||||
import React, { Component } from 'react';
|
||||
import Tooltip from '@atlaskit/tooltip';
|
||||
|
||||
@@ -58,13 +57,11 @@ class JoinButton extends Component<Props> {
|
||||
return (
|
||||
<Tooltip
|
||||
content = { t('calendarSync.joinTooltip') }>
|
||||
<Button
|
||||
appearance = 'primary'
|
||||
className = 'join-button'
|
||||
onClick = { this._onClick }
|
||||
type = 'button'>
|
||||
<div
|
||||
className = 'button join-button'
|
||||
onClick = { this._onClick }>
|
||||
{ t('calendarSync.join') }
|
||||
</Button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
@@ -84,4 +81,3 @@ class JoinButton extends Component<Props> {
|
||||
}
|
||||
|
||||
export default translate(JoinButton);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ function _isDisplayableCalendarEntry(entry) {
|
||||
/**
|
||||
* Updates the calendar entries in redux when new list is received. The feature
|
||||
* calendar-sync doesn't display all calendar events, it displays unique
|
||||
* title, URL, and start time tuples i.e. it doesn't display subsequent
|
||||
* title, URL, and start time tuples, and it doesn't display subsequent
|
||||
* occurrences of recurring events, and the repetitions of events coming from
|
||||
* multiple calendars.
|
||||
*
|
||||
|
||||
@@ -433,9 +433,9 @@ function _mapDispatchToProps(dispatch) {
|
||||
/**
|
||||
* Dispatches an action changing the visibility of the {@link Toolbox}.
|
||||
*
|
||||
* @param {boolean} visible - {@code true} to show the {@code Toolbox}
|
||||
* or {@code false} to hide it.
|
||||
* @private
|
||||
* @param {boolean} visible - Pass {@code true} to show the
|
||||
* {@code Toolbox} or {@code false} to hide it.
|
||||
* @returns {void}
|
||||
*/
|
||||
_setToolboxVisible(visible) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* global interfaceConfig */
|
||||
/* @flow */
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
@@ -10,6 +9,8 @@ import { ConnectionStatsTable } from '../../connection-stats';
|
||||
|
||||
import statsEmitter from '../statsEmitter';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The connection quality percentage that must be reached to be considered of
|
||||
* good quality and can result in the connection indicator being hidden.
|
||||
@@ -25,7 +26,7 @@ const INDICATOR_DISPLAY_THRESHOLD = 30;
|
||||
*
|
||||
* @type {Object[]}
|
||||
*/
|
||||
const QUALITY_TO_WIDTH = [
|
||||
const QUALITY_TO_WIDTH: Array<Object> = [
|
||||
|
||||
// Full (3 bars)
|
||||
{
|
||||
@@ -54,108 +55,107 @@ const QUALITY_TO_WIDTH = [
|
||||
// Note: we never show 0 bars as long as there is a connection.
|
||||
];
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link ConnectionIndicator}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Whether or not the component should ignore setting a visibility class for
|
||||
* hiding the component when the connection quality is not strong.
|
||||
*/
|
||||
alwaysVisible: boolean,
|
||||
|
||||
/**
|
||||
* The current condition of the user's connection, matching one of the
|
||||
* enumerated values in the library.
|
||||
*/
|
||||
connectionStatus: string,
|
||||
|
||||
/**
|
||||
* Whether or not clicking the indicator should display a popover for more
|
||||
* details.
|
||||
*/
|
||||
enableStatsDisplay: boolean,
|
||||
|
||||
/**
|
||||
* The font-size for the icon.
|
||||
*/
|
||||
iconSize: number,
|
||||
|
||||
/**
|
||||
* Whether or not the displays stats are for local video.
|
||||
*/
|
||||
isLocalVideo: boolean,
|
||||
|
||||
/**
|
||||
* Relative to the icon from where the popover for more connection details
|
||||
* should display.
|
||||
*/
|
||||
statsPopoverPosition: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function,
|
||||
|
||||
/**
|
||||
* The user ID associated with the displayed connection indication and
|
||||
* stats.
|
||||
*/
|
||||
userID: string
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link ConnectionIndicator}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The timeout for automatically hiding the indicator.
|
||||
*/
|
||||
autoHideTimeout: TimeoutID | null,
|
||||
|
||||
/**
|
||||
* Whether or not a CSS class should be applied to the root for hiding the
|
||||
* connection indicator. By default the indicator should start out hidden
|
||||
* because the current connection status is not known at mount.
|
||||
*/
|
||||
showIndicator: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the popover content should display additional statistics.
|
||||
*/
|
||||
showMoreStats: boolean,
|
||||
|
||||
/**
|
||||
* Cache of the stats received from subscribing to stats emitting. The keys
|
||||
* should be the name of the stat. With each stat update, updates stats are
|
||||
* mixed in with cached stats and a new stats object is set in state.
|
||||
*/
|
||||
stats: Object
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React {@link Component} which displays the current connection
|
||||
* quality percentage and has a popover to show more detailed connection stats.
|
||||
*
|
||||
* @extends {Component}
|
||||
*/
|
||||
class ConnectionIndicator extends Component {
|
||||
/**
|
||||
* {@code ConnectionIndicator} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Whether or not the component should ignore setting a visibility class
|
||||
* for hiding the component when the connection quality is not strong.
|
||||
*/
|
||||
alwaysVisible: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The current condition of the user's connection, matching one of the
|
||||
* enumerated values in the library.
|
||||
*
|
||||
* @type {JitsiParticipantConnectionStatus}
|
||||
*/
|
||||
connectionStatus: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Whether or not clicking the indicator should display a popover for
|
||||
* more details.
|
||||
*/
|
||||
enableStatsDisplay: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The font-size for the icon.
|
||||
*/
|
||||
iconSize: PropTypes.number,
|
||||
|
||||
/**
|
||||
* Whether or not the displays stats are for local video.
|
||||
*/
|
||||
isLocalVideo: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Relative to the icon from where the popover for more connection
|
||||
* details should display.
|
||||
*/
|
||||
statsPopoverPosition: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The user ID associated with the displayed connection indication and
|
||||
* stats.
|
||||
*/
|
||||
userID: PropTypes.string
|
||||
};
|
||||
|
||||
class ConnectionIndicator extends Component<Props, State> {
|
||||
/**
|
||||
* Initializes a new {@code ConnectionIndicator} instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
/**
|
||||
* The timeout for automatically hiding the indicator.
|
||||
*
|
||||
* @type {timeoutID}
|
||||
*/
|
||||
autoHideTimeout: null,
|
||||
|
||||
/**
|
||||
* Whether or not a CSS class should be applied to the root for
|
||||
* hiding the connection indicator. By default the indicator should
|
||||
* start out hidden because the current connection status is not
|
||||
* known at mount.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
showIndicator: false,
|
||||
|
||||
/**
|
||||
* Whether or not the popover content should display additional
|
||||
* statistics.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
showMoreStats: false,
|
||||
|
||||
/**
|
||||
* Cache of the stats received from subscribing to stats emitting.
|
||||
* The keys should be the name of the stat. With each stat update,
|
||||
* updates stats are mixed in with cached stats and a new stats
|
||||
* object is set in state.
|
||||
*/
|
||||
stats: {}
|
||||
};
|
||||
|
||||
@@ -201,7 +201,9 @@ class ConnectionIndicator extends Component {
|
||||
statsEmitter.unsubscribeToClientStats(
|
||||
this.props.userID, this._onStatsUpdated);
|
||||
|
||||
clearTimeout(this.state.autoHideTimeout);
|
||||
if (this.state.autoHideTimeout) {
|
||||
clearTimeout(this.state.autoHideTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,7 +259,7 @@ class ConnectionIndicator extends Component {
|
||||
return 'status-high';
|
||||
}
|
||||
|
||||
return QUALITY_TO_WIDTH.find(x => percent >= x.percent).colorClass;
|
||||
return this._getDisplayConfiguration(percent).colorClass;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,7 +289,7 @@ class ConnectionIndicator extends Component {
|
||||
// established so far. Assume a strong connection to start.
|
||||
tipKey = 'connectionindicator.quality.good';
|
||||
} else {
|
||||
const config = QUALITY_TO_WIDTH.find(x => percent >= x.percent);
|
||||
const config = this._getDisplayConfiguration(percent);
|
||||
|
||||
tipKey = config.tip;
|
||||
}
|
||||
@@ -297,6 +299,21 @@ class ConnectionIndicator extends Component {
|
||||
return this.props.t(tipKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon configuration from QUALITY_TO_WIDTH which has a percentage
|
||||
* that matches or exceeds the passed in percentage. The implementation
|
||||
* assumes QUALITY_TO_WIDTH is already sorted by highest to lowest
|
||||
* percentage.
|
||||
*
|
||||
* @param {number} percent - The connection percentage, out of 100, to find
|
||||
* the closest matching configuration for.
|
||||
* @private
|
||||
* @returns {Object}
|
||||
*/
|
||||
_getDisplayConfiguration(percent: number): Object {
|
||||
return QUALITY_TO_WIDTH.find(x => percent >= x.percent) || {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns additional class names to add to the root of the component. The
|
||||
* class names are intended to be used for hiding or showing the indicator.
|
||||
@@ -314,6 +331,8 @@ class ConnectionIndicator extends Component {
|
||||
? 'show-connection-indicator' : 'hide-connection-indicator';
|
||||
}
|
||||
|
||||
_onStatsUpdated: (Object) => void;
|
||||
|
||||
/**
|
||||
* Callback invoked when new connection stats associated with the passed in
|
||||
* user ID are available. Will update the component's display of current
|
||||
@@ -341,6 +360,8 @@ class ConnectionIndicator extends Component {
|
||||
this._updateIndicatorAutoHide(newStats.percent);
|
||||
}
|
||||
|
||||
_onToggleShowMore: () => void;
|
||||
|
||||
/**
|
||||
* Callback to invoke when the show more link in the popover content is
|
||||
* clicked. Sets the state which will determine if the popover should show
|
||||
@@ -383,7 +404,7 @@ class ConnectionIndicator extends Component {
|
||||
} else {
|
||||
const { percent } = this.state.stats;
|
||||
|
||||
iconWidth = QUALITY_TO_WIDTH.find(x => percent >= x.percent).width;
|
||||
iconWidth = this._getDisplayConfiguration(percent).width;
|
||||
}
|
||||
|
||||
return [
|
||||
@@ -449,7 +470,10 @@ class ConnectionIndicator extends Component {
|
||||
*/
|
||||
_updateIndicatorAutoHide(percent) {
|
||||
if (percent < INDICATOR_DISPLAY_THRESHOLD) {
|
||||
clearTimeout(this.state.autoHideTimeout);
|
||||
if (this.state.autoHideTimeout) {
|
||||
clearTimeout(this.state.autoHideTimeout);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
autoHideTimeout: null,
|
||||
showIndicator: true
|
||||
|
||||
@@ -1,119 +1,120 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link ConnectionStatsTable}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Statistics related to bandwidth.
|
||||
* {{
|
||||
* download: Number,
|
||||
* upload: Number
|
||||
* }}
|
||||
*/
|
||||
bandwidth: Object,
|
||||
|
||||
/**
|
||||
* Statistics related to bitrate.
|
||||
* {{
|
||||
* download: Number,
|
||||
* upload: Number
|
||||
* }}
|
||||
*/
|
||||
bitrate: Object,
|
||||
|
||||
/**
|
||||
* The number of bridges (aka media servers) currently used in the
|
||||
* conference.
|
||||
*/
|
||||
bridgeCount: number,
|
||||
|
||||
/**
|
||||
* A message describing the connection quality.
|
||||
*/
|
||||
connectionSummary: string,
|
||||
|
||||
/**
|
||||
* The end-to-end round-trip-time.
|
||||
*/
|
||||
e2eRtt: number,
|
||||
|
||||
/**
|
||||
* Statistics related to frame rates for each ssrc.
|
||||
* {{
|
||||
* [ ssrc ]: Number
|
||||
* }}
|
||||
*/
|
||||
framerate: Object,
|
||||
|
||||
/**
|
||||
* Whether or not the statistics are for local video.
|
||||
*/
|
||||
isLocalVideo: boolean,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the show additional stats link is clicked.
|
||||
*/
|
||||
onShowMore: Function,
|
||||
|
||||
/**
|
||||
* Statistics related to packet loss.
|
||||
* {{
|
||||
* download: Number,
|
||||
* upload: Number
|
||||
* }}
|
||||
*/
|
||||
packetLoss: Object,
|
||||
|
||||
/**
|
||||
* The region that we think the client is in.
|
||||
*/
|
||||
region: string,
|
||||
|
||||
/**
|
||||
* Statistics related to display resolutions for each ssrc.
|
||||
* {{
|
||||
* [ ssrc ]: {
|
||||
* height: Number,
|
||||
* width: Number
|
||||
* }
|
||||
* }}
|
||||
*/
|
||||
resolution: Object,
|
||||
|
||||
/**
|
||||
* The region of the media server that we are connected to.
|
||||
*/
|
||||
serverRegion: string,
|
||||
|
||||
/**
|
||||
* Whether or not additional stats about bandwidth and transport should be
|
||||
* displayed. Will not display even if true for remote participants.
|
||||
*/
|
||||
shouldShowMore: boolean,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function,
|
||||
|
||||
/**
|
||||
* Statistics related to transports.
|
||||
*/
|
||||
transport: Array<Object>
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for displaying connection statistics.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class ConnectionStatsTable extends Component {
|
||||
/**
|
||||
* {@code ConnectionStatsTable} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Statistics related to bandwidth.
|
||||
* {{
|
||||
* download: Number,
|
||||
* upload: Number
|
||||
* }}
|
||||
*/
|
||||
bandwidth: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Statistics related to bitrate.
|
||||
* {{
|
||||
* download: Number,
|
||||
* upload: Number
|
||||
* }}
|
||||
*/
|
||||
bitrate: PropTypes.object,
|
||||
|
||||
/**
|
||||
* The number of bridges (aka media servers) currently used in the
|
||||
* conference.
|
||||
*/
|
||||
bridgeCount: PropTypes.number,
|
||||
|
||||
/**
|
||||
* A message describing the connection quality.
|
||||
*/
|
||||
connectionSummary: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The end-to-end round-trip-time.
|
||||
*/
|
||||
e2eRtt: PropTypes.number,
|
||||
|
||||
/**
|
||||
* Statistics related to frame rates for each ssrc.
|
||||
* {{
|
||||
* [ ssrc ]: Number
|
||||
* }}
|
||||
*/
|
||||
framerate: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Whether or not the statistics are for local video.
|
||||
*/
|
||||
isLocalVideo: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the show additional stats link is clicked.
|
||||
*/
|
||||
onShowMore: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Statistics related to packet loss.
|
||||
* {{
|
||||
* download: Number,
|
||||
* upload: Number
|
||||
* }}
|
||||
*/
|
||||
packetLoss: PropTypes.object,
|
||||
|
||||
/**
|
||||
* The region that we think the client is in.
|
||||
*/
|
||||
region: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Statistics related to display resolutions for each ssrc.
|
||||
* {{
|
||||
* [ ssrc ]: {
|
||||
* height: Number,
|
||||
* width: Number
|
||||
* }
|
||||
* }}
|
||||
*/
|
||||
resolution: PropTypes.object,
|
||||
|
||||
/**
|
||||
* The region of the media server that we are connected to.
|
||||
*/
|
||||
serverRegion: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Whether or not additional stats about bandwidth and transport should
|
||||
* be displayed. Will not display even if true for remote participants.
|
||||
*/
|
||||
shouldShowMore: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Statistics related to transports.
|
||||
*/
|
||||
transport: PropTypes.array
|
||||
};
|
||||
|
||||
class ConnectionStatsTable extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
@@ -574,7 +575,7 @@ class ConnectionStatsTable extends Component {
|
||||
* @private
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderTransportTableRow(config) {
|
||||
_renderTransportTableRow(config: Object) {
|
||||
const { additionalData, data, key, label } = config;
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -34,32 +33,43 @@ const _URLS = {
|
||||
ios: interfaceConfig.MOBILE_DOWNLOAD_LINK_IOS
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link DeepLinkingMobilePage}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The name of the conference attempting to being joined.
|
||||
*/
|
||||
_room: string,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of
|
||||
* {@link DeepLinkingMobilePage}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The URL to link to on the button for opening the mobile app.
|
||||
*/
|
||||
joinURL: string
|
||||
};
|
||||
|
||||
/**
|
||||
* React component representing mobile browser page.
|
||||
*
|
||||
* @class DeepLinkingMobilePage
|
||||
*/
|
||||
class DeepLinkingMobilePage extends Component<*, *> {
|
||||
state: Object;
|
||||
|
||||
/**
|
||||
* DeepLinkingMobilePage component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The name of the conference attempting to being joined.
|
||||
*/
|
||||
_room: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {Function}
|
||||
*/
|
||||
t: PropTypes.func
|
||||
class DeepLinkingMobilePage extends Component<Props, State> {
|
||||
state = {
|
||||
joinURL: ''
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -68,7 +78,7 @@ class DeepLinkingMobilePage extends Component<*, *> {
|
||||
* @param {Object} props - The read-only React {@code Component} props with
|
||||
* which the new instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import Tabs from '@atlaskit/tabs';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -42,41 +41,65 @@ const TAB_LABELS = {
|
||||
|
||||
const VALID_TYPES = Object.keys(TAB_LABELS);
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link DesktopPicker}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* An array with desktop sharing sources to be displayed.
|
||||
*/
|
||||
desktopSharingSources: Array<string>,
|
||||
|
||||
/**
|
||||
* Used to request DesktopCapturerSources.
|
||||
*/
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* The callback to be invoked when the component is closed or when a
|
||||
* DesktopCapturerSource has been chosen.
|
||||
*/
|
||||
onSourceChoose: Function,
|
||||
|
||||
/**
|
||||
* Used to obtain translations.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link DesktopPicker}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The currently higlighted DesktopCapturerSource.
|
||||
*/
|
||||
selectedSource: Object,
|
||||
|
||||
/**
|
||||
* The desktop source type currently being displayed.
|
||||
*/
|
||||
selectedTab: number,
|
||||
|
||||
/**
|
||||
* An object containing all the DesktopCapturerSources.
|
||||
*/
|
||||
sources: Object,
|
||||
|
||||
/**
|
||||
* The desktop source types to fetch previews for.
|
||||
*/
|
||||
types: Array<string>
|
||||
};
|
||||
|
||||
/**
|
||||
* React component for DesktopPicker.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class DesktopPicker extends Component<*, *> {
|
||||
/**
|
||||
* DesktopPicker component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
|
||||
/**
|
||||
* An array with desktop sharing sources to be displayed.
|
||||
*/
|
||||
desktopSharingSources: PropTypes.arrayOf(PropTypes.string),
|
||||
|
||||
/**
|
||||
* Used to request DesktopCapturerSources.
|
||||
*/
|
||||
dispatch: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The callback to be invoked when the component is closed or when
|
||||
* a DesktopCapturerSource has been chosen.
|
||||
*/
|
||||
onSourceChoose: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Used to obtain translations.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class DesktopPicker extends Component<Props, State> {
|
||||
_poller = null;
|
||||
|
||||
state = {
|
||||
@@ -99,7 +122,7 @@ class DesktopPicker extends Component<*, *> {
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
@@ -132,7 +155,7 @@ class DesktopPicker extends Component<*, *> {
|
||||
* instance will receive.
|
||||
* @returns {void}
|
||||
*/
|
||||
componentWillReceiveProps(nextProps) {
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
const { desktopSharingSources } = nextProps;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,48 +1,47 @@
|
||||
/* @flow */
|
||||
|
||||
import Spinner from '@atlaskit/spinner';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import DesktopSourcePreview from './DesktopSourcePreview';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link DesktopPickerPane}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The handler to be invoked when a DesktopSourcePreview is clicked.
|
||||
*/
|
||||
onClick: Function,
|
||||
|
||||
/**
|
||||
* The handler to be invoked when a DesktopSourcePreview is double clicked.
|
||||
*/
|
||||
onDoubleClick: Function,
|
||||
|
||||
/**
|
||||
* The id of the DesktopCapturerSource that is currently selected.
|
||||
*/
|
||||
selectedSourceId: string,
|
||||
|
||||
/**
|
||||
* An array of DesktopCapturerSources.
|
||||
*/
|
||||
sources: Array<Object>,
|
||||
|
||||
/**
|
||||
* The source type of the DesktopCapturerSources to display.
|
||||
*/
|
||||
type: string
|
||||
};
|
||||
|
||||
/**
|
||||
* React component for showing a grid of DesktopSourcePreviews.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class DesktopPickerPane extends Component {
|
||||
/**
|
||||
* DesktopPickerPane component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The handler to be invoked when a DesktopSourcePreview is clicked.
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The handler to be invoked when a DesktopSourcePreview is double
|
||||
* clicked.
|
||||
*/
|
||||
onDoubleClick: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The id of the DesktopCapturerSource that is currently selected.
|
||||
*/
|
||||
selectedSourceId: PropTypes.string,
|
||||
|
||||
/**
|
||||
* An array of DesktopCapturerSources.
|
||||
*/
|
||||
sources: PropTypes.array,
|
||||
|
||||
/**
|
||||
* The source type of the DesktopCapturerSources to display.
|
||||
*/
|
||||
type: PropTypes.string
|
||||
};
|
||||
|
||||
class DesktopPickerPane extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,55 +1,56 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link DesktopSourcePreview}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The callback to invoke when the component is clicked. The id of the
|
||||
* clicked on DesktopCapturerSource will be passed in.
|
||||
*/
|
||||
onClick: Function,
|
||||
|
||||
/**
|
||||
* The callback to invoke when the component is double clicked. The id of
|
||||
* the DesktopCapturerSource will be passed in.
|
||||
*/
|
||||
onDoubleClick: Function,
|
||||
|
||||
/**
|
||||
* The indicator which determines whether this DesktopSourcePreview is
|
||||
* selected. If true, the 'is-selected' CSS class will be added to the root
|
||||
* of Component.
|
||||
*/
|
||||
selected: boolean,
|
||||
|
||||
/**
|
||||
* The DesktopCapturerSource to display.
|
||||
*/
|
||||
source: Object,
|
||||
|
||||
/**
|
||||
* The source type of the DesktopCapturerSources to display.
|
||||
*/
|
||||
type: string
|
||||
};
|
||||
|
||||
/**
|
||||
* React component for displaying a preview of a DesktopCapturerSource.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class DesktopSourcePreview extends Component {
|
||||
/**
|
||||
* DesktopSourcePreview component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The callback to invoke when the component is clicked. The id of
|
||||
* the DesktopCapturerSource will be passed in.
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The callback to invoke when the component is double clicked. The id
|
||||
* of the DesktopCapturerSource will be passed in.
|
||||
*/
|
||||
onDoubleClick: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The indicator which determines whether this DesktopSourcePreview is
|
||||
* selected. If true, the 'is-selected' CSS class will be added to the
|
||||
* Component.
|
||||
*/
|
||||
selected: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The DesktopCapturerSource to display.
|
||||
*/
|
||||
source: PropTypes.object,
|
||||
|
||||
/**
|
||||
* The source type of the DesktopCapturerSources to display.
|
||||
*/
|
||||
type: PropTypes.string
|
||||
};
|
||||
|
||||
class DesktopSourcePreview extends Component<Props> {
|
||||
/**
|
||||
* Initializes a new DesktopSourcePreview instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this._onClick = this._onClick.bind(this);
|
||||
@@ -83,6 +84,8 @@ class DesktopSourcePreview extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onClick: () => void;
|
||||
|
||||
/**
|
||||
* Invokes the passed in onClick callback.
|
||||
*
|
||||
@@ -94,6 +97,8 @@ class DesktopSourcePreview extends Component {
|
||||
this.props.onClick(source.id, type);
|
||||
}
|
||||
|
||||
_onDoubleClick: () => void;
|
||||
|
||||
/**
|
||||
* Invokes the passed in onDoubleClick callback.
|
||||
*
|
||||
|
||||
@@ -1,31 +1,42 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { JitsiTrackEvents } from '../../base/lib-jitsi-meet';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AudioInputPreview}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The JitsiLocalTrack to show an audio level meter for.
|
||||
*/
|
||||
track: Object
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AudioInputPreview}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The current audio input level being received, from 0 to 1.
|
||||
*/
|
||||
audioLevel: number
|
||||
};
|
||||
|
||||
/**
|
||||
* React component for displaying a audio level meter for a JitsiLocalTrack.
|
||||
*/
|
||||
class AudioInputPreview extends Component {
|
||||
/**
|
||||
* AudioInputPreview component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/*
|
||||
* The JitsiLocalTrack to show an audio level meter for.
|
||||
*/
|
||||
track: PropTypes.object
|
||||
};
|
||||
|
||||
class AudioInputPreview extends Component<Props, State> {
|
||||
/**
|
||||
* Initializes a new AudioInputPreview instance.
|
||||
*
|
||||
* @param {Object} props - The read-only React Component props with which
|
||||
* the new instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@@ -52,7 +63,7 @@ class AudioInputPreview extends Component {
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentWillReceiveProps(nextProps) {
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
if (nextProps.track !== this.props.track) {
|
||||
this._listenForAudioUpdates(nextProps.track);
|
||||
this._updateAudioLevel(0);
|
||||
@@ -117,6 +128,8 @@ class AudioInputPreview extends Component {
|
||||
this._updateAudioLevel);
|
||||
}
|
||||
|
||||
_updateAudioLevel: (number) => void;
|
||||
|
||||
/**
|
||||
* Updates the internal state of the last know audio level. The level should
|
||||
* be between 0 and 1, as the level will be used as a percentage out of 1.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
@@ -6,28 +7,29 @@ import { Audio } from '../../base/media';
|
||||
|
||||
const TEST_SOUND_PATH = 'sounds/ring.wav';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AudioOutputPreview}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The device id of the audio output device to use.
|
||||
*/
|
||||
deviceId: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* React component for playing a test sound through a specified audio device.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class AudioOutputPreview extends Component {
|
||||
/**
|
||||
* AudioOutputPreview component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The device id of the audio output device to use.
|
||||
*/
|
||||
deviceId: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
class AudioOutputPreview extends Component<Props> {
|
||||
_audioElement: ?Object;
|
||||
|
||||
/**
|
||||
* Initializes a new AudioOutputPreview instance.
|
||||
@@ -35,7 +37,7 @@ class AudioOutputPreview extends Component {
|
||||
* @param {Object} props - The read-only React Component props with which
|
||||
* the new instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this._audioElement = null;
|
||||
@@ -85,6 +87,8 @@ class AudioOutputPreview extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onClick: () => void;
|
||||
|
||||
/**
|
||||
* Plays a test sound.
|
||||
*
|
||||
@@ -96,6 +100,8 @@ class AudioOutputPreview extends Component {
|
||||
&& this._audioElement.play();
|
||||
}
|
||||
|
||||
_setAudioElement: (Object) => void;
|
||||
|
||||
/**
|
||||
* Sets the instance variable for the component's audio element so it can be
|
||||
* accessed directly.
|
||||
@@ -104,7 +110,7 @@ class AudioOutputPreview extends Component {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setAudioElement(element) {
|
||||
_setAudioElement(element: Object) {
|
||||
this._audioElement = element;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
/* @flow */
|
||||
|
||||
import AKDropdownMenu from '@atlaskit/dropdown-menu';
|
||||
import ChevronDownIcon from '@atlaskit/icon/glyph/chevron-down';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link DeviceSelector}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* MediaDeviceInfos used for display in the select element.
|
||||
*/
|
||||
devices: Array<Object>,
|
||||
|
||||
/**
|
||||
* If false, will return a selector with no selection options.
|
||||
*/
|
||||
hasPermission: boolean,
|
||||
|
||||
/**
|
||||
* CSS class for the icon to the left of the dropdown trigger.
|
||||
*/
|
||||
icon: string,
|
||||
|
||||
/**
|
||||
* If true, will render the selector disabled with a default selection.
|
||||
*/
|
||||
isDisabled: boolean,
|
||||
|
||||
/**
|
||||
* The translation key to display as a menu label.
|
||||
*/
|
||||
label: string,
|
||||
|
||||
/**
|
||||
* The callback to invoke when a selection is made.
|
||||
*/
|
||||
onSelect: Function,
|
||||
|
||||
/**
|
||||
* The default device to display as selected.
|
||||
*/
|
||||
selectedDeviceId: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* React component for selecting a device from a select element. Wraps
|
||||
* AKDropdownMenu with device selection specific logic.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class DeviceSelector extends Component {
|
||||
/**
|
||||
* DeviceSelector component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* MediaDeviceInfos used for display in the select element.
|
||||
*/
|
||||
devices: PropTypes.array,
|
||||
|
||||
/**
|
||||
* If false, will return a selector with no selection options.
|
||||
*/
|
||||
hasPermission: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* CSS class for the icon to the left of the dropdown trigger.
|
||||
*/
|
||||
icon: PropTypes.string,
|
||||
|
||||
/**
|
||||
* If true, will render the selector disabled with a default selection.
|
||||
*/
|
||||
isDisabled: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The translation key to display as a menu label.
|
||||
*/
|
||||
label: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The callback to invoke when a selection is made.
|
||||
*/
|
||||
onSelect: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The default device to display as selected.
|
||||
*/
|
||||
selectedDeviceId: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class DeviceSelector extends Component<Props> {
|
||||
/**
|
||||
* Initializes a new DeviceSelector instance.
|
||||
*
|
||||
@@ -178,6 +178,8 @@ class DeviceSelector extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onSelect: (Object) => void;
|
||||
|
||||
/**
|
||||
* Invokes the passed in callback to notify of selection changes.
|
||||
*
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { Video } from '../../base/media';
|
||||
|
||||
const VIDEO_ERROR_CLASS = 'video-preview-has-error';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link VideoInputPreview}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* An error message to display instead of a preview. Displaying an error
|
||||
* will take priority over displaying a video preview.
|
||||
*/
|
||||
error: string,
|
||||
|
||||
/**
|
||||
* The JitsiLocalTrack to display.
|
||||
*/
|
||||
track: Object
|
||||
};
|
||||
|
||||
/**
|
||||
* React component for displaying video. This component defers to lib-jitsi-meet
|
||||
* logic for rendering the video.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class VideoInputPreview extends Component {
|
||||
/**
|
||||
* VideoInputPreview component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* An error message to display instead of a preview. Displaying an error
|
||||
* will take priority over displaying a video preview.
|
||||
*/
|
||||
error: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The JitsiLocalTrack to display.
|
||||
*/
|
||||
track: PropTypes.object
|
||||
};
|
||||
|
||||
class VideoInputPreview extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -7,54 +8,71 @@ import { appendSuffix } from '../functions';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { participantDisplayNameChanged } from '../../base/participants';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link DisplayName}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Whether or not the display name should be editable on click.
|
||||
*/
|
||||
allowEditing: boolean,
|
||||
|
||||
/**
|
||||
* Invoked to update the participant's display name.
|
||||
*/
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* The participant's current display name.
|
||||
*/
|
||||
displayName: string,
|
||||
|
||||
/**
|
||||
* A string to append to the displayName, if provided.
|
||||
*/
|
||||
displayNameSuffix: string,
|
||||
|
||||
/**
|
||||
* The ID attribute to add to the component. Useful for global querying for
|
||||
* the component by legacy components and torture tests.
|
||||
*/
|
||||
elementID: string,
|
||||
|
||||
/**
|
||||
* The ID of the participant whose name is being displayed.
|
||||
*/
|
||||
participantID: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link DisplayName}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The current value of the display name in the edit field.
|
||||
*/
|
||||
editDisplayNameValue: string,
|
||||
|
||||
/**
|
||||
* Whether or not the component should be displaying an editable input.
|
||||
*/
|
||||
isEditing: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for displaying and editing a participant's name.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class DisplayName extends Component {
|
||||
/**
|
||||
* {@code DisplayName}'s property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Whether or not the display name should be editable on click.
|
||||
*/
|
||||
allowEditing: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Invoked to update the participant's display name.
|
||||
*/
|
||||
dispatch: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The participant's current display name.
|
||||
*/
|
||||
displayName: PropTypes.string,
|
||||
|
||||
/**
|
||||
* A string to append to the displayName, if provided.
|
||||
*/
|
||||
displayNameSuffix: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The ID attribute to add to the component. Useful for global querying
|
||||
* for the component by legacy components and torture tests.
|
||||
*/
|
||||
elementID: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The ID of the participant whose name is being displayed.
|
||||
*/
|
||||
participantID: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
class DisplayName extends Component<Props, State> {
|
||||
_nameInput: ?HTMLInputElement;
|
||||
|
||||
/**
|
||||
* Initializes a new {@code DisplayName} instance.
|
||||
@@ -62,23 +80,11 @@ class DisplayName extends Component {
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
/**
|
||||
* The current value of the display name in the edit field.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
editDisplayNameValue: '',
|
||||
|
||||
/**
|
||||
* Whether or not the component should be displaying an editable
|
||||
* input.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
isEditing: false
|
||||
};
|
||||
|
||||
@@ -109,7 +115,9 @@ class DisplayName extends Component {
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidUpdate(previousProps, previousState) {
|
||||
if (!previousState.isEditing && this.state.isEditing) {
|
||||
if (!previousState.isEditing
|
||||
&& this.state.isEditing
|
||||
&& this._nameInput) {
|
||||
this._nameInput.select();
|
||||
}
|
||||
}
|
||||
@@ -156,6 +164,8 @@ class DisplayName extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onChange: () => void;
|
||||
|
||||
/**
|
||||
* Updates the internal state of the display name entered into the edit
|
||||
* field.
|
||||
@@ -170,6 +180,8 @@ class DisplayName extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
_onKeyDown: () => void;
|
||||
|
||||
/**
|
||||
* Submits the editted display name update if the enter key is pressed.
|
||||
*
|
||||
@@ -183,6 +195,8 @@ class DisplayName extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
_onStartEditing: () => void;
|
||||
|
||||
/**
|
||||
* Updates the component to display an editable input field and sets the
|
||||
* initial value to the current display name.
|
||||
@@ -199,6 +213,8 @@ class DisplayName extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
_onSubmit: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action to update the display name if any change has
|
||||
* occurred after editing. Clears any temporary state used to keep track
|
||||
@@ -223,6 +239,8 @@ class DisplayName extends Component {
|
||||
this._nameInput = null;
|
||||
}
|
||||
|
||||
_setNameInputRef: (HTMLInputElement | null) => void;
|
||||
|
||||
/**
|
||||
* Sets the internal reference to the HTML element backing the React
|
||||
* {@code Component} input with id {@code editDisplayName}.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { FieldTextStateless as TextField } from '@atlaskit/field-text';
|
||||
@@ -10,51 +11,56 @@ import {
|
||||
participantDisplayNameChanged
|
||||
} from '../../base/participants';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link DisplayNamePrompt}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The current ID for the local participant. Used for setting the display
|
||||
* name on the associated participant.
|
||||
*/
|
||||
_localParticipantID: string,
|
||||
|
||||
/**
|
||||
* Invoked to update the local participant's display name.
|
||||
*/
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link DisplayNamePrompt}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The name to show in the display name text field.
|
||||
*/
|
||||
displayName: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React {@code Component} for displaying a dialog with an field
|
||||
* for setting the local participant's display name.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class DisplayNamePrompt extends Component {
|
||||
/**
|
||||
* {@code DisplayNamePrompt} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The current ID for the local participant. Used for setting the
|
||||
* display name on the associated participant.
|
||||
*/
|
||||
_localParticipantID: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to update the local participant's display name.
|
||||
*/
|
||||
dispatch: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class DisplayNamePrompt extends Component<Props, State> {
|
||||
/**
|
||||
* Initializes a new {@code DisplayNamePrompt} instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
/**
|
||||
* The name to show in the display name text field.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
displayName: ''
|
||||
};
|
||||
|
||||
@@ -88,6 +94,8 @@ class DisplayNamePrompt extends Component {
|
||||
</Dialog>);
|
||||
}
|
||||
|
||||
_onDisplayNameChange: (Object) => void;
|
||||
|
||||
/**
|
||||
* Updates the entered display name.
|
||||
*
|
||||
@@ -102,12 +110,14 @@ class DisplayNamePrompt extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
_onSubmit: () => boolean;
|
||||
|
||||
/**
|
||||
* Dispatches an action to update the local participant's display name. A
|
||||
* name must be entered for the action to dispatch.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_onSubmit() {
|
||||
const { displayName } = this.state;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/* global interfaceConfig */
|
||||
/* @flow */
|
||||
|
||||
import { FieldTextAreaStateless } from '@atlaskit/field-text-area';
|
||||
import StarIcon from '@atlaskit/icon/glyph/star';
|
||||
import StarFilledIcon from '@atlaskit/icon/glyph/star-filled';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -16,6 +15,8 @@ import { translate } from '../../base/i18n';
|
||||
|
||||
import { cancelFeedback, submitFeedback } from '../actions';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
const scoreAnimationClass
|
||||
= interfaceConfig.ENABLE_FEEDBACK_ANIMATION ? 'shake-rotate' : '';
|
||||
|
||||
@@ -33,6 +34,70 @@ const SCORES = [
|
||||
'feedback.veryGood'
|
||||
];
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link FeedbackDialog}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The cached feedback message, if any, that was set when closing a previous
|
||||
* instance of {@code FeedbackDialog}.
|
||||
*/
|
||||
_message: string,
|
||||
|
||||
/**
|
||||
* The cached feedback score, if any, that was set when closing a previous
|
||||
* instance of {@code FeedbackDialog}.
|
||||
*/
|
||||
_score: number,
|
||||
|
||||
/**
|
||||
* The JitsiConference that is being rated. The conference is passed in
|
||||
* because feedback can occur after a conference has been left, so
|
||||
* references to it may no longer exist in redux.
|
||||
*/
|
||||
conference: Object,
|
||||
|
||||
/**
|
||||
* Invoked to signal feedback submission or canceling.
|
||||
*/
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* Callback invoked when {@code FeedbackDialog} is unmounted.
|
||||
*/
|
||||
onClose: Function,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link FeedbackDialog}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The currently entered feedback message.
|
||||
*/
|
||||
message: string,
|
||||
|
||||
/**
|
||||
* The score selection index which is currently being hovered. The value -1
|
||||
* is used as a sentinel value to match store behavior of using -1 for no
|
||||
* score having been selected.
|
||||
*/
|
||||
mousedOverScore: number,
|
||||
|
||||
/**
|
||||
* The currently selected score selection index. The score will not be 0
|
||||
* indexed so subtract one to map with SCORES.
|
||||
*/
|
||||
score: number
|
||||
};
|
||||
|
||||
/**
|
||||
* A React {@code Component} for displaying a dialog to rate the current
|
||||
* conference quality, write a message describing the experience, and submit
|
||||
@@ -40,49 +105,13 @@ const SCORES = [
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class FeedbackDialog extends Component {
|
||||
class FeedbackDialog extends Component<Props, State> {
|
||||
/**
|
||||
* {@code FeedbackDialog} component's property types.
|
||||
*
|
||||
* @static
|
||||
* An array of objects with click handlers for each of the scores listed in
|
||||
* the constant SCORES. This pattern is used for binding event handlers only
|
||||
* once for each score selection icon.
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The cached feedback message, if any, that was set when closing a
|
||||
* previous instance of {@code FeedbackDialog}.
|
||||
*/
|
||||
_message: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The cached feedback score, if any, that was set when closing a
|
||||
* previous instance of {@code FeedbackDialog}.
|
||||
*/
|
||||
_score: PropTypes.number,
|
||||
|
||||
/**
|
||||
* The JitsiConference that is being rated. The conference is passed in
|
||||
* because feedback can occur after a conference has been left, so
|
||||
* references to it may no longer exist in redux.
|
||||
*
|
||||
* @type {JitsiConference}
|
||||
*/
|
||||
conference: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Invoked to signal feedback submission or canceling.
|
||||
*/
|
||||
dispatch: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Callback invoked when {@code FeedbackDialog} is unmounted.
|
||||
*/
|
||||
onClose: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
_scoreClickConfigurations: Array<Object>;
|
||||
|
||||
/**
|
||||
* Initializes a new {@code FeedbackDialog} instance.
|
||||
@@ -90,7 +119,7 @@ class FeedbackDialog extends Component {
|
||||
* @param {Object} props - The read-only React {@code Component} props with
|
||||
* which the new instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
const { _message, _score } = this.props;
|
||||
@@ -121,13 +150,6 @@ class FeedbackDialog extends Component {
|
||||
score: _score > -1 ? _score - 1 : _score
|
||||
};
|
||||
|
||||
/**
|
||||
* An array of objects with click handlers for each of the scores listed
|
||||
* in SCORES. This pattern is used for binding event handlers only once
|
||||
* for each score selection icon.
|
||||
*
|
||||
* @type {Object[]}
|
||||
*/
|
||||
this._scoreClickConfigurations = SCORES.map((textKey, index) => {
|
||||
return {
|
||||
_onClick: () => this._onScoreSelect(index),
|
||||
@@ -234,6 +256,8 @@ class FeedbackDialog extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onCancel: () => boolean;
|
||||
|
||||
/**
|
||||
* Dispatches an action notifying feedback was not submitted. The submitted
|
||||
* score will have one added as the rest of the app does not expect 0
|
||||
@@ -251,6 +275,8 @@ class FeedbackDialog extends Component {
|
||||
return true;
|
||||
}
|
||||
|
||||
_onMessageChange: (Object) => void;
|
||||
|
||||
/**
|
||||
* Updates the known entered feedback message.
|
||||
*
|
||||
@@ -274,6 +300,8 @@ class FeedbackDialog extends Component {
|
||||
this.setState({ score });
|
||||
}
|
||||
|
||||
_onScoreContainerMouseLeave: () => void;
|
||||
|
||||
/**
|
||||
* Sets the currently hovered score to null to indicate no hover is
|
||||
* occurring.
|
||||
@@ -297,6 +325,8 @@ class FeedbackDialog extends Component {
|
||||
this.setState({ mousedOverScore });
|
||||
}
|
||||
|
||||
_onSubmit: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches the entered feedback for submission. The submitted score will
|
||||
* have one added as the rest of the app does not expect 0 indexing.
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import BaseIndicator from './BaseIndicator';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AudioMutedIndicator}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: string
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for showing an audio muted icon with a tooltip.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class AudioMutedIndicator extends Component {
|
||||
/**
|
||||
* {@code AudioMutedIndicator} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: PropTypes.string
|
||||
};
|
||||
|
||||
class AudioMutedIndicator extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,15 +1,59 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import Tooltip from '@atlaskit/tooltip';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link BaseIndicator}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Additional CSS class names to set on the icon container.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* The CSS classnames to set on the icon element of the component.
|
||||
*/
|
||||
iconClassName: string,
|
||||
|
||||
/**
|
||||
* The font size for the icon.
|
||||
*/
|
||||
iconSize: string,
|
||||
|
||||
/**
|
||||
* The ID attribue to set on the root element of the component.
|
||||
*/
|
||||
id: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function,
|
||||
|
||||
/**
|
||||
* The translation key to use for displaying a tooltip when hovering over
|
||||
* the component.
|
||||
*/
|
||||
tooltipKey: string,
|
||||
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from,
|
||||
* defaulting to "top".
|
||||
*/
|
||||
tooltipPosition: string
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for showing an icon with a tooltip.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class BaseIndicator extends Component {
|
||||
class BaseIndicator extends Component<Props> {
|
||||
/**
|
||||
* Default values for {@code BaseIndicator} component's properties.
|
||||
*
|
||||
@@ -23,50 +67,6 @@ class BaseIndicator extends Component {
|
||||
tooltipPosition: 'top'
|
||||
};
|
||||
|
||||
/**
|
||||
* {@code BaseIndicator} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Additional CSS class names to set on the icon container.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The CSS classnames to set on the icon element of the component.
|
||||
*/
|
||||
iconClassName: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The font size for the icon.
|
||||
*/
|
||||
iconSize: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The ID attribue to set on the root element of the component.
|
||||
*/
|
||||
id: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The translation key to use for displaying a tooltip when hovering
|
||||
* over the component.
|
||||
*/
|
||||
tooltipKey: PropTypes.string,
|
||||
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
* Defaults to "top".
|
||||
*/
|
||||
tooltipPosition: PropTypes.string
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import BaseIndicator from './BaseIndicator';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link DominantSpeakerIndicator}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The font-size for the icon.
|
||||
*/
|
||||
iconSize: number,
|
||||
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Thumbnail badge showing that the participant is the dominant speaker in
|
||||
* the conference.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class DominantSpeakerIndicator extends Component {
|
||||
/**
|
||||
* {@code DominantSpeakerIndicator} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The font-size for the icon.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
iconSize: PropTypes.number,
|
||||
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: PropTypes.string
|
||||
};
|
||||
|
||||
class DominantSpeakerIndicator extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import BaseIndicator from './BaseIndicator';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link ModeratorIndicator}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: string
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for showing a moderator icon with a tooltip.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class ModeratorIndicator extends Component {
|
||||
/**
|
||||
* {@code ModeratorIndicator} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: PropTypes.string
|
||||
};
|
||||
|
||||
class ModeratorIndicator extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import BaseIndicator from './BaseIndicator';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link RaisedHandIndicator}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The font-size for the icon.
|
||||
*/
|
||||
iconSize: number,
|
||||
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Thumbnail badge showing that the participant would like to speak.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class RaisedHandIndicator extends Component {
|
||||
/**
|
||||
* {@code RaisedHandIndicator} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The font-size for the icon.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
iconSize: PropTypes.number,
|
||||
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: PropTypes.string
|
||||
};
|
||||
|
||||
class RaisedHandIndicator extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import BaseIndicator from './BaseIndicator';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link VideoMutedIndicator}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: string
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for showing a video muted icon with a tooltip.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class VideoMutedIndicator extends Component {
|
||||
/**
|
||||
* {@code VideoMutedIndicator} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* From which side of the indicator the tooltip should appear from.
|
||||
*/
|
||||
tooltipPosition: PropTypes.string
|
||||
};
|
||||
|
||||
class VideoMutedIndicator extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -149,11 +149,12 @@ class GoogleApi {
|
||||
let title;
|
||||
|
||||
// Finding title from the broadcast with the same
|
||||
// channelId. If not found (unknown scenario), we use
|
||||
// the key as title again.
|
||||
// boundStreamId. If not found (unknown scenario), we
|
||||
// use the key as title again.
|
||||
for (const broadcast of broadcasts) {
|
||||
if (broadcast.snippet.channelId
|
||||
=== stream.snippet.channelId) {
|
||||
if (broadcast.contentDetails
|
||||
&& broadcast.contentDetails.boundStreamId
|
||||
=== stream.id) {
|
||||
title = broadcast.snippet.title;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,14 +37,14 @@ export function beginAddPeople() {
|
||||
|
||||
|
||||
/**
|
||||
* Invites (i.e. sends invites to) an array of invitees (which may be a
|
||||
* combination of users, rooms, phone numbers, and video rooms).
|
||||
* Invites (i.e. Sends invites to) an array of invitees (which may be a
|
||||
* combination of users, rooms, phone numbers, and video rooms.
|
||||
*
|
||||
* @param {Array<Object>} invitees - The recepients to send invites to.
|
||||
* @param {Array<Object>} showCalleeInfo - Indicates whether the
|
||||
* {@code CalleeInfo} should be displayed or not.
|
||||
* @returns {Promise<Array<Object>>} A {@code Promise} resolving with an array
|
||||
* of invitees who were not invited (i.e. invites were not sent to them).
|
||||
* of invitees who were not invited (i.e. Invites were not sent to them).
|
||||
*/
|
||||
export function invite(
|
||||
invitees: Array<Object>,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import Avatar from '@atlaskit/avatar';
|
||||
import InlineMessage from '@atlaskit/inline-message';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -19,88 +18,96 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AddPeopleDialog}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The {@link JitsiMeetConference} which will be used to invite "room"
|
||||
* participants through the SIP Jibri (Video SIP gateway).
|
||||
*/
|
||||
_conference: Object,
|
||||
|
||||
/**
|
||||
* The URL for validating if a phone number can be called.
|
||||
*/
|
||||
_dialOutAuthUrl: string,
|
||||
|
||||
/**
|
||||
* Whether to show a footer text after the search results as a last element.
|
||||
*/
|
||||
_footerTextEnabled: boolean,
|
||||
|
||||
/**
|
||||
* The JWT token.
|
||||
*/
|
||||
_jwt: string,
|
||||
|
||||
/**
|
||||
* The query types used when searching people.
|
||||
*/
|
||||
_peopleSearchQueryTypes: Array<string>,
|
||||
|
||||
/**
|
||||
* The URL pointing to the service allowing for people search.
|
||||
*/
|
||||
_peopleSearchUrl: string,
|
||||
|
||||
/**
|
||||
* Whether or not to show Add People functionality.
|
||||
*/
|
||||
addPeopleEnabled: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not to show Dial Out functionality.
|
||||
*/
|
||||
dialOutEnabled: boolean,
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
*/
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function,
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link AddPeopleDialog}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Indicating that an error occurred when adding people to the call.
|
||||
*/
|
||||
addToCallError: boolean,
|
||||
|
||||
/**
|
||||
* Indicating that we're currently adding the new people to the
|
||||
* call.
|
||||
*/
|
||||
addToCallInProgress: boolean,
|
||||
|
||||
/**
|
||||
* The list of invite items.
|
||||
*/
|
||||
inviteItems: Array<Object>
|
||||
};
|
||||
|
||||
/**
|
||||
* The dialog that allows to invite people to the call.
|
||||
*/
|
||||
class AddPeopleDialog extends Component<*, *> {
|
||||
/**
|
||||
* {@code AddPeopleDialog}'s property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The {@link JitsiMeetConference} which will be used to invite "room"
|
||||
* participants through the SIP Jibri (Video SIP gateway).
|
||||
*/
|
||||
_conference: PropTypes.object,
|
||||
|
||||
/**
|
||||
* The URL for validating if a phone number can be called.
|
||||
*/
|
||||
_dialOutAuthUrl: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Whether to show a footer text after the search results
|
||||
* as a last element.
|
||||
*/
|
||||
_footerTextEnabled: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The JWT token.
|
||||
*/
|
||||
_jwt: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The query types used when searching people.
|
||||
*/
|
||||
_peopleSearchQueryTypes: PropTypes.arrayOf(PropTypes.string),
|
||||
|
||||
/**
|
||||
* The URL pointing to the service allowing for people search.
|
||||
*/
|
||||
_peopleSearchUrl: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Whether or not to show Add People functionality.
|
||||
*/
|
||||
addPeopleEnabled: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Whether or not to show Dial Out functionality.
|
||||
*/
|
||||
dialOutEnabled: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
*/
|
||||
dispatch: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class AddPeopleDialog extends Component<Props, State> {
|
||||
_multiselect = null;
|
||||
|
||||
_resourceClient: Object;
|
||||
|
||||
state = {
|
||||
/**
|
||||
* Indicating that an error occurred when adding people to the call.
|
||||
*/
|
||||
addToCallError: false,
|
||||
|
||||
/**
|
||||
* Indicating that we're currently adding the new people to the
|
||||
* call.
|
||||
*/
|
||||
addToCallInProgress: false,
|
||||
|
||||
/**
|
||||
* The list of invite items.
|
||||
*/
|
||||
inviteItems: []
|
||||
};
|
||||
|
||||
@@ -110,7 +117,7 @@ class AddPeopleDialog extends Component<*, *> {
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
@@ -142,10 +149,11 @@ class AddPeopleDialog extends Component<*, *> {
|
||||
/**
|
||||
* React Component method that executes once component is updated.
|
||||
*
|
||||
* @param {Object} prevProps - The state object before the update.
|
||||
* @param {Object} prevState - The state object before the update.
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidUpdate(prevState) {
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
/**
|
||||
* Clears selected items from the multi select component on successful
|
||||
* invite.
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link NoRoomError}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Additional CSS classnames to append to the root of the component.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays an error message stating no room name was specified to fetch dial-in
|
||||
* numbers for.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class NoRoomError extends Component {
|
||||
/**
|
||||
* {@code NoRoomError} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Additional CSS classnames to append to the root of the component.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class NoRoomError extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
|
||||
/**
|
||||
* Displays a conference ID used as a pin for dialing into a conferene.
|
||||
* The type of the React {@code Component} props of {@link ConferenceID}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The conference ID for dialing in.
|
||||
*/
|
||||
conferenceID: number,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays a conference ID used as a pin for dialing into a conference.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class ConferenceID extends Component {
|
||||
/**
|
||||
* {@code ConferenceID} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The conference ID for dialing in.
|
||||
*/
|
||||
conferenceID: PropTypes.number,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class ConferenceID extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* global config */
|
||||
/* @flow */
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
@@ -8,53 +7,72 @@ import { translate } from '../../../base/i18n';
|
||||
import ConferenceID from './ConferenceID';
|
||||
import NumbersList from './NumbersList';
|
||||
|
||||
declare var config: Object;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link DialInSummary}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Additional CSS classnames to append to the root of the component.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* Whether or not numbers should include links with the telephone protocol.
|
||||
*/
|
||||
clickableNumbers: boolean,
|
||||
|
||||
/**
|
||||
* The name of the conference to show a conferenceID for.
|
||||
*/
|
||||
room: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link DialInSummary}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The numeric ID of the conference, used as a pin when dialing in.
|
||||
*/
|
||||
conferenceID: ?string,
|
||||
|
||||
/**
|
||||
* An error message to display.
|
||||
*/
|
||||
error: string,
|
||||
|
||||
/**
|
||||
* Whether or not the app is fetching data.
|
||||
*/
|
||||
loading: boolean,
|
||||
|
||||
/**
|
||||
* The dial-in numbers. entered by the local participant.
|
||||
*/
|
||||
numbers: ?Array<Object>,
|
||||
|
||||
/**
|
||||
* Whether or not dial-in is allowed.
|
||||
*/
|
||||
numbersEnabled: ?boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a page listing numbers for dialing into a conference and pin to
|
||||
* the a specific conference.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class DialInSummary extends Component {
|
||||
/**
|
||||
* {@code DialInSummary} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Additional CSS classnames to append to the root of the component.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Whether or not numbers should include links with the telephone
|
||||
* protocol.
|
||||
*/
|
||||
clickableNumbers: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The name of the conference to show a conferenceID for.
|
||||
*/
|
||||
room: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
/**
|
||||
* {@code DialInSummary} component's local state.
|
||||
*
|
||||
* @type {Object}
|
||||
* @property {number} conferenceID - The numeric ID of the conference, used
|
||||
* as a pin when dialing in.
|
||||
* @property {string} error - An error message to display.
|
||||
* @property {boolean} loading - Whether or not the app is fetching data.
|
||||
* @property {Array|Object} numbers - The dial-in numbers.
|
||||
* entered by the local participant.
|
||||
* @property {boolean} numbersEnabled - Whether or not dial-in is allowed.
|
||||
*/
|
||||
class DialInSummary extends Component<Props, State> {
|
||||
state = {
|
||||
conferenceID: null,
|
||||
error: '',
|
||||
@@ -69,7 +87,7 @@ class DialInSummary extends Component {
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
@@ -183,6 +201,8 @@ class DialInSummary extends Component {
|
||||
.catch(() => Promise.reject(this.props.t('info.genericError')));
|
||||
}
|
||||
|
||||
_onGetConferenceIDSuccess: (Object) => void;
|
||||
|
||||
/**
|
||||
* Callback invoked when fetching the conference ID succeeds.
|
||||
*
|
||||
@@ -200,6 +220,8 @@ class DialInSummary extends Component {
|
||||
this.setState({ conferenceID: id });
|
||||
}
|
||||
|
||||
_onGetNumbersSuccess: (Object) => void;
|
||||
|
||||
/**
|
||||
* Callback invoked when fetching dial-in numbers succeeds. Sets the
|
||||
* internal to show the numbers.
|
||||
@@ -218,6 +240,8 @@ class DialInSummary extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
_setErrorMessage: (string) => void;
|
||||
|
||||
/**
|
||||
* Sets an error message to display on the page instead of content.
|
||||
*
|
||||
|
||||
@@ -1,47 +1,39 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Whether or not numbers should include links with the telephone protocol.
|
||||
*/
|
||||
clickableNumbers: boolean,
|
||||
|
||||
/**
|
||||
* The conference ID for dialing in.
|
||||
*/
|
||||
conferenceID: number,
|
||||
|
||||
/**
|
||||
* The phone numbers to display. Can be an array of numbers or an object
|
||||
* with countries as keys and an array of numbers as values.
|
||||
*/
|
||||
numbers: { [string]: Array<string> } | Array<string>,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a table with phone numbers to dial in to a conference.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class NumbersList extends Component {
|
||||
/**
|
||||
* {@code NumbersList} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Whether or not numbers should include links with the telephone
|
||||
* protocol.
|
||||
*/
|
||||
clickableNumbers: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The conference ID for dialing in.
|
||||
*/
|
||||
conferenceID: PropTypes.number,
|
||||
|
||||
/**
|
||||
* The phone numbers to display. Can be an array of numbers
|
||||
* or an object with countries as keys and an array of numbers
|
||||
* as values.
|
||||
*/
|
||||
numbers: PropTypes.oneOfType([
|
||||
PropTypes.array,
|
||||
PropTypes.object
|
||||
]),
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class NumbersList extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
@@ -50,22 +42,21 @@ class NumbersList extends Component {
|
||||
*/
|
||||
render() {
|
||||
const { numbers, t } = this.props;
|
||||
const showWithoutCountries = Array.isArray(numbers);
|
||||
|
||||
return (
|
||||
<table className = 'dial-in-numbers-list'>
|
||||
<thead>
|
||||
<tr>
|
||||
{ showWithoutCountries
|
||||
{ Array.isArray(numbers)
|
||||
? null
|
||||
: <th>{ t('info.country') }</th> }
|
||||
<th>{ t('info.numbers') }</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className = 'dial-in-numbers-body'>
|
||||
{ showWithoutCountries
|
||||
{ Array.isArray(numbers)
|
||||
? numbers.map(this._renderNumberRow)
|
||||
: this._renderWithCountries() }
|
||||
: this._renderWithCountries(numbers) }
|
||||
</tbody>
|
||||
</table>);
|
||||
}
|
||||
@@ -73,15 +64,25 @@ class NumbersList extends Component {
|
||||
/**
|
||||
* Renders rows of countries and associated phone numbers.
|
||||
*
|
||||
* @param {Object} numbersMapping - Things yeah.
|
||||
* @private
|
||||
* @returns {ReactElement[]}
|
||||
*/
|
||||
_renderWithCountries() {
|
||||
_renderWithCountries(numbersMapping: Object) {
|
||||
const rows = [];
|
||||
|
||||
for (const [ country, numbers ] of Object.entries(this.props.numbers)) {
|
||||
const formattedNumbers = numbers.map(
|
||||
number => this._renderNumberDiv(number));
|
||||
for (const [ country, numbers ] of Object.entries(numbersMapping)) {
|
||||
if (!Array.isArray(numbers)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formattedNumbers = numbers.map(number => {
|
||||
if (typeof number === 'string') {
|
||||
return this._renderNumberDiv(number);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
rows.push(
|
||||
<tr key = { country }>
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link DialInNumber}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The numberic identifier for the current conference, used after dialing a
|
||||
* the number to join the conference.
|
||||
*/
|
||||
conferenceID: number,
|
||||
|
||||
/**
|
||||
* The phone number to dial to begin the process of dialing into a
|
||||
* conference.
|
||||
*/
|
||||
phoneNumber: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} responsible for displaying a telephone number and
|
||||
* conference ID for dialing into a conference.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class DialInNumber extends Component {
|
||||
/**
|
||||
* {@code DialInNumber} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The numberic identifier for the current conference, used after
|
||||
* dialing a the number to join the conference.
|
||||
*/
|
||||
conferenceID: PropTypes.number,
|
||||
|
||||
/**
|
||||
* The phone number to dial to begin the process of dialing into a
|
||||
* conference.
|
||||
*/
|
||||
phoneNumber: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class DialInNumber extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -13,88 +14,103 @@ import PasswordForm from './PasswordForm';
|
||||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link InfoDialog}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Whether or not the current user can modify the current password.
|
||||
*/
|
||||
_canEditPassword: boolean,
|
||||
|
||||
/**
|
||||
* The JitsiConference for which to display a lock state and change the
|
||||
* password.
|
||||
*/
|
||||
_conference: Object,
|
||||
|
||||
/**
|
||||
* The name of the current conference. Used as part of inviting users.
|
||||
*/
|
||||
_conferenceName: string,
|
||||
|
||||
/**
|
||||
* The current url of the conference to be copied onto the clipboard.
|
||||
*/
|
||||
_inviteURL: string,
|
||||
|
||||
/**
|
||||
* The current location url of the conference.
|
||||
*/
|
||||
_locationURL: Object,
|
||||
|
||||
/**
|
||||
* The value for how the conference is locked (or undefined if not locked)
|
||||
* as defined by room-lock constants.
|
||||
*/
|
||||
_locked: string,
|
||||
|
||||
/**
|
||||
* The current known password for the JitsiConference.
|
||||
*/
|
||||
_password: string,
|
||||
|
||||
/**
|
||||
* The object representing the dialIn feature.
|
||||
*/
|
||||
dialIn: Object,
|
||||
|
||||
/**
|
||||
* Invoked to open a dialog for adding participants to the conference.
|
||||
*/
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* The current known URL for a live stream in progress.
|
||||
*/
|
||||
liveStreamViewURL: string,
|
||||
|
||||
/**
|
||||
* Callback invoked when the dialog should be closed.
|
||||
*/
|
||||
onClose: Function,
|
||||
|
||||
/**
|
||||
* Callback invoked when a mouse-related event has been detected.
|
||||
*/
|
||||
onMouseOver: Function,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link InfoDialog}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Whether or not to show the password in editing mode.
|
||||
*/
|
||||
passwordEditEnabled: boolean,
|
||||
|
||||
/**
|
||||
* The conference dial-in number to display.
|
||||
*/
|
||||
phoneNumber: ?string
|
||||
};
|
||||
|
||||
/**
|
||||
* A React Component with the contents for a dialog that shows information about
|
||||
* the current conference.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class InfoDialog extends Component {
|
||||
/**
|
||||
* {@code InfoDialog} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Whether or not the current user can modify the current password.
|
||||
*/
|
||||
_canEditPassword: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The JitsiConference for which to display a lock state and change the
|
||||
* password.
|
||||
*
|
||||
* @type {JitsiConference}
|
||||
*/
|
||||
_conference: PropTypes.object,
|
||||
|
||||
/**
|
||||
* The name of the current conference. Used as part of inviting users.
|
||||
*/
|
||||
_conferenceName: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The current url of the conference to be copied onto the clipboard.
|
||||
*/
|
||||
_inviteURL: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The current location url of the conference.
|
||||
*/
|
||||
_locationURL: PropTypes.object,
|
||||
|
||||
/**
|
||||
* The value for how the conference is locked (or undefined if not
|
||||
* locked) as defined by room-lock constants.
|
||||
*/
|
||||
_locked: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The current known password for the JitsiConference.
|
||||
*/
|
||||
_password: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The object representing the dialIn feature.
|
||||
*/
|
||||
dialIn: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Invoked to open a dialog for adding participants to the conference.
|
||||
*/
|
||||
dispatch: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The current known URL for a live stream in progress.
|
||||
*/
|
||||
liveStreamViewURL: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Callback invoked when the dialog should be closed.
|
||||
*/
|
||||
onClose: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Callback invoked when a mouse-related event has been detected.
|
||||
*/
|
||||
onMouseOver: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
class InfoDialog extends Component<Props, State> {
|
||||
_copyElement: ?Object;
|
||||
|
||||
/**
|
||||
* {@code InfoDialog} component's local state.
|
||||
@@ -107,7 +123,7 @@ class InfoDialog extends Component {
|
||||
*/
|
||||
state = {
|
||||
passwordEditEnabled: false,
|
||||
phoneNumber: ''
|
||||
phoneNumber: undefined
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -116,7 +132,7 @@ class InfoDialog extends Component {
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
const { defaultCountry, numbers } = props.dialIn;
|
||||
@@ -162,7 +178,8 @@ class InfoDialog extends Component {
|
||||
const { defaultCountry, numbers } = nextProps.dialIn;
|
||||
|
||||
this.setState({
|
||||
phoneNumber: _getDefaultPhoneNumber(numbers, defaultCountry)
|
||||
phoneNumber:
|
||||
_getDefaultPhoneNumber(numbers, defaultCountry)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -293,6 +310,8 @@ class InfoDialog extends Component {
|
||||
return this.props._inviteURL.replace(/^https?:\/\//i, '');
|
||||
}
|
||||
|
||||
_onClickURLText: (Object) => void;
|
||||
|
||||
/**
|
||||
* Callback invoked when a displayed URL link is clicked to prevent actual
|
||||
* navigation from happening. The URL links have an href to display the
|
||||
@@ -307,6 +326,8 @@ class InfoDialog extends Component {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
_onCopyInviteURL: () => void;
|
||||
|
||||
/**
|
||||
* Callback invoked to copy the contents of {@code this._copyElement} to the
|
||||
* clipboard.
|
||||
@@ -316,14 +337,20 @@ class InfoDialog extends Component {
|
||||
*/
|
||||
_onCopyInviteURL() {
|
||||
try {
|
||||
this._copyElement.select();
|
||||
if (!this._copyElement) {
|
||||
throw new Error('No element to copy from.');
|
||||
}
|
||||
|
||||
this._copyElement && this._copyElement.select();
|
||||
document.execCommand('copy');
|
||||
this._copyElement.blur();
|
||||
this._copyElement && this._copyElement.blur();
|
||||
} catch (err) {
|
||||
logger.error('error when copying the text', err);
|
||||
}
|
||||
}
|
||||
|
||||
_onPasswordRemove: () => void;
|
||||
|
||||
/**
|
||||
* Callback invoked to unlock the current JitsiConference.
|
||||
*
|
||||
@@ -334,6 +361,8 @@ class InfoDialog extends Component {
|
||||
this._onPasswordSubmit('');
|
||||
}
|
||||
|
||||
_onPasswordSubmit: (string) => void;
|
||||
|
||||
/**
|
||||
* Callback invoked to set a password on the current JitsiConference.
|
||||
*
|
||||
@@ -352,6 +381,8 @@ class InfoDialog extends Component {
|
||||
));
|
||||
}
|
||||
|
||||
_onTogglePasswordEditState: () => void;
|
||||
|
||||
/**
|
||||
* Toggles whether or not the password should currently be shown as being
|
||||
* edited locally.
|
||||
@@ -476,6 +507,8 @@ class InfoDialog extends Component {
|
||||
&& phoneNumber);
|
||||
}
|
||||
|
||||
_setCopyElement: () => void;
|
||||
|
||||
/**
|
||||
* Sets the internal reference to the DOM/HTML element backing the React
|
||||
* {@code Component} input.
|
||||
@@ -485,7 +518,7 @@ class InfoDialog extends Component {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setCopyElement(element) {
|
||||
_setCopyElement(element: Object) {
|
||||
this._copyElement = element;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,60 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { LOCKED_LOCALLY } from '../../../room-lock';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link PasswordForm}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Whether or not to show the password editing field.
|
||||
*/
|
||||
editEnabled: boolean,
|
||||
|
||||
/**
|
||||
* The value for how the conference is locked (or undefined if not locked)
|
||||
* as defined by room-lock constants.
|
||||
*/
|
||||
locked: string,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the local participant is submitting a password
|
||||
* set request.
|
||||
*/
|
||||
onSubmit: Function,
|
||||
|
||||
/**
|
||||
* The current known password for the JitsiConference.
|
||||
*/
|
||||
password: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link PasswordForm}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The value of the password being entered by the local participant.
|
||||
*/
|
||||
enteredPassword: string
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for displaying and editing the conference password.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class PasswordForm extends Component {
|
||||
/**
|
||||
* {@code PasswordForm} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Whether or not to show the password editing field.
|
||||
*/
|
||||
editEnabled: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The value for how the conference is locked (or undefined if not
|
||||
* locked) as defined by room-lock constants.
|
||||
*/
|
||||
locked: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Callback to invoke when the local participant is submitting a
|
||||
* password set request.
|
||||
*/
|
||||
onSubmit: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The current known password for the JitsiConference.
|
||||
*/
|
||||
password: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
/**
|
||||
* {@code PasswordForm} component's local state.
|
||||
*
|
||||
* @type {Object}
|
||||
* @property {string} enteredPassword - The value of the password being
|
||||
* entered by the local participant.
|
||||
*/
|
||||
class PasswordForm extends Component<Props, State> {
|
||||
state = {
|
||||
enteredPassword: ''
|
||||
};
|
||||
@@ -61,7 +65,7 @@ class PasswordForm extends Component {
|
||||
* @param {Props} props - The React {@code Component} props to initialize
|
||||
* the new {@code PasswordForm} instance with.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
@@ -77,7 +81,7 @@ class PasswordForm extends Component {
|
||||
* @inheritdoc
|
||||
* @param {Props} nextProps - New props component will receive.
|
||||
*/
|
||||
componentWillReceiveProps(nextProps) {
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
if (this.props.editEnabled && !nextProps.editEnabled) {
|
||||
this.setState({ enteredPassword: '' });
|
||||
}
|
||||
@@ -148,6 +152,8 @@ class PasswordForm extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
_onEnteredPasswordChange: (Object) => void;
|
||||
|
||||
/**
|
||||
* Updates the internal state of entered password.
|
||||
*
|
||||
@@ -159,6 +165,8 @@ class PasswordForm extends Component {
|
||||
this.setState({ enteredPassword: event.target.value });
|
||||
}
|
||||
|
||||
_onPasswordSubmit: (Object) => void;
|
||||
|
||||
/**
|
||||
* Invokes the passed in onSubmit callback to notify the parent that a
|
||||
* password submission has been attempted.
|
||||
|
||||
@@ -532,7 +532,7 @@ export function getDialInfoPageURL(
|
||||
*/
|
||||
export function _getDefaultPhoneNumber(
|
||||
dialInNumbers: Object,
|
||||
defaultCountry: string = 'US') {
|
||||
defaultCountry: string = 'US'): ?string {
|
||||
if (Array.isArray(dialInNumbers)) {
|
||||
// Dumbly return the first number if an array.
|
||||
return dialInNumbers[0];
|
||||
|
||||
@@ -121,7 +121,7 @@ function _beginAddPeople(store, next, action) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the {@code invite} event of the feature invite i.e. invites specific
|
||||
* Handles the {@code invite} event of the feature invite and invites specific
|
||||
* invitees to the current, ongoing conference.
|
||||
*
|
||||
* @param {Object} event - The details of the event.
|
||||
@@ -146,7 +146,7 @@ function _onInvite({ addPeopleControllerScope, externalAPIScope, invitees }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the {@code performQuery} event of the feature invite i.e. queries for
|
||||
* Handles the {@code performQuery} event of the feature invite and queries for
|
||||
* invitees who may subsequently be invited to the current, ongoing conference.
|
||||
*
|
||||
* @param {Object} event - The details of the event.
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
/* @flow */
|
||||
|
||||
import Lozenge from '@atlaskit/lozenge';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { Dialog } from '../../base/dialog';
|
||||
import { translate } from '../../base/i18n';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link KeyboardShortcutsDialog}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* A Map with keyboard keys as keys and translation keys as values.
|
||||
*/
|
||||
shortcutDescriptions: Object,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React {@link Component} which displays a dialog describing
|
||||
* registered keyboard shortcuts.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class KeyboardShortcutsDialog extends Component {
|
||||
/**
|
||||
* {@code KeyboardShortcutsDialog} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* A Map with keyboard keys as keys and translation keys as values.
|
||||
*/
|
||||
shortcutDescriptions: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
class KeyboardShortcutsDialog extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -48,7 +48,7 @@ export function selectParticipant() {
|
||||
|
||||
/**
|
||||
* Action to select the participant to be displayed in LargeVideo based on a
|
||||
* variety of factors: if there is a dominant or pinned speaker, or if there are
|
||||
* variety of factors: If there is a dominant or pinned speaker, or if there are
|
||||
* remote tracks, etc.
|
||||
*
|
||||
* @returns {Function}
|
||||
@@ -105,7 +105,7 @@ function _electLastVisibleRemoteVideo(tracks) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier of the participant who is to be on the stage i.e.
|
||||
* Returns the identifier of the participant who is to be on the stage and
|
||||
* should be displayed in {@code LargeVideo}.
|
||||
*
|
||||
* @param {Object} state - The Redux state from which the participant to be
|
||||
|
||||
@@ -288,7 +288,7 @@ class LocalRecordingInfoDialog extends Component<Props, State> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the moderator-only controls, i.e. stats of all users and the
|
||||
* Renders the moderator-only controls: The stats of all users and the
|
||||
* action links.
|
||||
*
|
||||
* @private
|
||||
|
||||
@@ -221,7 +221,7 @@ class RecordingController {
|
||||
/**
|
||||
* Registers listeners for XMPP events.
|
||||
*
|
||||
* @param {JitsiConference} conference - {@code JitsiConference} instance.
|
||||
* @param {JitsiConference} conference - A {@code JitsiConference} instance.
|
||||
* @returns {void}
|
||||
*/
|
||||
registerEvents(conference: Object) {
|
||||
@@ -633,7 +633,7 @@ class RecordingController {
|
||||
}
|
||||
|
||||
/* eslint-disable */
|
||||
return (Promise.resolve(): Promise<void>);
|
||||
return (Promise.resolve(): Promise<void>);
|
||||
// FIXME: better ways to satisfy flow and ESLint at the same time?
|
||||
/* eslint-enable */
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ class Encoder {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Note: only create instance when Flac.isReady() returns true.
|
||||
* Note: Only create instance when Flac.isReady() returns true.
|
||||
*
|
||||
* @param {number} sampleRate - Sample rate of the raw audio data.
|
||||
* @param {number} bitDepth - Bit depth (bit per sample).
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
/* @flow */
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { LoadingIndicator } from '../../../base/react';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link NetworkActivityIndicator}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Indicates whether there is network activity i.e. ongoing network
|
||||
* requests.
|
||||
*/
|
||||
_networkActivity: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* The React {@code Component} which renders a progress indicator when there
|
||||
* are ongoing network requests.
|
||||
*/
|
||||
class NetworkActivityIndicator extends Component<*> {
|
||||
/**
|
||||
* {@code NetworkActivityIndicator} React {@code Component}'s prop types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Indicates whether there is network activity i.e. ongoing network
|
||||
* requests.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_networkActivity: PropTypes.bool
|
||||
};
|
||||
|
||||
class NetworkActivityIndicator extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import {
|
||||
@@ -20,54 +19,71 @@ declare var APP: Object;
|
||||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link AbstractPageReloadOverlay}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The details is an object containing more information about the connection
|
||||
* failed (shard changes, was the computer suspended, etc.)
|
||||
*/
|
||||
details: Object,
|
||||
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* The indicator which determines whether the reload was caused by network
|
||||
* failure.
|
||||
*/
|
||||
isNetworkFailure: boolean,
|
||||
|
||||
/**
|
||||
* The reason for the error that will cause the reload.
|
||||
* NOTE: Used by PageReloadOverlay only.
|
||||
*/
|
||||
reason: string,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of
|
||||
* {@link AbstractPageReloadOverlay}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The translation key for the title of the overlay.
|
||||
*/
|
||||
message: string,
|
||||
|
||||
/**
|
||||
* Current value(time) of the timer.
|
||||
*/
|
||||
timeLeft: number,
|
||||
|
||||
/**
|
||||
* How long the overlay dialog will be displayed before the conference will
|
||||
* be reloaded.
|
||||
*/
|
||||
timeoutSeconds: number,
|
||||
|
||||
/**
|
||||
* The translation key for the title of the overlay.
|
||||
*/
|
||||
title: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements an abstract React {@link Component} for the page reload overlays.
|
||||
*/
|
||||
export default class AbstractPageReloadOverlay extends Component<*, *> {
|
||||
/**
|
||||
* {@code AbstractPageReloadOverlay} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The details is an object containing more information about the
|
||||
* connection failed (shard changes, was the computer suspended, etc.)
|
||||
*
|
||||
* @public
|
||||
* @type {object}
|
||||
*/
|
||||
details: PropTypes.object,
|
||||
|
||||
dispatch: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The indicator which determines whether the reload was caused by
|
||||
* network failure.
|
||||
*
|
||||
* @public
|
||||
* @type {boolean}
|
||||
*/
|
||||
isNetworkFailure: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The reason for the error that will cause the reload.
|
||||
* NOTE: Used by PageReloadOverlay only.
|
||||
*
|
||||
* @public
|
||||
* @type {string}
|
||||
*/
|
||||
reason: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {Function}
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
export default class AbstractPageReloadOverlay
|
||||
extends Component<Props, State> {
|
||||
/**
|
||||
* Determines whether this overlay needs to be rendered (according to a
|
||||
* specific redux state). Called by {@link OverlayContainer}.
|
||||
@@ -109,38 +125,6 @@ export default class AbstractPageReloadOverlay extends Component<*, *> {
|
||||
|
||||
_interval: ?IntervalID;
|
||||
|
||||
state: {
|
||||
|
||||
/**
|
||||
* The translation key for the title of the overlay.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
message: string,
|
||||
|
||||
/**
|
||||
* Current value(time) of the timer.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
timeLeft: number,
|
||||
|
||||
/**
|
||||
* How long the overlay dialog will be displayed before the
|
||||
* conference will be reloaded.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
timeoutSeconds: number,
|
||||
|
||||
/**
|
||||
* The translation key for the title of the overlay.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
title: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes a new AbstractPageReloadOverlay instance.
|
||||
*
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link AbstractSuspendedOverlay}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React {@link Component} for suspended overlay. Shown when a
|
||||
* suspend is detected.
|
||||
*/
|
||||
export default class AbstractSuspendedOverlay extends Component {
|
||||
/**
|
||||
* {@code AbstractSuspendedOverlay} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {Function}
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
export default class AbstractSuspendedOverlay extends Component<Props> {
|
||||
/**
|
||||
* Determines whether this overlay needs to be rendered (according to a
|
||||
* specific redux state). Called by {@link OverlayContainer}.
|
||||
@@ -29,7 +27,7 @@ export default class AbstractSuspendedOverlay extends Component {
|
||||
* @returns {boolean} - If this overlay needs to be rendered, {@code true};
|
||||
* {@code false}, otherwise.
|
||||
*/
|
||||
static needsRender(state) {
|
||||
static needsRender(state: Object) {
|
||||
return state['features/overlay'].suspendDetected;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,31 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link AbstractUserMediaPermissionsOverlay}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The browser which is used currently. The text is different for every
|
||||
* browser.
|
||||
*/
|
||||
browser: string,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React {@link Component} for overlay with guidance how to proceed
|
||||
* with gUM prompt.
|
||||
*/
|
||||
export default class AbstractUserMediaPermissionsOverlay extends Component {
|
||||
/**
|
||||
* {@code AbstractUserMediaPermissionsOverlay} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The browser which is used currently. The text is different for every
|
||||
* browser.
|
||||
*
|
||||
* @public
|
||||
* @type {string}
|
||||
*/
|
||||
browser: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {Function}
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
export default class AbstractUserMediaPermissionsOverlay
|
||||
extends Component<Props> {
|
||||
/**
|
||||
* Determines whether this overlay needs to be rendered (according to a
|
||||
* specific redux state). Called by {@link OverlayContainer}.
|
||||
@@ -38,7 +34,7 @@ export default class AbstractUserMediaPermissionsOverlay extends Component {
|
||||
* @returns {boolean} - If this overlay needs to be rendered, {@code true};
|
||||
* {@code false}, otherwise.
|
||||
*/
|
||||
static needsRender(state) {
|
||||
static needsRender(state: Object) {
|
||||
return state['features/overlay'].isMediaPermissionPromptVisible;
|
||||
}
|
||||
}
|
||||
@@ -52,7 +48,7 @@ export default class AbstractUserMediaPermissionsOverlay extends Component {
|
||||
* browser: string
|
||||
* }}
|
||||
*/
|
||||
export function abstractMapStateToProps(state) {
|
||||
export function abstractMapStateToProps(state: Object) {
|
||||
const { browser } = state['features/overlay'];
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -10,50 +11,40 @@ import {
|
||||
|
||||
import OverlayFrame from './OverlayFrame';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link FilmstripOnlyOverlayFrame}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The source (e.g. URI, URL) of the avatar image of the local participant.
|
||||
*/
|
||||
_avatar: string,
|
||||
|
||||
/**
|
||||
* The children components to be displayed into the overlay frame for
|
||||
* filmstrip only mode.
|
||||
*/
|
||||
children: React$Node,
|
||||
|
||||
/**
|
||||
* The css class name for the icon that will be displayed over the avatar.
|
||||
*/
|
||||
icon: string,
|
||||
|
||||
/**
|
||||
* Indicates the css style of the overlay. If true, then lighter; darker,
|
||||
* otherwise.
|
||||
*/
|
||||
isLightOverlay: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React Component for the frame of the overlays in filmstrip only
|
||||
* mode.
|
||||
*/
|
||||
class FilmstripOnlyOverlayFrame extends Component {
|
||||
/**
|
||||
* FilmstripOnlyOverlayFrame component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The source (e.g. URI, URL) of the avatar image of the local
|
||||
* participant.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_avatar: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The children components to be displayed into the overlay frame for
|
||||
* filmstrip only mode.
|
||||
*
|
||||
* @type {ReactElement}
|
||||
*/
|
||||
children: PropTypes.node.isRequired,
|
||||
|
||||
/**
|
||||
* The css class name for the icon that will be displayed over the
|
||||
* avatar.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
icon: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Indicates the css style of the overlay. If true, then lighter;
|
||||
* darker, otherwise.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
isLightOverlay: PropTypes.bool
|
||||
};
|
||||
|
||||
class FilmstripOnlyOverlayFrame extends Component<Props> {
|
||||
/**
|
||||
* Renders content related to the icon.
|
||||
*
|
||||
|
||||
@@ -1,32 +1,42 @@
|
||||
/* global interfaceConfig */
|
||||
/* @flow */
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link OverlayFrame}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The children components to be displayed into the overlay frame.
|
||||
*/
|
||||
children: React$Node,
|
||||
|
||||
/**
|
||||
* Indicates the css style of the overlay. If true, then lighter; darker,
|
||||
* otherwise.
|
||||
*/
|
||||
isLightOverlay: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link OverlayFrame}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Whether or not the application is currently displaying in filmstrip only
|
||||
* mode.
|
||||
*/
|
||||
filmstripOnly: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React {@link Component} for the frame of the overlays.
|
||||
*/
|
||||
export default class OverlayFrame extends Component {
|
||||
/**
|
||||
* OverlayFrame component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The children components to be displayed into the overlay frame.
|
||||
*/
|
||||
children: PropTypes.node.isRequired,
|
||||
|
||||
/**
|
||||
* Indicates the css style of the overlay. If true, then lighter;
|
||||
* darker, otherwise.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
isLightOverlay: PropTypes.bool
|
||||
};
|
||||
|
||||
export default class OverlayFrame extends Component<Props, State> {
|
||||
/**
|
||||
* Initializes a new AbstractOverlay instance.
|
||||
*
|
||||
@@ -34,7 +44,7 @@ export default class OverlayFrame extends Component {
|
||||
* instance is to be initialized.
|
||||
* @public
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
|
||||
@@ -1,46 +1,37 @@
|
||||
/* @flow */
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { reloadNow } from '../../app';
|
||||
import { translate } from '../../base/i18n';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link ReloadButton}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Reloads the page.
|
||||
*/
|
||||
_reloadNow: Function,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*/
|
||||
t: Function,
|
||||
|
||||
/**
|
||||
* The translation key for the text in the button.
|
||||
*/
|
||||
textKey: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React Component for button for the overlays that will reload
|
||||
* the page.
|
||||
*/
|
||||
class ReloadButton extends Component<*> {
|
||||
/**
|
||||
* PageReloadOverlay component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* Reloads the page.
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
_reloadNow: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {Function}
|
||||
*/
|
||||
t: PropTypes.func,
|
||||
|
||||
/**
|
||||
* The translation key for the text in the button.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
textKey: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
class ReloadButton extends Component<Props> {
|
||||
/**
|
||||
* Renders the button for relaod the page if necessary.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -8,13 +9,51 @@ import { Text } from '../../base/react';
|
||||
|
||||
import { STATUS_TO_I18N_KEY } from '../constants';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link PresenceLabel}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The current present status associated with the passed in participantID
|
||||
* prop.
|
||||
*/
|
||||
_presence: string,
|
||||
|
||||
/**
|
||||
* Class name for the presence label.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* Default presence status that will be displayed if user's presence status
|
||||
* is not available.
|
||||
*/
|
||||
defaultPresence: string,
|
||||
|
||||
/**
|
||||
* The ID of the participant whose presence status should display.
|
||||
*/
|
||||
participantID: string,
|
||||
|
||||
/**
|
||||
* Styles for the presence label.
|
||||
*/
|
||||
style: Object,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for displaying the current presence status of a
|
||||
* participant.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class PresenceLabel extends Component {
|
||||
class PresenceLabel extends Component<Props> {
|
||||
/**
|
||||
* The default values for {@code PresenceLabel} component's property types.
|
||||
*
|
||||
@@ -24,45 +63,6 @@ class PresenceLabel extends Component {
|
||||
_presence: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* {@code PresenceLabel} component's property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The current present status associated with the passed in
|
||||
* participantID prop.
|
||||
*/
|
||||
_presence: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Class name for the presence label.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Default presence status that will be displayed if user's presence
|
||||
* status is not available.
|
||||
*/
|
||||
defaultPresence: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The ID of the participant whose presence status shoul display.
|
||||
*/
|
||||
participantID: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Styles for the presence label.
|
||||
*/
|
||||
style: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: PropTypes.func
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
||||
102
react/features/recent-list/components/AbstractRecentList.js
Normal file
102
react/features/recent-list/components/AbstractRecentList.js
Normal file
@@ -0,0 +1,102 @@
|
||||
// @flow
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
createRecentClickedEvent,
|
||||
createRecentSelectedEvent,
|
||||
sendAnalytics
|
||||
} from '../../analytics';
|
||||
import { appNavigate } from '../../app';
|
||||
import {
|
||||
AbstractPage,
|
||||
Container,
|
||||
Text
|
||||
} from '../../base/react';
|
||||
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AbstractRecentList}
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The redux store's {@code dispatch} function.
|
||||
*/
|
||||
dispatch: Dispatch<*>,
|
||||
|
||||
/**
|
||||
* The translate function.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* An abstract component for the recent list.
|
||||
*
|
||||
*/
|
||||
export default class AbstractRecentList<P: Props> extends AbstractPage<P> {
|
||||
/**
|
||||
* Initializes a new {@code RecentList} instance.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: P) {
|
||||
super(props);
|
||||
|
||||
this._onPress = this._onPress.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#componentDidMount()}. Invoked
|
||||
* immediately after this component is mounted.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidMount() {
|
||||
sendAnalytics(createRecentSelectedEvent());
|
||||
}
|
||||
|
||||
_getRenderListEmptyComponent: () => React$Node;
|
||||
|
||||
/**
|
||||
* Returns a list empty component if a custom one has to be rendered instead
|
||||
* of the default one in the {@link NavigateSectionList}.
|
||||
*
|
||||
* @private
|
||||
* @returns {React$Component}
|
||||
*/
|
||||
_getRenderListEmptyComponent() {
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<Container
|
||||
className = 'meetings-list-empty'
|
||||
style = { styles.emptyListContainer }>
|
||||
<Text
|
||||
className = 'description'
|
||||
style = { styles.emptyListText }>
|
||||
{ t('welcomepage.recentListEmpty') }
|
||||
</Text>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
_onPress: string => {};
|
||||
|
||||
/**
|
||||
* Handles the list's navigate action.
|
||||
*
|
||||
* @private
|
||||
* @param {string} url - The url string to navigate to.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onPress(url) {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
sendAnalytics(createRecentClickedEvent('recent.meeting.tile'));
|
||||
|
||||
dispatch(appNavigate(url));
|
||||
}
|
||||
}
|
||||
@@ -2,25 +2,14 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import {
|
||||
createRecentClickedEvent,
|
||||
createRecentSelectedEvent,
|
||||
sendAnalytics
|
||||
} from '../../analytics';
|
||||
import { appNavigate, getDefaultURL } from '../../app';
|
||||
import { getDefaultURL } from '../../app';
|
||||
import { translate } from '../../base/i18n';
|
||||
import {
|
||||
AbstractPage,
|
||||
Container,
|
||||
NavigateSectionList,
|
||||
Text
|
||||
} from '../../base/react';
|
||||
import { NavigateSectionList } from '../../base/react';
|
||||
import type { Section } from '../../base/react';
|
||||
|
||||
import { deleteRecentListEntry } from '../actions';
|
||||
import { isRecentListEnabled, toDisplayableList } from '../functions';
|
||||
|
||||
import styles from './styles';
|
||||
import AbstractRecentList from './AbstractRecentList';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link RecentList}
|
||||
@@ -54,10 +43,13 @@ type Props = {
|
||||
};
|
||||
|
||||
/**
|
||||
* The cross platform container rendering the list of the recently joined rooms.
|
||||
* A class that renders the list of the recently joined rooms.
|
||||
*
|
||||
*/
|
||||
class RecentList extends AbstractPage<Props> {
|
||||
class RecentList extends AbstractRecentList<Props> {
|
||||
_getRenderListEmptyComponent: () => React$Node;
|
||||
_onPress: string => {};
|
||||
|
||||
/**
|
||||
* Initializes a new {@code RecentList} instance.
|
||||
*
|
||||
@@ -67,18 +59,6 @@ class RecentList extends AbstractPage<Props> {
|
||||
super(props);
|
||||
|
||||
this._onDelete = this._onDelete.bind(this);
|
||||
this._onPress = this._onPress.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#componentDidMount()}. Invoked
|
||||
* immediately after this component is mounted.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidMount() {
|
||||
sendAnalytics(createRecentSelectedEvent());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +70,12 @@ class RecentList extends AbstractPage<Props> {
|
||||
if (!isRecentListEnabled()) {
|
||||
return null;
|
||||
}
|
||||
const { disabled, t, _defaultServerURL, _recentList } = this.props;
|
||||
const {
|
||||
disabled,
|
||||
t,
|
||||
_defaultServerURL,
|
||||
_recentList
|
||||
} = this.props;
|
||||
const recentList = toDisplayableList(_recentList, t, _defaultServerURL);
|
||||
const slideActions = [ {
|
||||
backgroundColor: 'red',
|
||||
@@ -109,31 +94,6 @@ class RecentList extends AbstractPage<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_getRenderListEmptyComponent: () => Object;
|
||||
|
||||
/**
|
||||
* Returns a list empty component if a custom one has to be rendered instead
|
||||
* of the default one in the {@link NavigateSectionList}.
|
||||
*
|
||||
* @private
|
||||
* @returns {React$Component}
|
||||
*/
|
||||
_getRenderListEmptyComponent() {
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<Container
|
||||
className = 'navigate-section-list-empty'
|
||||
style = { styles.emptyListContainer }>
|
||||
<Text
|
||||
className = 'header-text-description'
|
||||
style = { styles.emptyListText }>
|
||||
{ t('welcomepage.recentListEmpty') }
|
||||
</Text>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
_onDelete: Object => void
|
||||
|
||||
/**
|
||||
@@ -146,23 +106,6 @@ class RecentList extends AbstractPage<Props> {
|
||||
_onDelete(itemId) {
|
||||
this.props.dispatch(deleteRecentListEntry(itemId));
|
||||
}
|
||||
|
||||
_onPress: string => Function;
|
||||
|
||||
/**
|
||||
* Handles the list's navigate action.
|
||||
*
|
||||
* @private
|
||||
* @param {string} url - The url string to navigate to.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onPress(url) {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
sendAnalytics(createRecentClickedEvent('recent.meeting.tile'));
|
||||
|
||||
dispatch(appNavigate(url));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user