Merge branch 'hs/custom-notif-sounds' of github.com:Half-Shot/matrix-react-sdk into hs/custom-notif-sounds

pull/21833/head
Will Hunt 2019-05-14 21:05:55 +01:00
commit 46132a2463
5 changed files with 157 additions and 4 deletions

View File

@ -1,6 +1,7 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2018 New Vector Ltd
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -30,6 +31,8 @@ import MultiInviter from './utils/MultiInviter';
import { linkifyAndSanitizeHtml } from './HtmlUtils';
import QuestionDialog from "./components/views/dialogs/QuestionDialog";
import WidgetUtils from "./utils/WidgetUtils";
import {textToHtmlRainbow} from "./utils/colour";
import Promise from "bluebird";
class Command {
constructor({name, args='', description, runFn, hideCompletionAfterSpace=false}) {
@ -190,8 +193,8 @@ export const CommandMap = {
},
}),
roomnick: new Command({
name: 'roomnick',
myroomnick: new Command({
name: 'myroomnick',
args: '<display_name>',
description: _td('Changes your display nickname in the current room only'),
runFn: function(roomId, args) {
@ -208,6 +211,47 @@ export const CommandMap = {
},
}),
myroomavatar: new Command({
name: 'myroomavatar',
args: '[<mxc_url>]',
description: _td('Changes your avatar in this current room only'),
runFn: function(roomId, args) {
const cli = MatrixClientPeg.get();
const room = cli.getRoom(roomId);
const userId = cli.getUserId();
let promise = Promise.resolve(args);
if (!args) {
promise = new Promise((resolve) => {
const fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');
fileSelector.onchange = (ev) => {
const file = ev.target.files[0];
const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
Modal.createTrackedDialog('Upload Files confirmation', '', UploadConfirmDialog, {
file,
onFinished: (shouldContinue) => {
if (shouldContinue) resolve(cli.uploadContent(file));
},
});
};
fileSelector.click();
});
}
return success(promise.then((url) => {
const ev = room.currentState.getStateEvents('m.room.member', userId);
const content = {
...ev ? ev.getContent() : { membership: 'join' },
avatar_url: url,
};
return cli.sendStateEvent(roomId, 'm.room.member', content, userId);
}));
},
}),
tint: new Command({
name: 'tint',
args: '<color1> [<color2>]',
@ -718,6 +762,26 @@ export const CommandMap = {
return success();
},
}),
rainbow: new Command({
name: "rainbow",
description: _td("Sends the given message coloured as a rainbow"),
args: '<message>',
runFn: function(roomId, args) {
if (!args) return reject(this.getUserId());
return success(MatrixClientPeg.get().sendHtmlMessage(roomId, args, textToHtmlRainbow(args)));
},
}),
rainbowme: new Command({
name: "rainbowme",
description: _td("Sends the given emote coloured as a rainbow"),
args: '<message>',
runFn: function(roomId, args) {
if (!args) return reject(this.getUserId());
return success(MatrixClientPeg.get().sendHtmlEmote(roomId, args, textToHtmlRainbow(args)));
},
}),
};
/* eslint-enable babel/no-invalid-this */
@ -727,6 +791,7 @@ const aliases = {
j: "join",
newballsplease: "discardsession",
goto: "join", // because it handles event permalinks magically
roomnick: "myroomnick",
};

View File

@ -1,5 +1,6 @@
/*
Copyright 2019 New Vector Ltd
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -26,6 +27,7 @@ import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsT
import sdk from "../../../index";
import MatrixClientPeg from "../../../MatrixClientPeg";
import SettingsStore from '../../../settings/SettingsStore';
import dis from "../../../dispatcher";
export default class RoomSettingsDialog extends React.Component {
static propTypes = {
@ -33,6 +35,22 @@ export default class RoomSettingsDialog extends React.Component {
onFinished: PropTypes.func.isRequired,
};
componentWillMount() {
this._dispatcherRef = dis.register(this._onAction);
}
componentWillUnmount() {
dis.unregister(this._dispatcherRef);
}
_onAction = (payload) => {
// When room changes below us, close the room settings
// whilst the modal is open this can only be triggered when someone hits Leave Room
if (payload.action === 'view_next_room') {
this.props.onFinished();
}
};
_getTabs() {
const tabs = [];

View File

@ -735,8 +735,8 @@ module.exports = withMatrixClient(React.createClass({
// we're only inviting one user.
const inviter = new MultiInviter(roomId);
await inviter.invite([member.userId]).then(() => {
if (inviter.getCompletionState(userId) !== "invited")
throw new Error(inviter.getErrorText(userId));
if (inviter.getCompletionState(member.userId) !== "invited")
throw new Error(inviter.getErrorText(member.userId));
});
} catch (err) {
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');

View File

@ -146,6 +146,7 @@
"Upgrade": "Upgrade",
"Changes your display nickname": "Changes your display nickname",
"Changes your display nickname in the current room only": "Changes your display nickname in the current room only",
"Changes your avatar in this current room only": "Changes your avatar in this current room only",
"Changes colour scheme of current room": "Changes colour scheme of current room",
"Gets or sets the room topic": "Gets or sets the room topic",
"This room has no topic.": "This room has no topic.",
@ -178,6 +179,8 @@
"The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.",
"Displays action": "Displays action",
"Forces the current outbound group session in an encrypted room to be discarded": "Forces the current outbound group session in an encrypted room to be discarded",
"Sends the given message coloured as a rainbow": "Sends the given message coloured as a rainbow",
"Sends the given emote coloured as a rainbow": "Sends the given emote coloured as a rainbow",
"Unrecognised command:": "Unrecognised command:",
"Reason": "Reason",
"%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s accepted the invitation for %(displayName)s.",

67
src/utils/colour.js Normal file
View File

@ -0,0 +1,67 @@
/*
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
export function hueToRGB(h, s, l) {
const c = s * (1 - Math.abs(2 * l - 1));
const x = c * (1 - Math.abs((h / 60) % 2 - 1));
const m = l - c / 2;
let r = 0;
let g = 0;
let b = 0;
if (0 <= h && h < 60) {
r = c;
g = x;
b = 0;
} else if (60 <= h && h < 120) {
r = x;
g = c;
b = 0;
} else if (120 <= h && h < 180) {
r = 0;
g = c;
b = x;
} else if (180 <= h && h < 240) {
r = 0;
g = x;
b = c;
} else if (240 <= h && h < 300) {
r = x;
g = 0;
b = c;
} else if (300 <= h && h < 360) {
r = c;
g = 0;
b = x;
}
return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)];
}
export function textToHtmlRainbow(str) {
const frequency = 360 / str.length;
return str.split("").map((c, i) => {
const [r, g, b] = hueToRGB(i * frequency, 1.0, 0.5);
return '<font color="#' +
r.toString(16).padStart(2, "0") +
g.toString(16).padStart(2, "0") +
b.toString(16).padStart(2, "0") +
'">' + c + '</font>';
}).join("");
}