mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-18 14:44:58 +08:00
refactoring roomView / slashCommands / SendMessageComposer with the new effects configurations and fix confetti animation timeout
This commit is contained in:
parent
48633f76ab
commit
1c6d28b861
@ -46,6 +46,7 @@ import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from
|
|||||||
import SdkConfig from "./SdkConfig";
|
import SdkConfig from "./SdkConfig";
|
||||||
import SettingsStore from "./settings/SettingsStore";
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
import {UIFeature} from "./settings/UIFeature";
|
import {UIFeature} from "./settings/UIFeature";
|
||||||
|
import effects from "./components/views/elements/effects"
|
||||||
|
|
||||||
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
|
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
|
||||||
interface HTMLInputEvent extends Event {
|
interface HTMLInputEvent extends Event {
|
||||||
@ -1040,22 +1041,28 @@ export const Commands = [
|
|||||||
},
|
},
|
||||||
category: CommandCategories.actions,
|
category: CommandCategories.actions,
|
||||||
}),
|
}),
|
||||||
new Command({
|
...effects.map((effect) => {
|
||||||
command: "confetti",
|
return new Command({
|
||||||
description: _td("Sends the given message with confetti"),
|
command: effect.command,
|
||||||
args: '<message>',
|
description: effect.description(),
|
||||||
runFn: function(roomId, args) {
|
args: '<message>',
|
||||||
return success((async () => {
|
runFn: function(roomId, args) {
|
||||||
if (!args) {
|
return success((async () => {
|
||||||
args = "sends confetti";
|
if (!args) {
|
||||||
MatrixClientPeg.get().sendEmoteMessage(roomId, args);
|
args = effect.fallbackMessage();
|
||||||
} else {
|
MatrixClientPeg.get().sendEmoteMessage(roomId, args);
|
||||||
MatrixClientPeg.get().sendTextMessage(roomId, args);
|
} else {
|
||||||
}
|
const content = {
|
||||||
dis.dispatch({action: 'effects.confetti'});
|
msgtype: effect.msgType,
|
||||||
})());
|
body: args,
|
||||||
},
|
};
|
||||||
category: CommandCategories.effects,
|
MatrixClientPeg.get().sendMessage(roomId, content);
|
||||||
|
}
|
||||||
|
dis.dispatch({action: `effects.${effect.command}`});
|
||||||
|
})());
|
||||||
|
},
|
||||||
|
category: CommandCategories.effects,
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Command definitions for autocompletion ONLY:
|
// Command definitions for autocompletion ONLY:
|
||||||
|
@ -73,7 +73,8 @@ import {XOR} from "../../@types/common";
|
|||||||
import { IThreepidInvite } from "../../stores/ThreepidInviteStore";
|
import { IThreepidInvite } from "../../stores/ThreepidInviteStore";
|
||||||
import { CallState, CallType, MatrixCall } from "matrix-js-sdk/lib/webrtc/call";
|
import { CallState, CallType, MatrixCall } from "matrix-js-sdk/lib/webrtc/call";
|
||||||
import EffectsOverlay from "../views/elements/effects/EffectsOverlay";
|
import EffectsOverlay from "../views/elements/effects/EffectsOverlay";
|
||||||
import { isConfettiEmoji } from '../views/elements/effects/confetti';
|
import {containsEmoji} from '../views/elements/effects/effectUtilities';
|
||||||
|
import effects from '../views/elements/effects'
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
let debuglog = function(msg: string) {};
|
let debuglog = function(msg: string) {};
|
||||||
@ -800,10 +801,9 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onEventDecrypted = (ev) => {
|
private onEventDecrypted = (ev) => {
|
||||||
if (ev.isBeingDecrypted() || ev.isDecryptionFailure() ||
|
if (ev.isDecryptionFailure()) return;
|
||||||
this.state.room.getUnreadNotificationCount() === 0) return;
|
|
||||||
this.handleConfetti(ev);
|
this.handleConfetti(ev);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -813,11 +813,13 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private handleConfetti = (ev) => {
|
private handleConfetti = (ev) => {
|
||||||
|
if (this.state.room.getUnreadNotificationCount() === 0) return;
|
||||||
if (this.state.matrixClientIsReady) {
|
if (this.state.matrixClientIsReady) {
|
||||||
const messageBody = 'sends confetti';
|
effects.map(effect => {
|
||||||
if (isConfettiEmoji(ev.getContent()) || ev.getContent().body === messageBody) {
|
if (containsEmoji(ev.getContent(), effect.emojis) || ev.getContent().msgtype === effect.msgType) {
|
||||||
dis.dispatch({action: 'effects.confetti'});
|
dis.dispatch({action: `effects.${effect.command}`});
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export default interface ICanvasEffect {
|
export default interface ICanvasEffect {
|
||||||
start: (canvas: HTMLCanvasElement, timeout?: number) => Promise<void>,
|
start: (canvas: HTMLCanvasElement, timeout: number) => Promise<void>,
|
||||||
stop: () => Promise<void>,
|
stop: () => Promise<void>,
|
||||||
isRunning: boolean
|
isRunning: boolean
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ export default class Confetti implements ICanvasEffect {
|
|||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
private context: CanvasRenderingContext2D | null;
|
private context: CanvasRenderingContext2D | null = null;
|
||||||
private supportsAnimationFrame = window.requestAnimationFrame ||
|
private supportsAnimationFrame = window.requestAnimationFrame ||
|
||||||
window.webkitRequestAnimationFrame ||
|
window.webkitRequestAnimationFrame ||
|
||||||
window.mozRequestAnimationFrame ||
|
window.mozRequestAnimationFrame ||
|
||||||
@ -64,7 +64,7 @@ export default class Confetti implements ICanvasEffect {
|
|||||||
|
|
||||||
public isRunning: boolean;
|
public isRunning: boolean;
|
||||||
|
|
||||||
public start = async (canvas: HTMLCanvasElement, timeout?: number) => {
|
public start = async (canvas: HTMLCanvasElement, timeout = 3000) => {
|
||||||
if(!canvas) {
|
if(!canvas) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -88,13 +88,13 @@ export default class Confetti implements ICanvasEffect {
|
|||||||
this.isRunning = true;
|
this.isRunning = true;
|
||||||
this.runAnimation();
|
this.runAnimation();
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
window.setTimeout(this.stop, timeout || 3000);
|
window.setTimeout(this.stop, timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public stop = async () => {
|
public stop = async () => {
|
||||||
this.isRunning = false;
|
this.isRunning = false;
|
||||||
this.particles = [];
|
// this.particles = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private resetParticle = (particle: ConfettiParticle, width: number, height: number): ConfettiParticle => {
|
private resetParticle = (particle: ConfettiParticle, width: number, height: number): ConfettiParticle => {
|
||||||
@ -177,21 +177,3 @@ export default class Confetti implements ICanvasEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const convertToHex = (data: string): Array<string> => {
|
|
||||||
const contentBodyToHexArray = [];
|
|
||||||
if (!data) return contentBodyToHexArray;
|
|
||||||
let hex;
|
|
||||||
if (data) {
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
|
||||||
hex = data.codePointAt(i).toString(16);
|
|
||||||
contentBodyToHexArray.push(hex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return contentBodyToHexArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isConfettiEmoji = (content: { msgtype: string, body: string }): boolean => {
|
|
||||||
const hexArray = convertToHex(content.body);
|
|
||||||
return !!(hexArray.includes('1f389') || hexArray.includes('1f38a'));
|
|
||||||
}
|
|
||||||
|
3
src/components/views/elements/effects/effectUtilities.ts
Normal file
3
src/components/views/elements/effects/effectUtilities.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const containsEmoji = (content: { msgtype: string, body: string }, emojis: Array<string>): boolean => {
|
||||||
|
return emojis.some((emoji) => content.body.includes(emoji));
|
||||||
|
}
|
11
src/components/views/elements/effects/index.ts
Normal file
11
src/components/views/elements/effects/index.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import {_t, _td} from "../../../../languageHandler";
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
emojis: ['🎊', '🎉'],
|
||||||
|
msgType: 'nic.custom.confetti',
|
||||||
|
command: 'confetti',
|
||||||
|
description: () => _td("Sends the given message with confetti"),
|
||||||
|
fallbackMessage: () => _t("sends confetti") + " 🎉",
|
||||||
|
},
|
||||||
|
]
|
@ -42,8 +42,8 @@ import {Key} from "../../../Keyboard";
|
|||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import RateLimitedFunc from '../../../ratelimitedfunc';
|
import RateLimitedFunc from '../../../ratelimitedfunc';
|
||||||
import {Action} from "../../../dispatcher/actions";
|
import {Action} from "../../../dispatcher/actions";
|
||||||
import {isConfettiEmoji} from "../elements/effects/confetti";
|
import {containsEmoji} from "../elements/effects/effectUtilities";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import effects from '../elements/effects';
|
||||||
|
|
||||||
function addReplyToMessageContent(content, repliedToEvent, permalinkCreator) {
|
function addReplyToMessageContent(content, repliedToEvent, permalinkCreator) {
|
||||||
const replyContent = ReplyThread.makeReplyMixIn(repliedToEvent);
|
const replyContent = ReplyThread.makeReplyMixIn(repliedToEvent);
|
||||||
@ -318,9 +318,11 @@ export default class SendMessageComposer extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
dis.dispatch({action: "message_sent"});
|
dis.dispatch({action: "message_sent"});
|
||||||
if (isConfettiEmoji(content)) {
|
effects.map( (effect) => {
|
||||||
dis.dispatch({action: 'effects.confetti'});
|
if (containsEmoji(content, effect.emojis)) {
|
||||||
|
dis.dispatch({action: `effects.${effect.command}`});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendHistoryManager.save(this.model, replyToEvent);
|
this.sendHistoryManager.save(this.model, replyToEvent);
|
||||||
|
Loading…
Reference in New Issue
Block a user