diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.js b/src/components/views/settings/tabs/room/NotificationSettingsTab.js index fa56fa2cb65..4c0dbd8d11d 100644 --- a/src/components/views/settings/tabs/room/NotificationSettingsTab.js +++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.js @@ -19,10 +19,12 @@ import PropTypes from 'prop-types'; import {_t} from "../../../../../languageHandler"; import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import AccessibleButton from "../../../elements/AccessibleButton"; -import Notifier from "../../../../../Notifier"; import SettingsStore from '../../../../../settings/SettingsStore'; import {SettingLevel} from "../../../../../settings/SettingLevel"; import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +import Field from "../../../elements/Field"; +import Modal from '../../../../../Modal'; +import * as sdk from '../../../../../index'; @replaceableComponent("views.settings.tabs.room.NotificationsSettingsTab") export default class NotificationsSettingsTab extends React.Component { @@ -37,37 +39,91 @@ export default class NotificationsSettingsTab extends React.Component { this.state = { currentSound: "default", - uploadedFile: null, + currentSoundReplaced: false, + selected: null, + soundLibrary: {}, }; } // TODO: [REACT-WARNING] Replace component with real class, use constructor for refs UNSAFE_componentWillMount() { // eslint-disable-line camelcase - const soundData = Notifier.getSoundForRoom(this.props.roomId); - if (!soundData) { - return; - } - this.setState({currentSound: soundData.name || soundData.url}); + const soundData = SettingsStore.getValue("notificationSound", this.props.roomId); + const soundLibrary = SettingsStore.getValue("soundLibrary", null); + console.log(soundLibrary); + const selected = (soundData === null) ? "default" : soundData.name; + this.setState({ + currentSound: soundData.name || soundData.url, + selected: selected, + soundLibrary: soundLibrary, + }); } - async _triggerUploader(e) { - e.stopPropagation(); - e.preventDefault(); - + async _triggerUploader() { this._soundUpload.current.click(); } async _onSoundUploadChanged(e) { if (!e.target.files || !e.target.files.length) { - this.setState({ - uploadedFile: null, - }); return; } const file = e.target.files[0]; + const soundLibrary = this.state.soundLibrary; + + if (file.name in soundLibrary) { + const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog'); + Modal.createDialog(QuestionDialog, { + title: _t("Replace File"), + description: _t("There already exists a file with this name. " + + "Are you sure, you want to replace it?"), + button: _t("Replace"), + onFinished: () => { + this.setState({currentSoundReplaced: true}); + this._uploadSound(file); + }, + }); + + return; + } + this._uploadSound(file); + } + + async _uploadSound(file) { + let type = file.type; + + if (type === "video/ogg") { + // XXX: I've observed browsers allowing users to pick a audio/ogg files, + // and then calling it a video/ogg. This is a lame hack, but man browsers + // suck at detecting mimetypes. + type = "audio/ogg"; + } + + const url = await MatrixClientPeg.get().uploadContent( + file, { + type, + }, + ); + + const soundJSON = { + name: file.name, + type: type, + size: file.size, + url, + }; + + const soundLibrary = this.state.soundLibrary; + soundLibrary[soundJSON.name] = soundJSON; + + await SettingsStore.setValue( + "soundLibrary", + null, + SettingLevel.ACCOUNT, + soundLibrary, + ); + this.setState({ - uploadedFile: file, + soundLibrary: soundLibrary, + selected: soundJSON.name, }); } @@ -86,45 +142,30 @@ export default class NotificationsSettingsTab extends React.Component { } async _saveSound() { - if (!this.state.uploadedFile) { + if (!this.state.selected) { return; } - let type = this.state.uploadedFile.type; - if (type === "video/ogg") { - // XXX: I've observed browsers allowing users to pick a audio/ogg files, - // and then calling it a video/ogg. This is a lame hack, but man browsers - // suck at detecting mimetypes. - type = "audio/ogg"; + if (this.state.selected == "default") { + this._clearSound(); + return; } - const url = await MatrixClientPeg.get().uploadContent( - this.state.uploadedFile, { - type, - }, - ); + const soundJSON = this.state.soundLibrary[this.state.selected]; await SettingsStore.setValue( "notificationSound", this.props.roomId, SettingLevel.ROOM_ACCOUNT, - { - name: this.state.uploadedFile.name, - type: type, - size: this.state.uploadedFile.size, - url, - }, + soundJSON, ); this.setState({ - uploadedFile: null, - currentSound: this.state.uploadedFile.name, + currentSound: soundJSON.name, }); } - _clearSound(e) { - e.stopPropagation(); - e.preventDefault(); + _clearSound() { SettingsStore.setValue( "notificationSound", this.props.roomId, @@ -137,16 +178,32 @@ export default class NotificationsSettingsTab extends React.Component { }); } - render() { - let currentUploadedFile = null; - if (this.state.uploadedFile) { - currentUploadedFile = ( -
{this.state.uploadedFile.name}
- {this.state.currentSound}