Skip to content
This repository has been archived by the owner on Jul 25, 2022. It is now read-only.

Commit

Permalink
Fix performance issues, updating issues and a UX issue (#6)
Browse files Browse the repository at this point in the history
* fix possible failure bricking updating on pc

* fix constant hard rerendering issues

* fix webpack search in render and rerendering issue

* make UX slightly better by adding min height

* bump version
  • Loading branch information
1Lighty authored Jun 26, 2021
1 parent 483eade commit b159d31
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 24 deletions.
23 changes: 14 additions & 9 deletions components/TypingIndicator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,32 @@
const { React, getModule, i18n: { Messages }, constants: { Routes } } = require('powercord/webpack');
const { Tooltip, Spinner } = require('powercord/components');

const ChannelStore = getModule([ 'hasChannel' ], false);
const ChannelUtils = getModule([ 'openPrivateChannel' ], false);
const Router = getModule([ 'transitionTo' ], false);

module.exports = class TypingIndicator extends React.PureComponent {
constructor (props) {
super(props);

this.getSetting = props.getSetting;
this.channelStore = getModule([ 'hasChannel' ], false);
this.channelUtils = getModule([ 'openPrivateChannel' ], false);
this.transitionTo = getModule([ 'transitionTo'], false).transitionTo;
// bind has to happen here, if you do bind in render, then it will just
// rerender every single time needlessly
this.handleOpenPrivateChannel = this.handleOpenPrivateChannel.bind(this);
}

async handleOpenPrivateChannel (typingUsers, user) {
handleOpenPrivateChannel () {
const { typingUsers, typingUsersFlat: [ user ] } = this.props;
const channelIds = Object.keys(typingUsers);
const privateGroupChannel = Object.values(this.channelStore.getMutablePrivateChannels()).find(channel => (
const privateGroupChannel = Object.values(ChannelStore.getMutablePrivateChannels()).find(channel => (
channel.isGroupDM() && channel.id === channelIds[0]
));

if (privateGroupChannel) {
return this.transitionTo(Routes.CHANNEL('@me', privateGroupChannel.id));
return Router.transitionTo(Routes.CHANNEL('@me', privateGroupChannel.id));
}

return this.channelUtils.openPrivateChannel(user.id);
return ChannelUtils.openPrivateChannel(user.id);
}

formatUsernames () {
Expand Down Expand Up @@ -91,7 +96,7 @@ module.exports = class TypingIndicator extends React.PureComponent {
}

render () {
const { clickable, typingUsers, typingUsersFlat } = this.props;
const { clickable, typingUsersFlat } = this.props;

if (typingUsersFlat.length === 0) return null;

Expand All @@ -102,7 +107,7 @@ module.exports = class TypingIndicator extends React.PureComponent {
return <Spinner type='pulsingEllipsis' animated={animateIndicator} className='dm-typing-badge' itemClassName='dm-typing-badge-spinner' style={badgeStyle} />;
}

return <div className={this.props.className} onClick={clickable && this.handleOpenPrivateChannel.bind(this, typingUsers, typingUsersFlat[0])}>
return <div className={this.props.className} onClick={clickable && this.handleOpenPrivateChannel}>
<Tooltip
color='black'
position='right'
Expand Down
35 changes: 23 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ module.exports = class DMTypingIndicator extends Plugin {
constructor () {
super();

this.classes = {
tutorialContainer: getModule([ 'homeIcon', 'downloadProgress' ], false).tutorialContainer,
listItem: getModule([ 'guildSeparator', 'listItem' ], false).listItem
};
// must try catch, if you don't, then if this ever errors out, you won't
try {
this.classes = {
tutorialContainer: getModule([ 'homeIcon', 'downloadProgress' ], false).tutorialContainer,
listItem: getModule([ 'guildSeparator', 'listItem' ], false).listItem
};
} catch (err) {
this.error('Failed to fetch classes', err);
}
}

get dmTypingStore () {
Expand All @@ -40,6 +45,16 @@ module.exports = class DMTypingIndicator extends Plugin {
async injectTypingIndicator () {
const HomeButtonsModule = await getModule([ 'DefaultHomeButton' ]);

// why outside? well, if you do it inside the patch, then it will create a new element each time
// and if a new element is made each time, it will needlessly rerender each time
// not is a rerender slow, but it actually reconstructs the entire TypingIndicator class
// every single time, big nono, especially if you use webpack search in the constructor of TypingIndicator
const ConnectedTypingIndicator = Flux.connectStores([ powercord.api.settings.store, dmTypingStore ], ({ typingUsersFlat, typingUsers }) => ({
typingUsers,
typingUsersFlat,
...powercord.api.settings._fluxProps('dm-typing-indicator')
}))(TypingIndicator);

inject('dm-typing-indicator', HomeButtonsModule, 'DefaultHomeButton', ([ props ], res) => {
if (!Array.isArray(res)) res = [ res ];

Expand All @@ -48,12 +63,6 @@ module.exports = class DMTypingIndicator extends Plugin {
const typingUsersFlat = props.typingUsersFlat || dmTypingStore.getFlattenedDMTypingUsers();
const typingUsers = props.typingUsers || dmTypingStore.getDMTypingUsers();

const ConnectedTypingIndicator = Flux.connectStores([ powercord.api.settings.store, dmTypingStore ], () => ({
typingUsers,
typingUsersFlat,
...powercord.api.settings._fluxProps('dm-typing-indicator')
}))(TypingIndicator);

const indicatorStyle = this.settings.get('indicatorStyle', 'icon');
const hideWhenViewed = this.settings.get('hideWhenViewed', true);

Expand All @@ -66,11 +75,13 @@ module.exports = class DMTypingIndicator extends Plugin {

if (badgeContainer && indicatorStyle === 'badge' && typingUsersFlat.length > 0) {
badgeContainer.props.lowerBadgeWidth = 28;
badgeContainer.props.lowerBadge = React.createElement(ConnectedTypingIndicator, { badge: true });
badgeContainer.props.lowerBadge = React.createElement(ConnectedTypingIndicator, { badge: true, typingUsersFlat, typingUsers });
} else {
res.splice(1, 0, React.createElement(ConnectedTypingIndicator, {
className: this.classes.listItem,
clickable: typingUsersFlat.length === 1
clickable: typingUsersFlat.length === 1,
typingUsersFlat,
typingUsers
}));
}

Expand Down
4 changes: 2 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"description": "Displays whenever a user is typing in your DMs.",
"author": "Moth, M|-|4r13y ツ",
"license": "MIT",
"version": "3.1.8"
}
"version": "3.1.9"
}
3 changes: 2 additions & 1 deletion stores/dmTypingStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ const { Flux, FluxDispatcher, getModule } = require('powercord/webpack');
const { forceUpdateElement } = require('powercord/util');

const { getSetting } = powercord.api.settings._fluxProps('dm-typing-indicator');
const { tutorialContainer } = getModule([ 'homeIcon', 'downloadProgress' ], false);
// use an || {}, otherwise plugin will fail to construct and you won't be able to update it
const { tutorialContainer } = getModule([ 'homeIcon', 'downloadProgress' ], false) || (console.error('tutorialContainer not found in DM-Typing-Indicator!'), { tutorialContainer: 'CLASSNOTFOUND' });

const privateChannelStore = getModule([ 'getPrivateChannelIds' ], false);
const relationshipStore = getModule([ 'isBlocked', 'isFriend' ], false);
Expand Down
1 change: 1 addition & 0 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
text-transform: uppercase;
word-wrap: normal;
width: 62px;
min-height: 10px;
color: var(--text-muted);
}

Expand Down

0 comments on commit b159d31

Please sign in to comment.