Merge pull request #1 from antobinary/test-ghazi-pr
Extra commit for html5 client emojis
This commit is contained in:
commit
fd6092e5a8
@ -10,8 +10,6 @@ import {
|
||||
getCaptionsStatus,
|
||||
} from './service';
|
||||
|
||||
import { setDefaultSettings } from '../settings/service';
|
||||
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Users from '/imports/api/users';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
@ -53,7 +51,6 @@ class AppContainer extends Component {
|
||||
const APP_CONFIG = Meteor.settings.public.app;
|
||||
|
||||
const init = () => {
|
||||
setDefaultSettings();
|
||||
if (APP_CONFIG.autoJoinAudio) {
|
||||
showModal(<AudioModalContainer />);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import SettingsService from '/imports/ui/components/settings/service';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
|
||||
let currentModal = {
|
||||
component: null,
|
||||
@ -23,13 +23,13 @@ const clearModal = () => {
|
||||
};
|
||||
|
||||
const getCaptionsStatus = () => {
|
||||
const settings = SettingsService.getSettingsFor('cc');
|
||||
return settings ? settings.closedCaptions : false;
|
||||
const ccSettings = Settings.cc;
|
||||
return ccSettings ? ccSettings.enabled : false;
|
||||
};
|
||||
|
||||
const getFontSize = () => {
|
||||
const settings = SettingsService.getSettingsFor('application');
|
||||
return settings ? settings.fontSize : '16px';
|
||||
const applicationSettings = Settings.application;
|
||||
return applicationSettings ? applicationSettings.fontSize : '16px';
|
||||
};
|
||||
|
||||
function meetingIsBreakout() {
|
||||
|
@ -6,6 +6,7 @@ import styles from './styles';
|
||||
|
||||
import MessageFormActions from './message-form-actions/component';
|
||||
import TextareaAutosize from 'react-autosize-textarea';
|
||||
import Button from '../../button/component';
|
||||
|
||||
const propTypes = {
|
||||
};
|
||||
@ -42,9 +43,12 @@ class MessageForm extends Component {
|
||||
this.handleMessageChange = this.handleMessageChange.bind(this);
|
||||
this.handleMessageKeyDown = this.handleMessageKeyDown.bind(this);
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
|
||||
}
|
||||
|
||||
handleMessageKeyDown(e) {
|
||||
|
||||
//TODO Prevent send message pressing enter on mobile and/or virtual keyboard
|
||||
if (e.keyCode === 13 && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
|
||||
@ -104,9 +108,9 @@ class MessageForm extends Component {
|
||||
<TextareaAutosize
|
||||
className={styles.input}
|
||||
id="message-input"
|
||||
placeholder={ intl.formatMessage(messages.inputPlaceholder, { name: chatName }) }
|
||||
placeholder={intl.formatMessage(messages.inputPlaceholder, { name: chatName })}
|
||||
aria-controls={this.props.chatAreaId}
|
||||
aria-label={ intl.formatMessage(messages.inputLabel, { name: chatTitle }) }
|
||||
aria-label={intl.formatMessage(messages.inputLabel, { name: chatTitle })}
|
||||
autoCorrect="off"
|
||||
autoComplete="off"
|
||||
spellCheck="true"
|
||||
@ -115,13 +119,16 @@ class MessageForm extends Component {
|
||||
onChange={this.handleMessageChange}
|
||||
onKeyDown={this.handleMessageKeyDown}
|
||||
/>
|
||||
<input
|
||||
ref="btnSubmit"
|
||||
className={'sr-only'}
|
||||
<Button
|
||||
className={styles.sendButton}
|
||||
aria-label={intl.formatMessage(messages.submitLabel)}
|
||||
type="submit"
|
||||
disabled={disabled}
|
||||
value={ intl.formatMessage(messages.submitLabel) }
|
||||
/>
|
||||
label={intl.formatMessage(messages.submitLabel)}
|
||||
hideLabel={true}
|
||||
icon={"right_arrow"}
|
||||
onClick={()=>{}}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
@ -61,3 +61,14 @@
|
||||
background-color: fade-out($color-gray-lighter, .75);
|
||||
}
|
||||
}
|
||||
|
||||
.sendButton {
|
||||
@extend .input;
|
||||
border-left: 0px;
|
||||
min-width: 1rem;
|
||||
max-width: 2.5rem;
|
||||
|
||||
> [class*=" icon-bbb-"] {
|
||||
color: $color-gray-light;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import _ from 'lodash';
|
||||
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import UserListService from '/imports/ui/components/user-list/service';
|
||||
import SettingsService from '/imports/ui/components/settings/service';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
|
||||
class ChatNotificationContainer extends Component {
|
||||
constructor(props) {
|
||||
@ -30,7 +30,7 @@ class ChatNotificationContainer extends Component {
|
||||
}
|
||||
|
||||
export default createContainer(({ currentChatID }) => {
|
||||
const AppSettings = SettingsService.getSettingsFor('application');
|
||||
const AppSettings = Settings.application;
|
||||
|
||||
const unreadMessagesCount = UserListService.getOpenChats()
|
||||
.map(chat => chat.unreadCounter)
|
||||
|
@ -1,13 +1,13 @@
|
||||
import Captions from '/imports/api/captions';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Storage from '/imports/ui/services/storage/session';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
|
||||
let getCCData = () => {
|
||||
const meetingID = Auth.meetingID;
|
||||
|
||||
const ccSettings = Storage.getItem('settings_cc');
|
||||
const ccSettings = Settings.cc;
|
||||
|
||||
let CCEnabled = ccSettings.closedCaptions;
|
||||
let CCEnabled = ccSettings.enabled;
|
||||
|
||||
//associative array that keeps locales with arrays of string objects related to those locales
|
||||
let captions = [];
|
||||
|
@ -7,6 +7,7 @@ import Audio from '/imports/ui/components/settings/submenus/audio/component';
|
||||
import Application from '/imports/ui/components/settings/submenus/application/container';
|
||||
import Participants from '/imports/ui/components/settings/submenus/participants/component';
|
||||
import Video from '/imports/ui/components/settings/submenus/video/component';
|
||||
import _ from 'lodash';
|
||||
|
||||
import Icon from '../icon/component';
|
||||
import styles from './styles';
|
||||
@ -26,11 +27,11 @@ export default class Settings extends Component {
|
||||
|
||||
this.state = {
|
||||
current: {
|
||||
audio,
|
||||
video,
|
||||
application,
|
||||
cc,
|
||||
participants,
|
||||
audio: _.clone(audio),
|
||||
video: _.clone(video),
|
||||
application: _.clone(application),
|
||||
cc: _.clone(cc),
|
||||
participants: _.clone(participants),
|
||||
},
|
||||
saved: {
|
||||
audio: _.clone(audio),
|
||||
@ -42,7 +43,7 @@ export default class Settings extends Component {
|
||||
selectedTab: 0,
|
||||
};
|
||||
|
||||
this.handleSettingsApply = props.updateSettings;
|
||||
this.updateSettings = props.updateSettings;
|
||||
this.handleUpdateSettings = this.handleUpdateSettings.bind(this);
|
||||
this.handleSelectTab = this.handleSelectTab.bind(this);
|
||||
}
|
||||
@ -57,7 +58,7 @@ export default class Settings extends Component {
|
||||
title="Settings"
|
||||
confirm={{
|
||||
callback: (() => {
|
||||
this.handleSettingsApply(this.state.current);
|
||||
this.updateSettings(this.state.current);
|
||||
}),
|
||||
label: 'Save',
|
||||
description: 'Saves the changes and close the settings menu',
|
||||
|
@ -2,11 +2,12 @@ import React, { Component, PropTypes } from 'react';
|
||||
import { createContainer } from 'meteor/react-meteor-data';
|
||||
import _ from 'lodash';
|
||||
import Settings from './component';
|
||||
import SettingsService from '/imports/ui/services/settings';
|
||||
|
||||
import {
|
||||
getSettingsFor,
|
||||
updateSettings,
|
||||
getClosedCaptionLocales,
|
||||
getUserRoles,
|
||||
updateSettings,
|
||||
} from './service';
|
||||
|
||||
class SettingsContainer extends Component {
|
||||
@ -19,11 +20,11 @@ class SettingsContainer extends Component {
|
||||
|
||||
export default createContainer(() => {
|
||||
return {
|
||||
audio: getSettingsFor('audio'),
|
||||
video: getSettingsFor('video'),
|
||||
application: getSettingsFor('application'),
|
||||
cc: getSettingsFor('cc'),
|
||||
participants: getSettingsFor('participants'),
|
||||
audio: SettingsService.audio,
|
||||
video: SettingsService.video,
|
||||
application: SettingsService.application,
|
||||
cc: SettingsService.cc,
|
||||
participants: SettingsService.participants,
|
||||
updateSettings,
|
||||
locales: getClosedCaptionLocales(),
|
||||
isModerator: getUserRoles() === 'MODERATOR',
|
||||
|
@ -1,18 +1,8 @@
|
||||
import Storage from '/imports/ui/services/storage/session';
|
||||
import Users from '/imports/api/users';
|
||||
import Captions from '/imports/api/captions';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import _ from 'lodash';
|
||||
|
||||
const updateSettings = (obj) => {
|
||||
Object.keys(obj).forEach(k => Storage.setItem(`settings_${k}`, obj[k]));
|
||||
};
|
||||
|
||||
const getSettingsFor = (key) => {
|
||||
const setting = Storage.getItem(`settings_${key}`);
|
||||
|
||||
return setting;
|
||||
};
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
|
||||
const getClosedCaptionLocales = () => {
|
||||
//list of unique locales in the Captions Collection
|
||||
@ -34,61 +24,13 @@ const getUserRoles = () => {
|
||||
return user.role;
|
||||
};
|
||||
|
||||
const setDefaultSettings = () => {
|
||||
const defaultSettings = {
|
||||
application: {
|
||||
chatAudioNotifications: false,
|
||||
chatPushNotifications: false,
|
||||
fontSize: '16px',
|
||||
},
|
||||
audio: {
|
||||
inputDeviceId: undefined,
|
||||
outputDeviceId: undefined,
|
||||
},
|
||||
video: {
|
||||
viewParticipantsWebcams: true,
|
||||
},
|
||||
cc: {
|
||||
backgroundColor: '#FFFFFF',
|
||||
fontColor: '#000000',
|
||||
closedCaptions: false,
|
||||
fontFamily: 'Calibri',
|
||||
fontSize: -1,
|
||||
locale: undefined,
|
||||
takeOwnership: false,
|
||||
},
|
||||
participants: {
|
||||
muteAll: false,
|
||||
lockAll: false,
|
||||
lockAll: false,
|
||||
microphone: false,
|
||||
publicChat: false,
|
||||
privateChat: false,
|
||||
layout: false,
|
||||
},
|
||||
};
|
||||
|
||||
const savedSettings = {
|
||||
application: getSettingsFor('application'),
|
||||
audio: getSettingsFor('audio'),
|
||||
video: getSettingsFor('video'),
|
||||
cc: getSettingsFor('cc'),
|
||||
participants: getSettingsFor('participants'),
|
||||
};
|
||||
|
||||
let settings = {};
|
||||
|
||||
Object.keys(defaultSettings).forEach(key => {
|
||||
settings[key] = _.extend(defaultSettings[key], savedSettings[key]);
|
||||
});
|
||||
|
||||
updateSettings(settings);
|
||||
const updateSettings = (obj) => {
|
||||
Object.keys(obj).forEach(k => Settings[k] = obj[k]);
|
||||
Settings.save();
|
||||
};
|
||||
|
||||
export {
|
||||
updateSettings,
|
||||
getSettingsFor,
|
||||
getClosedCaptionLocales,
|
||||
getUserRoles,
|
||||
setDefaultSettings,
|
||||
updateSettings,
|
||||
};
|
||||
|
@ -28,7 +28,7 @@ export default class ClosedCaptionsMenu extends BaseMenu {
|
||||
settings: {
|
||||
backgroundColor: props.settings ? props.settings.backgroundColor : '#f3f6f9',
|
||||
fontColor: props.settings ? props.settings.fontColor : '#000000',
|
||||
closedCaptions: props.settings ? props.settings.closedCaptions : false,
|
||||
enabled: props.settings ? props.settings.enabled : false,
|
||||
fontFamily: props.settings ? props.settings.fontFamily : 'Calibri',
|
||||
fontSize: props.settings ? props.settings.fontSize : -1,
|
||||
locale: props.settings ? props.settings.locale : -1,
|
||||
@ -99,8 +99,8 @@ export default class ClosedCaptionsMenu extends BaseMenu {
|
||||
<div className={cx(styles.formElement, styles.pullContentRight)}>
|
||||
<Toggle
|
||||
icons={false}
|
||||
defaultChecked={this.state.settings.closedCaptions}
|
||||
onChange={() => this.handleToggle('closedCaptions')} />
|
||||
defaultChecked={this.state.settings.enabled}
|
||||
onChange={() => this.handleToggle('enabled')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -48,7 +48,28 @@ export default class UserAvatar extends Component {
|
||||
let content = user.name.slice(0, 2);
|
||||
|
||||
if (user.emoji.status !== 'none') {
|
||||
content = <Icon iconName={user.emoji.status}/>;
|
||||
let iconEmoji = undefined;
|
||||
|
||||
switch (user.emoji.status) {
|
||||
case 'thumbsUp':
|
||||
iconEmoji = 'thumbs_up';
|
||||
break;
|
||||
case 'thumbsDown':
|
||||
iconEmoji = 'thumbs_down';
|
||||
break;
|
||||
case 'raiseHand':
|
||||
iconEmoji = 'hand';
|
||||
break;
|
||||
case 'away':
|
||||
iconEmoji = 'time';
|
||||
break;
|
||||
case 'neutral':
|
||||
iconEmoji = 'undecided';
|
||||
break;
|
||||
default:
|
||||
iconEmoji = user.emoji.status;
|
||||
}
|
||||
content = <Icon iconName={iconEmoji}/>;
|
||||
}
|
||||
|
||||
return content;
|
||||
|
@ -10,7 +10,12 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||
const intlMessages = defineMessages({
|
||||
titlePublic: {
|
||||
id: 'app.chat.titlePublic',
|
||||
defaultMessage: "Public Chat",
|
||||
},
|
||||
unreadPlural: {
|
||||
id: 'app.userlist.chatlistitem.unreadPlural',
|
||||
},
|
||||
unreadSingular: {
|
||||
id: 'app.userlist.chatlistitem.unreadSingular',
|
||||
},
|
||||
});
|
||||
|
||||
@ -38,9 +43,11 @@ class ChatListItem extends Component {
|
||||
} = this.props;
|
||||
|
||||
const linkPath = [PRIVATE_CHAT_PATH, chat.id].join('');
|
||||
const isCurrentChat = chat.id === openChat;
|
||||
let isSingleMessage = chat.unreadCounter === 1;
|
||||
|
||||
let linkClasses = {};
|
||||
linkClasses[styles.active] = chat.id === openChat;
|
||||
linkClasses[styles.active] = isCurrentChat;
|
||||
|
||||
if (chat.name === 'Public Chat') {
|
||||
chat.name = intl.formatMessage(intlMessages.titlePublic);
|
||||
@ -48,18 +55,26 @@ class ChatListItem extends Component {
|
||||
|
||||
return (
|
||||
<li className={cx(styles.chatListItem, linkClasses)}>
|
||||
<Link to={linkPath} className={styles.chatListItemLink}>
|
||||
{chat.icon ? this.renderChatIcon() : this.renderChatAvatar()}
|
||||
<div className={styles.chatName}>
|
||||
{!compact ? <h3 className={styles.chatNameMain}>{chat.name}</h3> : null }
|
||||
</div>
|
||||
{(chat.unreadCounter > 0) ?
|
||||
<div className={styles.unreadMessages}>
|
||||
<p className={styles.unreadMessagesText}>
|
||||
{chat.unreadCounter}
|
||||
</p>
|
||||
<Link
|
||||
to={linkPath}
|
||||
className={styles.chatListItemLink}
|
||||
role="button"
|
||||
aria-expanded={isCurrentChat}>
|
||||
{chat.icon ? this.renderChatIcon() : this.renderChatAvatar()}
|
||||
<div className={styles.chatName}>
|
||||
{!compact ? <span className={styles.chatNameMain}>{chat.name}</span> : null }
|
||||
</div>
|
||||
: null}
|
||||
{(chat.unreadCounter > 0) ?
|
||||
<div
|
||||
className={styles.unreadMessages}
|
||||
aria-label={isSingleMessage
|
||||
? intl.formatMessage(intlMessages.unreadSingular, { count: chat.unreadCounter })
|
||||
: intl.formatMessage(intlMessages.unreadPlural, { count: chat.unreadCounter })}>
|
||||
<div className={styles.unreadMessagesText} aria-hidden="true">
|
||||
{chat.unreadCounter}
|
||||
</div>
|
||||
</div>
|
||||
: null}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
|
56
bigbluebutton-html5/imports/ui/services/settings/index.js
Normal file
56
bigbluebutton-html5/imports/ui/services/settings/index.js
Normal file
@ -0,0 +1,56 @@
|
||||
import Storage from '/imports/ui/services/storage/session';
|
||||
import _ from 'lodash';
|
||||
|
||||
const SETTINGS = [
|
||||
'application',
|
||||
'audio',
|
||||
'video',
|
||||
'cc',
|
||||
'participants',
|
||||
];
|
||||
|
||||
class Settings {
|
||||
constructor(defaultValues = {}) {
|
||||
SETTINGS.forEach(p => {
|
||||
const privateProp = `_${p}`;
|
||||
this[privateProp] = {
|
||||
tracker: new Tracker.Dependency,
|
||||
value: undefined,
|
||||
};
|
||||
|
||||
Object.defineProperty(this, p, {
|
||||
get: () => {
|
||||
this[privateProp].tracker.depend();
|
||||
return this[privateProp].value;
|
||||
},
|
||||
|
||||
set: v => {
|
||||
this[privateProp].value = v;
|
||||
this[privateProp].tracker.changed();
|
||||
},
|
||||
});
|
||||
});
|
||||
this.setDefault(defaultValues);
|
||||
}
|
||||
|
||||
setDefault(defaultValues) {
|
||||
const savedSettings = {};
|
||||
|
||||
SETTINGS.forEach(s => {
|
||||
savedSettings[s] = Storage.getItem(`settings_${s}`);
|
||||
});
|
||||
|
||||
Object.keys(defaultValues).forEach(key => {
|
||||
this[key] = _.extend(defaultValues[key], savedSettings[key]);
|
||||
});
|
||||
|
||||
this.save();
|
||||
};
|
||||
|
||||
save() {
|
||||
Object.keys(this).forEach(k => Storage.setItem(`settings${k}`, this[k].value));
|
||||
}
|
||||
}
|
||||
|
||||
const SettingsSingleton = new Settings(Meteor.settings.public.app.defaultSettings);
|
||||
export default SettingsSingleton;
|
@ -1,4 +1,4 @@
|
||||
const EMOJI_STATUSES = ['time', 'hand', 'undecided', 'confused', 'sad',
|
||||
'happy', 'applause', 'thumbs_up', 'thumbs_down'];
|
||||
const EMOJI_STATUSES = ['away', 'raiseHand', 'neutral', 'confused', 'sad',
|
||||
'happy', 'applause', 'thumbsUp', 'thumbsDown'];
|
||||
|
||||
export { EMOJI_STATUSES };
|
||||
|
@ -25,3 +25,30 @@ app:
|
||||
basename: '/html5client'
|
||||
|
||||
defaultLocale: 'en'
|
||||
#default settings for session storage
|
||||
defaultSettings:
|
||||
application:
|
||||
chatAudioNotifications: false
|
||||
chatPushNotifications: false
|
||||
fontSize: "16px"
|
||||
audio:
|
||||
inputDeviceId: undefined
|
||||
outputDeviceId: undefined
|
||||
video:
|
||||
viewParticipantsWebcams: true
|
||||
cc:
|
||||
backgroundColor: "#FFFFFF"
|
||||
fontColor: "#000000"
|
||||
enabled: false
|
||||
fontFamily: "Calibri"
|
||||
fontSize: '16px'
|
||||
# locale: undefined
|
||||
takeOwnership: false
|
||||
participants:
|
||||
muteAll: false
|
||||
lockAll: false
|
||||
lockAll: false
|
||||
microphone: false
|
||||
publicChat: false
|
||||
privateChat: false
|
||||
layout: false
|
||||
|
@ -14,6 +14,8 @@
|
||||
"app.chat.partnerDisconnected": "{name} has left the meeting",
|
||||
"app.chat.closeChatLabel": "Close {title}",
|
||||
"app.chat.moreMessages": "More messages below",
|
||||
"app.userlist.chatlistitem.unreadSingular": "{count} New Message",
|
||||
"app.userlist.chatlistitem.unreadPlural": "{count} New Messages",
|
||||
"app.chat.Label": "Chat",
|
||||
"app.media.Label": "Media",
|
||||
"app.presentation.presentationToolbar.prevSlideLabel": "Previous slide",
|
||||
|
Loading…
Reference in New Issue
Block a user