summaryrefslogtreecommitdiffstats
path: root/web/react/components
diff options
context:
space:
mode:
Diffstat (limited to 'web/react/components')
-rw-r--r--web/react/components/channel_loader.jsx4
-rw-r--r--web/react/components/posts_view.jsx14
-rw-r--r--web/react/components/sidebar.jsx65
-rw-r--r--web/react/components/user_settings/user_settings_display.jsx83
4 files changed, 108 insertions, 58 deletions
diff --git a/web/react/components/channel_loader.jsx b/web/react/components/channel_loader.jsx
index c8f1196a8..13045d732 100644
--- a/web/react/components/channel_loader.jsx
+++ b/web/react/components/channel_loader.jsx
@@ -10,6 +10,7 @@ import SocketStore from '../stores/socket_store.jsx';
import ChannelStore from '../stores/channel_store.jsx';
import PostStore from '../stores/post_store.jsx';
import UserStore from '../stores/user_store.jsx';
+import PreferenceStore from '../stores/preference_store.jsx';
import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
@@ -69,6 +70,9 @@ export default class ChannelLoader extends React.Component {
Utils.applyTheme(Constants.THEMES.default);
}
+ const selectedFont = PreferenceStore.getPreference(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, 'selected_font', {value: Constants.DEFAULT_FONT}).value;
+ Utils.applyFont(selectedFont);
+
$('body').on('mouseenter mouseleave', '.post', function mouseOver(ev) {
if (ev.type === 'mouseenter') {
$(this).parent('div').prev('.date-separator, .new-separator').addClass('hovered--after');
diff --git a/web/react/components/posts_view.jsx b/web/react/components/posts_view.jsx
index 242b26b91..d0eee5a23 100644
--- a/web/react/components/posts_view.jsx
+++ b/web/react/components/posts_view.jsx
@@ -280,18 +280,22 @@ export default class PostsView extends React.Component {
this.updateScrolling();
}
window.addEventListener('resize', this.handleResize);
- $(this.refs.postlist).perfectScrollbar();
- PreferenceStore.addChangeListener(this.updateState);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
- PreferenceStore.removeChangeListener(this.updateState);
}
componentDidUpdate() {
if (this.props.postList != null) {
this.updateScrolling();
}
- $(this.refs.postlist).perfectScrollbar('update');
+ }
+ componentWillReceiveProps(nextProps) {
+ if (!this.props.isActive && nextProps.isActive) {
+ this.updateState();
+ PreferenceStore.addChangeListener(this.updateState);
+ } else if (this.props.isActive && !nextProps.isActive) {
+ PreferenceStore.removeChangeListener(this.updateState);
+ }
}
shouldComponentUpdate(nextProps, nextState) {
if (this.props.isActive !== nextProps.isActive) {
@@ -373,7 +377,7 @@ export default class PostsView extends React.Component {
return (
<div
ref='postlist'
- className={'ps-container post-list-holder-by-time ' + activeClass}
+ className={'post-list-holder-by-time ' + activeClass}
onScroll={this.handleScroll}
>
<div className='post-list__table'>
diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx
index 5c8e73874..3d7f449d1 100644
--- a/web/react/components/sidebar.jsx
+++ b/web/react/components/sidebar.jsx
@@ -19,7 +19,6 @@ import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
const Preferences = Constants.Preferences;
const TutorialSteps = Constants.TutorialSteps;
-const NotificationPrefs = Constants.NotificationPrefs;
const Tooltip = ReactBootstrap.Tooltip;
const OverlayTrigger = ReactBootstrap.OverlayTrigger;
@@ -38,7 +37,6 @@ export default class Sidebar extends React.Component {
this.onScroll = this.onScroll.bind(this);
this.updateUnreadIndicators = this.updateUnreadIndicators.bind(this);
this.handleLeaveDirectChannel = this.handleLeaveDirectChannel.bind(this);
- this.updateScrollbar = this.updateScrollbar.bind(this);
this.handleResize = this.handleResize.bind(this);
this.showNewChannelModal = this.showNewChannelModal.bind(this);
@@ -48,8 +46,6 @@ export default class Sidebar extends React.Component {
this.createChannelElement = this.createChannelElement.bind(this);
this.updateTitle = this.updateTitle.bind(this);
- this.setUnreadCountPerChannel = this.setUnreadCountPerChannel.bind(this);
- this.getUnreadCount = this.getUnreadCount.bind(this);
this.isLeaving = new Map();
@@ -59,43 +55,15 @@ export default class Sidebar extends React.Component {
state.loadingDMChannel = -1;
state.windowWidth = Utils.windowWidth();
this.state = state;
-
- this.unreadCountPerChannel = {};
- this.setUnreadCountPerChannel();
- }
- setUnreadCountPerChannel() {
- const channels = ChannelStore.getAll();
- const members = ChannelStore.getAllMembers();
- const channelUnreadCounts = {};
-
- channels.forEach((ch) => {
- const chMember = members[ch.id];
- let chMentionCount = chMember.mention_count;
- let chUnreadCount = ch.total_msg_count - chMember.msg_count - chMentionCount;
-
- if (ch.type === 'D') {
- chMentionCount = chUnreadCount;
- chUnreadCount = 0;
- } else if (chMember.notify_props && chMember.notify_props.mark_unread === NotificationPrefs.MENTION) {
- chUnreadCount = 0;
- }
-
- channelUnreadCounts[ch.id] = {msgs: chUnreadCount, mentions: chMentionCount};
- });
-
- this.unreadCountPerChannel = channelUnreadCounts;
}
- getUnreadCount(channelId) {
- let mentions = 0;
+ getTotalUnreadCount() {
let msgs = 0;
+ let mentions = 0;
+ const unreadCounts = this.state.unreadCounts;
- if (channelId) {
- return this.unreadCountPerChannel[channelId] ? this.unreadCountPerChannel[channelId] : {msgs, mentions};
- }
-
- Object.keys(this.unreadCountPerChannel).forEach((chId) => {
- msgs += this.unreadCountPerChannel[chId].msgs;
- mentions += this.unreadCountPerChannel[chId].mentions;
+ Object.keys(unreadCounts).forEach((chId) => {
+ msgs += unreadCounts[chId].msgs;
+ mentions += unreadCounts[chId].mentions;
});
return {msgs, mentions};
@@ -156,6 +124,7 @@ export default class Sidebar extends React.Component {
privateChannels,
visibleDirectChannels,
hiddenDirectChannelCount,
+ unreadCounts: JSON.parse(JSON.stringify(ChannelStore.getUnreadCounts())),
showTutorialTip: parseInt(tutorialPref.value, 10) === TutorialSteps.CHANNEL_POPOVER
};
}
@@ -169,7 +138,6 @@ export default class Sidebar extends React.Component {
this.updateTitle();
this.updateUnreadIndicators();
- this.updateScrollbar();
window.addEventListener('resize', this.handleResize);
@@ -186,7 +154,6 @@ export default class Sidebar extends React.Component {
componentDidUpdate() {
this.updateTitle();
this.updateUnreadIndicators();
- this.updateScrollbar();
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
@@ -203,8 +170,6 @@ export default class Sidebar extends React.Component {
windowHeight: Utils.windowHeight()
});
}
- updateScrollbar() {
- }
onChange() {
this.setState(this.getStateFromStores());
}
@@ -221,7 +186,7 @@ export default class Sidebar extends React.Component {
currentChannelName = Utils.getDirectTeammate(channel.id).username;
}
- const unread = this.getUnreadCount();
+ const unread = this.getTotalUnreadCount();
const mentionTitle = unread.mentions > 0 ? '(' + unread.mentions + ') ' : '';
const unreadTitle = unread.msgs > 0 ? '* ' : '';
document.title = mentionTitle + unreadTitle + currentChannelName + ' - ' + TeamStore.getCurrent().display_name + ' ' + currentSiteName;
@@ -347,13 +312,13 @@ export default class Sidebar extends React.Component {
}
createChannelElement(channel, index, arr, handleClose) {
- var members = this.state.members;
- var activeId = this.state.activeId;
- var channelMember = members[channel.id];
- var unreadCount = this.getUnreadCount(channel.id);
- var msgCount;
+ const members = this.state.members;
+ const activeId = this.state.activeId;
+ const channelMember = members[channel.id];
+ const unreadCount = this.state.unreadCounts[channel.id] || {msgs: 0, mentions: 0};
+ let msgCount;
- var linkClass = '';
+ let linkClass = '';
if (channel.id === activeId) {
linkClass = 'active';
}
@@ -510,8 +475,6 @@ export default class Sidebar extends React.Component {
render() {
this.badgesActive = false;
- this.setUnreadCountPerChannel();
-
// keep track of the first and last unread channels so we can use them to set the unread indicators
this.firstUnreadChannel = null;
this.lastUnreadChannel = null;
diff --git a/web/react/components/user_settings/user_settings_display.jsx b/web/react/components/user_settings/user_settings_display.jsx
index 43c8d33d1..dc3865c68 100644
--- a/web/react/components/user_settings/user_settings_display.jsx
+++ b/web/react/components/user_settings/user_settings_display.jsx
@@ -6,14 +6,17 @@ import SettingItemMin from '../setting_item_min.jsx';
import SettingItemMax from '../setting_item_max.jsx';
import Constants from '../../utils/constants.jsx';
import PreferenceStore from '../../stores/preference_store.jsx';
+import * as Utils from '../../utils/utils.jsx';
function getDisplayStateFromStores() {
const militaryTime = PreferenceStore.getPreference(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, 'use_military_time', {value: 'false'});
const nameFormat = PreferenceStore.getPreference(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, 'name_format', {value: 'username'});
+ const selectedFont = PreferenceStore.getPreference(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, 'selected_font', {value: Constants.DEFAULT_FONT});
return {
militaryTime: militaryTime.value,
- nameFormat: nameFormat.value
+ nameFormat: nameFormat.value,
+ selectedFont: selectedFont.value
};
}
@@ -24,15 +27,20 @@ export default class UserSettingsDisplay extends React.Component {
this.handleSubmit = this.handleSubmit.bind(this);
this.handleClockRadio = this.handleClockRadio.bind(this);
this.handleNameRadio = this.handleNameRadio.bind(this);
+ this.handleFont = this.handleFont.bind(this);
this.updateSection = this.updateSection.bind(this);
this.state = getDisplayStateFromStores();
+ this.selectedFont = this.state.selectedFont;
}
handleSubmit() {
const timePreference = PreferenceStore.setPreference(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, 'use_military_time', this.state.militaryTime);
const namePreference = PreferenceStore.setPreference(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, 'name_format', this.state.nameFormat);
+ const fontPreference = PreferenceStore.setPreference(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, 'selected_font', this.state.selectedFont);
- savePreferences([timePreference, namePreference],
+ this.selectedFont = this.state.selectedFont;
+
+ savePreferences([timePreference, namePreference, fontPreference],
() => {
PreferenceStore.emitChange();
this.updateSection('');
@@ -48,6 +56,10 @@ export default class UserSettingsDisplay extends React.Component {
handleNameRadio(nameFormat) {
this.setState({nameFormat});
}
+ handleFont(selectedFont) {
+ Utils.applyFont(selectedFont);
+ this.setState({selectedFont});
+ }
updateSection(section) {
this.setState(getDisplayStateFromStores());
this.props.updateSection(section);
@@ -56,6 +68,8 @@ export default class UserSettingsDisplay extends React.Component {
const serverError = this.state.serverError || null;
let clockSection;
let nameFormatSection;
+ let fontSection;
+
if (this.props.activeSection === 'clock') {
const clockFormat = [false, false];
if (this.state.militaryTime === 'true') {
@@ -209,6 +223,69 @@ export default class UserSettingsDisplay extends React.Component {
);
}
+ if (this.props.activeSection === 'font') {
+ const options = [];
+ Object.keys(Constants.FONTS).forEach((fontName, idx) => {
+ const className = Constants.FONTS[fontName];
+ options.push(
+ <option
+ key={'font_' + idx}
+ value={fontName}
+ className={className}
+ >
+ {fontName}
+ </option>
+ );
+ });
+
+ const inputs = [
+ <div key='userDisplayNameOptions'>
+ <div
+ className='input-group theme-group dropdown'
+ >
+ <select
+ className='form-control'
+ type='text'
+ value={this.state.selectedFont}
+ onChange={(e) => this.handleFont(e.target.value)}
+ >
+ {options}
+ </select>
+ <span className={'input-group-addon ' + Constants.FONTS[this.state.selectedFont]}>
+ {this.state.selectedFont}
+ </span>
+ </div>
+ <div><br/>{'Select the font displayed in the Mattermost user interface.'}</div>
+ </div>
+ ];
+
+ fontSection = (
+ <SettingItemMax
+ title='Display Font'
+ inputs={inputs}
+ submit={this.handleSubmit}
+ server_error={serverError}
+ updateSection={(e) => {
+ if (this.selectedFont !== this.state.selectedFont) {
+ this.handleFont(this.selectedFont);
+ }
+ this.updateSection('');
+ e.preventDefault();
+ }}
+ />
+ );
+ } else {
+ fontSection = (
+ <SettingItemMin
+ title='Display Font'
+ describe={this.state.selectedFont}
+ updateSection={() => {
+ this.props.updateSection('font');
+ }}
+ />
+ );
+ }
+
return (
<div>
<div className='modal-header'>
@@ -239,6 +316,8 @@ export default class UserSettingsDisplay extends React.Component {
<div className='divider-dark'/>
{nameFormatSection}
<div className='divider-dark'/>
+ {fontSection}
+ <div className='divider-dark'/>
</div>
</div>
);