Resolve issues

This commit is contained in:
Will Hunt 2019-05-12 17:14:21 +01:00
parent 2023b3d905
commit 64a384477e
4 changed files with 38 additions and 23 deletions

View file

@ -97,20 +97,24 @@ const Notifier = {
}, },
getSoundForRoom: async function(roomId) { getSoundForRoom: async function(roomId) {
// We do no caching here because the SDK caches the event content // We do no caching here because the SDK caches setting
// and the browser will cache the sound. // and the browser will cache the sound.
let content = SettingsStore.getValue("notificationSound", roomId); let content = SettingsStore.getValue("notificationSound", roomId);
if (!content) { if (!content) {
content = SettingsStore.getValue("notificationSound"); return null;
if (!content) {
return null;
}
} }
if (!content.url) { if (!content.url) {
console.warn(`${roomId} has custom notification sound event, but no url key`); console.warn(`${roomId} has custom notification sound event, but no url key`);
return null; return null;
} }
if (!content.url.startsWith("mxc://")) {
console.warn(`${roomId} has custom notification sound event, but url is not a mxc url`);
return null;
}
// Ideally in here we could use MSC1310 to detect the type of file, and reject it.
return { return {
url: MatrixClientPeg.get().mxcUrlToHttp(content.url), url: MatrixClientPeg.get().mxcUrlToHttp(content.url),
@ -123,7 +127,7 @@ const Notifier = {
_playAudioNotification: async function(ev, room) { _playAudioNotification: async function(ev, room) {
const sound = SettingsStore.isFeatureEnabled("feature_notification_sounds") ? await this.getSoundForRoom(room.roomId) : null; const sound = SettingsStore.isFeatureEnabled("feature_notification_sounds") ? await this.getSoundForRoom(room.roomId) : null;
console.log(`Got sound ${sound && sound.name || "default"} for ${room.roomId}`); console.log(`Got sound ${sound && sound.name || "default"} for ${room.roomId}`);
// XXX: How do we ensure this is a sound file and not going to be exploited?
try { try {
const selector = document.querySelector(sound ? `audio[src='${sound.url}']` : "#messageAudio"); const selector = document.querySelector(sound ? `audio[src='${sound.url}']` : "#messageAudio");
let audioElement = selector; let audioElement = selector;

View file

@ -20,12 +20,12 @@ import {_t} from "../../../../../languageHandler";
import MatrixClientPeg from "../../../../../MatrixClientPeg"; import MatrixClientPeg from "../../../../../MatrixClientPeg";
import AccessibleButton from "../../../elements/AccessibleButton"; import AccessibleButton from "../../../elements/AccessibleButton";
import Notifier from "../../../../../Notifier"; import Notifier from "../../../../../Notifier";
import SettingsStore from '../../../../../settings/SettingsStore'; import SettingsStore from '../../../../../settings/SettingsStore';
import { SettingLevel } from '../../../../../settings/SettingsStore';
export default class NotificationsSettingsTab extends React.Component { export default class NotificationsSettingsTab extends React.Component {
static propTypes = { static propTypes = {
roomId: PropTypes.string.isRequired, roomId: PropTypes.string.isRequired,
closeSettingsFn: PropTypes.func.isRequired,
}; };
constructor() { constructor() {
@ -46,7 +46,7 @@ export default class NotificationsSettingsTab extends React.Component {
}); });
} }
_onSoundUploadChanged(e) { async _onSoundUploadChanged(e) {
if (!e.target.files || !e.target.files.length) { if (!e.target.files || !e.target.files.length) {
this.setState({ this.setState({
uploadedFile: null, uploadedFile: null,
@ -58,11 +58,18 @@ export default class NotificationsSettingsTab extends React.Component {
this.setState({ this.setState({
uploadedFile: file, uploadedFile: file,
}); });
try {
await this._saveSound();
} catch (ex) {
console.error(
`Unable to save notification sound for ${this.props.roomId}`,
ex,
);
}
} }
async _saveSound(e) { async _saveSound() {
e.stopPropagation();
e.preventDefault();
if (!this.state.uploadedFile) { if (!this.state.uploadedFile) {
return; return;
} }
@ -82,7 +89,8 @@ export default class NotificationsSettingsTab extends React.Component {
await SettingsStore.setValue( await SettingsStore.setValue(
"notificationSound", "notificationSound",
this.props.roomId, this.props.roomId,
"room-account", SettingsStore.
SettingLevel.ROOM_ACCOUNT,
{ {
name: this.state.uploadedFile.name, name: this.state.uploadedFile.name,
type: type, type: type,
@ -101,7 +109,12 @@ export default class NotificationsSettingsTab extends React.Component {
_clearSound(e) { _clearSound(e) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
SettingsStore.setValue("notificationSound", this.props.roomId, "room-account", null); SettingsStore.setValue(
"notificationSound",
this.props.roomId,
SettingLevel.ROOM_ACCOUNT,
null,
);
this.setState({ this.setState({
currentSound: "default", currentSound: "default",
@ -119,11 +132,8 @@ export default class NotificationsSettingsTab extends React.Component {
</div> </div>
<div> <div>
<h3>{_t("Set a new custom sound")}</h3> <h3>{_t("Set a new custom sound")}</h3>
<form onSubmit={this._saveSound.bind(this)} autoComplete={false} noValidate={true}> <form autoComplete={false} noValidate={true}>
<input type="file" onChange={this._onSoundUploadChanged.bind(this)} accept="audio/*" /> <input type="file" onChange={this._onSoundUploadChanged.bind(this)} accept="audio/*" />
<AccessibleButton onClick={this._saveSound.bind(this)} kind="primary" disabled={!this.state.uploadedFile}>
{_t("Save")}
</AccessibleButton>
</form> </form>
<AccessibleButton onClick={this._clearSound.bind(this)} kind="primary"> <AccessibleButton onClick={this._clearSound.bind(this)} kind="primary">
{_t("Reset to default sound")} {_t("Reset to default sound")}

View file

@ -297,6 +297,7 @@
"Show recent room avatars above the room list": "Show recent room avatars above the room list", "Show recent room avatars above the room list": "Show recent room avatars above the room list",
"Group & filter rooms by custom tags (refresh to apply changes)": "Group & filter rooms by custom tags (refresh to apply changes)", "Group & filter rooms by custom tags (refresh to apply changes)": "Group & filter rooms by custom tags (refresh to apply changes)",
"Render simple counters in room header": "Render simple counters in room header", "Render simple counters in room header": "Render simple counters in room header",
"Custom Notification Sounds": "Custom Notification Sounds",
"React to messages with emoji": "React to messages with emoji", "React to messages with emoji": "React to messages with emoji",
"Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing", "Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing",
"Use compact timeline layout": "Use compact timeline layout", "Use compact timeline layout": "Use compact timeline layout",
@ -613,6 +614,9 @@
"Room Addresses": "Room Addresses", "Room Addresses": "Room Addresses",
"Publish this room to the public in %(domain)s's room directory?": "Publish this room to the public in %(domain)s's room directory?", "Publish this room to the public in %(domain)s's room directory?": "Publish this room to the public in %(domain)s's room directory?",
"URL Previews": "URL Previews", "URL Previews": "URL Previews",
"Sounds": "Sounds",
"Set a new custom sound": "Set a new custom sound",
"Reset to default sound": "Reset to default sound",
"Change room avatar": "Change room avatar", "Change room avatar": "Change room avatar",
"Change room name": "Change room name", "Change room name": "Change room name",
"Change main address for the room": "Change main address for the room", "Change main address for the room": "Change main address for the room",
@ -1619,9 +1623,5 @@
"If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.", "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.",
"Failed to set direct chat tag": "Failed to set direct chat tag", "Failed to set direct chat tag": "Failed to set direct chat tag",
"Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room", "Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
"Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room", "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room"
"Sounds": "Sounds",
"Custom Notification Sounds": "Notification sound",
"Set a new custom sound": "Set a new custom sound",
"Reset to default sound": "Reset to default sound"
} }

View file

@ -122,6 +122,7 @@ export const SETTINGS = {
"feature_notification_sounds": { "feature_notification_sounds": {
isFeature: true, isFeature: true,
displayName: _td("Custom Notification Sounds"), displayName: _td("Custom Notification Sounds"),
},
"feature_reactions": { "feature_reactions": {
isFeature: true, isFeature: true,
displayName: _td("React to messages with emoji"), displayName: _td("React to messages with emoji"),