From 92a932158df32e8360c649df1c5280390652595b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 9 May 2019 22:12:21 +0100 Subject: [PATCH 1/8] Command to change avatar for a single room, including upload of mxc res Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/SlashCommands.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/SlashCommands.js b/src/SlashCommands.js index f72ba1e005..8757f5108a 100644 --- a/src/SlashCommands.js +++ b/src/SlashCommands.js @@ -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,7 @@ import MultiInviter from './utils/MultiInviter'; import { linkifyAndSanitizeHtml } from './HtmlUtils'; import QuestionDialog from "./components/views/dialogs/QuestionDialog"; import WidgetUtils from "./utils/WidgetUtils"; +import Promise from "bluebird"; class Command { constructor({name, args='', description, runFn, hideCompletionAfterSpace=false}) { @@ -208,6 +210,47 @@ export const CommandMap = { }, }), + roomavatar: new Command({ + name: 'roomavatar', + args: '', + 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: ' []', From 5cb0a81565385b33c34d9472ed355bbafa49e2b4 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 10 May 2019 20:28:28 +0100 Subject: [PATCH 2/8] Change roomavatar to myroomavatar and roomnick to match, leaving alias Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/SlashCommands.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/SlashCommands.js b/src/SlashCommands.js index 8757f5108a..a1364efbe1 100644 --- a/src/SlashCommands.js +++ b/src/SlashCommands.js @@ -192,8 +192,8 @@ export const CommandMap = { }, }), - roomnick: new Command({ - name: 'roomnick', + myroomnick: new Command({ + name: 'myroomnick', args: '', description: _td('Changes your display nickname in the current room only'), runFn: function(roomId, args) { @@ -210,9 +210,9 @@ export const CommandMap = { }, }), - roomavatar: new Command({ - name: 'roomavatar', - args: '', + myroomavatar: new Command({ + name: 'myroomavatar', + args: '[]', description: _td('Changes your avatar in this current room only'), runFn: function(roomId, args) { const cli = MatrixClientPeg.get(); @@ -770,6 +770,7 @@ const aliases = { j: "join", newballsplease: "discardsession", goto: "join", // because it handles event permalinks magically + roomnick: "myroomnick", }; From 249f3d972b2230fececd82e2525f293561a25ba9 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 10 May 2019 20:58:32 +0100 Subject: [PATCH 3/8] Close Room Settings upon Leave Room Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../views/dialogs/RoomSettingsDialog.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/components/views/dialogs/RoomSettingsDialog.js b/src/components/views/dialogs/RoomSettingsDialog.js index 05ed262078..c221289ff3 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.js +++ b/src/components/views/dialogs/RoomSettingsDialog.js @@ -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. @@ -24,6 +25,7 @@ import GeneralRoomSettingsTab from "../settings/tabs/room/GeneralRoomSettingsTab import SecurityRoomSettingsTab from "../settings/tabs/room/SecurityRoomSettingsTab"; import sdk from "../../../index"; import MatrixClientPeg from "../../../MatrixClientPeg"; +import dis from "../../../dispatcher"; export default class RoomSettingsDialog extends React.Component { static propTypes = { @@ -31,6 +33,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 = []; From 0530a64f1905876ee2e6c38b4ee07e6d7ca84801 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 11 May 2019 18:46:13 +0100 Subject: [PATCH 4/8] Fix invite via MemberInfo. Thank U JetBrains for solving this one for me <3 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/MemberInfo.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 35161dedf7..be10a3900f 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -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'); From 8bd45ce893406d3cba3fee0c17b0528833380d47 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 12 May 2019 16:36:43 +0100 Subject: [PATCH 5/8] add /rainbow and /rainbowme Slash Commands Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/SlashCommands.js | 21 ++++++++++++++ src/utils/colour.js | 67 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 src/utils/colour.js diff --git a/src/SlashCommands.js b/src/SlashCommands.js index f72ba1e005..0dc717a6fe 100644 --- a/src/SlashCommands.js +++ b/src/SlashCommands.js @@ -30,6 +30,7 @@ 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"; class Command { constructor({name, args='', description, runFn, hideCompletionAfterSpace=false}) { @@ -718,6 +719,26 @@ export const CommandMap = { return success(); }, }), + + rainbow: new Command({ + name: "rainbow", + description: _td(""), + args: '', + 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(""), + args: '', + 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 */ diff --git a/src/utils/colour.js b/src/utils/colour.js new file mode 100644 index 0000000000..5d90bf0773 --- /dev/null +++ b/src/utils/colour.js @@ -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 '' + c + ''; + }).join(""); +} From 4c8593a91fb71f4336258e3c71341f482273f5a2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 12 May 2019 16:40:27 +0100 Subject: [PATCH 6/8] Add i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/SlashCommands.js | 4 ++-- src/i18n/strings/en_EN.json | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/SlashCommands.js b/src/SlashCommands.js index 0dc717a6fe..06120b183f 100644 --- a/src/SlashCommands.js +++ b/src/SlashCommands.js @@ -722,7 +722,7 @@ export const CommandMap = { rainbow: new Command({ name: "rainbow", - description: _td(""), + description: _td("Sends the given message coloured as a rainbow"), args: '', runFn: function(roomId, args) { if (!args) return reject(this.getUserId()); @@ -732,7 +732,7 @@ export const CommandMap = { rainbowme: new Command({ name: "rainbowme", - description: _td(""), + description: _td("Sends the given emote coloured as a rainbow"), args: '', runFn: function(roomId, args) { if (!args) return reject(this.getUserId()); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8534091176..be82c5427a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -178,6 +178,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.", From d9b03b019676575ae32ecebeda77888af83a17c3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 12 May 2019 16:42:13 +0100 Subject: [PATCH 7/8] fix i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index eaea057b36..5b28cd2e7a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -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.", From 9f9a245af19bfa773aa7c5d5313caaa91686eaac Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 12 May 2019 17:14:30 +0100 Subject: [PATCH 8/8] delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/SlashCommands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SlashCommands.js b/src/SlashCommands.js index 06120b183f..a3d4f71894 100644 --- a/src/SlashCommands.js +++ b/src/SlashCommands.js @@ -738,7 +738,7 @@ export const CommandMap = { if (!args) return reject(this.getUserId()); return success(MatrixClientPeg.get().sendHtmlEmote(roomId, args, textToHtmlRainbow(args))); }, - }) + }), }; /* eslint-enable babel/no-invalid-this */