Skip to content

Commit

Permalink
[MM-42420] Implement new "Start Call" channel header button (#62)
Browse files Browse the repository at this point in the history
* Update header button to use registerCallButtonAction

* Simplify registrations
  • Loading branch information
streamer45 authored May 10, 2022
1 parent fd6a63c commit fe44602
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 28 deletions.
2 changes: 1 addition & 1 deletion plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Integrates real-time voice communication in Mattermost",
"homepage_url": "https://github.com/mattermost/mattermost-plugin-calls/",
"support_url": "https://github.com/mattermost/mattermost-plugin-calls/issues",
"min_server_version": "6.3.0",
"min_server_version": "6.6.0",
"server": {
"executables": {
"linux-amd64": "server/dist/plugin-linux-amd64",
Expand Down
15 changes: 8 additions & 7 deletions webapp/src/components/channel_header_button/component.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';

import CallIcon from '../../components/icons/call_icon';
import CompassIcon from '../../components/icons/compassIcon';

interface Props {
show: boolean,
inCall: boolean,
hasCall: boolean,
}

Expand All @@ -13,18 +14,18 @@ const ChannelHeaderButton = (props: Props) => {
return null;
}
return (
<div
<button
id='calls-join-button'
style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}
className={'style--none call-button ' + (props.inCall ? 'disabled' : '')}
disabled={Boolean(props.inCall)}
>
<CallIcon style={{margin: '0 4px'}}/>
<CompassIcon icon='phone-outline'/>
<span
className='icon__text'
style={{margin: '0 4px'}}
className='call-button-label'
>
{props.hasCall ? 'Join Call' : 'Start Call'}
</span>
</div>
</button>
);
};

Expand Down
3 changes: 2 additions & 1 deletion webapp/src/components/channel_header_button/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import ChannelHeaderButton from './component';

const mapStateToProps = (state: GlobalState) => ({
hasCall: voiceConnectedUsers(state).length > 0,
show: isVoiceEnabled(state) && (!connectedChannelID(state) || getCurrentChannelId(state) !== connectedChannelID(state)),
inCall: connectedChannelID(state) && connectedChannelID(state) === getCurrentChannelId(state),
show: isVoiceEnabled(state),
});

export default connect(mapStateToProps)(ChannelHeaderButton);
37 changes: 37 additions & 0 deletions webapp/src/components/channel_header_dropdown_button/component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import PropTypes from 'prop-types';

import CompassIcon from '../../components/icons/compassIcon';

interface Props {
show: boolean,
inCall: boolean,
hasCall: boolean,
}

const ChannelHeaderDropdownButton = (props: Props) => {
if (!props.show) {
return null;
}
return (
<button
id='calls-join-button'
className={'style--none call-button-dropdown ' + (props.inCall ? 'disabled' : '')}
disabled={Boolean(props.inCall)}
>
<CompassIcon icon='phone-outline'/>
<div>
<span >
{props.hasCall ? 'Join Call' : 'Start Call'}
</span>
<span
className='call-button-dropdown-sublabel'
>
{'In this channel'}
</span>
</div>
</button>
);
};

export default ChannelHeaderDropdownButton;
16 changes: 16 additions & 0 deletions webapp/src/components/channel_header_dropdown_button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {connect} from 'react-redux';
import {GlobalState} from 'mattermost-redux/types/store';

import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';

import {voiceConnectedUsers, connectedChannelID, isVoiceEnabled} from '../../selectors';

import ChannelHeaderDropdownButton from './component';

const mapStateToProps = (state: GlobalState) => ({
hasCall: voiceConnectedUsers(state).length > 0,
inCall: connectedChannelID(state) && connectedChannelID(state) === getCurrentChannelId(state),
show: isVoiceEnabled(state),
});

export default connect(mapStateToProps)(ChannelHeaderDropdownButton);
29 changes: 10 additions & 19 deletions webapp/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {pluginId} from './manifest';
import CallsClient from './client';

import ChannelHeaderButton from './components/channel_header_button';
import ChannelHeaderDropdownButton from './components/channel_header_dropdown_button';
import ChannelHeaderMenuButton from './components/channel_header_menu_button';
import CallWidget from './components/call_widget';
import ChannelLinkLabel from './components/channel_link_label';
Expand Down Expand Up @@ -70,8 +71,6 @@ import {PluginRegistry, Store} from './types/mattermost-webapp';

export default class Plugin {
private unsubscribers: (() => void)[];
private unregisterChannelHeaderMenuButton: any;
private registerChannelHeaderMenuButton: any;

constructor() {
this.unsubscribers = [];
Expand All @@ -84,15 +83,12 @@ export default class Plugin {

private registerWebSocketEvents(registry: PluginRegistry, store: Store) {
registry.registerWebSocketEventHandler(`custom_${pluginId}_channel_enable_voice`, (data) => {
this.unregisterChannelHeaderMenuButton();
this.registerChannelHeaderMenuButton();
store.dispatch({
type: VOICE_CHANNEL_ENABLE,
});
});

registry.registerWebSocketEventHandler(`custom_${pluginId}_channel_disable_voice`, (data) => {
this.unregisterChannelHeaderMenuButton();
store.dispatch({
type: VOICE_CHANNEL_DISABLE,
});
Expand Down Expand Up @@ -312,20 +308,21 @@ export default class Plugin {
});

let channelHeaderMenuButtonID: string;
this.unregisterChannelHeaderMenuButton = () => {
const unregisterChannelHeaderMenuButton = () => {
if (channelHeaderMenuButtonID) {
registry.unregisterComponent(channelHeaderMenuButtonID);
channelHeaderMenuButtonID = '';
}
};
this.unsubscribers.push(this.unregisterChannelHeaderMenuButton);
this.registerChannelHeaderMenuButton = () => {
this.unsubscribers.push(unregisterChannelHeaderMenuButton);
const registerChannelHeaderMenuButton = () => {
if (channelHeaderMenuButtonID) {
return;
}
channelHeaderMenuButtonID = registry.registerChannelHeaderButtonAction(
ChannelHeaderButton
,

channelHeaderMenuButtonID = registry.registerCallButtonAction(
ChannelHeaderButton,
ChannelHeaderDropdownButton,
async (channel) => {
try {
const users = voiceConnectedUsers(store.getState());
Expand Down Expand Up @@ -354,6 +351,8 @@ export default class Plugin {
);
};

registerChannelHeaderMenuButton();

const connectCall = async (channelID: string) => {
try {
if (window.callsClient) {
Expand All @@ -367,7 +366,6 @@ export default class Plugin {
window.callsClient.on('close', () => {
registry.unregisterComponent(globalComponentID);
registry.unregisterComponent(rootComponentID);
this.registerChannelHeaderMenuButton();
if (window.callsClient) {
window.callsClient.destroy();
delete window.callsClient;
Expand All @@ -378,8 +376,6 @@ export default class Plugin {
});

window.callsClient.init(channelID);

this.unregisterChannelHeaderMenuButton();
} catch (err) {
delete window.callsClient;
console.log(err);
Expand Down Expand Up @@ -472,13 +468,8 @@ export default class Plugin {
console.log(err);
}

this.unregisterChannelHeaderMenuButton();

try {
const resp = await axios.get(`${getPluginPath()}/${channelID}`);
if (resp.data.enabled && connectedChannelID(store.getState()) !== channelID) {
this.registerChannelHeaderMenuButton();
}
store.dispatch({
type: resp.data.enabled ? VOICE_CHANNEL_ENABLE : VOICE_CHANNEL_DISABLE,
});
Expand Down
1 change: 1 addition & 0 deletions webapp/src/types/mattermost-webapp/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface PluginRegistry {
registerCustomRoute(route: string, component: React.ElementType)
registerNeedsTeamRoute(route: string, component: React.ElementType)
registerSlashCommandWillBePostedHook(hook: (message: string, args: CommandArgs) => any)
registerCallButtonAction(button: React.ElementType, dropdownButton: React.ElementType, fn: (channel: Channel) => void)
unregisterComponent(componentID: string)
unregisterPostTypeComponent(componentID: string)
}
Expand Down

0 comments on commit fe44602

Please sign in to comment.