Merge branch 'develop' of https://github.com/matrix-org/matrix-react-sdk into rxl881/invertOutlineColour
This commit is contained in:
commit
7bab7813bb
57 changed files with 2199 additions and 756 deletions
|
@ -19,7 +19,6 @@ limitations under the License.
|
|||
import * as Matrix from 'matrix-js-sdk';
|
||||
import React from 'react';
|
||||
|
||||
import UserSettingsStore from '../../UserSettingsStore';
|
||||
import KeyCode from '../../KeyCode';
|
||||
import Notifier from '../../Notifier';
|
||||
import PageTypes from '../../PageTypes';
|
||||
|
@ -28,6 +27,7 @@ import sdk from '../../index';
|
|||
import dis from '../../dispatcher';
|
||||
import sessionStore from '../../stores/SessionStore';
|
||||
import MatrixClientPeg from '../../MatrixClientPeg';
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
|
||||
/**
|
||||
* This is what our MatrixChat shows when we are logged in. The precise view is
|
||||
|
@ -74,7 +74,7 @@ export default React.createClass({
|
|||
getInitialState: function() {
|
||||
return {
|
||||
// use compact timeline view
|
||||
useCompactLayout: UserSettingsStore.getSyncedSetting('useCompactLayout'),
|
||||
useCompactLayout: SettingsStore.getValue('useCompactLayout'),
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import React from 'react';
|
|||
import Matrix from "matrix-js-sdk";
|
||||
|
||||
import Analytics from "../../Analytics";
|
||||
import UserSettingsStore from '../../UserSettingsStore';
|
||||
import MatrixClientPeg from "../../MatrixClientPeg";
|
||||
import PlatformPeg from "../../PlatformPeg";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
|
@ -44,6 +43,7 @@ import createRoom from "../../createRoom";
|
|||
import * as UDEHandler from '../../UnknownDeviceErrorHandler';
|
||||
import KeyRequestHandler from '../../KeyRequestHandler';
|
||||
import { _t, getCurrentLanguage } from '../../languageHandler';
|
||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
||||
|
||||
/** constants for MatrixChat.state.view */
|
||||
const VIEWS = {
|
||||
|
@ -224,7 +224,7 @@ module.exports = React.createClass({
|
|||
componentWillMount: function() {
|
||||
SdkConfig.put(this.props.config);
|
||||
|
||||
if (!UserSettingsStore.getLocalSetting('analyticsOptOut', false)) Analytics.enable();
|
||||
if (!SettingsStore.getValue("analyticsOptOut")) Analytics.enable();
|
||||
|
||||
// Used by _viewRoom before getting state from sync
|
||||
this.firstSyncComplete = false;
|
||||
|
@ -591,6 +591,9 @@ module.exports = React.createClass({
|
|||
this._onWillStartClient();
|
||||
});
|
||||
break;
|
||||
case 'client_started':
|
||||
this._onClientStarted();
|
||||
break;
|
||||
case 'new_version':
|
||||
this.onVersion(
|
||||
payload.currentVersion, payload.newVersion,
|
||||
|
@ -922,6 +925,11 @@ module.exports = React.createClass({
|
|||
styleElements[theme].disabled = false;
|
||||
|
||||
const switchTheme = function() {
|
||||
// we re-enable our theme here just in case we raced with another
|
||||
// theme set request as per https://github.com/vector-im/riot-web/issues/5601.
|
||||
// We could alternatively lock or similar to stop the race, but
|
||||
// this is probably good enough for now.
|
||||
styleElements[theme].disabled = false;
|
||||
Object.values(styleElements).forEach((a) => {
|
||||
if (a == styleElements[theme]) return;
|
||||
a.disabled = true;
|
||||
|
@ -1119,6 +1127,34 @@ module.exports = React.createClass({
|
|||
cli.on("crypto.roomKeyRequestCancellation", (req) => {
|
||||
krh.handleKeyRequestCancellation(req);
|
||||
});
|
||||
cli.on("Room", (room) => {
|
||||
if (MatrixClientPeg.get().isCryptoEnabled()) {
|
||||
const blacklistEnabled = SettingsStore.getValueAt(
|
||||
SettingLevel.ROOM_DEVICE,
|
||||
"blacklistUnverifiedDevices",
|
||||
room.roomId,
|
||||
/*explicit=*/true,
|
||||
);
|
||||
room.setBlacklistUnverifiedDevices(blacklistEnabled);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Called shortly after the matrix client has started. Useful for
|
||||
* setting up anything that requires the client to be started.
|
||||
* @private
|
||||
*/
|
||||
_onClientStarted: function() {
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
if (cli.isCryptoEnabled()) {
|
||||
const blacklistEnabled = SettingsStore.getValueAt(
|
||||
SettingLevel.DEVICE,
|
||||
"blacklistUnverifiedDevices",
|
||||
);
|
||||
cli.setGlobalBlacklistUnverifiedDevices(blacklistEnabled);
|
||||
}
|
||||
},
|
||||
|
||||
showScreen: function(screen, params) {
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import classNames from 'classnames';
|
||||
import UserSettingsStore from '../../UserSettingsStore';
|
||||
import shouldHideEvent from '../../shouldHideEvent';
|
||||
import dis from "../../dispatcher";
|
||||
import sdk from '../../index';
|
||||
|
@ -110,8 +109,6 @@ module.exports = React.createClass({
|
|||
// Velocity requires
|
||||
this._readMarkerGhostNode = null;
|
||||
|
||||
this._syncedSettings = UserSettingsStore.getSyncedSettings();
|
||||
|
||||
this._isMounted = true;
|
||||
},
|
||||
|
||||
|
@ -251,7 +248,7 @@ module.exports = React.createClass({
|
|||
// Always show highlighted event
|
||||
if (this.props.highlightedEventId === mxEv.getId()) return true;
|
||||
|
||||
return !shouldHideEvent(mxEv, this._syncedSettings);
|
||||
return !shouldHideEvent(mxEv);
|
||||
},
|
||||
|
||||
_getEventTiles: function() {
|
||||
|
|
|
@ -29,7 +29,6 @@ const classNames = require("classnames");
|
|||
const Matrix = require("matrix-js-sdk");
|
||||
import { _t } from '../../languageHandler';
|
||||
|
||||
const UserSettingsStore = require('../../UserSettingsStore');
|
||||
const MatrixClientPeg = require("../../MatrixClientPeg");
|
||||
const ContentMessages = require("../../ContentMessages");
|
||||
const Modal = require("../../Modal");
|
||||
|
@ -46,6 +45,7 @@ import KeyCode from '../../KeyCode';
|
|||
|
||||
import RoomViewStore from '../../stores/RoomViewStore';
|
||||
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
|
||||
const DEBUG = false;
|
||||
let debuglog = function() {};
|
||||
|
@ -149,8 +149,6 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().on("RoomMember.membership", this.onRoomMemberMembership);
|
||||
MatrixClientPeg.get().on("accountData", this.onAccountData);
|
||||
|
||||
this._syncedSettings = UserSettingsStore.getSyncedSettings();
|
||||
|
||||
// Start listening for RoomViewStore updates
|
||||
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate);
|
||||
this._onRoomViewStoreUpdate(true);
|
||||
|
@ -542,7 +540,7 @@ module.exports = React.createClass({
|
|||
// update unread count when scrolled up
|
||||
if (!this.state.searchResults && this.state.atEndOfLiveTimeline) {
|
||||
// no change
|
||||
} else if (!shouldHideEvent(ev, this._syncedSettings)) {
|
||||
} else if (!shouldHideEvent(ev)) {
|
||||
this.setState((state, props) => {
|
||||
return {numUnreadMessages: state.numUnreadMessages + 1};
|
||||
});
|
||||
|
@ -616,38 +614,8 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_updatePreviewUrlVisibility: function(room) {
|
||||
// console.log("_updatePreviewUrlVisibility");
|
||||
|
||||
// check our per-room overrides
|
||||
const roomPreviewUrls = room.getAccountData("org.matrix.room.preview_urls");
|
||||
if (roomPreviewUrls && roomPreviewUrls.getContent().disable !== undefined) {
|
||||
this.setState({
|
||||
showUrlPreview: !roomPreviewUrls.getContent().disable,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// check our global disable override
|
||||
const userRoomPreviewUrls = MatrixClientPeg.get().getAccountData("org.matrix.preview_urls");
|
||||
if (userRoomPreviewUrls && userRoomPreviewUrls.getContent().disable) {
|
||||
this.setState({
|
||||
showUrlPreview: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// check the room state event
|
||||
const roomStatePreviewUrls = room.currentState.getStateEvents('org.matrix.room.preview_urls', '');
|
||||
if (roomStatePreviewUrls && roomStatePreviewUrls.getContent().disable) {
|
||||
this.setState({
|
||||
showUrlPreview: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, we assume they're on.
|
||||
this.setState({
|
||||
showUrlPreview: true,
|
||||
showUrlPreview: SettingsStore.getValue("urlPreviewsEnabled", room.roomId),
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -666,12 +634,7 @@ module.exports = React.createClass({
|
|||
const room = this.state.room;
|
||||
if (!room) return;
|
||||
|
||||
const color_scheme_event = room.getAccountData("org.matrix.room.color_scheme");
|
||||
let color_scheme = {};
|
||||
if (color_scheme_event) {
|
||||
color_scheme = color_scheme_event.getContent();
|
||||
// XXX: we should validate the event
|
||||
}
|
||||
const color_scheme = SettingsStore.getValue("roomColor", room.room_id);
|
||||
console.log("Tinter.tint from updateTint");
|
||||
Tinter.tint(color_scheme.primary_color, color_scheme.secondary_color);
|
||||
},
|
||||
|
@ -1775,7 +1738,7 @@ module.exports = React.createClass({
|
|||
const messagePanel = (
|
||||
<TimelinePanel ref={this._gatherTimelinePanelRef}
|
||||
timelineSet={this.state.room.getUnfilteredTimelineSet()}
|
||||
showReadReceipts={!UserSettingsStore.getSyncedSetting('hideReadReceipts', false)}
|
||||
showReadReceipts={!SettingsStore.getValue('hideReadReceipts')}
|
||||
manageReadReceipts={!this.state.isPeeking}
|
||||
manageReadMarkers={!this.state.isPeeking}
|
||||
hidden={hideMessagePanel}
|
||||
|
|
|
@ -15,6 +15,8 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
|
||||
const React = require('react');
|
||||
const ReactDOM = require("react-dom");
|
||||
import Promise from 'bluebird';
|
||||
|
@ -30,7 +32,6 @@ const ObjectUtils = require('../../ObjectUtils');
|
|||
const Modal = require("../../Modal");
|
||||
const UserActivity = require("../../UserActivity");
|
||||
const KeyCode = require('../../KeyCode');
|
||||
import UserSettingsStore from '../../UserSettingsStore';
|
||||
|
||||
const PAGINATE_SIZE = 20;
|
||||
const INITIAL_SIZE = 20;
|
||||
|
@ -129,8 +130,6 @@ var TimelinePanel = React.createClass({
|
|||
}
|
||||
}
|
||||
|
||||
const syncedSettings = UserSettingsStore.getSyncedSettings();
|
||||
|
||||
return {
|
||||
events: [],
|
||||
timelineLoading: true, // track whether our room timeline is loading
|
||||
|
@ -175,10 +174,10 @@ var TimelinePanel = React.createClass({
|
|||
clientSyncState: MatrixClientPeg.get().getSyncState(),
|
||||
|
||||
// should the event tiles have twelve hour times
|
||||
isTwelveHour: syncedSettings.showTwelveHourTimestamps,
|
||||
isTwelveHour: SettingsStore.getValue("showTwelveHourTimestamps"),
|
||||
|
||||
// always show timestamps on event tiles?
|
||||
alwaysShowTimestamps: syncedSettings.alwaysShowTimestamps,
|
||||
alwaysShowTimestamps: SettingsStore.getValue("alwaysShowTimestamps"),
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
||||
|
||||
const React = require('react');
|
||||
const ReactDOM = require('react-dom');
|
||||
const sdk = require('../../index');
|
||||
|
@ -56,138 +58,64 @@ const gHVersionLabel = function(repo, token='') {
|
|||
return <a target="_blank" rel="noopener" href={url}>{ token }</a>;
|
||||
};
|
||||
|
||||
// Enumerate some simple 'flip a bit' UI settings (if any).
|
||||
// 'id' gives the key name in the im.vector.web.settings account data event
|
||||
// 'label' is how we describe it in the UI.
|
||||
// Warning: Each "label" string below must be added to i18n/strings/en_EN.json,
|
||||
// since they will be translated when rendered.
|
||||
const SETTINGS_LABELS = [
|
||||
{
|
||||
id: 'autoplayGifsAndVideos',
|
||||
label: _td('Autoplay GIFs and videos'),
|
||||
},
|
||||
{
|
||||
id: 'hideReadReceipts',
|
||||
label: _td('Hide read receipts'),
|
||||
},
|
||||
{
|
||||
id: 'dontSendTypingNotifications',
|
||||
label: _td("Don't send typing notifications"),
|
||||
},
|
||||
{
|
||||
id: 'alwaysShowTimestamps',
|
||||
label: _td('Always show message timestamps'),
|
||||
},
|
||||
{
|
||||
id: 'showTwelveHourTimestamps',
|
||||
label: _td('Show timestamps in 12 hour format (e.g. 2:30pm)'),
|
||||
},
|
||||
{
|
||||
id: 'hideJoinLeaves',
|
||||
label: _td('Hide join/leave messages (invites/kicks/bans unaffected)'),
|
||||
},
|
||||
{
|
||||
id: 'hideAvatarDisplaynameChanges',
|
||||
label: _td('Hide avatar and display name changes'),
|
||||
},
|
||||
{
|
||||
id: 'useCompactLayout',
|
||||
label: _td('Use compact timeline layout'),
|
||||
},
|
||||
{
|
||||
id: 'hideRedactions',
|
||||
label: _td('Hide removed messages'),
|
||||
},
|
||||
{
|
||||
id: 'enableSyntaxHighlightLanguageDetection',
|
||||
label: _td('Enable automatic language detection for syntax highlighting'),
|
||||
},
|
||||
{
|
||||
id: 'MessageComposerInput.autoReplaceEmoji',
|
||||
label: _td('Automatically replace plain text Emoji'),
|
||||
},
|
||||
{
|
||||
id: 'MessageComposerInput.dontSuggestEmoji',
|
||||
label: _td('Disable Emoji suggestions while typing'),
|
||||
},
|
||||
{
|
||||
id: 'Pill.shouldHidePillAvatar',
|
||||
label: _td('Hide avatars in user and room mentions'),
|
||||
},
|
||||
{
|
||||
id: 'TextualBody.disableBigEmoji',
|
||||
label: _td('Disable big emoji in chat'),
|
||||
},
|
||||
{
|
||||
id: 'VideoView.flipVideoHorizontally',
|
||||
label: _td('Mirror local video feed'),
|
||||
},
|
||||
/*
|
||||
{
|
||||
id: 'useFixedWidthFont',
|
||||
label: 'Use fixed width font',
|
||||
},
|
||||
*/
|
||||
// Enumerate some simple 'flip a bit' UI settings (if any). The strings provided here
|
||||
// must be settings defined in SettingsStore.
|
||||
const SIMPLE_SETTINGS = [
|
||||
{ id: "urlPreviewsEnabled" },
|
||||
{ id: "autoplayGifsAndVideos" },
|
||||
{ id: "hideReadReceipts" },
|
||||
{ id: "dontSendTypingNotifications" },
|
||||
{ id: "alwaysShowTimestamps" },
|
||||
{ id: "showTwelveHourTimestamps" },
|
||||
{ id: "hideJoinLeaves" },
|
||||
{ id: "hideAvatarChanges" },
|
||||
{ id: "hideDisplaynameChanges" },
|
||||
{ id: "useCompactLayout" },
|
||||
{ id: "hideRedactions" },
|
||||
{ id: "enableSyntaxHighlightLanguageDetection" },
|
||||
{ id: "MessageComposerInput.autoReplaceEmoji" },
|
||||
{ id: "MessageComposerInput.dontSuggestEmoji" },
|
||||
{ id: "Pill.shouldHidePillAvatar" },
|
||||
{ id: "TextualBody.disableBigEmoji" },
|
||||
{ id: "VideoView.flipVideoHorizontally" },
|
||||
];
|
||||
|
||||
const ANALYTICS_SETTINGS_LABELS = [
|
||||
// These settings must be defined in SettingsStore
|
||||
const ANALYTICS_SETTINGS = [
|
||||
{
|
||||
id: 'analyticsOptOut',
|
||||
label: _td('Opt out of analytics'),
|
||||
fn: function(checked) {
|
||||
Analytics[checked ? 'disable' : 'enable']();
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const WEBRTC_SETTINGS_LABELS = [
|
||||
{
|
||||
id: 'webRtcForceTURN',
|
||||
label: _td('Disable Peer-to-Peer for 1:1 calls'),
|
||||
},
|
||||
// These settings must be defined in SettingsStore
|
||||
const WEBRTC_SETTINGS = [
|
||||
{ id: 'webRtcForceTURN' },
|
||||
];
|
||||
|
||||
// Warning: Each "label" string below must be added to i18n/strings/en_EN.json,
|
||||
// since they will be translated when rendered.
|
||||
const CRYPTO_SETTINGS_LABELS = [
|
||||
// These settings must be defined in SettingsStore
|
||||
const CRYPTO_SETTINGS = [
|
||||
{
|
||||
id: 'blacklistUnverifiedDevices',
|
||||
label: _td('Never send encrypted messages to unverified devices from this device'),
|
||||
fn: function(checked) {
|
||||
MatrixClientPeg.get().setGlobalBlacklistUnverifiedDevices(checked);
|
||||
},
|
||||
},
|
||||
// XXX: this is here for documentation; the actual setting is managed via RoomSettings
|
||||
// {
|
||||
// id: 'blacklistUnverifiedDevicesPerRoom'
|
||||
// label: 'Never send encrypted messages to unverified devices in this room',
|
||||
// }
|
||||
];
|
||||
|
||||
// Enumerate the available themes, with a nice human text label.
|
||||
// 'id' gives the key name in the im.vector.web.settings account data event
|
||||
// 'value' is the value for that key in the event
|
||||
// 'label' is how we describe it in the UI.
|
||||
// 'value' is the value for the theme setting
|
||||
//
|
||||
// XXX: Ideally we would have a theme manifest or something and they'd be nicely
|
||||
// packaged up in a single directory, and/or located at the application layer.
|
||||
// But for now for expedience we just hardcode them here.
|
||||
const THEMES = [
|
||||
{
|
||||
id: 'theme',
|
||||
label: _td('Light theme'),
|
||||
value: 'light',
|
||||
},
|
||||
{
|
||||
id: 'theme',
|
||||
label: _td('Dark theme'),
|
||||
value: 'dark',
|
||||
},
|
||||
{
|
||||
id: 'theme',
|
||||
label: _td('Status.im theme'),
|
||||
value: 'status',
|
||||
},
|
||||
{ label: _td('Light theme'), value: 'light' },
|
||||
{ label: _td('Dark theme'), value: 'dark' },
|
||||
{ label: _td('Status.im theme'), value: 'status' },
|
||||
];
|
||||
|
||||
const IgnoredUser = React.createClass({
|
||||
|
@ -286,14 +214,6 @@ module.exports = React.createClass({
|
|||
});
|
||||
this._refreshFromServer();
|
||||
|
||||
const syncedSettings = UserSettingsStore.getSyncedSettings();
|
||||
if (!syncedSettings.theme) {
|
||||
syncedSettings.theme = SdkConfig.get().default_theme || 'light';
|
||||
}
|
||||
this._syncedSettings = syncedSettings;
|
||||
|
||||
this._localSettings = UserSettingsStore.getLocalSettings();
|
||||
|
||||
if (PlatformPeg.get().isElectron()) {
|
||||
const {ipcRenderer} = require('electron');
|
||||
|
||||
|
@ -364,8 +284,8 @@ module.exports = React.createClass({
|
|||
if (this._unmounted) return;
|
||||
this.setState({
|
||||
mediaDevices,
|
||||
activeAudioInput: this._localSettings['webrtc_audioinput'],
|
||||
activeVideoInput: this._localSettings['webrtc_videoinput'],
|
||||
activeAudioInput: SettingsStore.getValueAt(SettingLevel.DEVICE, 'webrtc_audioinput'),
|
||||
activeVideoInput: SettingsStore.getValueAt(SettingLevel.DEVICE, 'webrtc_videoinput'),
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -497,10 +417,6 @@ module.exports = React.createClass({
|
|||
dis.dispatch({action: 'password_changed'});
|
||||
},
|
||||
|
||||
onEnableNotificationsChange: function(event) {
|
||||
UserSettingsStore.setEnableNotifications(event.target.checked);
|
||||
},
|
||||
|
||||
_onAddEmailEditFinished: function(value, shouldSubmit) {
|
||||
if (!shouldSubmit) return;
|
||||
this._addEmail();
|
||||
|
@ -697,7 +613,8 @@ module.exports = React.createClass({
|
|||
|
||||
onLanguageChange: function(newLang) {
|
||||
if(this.state.language !== newLang) {
|
||||
UserSettingsStore.setLocalSetting('language', newLang);
|
||||
// We intentionally promote this to the account level at this point
|
||||
SettingsStore.setValue("language", null, SettingLevel.ACCOUNT, newLang);
|
||||
this.setState({
|
||||
language: newLang,
|
||||
});
|
||||
|
@ -720,14 +637,13 @@ module.exports = React.createClass({
|
|||
// TODO: this ought to be a separate component so that we don't need
|
||||
// to rebind the onChange each time we render
|
||||
const onChange = (e) =>
|
||||
UserSettingsStore.setLocalSetting('autocompleteDelay', + e.target.value);
|
||||
SettingsStore.setValue("autocompleteDelay", null, SettingLevel.DEVICE, e.target.value);
|
||||
return (
|
||||
<div>
|
||||
<h3>{ _t("User Interface") }</h3>
|
||||
<div className="mx_UserSettings_section">
|
||||
{ this._renderUrlPreviewSelector() }
|
||||
{ SETTINGS_LABELS.map( this._renderSyncedSetting ) }
|
||||
{ THEMES.map( this._renderThemeSelector ) }
|
||||
{ SIMPLE_SETTINGS.map( this._renderAccountSetting ) }
|
||||
{ THEMES.map( this._renderThemeOption ) }
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
|
@ -735,7 +651,7 @@ module.exports = React.createClass({
|
|||
<td>
|
||||
<input
|
||||
type="number"
|
||||
defaultValue={UserSettingsStore.getLocalSetting('autocompleteDelay', 200)}
|
||||
defaultValue={SettingsStore.getValueAt(SettingLevel.DEVICE, "autocompleteDelay")}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</td>
|
||||
|
@ -748,69 +664,31 @@ module.exports = React.createClass({
|
|||
);
|
||||
},
|
||||
|
||||
_renderUrlPreviewSelector: function() {
|
||||
return <div className="mx_UserSettings_toggle">
|
||||
<input id="urlPreviewsDisabled"
|
||||
type="checkbox"
|
||||
defaultChecked={UserSettingsStore.getUrlPreviewsDisabled()}
|
||||
onChange={this._onPreviewsDisabledChanged}
|
||||
/>
|
||||
<label htmlFor="urlPreviewsDisabled">
|
||||
{ _t("Disable inline URL previews by default") }
|
||||
</label>
|
||||
</div>;
|
||||
_renderAccountSetting: function(setting) {
|
||||
const SettingsFlag = sdk.getComponent("elements.SettingsFlag");
|
||||
return (
|
||||
<div className="mx_UserSettings_toggle" key={setting.id}>
|
||||
<SettingsFlag name={setting.id}
|
||||
label={setting.label}
|
||||
level={SettingLevel.ACCOUNT}
|
||||
onChange={setting.fn} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
_onPreviewsDisabledChanged: function(e) {
|
||||
UserSettingsStore.setUrlPreviewsDisabled(e.target.checked);
|
||||
},
|
||||
|
||||
_renderSyncedSetting: function(setting) {
|
||||
// TODO: this ought to be a separate component so that we don't need
|
||||
// to rebind the onChange each time we render
|
||||
|
||||
const onChange = (e) => {
|
||||
UserSettingsStore.setSyncedSetting(setting.id, e.target.checked);
|
||||
if (setting.fn) setting.fn(e.target.checked);
|
||||
};
|
||||
|
||||
return <div className="mx_UserSettings_toggle" key={setting.id}>
|
||||
<input id={setting.id}
|
||||
type="checkbox"
|
||||
defaultChecked={this._syncedSettings[setting.id]}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<label htmlFor={setting.id}>
|
||||
{ _t(setting.label) }
|
||||
</label>
|
||||
</div>;
|
||||
},
|
||||
|
||||
_renderThemeSelector: function(setting) {
|
||||
// TODO: this ought to be a separate component so that we don't need
|
||||
// to rebind the onChange each time we render
|
||||
const onChange = (e) => {
|
||||
if (e.target.checked) {
|
||||
this._syncedSettings[setting.id] = setting.value;
|
||||
UserSettingsStore.setSyncedSetting(setting.id, setting.value);
|
||||
}
|
||||
dis.dispatch({
|
||||
action: 'set_theme',
|
||||
value: setting.value,
|
||||
});
|
||||
};
|
||||
return <div className="mx_UserSettings_toggle" key={setting.id + "_" + setting.value}>
|
||||
<input id={setting.id + "_" + setting.value}
|
||||
type="radio"
|
||||
name={setting.id}
|
||||
value={setting.value}
|
||||
checked={this._syncedSettings[setting.id] === setting.value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<label htmlFor={setting.id + "_" + setting.value}>
|
||||
{ _t(setting.label) }
|
||||
</label>
|
||||
</div>;
|
||||
_renderThemeOption: function(setting) {
|
||||
const SettingsFlag = sdk.getComponent("elements.SettingsFlag");
|
||||
const onChange = (v) => dis.dispatch({action: 'set_theme', value: setting.value});
|
||||
return (
|
||||
<div className="mx_UserSettings_toggle" key={setting.id + '_' + setting.value}>
|
||||
<SettingsFlag name="theme"
|
||||
label={setting.label}
|
||||
level={SettingLevel.ACCOUNT}
|
||||
onChange={onChange}
|
||||
group="theme"
|
||||
value={setting.value} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
_renderCryptoInfo: function() {
|
||||
|
@ -852,7 +730,7 @@ module.exports = React.createClass({
|
|||
{ importExportButtons }
|
||||
</div>
|
||||
<div className="mx_UserSettings_section">
|
||||
{ CRYPTO_SETTINGS_LABELS.map( this._renderLocalSetting ) }
|
||||
{ CRYPTO_SETTINGS.map( this._renderDeviceSetting ) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -878,24 +756,16 @@ module.exports = React.createClass({
|
|||
} else return (<div />);
|
||||
},
|
||||
|
||||
_renderLocalSetting: function(setting) {
|
||||
// TODO: this ought to be a separate component so that we don't need
|
||||
// to rebind the onChange each time we render
|
||||
const onChange = (e) => {
|
||||
UserSettingsStore.setLocalSetting(setting.id, e.target.checked);
|
||||
if (setting.fn) setting.fn(e.target.checked);
|
||||
};
|
||||
|
||||
return <div className="mx_UserSettings_toggle" key={setting.id}>
|
||||
<input id={setting.id}
|
||||
type="checkbox"
|
||||
defaultChecked={this._localSettings[setting.id]}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<label htmlFor={setting.id}>
|
||||
{ _t(setting.label) }
|
||||
</label>
|
||||
</div>;
|
||||
_renderDeviceSetting: function(setting) {
|
||||
const SettingsFlag = sdk.getComponent("elements.SettingsFlag");
|
||||
return (
|
||||
<div className="mx_UserSettings_toggle" key={setting.id}>
|
||||
<SettingsFlag name={setting.id}
|
||||
label={setting.label}
|
||||
level={SettingLevel.DEVICE}
|
||||
onChange={setting.fn} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
_renderDevicesPanel: function() {
|
||||
|
@ -932,18 +802,18 @@ module.exports = React.createClass({
|
|||
<h3>{ _t('Analytics') }</h3>
|
||||
<div className="mx_UserSettings_section">
|
||||
{ _t('Riot collects anonymous analytics to allow us to improve the application.') }
|
||||
{ ANALYTICS_SETTINGS_LABELS.map( this._renderLocalSetting ) }
|
||||
{ ANALYTICS_SETTINGS.map( this._renderDeviceSetting ) }
|
||||
</div>
|
||||
</div>;
|
||||
},
|
||||
|
||||
_renderLabs: function() {
|
||||
const features = [];
|
||||
UserSettingsStore.getLabsFeatures().forEach((featureId) => {
|
||||
SettingsStore.getLabsFeatures().forEach((featureId) => {
|
||||
// TODO: this ought to be a separate component so that we don't need
|
||||
// to rebind the onChange each time we render
|
||||
const onChange = (e) => {
|
||||
UserSettingsStore.setFeatureEnabled(featureId, e.target.checked);
|
||||
SettingsStore.setFeatureEnabled(featureId, e.target.checked);
|
||||
this.forceUpdate();
|
||||
};
|
||||
|
||||
|
@ -953,10 +823,10 @@ module.exports = React.createClass({
|
|||
type="checkbox"
|
||||
id={featureId}
|
||||
name={featureId}
|
||||
defaultChecked={UserSettingsStore.isFeatureEnabled(featureId)}
|
||||
defaultChecked={SettingsStore.isFeatureEnabled(featureId)}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<label htmlFor={featureId}>{ UserSettingsStore.translatedNameForFeature(featureId) }</label>
|
||||
<label htmlFor={featureId}>{ SettingsStore.getDisplayName(featureId) }</label>
|
||||
</div>);
|
||||
});
|
||||
|
||||
|
@ -1049,6 +919,8 @@ module.exports = React.createClass({
|
|||
const settings = this.state.electron_settings;
|
||||
if (!settings) return;
|
||||
|
||||
// TODO: This should probably be a granular setting, but it only applies to electron
|
||||
// and ends up being get/set outside of matrix anyways (local system setting).
|
||||
return <div>
|
||||
<h3>{ _t('Desktop specific') }</h3>
|
||||
<div className="mx_UserSettings_section">
|
||||
|
@ -1171,7 +1043,7 @@ module.exports = React.createClass({
|
|||
return <div>
|
||||
<h3>{ _t('VoIP') }</h3>
|
||||
<div className="mx_UserSettings_section">
|
||||
{ WEBRTC_SETTINGS_LABELS.map(this._renderLocalSetting) }
|
||||
{ WEBRTC_SETTINGS.map(this._renderDeviceSetting) }
|
||||
{ this._renderWebRtcDeviceSettings() }
|
||||
</div>
|
||||
</div>;
|
||||
|
|
|
@ -22,9 +22,9 @@ import { _t, _tJsx } from '../../../languageHandler';
|
|||
import * as languageHandler from '../../../languageHandler';
|
||||
import sdk from '../../../index';
|
||||
import Login from '../../../Login';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import PlatformPeg from '../../../PlatformPeg';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
|
||||
// For validating phone numbers without country codes
|
||||
const PHONE_NUMBER_REGEX = /^[0-9\(\)\-\s]*$/;
|
||||
|
@ -328,7 +328,7 @@ module.exports = React.createClass({
|
|||
|
||||
_onLanguageChange: function(newLang) {
|
||||
if(languageHandler.getCurrentLanguage() !== newLang) {
|
||||
UserSettingsStore.setLocalSetting('language', newLang);
|
||||
SettingsStore.setValue("language", null, SettingLevel.DEVICE, newLang);
|
||||
PlatformPeg.get().reload();
|
||||
}
|
||||
},
|
||||
|
@ -385,7 +385,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
// FIXME: remove status.im theme tweaks
|
||||
const theme = UserSettingsStore.getTheme();
|
||||
const theme = SettingsStore.getValue("theme");
|
||||
if (theme !== "status") {
|
||||
header = <h2>{ _t('Sign in') }</h2>;
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ import MatrixClientPeg from '../../../MatrixClientPeg';
|
|||
import RegistrationForm from '../../views/login/RegistrationForm';
|
||||
import RtsClient from '../../../RtsClient';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
const MIN_PASSWORD_LENGTH = 6;
|
||||
|
||||
|
@ -329,7 +329,7 @@ module.exports = React.createClass({
|
|||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
const ServerConfig = sdk.getComponent('views.login.ServerConfig');
|
||||
|
||||
const theme = UserSettingsStore.getTheme();
|
||||
const theme = SettingsStore.getValue("theme");
|
||||
|
||||
let registerBody;
|
||||
if (this.state.doingUIAuth) {
|
||||
|
|
|
@ -22,8 +22,8 @@ import MatrixClientPeg from "../../../MatrixClientPeg";
|
|||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import Presence from "../../../Presence";
|
||||
import dispatcher from "../../../dispatcher";
|
||||
import UserSettingsStore from "../../../UserSettingsStore";
|
||||
import * as ContextualMenu from "../../structures/ContextualMenu";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MemberPresenceAvatar',
|
||||
|
@ -133,7 +133,7 @@ module.exports = React.createClass({
|
|||
);
|
||||
|
||||
// LABS: Disable presence management functions for now
|
||||
if (!UserSettingsStore.isFeatureEnabled("feature_presence_management")) {
|
||||
if (!SettingsStore.isFeatureEnabled("feature_presence_management")) {
|
||||
statusNode = null;
|
||||
onClickFn = null;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import MatrixClientPeg from '../../../MatrixClientPeg';
|
|||
import GeminiScrollbar from 'react-gemini-scrollbar';
|
||||
import Resend from '../../../Resend';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
function DeviceListEntry(props) {
|
||||
const {userId, device} = props;
|
||||
|
@ -112,12 +113,13 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
const client = MatrixClientPeg.get();
|
||||
const blacklistUnverified = client.getGlobalBlacklistUnverifiedDevices() ||
|
||||
this.props.room.getBlacklistUnverifiedDevices();
|
||||
if (this.state.devices === null) {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
let warning;
|
||||
if (blacklistUnverified) {
|
||||
if (SettingsStore.getValue("blacklistUnverifiedDevices", this.props.room.roomId)) {
|
||||
warning = (
|
||||
<h4>
|
||||
{ _t("You are currently blacklisting unverified devices; to send " +
|
||||
|
|
|
@ -18,8 +18,8 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
|
||||
import sdk from '../../../index';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import * as languageHandler from '../../../languageHandler';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
function languageMatchesSearchQuery(query, language) {
|
||||
if (language.label.toUpperCase().indexOf(query.toUpperCase()) == 0) return true;
|
||||
|
@ -54,9 +54,9 @@ export default class LanguageDropdown extends React.Component {
|
|||
// If no value is given, we start with the first
|
||||
// country selected, but our parent component
|
||||
// doesn't know this, therefore we do this.
|
||||
const _localSettings = UserSettingsStore.getLocalSettings();
|
||||
if (_localSettings.hasOwnProperty('language')) {
|
||||
this.props.onOptionChange(_localSettings.language);
|
||||
const language = SettingsStore.getValue("language", null, /*excludeDefault:*/true);
|
||||
if (language) {
|
||||
this.props.onOptionChange(language);
|
||||
}else {
|
||||
const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser());
|
||||
this.props.onOptionChange(language);
|
||||
|
@ -95,12 +95,12 @@ export default class LanguageDropdown extends React.Component {
|
|||
|
||||
// default value here too, otherwise we need to handle null / undefined
|
||||
// values between mounting and the initial value propgating
|
||||
let language = SettingsStore.getValue("language", null, /*excludeDefault:*/true);
|
||||
let value = null;
|
||||
const _localSettings = UserSettingsStore.getLocalSettings();
|
||||
if (_localSettings.hasOwnProperty('language')) {
|
||||
value = this.props.value || _localSettings.language;
|
||||
if (language) {
|
||||
value = this.props.value || language;
|
||||
} else {
|
||||
const language = navigator.language || navigator.userLanguage;
|
||||
language = navigator.language || navigator.userLanguage;
|
||||
value = this.props.value || language;
|
||||
}
|
||||
|
||||
|
|
110
src/components/views/elements/SettingsFlag.js
Normal file
110
src/components/views/elements/SettingsFlag.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'SettingsFlag',
|
||||
propTypes: {
|
||||
name: React.PropTypes.string.isRequired,
|
||||
level: React.PropTypes.string.isRequired,
|
||||
roomId: React.PropTypes.string, // for per-room settings
|
||||
label: React.PropTypes.string, // untranslated
|
||||
onChange: React.PropTypes.func,
|
||||
isExplicit: React.PropTypes.bool,
|
||||
manualSave: React.PropTypes.bool,
|
||||
|
||||
// If group is supplied, then this will create a radio button instead.
|
||||
group: React.PropTypes.string,
|
||||
value: React.PropTypes.any, // the value for the radio button
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
value: SettingsStore.getValueAt(
|
||||
this.props.level,
|
||||
this.props.name,
|
||||
this.props.roomId,
|
||||
this.props.isExplicit,
|
||||
),
|
||||
};
|
||||
},
|
||||
|
||||
onChange: function(e) {
|
||||
if (this.props.group && !e.target.checked) return;
|
||||
|
||||
const newState = this.props.group ? this.props.value : e.target.checked;
|
||||
if (!this.props.manualSave) this.save(newState);
|
||||
else this.setState({ value: newState });
|
||||
if (this.props.onChange) this.props.onChange(newState);
|
||||
},
|
||||
|
||||
save: function(val = undefined) {
|
||||
return SettingsStore.setValue(
|
||||
this.props.name,
|
||||
this.props.roomId,
|
||||
this.props.level,
|
||||
val !== undefined ? val : this.state.value,
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const value = this.props.manualSave ? this.state.value : SettingsStore.getValueAt(
|
||||
this.props.level,
|
||||
this.props.name,
|
||||
this.props.roomId,
|
||||
this.props.isExplicit,
|
||||
);
|
||||
|
||||
const canChange = SettingsStore.canSetValue(this.props.name, this.props.roomId, this.props.level);
|
||||
|
||||
let label = this.props.label;
|
||||
if (!label) label = SettingsStore.getDisplayName(this.props.name, this.props.level);
|
||||
else label = _t(label);
|
||||
|
||||
// We generate a relatively complex ID to avoid conflicts
|
||||
const id = this.props.name + "_" + this.props.group + "_" + this.props.value + "_" + this.props.level;
|
||||
let checkbox = (
|
||||
<input id={id}
|
||||
type="checkbox"
|
||||
defaultChecked={value}
|
||||
onChange={this.onChange}
|
||||
disabled={!canChange}
|
||||
/>
|
||||
);
|
||||
if (this.props.group) {
|
||||
checkbox = (
|
||||
<input id={id}
|
||||
type="radio"
|
||||
name={this.props.group}
|
||||
value={this.props.value}
|
||||
checked={value === this.props.value}
|
||||
onChange={this.onChange}
|
||||
disabled={!canChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<label>
|
||||
{ checkbox }
|
||||
{ label }
|
||||
</label>
|
||||
);
|
||||
},
|
||||
});
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
const React = require('react');
|
||||
|
||||
|
@ -25,7 +25,7 @@ module.exports = React.createClass({
|
|||
|
||||
render: function() {
|
||||
// FIXME: this should be turned into a proper skin with a StatusLoginPage component
|
||||
if (UserSettingsStore.getTheme() === 'status') {
|
||||
if (SettingsStore.getValue("theme") === 'status') {
|
||||
return (
|
||||
<div className="mx_StatusLogin">
|
||||
<div className="mx_StatusLogin_brand">
|
||||
|
|
|
@ -22,8 +22,8 @@ import Email from '../../../email';
|
|||
import { looksValid as phoneNumberLooksValid } from '../../../phonenumber';
|
||||
import Modal from '../../../Modal';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
const FIELD_EMAIL = 'field_email';
|
||||
const FIELD_PHONE_COUNTRY = 'field_phone_country';
|
||||
|
@ -275,7 +275,7 @@ module.exports = React.createClass({
|
|||
render: function() {
|
||||
const self = this;
|
||||
|
||||
const theme = UserSettingsStore.getTheme();
|
||||
const theme = SettingsStore.getValue("theme");
|
||||
// FIXME: remove hardcoded Status team tweaks at some point
|
||||
const emailPlaceholder = theme === 'status' ? _t("Email address") : _t("Email address (optional)");
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ import sdk from '../../../index';
|
|||
import dis from '../../../dispatcher';
|
||||
import { decryptFile, readBlobAsDataUri } from '../../../utils/DecryptFile';
|
||||
import Promise from 'bluebird';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MImageBody',
|
||||
|
@ -81,7 +81,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onImageEnter: function(e) {
|
||||
if (!this._isGif() || UserSettingsStore.getSyncedSetting("autoplayGifsAndVideos", false)) {
|
||||
if (!this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) {
|
||||
return;
|
||||
}
|
||||
const imgElement = e.target;
|
||||
|
@ -89,7 +89,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onImageLeave: function(e) {
|
||||
if (!this._isGif() || UserSettingsStore.getSyncedSetting("autoplayGifsAndVideos", false)) {
|
||||
if (!this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) {
|
||||
return;
|
||||
}
|
||||
const imgElement = e.target;
|
||||
|
@ -218,7 +218,7 @@ module.exports = React.createClass({
|
|||
|
||||
const contentUrl = this._getContentUrl();
|
||||
let thumbUrl;
|
||||
if (this._isGif() && UserSettingsStore.getSyncedSetting("autoplayGifsAndVideos", false)) {
|
||||
if (this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) {
|
||||
thumbUrl = contentUrl;
|
||||
} else {
|
||||
thumbUrl = this._getThumbUrl();
|
||||
|
|
|
@ -21,8 +21,8 @@ import MFileBody from './MFileBody';
|
|||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||
import { decryptFile, readBlobAsDataUri } from '../../../utils/DecryptFile';
|
||||
import Promise from 'bluebird';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MVideoBody',
|
||||
|
@ -151,7 +151,7 @@ module.exports = React.createClass({
|
|||
|
||||
const contentUrl = this._getContentUrl();
|
||||
const thumbUrl = this._getThumbUrl();
|
||||
const autoplay = UserSettingsStore.getSyncedSetting("autoplayGifsAndVideos", false);
|
||||
const autoplay = SettingsStore.getValue("autoplayGifsAndVideos");
|
||||
let height = null;
|
||||
let width = null;
|
||||
let poster = null;
|
||||
|
|
|
@ -29,11 +29,11 @@ import Modal from '../../../Modal';
|
|||
import SdkConfig from '../../../SdkConfig';
|
||||
import dis from '../../../dispatcher';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import UserSettingsStore from "../../../UserSettingsStore";
|
||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||
import ContextualMenu from '../../structures/ContextualMenu';
|
||||
import {RoomMember} from 'matrix-js-sdk';
|
||||
import classNames from 'classnames';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import PushProcessor from 'matrix-js-sdk/lib/pushprocessor';
|
||||
|
||||
linkifyMatrix(linkify);
|
||||
|
@ -104,7 +104,7 @@ module.exports = React.createClass({
|
|||
setTimeout(() => {
|
||||
if (this._unmounted) return;
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
if (UserSettingsStore.getSyncedSetting("enableSyntaxHighlightLanguageDetection", false)) {
|
||||
if (SettingsStore.getValue("enableSyntaxHighlightLanguageDetection")) {
|
||||
highlight.highlightBlock(blocks[i]);
|
||||
} else {
|
||||
// Only syntax highlight if there's a class starting with language-
|
||||
|
@ -169,7 +169,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
pillifyLinks: function(nodes) {
|
||||
const shouldShowPillAvatar = !UserSettingsStore.getSyncedSetting("Pill.shouldHidePillAvatar", false);
|
||||
const shouldShowPillAvatar = !SettingsStore.getValue("Pill.shouldHidePillAvatar");
|
||||
let node = nodes[0];
|
||||
while (node) {
|
||||
let pillified = false;
|
||||
|
@ -419,7 +419,7 @@ module.exports = React.createClass({
|
|||
const content = mxEvent.getContent();
|
||||
|
||||
let body = HtmlUtils.bodyToHtml(content, this.props.highlights, {
|
||||
disableBigEmoji: UserSettingsStore.getSyncedSetting('TextualBody.disableBigEmoji', false),
|
||||
disableBigEmoji: SettingsStore.getValue('TextualBody.disableBigEmoji'),
|
||||
});
|
||||
|
||||
if (this.props.highlightLink) {
|
||||
|
|
|
@ -22,6 +22,7 @@ const MatrixClientPeg = require("../../../MatrixClientPeg");
|
|||
const Modal = require("../../../Modal");
|
||||
|
||||
import dis from '../../../dispatcher';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
|
||||
const ROOM_COLORS = [
|
||||
// magic room default values courtesy of Ribot
|
||||
|
@ -47,17 +48,17 @@ module.exports = React.createClass({
|
|||
getInitialState: function() {
|
||||
const data = {
|
||||
index: 0,
|
||||
primary_color: ROOM_COLORS[0].primary_color,
|
||||
secondary_color: ROOM_COLORS[0].secondary_color,
|
||||
primary_color: ROOM_COLORS[0][0],
|
||||
secondary_color: ROOM_COLORS[0][1],
|
||||
hasChanged: false,
|
||||
};
|
||||
const event = this.props.room.getAccountData("org.matrix.room.color_scheme");
|
||||
if (!event) {
|
||||
return data;
|
||||
const scheme = SettingsStore.getValueAt(SettingLevel.ROOM_ACCOUNT, "roomColor", this.props.room.roomId);
|
||||
|
||||
if (scheme.primary_color && scheme.secondary_color) {
|
||||
// We only use the user's scheme if the scheme is valid.
|
||||
data.primary_color = scheme.primary_color;
|
||||
data.secondary_color = scheme.secondary_color;
|
||||
}
|
||||
const scheme = event.getContent();
|
||||
data.primary_color = scheme.primary_color;
|
||||
data.secondary_color = scheme.secondary_color;
|
||||
data.index = this._getColorIndex(data);
|
||||
|
||||
if (data.index === -1) {
|
||||
|
@ -81,13 +82,13 @@ module.exports = React.createClass({
|
|||
// We would like guests to be able to set room colour but currently
|
||||
// they can't, so we still send the request but display a sensible
|
||||
// error if it fails.
|
||||
return MatrixClientPeg.get().setRoomAccountData(
|
||||
this.props.room.roomId, "org.matrix.room.color_scheme", {
|
||||
primary_color: this.state.primary_color,
|
||||
secondary_color: this.state.secondary_color,
|
||||
},
|
||||
).catch(function(err) {
|
||||
if (err.errcode == 'M_GUEST_ACCESS_FORBIDDEN') {
|
||||
// TODO: Support guests for room color. Technically this is possible via granular settings
|
||||
// Granular settings would mean the guest is forced to use the DEVICE level though.
|
||||
SettingsStore.setValue("roomColor", this.props.room.roomId, SettingLevel.ROOM_ACCOUNT, {
|
||||
primary_color: this.state.primary_color,
|
||||
secondary_color: this.state.secondary_color,
|
||||
}).catch(function(err) {
|
||||
if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN') {
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
Copyright 2017 Travis Ralston
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -14,13 +15,10 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Promise from 'bluebird';
|
||||
const React = require('react');
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const sdk = require("../../../index");
|
||||
const Modal = require("../../../Modal");
|
||||
const UserSettingsStore = require('../../../UserSettingsStore');
|
||||
import { _t, _tJsx } from '../../../languageHandler';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -30,137 +28,64 @@ module.exports = React.createClass({
|
|||
room: React.PropTypes.object,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const roomState = this.props.room.currentState;
|
||||
|
||||
const roomPreviewUrls = this.props.room.currentState.getStateEvents('org.matrix.room.preview_urls', '');
|
||||
const userPreviewUrls = this.props.room.getAccountData("org.matrix.room.preview_urls");
|
||||
|
||||
return {
|
||||
globalDisableUrlPreview: (roomPreviewUrls && roomPreviewUrls.getContent().disable) || false,
|
||||
userDisableUrlPreview: (userPreviewUrls && (userPreviewUrls.getContent().disable === true)) || false,
|
||||
userEnableUrlPreview: (userPreviewUrls && (userPreviewUrls.getContent().disable === false)) || false,
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.originalState = Object.assign({}, this.state);
|
||||
},
|
||||
|
||||
saveSettings: function() {
|
||||
const promises = [];
|
||||
|
||||
if (this.state.globalDisableUrlPreview !== this.originalState.globalDisableUrlPreview) {
|
||||
console.log("UrlPreviewSettings: Updating room's preview_urls state event");
|
||||
promises.push(
|
||||
MatrixClientPeg.get().sendStateEvent(
|
||||
this.props.room.roomId, "org.matrix.room.preview_urls", {
|
||||
disable: this.state.globalDisableUrlPreview,
|
||||
}, "",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
let content = undefined;
|
||||
if (this.state.userDisableUrlPreview !== this.originalState.userDisableUrlPreview) {
|
||||
console.log("UrlPreviewSettings: Disabling user's per-room preview_urls");
|
||||
content = this.state.userDisableUrlPreview ? { disable: true } : {};
|
||||
}
|
||||
|
||||
if (this.state.userEnableUrlPreview !== this.originalState.userEnableUrlPreview) {
|
||||
console.log("UrlPreviewSettings: Enabling user's per-room preview_urls");
|
||||
if (!content || content.disable === undefined) {
|
||||
content = this.state.userEnableUrlPreview ? { disable: false } : {};
|
||||
}
|
||||
}
|
||||
|
||||
if (content) {
|
||||
promises.push(
|
||||
MatrixClientPeg.get().setRoomAccountData(
|
||||
this.props.room.roomId, "org.matrix.room.preview_urls", content,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
console.log("UrlPreviewSettings: saveSettings: " + JSON.stringify(promises));
|
||||
|
||||
if (this.refs.urlPreviewsRoom) promises.push(this.refs.urlPreviewsRoom.save());
|
||||
if (this.refs.urlPrviewsSelf) promises.push(this.refs.urlPreviewsSelf.save());
|
||||
return promises;
|
||||
},
|
||||
|
||||
onGlobalDisableUrlPreviewChange: function() {
|
||||
this.setState({
|
||||
globalDisableUrlPreview: this.refs.globalDisableUrlPreview.checked ? true : false,
|
||||
});
|
||||
},
|
||||
|
||||
onUserEnableUrlPreviewChange: function() {
|
||||
this.setState({
|
||||
userDisableUrlPreview: false,
|
||||
userEnableUrlPreview: this.refs.userEnableUrlPreview.checked ? true : false,
|
||||
});
|
||||
},
|
||||
|
||||
onUserDisableUrlPreviewChange: function() {
|
||||
this.setState({
|
||||
userDisableUrlPreview: this.refs.userDisableUrlPreview.checked ? true : false,
|
||||
userEnableUrlPreview: false,
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const self = this;
|
||||
const roomState = this.props.room.currentState;
|
||||
const cli = MatrixClientPeg.get();
|
||||
const SettingsFlag = sdk.getComponent("elements.SettingsFlag");
|
||||
const roomId = this.props.room.roomId;
|
||||
|
||||
const maySetRoomPreviewUrls = roomState.mayClientSendStateEvent('org.matrix.room.preview_urls', cli);
|
||||
let disableRoomPreviewUrls;
|
||||
if (maySetRoomPreviewUrls) {
|
||||
disableRoomPreviewUrls =
|
||||
<label>
|
||||
<input type="checkbox" ref="globalDisableUrlPreview"
|
||||
onChange={this.onGlobalDisableUrlPreviewChange}
|
||||
checked={this.state.globalDisableUrlPreview} />
|
||||
{ _t("Disable URL previews by default for participants in this room") }
|
||||
</label>;
|
||||
} else {
|
||||
disableRoomPreviewUrls =
|
||||
<label>
|
||||
{ _t("URL previews are %(globalDisableUrlPreview)s by default for participants in this room.", {globalDisableUrlPreview: this.state.globalDisableUrlPreview ? _t("disabled") : _t("enabled")}) }
|
||||
</label>;
|
||||
}
|
||||
|
||||
let urlPreviewText = null;
|
||||
if (UserSettingsStore.getUrlPreviewsDisabled()) {
|
||||
urlPreviewText = (
|
||||
_tJsx("You have <a>disabled</a> URL previews by default.", /<a>(.*?)<\/a>/, (sub)=><a href="#/settings">{ sub }</a>)
|
||||
);
|
||||
} else {
|
||||
urlPreviewText = (
|
||||
let previewsForAccount = null;
|
||||
if (SettingsStore.getValueAt(SettingLevel.ACCOUNT, "urlPreviewsEnabled")) {
|
||||
previewsForAccount = (
|
||||
_tJsx("You have <a>enabled</a> URL previews by default.", /<a>(.*?)<\/a>/, (sub)=><a href="#/settings">{ sub }</a>)
|
||||
);
|
||||
} else {
|
||||
previewsForAccount = (
|
||||
_tJsx("You have <a>disabled</a> URL previews by default.", /<a>(.*?)<\/a>/, (sub)=><a href="#/settings">{ sub }</a>)
|
||||
);
|
||||
}
|
||||
|
||||
let previewsForRoom = null;
|
||||
if (SettingsStore.canSetValue("urlPreviewsEnabled", roomId, "room")) {
|
||||
previewsForRoom = (
|
||||
<label>
|
||||
<SettingsFlag name="urlPreviewsEnabled"
|
||||
level={SettingLevel.ROOM}
|
||||
roomId={this.props.room.roomId}
|
||||
isExplicit={true}
|
||||
manualSave={true}
|
||||
ref="urlPreviewsRoom" />
|
||||
</label>
|
||||
);
|
||||
} else {
|
||||
let str = "URL previews are enabled by default for participants in this room.";
|
||||
if (!SettingsStore.getValueAt(SettingLevel.ROOM, "urlPreviewsEnabled")) {
|
||||
str = "URL previews are disabled by default for participants in this room.";
|
||||
}
|
||||
previewsForRoom = (<label>{ _t(str) }</label>);
|
||||
}
|
||||
|
||||
let previewsForRoomAccount = (
|
||||
<SettingsFlag name="urlPreviewsEnabled"
|
||||
level={SettingLevel.ROOM_ACCOUNT}
|
||||
roomId={this.props.room.roomId}
|
||||
manualSave={true}
|
||||
ref="urlPreviewsSelf"
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mx_RoomSettings_toggles">
|
||||
<h3>{ _t("URL Previews") }</h3>
|
||||
|
||||
<label>
|
||||
{ urlPreviewText }
|
||||
</label>
|
||||
{ disableRoomPreviewUrls }
|
||||
<label>
|
||||
<input type="checkbox" ref="userEnableUrlPreview"
|
||||
onChange={this.onUserEnableUrlPreviewChange}
|
||||
checked={this.state.userEnableUrlPreview} />
|
||||
{ _t("Enable URL previews for this room (affects only you)") }
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" ref="userDisableUrlPreview"
|
||||
onChange={this.onUserDisableUrlPreviewChange}
|
||||
checked={this.state.userDisableUrlPreview} />
|
||||
{ _t("Disable URL previews for this room (affects only you)") }
|
||||
</label>
|
||||
<label>{ previewsForAccount }</label>
|
||||
{ previewsForRoom }
|
||||
<label>{ previewsForRoomAccount }</label>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -24,9 +24,10 @@ import isEqual from 'lodash/isEqual';
|
|||
import sdk from '../../../index';
|
||||
import type {Completion} from '../../../autocomplete/Autocompleter';
|
||||
import Promise from 'bluebird';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import { Room } from 'matrix-js-sdk';
|
||||
|
||||
import {getCompletions} from '../../../autocomplete/Autocompleter';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import Autocompleter from '../../../autocomplete/Autocompleter';
|
||||
|
||||
const COMPOSER_SELECTED = 0;
|
||||
|
@ -95,7 +96,7 @@ export default class Autocomplete extends React.Component {
|
|||
});
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
let autocompleteDelay = UserSettingsStore.getLocalSetting('autocompleteDelay', 200);
|
||||
let autocompleteDelay = SettingsStore.getValue("autocompleteDelay");
|
||||
|
||||
// Don't debounce if we are already showing completions
|
||||
if (this.state.completions.length > 0 || this.state.forceComplete) {
|
||||
|
|
|
@ -22,7 +22,6 @@ import dis from "../../../dispatcher";
|
|||
import ObjectUtils from '../../../ObjectUtils';
|
||||
import AppsDrawer from './AppsDrawer';
|
||||
import { _t, _tJsx} from '../../../languageHandler';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
|
|
@ -22,7 +22,7 @@ import Modal from '../../../Modal';
|
|||
import sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import Autocomplete from './Autocomplete';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
|
||||
|
||||
export default class MessageComposer extends React.Component {
|
||||
|
@ -49,10 +49,10 @@ export default class MessageComposer extends React.Component {
|
|||
inputState: {
|
||||
style: [],
|
||||
blockType: null,
|
||||
isRichtextEnabled: UserSettingsStore.getSyncedSetting('MessageComposerInput.isRichTextEnabled', false),
|
||||
isRichtextEnabled: SettingsStore.getValue('MessageComposerInput.isRichTextEnabled'),
|
||||
wordCount: 0,
|
||||
},
|
||||
showFormatting: UserSettingsStore.getSyncedSetting('MessageComposer.showFormatting', false),
|
||||
showFormatting: SettingsStore.getValue('MessageComposer.showFormatting'),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ export default class MessageComposer extends React.Component {
|
|||
}
|
||||
|
||||
onToggleFormattingClicked() {
|
||||
UserSettingsStore.setSyncedSetting('MessageComposer.showFormatting', !this.state.showFormatting);
|
||||
SettingsStore.setValue("MessageComposer.showFormatting", null, SettingLevel.DEVICE, !this.state.showFormatting);
|
||||
this.setState({showFormatting: !this.state.showFormatting});
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ import { _t, _td } from '../../../languageHandler';
|
|||
import Analytics from '../../../Analytics';
|
||||
|
||||
import dis from '../../../dispatcher';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
|
||||
import * as RichText from '../../../RichText';
|
||||
import * as HtmlUtils from '../../../HtmlUtils';
|
||||
|
@ -50,6 +49,7 @@ const REGEX_MATRIXTO = new RegExp(MATRIXTO_URL_PATTERN);
|
|||
const REGEX_MATRIXTO_MARKDOWN_GLOBAL = new RegExp(MATRIXTO_MD_LINK_PATTERN, 'g');
|
||||
|
||||
import {asciiRegexp, shortnameToUnicode, emojioneList, asciiList, mapUnicodeToShort} from 'emojione';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
const EMOJI_SHORTNAMES = Object.keys(emojioneList);
|
||||
const EMOJI_UNICODE_TO_SHORTNAME = mapUnicodeToShort();
|
||||
const REGEX_EMOJI_WHITESPACE = new RegExp('(?:^|\\s)(' + asciiRegexp + ')\\s$');
|
||||
|
@ -165,7 +165,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
this.onMarkdownToggleClicked = this.onMarkdownToggleClicked.bind(this);
|
||||
this.onTextPasted = this.onTextPasted.bind(this);
|
||||
|
||||
const isRichtextEnabled = UserSettingsStore.getSyncedSetting('MessageComposerInput.isRichTextEnabled', false);
|
||||
const isRichtextEnabled = SettingsStore.getValue('MessageComposerInput.isRichTextEnabled');
|
||||
|
||||
Analytics.setRichtextMode(isRichtextEnabled);
|
||||
|
||||
|
@ -216,7 +216,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
createEditorState(richText: boolean, contentState: ?ContentState): EditorState {
|
||||
const decorators = richText ? RichText.getScopedRTDecorators(this.props) :
|
||||
RichText.getScopedMDDecorators(this.props);
|
||||
const shouldShowPillAvatar = !UserSettingsStore.getSyncedSetting("Pill.shouldHidePillAvatar", false);
|
||||
const shouldShowPillAvatar = !SettingsStore.getValue("Pill.shouldHidePillAvatar");
|
||||
decorators.push({
|
||||
strategy: this.findPillEntities.bind(this),
|
||||
component: (entityProps) => {
|
||||
|
@ -384,7 +384,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
}
|
||||
|
||||
sendTyping(isTyping) {
|
||||
if (UserSettingsStore.getSyncedSetting('dontSendTypingNotifications', false)) return;
|
||||
if (SettingsStore.getValue('dontSendTypingNotifications')) return;
|
||||
MatrixClientPeg.get().sendTyping(
|
||||
this.props.room.roomId,
|
||||
this.isTyping, TYPING_SERVER_TIMEOUT,
|
||||
|
@ -431,7 +431,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
}
|
||||
|
||||
// Automatic replacement of plaintext emoji to Unicode emoji
|
||||
if (UserSettingsStore.getSyncedSetting('MessageComposerInput.autoReplaceEmoji', false)) {
|
||||
if (SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji')) {
|
||||
// The first matched group includes just the matched plaintext emoji
|
||||
const emojiMatch = REGEX_EMOJI_WHITESPACE.exec(text.slice(0, currentStartOffset));
|
||||
if(emojiMatch) {
|
||||
|
@ -551,7 +551,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
editorState: this.createEditorState(enabled, contentState),
|
||||
isRichtextEnabled: enabled,
|
||||
});
|
||||
UserSettingsStore.setSyncedSetting('MessageComposerInput.isRichTextEnabled', enabled);
|
||||
SettingsStore.setValue("MessageComposerInput.isRichTextEnabled", null, SettingLevel.ACCOUNT, enabled);
|
||||
}
|
||||
|
||||
handleKeyCommand = (command: string): boolean => {
|
||||
|
|
|
@ -31,7 +31,7 @@ import linkifyMatrix from '../../../linkify-matrix';
|
|||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import ManageIntegsButton from '../elements/ManageIntegsButton';
|
||||
import {CancelButton} from './SimpleRoomHeader';
|
||||
import UserSettingsStore from "../../../UserSettingsStore";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
linkifyMatrix(linkify);
|
||||
|
||||
|
@ -339,7 +339,7 @@ module.exports = React.createClass({
|
|||
</AccessibleButton>;
|
||||
}
|
||||
|
||||
if (this.props.onPinnedClick && UserSettingsStore.isFeatureEnabled('feature_pinning')) {
|
||||
if (this.props.onPinnedClick && SettingsStore.isFeatureEnabled('feature_pinning')) {
|
||||
let pinsIndicator = null;
|
||||
if (this._hasUnreadPins()) {
|
||||
pinsIndicator = (<div className="mx_RoomHeader_pinsIndicator mx_RoomHeader_pinsIndicatorUnread" />);
|
||||
|
|
|
@ -23,8 +23,8 @@ import sdk from '../../../index';
|
|||
import Modal from '../../../Modal';
|
||||
import ObjectUtils from '../../../ObjectUtils';
|
||||
import dis from '../../../dispatcher';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
|
||||
|
||||
// parse a string as an integer; if the input is undefined, or cannot be parsed
|
||||
|
@ -309,9 +309,9 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
// url preview settings
|
||||
const ps = this.saveUrlPreviewSettings();
|
||||
let ps = this.saveUrlPreviewSettings();
|
||||
if (ps.length > 0) {
|
||||
promises.push(ps);
|
||||
ps.map(p => promises.push(p));
|
||||
}
|
||||
|
||||
// related groups
|
||||
|
@ -363,26 +363,16 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
saveBlacklistUnverifiedDevicesPerRoom: function() {
|
||||
if (!this.refs.blacklistUnverified) return;
|
||||
if (this._isRoomBlacklistUnverified() !== this.refs.blacklistUnverified.checked) {
|
||||
this._setRoomBlacklistUnverified(this.refs.blacklistUnverified.checked);
|
||||
}
|
||||
},
|
||||
|
||||
_isRoomBlacklistUnverified: function() {
|
||||
const blacklistUnverifiedDevicesPerRoom = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevicesPerRoom;
|
||||
if (blacklistUnverifiedDevicesPerRoom) {
|
||||
return blacklistUnverifiedDevicesPerRoom[this.props.room.roomId];
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_setRoomBlacklistUnverified: function(value) {
|
||||
const blacklistUnverifiedDevicesPerRoom = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevicesPerRoom || {};
|
||||
blacklistUnverifiedDevicesPerRoom[this.props.room.roomId] = value;
|
||||
UserSettingsStore.setLocalSetting('blacklistUnverifiedDevicesPerRoom', blacklistUnverifiedDevicesPerRoom);
|
||||
|
||||
this.props.room.setBlacklistUnverifiedDevices(value);
|
||||
if (!this.refs.blacklistUnverifiedDevices) return;
|
||||
this.refs.blacklistUnverifiedDevices.save().then(() => {
|
||||
const value = SettingsStore.getValueAt(
|
||||
SettingLevel.ROOM_DEVICE,
|
||||
"blacklistUnverifiedDevices",
|
||||
this.props.room.roomId,
|
||||
/*explicit=*/true,
|
||||
);
|
||||
this.props.room.setBlacklistUnverifiedDevices(value);
|
||||
});
|
||||
},
|
||||
|
||||
_hasDiff: function(strA, strB) {
|
||||
|
@ -588,19 +578,20 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_renderEncryptionSection: function() {
|
||||
const SettingsFlag = sdk.getComponent("elements.SettingsFlag");
|
||||
|
||||
const cli = MatrixClientPeg.get();
|
||||
const roomState = this.props.room.currentState;
|
||||
const isEncrypted = cli.isRoomEncrypted(this.props.room.roomId);
|
||||
const isGlobalBlacklistUnverified = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevices;
|
||||
const isRoomBlacklistUnverified = this._isRoomBlacklistUnverified();
|
||||
|
||||
const settings =
|
||||
<label>
|
||||
<input type="checkbox" ref="blacklistUnverified"
|
||||
defaultChecked={isGlobalBlacklistUnverified || isRoomBlacklistUnverified}
|
||||
disabled={isGlobalBlacklistUnverified || (this.refs.encrypt && !this.refs.encrypt.checked)} />
|
||||
{ _t('Never send encrypted messages to unverified devices in this room from this device') }.
|
||||
</label>;
|
||||
let settings = (
|
||||
<SettingsFlag name="blacklistUnverifiedDevices"
|
||||
level={SettingLevel.ROOM_DEVICE}
|
||||
roomId={this.props.room.roomId}
|
||||
manualSave={true}
|
||||
ref="blacklistUnverifiedDevices"
|
||||
/>
|
||||
);
|
||||
|
||||
if (!isEncrypted && roomState.mayClientSendStateEvent("m.room.encryption", cli)) {
|
||||
return (
|
||||
|
|
|
@ -27,7 +27,6 @@ const ContextualMenu = require('../../structures/ContextualMenu');
|
|||
const RoomNotifs = require('../../../RoomNotifs');
|
||||
const FormattingUtils = require('../../../utils/FormattingUtils');
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
const UserSettingsStore = require('../../../UserSettingsStore');
|
||||
import ActiveRoomObserver from '../../../ActiveRoomObserver';
|
||||
import RoomViewStore from '../../../stores/RoomViewStore';
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import classNames from 'classnames';
|
|||
import sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'VideoView',
|
||||
|
@ -113,7 +113,7 @@ module.exports = React.createClass({
|
|||
const maxVideoHeight = fullscreenElement ? null : this.props.maxHeight;
|
||||
const localVideoFeedClasses = classNames("mx_VideoView_localVideoFeed",
|
||||
{ "mx_VideoView_localVideoFeed_flipped":
|
||||
UserSettingsStore.getSyncedSetting('VideoView.flipVideoHorizontally', false),
|
||||
SettingsStore.getValue('VideoView.flipVideoHorizontally'),
|
||||
},
|
||||
);
|
||||
return (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue