mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-18 14:44:58 +08:00
Merge remote-tracking branch 'origin/develop' into dbkr/group_userlist
This commit is contained in:
commit
64f352dda7
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { getCurrentLanguage } from './languageHandler';
|
import { getCurrentLanguage } from './languageHandler';
|
||||||
import MatrixClientPeg from './MatrixClientPeg';
|
|
||||||
import PlatformPeg from './PlatformPeg';
|
import PlatformPeg from './PlatformPeg';
|
||||||
import SdkConfig from './SdkConfig';
|
import SdkConfig from './SdkConfig';
|
||||||
|
|
||||||
@ -31,8 +30,18 @@ const customVariables = {
|
|||||||
'User Type': 3,
|
'User Type': 3,
|
||||||
'Chosen Language': 4,
|
'Chosen Language': 4,
|
||||||
'Instance': 5,
|
'Instance': 5,
|
||||||
|
'RTE: Uses Richtext Mode': 6,
|
||||||
|
'Homeserver URL': 7,
|
||||||
|
'Identity Server URL': 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function whitelistRedact(whitelist, str) {
|
||||||
|
if (whitelist.includes(str)) return str;
|
||||||
|
return '<redacted>';
|
||||||
|
}
|
||||||
|
|
||||||
|
const whitelistedHSUrls = ["https://matrix.org"];
|
||||||
|
const whitelistedISUrls = ["https://vector.im"];
|
||||||
|
|
||||||
class Analytics {
|
class Analytics {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -76,7 +85,7 @@ class Analytics {
|
|||||||
this._paq.push(['trackAllContentImpressions']);
|
this._paq.push(['trackAllContentImpressions']);
|
||||||
this._paq.push(['discardHashTag', false]);
|
this._paq.push(['discardHashTag', false]);
|
||||||
this._paq.push(['enableHeartBeatTimer']);
|
this._paq.push(['enableHeartBeatTimer']);
|
||||||
this._paq.push(['enableLinkTracking', true]);
|
// this._paq.push(['enableLinkTracking', true]);
|
||||||
|
|
||||||
const platform = PlatformPeg.get();
|
const platform = PlatformPeg.get();
|
||||||
this._setVisitVariable('App Platform', platform.getHumanReadableName());
|
this._setVisitVariable('App Platform', platform.getHumanReadableName());
|
||||||
@ -130,20 +139,20 @@ class Analytics {
|
|||||||
this._paq.push(['deleteCookies']);
|
this._paq.push(['deleteCookies']);
|
||||||
}
|
}
|
||||||
|
|
||||||
login() { // not used currently
|
|
||||||
const cli = MatrixClientPeg.get();
|
|
||||||
if (this.disabled || !cli) return;
|
|
||||||
|
|
||||||
this._paq.push(['setUserId', `@${cli.getUserIdLocalpart()}:${cli.getDomain()}`]);
|
|
||||||
}
|
|
||||||
|
|
||||||
_setVisitVariable(key, value) {
|
_setVisitVariable(key, value) {
|
||||||
this._paq.push(['setCustomVariable', customVariables[key], key, value, 'visit']);
|
this._paq.push(['setCustomVariable', customVariables[key], key, value, 'visit']);
|
||||||
}
|
}
|
||||||
|
|
||||||
setGuest(guest) {
|
setLoggedIn(isGuest, homeserverUrl, identityServerUrl) {
|
||||||
if (this.disabled) return;
|
if (this.disabled) return;
|
||||||
this._setVisitVariable('User Type', guest ? 'Guest' : 'Logged In');
|
this._setVisitVariable('User Type', isGuest ? 'Guest' : 'Logged In');
|
||||||
|
this._setVisitVariable('Homeserver URL', whitelistRedact(whitelistedHSUrls, homeserverUrl));
|
||||||
|
this._setVisitVariable('Identity Server URL', whitelistRedact(whitelistedISUrls, identityServerUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
setRichtextMode(state) {
|
||||||
|
if (this.disabled) return;
|
||||||
|
this._setVisitVariable('RTE: Uses Richtext Mode', state ? 'on' : 'off');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ function _setCallListeners(call) {
|
|||||||
pause("ringbackAudio");
|
pause("ringbackAudio");
|
||||||
play("busyAudio");
|
play("busyAudio");
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Call Handler', 'Call Timeout', ErrorDialog, {
|
||||||
title: _t('Call Timeout'),
|
title: _t('Call Timeout'),
|
||||||
description: _t('The remote side failed to pick up') + '.',
|
description: _t('The remote side failed to pick up') + '.',
|
||||||
});
|
});
|
||||||
@ -205,7 +205,7 @@ function _onAction(payload) {
|
|||||||
_setCallState(undefined, newCall.roomId, "ended");
|
_setCallState(undefined, newCall.roomId, "ended");
|
||||||
console.log("Can't capture screen: " + screenCapErrorString);
|
console.log("Can't capture screen: " + screenCapErrorString);
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Call Handler', 'Unable to capture screen', ErrorDialog, {
|
||||||
title: _t('Unable to capture screen'),
|
title: _t('Unable to capture screen'),
|
||||||
description: screenCapErrorString,
|
description: screenCapErrorString,
|
||||||
});
|
});
|
||||||
@ -225,7 +225,7 @@ function _onAction(payload) {
|
|||||||
case 'place_call':
|
case 'place_call':
|
||||||
if (module.exports.getAnyActiveCall()) {
|
if (module.exports.getAnyActiveCall()) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Call Handler', 'Existing Call', ErrorDialog, {
|
||||||
title: _t('Existing Call'),
|
title: _t('Existing Call'),
|
||||||
description: _t('You are already in a call.'),
|
description: _t('You are already in a call.'),
|
||||||
});
|
});
|
||||||
@ -235,7 +235,7 @@ function _onAction(payload) {
|
|||||||
// if the runtime env doesn't do VoIP, whine.
|
// if the runtime env doesn't do VoIP, whine.
|
||||||
if (!MatrixClientPeg.get().supportsVoip()) {
|
if (!MatrixClientPeg.get().supportsVoip()) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Call Handler', 'VoIP is unsupported', ErrorDialog, {
|
||||||
title: _t('VoIP is unsupported'),
|
title: _t('VoIP is unsupported'),
|
||||||
description: _t('You cannot place VoIP calls in this browser.'),
|
description: _t('You cannot place VoIP calls in this browser.'),
|
||||||
});
|
});
|
||||||
@ -251,7 +251,7 @@ function _onAction(payload) {
|
|||||||
var members = room.getJoinedMembers();
|
var members = room.getJoinedMembers();
|
||||||
if (members.length <= 1) {
|
if (members.length <= 1) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Call Handler', 'Cannot place call with self', ErrorDialog, {
|
||||||
description: _t('You cannot place a call with yourself.'),
|
description: _t('You cannot place a call with yourself.'),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@ -277,13 +277,13 @@ function _onAction(payload) {
|
|||||||
console.log("Place conference call in %s", payload.room_id);
|
console.log("Place conference call in %s", payload.room_id);
|
||||||
if (!ConferenceHandler) {
|
if (!ConferenceHandler) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Call Handler', 'Conference call unsupported client', ErrorDialog, {
|
||||||
description: _t('Conference calls are not supported in this client'),
|
description: _t('Conference calls are not supported in this client'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (!MatrixClientPeg.get().supportsVoip()) {
|
else if (!MatrixClientPeg.get().supportsVoip()) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Call Handler', 'VoIP is unsupported', ErrorDialog, {
|
||||||
title: _t('VoIP is unsupported'),
|
title: _t('VoIP is unsupported'),
|
||||||
description: _t('You cannot place VoIP calls in this browser.'),
|
description: _t('You cannot place VoIP calls in this browser.'),
|
||||||
});
|
});
|
||||||
@ -296,13 +296,13 @@ function _onAction(payload) {
|
|||||||
// participant.
|
// participant.
|
||||||
// Therefore we disable conference calling in E2E rooms.
|
// Therefore we disable conference calling in E2E rooms.
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Call Handler', 'Conference calls unsupported e2e', ErrorDialog, {
|
||||||
description: _t('Conference calls are not supported in encrypted rooms'),
|
description: _t('Conference calls are not supported in encrypted rooms'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Call Handler', 'Conference calling in development', QuestionDialog, {
|
||||||
title: _t('Warning!'),
|
title: _t('Warning!'),
|
||||||
description: _t('Conference calling is in development and may not be reliable.'),
|
description: _t('Conference calling is in development and may not be reliable.'),
|
||||||
onFinished: confirm=>{
|
onFinished: confirm=>{
|
||||||
@ -314,7 +314,7 @@ function _onAction(payload) {
|
|||||||
}, function(err) {
|
}, function(err) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Conference call failed: " + err);
|
console.error("Conference call failed: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Call Handler', 'Failed to set up conference call', ErrorDialog, {
|
||||||
title: _t('Failed to set up conference call'),
|
title: _t('Failed to set up conference call'),
|
||||||
description: _t('Conference call failed.') + ' ' + ((err && err.message) ? err.message : ''),
|
description: _t('Conference call failed.') + ' ' + ((err && err.message) ? err.message : ''),
|
||||||
});
|
});
|
||||||
|
@ -15,36 +15,38 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {ContentState} from 'draft-js';
|
import {ContentState, convertToRaw, convertFromRaw} from 'draft-js';
|
||||||
import * as RichText from './RichText';
|
import * as RichText from './RichText';
|
||||||
import Markdown from './Markdown';
|
import Markdown from './Markdown';
|
||||||
import _flow from 'lodash/flow';
|
|
||||||
import _clamp from 'lodash/clamp';
|
import _clamp from 'lodash/clamp';
|
||||||
|
|
||||||
type MessageFormat = 'html' | 'markdown';
|
type MessageFormat = 'html' | 'markdown';
|
||||||
|
|
||||||
class HistoryItem {
|
class HistoryItem {
|
||||||
message: string = '';
|
|
||||||
|
// Keeping message for backwards-compatibility
|
||||||
|
message: string;
|
||||||
|
rawContentState: RawDraftContentState;
|
||||||
format: MessageFormat = 'html';
|
format: MessageFormat = 'html';
|
||||||
|
|
||||||
constructor(message: string, format: MessageFormat) {
|
constructor(contentState: ?ContentState, format: ?MessageFormat) {
|
||||||
this.message = message;
|
this.rawContentState = contentState ? convertToRaw(contentState) : null;
|
||||||
this.format = format;
|
this.format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
toContentState(format: MessageFormat): ContentState {
|
toContentState(outputFormat: MessageFormat): ContentState {
|
||||||
let {message} = this;
|
const contentState = convertFromRaw(this.rawContentState);
|
||||||
if (format === 'markdown') {
|
if (outputFormat === 'markdown') {
|
||||||
if (this.format === 'html') {
|
if (this.format === 'html') {
|
||||||
message = _flow([RichText.htmlToContentState, RichText.stateToMarkdown])(message);
|
return ContentState.createFromText(RichText.stateToMarkdown(contentState));
|
||||||
}
|
}
|
||||||
return ContentState.createFromText(message);
|
|
||||||
} else {
|
} else {
|
||||||
if (this.format === 'markdown') {
|
if (this.format === 'markdown') {
|
||||||
message = new Markdown(message).toHTML();
|
return RichText.htmlToContentState(new Markdown(contentState.getPlainText()).toHTML());
|
||||||
}
|
}
|
||||||
return RichText.htmlToContentState(message);
|
|
||||||
}
|
}
|
||||||
|
// history item has format === outputFormat
|
||||||
|
return contentState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,8 +69,8 @@ export default class ComposerHistoryManager {
|
|||||||
this.lastIndex = this.currentIndex;
|
this.lastIndex = this.currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
addItem(message: string, format: MessageFormat) {
|
save(contentState: ContentState, format: MessageFormat) {
|
||||||
const item = new HistoryItem(message, format);
|
const item = new HistoryItem(contentState, format);
|
||||||
this.history.push(item);
|
this.history.push(item);
|
||||||
this.currentIndex = this.lastIndex + 1;
|
this.currentIndex = this.lastIndex + 1;
|
||||||
sessionStorage.setItem(`${this.prefix}[${this.lastIndex++}]`, JSON.stringify(item));
|
sessionStorage.setItem(`${this.prefix}[${this.lastIndex++}]`, JSON.stringify(item));
|
||||||
|
@ -360,7 +360,7 @@ class ContentMessages {
|
|||||||
desc = _t('The file \'%(fileName)s\' exceeds this home server\'s size limit for uploads', {fileName: upload.fileName});
|
desc = _t('The file \'%(fileName)s\' exceeds this home server\'s size limit for uploads', {fileName: upload.fileName});
|
||||||
}
|
}
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Upload failed', '', ErrorDialog, {
|
||||||
title: _t('Upload Failed'),
|
title: _t('Upload Failed'),
|
||||||
description: desc,
|
description: desc,
|
||||||
});
|
});
|
||||||
|
@ -125,7 +125,7 @@ export default class KeyRequestHandler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const KeyShareDialog = sdk.getComponent("dialogs.KeyShareDialog");
|
const KeyShareDialog = sdk.getComponent("dialogs.KeyShareDialog");
|
||||||
Modal.createDialog(KeyShareDialog, {
|
Modal.createTrackedDialog('Key Share', 'Process Next Request', KeyShareDialog, {
|
||||||
matrixClient: this._matrixClient,
|
matrixClient: this._matrixClient,
|
||||||
userId: userId,
|
userId: userId,
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
|
@ -240,7 +240,7 @@ function _handleRestoreFailure(e) {
|
|||||||
const SessionRestoreErrorDialog =
|
const SessionRestoreErrorDialog =
|
||||||
sdk.getComponent('views.dialogs.SessionRestoreErrorDialog');
|
sdk.getComponent('views.dialogs.SessionRestoreErrorDialog');
|
||||||
|
|
||||||
Modal.createDialog(SessionRestoreErrorDialog, {
|
Modal.createTrackedDialog('Session Restore Error', '', SessionRestoreErrorDialog, {
|
||||||
error: e.message,
|
error: e.message,
|
||||||
onFinished: (success) => {
|
onFinished: (success) => {
|
||||||
def.resolve(success);
|
def.resolve(success);
|
||||||
@ -318,7 +318,7 @@ async function _doSetLoggedIn(credentials, clearStorage) {
|
|||||||
await _clearStorage();
|
await _clearStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
Analytics.setGuest(credentials.guest);
|
Analytics.setLoggedIn(credentials.guest, credentials.homeserverUrl, credentials.identityServerUrl);
|
||||||
|
|
||||||
// Resolves by default
|
// Resolves by default
|
||||||
let teamPromise = Promise.resolve(null);
|
let teamPromise = Promise.resolve(null);
|
||||||
|
13
src/Modal.js
13
src/Modal.js
@ -103,13 +103,20 @@ class ModalManager {
|
|||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createTrackedDialog(analyticsAction, analyticsInfo, Element, props, className) {
|
||||||
|
Analytics.trackEvent('Modal', analyticsAction, analyticsInfo);
|
||||||
|
return this.createDialog(Element, props, className);
|
||||||
|
}
|
||||||
|
|
||||||
createDialog(Element, props, className) {
|
createDialog(Element, props, className) {
|
||||||
if (props && props.title) {
|
|
||||||
Analytics.trackEvent('Modal', props.title, 'createDialog');
|
|
||||||
}
|
|
||||||
return this.createDialogAsync((cb) => {cb(Element);}, props, className);
|
return this.createDialogAsync((cb) => {cb(Element);}, props, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createTrackedDialogAsync(analyticsId, loader, props, className) {
|
||||||
|
Analytics.trackEvent('Modal', analyticsId);
|
||||||
|
return this.createDialogAsync(loader, props, className);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a modal view.
|
* Open a modal view.
|
||||||
*
|
*
|
||||||
|
@ -142,7 +142,7 @@ const Notifier = {
|
|||||||
? _t('Riot does not have permission to send you notifications - please check your browser settings')
|
? _t('Riot does not have permission to send you notifications - please check your browser settings')
|
||||||
: _t('Riot was not given permission to send notifications - please try again');
|
: _t('Riot was not given permission to send notifications - please try again');
|
||||||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Unable to enable Notifications', result, ErrorDialog, {
|
||||||
title: _t('Unable to enable Notifications'),
|
title: _t('Unable to enable Notifications'),
|
||||||
description,
|
description,
|
||||||
});
|
});
|
||||||
|
@ -68,7 +68,7 @@ const commands = {
|
|||||||
ddg: new Command("ddg", "<query>", function(roomId, args) {
|
ddg: new Command("ddg", "<query>", function(roomId, args) {
|
||||||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
||||||
// TODO Don't explain this away, actually show a search UI here.
|
// TODO Don't explain this away, actually show a search UI here.
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Slash Commands', '/ddg is not a command', ErrorDialog, {
|
||||||
title: _t('/ddg is not a command'),
|
title: _t('/ddg is not a command'),
|
||||||
description: _t('To use it, just wait for autocomplete results to load and tab through them.'),
|
description: _t('To use it, just wait for autocomplete results to load and tab through them.'),
|
||||||
});
|
});
|
||||||
@ -326,13 +326,11 @@ const commands = {
|
|||||||
{deviceId: deviceId, fprint: fprint, userId: userId, fingerprint: fingerprint}));
|
{deviceId: deviceId, fprint: fprint, userId: userId, fingerprint: fingerprint}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return MatrixClientPeg.get().setDeviceVerified(
|
return MatrixClientPeg.get().setDeviceVerified(userId, deviceId, true);
|
||||||
userId, deviceId, true,
|
|
||||||
);
|
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// Tell the user we verified everything
|
// Tell the user we verified everything
|
||||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Slash Commands', 'Verified key', QuestionDialog, {
|
||||||
title: _t("Verified key"),
|
title: _t("Verified key"),
|
||||||
description: (
|
description: (
|
||||||
<div>
|
<div>
|
||||||
|
@ -24,7 +24,7 @@ const onAction = function(payload) {
|
|||||||
if (payload.action === 'unknown_device_error' && !isDialogOpen) {
|
if (payload.action === 'unknown_device_error' && !isDialogOpen) {
|
||||||
const UnknownDeviceDialog = sdk.getComponent('dialogs.UnknownDeviceDialog');
|
const UnknownDeviceDialog = sdk.getComponent('dialogs.UnknownDeviceDialog');
|
||||||
isDialogOpen = true;
|
isDialogOpen = true;
|
||||||
Modal.createDialog(UnknownDeviceDialog, {
|
Modal.createTrackedDialog('Unknown Device Error', '', UnknownDeviceDialog, {
|
||||||
devices: payload.err.devices,
|
devices: payload.err.devices,
|
||||||
room: payload.room,
|
room: payload.room,
|
||||||
onFinished: (r) => {
|
onFinished: (r) => {
|
||||||
|
@ -29,6 +29,9 @@ export default {
|
|||||||
name: "-",
|
name: "-",
|
||||||
id: 'matrix_apps',
|
id: 'matrix_apps',
|
||||||
default: false,
|
default: false,
|
||||||
|
|
||||||
|
// XXX: Always use default, ignore localStorage and remove from labs
|
||||||
|
override: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
@ -171,22 +174,36 @@ export default {
|
|||||||
localStorage.setItem('mx_local_settings', JSON.stringify(settings));
|
localStorage.setItem('mx_local_settings', JSON.stringify(settings));
|
||||||
},
|
},
|
||||||
|
|
||||||
isFeatureEnabled: function(feature: string): boolean {
|
getFeatureById(feature: string) {
|
||||||
|
for (let i = 0; i < this.LABS_FEATURES.length; i++) {
|
||||||
|
const f = this.LABS_FEATURES[i];
|
||||||
|
if (f.id === feature) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
isFeatureEnabled: function(featureId: string): boolean {
|
||||||
// Disable labs for guests.
|
// Disable labs for guests.
|
||||||
if (MatrixClientPeg.get().isGuest()) return false;
|
if (MatrixClientPeg.get().isGuest()) return false;
|
||||||
|
|
||||||
if (localStorage.getItem(`mx_labs_feature_${feature}`) === null) {
|
const feature = this.getFeatureById(featureId);
|
||||||
for (let i = 0; i < this.LABS_FEATURES.length; i++) {
|
if (!feature) {
|
||||||
const f = this.LABS_FEATURES[i];
|
console.warn(`Unknown feature "${featureId}"`);
|
||||||
if (f.id === feature) {
|
return false;
|
||||||
return f.default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return localStorage.getItem(`mx_labs_feature_${feature}`) === 'true';
|
// Return the default if this feature has an override to be the default value or
|
||||||
|
// if the feature has never been toggled and is therefore not in localStorage
|
||||||
|
if (Object.keys(feature).includes('override') ||
|
||||||
|
localStorage.getItem(`mx_labs_feature_${featureId}`) === null
|
||||||
|
) {
|
||||||
|
return feature.default;
|
||||||
|
}
|
||||||
|
return localStorage.getItem(`mx_labs_feature_${featureId}`) === 'true';
|
||||||
},
|
},
|
||||||
|
|
||||||
setFeatureEnabled: function(feature: string, enabled: boolean) {
|
setFeatureEnabled: function(featureId: string, enabled: boolean) {
|
||||||
localStorage.setItem(`mx_labs_feature_${feature}`, enabled);
|
localStorage.setItem(`mx_labs_feature_${featureId}`, enabled);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -266,7 +266,7 @@ export default React.createClass({
|
|||||||
this.setState({uploadingAvatar: false});
|
this.setState({uploadingAvatar: false});
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Failed to upload avatar image", e);
|
console.error("Failed to upload avatar image", e);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to upload image', '', ErrorDialog, {
|
||||||
title: _t('Error'),
|
title: _t('Error'),
|
||||||
description: _t('Failed to upload image'),
|
description: _t('Failed to upload image'),
|
||||||
});
|
});
|
||||||
@ -288,7 +288,7 @@ export default React.createClass({
|
|||||||
});
|
});
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Failed to save group profile", e);
|
console.error("Failed to save group profile", e);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to update group', '', ErrorDialog, {
|
||||||
title: _t('Error'),
|
title: _t('Error'),
|
||||||
description: _t('Failed to update group'),
|
description: _t('Failed to update group'),
|
||||||
});
|
});
|
||||||
|
@ -301,7 +301,7 @@ export default React.createClass({
|
|||||||
|
|
||||||
case PageTypes.UserView:
|
case PageTypes.UserView:
|
||||||
page_element = null; // deliberately null for now
|
page_element = null; // deliberately null for now
|
||||||
right_panel = <RightPanel userId={this.props.viewUserId} opacity={this.props.rightOpacity} />;
|
right_panel = <RightPanel opacity={this.props.rightOpacity} />;
|
||||||
break;
|
break;
|
||||||
case PageTypes.GroupView:
|
case PageTypes.GroupView:
|
||||||
page_element = <GroupView
|
page_element = <GroupView
|
||||||
|
@ -410,7 +410,7 @@ module.exports = React.createClass({
|
|||||||
this._leaveRoom(payload.room_id);
|
this._leaveRoom(payload.room_id);
|
||||||
break;
|
break;
|
||||||
case 'reject_invite':
|
case 'reject_invite':
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Reject invitation', '', QuestionDialog, {
|
||||||
title: _t('Reject invitation'),
|
title: _t('Reject invitation'),
|
||||||
description: _t('Are you sure you want to reject the invitation?'),
|
description: _t('Are you sure you want to reject the invitation?'),
|
||||||
onFinished: (confirm) => {
|
onFinished: (confirm) => {
|
||||||
@ -426,7 +426,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
modal.close();
|
modal.close();
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to reject invitation', '', ErrorDialog, {
|
||||||
title: _t('Failed to reject invitation'),
|
title: _t('Failed to reject invitation'),
|
||||||
description: err.toString(),
|
description: err.toString(),
|
||||||
});
|
});
|
||||||
@ -728,7 +728,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
_setMxId: function(payload) {
|
_setMxId: function(payload) {
|
||||||
const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog');
|
const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog');
|
||||||
const close = Modal.createDialog(SetMxIdDialog, {
|
const close = Modal.createTrackedDialog('Set MXID', '', SetMxIdDialog, {
|
||||||
homeserverUrl: MatrixClientPeg.get().getHomeserverUrl(),
|
homeserverUrl: MatrixClientPeg.get().getHomeserverUrl(),
|
||||||
onFinished: (submitted, credentials) => {
|
onFinished: (submitted, credentials) => {
|
||||||
if (!submitted) {
|
if (!submitted) {
|
||||||
@ -767,7 +767,7 @@ module.exports = React.createClass({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
||||||
Modal.createDialog(ChatInviteDialog, {
|
Modal.createTrackedDialog('Start a chat', '', ChatInviteDialog, {
|
||||||
title: _t('Start a chat'),
|
title: _t('Start a chat'),
|
||||||
description: _t("Who would you like to communicate with?"),
|
description: _t("Who would you like to communicate with?"),
|
||||||
placeholder: _t("Email, name or matrix ID"),
|
placeholder: _t("Email, name or matrix ID"),
|
||||||
@ -787,7 +787,7 @@ module.exports = React.createClass({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
||||||
Modal.createDialog(TextInputDialog, {
|
Modal.createTrackedDialog('Create Room', '', TextInputDialog, {
|
||||||
title: _t('Create Room'),
|
title: _t('Create Room'),
|
||||||
description: _t('Room name (optional)'),
|
description: _t('Room name (optional)'),
|
||||||
button: _t('Create Room'),
|
button: _t('Create Room'),
|
||||||
@ -831,7 +831,7 @@ module.exports = React.createClass({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const close = Modal.createDialog(ChatCreateOrReuseDialog, {
|
const close = Modal.createTrackedDialog('Chat create or reuse', '', ChatCreateOrReuseDialog, {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
onFinished: (success) => {
|
onFinished: (success) => {
|
||||||
if (!success && goHomeOnCancel) {
|
if (!success && goHomeOnCancel) {
|
||||||
@ -859,7 +859,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
_invite: function(roomId) {
|
_invite: function(roomId) {
|
||||||
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
||||||
Modal.createDialog(ChatInviteDialog, {
|
Modal.createTrackedDialog('Chat Invite', '', ChatInviteDialog, {
|
||||||
title: _t('Invite new room members'),
|
title: _t('Invite new room members'),
|
||||||
description: _t('Who would you like to add to this room?'),
|
description: _t('Who would you like to add to this room?'),
|
||||||
button: _t('Send Invites'),
|
button: _t('Send Invites'),
|
||||||
@ -873,7 +873,7 @@ module.exports = React.createClass({
|
|||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
|
||||||
const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
|
const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Leave room', '', QuestionDialog, {
|
||||||
title: _t("Leave room"),
|
title: _t("Leave room"),
|
||||||
description: (
|
description: (
|
||||||
<span>
|
<span>
|
||||||
@ -896,7 +896,7 @@ module.exports = React.createClass({
|
|||||||
}, (err) => {
|
}, (err) => {
|
||||||
modal.close();
|
modal.close();
|
||||||
console.error("Failed to leave room " + roomId + " " + err);
|
console.error("Failed to leave room " + roomId + " " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to leave room', '', ErrorDialog, {
|
||||||
title: _t("Failed to leave room"),
|
title: _t("Failed to leave room"),
|
||||||
description: (err && err.message ? err.message :
|
description: (err && err.message ? err.message :
|
||||||
_t("Server may be unavailable, overloaded, or you hit a bug.")),
|
_t("Server may be unavailable, overloaded, or you hit a bug.")),
|
||||||
@ -1090,7 +1090,7 @@ module.exports = React.createClass({
|
|||||||
});
|
});
|
||||||
cli.on('Session.logged_out', function(call) {
|
cli.on('Session.logged_out', function(call) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Signed out', '', ErrorDialog, {
|
||||||
title: _t('Signed Out'),
|
title: _t('Signed Out'),
|
||||||
description: _t('For security, this session has been signed out. Please sign in again.'),
|
description: _t('For security, this session has been signed out. Please sign in again.'),
|
||||||
});
|
});
|
||||||
@ -1203,21 +1203,24 @@ module.exports = React.createClass({
|
|||||||
} else if (screen.indexOf('user/') == 0) {
|
} else if (screen.indexOf('user/') == 0) {
|
||||||
const userId = screen.substring(5);
|
const userId = screen.substring(5);
|
||||||
|
|
||||||
if (params.action === 'chat') {
|
// Wait for the first sync so that `getRoom` gives us a room object if it's
|
||||||
this._chatCreateOrReuse(userId);
|
// in the sync response
|
||||||
return;
|
const waitFor = this.firstSyncPromise ?
|
||||||
}
|
this.firstSyncPromise.promise : Promise.resolve();
|
||||||
|
waitFor.then(() => {
|
||||||
|
if (params.action === 'chat') {
|
||||||
|
this._chatCreateOrReuse(userId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({ viewUserId: userId });
|
this._setPage(PageTypes.UserView);
|
||||||
this._setPage(PageTypes.UserView);
|
this.notifyNewScreen('user/' + userId);
|
||||||
this.notifyNewScreen('user/' + userId);
|
const member = new Matrix.RoomMember(null, userId);
|
||||||
const member = new Matrix.RoomMember(null, userId);
|
|
||||||
if (member) {
|
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_user',
|
action: 'view_user',
|
||||||
member: member,
|
member: member,
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
} else if (screen.indexOf('group/') == 0) {
|
} else if (screen.indexOf('group/') == 0) {
|
||||||
const groupId = screen.substring(6);
|
const groupId = screen.substring(6);
|
||||||
|
|
||||||
|
@ -307,13 +307,13 @@ module.exports = React.createClass({
|
|||||||
for (i = 0; i < this.props.events.length; i++) {
|
for (i = 0; i < this.props.events.length; i++) {
|
||||||
let mxEv = this.props.events[i];
|
let mxEv = this.props.events[i];
|
||||||
let eventId = mxEv.getId();
|
let eventId = mxEv.getId();
|
||||||
let readMarkerInMels = false;
|
|
||||||
let last = (mxEv === lastShownEvent);
|
let last = (mxEv === lastShownEvent);
|
||||||
|
|
||||||
const wantTile = this._shouldShowEvent(mxEv);
|
const wantTile = this._shouldShowEvent(mxEv);
|
||||||
|
|
||||||
// Wrap consecutive member events in a ListSummary, ignore if redacted
|
// Wrap consecutive member events in a ListSummary, ignore if redacted
|
||||||
if (isMembershipChange(mxEv) && wantTile) {
|
if (isMembershipChange(mxEv) && wantTile) {
|
||||||
|
let readMarkerInMels = false;
|
||||||
let ts1 = mxEv.getTs();
|
let ts1 = mxEv.getTs();
|
||||||
// Ensure that the key of the MemberEventListSummary does not change with new
|
// Ensure that the key of the MemberEventListSummary does not change with new
|
||||||
// member events. This will prevent it from being re-created unnecessarily, and
|
// member events. This will prevent it from being re-created unnecessarily, and
|
||||||
@ -330,6 +330,11 @@ module.exports = React.createClass({
|
|||||||
ret.push(dateSeparator);
|
ret.push(dateSeparator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If RM event is the first in the MELS, append the RM after MELS
|
||||||
|
if (mxEv.getId() === this.props.readMarkerEventId) {
|
||||||
|
readMarkerInMels = true;
|
||||||
|
}
|
||||||
|
|
||||||
let summarisedEvents = [mxEv];
|
let summarisedEvents = [mxEv];
|
||||||
for (;i + 1 < this.props.events.length; i++) {
|
for (;i + 1 < this.props.events.length; i++) {
|
||||||
const collapsedMxEv = this.props.events[i + 1];
|
const collapsedMxEv = this.props.events[i + 1];
|
||||||
|
@ -63,7 +63,7 @@ export default withMatrixClient(React.createClass({
|
|||||||
|
|
||||||
_onCreateGroupClick: function() {
|
_onCreateGroupClick: function() {
|
||||||
const CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog");
|
const CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog");
|
||||||
Modal.createDialog(CreateGroupDialog);
|
Modal.createTrackedDialog('Create Group', '', CreateGroupDialog);
|
||||||
},
|
},
|
||||||
|
|
||||||
_fetch: function() {
|
_fetch: function() {
|
||||||
|
@ -544,7 +544,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
if (!userHasUsedEncryption) {
|
if (!userHasUsedEncryption) {
|
||||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('E2E Warning', '', QuestionDialog, {
|
||||||
title: _t("Warning!"),
|
title: _t("Warning!"),
|
||||||
hasCancelButton: false,
|
hasCancelButton: false,
|
||||||
description: (
|
description: (
|
||||||
@ -820,7 +820,7 @@ module.exports = React.createClass({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog');
|
const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog');
|
||||||
const close = Modal.createDialog(SetMxIdDialog, {
|
const close = Modal.createTrackedDialog('Set MXID', '', SetMxIdDialog, {
|
||||||
homeserverUrl: cli.getHomeserverUrl(),
|
homeserverUrl: cli.getHomeserverUrl(),
|
||||||
onFinished: (submitted, credentials) => {
|
onFinished: (submitted, credentials) => {
|
||||||
if (submitted) {
|
if (submitted) {
|
||||||
@ -934,7 +934,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Failed to upload file " + file + " " + error);
|
console.error("Failed to upload file " + file + " " + error);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to upload file', '', ErrorDialog, {
|
||||||
title: _t('Failed to upload file'),
|
title: _t('Failed to upload file'),
|
||||||
description: ((error && error.message) ? error.message : _t("Server may be unavailable, overloaded, or the file too big")),
|
description: ((error && error.message) ? error.message : _t("Server may be unavailable, overloaded, or the file too big")),
|
||||||
});
|
});
|
||||||
@ -1021,7 +1021,7 @@ module.exports = React.createClass({
|
|||||||
}, function(error) {
|
}, function(error) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Search failed: " + error);
|
console.error("Search failed: " + error);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Search failed', '', ErrorDialog, {
|
||||||
title: _t("Search failed"),
|
title: _t("Search failed"),
|
||||||
description: ((error && error.message) ? error.message : _t("Server may be unavailable, overloaded, or search timed out :(")),
|
description: ((error && error.message) ? error.message : _t("Server may be unavailable, overloaded, or search timed out :(")),
|
||||||
});
|
});
|
||||||
@ -1148,7 +1148,7 @@ module.exports = React.createClass({
|
|||||||
console.error(result.reason);
|
console.error(result.reason);
|
||||||
});
|
});
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to save room settings', '', ErrorDialog, {
|
||||||
title: _t("Failed to save settings"),
|
title: _t("Failed to save settings"),
|
||||||
description: fails.map(function(result) { return result.reason; }).join("\n"),
|
description: fails.map(function(result) { return result.reason; }).join("\n"),
|
||||||
});
|
});
|
||||||
@ -1195,7 +1195,7 @@ module.exports = React.createClass({
|
|||||||
}, function(err) {
|
}, function(err) {
|
||||||
var errCode = err.errcode || _t("unknown error code");
|
var errCode = err.errcode || _t("unknown error code");
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to forget room', '', ErrorDialog, {
|
||||||
title: _t("Error"),
|
title: _t("Error"),
|
||||||
description: _t("Failed to forget room %(errCode)s", { errCode: errCode }),
|
description: _t("Failed to forget room %(errCode)s", { errCode: errCode }),
|
||||||
});
|
});
|
||||||
@ -1217,7 +1217,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
var msg = error.message ? error.message : JSON.stringify(error);
|
var msg = error.message ? error.message : JSON.stringify(error);
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
|
||||||
title: _t("Failed to reject invite"),
|
title: _t("Failed to reject invite"),
|
||||||
description: msg,
|
description: msg,
|
||||||
});
|
});
|
||||||
|
@ -923,7 +923,7 @@ var TimelinePanel = React.createClass({
|
|||||||
var message = (error.errcode == 'M_FORBIDDEN')
|
var message = (error.errcode == 'M_FORBIDDEN')
|
||||||
? _t("Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.")
|
? _t("Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.")
|
||||||
: _t("Tried to load a specific point in this room's timeline, but was unable to find it.");
|
: _t("Tried to load a specific point in this room's timeline, but was unable to find it.");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to load timeline position', '', ErrorDialog, {
|
||||||
title: _t("Failed to load timeline position"),
|
title: _t("Failed to load timeline position"),
|
||||||
description: message,
|
description: message,
|
||||||
onFinished: onFinished,
|
onFinished: onFinished,
|
||||||
|
@ -85,6 +85,10 @@ const SETTINGS_LABELS = [
|
|||||||
id: 'hideJoinLeaves',
|
id: 'hideJoinLeaves',
|
||||||
label: 'Hide join/leave messages (invites/kicks/bans unaffected)',
|
label: 'Hide join/leave messages (invites/kicks/bans unaffected)',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'hideAvatarDisplaynameChanges',
|
||||||
|
label: 'Hide avatar and display name changes',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'useCompactLayout',
|
id: 'useCompactLayout',
|
||||||
label: 'Use compact timeline layout',
|
label: 'Use compact timeline layout',
|
||||||
@ -335,7 +339,7 @@ module.exports = React.createClass({
|
|||||||
}, function(error) {
|
}, function(error) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Failed to load user settings: " + error);
|
console.error("Failed to load user settings: " + error);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Can\'t load user settings', '', ErrorDialog, {
|
||||||
title: _t("Can't load user settings"),
|
title: _t("Can't load user settings"),
|
||||||
description: ((error && error.message) ? error.message : _t("Server may be unavailable or overloaded")),
|
description: ((error && error.message) ? error.message : _t("Server may be unavailable or overloaded")),
|
||||||
});
|
});
|
||||||
@ -368,7 +372,7 @@ module.exports = React.createClass({
|
|||||||
// const errMsg = (typeof err === "string") ? err : (err.error || "");
|
// const errMsg = (typeof err === "string") ? err : (err.error || "");
|
||||||
console.error("Failed to set avatar: " + err);
|
console.error("Failed to set avatar: " + err);
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to set avatar', '', ErrorDialog, {
|
||||||
title: _t("Failed to set avatar."),
|
title: _t("Failed to set avatar."),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
@ -377,7 +381,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
onLogoutClicked: function(ev) {
|
onLogoutClicked: function(ev) {
|
||||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Logout E2E Export', '', QuestionDialog, {
|
||||||
title: _t("Sign out"),
|
title: _t("Sign out"),
|
||||||
description:
|
description:
|
||||||
<div>
|
<div>
|
||||||
@ -413,7 +417,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Failed to change password: " + errMsg);
|
console.error("Failed to change password: " + errMsg);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to change password', '', ErrorDialog, {
|
||||||
title: _t("Error"),
|
title: _t("Error"),
|
||||||
description: errMsg,
|
description: errMsg,
|
||||||
});
|
});
|
||||||
@ -421,7 +425,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
onPasswordChanged: function() {
|
onPasswordChanged: function() {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Password changed', '', ErrorDialog, {
|
||||||
title: _t("Success"),
|
title: _t("Success"),
|
||||||
description: _t(
|
description: _t(
|
||||||
"Your password was successfully changed. You will not receive " +
|
"Your password was successfully changed. You will not receive " +
|
||||||
@ -446,7 +450,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
const emailAddress = this.refs.add_email_input.value;
|
const emailAddress = this.refs.add_email_input.value;
|
||||||
if (!Email.looksValid(emailAddress)) {
|
if (!Email.looksValid(emailAddress)) {
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Invalid email address', '', ErrorDialog, {
|
||||||
title: _t("Invalid Email Address"),
|
title: _t("Invalid Email Address"),
|
||||||
description: _t("This doesn't appear to be a valid email address"),
|
description: _t("This doesn't appear to be a valid email address"),
|
||||||
});
|
});
|
||||||
@ -456,7 +460,7 @@ module.exports = React.createClass({
|
|||||||
// we always bind emails when registering, so let's do the
|
// we always bind emails when registering, so let's do the
|
||||||
// same here.
|
// same here.
|
||||||
this._addThreepid.addEmailAddress(emailAddress, true).done(() => {
|
this._addThreepid.addEmailAddress(emailAddress, true).done(() => {
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Verification Pending', '', QuestionDialog, {
|
||||||
title: _t("Verification Pending"),
|
title: _t("Verification Pending"),
|
||||||
description: _t(
|
description: _t(
|
||||||
"Please check your email and click on the link it contains. Once this " +
|
"Please check your email and click on the link it contains. Once this " +
|
||||||
@ -468,7 +472,7 @@ module.exports = React.createClass({
|
|||||||
}, (err) => {
|
}, (err) => {
|
||||||
this.setState({email_add_pending: false});
|
this.setState({email_add_pending: false});
|
||||||
console.error("Unable to add email address " + emailAddress + " " + err);
|
console.error("Unable to add email address " + emailAddress + " " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Unable to add email address', '', ErrorDialog, {
|
||||||
title: _t("Unable to add email address"),
|
title: _t("Unable to add email address"),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
@ -479,7 +483,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
onRemoveThreepidClicked: function(threepid) {
|
onRemoveThreepidClicked: function(threepid) {
|
||||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Remove 3pid', '', QuestionDialog, {
|
||||||
title: _t("Remove Contact Information?"),
|
title: _t("Remove Contact Information?"),
|
||||||
description: _t("Remove %(threePid)s?", { threePid: threepid.address }),
|
description: _t("Remove %(threePid)s?", { threePid: threepid.address }),
|
||||||
button: _t('Remove'),
|
button: _t('Remove'),
|
||||||
@ -493,7 +497,7 @@ module.exports = React.createClass({
|
|||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Unable to remove contact information: " + err);
|
console.error("Unable to remove contact information: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Remove 3pid failed', '', ErrorDialog, {
|
||||||
title: _t("Unable to remove contact information"),
|
title: _t("Unable to remove contact information"),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
@ -525,7 +529,7 @@ module.exports = React.createClass({
|
|||||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
const message = _t("Unable to verify email address.") + " " +
|
const message = _t("Unable to verify email address.") + " " +
|
||||||
_t("Please check your email and click on the link it contains. Once this is done, click continue.");
|
_t("Please check your email and click on the link it contains. Once this is done, click continue.");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Verification Pending', '', QuestionDialog, {
|
||||||
title: _t("Verification Pending"),
|
title: _t("Verification Pending"),
|
||||||
description: message,
|
description: message,
|
||||||
button: _t('Continue'),
|
button: _t('Continue'),
|
||||||
@ -534,7 +538,7 @@ module.exports = React.createClass({
|
|||||||
} else {
|
} else {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Unable to verify email address: " + err);
|
console.error("Unable to verify email address: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Unable to verify email address', '', ErrorDialog, {
|
||||||
title: _t("Unable to verify email address."),
|
title: _t("Unable to verify email address."),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
@ -544,7 +548,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
_onDeactivateAccountClicked: function() {
|
_onDeactivateAccountClicked: function() {
|
||||||
const DeactivateAccountDialog = sdk.getComponent("dialogs.DeactivateAccountDialog");
|
const DeactivateAccountDialog = sdk.getComponent("dialogs.DeactivateAccountDialog");
|
||||||
Modal.createDialog(DeactivateAccountDialog, {});
|
Modal.createTrackedDialog('Deactivate Account', '', DeactivateAccountDialog, {});
|
||||||
},
|
},
|
||||||
|
|
||||||
_onBugReportClicked: function() {
|
_onBugReportClicked: function() {
|
||||||
@ -552,7 +556,7 @@ module.exports = React.createClass({
|
|||||||
if (!BugReportDialog) {
|
if (!BugReportDialog) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Modal.createDialog(BugReportDialog, {});
|
Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
|
||||||
},
|
},
|
||||||
|
|
||||||
_onClearCacheClicked: function() {
|
_onClearCacheClicked: function() {
|
||||||
@ -589,27 +593,23 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onExportE2eKeysClicked: function() {
|
_onExportE2eKeysClicked: function() {
|
||||||
Modal.createDialogAsync(
|
Modal.createTrackedDialogAsync('Export E2E Keys', '', (cb) => {
|
||||||
(cb) => {
|
require.ensure(['../../async-components/views/dialogs/ExportE2eKeysDialog'], () => {
|
||||||
require.ensure(['../../async-components/views/dialogs/ExportE2eKeysDialog'], () => {
|
cb(require('../../async-components/views/dialogs/ExportE2eKeysDialog'));
|
||||||
cb(require('../../async-components/views/dialogs/ExportE2eKeysDialog'));
|
}, "e2e-export");
|
||||||
}, "e2e-export");
|
}, {
|
||||||
}, {
|
matrixClient: MatrixClientPeg.get(),
|
||||||
matrixClient: MatrixClientPeg.get(),
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onImportE2eKeysClicked: function() {
|
_onImportE2eKeysClicked: function() {
|
||||||
Modal.createDialogAsync(
|
Modal.createTrackedDialogAsync('Import E2E Keys', '', (cb) => {
|
||||||
(cb) => {
|
require.ensure(['../../async-components/views/dialogs/ImportE2eKeysDialog'], () => {
|
||||||
require.ensure(['../../async-components/views/dialogs/ImportE2eKeysDialog'], () => {
|
cb(require('../../async-components/views/dialogs/ImportE2eKeysDialog'));
|
||||||
cb(require('../../async-components/views/dialogs/ImportE2eKeysDialog'));
|
}, "e2e-export");
|
||||||
}, "e2e-export");
|
}, {
|
||||||
}, {
|
matrixClient: MatrixClientPeg.get(),
|
||||||
matrixClient: MatrixClientPeg.get(),
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_renderReferral: function() {
|
_renderReferral: function() {
|
||||||
@ -859,7 +859,13 @@ module.exports = React.createClass({
|
|||||||
if (this.props.enableLabs === false) return null;
|
if (this.props.enableLabs === false) return null;
|
||||||
UserSettingsStore.doTranslations();
|
UserSettingsStore.doTranslations();
|
||||||
|
|
||||||
const features = UserSettingsStore.LABS_FEATURES.map((feature) => {
|
const features = [];
|
||||||
|
UserSettingsStore.LABS_FEATURES.forEach((feature) => {
|
||||||
|
// This feature has an override and will be set to the default, so do not
|
||||||
|
// show it here.
|
||||||
|
if (feature.override) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// TODO: this ought to be a separate component so that we don't need
|
// TODO: this ought to be a separate component so that we don't need
|
||||||
// to rebind the onChange each time we render
|
// to rebind the onChange each time we render
|
||||||
const onChange = (e) => {
|
const onChange = (e) => {
|
||||||
@ -867,7 +873,7 @@ module.exports = React.createClass({
|
|||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
features.push(
|
||||||
<div key={feature.id} className="mx_UserSettings_toggle">
|
<div key={feature.id} className="mx_UserSettings_toggle">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@ -877,9 +883,14 @@ module.exports = React.createClass({
|
|||||||
onChange={ onChange }
|
onChange={ onChange }
|
||||||
/>
|
/>
|
||||||
<label htmlFor={feature.id}>{feature.name}</label>
|
<label htmlFor={feature.id}>{feature.name}</label>
|
||||||
</div>
|
</div>);
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// No labs section when there are no features in labs
|
||||||
|
if (features.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h3>{ _t("Labs") }</h3>
|
<h3>{ _t("Labs") }</h3>
|
||||||
@ -1008,7 +1019,7 @@ module.exports = React.createClass({
|
|||||||
this._refreshMediaDevices,
|
this._refreshMediaDevices,
|
||||||
function() {
|
function() {
|
||||||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('No media permissions', '', ErrorDialog, {
|
||||||
title: _t('No media permissions'),
|
title: _t('No media permissions'),
|
||||||
description: _t('You may need to manually permit Riot to access your microphone/webcam'),
|
description: _t('You may need to manually permit Riot to access your microphone/webcam'),
|
||||||
});
|
});
|
||||||
|
@ -89,7 +89,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Forgot Password Warning', '', QuestionDialog, {
|
||||||
title: _t('Warning!'),
|
title: _t('Warning!'),
|
||||||
description:
|
description:
|
||||||
<div>
|
<div>
|
||||||
@ -121,15 +121,13 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onExportE2eKeysClicked: function() {
|
_onExportE2eKeysClicked: function() {
|
||||||
Modal.createDialogAsync(
|
Modal.createTrackedDialogAsync('Export E2E Keys', 'Forgot Password', (cb) => {
|
||||||
(cb) => {
|
require.ensure(['../../../async-components/views/dialogs/ExportE2eKeysDialog'], () => {
|
||||||
require.ensure(['../../../async-components/views/dialogs/ExportE2eKeysDialog'], () => {
|
cb(require('../../../async-components/views/dialogs/ExportE2eKeysDialog'));
|
||||||
cb(require('../../../async-components/views/dialogs/ExportE2eKeysDialog'));
|
}, "e2e-export");
|
||||||
}, "e2e-export");
|
}, {
|
||||||
}, {
|
matrixClient: MatrixClientPeg.get(),
|
||||||
matrixClient: MatrixClientPeg.get(),
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onInputChanged: function(stateKey, ev) {
|
onInputChanged: function(stateKey, ev) {
|
||||||
@ -152,7 +150,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
showErrorDialog: function(body, title) {
|
showErrorDialog: function(body, title) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Forgot Password Error', '', ErrorDialog, {
|
||||||
title: title,
|
title: title,
|
||||||
description: body,
|
description: body,
|
||||||
});
|
});
|
||||||
|
@ -19,8 +19,11 @@ limitations under the License.
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { _t, _tJsx } from '../../../languageHandler';
|
import { _t, _tJsx } from '../../../languageHandler';
|
||||||
|
import * as languageHandler from '../../../languageHandler';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import Login from '../../../Login';
|
import Login from '../../../Login';
|
||||||
|
import UserSettingsStore from '../../../UserSettingsStore';
|
||||||
|
import PlatformPeg from '../../../PlatformPeg';
|
||||||
|
|
||||||
// For validating phone numbers without country codes
|
// For validating phone numbers without country codes
|
||||||
const PHONE_NUMBER_REGEX = /^[0-9\(\)\-\s]*$/;
|
const PHONE_NUMBER_REGEX = /^[0-9\(\)\-\s]*$/;
|
||||||
@ -306,6 +309,23 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onLanguageChange: function(newLang) {
|
||||||
|
if(languageHandler.getCurrentLanguage() !== newLang) {
|
||||||
|
UserSettingsStore.setLocalSetting('language', newLang);
|
||||||
|
PlatformPeg.get().reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderLanguageSetting: function() {
|
||||||
|
const LanguageDropdown = sdk.getComponent('views.elements.LanguageDropdown');
|
||||||
|
return <div className="mx_Login_language_div">
|
||||||
|
<LanguageDropdown onOptionChange={this._onLanguageChange}
|
||||||
|
className="mx_Login_language"
|
||||||
|
value={languageHandler.getCurrentLanguage()}
|
||||||
|
/>
|
||||||
|
</div>;
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
const Loader = sdk.getComponent("elements.Spinner");
|
const Loader = sdk.getComponent("elements.Spinner");
|
||||||
const LoginHeader = sdk.getComponent("login.LoginHeader");
|
const LoginHeader = sdk.getComponent("login.LoginHeader");
|
||||||
@ -354,6 +374,7 @@ module.exports = React.createClass({
|
|||||||
</a>
|
</a>
|
||||||
{ loginAsGuestJsx }
|
{ loginAsGuestJsx }
|
||||||
{ returnToAppJsx }
|
{ returnToAppJsx }
|
||||||
|
{ this._renderLanguageSetting() }
|
||||||
<LoginFooter />
|
<LoginFooter />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -103,7 +103,7 @@ module.exports = React.createClass({
|
|||||||
const ChatCreateOrReuseDialog = sdk.getComponent(
|
const ChatCreateOrReuseDialog = sdk.getComponent(
|
||||||
"views.dialogs.ChatCreateOrReuseDialog",
|
"views.dialogs.ChatCreateOrReuseDialog",
|
||||||
);
|
);
|
||||||
const close = Modal.createDialog(ChatCreateOrReuseDialog, {
|
const close = Modal.createTrackedDialog('Create or Reuse', '', ChatCreateOrReuseDialog, {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
onFinished: (success) => {
|
onFinished: (success) => {
|
||||||
this.props.onFinished(success);
|
this.props.onFinished(success);
|
||||||
@ -367,7 +367,7 @@ module.exports = React.createClass({
|
|||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
|
||||||
title: _t("Failed to invite"),
|
title: _t("Failed to invite"),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
@ -380,7 +380,7 @@ module.exports = React.createClass({
|
|||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to invite user', '', ErrorDialog, {
|
||||||
title: _t("Failed to invite user"),
|
title: _t("Failed to invite user"),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
@ -401,7 +401,7 @@ module.exports = React.createClass({
|
|||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
|
||||||
title: _t("Failed to invite"),
|
title: _t("Failed to invite"),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
@ -448,7 +448,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
if (errorList.length > 0) {
|
if (errorList.length > 0) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to invite the following users to the room', '', ErrorDialog, {
|
||||||
title: _t("Failed to invite the following users to the %(roomName)s room:", {roomName: room.name}),
|
title: _t("Failed to invite the following users to the %(roomName)s room:", {roomName: room.name}),
|
||||||
description: errorList.join(", "),
|
description: errorList.join(", "),
|
||||||
});
|
});
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
|
import Analytics from '../../../Analytics';
|
||||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||||
import * as Lifecycle from '../../../Lifecycle';
|
import * as Lifecycle from '../../../Lifecycle';
|
||||||
import Velocity from 'velocity-vector';
|
import Velocity from 'velocity-vector';
|
||||||
@ -54,6 +55,7 @@ export default class DeactivateAccountDialog extends React.Component {
|
|||||||
user: MatrixClientPeg.get().credentials.userId,
|
user: MatrixClientPeg.get().credentials.userId,
|
||||||
password: this._passwordField.value,
|
password: this._passwordField.value,
|
||||||
}).done(() => {
|
}).done(() => {
|
||||||
|
Analytics.trackEvent('Account', 'Deactivate Account');
|
||||||
Lifecycle.onLoggedOut();
|
Lifecycle.onLoggedOut();
|
||||||
this.props.onFinished(false);
|
this.props.onFinished(false);
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Usage:
|
* Usage:
|
||||||
* Modal.createDialog(ErrorDialog, {
|
* Modal.createTrackedDialog('An Identifier', 'some detail', ErrorDialog, {
|
||||||
* title: "some text", (default: "Error")
|
* title: "some text", (default: "Error")
|
||||||
* description: "some more text",
|
* description: "some more text",
|
||||||
* button: "Button Text",
|
* button: "Button Text",
|
||||||
|
@ -88,7 +88,7 @@ export default React.createClass({
|
|||||||
const DeviceVerifyDialog = sdk.getComponent('views.dialogs.DeviceVerifyDialog');
|
const DeviceVerifyDialog = sdk.getComponent('views.dialogs.DeviceVerifyDialog');
|
||||||
|
|
||||||
console.log("KeyShareDialog: Starting verify dialog");
|
console.log("KeyShareDialog: Starting verify dialog");
|
||||||
Modal.createDialog(DeviceVerifyDialog, {
|
Modal.createTrackedDialog('Key Share', 'Starting dialog', DeviceVerifyDialog, {
|
||||||
userId: this.props.userId,
|
userId: this.props.userId,
|
||||||
device: this.state.deviceInfo,
|
device: this.state.deviceInfo,
|
||||||
onFinished: (verified) => {
|
onFinished: (verified) => {
|
||||||
|
@ -31,7 +31,7 @@ export default React.createClass({
|
|||||||
|
|
||||||
_sendBugReport: function() {
|
_sendBugReport: function() {
|
||||||
const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
|
const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
|
||||||
Modal.createDialog(BugReportDialog, {});
|
Modal.createTrackedDialog('Session Restore Error', 'Send Bug Report Dialog', BugReportDialog, {});
|
||||||
},
|
},
|
||||||
|
|
||||||
_continueClicked: function() {
|
_continueClicked: function() {
|
||||||
|
@ -55,7 +55,7 @@ export default React.createClass({
|
|||||||
|
|
||||||
const emailAddress = this.state.emailAddress;
|
const emailAddress = this.state.emailAddress;
|
||||||
if (!Email.looksValid(emailAddress)) {
|
if (!Email.looksValid(emailAddress)) {
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Invalid Email Address', '', ErrorDialog, {
|
||||||
title: _t("Invalid Email Address"),
|
title: _t("Invalid Email Address"),
|
||||||
description: _t("This doesn't appear to be a valid email address"),
|
description: _t("This doesn't appear to be a valid email address"),
|
||||||
});
|
});
|
||||||
@ -65,7 +65,7 @@ export default React.createClass({
|
|||||||
// we always bind emails when registering, so let's do the
|
// we always bind emails when registering, so let's do the
|
||||||
// same here.
|
// same here.
|
||||||
this._addThreepid.addEmailAddress(emailAddress, true).done(() => {
|
this._addThreepid.addEmailAddress(emailAddress, true).done(() => {
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Verification Pending', '', QuestionDialog, {
|
||||||
title: _t("Verification Pending"),
|
title: _t("Verification Pending"),
|
||||||
description: _t(
|
description: _t(
|
||||||
"Please check your email and click on the link it contains. Once this " +
|
"Please check your email and click on the link it contains. Once this " +
|
||||||
@ -77,7 +77,7 @@ export default React.createClass({
|
|||||||
}, (err) => {
|
}, (err) => {
|
||||||
this.setState({emailBusy: false});
|
this.setState({emailBusy: false});
|
||||||
console.error("Unable to add email address " + emailAddress + " " + err);
|
console.error("Unable to add email address " + emailAddress + " " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Unable to add email address', '', ErrorDialog, {
|
||||||
title: _t("Unable to add email address"),
|
title: _t("Unable to add email address"),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
@ -106,7 +106,7 @@ export default React.createClass({
|
|||||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
const message = _t("Unable to verify email address.") + " " +
|
const message = _t("Unable to verify email address.") + " " +
|
||||||
_t("Please check your email and click on the link it contains. Once this is done, click continue.");
|
_t("Please check your email and click on the link it contains. Once this is done, click continue.");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Verification Pending', '3pid Auth Failed', QuestionDialog, {
|
||||||
title: _t("Verification Pending"),
|
title: _t("Verification Pending"),
|
||||||
description: message,
|
description: message,
|
||||||
button: _t('Continue'),
|
button: _t('Continue'),
|
||||||
@ -115,7 +115,7 @@ export default React.createClass({
|
|||||||
} else {
|
} else {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Unable to verify email address: " + err);
|
console.error("Unable to verify email address: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Unable to verify email address', '', ErrorDialog, {
|
||||||
title: _t("Unable to verify email address."),
|
title: _t("Unable to verify email address."),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
|
@ -106,6 +106,16 @@ export default React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_doUsernameCheck: function() {
|
_doUsernameCheck: function() {
|
||||||
|
// XXX: SPEC-1
|
||||||
|
// Check if username is valid
|
||||||
|
// Naive impl copied from https://github.com/matrix-org/matrix-react-sdk/blob/66c3a6d9ca695780eb6b662e242e88323053ff33/src/components/views/login/RegistrationForm.js#L190
|
||||||
|
if (encodeURIComponent(this.state.username) !== this.state.username) {
|
||||||
|
this.setState({
|
||||||
|
usernameError: _t('User names may only contain letters, numbers, dots, hyphens and underscores.'),
|
||||||
|
});
|
||||||
|
return Promise.reject();
|
||||||
|
}
|
||||||
|
|
||||||
// Check if username is available
|
// Check if username is available
|
||||||
return this._matrixClient.isUsernameAvailable(this.state.username).then(
|
return this._matrixClient.isUsernameAvailable(this.state.username).then(
|
||||||
(isAvailable) => {
|
(isAvailable) => {
|
||||||
@ -242,7 +252,7 @@ export default React.createClass({
|
|||||||
return (
|
return (
|
||||||
<BaseDialog className="mx_SetMxIdDialog"
|
<BaseDialog className="mx_SetMxIdDialog"
|
||||||
onFinished={this.props.onFinished}
|
onFinished={this.props.onFinished}
|
||||||
title="To get started, please pick a username!"
|
title={_t('To get started, please pick a username!')}
|
||||||
>
|
>
|
||||||
<div className="mx_Dialog_content">
|
<div className="mx_Dialog_content">
|
||||||
<div className="mx_SetMxIdDialog_input_group">
|
<div className="mx_SetMxIdDialog_input_group">
|
||||||
|
@ -123,7 +123,7 @@ export default React.createClass({
|
|||||||
console.log("Edit widget ID ", this.props.id);
|
console.log("Edit widget ID ", this.props.id);
|
||||||
const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
|
const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
|
||||||
const src = this._scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId, 'type_' + this.props.type);
|
const src = this._scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId, 'type_' + this.props.type);
|
||||||
Modal.createDialog(IntegrationsManager, {
|
Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, {
|
||||||
src: src,
|
src: src,
|
||||||
}, "mx_IntegrationsManager");
|
}, "mx_IntegrationsManager");
|
||||||
},
|
},
|
||||||
|
@ -52,7 +52,7 @@ export default React.createClass({
|
|||||||
|
|
||||||
onVerifyClick: function() {
|
onVerifyClick: function() {
|
||||||
const DeviceVerifyDialog = sdk.getComponent('views.dialogs.DeviceVerifyDialog');
|
const DeviceVerifyDialog = sdk.getComponent('views.dialogs.DeviceVerifyDialog');
|
||||||
Modal.createDialog(DeviceVerifyDialog, {
|
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
|
||||||
userId: this.props.userId,
|
userId: this.props.userId,
|
||||||
device: this.state.device,
|
device: this.state.device,
|
||||||
});
|
});
|
||||||
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
|
import dis from '../../../dispatcher';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Room, RoomMember } from 'matrix-js-sdk';
|
import { Room, RoomMember } from 'matrix-js-sdk';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
@ -140,6 +141,12 @@ const Pill = React.createClass({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onUserPillClicked: function() {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'view_user',
|
||||||
|
member: this.state.member,
|
||||||
|
});
|
||||||
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||||
const RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
|
const RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
|
||||||
@ -150,6 +157,8 @@ const Pill = React.createClass({
|
|||||||
let linkText = resource;
|
let linkText = resource;
|
||||||
let pillClass;
|
let pillClass;
|
||||||
let userId;
|
let userId;
|
||||||
|
let href = this.props.url;
|
||||||
|
let onClick;
|
||||||
switch (this.state.pillType) {
|
switch (this.state.pillType) {
|
||||||
case Pill.TYPE_USER_MENTION: {
|
case Pill.TYPE_USER_MENTION: {
|
||||||
// If this user is not a member of this room, default to the empty member
|
// If this user is not a member of this room, default to the empty member
|
||||||
@ -161,6 +170,8 @@ const Pill = React.createClass({
|
|||||||
avatar = <MemberAvatar member={member} width={16} height={16}/>;
|
avatar = <MemberAvatar member={member} width={16} height={16}/>;
|
||||||
}
|
}
|
||||||
pillClass = 'mx_UserPill';
|
pillClass = 'mx_UserPill';
|
||||||
|
href = null;
|
||||||
|
onClick = this.onUserPillClicked.bind(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -183,7 +194,7 @@ const Pill = React.createClass({
|
|||||||
|
|
||||||
if (this.state.pillType) {
|
if (this.state.pillType) {
|
||||||
return this.props.inMessage ?
|
return this.props.inMessage ?
|
||||||
<a className={classes} href={this.props.url} title={resource} data-offset-key={this.props.offsetKey}>
|
<a className={classes} href={href} onClick={onClick} title={resource} data-offset-key={this.props.offsetKey}>
|
||||||
{avatar}
|
{avatar}
|
||||||
{linkText}
|
{linkText}
|
||||||
</a> :
|
</a> :
|
||||||
|
@ -95,7 +95,7 @@ module.exports = React.createClass({
|
|||||||
if (this.allFieldsValid()) {
|
if (this.allFieldsValid()) {
|
||||||
if (this.refs.email.value == '') {
|
if (this.refs.email.value == '') {
|
||||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('If you don\'t specify an email address...', '', QuestionDialog, {
|
||||||
title: _t("Warning!"),
|
title: _t("Warning!"),
|
||||||
description:
|
description:
|
||||||
<div>
|
<div>
|
||||||
|
@ -122,7 +122,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
showHelpPopup: function() {
|
showHelpPopup: function() {
|
||||||
var CustomServerDialog = sdk.getComponent('login.CustomServerDialog');
|
var CustomServerDialog = sdk.getComponent('login.CustomServerDialog');
|
||||||
Modal.createDialog(CustomServerDialog);
|
Modal.createTrackedDialog('Custom Server Dialog', '', CustomServerDialog);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
@ -282,8 +282,8 @@ module.exports = React.createClass({
|
|||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.warn("Unable to decrypt attachment: ", err);
|
console.warn("Unable to decrypt attachment: ", err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Error decrypting attachment', '', ErrorDialog, {
|
||||||
title: _t("Error"),
|
title: _t("Error"),
|
||||||
description: _t("Error decrypting attachment"),
|
description: _t("Error decrypting attachment"),
|
||||||
});
|
});
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
@ -275,18 +275,21 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getEventTileOps: function() {
|
getEventTileOps: function() {
|
||||||
var self = this;
|
|
||||||
return {
|
return {
|
||||||
isWidgetHidden: function() {
|
isWidgetHidden: () => {
|
||||||
return self.state.widgetHidden;
|
return this.state.widgetHidden;
|
||||||
},
|
},
|
||||||
|
|
||||||
unhideWidget: function() {
|
unhideWidget: () => {
|
||||||
self.setState({ widgetHidden: false });
|
this.setState({ widgetHidden: false });
|
||||||
if (global.localStorage) {
|
if (global.localStorage) {
|
||||||
global.localStorage.removeItem("hide_preview_" + self.props.mxEvent.getId());
|
global.localStorage.removeItem("hide_preview_" + this.props.mxEvent.getId());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getInnerText: () => {
|
||||||
|
return this.refs.content.innerText;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -305,7 +308,7 @@ module.exports = React.createClass({
|
|||||||
let completeUrl = scalarClient.getStarterLink(starterLink);
|
let completeUrl = scalarClient.getStarterLink(starterLink);
|
||||||
let QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
let QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
let integrationsUrl = SdkConfig.get().integrations_ui_url;
|
let integrationsUrl = SdkConfig.get().integrations_ui_url;
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Add an integration', '', QuestionDialog, {
|
||||||
title: _t("Add an Integration"),
|
title: _t("Add an Integration"),
|
||||||
description:
|
description:
|
||||||
<div>
|
<div>
|
||||||
|
@ -154,7 +154,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Invalid alias format', '', ErrorDialog, {
|
||||||
title: _t('Invalid alias format'),
|
title: _t('Invalid alias format'),
|
||||||
description: _t('\'%(alias)s\' is not a valid format for an alias', { alias: alias }),
|
description: _t('\'%(alias)s\' is not a valid format for an alias', { alias: alias }),
|
||||||
});
|
});
|
||||||
@ -170,7 +170,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Invalid address format', '', ErrorDialog, {
|
||||||
title: _t('Invalid address format'),
|
title: _t('Invalid address format'),
|
||||||
description: _t('\'%(alias)s\' is not a valid format for an address', { alias: alias }),
|
description: _t('\'%(alias)s\' is not a valid format for an address', { alias: alias }),
|
||||||
});
|
});
|
||||||
|
@ -166,7 +166,7 @@ module.exports = React.createClass({
|
|||||||
const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ?
|
const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ?
|
||||||
this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId, 'add_integ') :
|
this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId, 'add_integ') :
|
||||||
null;
|
null;
|
||||||
Modal.createDialog(IntegrationsManager, {
|
Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, {
|
||||||
src: src,
|
src: src,
|
||||||
}, "mx_IntegrationsManager");
|
}, "mx_IntegrationsManager");
|
||||||
},
|
},
|
||||||
|
@ -369,7 +369,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||||||
onCryptoClicked: function(e) {
|
onCryptoClicked: function(e) {
|
||||||
var event = this.props.mxEvent;
|
var event = this.props.mxEvent;
|
||||||
|
|
||||||
Modal.createDialogAsync((cb) => {
|
Modal.createTrackedDialogAsync('Encrypted Event Dialog', '', (cb) => {
|
||||||
require(['../../../async-components/views/dialogs/EncryptedEventDialog'], cb);
|
require(['../../../async-components/views/dialogs/EncryptedEventDialog'], cb);
|
||||||
}, {
|
}, {
|
||||||
event: event,
|
event: event,
|
||||||
|
@ -229,7 +229,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||||||
const membership = this.props.member.membership;
|
const membership = this.props.member.membership;
|
||||||
const kickLabel = membership === "invite" ? _t("Disinvite") : _t("Kick");
|
const kickLabel = membership === "invite" ? _t("Disinvite") : _t("Kick");
|
||||||
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
||||||
Modal.createDialog(ConfirmUserActionDialog, {
|
Modal.createTrackedDialog('Confirm User Action Dialog', 'onKick', ConfirmUserActionDialog, {
|
||||||
member: this.props.member,
|
member: this.props.member,
|
||||||
action: kickLabel,
|
action: kickLabel,
|
||||||
askReason: membership == "join",
|
askReason: membership == "join",
|
||||||
@ -248,7 +248,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||||||
}, function(err) {
|
}, function(err) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Kick error: " + err);
|
console.error("Kick error: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to kick', '', ErrorDialog, {
|
||||||
title: _t("Failed to kick"),
|
title: _t("Failed to kick"),
|
||||||
description: ((err && err.message) ? err.message : "Operation failed"),
|
description: ((err && err.message) ? err.message : "Operation failed"),
|
||||||
});
|
});
|
||||||
@ -262,7 +262,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||||||
|
|
||||||
onBanOrUnban: function() {
|
onBanOrUnban: function() {
|
||||||
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
||||||
Modal.createDialog(ConfirmUserActionDialog, {
|
Modal.createTrackedDialog('Confirm User Action Dialog', 'onBanOrUnban', ConfirmUserActionDialog, {
|
||||||
member: this.props.member,
|
member: this.props.member,
|
||||||
action: this.props.member.membership == 'ban' ? _t("Unban") : _t("Ban"),
|
action: this.props.member.membership == 'ban' ? _t("Unban") : _t("Ban"),
|
||||||
askReason: this.props.member.membership != 'ban',
|
askReason: this.props.member.membership != 'ban',
|
||||||
@ -290,7 +290,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||||||
}, function(err) {
|
}, function(err) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Ban error: " + err);
|
console.error("Ban error: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to ban user', '', ErrorDialog, {
|
||||||
title: _t("Error"),
|
title: _t("Error"),
|
||||||
description: _t("Failed to ban user"),
|
description: _t("Failed to ban user"),
|
||||||
});
|
});
|
||||||
@ -340,7 +340,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||||||
console.log("Mute toggle success");
|
console.log("Mute toggle success");
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
console.error("Mute error: " + err);
|
console.error("Mute error: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to mute user', '', ErrorDialog, {
|
||||||
title: _t("Error"),
|
title: _t("Error"),
|
||||||
description: _t("Failed to mute user"),
|
description: _t("Failed to mute user"),
|
||||||
});
|
});
|
||||||
@ -385,7 +385,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||||||
dis.dispatch({action: 'view_set_mxid'});
|
dis.dispatch({action: 'view_set_mxid'});
|
||||||
} else {
|
} else {
|
||||||
console.error("Toggle moderator error:" + err);
|
console.error("Toggle moderator error:" + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to toggle moderator status', '', ErrorDialog, {
|
||||||
title: _t("Error"),
|
title: _t("Error"),
|
||||||
description: _t("Failed to toggle moderator status"),
|
description: _t("Failed to toggle moderator status"),
|
||||||
});
|
});
|
||||||
@ -406,7 +406,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||||||
}, function(err) {
|
}, function(err) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Failed to change power level " + err);
|
console.error("Failed to change power level " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to change power level', '', ErrorDialog, {
|
||||||
title: _t("Error"),
|
title: _t("Error"),
|
||||||
description: _t("Failed to change power level"),
|
description: _t("Failed to change power level"),
|
||||||
});
|
});
|
||||||
@ -435,7 +435,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||||||
var myPower = powerLevelEvent.getContent().users[this.props.matrixClient.credentials.userId];
|
var myPower = powerLevelEvent.getContent().users[this.props.matrixClient.credentials.userId];
|
||||||
if (parseInt(myPower) === parseInt(powerLevel)) {
|
if (parseInt(myPower) === parseInt(powerLevel)) {
|
||||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Promote to PL100 Warning', '', QuestionDialog, {
|
||||||
title: _t("Warning!"),
|
title: _t("Warning!"),
|
||||||
description:
|
description:
|
||||||
<div>
|
<div>
|
||||||
|
@ -99,7 +99,7 @@ export default class MessageComposer extends React.Component {
|
|||||||
</li>);
|
</li>);
|
||||||
}
|
}
|
||||||
|
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Upload Files confirmation', '', QuestionDialog, {
|
||||||
title: _t('Upload Files'),
|
title: _t('Upload Files'),
|
||||||
description: (
|
description: (
|
||||||
<div>
|
<div>
|
||||||
|
@ -31,6 +31,7 @@ import KeyCode from '../../../KeyCode';
|
|||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
|
import Analytics from '../../../Analytics';
|
||||||
|
|
||||||
import dis from '../../../dispatcher';
|
import dis from '../../../dispatcher';
|
||||||
import UserSettingsStore from '../../../UserSettingsStore';
|
import UserSettingsStore from '../../../UserSettingsStore';
|
||||||
@ -160,6 +161,8 @@ export default class MessageComposerInput extends React.Component {
|
|||||||
|
|
||||||
const isRichtextEnabled = UserSettingsStore.getSyncedSetting('MessageComposerInput.isRichTextEnabled', false);
|
const isRichtextEnabled = UserSettingsStore.getSyncedSetting('MessageComposerInput.isRichTextEnabled', false);
|
||||||
|
|
||||||
|
Analytics.setRichtextMode(isRichtextEnabled);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
// whether we're in rich text or markdown mode
|
// whether we're in rich text or markdown mode
|
||||||
isRichtextEnabled,
|
isRichtextEnabled,
|
||||||
@ -280,11 +283,10 @@ export default class MessageComposerInput extends React.Component {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'quote': {
|
case 'quote': {
|
||||||
let {body} = payload.event.getContent();
|
|
||||||
/// XXX: Not doing rich-text quoting from formatted-body because draft-js
|
/// XXX: Not doing rich-text quoting from formatted-body because draft-js
|
||||||
/// has regressed such that when links are quoted, errors are thrown. See
|
/// has regressed such that when links are quoted, errors are thrown. See
|
||||||
/// https://github.com/vector-im/riot-web/issues/4756.
|
/// https://github.com/vector-im/riot-web/issues/4756.
|
||||||
body = escape(body);
|
let body = escape(payload.text);
|
||||||
if (body) {
|
if (body) {
|
||||||
let content = RichText.htmlToContentState(`<blockquote>${body}</blockquote>`);
|
let content = RichText.htmlToContentState(`<blockquote>${body}</blockquote>`);
|
||||||
if (!this.state.isRichtextEnabled) {
|
if (!this.state.isRichtextEnabled) {
|
||||||
@ -457,6 +459,19 @@ export default class MessageComposerInput extends React.Component {
|
|||||||
state.editorState = RichText.attachImmutableEntitiesToEmoji(
|
state.editorState = RichText.attachImmutableEntitiesToEmoji(
|
||||||
state.editorState);
|
state.editorState);
|
||||||
|
|
||||||
|
// Hide the autocomplete if the cursor location changes but the plaintext
|
||||||
|
// content stays the same. We don't hide if the pt has changed because the
|
||||||
|
// autocomplete will probably have different completions to show.
|
||||||
|
if (
|
||||||
|
!state.editorState.getSelection().equals(
|
||||||
|
this.state.editorState.getSelection()
|
||||||
|
)
|
||||||
|
&& state.editorState.getCurrentContent().getPlainText() ===
|
||||||
|
this.state.editorState.getCurrentContent().getPlainText()
|
||||||
|
) {
|
||||||
|
this.autocomplete.hide();
|
||||||
|
}
|
||||||
|
|
||||||
if (state.editorState.getCurrentContent().hasText()) {
|
if (state.editorState.getCurrentContent().hasText()) {
|
||||||
this.onTypingActivity();
|
this.onTypingActivity();
|
||||||
} else {
|
} else {
|
||||||
@ -513,6 +528,8 @@ export default class MessageComposerInput extends React.Component {
|
|||||||
contentState = ContentState.createFromText(markdown);
|
contentState = ContentState.createFromText(markdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Analytics.setRichtextMode(enabled);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
editorState: this.createEditorState(enabled, contentState),
|
editorState: this.createEditorState(enabled, contentState),
|
||||||
isRichtextEnabled: enabled,
|
isRichtextEnabled: enabled,
|
||||||
@ -704,7 +721,7 @@ export default class MessageComposerInput extends React.Component {
|
|||||||
}, function(err) {
|
}, function(err) {
|
||||||
console.error("Command failure: %s", err);
|
console.error("Command failure: %s", err);
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Server error', '', ErrorDialog, {
|
||||||
title: _t("Server error"),
|
title: _t("Server error"),
|
||||||
description: ((err && err.message) ? err.message : _t("Server unavailable, overloaded, or something else went wrong.")),
|
description: ((err && err.message) ? err.message : _t("Server unavailable, overloaded, or something else went wrong.")),
|
||||||
});
|
});
|
||||||
@ -712,7 +729,8 @@ export default class MessageComposerInput extends React.Component {
|
|||||||
} else if (cmd.error) {
|
} else if (cmd.error) {
|
||||||
console.error(cmd.error);
|
console.error(cmd.error);
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
// TODO possibly track which command they ran (not its Arguments) here
|
||||||
|
Modal.createTrackedDialog('Command error', '', ErrorDialog, {
|
||||||
title: _t("Command error"),
|
title: _t("Command error"),
|
||||||
description: cmd.error,
|
description: cmd.error,
|
||||||
});
|
});
|
||||||
@ -790,15 +808,10 @@ export default class MessageComposerInput extends React.Component {
|
|||||||
let sendHtmlFn = this.client.sendHtmlMessage;
|
let sendHtmlFn = this.client.sendHtmlMessage;
|
||||||
let sendTextFn = this.client.sendTextMessage;
|
let sendTextFn = this.client.sendTextMessage;
|
||||||
|
|
||||||
if (this.state.isRichtextEnabled) {
|
this.historyManager.save(
|
||||||
this.historyManager.addItem(
|
contentState,
|
||||||
contentHTML ? contentHTML : contentText,
|
this.state.isRichtextEnabled ? 'html' : 'markdown',
|
||||||
contentHTML ? 'html' : 'markdown',
|
);
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Always store MD input as input history
|
|
||||||
this.historyManager.addItem(contentText, 'markdown');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentText.startsWith('/me')) {
|
if (contentText.startsWith('/me')) {
|
||||||
contentText = contentText.substring(4);
|
contentText = contentText.substring(4);
|
||||||
@ -872,6 +885,7 @@ export default class MessageComposerInput extends React.Component {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.moveAutocompleteSelection(up);
|
this.moveAutocompleteSelection(up);
|
||||||
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ module.exports = React.createClass({
|
|||||||
const errMsg = (typeof err === "string") ? err : (err.error || "");
|
const errMsg = (typeof err === "string") ? err : (err.error || "");
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Failed to set avatar: " + errMsg);
|
console.error("Failed to set avatar: " + errMsg);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to set avatar', '', ErrorDialog, {
|
||||||
title: _t("Error"),
|
title: _t("Error"),
|
||||||
description: _t("Failed to set avatar."),
|
description: _t("Failed to set avatar."),
|
||||||
});
|
});
|
||||||
|
@ -46,7 +46,7 @@ const BannedUser = React.createClass({
|
|||||||
|
|
||||||
_onUnbanClick: function() {
|
_onUnbanClick: function() {
|
||||||
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
||||||
Modal.createDialog(ConfirmUserActionDialog, {
|
Modal.createTrackedDialog('Confirm User Action Dialog', 'onUnbanClick', ConfirmUserActionDialog, {
|
||||||
member: this.props.member,
|
member: this.props.member,
|
||||||
action: _t('Unban'),
|
action: _t('Unban'),
|
||||||
danger: false,
|
danger: false,
|
||||||
@ -58,7 +58,7 @@ const BannedUser = React.createClass({
|
|||||||
).catch((err) => {
|
).catch((err) => {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
console.error("Failed to unban: " + err);
|
console.error("Failed to unban: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to unban', '', ErrorDialog, {
|
||||||
title: _t('Error'),
|
title: _t('Error'),
|
||||||
description: _t('Failed to unban'),
|
description: _t('Failed to unban'),
|
||||||
});
|
});
|
||||||
@ -423,7 +423,7 @@ module.exports = React.createClass({
|
|||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
var value = ev.target.value;
|
var value = ev.target.value;
|
||||||
|
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Privacy warning', '', QuestionDialog, {
|
||||||
title: _t('Privacy warning'),
|
title: _t('Privacy warning'),
|
||||||
description:
|
description:
|
||||||
<div>
|
<div>
|
||||||
@ -516,7 +516,7 @@ module.exports = React.createClass({
|
|||||||
onManageIntegrations(ev) {
|
onManageIntegrations(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
var IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
|
var IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
|
||||||
Modal.createDialog(IntegrationsManager, {
|
Modal.createTrackedDialog('Integrations Manager', 'onManageIntegrations', IntegrationsManager, {
|
||||||
src: (this.scalarClient !== null && this.scalarClient.hasCredentials()) ?
|
src: (this.scalarClient !== null && this.scalarClient.hasCredentials()) ?
|
||||||
this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId) :
|
this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId) :
|
||||||
null,
|
null,
|
||||||
@ -549,7 +549,7 @@ module.exports = React.createClass({
|
|||||||
}, function(err) {
|
}, function(err) {
|
||||||
var errCode = err.errcode || _t('unknown error code');
|
var errCode = err.errcode || _t('unknown error code');
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to forget room', '', ErrorDialog, {
|
||||||
title: _t('Error'),
|
title: _t('Error'),
|
||||||
description: _t("Failed to forget room %(errCode)s", { errCode: errCode }),
|
description: _t("Failed to forget room %(errCode)s", { errCode: errCode }),
|
||||||
});
|
});
|
||||||
@ -560,7 +560,7 @@ module.exports = React.createClass({
|
|||||||
if (!this.refs.encrypt.checked) return;
|
if (!this.refs.encrypt.checked) return;
|
||||||
|
|
||||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('E2E Enable Warning', '', QuestionDialog, {
|
||||||
title: _t('Warning!'),
|
title: _t('Warning!'),
|
||||||
description: (
|
description: (
|
||||||
<div>
|
<div>
|
||||||
|
@ -82,7 +82,7 @@ export default withMatrixClient(React.createClass({
|
|||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error("Unable to add phone number: " + err);
|
console.error("Unable to add phone number: " + err);
|
||||||
let msg = err.message;
|
let msg = err.message;
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Add Phone Number Error', '', ErrorDialog, {
|
||||||
title: _t("Error"),
|
title: _t("Error"),
|
||||||
description: msg,
|
description: msg,
|
||||||
});
|
});
|
||||||
@ -107,7 +107,7 @@ export default withMatrixClient(React.createClass({
|
|||||||
}
|
}
|
||||||
msgElements.push(<div key="_error" className="error">{msg}</div>);
|
msgElements.push(<div key="_error" className="error">{msg}</div>);
|
||||||
}
|
}
|
||||||
Modal.createDialog(TextInputDialog, {
|
Modal.createTrackedDialog('Prompt for MSISDN Verification Code', '', TextInputDialog, {
|
||||||
title: _t("Enter Code"),
|
title: _t("Enter Code"),
|
||||||
description: <div>{msgElements}</div>,
|
description: <div>{msgElements}</div>,
|
||||||
button: _t("Submit"),
|
button: _t("Submit"),
|
||||||
|
@ -104,7 +104,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
Modal.createDialog(QuestionDialog, {
|
Modal.createTrackedDialog('Change Password', '', QuestionDialog, {
|
||||||
title: _t("Warning!"),
|
title: _t("Warning!"),
|
||||||
description:
|
description:
|
||||||
<div>
|
<div>
|
||||||
@ -164,7 +164,7 @@ module.exports = React.createClass({
|
|||||||
const deferred = Promise.defer();
|
const deferred = Promise.defer();
|
||||||
// Ask for an email otherwise the user has no way to reset their password
|
// Ask for an email otherwise the user has no way to reset their password
|
||||||
const SetEmailDialog = sdk.getComponent("dialogs.SetEmailDialog");
|
const SetEmailDialog = sdk.getComponent("dialogs.SetEmailDialog");
|
||||||
Modal.createDialog(SetEmailDialog, {
|
Modal.createTrackedDialog('Do you want to set an email address?', '', SetEmailDialog, {
|
||||||
title: _t('Do you want to set an email address?'),
|
title: _t('Do you want to set an email address?'),
|
||||||
onFinished: (confirmed) => {
|
onFinished: (confirmed) => {
|
||||||
// ignore confirmed, setting an email is optional
|
// ignore confirmed, setting an email is optional
|
||||||
@ -175,15 +175,13 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onExportE2eKeysClicked: function() {
|
_onExportE2eKeysClicked: function() {
|
||||||
Modal.createDialogAsync(
|
Modal.createTrackedDialogAsync('Export E2E Keys', 'Change Password', (cb) => {
|
||||||
(cb) => {
|
require.ensure(['../../../async-components/views/dialogs/ExportE2eKeysDialog'], () => {
|
||||||
require.ensure(['../../../async-components/views/dialogs/ExportE2eKeysDialog'], () => {
|
cb(require('../../../async-components/views/dialogs/ExportE2eKeysDialog'));
|
||||||
cb(require('../../../async-components/views/dialogs/ExportE2eKeysDialog'));
|
}, "e2e-export");
|
||||||
}, "e2e-export");
|
}, {
|
||||||
}, {
|
matrixClient: MatrixClientPeg.get(),
|
||||||
matrixClient: MatrixClientPeg.get(),
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onClickChange: function() {
|
onClickChange: function() {
|
||||||
|
@ -71,8 +71,8 @@ export default class DevicesPanelEntry extends React.Component {
|
|||||||
// pop up an interactive auth dialog
|
// pop up an interactive auth dialog
|
||||||
var InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
|
var InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
|
||||||
|
|
||||||
Modal.createDialog(InteractiveAuthDialog, {
|
Modal.createTrackedDialog('Delete Device Dialog', InteractiveAuthDialog, {
|
||||||
title: _t("Authentication"),
|
title: _t("Authentication"),
|
||||||
matrixClient: MatrixClientPeg.get(),
|
matrixClient: MatrixClientPeg.get(),
|
||||||
authData: error.data,
|
authData: error.data,
|
||||||
makeRequest: this._makeDeleteRequest,
|
makeRequest: this._makeDeleteRequest,
|
||||||
|
@ -115,7 +115,7 @@ function createRoom(opts) {
|
|||||||
action: 'join_room_error',
|
action: 'join_room_error',
|
||||||
});
|
});
|
||||||
console.error("Failed to create room " + roomId + " " + err);
|
console.error("Failed to create room " + roomId + " " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failure to create room', '', ErrorDialog, {
|
||||||
title: _t("Failure to create room"),
|
title: _t("Failure to create room"),
|
||||||
description: _t("Server may be unavailable, overloaded, or you hit a bug."),
|
description: _t("Server may be unavailable, overloaded, or you hit a bug."),
|
||||||
});
|
});
|
||||||
|
@ -346,6 +346,7 @@
|
|||||||
"Hangup": "Hangup",
|
"Hangup": "Hangup",
|
||||||
"Hide Apps": "Hide Apps",
|
"Hide Apps": "Hide Apps",
|
||||||
"Hide join/leave messages (invites/kicks/bans unaffected)": "Hide join/leave messages (invites/kicks/bans unaffected)",
|
"Hide join/leave messages (invites/kicks/bans unaffected)": "Hide join/leave messages (invites/kicks/bans unaffected)",
|
||||||
|
"Hide avatar and display name changes": "Hide avatar and display name changes",
|
||||||
"Hide read receipts": "Hide read receipts",
|
"Hide read receipts": "Hide read receipts",
|
||||||
"Hide Text Formatting Toolbar": "Hide Text Formatting Toolbar",
|
"Hide Text Formatting Toolbar": "Hide Text Formatting Toolbar",
|
||||||
"Historical": "Historical",
|
"Historical": "Historical",
|
||||||
@ -575,6 +576,7 @@
|
|||||||
"To configure the room": "To configure the room",
|
"To configure the room": "To configure the room",
|
||||||
"to demote": "to demote",
|
"to demote": "to demote",
|
||||||
"to favourite": "to favourite",
|
"to favourite": "to favourite",
|
||||||
|
"To get started, please pick a username!": "To get started, please pick a username!",
|
||||||
"To invite users into the room": "To invite users into the room",
|
"To invite users into the room": "To invite users into the room",
|
||||||
"To kick users": "To kick users",
|
"To kick users": "To kick users",
|
||||||
"To link to a room it must have <a>an address</a>.": "To link to a room it must have <a>an address</a>.",
|
"To link to a room it must have <a>an address</a>.": "To link to a room it must have <a>an address</a>.",
|
||||||
|
@ -14,38 +14,37 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function _isLeaveOrJoin(ev) {
|
function memberEventDiff(ev) {
|
||||||
const isMemberEvent = ev.getType() === 'm.room.member' && ev.getStateKey() !== undefined;
|
const diff = {
|
||||||
if (!isMemberEvent) {
|
isMemberEvent: ev.getType() === 'm.room.member',
|
||||||
return false; // bail early: all the checks below concern member events only
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: These checks are done to make sure we're dealing with membership transitions not avatar changes / dupe joins
|
// If is not a Member Event then the other checks do not apply, so bail early.
|
||||||
// These checks are also being done in TextForEvent and should really reside in the JS SDK as a helper function
|
if (!diff.isMemberEvent) return diff;
|
||||||
const membership = ev.getContent().membership;
|
|
||||||
const prevMembership = ev.getPrevContent().membership;
|
|
||||||
if (membership === prevMembership && membership === 'join') {
|
|
||||||
// join -> join : This happens when display names change / avatars are set / genuine dupe joins with no changes.
|
|
||||||
// Find out which we're dealing with.
|
|
||||||
if (ev.getPrevContent().displayname !== ev.getContent().displayname) {
|
|
||||||
return false; // display name changed
|
|
||||||
}
|
|
||||||
if (ev.getPrevContent().avatar_url !== ev.getContent().avatar_url) {
|
|
||||||
return false; // avatar url changed
|
|
||||||
}
|
|
||||||
// dupe join event, fall through to hide rules
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const content = ev.getContent();
|
||||||
|
const prevContent = ev.getPrevContent();
|
||||||
|
|
||||||
// this only applies to joins/invited joins/leaves not invites/kicks/bans
|
diff.isJoin = content.membership === 'join' && prevContent.membership !== 'ban';
|
||||||
const isJoin = membership === 'join' && prevMembership !== 'ban';
|
diff.isPart = content.membership === 'leave' && ev.getStateKey() === ev.getSender();
|
||||||
const isLeave = membership === 'leave' && ev.getStateKey() === ev.getSender();
|
|
||||||
return isJoin || isLeave;
|
const isJoinToJoin = content.membership === prevContent.membership && content.membership === 'join';
|
||||||
|
diff.isDisplaynameChange = isJoinToJoin && content.displayname !== prevContent.displayname;
|
||||||
|
diff.isAvatarChange = isJoinToJoin && content.avatar_url !== prevContent.avatar_url;
|
||||||
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function(ev, syncedSettings) {
|
export default function shouldHideEvent(ev, syncedSettings) {
|
||||||
// Hide redacted events
|
// Hide redacted events
|
||||||
if (syncedSettings['hideRedactions'] && ev.isRedacted()) return true;
|
if (syncedSettings['hideRedactions'] && ev.isRedacted()) return true;
|
||||||
if (syncedSettings['hideJoinLeaves'] && _isLeaveOrJoin(ev)) return true;
|
|
||||||
|
const eventDiff = memberEventDiff(ev);
|
||||||
|
|
||||||
|
if (eventDiff.isMemberEvent) {
|
||||||
|
if (syncedSettings['hideJoinLeaves'] && (eventDiff.isJoin || eventDiff.isPart)) return true;
|
||||||
|
const isMemberAvatarDisplaynameChange = eventDiff.isAvatarChange || eventDiff.isDisplaynameChange;
|
||||||
|
if (syncedSettings['hideAvatarDisplaynameChanges'] && isMemberAvatarDisplaynameChange) return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ class RoomViewStore extends Store {
|
|||||||
});
|
});
|
||||||
const msg = err.message ? err.message : JSON.stringify(err);
|
const msg = err.message ? err.message : JSON.stringify(err);
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createTrackedDialog('Failed to join room', '', ErrorDialog, {
|
||||||
title: _t("Failed to join room"),
|
title: _t("Failed to join room"),
|
||||||
description: msg,
|
description: msg,
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user