diff --git a/css/_meetings_list.scss b/css/_meetings_list.scss index 6ffb71615..2555d6ba6 100644 --- a/css/_meetings_list.scss +++ b/css/_meetings_list.scss @@ -7,9 +7,8 @@ display: flex; flex-direction: column; position: relative; - width: 100%; - height: 100%; overflow: auto; + width: 100%; .meetings-list-empty { text-align: center; @@ -20,11 +19,34 @@ flex-direction: column; .description { - font-size: 16px; - padding: 20px; + color: #2f3237; + font-size: 14px; + line-height: 18px; + margin-bottom: 16px; + max-width: 436px; } } + .meetings-list-empty-image { + text-align: center; + margin: 24px 0 20px 0; + } + + .meetings-list-empty-button { + align-items: center; + color: #0163FF; + cursor: pointer; + display: flex; + font-size: 14px; + line-height: 18px; + margin: 24px 0 32px 0; + } + + .meetings-list-empty-icon { + display: inline-block; + margin-right: 8px; + } + .button { background: #0074E0; border-radius: 4px; @@ -32,7 +54,7 @@ display: flex; justify-content: center; align-items: center; - padding: 5px 10px; + padding: 8px; cursor: pointer; } @@ -43,12 +65,13 @@ } .item { - background: rgba(255,255,255,0.50); + background: #fff; box-sizing: border-box; + border-radius: 4px; display: inline-flex; - margin-top: 5px; - min-height: 92px; - width: 100%; + margin: 4px 4px 0 4px; + min-height: 60px; + width: calc(100% - 8px); word-break: break-word; display: flex; flex-direction: row; @@ -61,37 +84,41 @@ .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; - } + padding-left: 16px; + padding-top: 13px; } .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; - } + padding-left: 16px; + padding-top: 13px; + position: relative; } + .title { + font-size: 12px; + font-weight: 600; + line-height: 16px; + padding-bottom: 4px; + } + + .subtitle { + color: #5E6D7A; + font-weight: normal; + font-size: 12px; + line-height: 16px; + } + + .actions { display: flex; align-items: center; justify-content: center; flex-grow: 0; - padding-right: 30px; + margin-right: 16px; } &.with-click-handler { @@ -99,7 +126,7 @@ } &.with-click-handler:hover { - background-color: #75A7E7; + background-color: #c7ddff; } .add-button { @@ -120,4 +147,20 @@ display: block } } + + .delete-meeting { + display: none; + margin-right: 16px; + position: absolute; + + &> svg { + fill: #0074e0; + } + } + + .item:hover { + .delete-meeting { + display: block; + } + } } diff --git a/css/_responsive.scss b/css/_responsive.scss index 01fd767b0..2e917d3af 100644 --- a/css/_responsive.scss +++ b/css/_responsive.scss @@ -30,6 +30,67 @@ } @media only screen and (max-width: $verySmallScreen) { + .welcome { + #enter_room { + position: relative; + height: 42px; + + .welcome-page-button { + font-size: 16px; + left: 0; + position: absolute; + top: 68px; + text-align: center; + width: 100%; + } + } + + .header { + background: #06345E; + background-image: linear-gradient(180deg, rgba(8, 110, 202, 0.8) 0%, rgba(8, 110, 202, 0) 100%); + + #enter_room { + .enter-room-input-container { + padding-right: 0; + } + + .warning-without-link, + .warning-with-link { + top: 120px; + } + } + } + + .welcome-tabs { + display: none; + } + + .header-text-title { + text-align: center; + } + + .welcome-cards-container { + padding: 0; + } + + &.without-content { + .header { + height: 100%; + } + } + + #moderated-meetings { + display: none; + } + + .welcome-footer-row-block { + display: block; + } + .welcome-badge { + margin-right: 16px; + } + } + #videoResolutionLabel { display: none; } diff --git a/css/_variables.scss b/css/_variables.scss index e20787aba..44ea96863 100644 --- a/css/_variables.scss +++ b/css/_variables.scss @@ -161,71 +161,47 @@ $unsupportedDesktopBrowserTextFontSize: 21px; /** * The size of the default watermark. */ -$watermarkWidth: 186px; -$watermarkHeight: 74px; +$watermarkWidth: 71px; +$watermarkHeight: 32px; -$welcomePageWatermarkWidth: 186px; -$welcomePageWatermarkHeight: 74px; +$welcomePageWatermarkWidth: 71px; +$welcomePageWatermarkHeight: 32px; /** * Welcome page variables. */ $welcomePageDescriptionColor: #fff; $welcomePageFontFamily: inherit; -$welcomePageBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%); +$welcomePageBackground: none; $welcomePageTitleColor: #fff; -$welcomePageHeaderBackground: none; -$welcomePageHeaderBackgroundSmall: none; +$welcomePageHeaderBackground: linear-gradient(0deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)), url('/images/welcome-background.png'); $welcomePageHeaderBackgroundPosition: none; $welcomePageHeaderBackgroundRepeat: none; -$welcomePageHeaderBackgroundSize: none; +$welcomePageHeaderBackgroundSize: cover; $welcomePageHeaderPaddingBottom: 0px; -$welcomePageHeaderMinHeight: fit-content; +$welcomePageHeaderTitleMaxWidth: initial; +$welcomePageHeaderTextAlign: center; -$welcomePageHeaderTextMarginTop: 35px; -$welcomePageHeaderTextMarginBottom: 35px; -$welcomePageHeaderTextDisplay: flex; -$welcomePageHeaderTextWidth: 650px; +$welcomePageHeaderContainerDisplay: flex; +$welcomePageHeaderContainerMargin: 146px 32px 0 32px; -$welcomePageHeaderTextTitleMarginBottom: 16px; -$welcomePageHeaderTextTitleFontSize: 2.5rem; -$welcomePageHeaderTextTitleFontWeight: 500; -$welcomePageHeaderTextTitleLineHeight: 1.18; +$welcomePageHeaderTextTitleMarginBottom: 0; +$welcomePageHeaderTextTitleFontSize: 42px; +$welcomePageHeaderTextTitleFontWeight: normal; +$welcomePageHeaderTextTitleLineHeight: 50px; $welcomePageHeaderTextTitleOpacity: 1; -$welcomePageHeaderTextDescriptionDisplay: inherit; -$welcomePageHeaderTextDescriptionFontSize: 1rem; -$welcomePageHeaderTextDescriptionFontWeight: 400; -$welcomePageHeaderTextDescriptionLineHeight: 24px; -$welcomePageHeaderTextDescriptionMarginBottom: 20px; -$welcomePageHeaderTextDescriptionAlignSelf: inherit; - $welcomePageEnterRoomDisplay: flex; -$welcomePageEnterRoomWidth: 680px; -$welcomePageEnterRoomPadding: 25px 30px; -$welcomePageEnterRoomBorderRadius: 0px; - -$welcomePageEnterRoomInputContainerPadding: 0 8px 5px 0px; -$welcomePageEnterRoomInputContainerBorderWidth: 0px 0px 2px 0px; -$welcomePageEnterRoomInputContainerBorderStyle: solid; -$welcomePageEnterRoomInputContainerBorderImage: linear-gradient(to right, #dee1e6, #fff) 1; - -$welcomePageEnterRoomTitleDisplay: inherit; +$welcomePageEnterRoomWidth: calc(100% - 32px); +$welcomePageEnterRoomPadding: 4px; +$welcomePageEnterRoomMargin: 0 auto; $welcomePageTabContainerDisplay: flex; $welcomePageTabContentDisplay: inherit; $welcomePageTabButtonsDisplay: flex; $welcomePageTabDisplay: block; -$welcomePageButtonWidth: 51px; -$welcomePageButtonMinWidth: inherit; -$welcomePageButtonFontSize: 14px; -$welcomePageButtonHeight: 35px; -$welcomePageButtonFontWeight: inherit; -$welcomePageButtonBorderRadius: 4px; -$welcomePageButtonLineHeight: 35px; - /** * Deep-linking page variables. */ diff --git a/css/_welcome_page.scss b/css/_welcome_page.scss index a1171aa1e..68c57e705 100644 --- a/css/_welcome_page.scss +++ b/css/_welcome_page.scss @@ -5,6 +5,7 @@ body.welcome-page { .welcome { background-image: $welcomePageBackground; + background-color: #fff; display: flex; flex-direction: column; font-family: $welcomePageFontFamily; @@ -18,21 +19,15 @@ body.welcome-page { background-repeat: $welcomePageHeaderBackgroundRepeat; background-size: $welcomePageHeaderBackgroundSize; padding-bottom: $welcomePageHeaderPaddingBottom; - align-items: center; - display: flex; - flex-direction: column; - min-height: $welcomePageHeaderMinHeight; + background-color: #002637; + height: 480px; overflow: hidden; position: relative; - text-align: center; - .header-text { - display: $welcomePageHeaderTextDisplay; + .header-container { + display: $welcomePageHeaderContainerDisplay; flex-direction: column; - margin-top: $watermarkHeight + $welcomePageHeaderTextMarginTop; - margin-bottom: $welcomePageHeaderTextMarginBottom; - max-width: calc(100% - 40px); - width: $welcomePageHeaderTextWidth; + margin: $welcomePageHeaderContainerMargin; z-index: $zindex2; } @@ -42,50 +37,52 @@ body.welcome-page { font-weight: $welcomePageHeaderTextTitleFontWeight; line-height: $welcomePageHeaderTextTitleLineHeight; margin-bottom: $welcomePageHeaderTextTitleMarginBottom; + max-width: $welcomePageHeaderTitleMaxWidth; opacity: $welcomePageHeaderTextTitleOpacity; + text-align: $welcomePageHeaderTextAlign; } - .header-text-description { - display: $welcomePageHeaderTextDescriptionDisplay; - color: $welcomePageDescriptionColor; - font-size: $welcomePageHeaderTextDescriptionFontSize; - font-weight: $welcomePageHeaderTextDescriptionFontWeight; - line-height: $welcomePageHeaderTextDescriptionLineHeight; - margin-bottom: $welcomePageHeaderTextDescriptionMarginBottom; - align-self: $welcomePageHeaderTextDescriptionAlignSelf; + .header-text-subtitle { + color: #fff; + font-size: 20px; + font-weight: 600; + line-height: 26px; + margin: 16px 0 32px 0; + text-align: $welcomePageHeaderTextAlign; + } #enter_room { display: $welcomePageEnterRoomDisplay; align-items: center; - max-width: calc(100% - 40px); + max-width: 480px; width: $welcomePageEnterRoomWidth; z-index: $zindex2; background-color: #fff; padding: $welcomePageEnterRoomPadding; - border-radius: $welcomePageEnterRoomBorderRadius; + border-radius: 4px; + margin: $welcomePageEnterRoomMargin; .enter-room-input-container { - width: 100%; - padding: $welcomePageEnterRoomInputContainerPadding; text-align: left; color: #253858; + flex-grow: 1; height: fit-content; - - .enter-room-title { - display: $welcomePageEnterRoomTitleDisplay; - font-size: 18px; - font-weight: bold; - padding-bottom: 5px; - } + padding-right: 4px; + position: relative; .enter-room-input { - border-width: $welcomePageEnterRoomInputContainerBorderWidth; - border-style: $welcomePageEnterRoomInputContainerBorderStyle; - border-image: $welcomePageEnterRoomInputContainerBorderImage; + border: 0; + background: #fff; display: inline-block; + height: 50px; width: 100%; font-size: 14px; + padding-left: 10px; + + &:focus { + outline: auto 2px #005fcc; + } } .insecure-room-name-warning { @@ -109,16 +106,28 @@ body.welcome-page { } } + .warning-without-link { + position: absolute; + top: 44px; + left: -10px; + } + + .warning-with-link { + position: absolute; + top: 84px; + } + } #moderated-meetings { max-width: calc(100% - 40px); padding: 16px 0 39px 0; + margin: $welcomePageEnterRoomMargin; width: $welcomePageEnterRoomWidth; p { color: $welcomePageDescriptionColor; - text-align: left; + text-align: $welcomePageHeaderTextAlign; a { color: inherit; @@ -126,76 +135,70 @@ body.welcome-page { } } } + } - .tab-container { - font-size: 16px; + .tab-container { + font-size: 16px; + position: relative; + text-align: left; + display: $welcomePageTabContainerDisplay; + flex-direction: column; + + .tab-content{ + display: $welcomePageTabContentDisplay; + height: 250px; + margin: 5px 0px; + overflow: hidden; + flex-grow: 1; position: relative; - text-align: left; - min-height: 354px; - width: 710px; - background: #75A7E7; - display: $welcomePageTabContainerDisplay; - flex-direction: column; + } - .tab-content{ - display: $welcomePageTabContentDisplay; - margin: 5px 0px; - overflow: hidden; + .tab-buttons { + background-color: #c7ddff; + border-radius: 6px; + color: #0163FF; + font-size: 14px; + line-height: 18px; + margin: 4px; + display: $welcomePageTabButtonsDisplay; + + .tab { + background-color: #c7ddff; + border-radius: 7px; + cursor: pointer; + display: $welcomePageTabDisplay; flex-grow: 1; - position: relative; + margin: 2px; + padding: 7px 0; + text-align: center; - > * { - position: absolute; + &.selected { + background-color: #FFF; } } - .tab-buttons { - font-size: 18px; - color: #FFFFFF; - display: $welcomePageTabButtonsDisplay; - flex-grow: 0; - flex-direction: row; - min-height: 54px; - width: 100%; - - .tab { - display: $welcomePageTabDisplay; - 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 { - width: $welcomePageButtonWidth; - min-width: $welcomePageButtonMinWidth; - height: $welcomePageButtonHeight; - font-size: $welcomePageButtonFontSize; - font-weight: $welcomePageButtonFontWeight; + border: 0; + font-size: 14px; background: #0074E0; - border-radius: $welcomePageButtonBorderRadius; + border-radius: 3px; color: #FFFFFF; - text-align: center; - vertical-align: middle; - line-height: $welcomePageButtonLineHeight; cursor: pointer; + padding: 16px 20px; + + &:focus-within { + outline: auto 2px #022e61; + } } .welcome-page-settings { + background: rgba(255, 255, 255, 0.38); + border-radius: 3px; color: $welcomePageDescriptionColor; + padding: 4px; position: absolute; top: 32px; right: 32px; @@ -217,4 +220,83 @@ body.welcome-page { height: $welcomePageWatermarkHeight; } } + + &.without-content { + .welcome-card { + min-width: 500px; + } + } + + .welcome-cards-container { + color:#131519; + padding-top: 40px; + } + + .welcome-card-row { + display: flex; + justify-content: center; + padding: 0 32px; + } + + .welcome-card-text { + padding: 32px; + } + + .welcome-card { + width: 49%; + border-radius: 8px; + + &--dark { + background: #444447; + color: #fff; + } + + &--blue { + background: #D5E5FF; + } + + &--grey { + background: #F2F3F4; + } + + &--shadow { + box-shadow: 0px 4px 30px rgba(0, 0, 0, 0.15); + } + } + + .welcome-footer { + background: #131519; + color: #fff; + margin-top: 40px; + position: relative; + } + + .welcome-footer-centered { + max-width: 688px; + margin: 0 auto; + } + + .welcome-footer-padded { + padding: 0px 16px; + } + + .welcome-footer-row-block { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #424447; + + &:last-child { + border-bottom: none; + } + } + + .welcome-footer--row-1 { + padding: 40px 0 24px 0; + } + + .welcome-footer-row-1-text { + max-width: 200px; + margin-right: 16px; + } } diff --git a/images/app-store-badge.png b/images/app-store-badge.png new file mode 100644 index 000000000..c774c29f4 Binary files /dev/null and b/images/app-store-badge.png differ diff --git a/images/calendar.svg b/images/calendar.svg new file mode 100644 index 000000000..133f2dd24 --- /dev/null +++ b/images/calendar.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/images/f-droid-badge.png b/images/f-droid-badge.png new file mode 100644 index 000000000..6efa1c2f8 Binary files /dev/null and b/images/f-droid-badge.png differ diff --git a/images/google-play-badge.png b/images/google-play-badge.png new file mode 100644 index 000000000..d34533767 Binary files /dev/null and b/images/google-play-badge.png differ diff --git a/images/watermark.png b/images/watermark.png deleted file mode 100644 index 6fa553d3b..000000000 Binary files a/images/watermark.png and /dev/null differ diff --git a/images/watermark.svg b/images/watermark.svg new file mode 100644 index 000000000..7286107ca --- /dev/null +++ b/images/watermark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/images/welcome-background.png b/images/welcome-background.png new file mode 100644 index 000000000..8509333b5 Binary files /dev/null and b/images/welcome-background.png differ diff --git a/index.html b/index.html index 60a6e9c06..dc51bed1c 100644 --- a/index.html +++ b/index.html @@ -182,6 +182,7 @@ + diff --git a/interface_config.js b/interface_config.js index 45358fc0b..994710884 100644 --- a/interface_config.js +++ b/interface_config.js @@ -46,9 +46,9 @@ var interfaceConfig = { DEFAULT_BACKGROUND: '#474747', DEFAULT_LOCAL_DISPLAY_NAME: 'me', - DEFAULT_LOGO_URL: 'images/watermark.png', + DEFAULT_LOGO_URL: 'images/watermark.svg', DEFAULT_REMOTE_DISPLAY_NAME: 'Fellow Jitster', - DEFAULT_WELCOME_PAGE_LOGO_URL: 'images/watermark.png', + DEFAULT_WELCOME_PAGE_LOGO_URL: 'images/watermark.svg', DISABLE_DOMINANT_SPEAKER_INDICATOR: false, @@ -86,7 +86,9 @@ var interfaceConfig = { */ DISABLE_VIDEO_BACKGROUND: false, - DISPLAY_WELCOME_PAGE_CONTENT: true, + DISPLAY_WELCOME_FOOTER: true, + DISPLAY_WELCOME_PAGE_ADDITIONAL_CARD: false, + DISPLAY_WELCOME_PAGE_CONTENT: false, DISPLAY_WELCOME_PAGE_TOOLBAR_ADDITIONAL_CONTENT: false, ENABLE_DIAL_OUT: true, @@ -136,6 +138,21 @@ var interfaceConfig = { */ MOBILE_APP_PROMO: true, + /** + * Specify custom URL for downloading android mobile app. + */ + MOBILE_DOWNLOAD_LINK_ANDROID: 'https://play.google.com/store/apps/details?id=org.jitsi.meet', + + /** + * Specify custom URL for downloading f droid app. + */ + MOBILE_DOWNLOAD_LINK_F_DROID: 'https://f-droid.org/en/packages/org.jitsi.meet/', + + /** + * Specify URL for downloading ios mobile app. + */ + MOBILE_DOWNLOAD_LINK_IOS: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905', + NATIVE_APP_NAME: 'Jitsi Meet', // Names of browsers which should show a warning stating the current browser @@ -234,16 +251,6 @@ var interfaceConfig = { */ // TILE_VIEW_MAX_COLUMNS: 5, - /** - * Specify custom URL for downloading android mobile app. - */ - // MOBILE_DOWNLOAD_LINK_ANDROID: 'https://play.google.com/store/apps/details?id=org.jitsi.meet', - - /** - * Specify URL for downloading ios mobile app. - */ - // MOBILE_DOWNLOAD_LINK_IOS: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905', - /** * Specify Firebase dynamic link properties for the mobile apps. */ diff --git a/lang/main.json b/lang/main.json index 5edc53050..bc1f95d25 100644 --- a/lang/main.json +++ b/lang/main.json @@ -878,6 +878,8 @@ "goSmall": "GO", "info": "Dial-in info", "join": "CREATE / JOIN", + "jitsiMeet": "Jitsi Meet", + "jitsiOnMobile": "Jitsi on mobile – download our apps and start a meeting from anywhere", "moderatedMessage": "Or book a meeting URL in advance where you are the only moderator.", "privacy": "Privacy", "recentList": "Recent", @@ -888,6 +890,8 @@ "roomname": "Enter room name", "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", + "secureMeetings": "Secure and high quality meetings", + "startMeeting": "Start meeting", "terms": "Terms", "title": "Secure, fully featured, and completely free video conferencing" }, diff --git a/react/features/base/icons/svg/calendar-plus.svg b/react/features/base/icons/svg/calendar-plus.svg new file mode 100644 index 000000000..f330390b4 --- /dev/null +++ b/react/features/base/icons/svg/calendar-plus.svg @@ -0,0 +1,3 @@ + + + diff --git a/react/features/base/icons/svg/index.js b/react/features/base/icons/svg/index.js index 402b5fd16..32caea7ca 100644 --- a/react/features/base/icons/svg/index.js +++ b/react/features/base/icons/svg/index.js @@ -11,6 +11,7 @@ export { default as IconAudioOnly } from './visibility.svg'; export { default as IconAudioOnlyOff } from './visibility-off.svg'; export { default as IconAudioRoute } from './volume.svg'; export { default as IconBlurBackground } from './blur-background.svg'; +export { default as IconPlusCalendar } from './calendar-plus.svg'; export { default as IconCamera } from './camera.svg'; export { default as IconCameraDisabled } from './camera-disabled.svg'; export { default as IconCancelSelection } from './cancel.svg'; diff --git a/react/features/base/react/components/web/MeetingsList.js b/react/features/base/react/components/web/MeetingsList.js index 1474328e2..80d9fd8de 100644 --- a/react/features/base/react/components/web/MeetingsList.js +++ b/react/features/base/react/components/web/MeetingsList.js @@ -6,6 +6,7 @@ import { getLocalizedDateFormatter, getLocalizedDurationFormatter } from '../../../i18n'; +import { Icon, IconTrash } from '../../../icons'; import Container from './Container'; import Text from './Text'; @@ -38,9 +39,9 @@ type Props = { meetings: Array, /** - * Defines what happens when an item in the section list is clicked + * Handler for deleting an item. */ - onItemClick: Function + onItemDelete?: Function }; /** @@ -138,6 +139,25 @@ export default class MeetingsList extends Component { return null; } + _onDelete: Object => Function; + + /** + * Returns a function that is used on the onDelete callback. + * + * @param {Object} item - The item to be deleted. + * @private + * @returns {Function} + */ + _onDelete(item) { + const { onItemDelete } = this.props; + + return evt => { + evt.stopPropagation(); + + onItemDelete && onItemDelete(item); + }; + } + _renderItem: (Object, number) => React$Node; /** @@ -156,7 +176,7 @@ export default class MeetingsList extends Component { title, url } = meeting; - const { hideURL = false } = this.props; + const { hideURL = false, onItemDelete } = this.props; const onPress = this._onPress(url); const rootClassName = `item ${ @@ -168,10 +188,10 @@ export default class MeetingsList extends Component { key = { index } onClick = { onPress }> - + { _toDateString(date) } - + { _toTimeString(time) } @@ -187,13 +207,18 @@ export default class MeetingsList extends Component { } { typeof duration === 'number' ? ( - + { getLocalizedDurationFormatter(duration) } ) : null } { elementAfter || null } + + { onItemDelete && } ); diff --git a/react/features/calendar-sync/components/CalendarList.web.js b/react/features/calendar-sync/components/CalendarList.web.js index 5a0162ef3..67006a80b 100644 --- a/react/features/calendar-sync/components/CalendarList.web.js +++ b/react/features/calendar-sync/components/CalendarList.web.js @@ -8,6 +8,7 @@ import { sendAnalytics } from '../../analytics'; import { translate } from '../../base/i18n'; +import { Icon, IconPlusCalendar } from '../../base/icons'; import { AbstractPage } from '../../base/react'; import { connect } from '../../base/redux'; import { openSettingsDialog, SETTINGS_TABS } from '../../settings'; @@ -185,16 +186,22 @@ class CalendarList extends AbstractPage { return (
-

+

+ +
+
{ t('welcomepage.connectCalendarText', { app: interfaceConfig.APP_NAME, provider: interfaceConfig.PROVIDER_NAME }) } -

+
- { t('welcomepage.connectCalendarButton') } + + { t('welcomepage.connectCalendarButton') }
); diff --git a/react/features/calendar-sync/components/JoinButton.web.js b/react/features/calendar-sync/components/JoinButton.web.js index 862df57bc..5cff5868b 100644 --- a/react/features/calendar-sync/components/JoinButton.web.js +++ b/react/features/calendar-sync/components/JoinButton.web.js @@ -4,6 +4,7 @@ import Tooltip from '@atlaskit/tooltip'; import React, { Component } from 'react'; import { translate } from '../../base/i18n'; +import { Icon, IconAdd } from '../../base/icons'; /** * The type of the React {@code Component} props of {@link JoinButton}. @@ -60,7 +61,9 @@ class JoinButton extends Component {
- { t('calendarSync.join') } +
); diff --git a/react/features/recent-list/components/RecentList.web.js b/react/features/recent-list/components/RecentList.web.js index cc4fc7940..1f68c4428 100644 --- a/react/features/recent-list/components/RecentList.web.js +++ b/react/features/recent-list/components/RecentList.web.js @@ -6,6 +6,7 @@ import type { Dispatch } from 'redux'; import { translate } from '../../base/i18n'; import { MeetingsList } from '../../base/react'; import { connect } from '../../base/redux'; +import { deleteRecentListEntry } from '../actions'; import { isRecentListEnabled, toDisplayableList } from '../functions'; import AbstractRecentList from './AbstractRecentList'; @@ -55,6 +56,19 @@ class RecentList extends AbstractRecentList { this._getRenderListEmptyComponent = this._getRenderListEmptyComponent.bind(this); this._onPress = this._onPress.bind(this); + this._onItemDelete = this._onItemDelete.bind(this); + } + + _onItemDelete: Object => void; + + /** + * Deletes a recent entry. + * + * @param {Object} entry - The entry to be deleted. + * @inheritdoc + */ + _onItemDelete(entry) { + this.props.dispatch(deleteRecentListEntry(entry)); } /** @@ -78,6 +92,7 @@ class RecentList extends AbstractRecentList { hideURL = { true } listEmptyComponent = { this._getRenderListEmptyComponent() } meetings = { recentList } + onItemDelete = { this._onItemDelete } onPress = { this._onPress } /> ); } diff --git a/react/features/recent-list/functions.web.js b/react/features/recent-list/functions.web.js index aac587085..1c8a67d6e 100644 --- a/react/features/recent-list/functions.web.js +++ b/react/features/recent-list/functions.web.js @@ -12,7 +12,7 @@ import { parseURIString, safeDecodeURIComponent } from '../base/util'; */ export function toDisplayableList(recentList) { return ( - recentList.slice(-3).reverse() + recentList.reverse() .map(item => { return { date: item.date, diff --git a/react/features/welcome/components/Tabs.js b/react/features/welcome/components/Tabs.js index 6ed8c31f5..5a3d47952 100644 --- a/react/features/welcome/components/Tabs.js +++ b/react/features/welcome/components/Tabs.js @@ -47,9 +47,6 @@ export default class Tabs extends Component { return (
-
- { content } -
{ tabs.length > 1 ? (
{ @@ -64,6 +61,9 @@ export default class Tabs extends Component { }
) : null } +
+ { content } +
); } diff --git a/react/features/welcome/components/WelcomePage.web.js b/react/features/welcome/components/WelcomePage.web.js index af39f2d7c..a59ac8d50 100644 --- a/react/features/welcome/components/WelcomePage.web.js +++ b/react/features/welcome/components/WelcomePage.web.js @@ -20,12 +20,6 @@ import Tabs from './Tabs'; */ export const ROOM_NAME_VALIDATE_PATTERN_STR = '^[^?&:\u0022\u0027%#]+$'; -/** - * Maximum number of pixels corresponding to a mobile layout. - * @type {number} - */ -const WINDOW_WIDTH_THRESHOLD = 425; - /** * The Web container rendering the welcome page. * @@ -78,6 +72,17 @@ class WelcomePage extends AbstractWelcomePage { */ this._additionalToolbarContentRef = null; + this._additionalCardRef = null; + + /** + * The template to use as the additional card displayed near the main one. + * + * @private + * @type {HTMLTemplateElement|null} + */ + this._additionalCardTemplate = document.getElementById( + 'welcome-page-additional-card-template'); + /** * The template to use as the main content for the welcome page. If * not found then only the welcome page head will display. @@ -102,12 +107,14 @@ class WelcomePage extends AbstractWelcomePage { // Bind event handlers so they are only bound once per instance. this._onFormSubmit = this._onFormSubmit.bind(this); this._onRoomChange = this._onRoomChange.bind(this); + this._setAdditionalCardRef = this._setAdditionalCardRef.bind(this); this._setAdditionalContentRef = this._setAdditionalContentRef.bind(this); this._setRoomInputRef = this._setRoomInputRef.bind(this); this._setAdditionalToolbarContentRef = this._setAdditionalToolbarContentRef.bind(this); this._onTabSelected = this._onTabSelected.bind(this); + this._renderFooter = this._renderFooter.bind(this); } /** @@ -137,6 +144,12 @@ class WelcomePage extends AbstractWelcomePage { this._additionalToolbarContentTemplate.content.cloneNode(true) ); } + + if (this._shouldShowAdditionalCard()) { + this._additionalCardRef.appendChild( + this._additionalCardTemplate.content.cloneNode(true) + ); + } } /** @@ -159,10 +172,10 @@ class WelcomePage extends AbstractWelcomePage { */ render() { const { _moderatedRoomServiceUrl, t } = this.props; - const { APP_NAME, DEFAULT_WELCOME_PAGE_LOGO_URL } = interfaceConfig; + const { DEFAULT_WELCOME_PAGE_LOGO_URL, DISPLAY_WELCOME_FOOTER } = interfaceConfig; + const showAdditionalCard = this._shouldShowAdditionalCard(); const showAdditionalContent = this._shouldShowAdditionalContent(); const showAdditionalToolbarContent = this._shouldShowAdditionalToolbarContent(); - const showResponsiveText = this._shouldShowResponsiveText(); return (
+
-
+

- { t('welcomepage.title') } + { t('welcomepage.jitsiMeet') }

-

- { t('welcomepage.appDescription', - { app: APP_NAME }) } -

-
-
-
-
- { t('welcomepage.enterRoomTitle') } + + { t('welcomepage.secureMeetings')} + +
+
+
+ +
+ { this._renderInsecureRoomNameWarning() } +
+
-
- - { this._renderInsecureRoomNameWarning() } -
+
-
- { - showResponsiveText - ? t('welcomepage.goSmall') - : t('welcomepage.go') - } -
-
- { _moderatedRoomServiceUrl && ( -
-

- { - translateToHTML( + + { _moderatedRoomServiceUrl && ( +

+

+ { + translateToHTML( t, 'welcomepage.moderatedMessage', { url: _moderatedRoomServiceUrl }) - } -

-
- ) } - { this._renderTabs() } + } +

+
)} +
- { showAdditionalContent - ?
- : null } + +
+
+
+ { this._renderTabs() } +
+ { showAdditionalCard + ?
+ : null } +
+ + { showAdditionalContent + ?
+ : null } +
+ { DISPLAY_WELCOME_FOOTER && this._renderFooter()}
+ ); } @@ -302,6 +334,45 @@ class WelcomePage extends AbstractWelcomePage { this.setState({ selectedTab: tabIndex }); } + /** + * Renders the footer. + * + * @returns {ReactElement} + */ + _renderFooter() { + const { t } = this.props; + const { + MOBILE_DOWNLOAD_LINK_ANDROID, + MOBILE_DOWNLOAD_LINK_F_DROID, + MOBILE_DOWNLOAD_LINK_IOS + } = interfaceConfig; + + return (); + } + /** * Renders tabs to show previous meetings and upcoming calendar events. The * tabs are purposefully hidden on mobile browsers. @@ -342,6 +413,19 @@ class WelcomePage extends AbstractWelcomePage { tabs = { tabs } />); } + /** + * Sets the internal reference to the HTMLDivElement used to hold the + * additional card shown near the tabs card. + * + * @param {HTMLDivElement} el - The HTMLElement for the div that is the root + * of the welcome page content. + * @private + * @returns {void} + */ + _setAdditionalCardRef(el) { + this._additionalCardRef = el; + } + /** * Sets the internal reference to the HTMLDivElement used to hold the * welcome page content. @@ -380,6 +464,19 @@ class WelcomePage extends AbstractWelcomePage { this._roomInputRef = el; } + /** + * Returns whether or not an additional card should be displayed near the tabs. + * + * @private + * @returns {boolean} + */ + _shouldShowAdditionalCard() { + return interfaceConfig.DISPLAY_WELCOME_PAGE_ADDITIONAL_CARD + && this._additionalCardTemplate + && this._additionalCardTemplate.content + && this._additionalCardTemplate.innerHTML.trim(); + } + /** * Returns whether or not additional content should be displayed below * the welcome page's header for entering a room name. @@ -407,20 +504,6 @@ class WelcomePage extends AbstractWelcomePage { && this._additionalToolbarContentTemplate.content && this._additionalToolbarContentTemplate.innerHTML.trim(); } - - /** - * Returns whether or not the screen has a size smaller than a custom margin - * and therefore display different text in the go button. - * - * @private - * @returns {boolean} - */ - _shouldShowResponsiveText() { - const { innerWidth } = window; - - return innerWidth <= WINDOW_WIDTH_THRESHOLD; - } - } export default translate(connect(_mapStateToProps)(WelcomePage)); diff --git a/static/welcomePageAdditionalCard.html b/static/welcomePageAdditionalCard.html new file mode 100644 index 000000000..9c938da12 --- /dev/null +++ b/static/welcomePageAdditionalCard.html @@ -0,0 +1 @@ +