UNPKG

@atlaskit/mention

Version:

A React component used to display user profiles in a list for 'Mention' functionality

189 lines (187 loc) 6.29 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import React from 'react'; import { withAnalyticsEvents } from '@atlaskit/analytics-next'; import uniqueId from '../../util/id'; import debug from '../../util/logger'; import MentionList from '../MentionList'; import { fireSliAnalyticsEvent, SLI_EVENT_TYPE } from '../../util/analytics'; function applyPresence(mentions, presences) { const updatedMentions = []; for (let i = 0; i < mentions.length; i++) { // Shallow copy const mention = { ...mentions[i] }; const presence = presences[mention.id]; if (presence) { mention.presence = presence; } updatedMentions.push(mention); } return updatedMentions; } function extractPresences(mentions) { const presences = {}; for (let i = 0; i < mentions.length; i++) { const mention = mentions[i]; if (mention.presence) { presences[mention.id] = mention.presence; } } return presences; } export class ResourcedMentionListWithoutAnalytics extends React.PureComponent { constructor(props) { super(props); // API _defineProperty(this, "selectNext", () => { if (this.mentionListRef) { this.mentionListRef.selectNext(); } }); _defineProperty(this, "selectPrevious", () => { if (this.mentionListRef) { this.mentionListRef.selectPrevious(); } }); _defineProperty(this, "selectIndex", (index, callback) => { if (this.mentionListRef) { this.mentionListRef.selectIndex(index, callback); } }); _defineProperty(this, "selectId", (id, callback) => { if (this.mentionListRef) { this.mentionListRef.selectId(id, callback); } }); _defineProperty(this, "chooseCurrentSelection", () => { if (this.mentionListRef) { this.mentionListRef.chooseCurrentSelection(); } }); _defineProperty(this, "mentionsCount", () => { if (this.mentionListRef) { return this.mentionListRef.mentionsCount(); } return 0; }); // internal, used for callbacks _defineProperty(this, "filterChange", mentions => { // Retain known presence const currentPresences = extractPresences(this.state.mentions); this.setState({ resourceError: undefined, mentions: applyPresence(mentions, currentPresences) }); this.refreshPresences(mentions); }); _defineProperty(this, "sendAnalytics", (event, actionSubject, action) => { if (event === SLI_EVENT_TYPE) { fireSliAnalyticsEvent(this.props)(actionSubject, action); } }); _defineProperty(this, "filterError", error => { debug('ak-resourced-mentions-list._filterError', error); this.setState({ resourceError: error }); }); _defineProperty(this, "presenceUpdate", presences => { this.setState({ mentions: applyPresence(this.state.mentions, presences) }); }); _defineProperty(this, "notifySelection", mention => { this.props.resourceProvider.recordMentionSelection(mention); if (this.props.onSelection) { this.props.onSelection(mention); } }); _defineProperty(this, "handleMentionListRef", ref => { this.mentionListRef = ref; }); this.subscriberKey = uniqueId('ak-resourced-mention-list'); this.state = { resourceError: undefined, mentions: [] }; this.applyPropChanges({}, props); } componentDidMount() { this.subscribeMentionProvider(this.props.resourceProvider); this.subscribePresenceProvider(this.props.presenceProvider); } UNSAFE_componentWillReceiveProps(nextProps) { this.applyPropChanges(this.props, nextProps); } componentWillUnmount() { this.unsubscribeMentionProvider(this.props.resourceProvider); this.unsubscribePresenceProvider(this.props.presenceProvider); } // internal subscribeMentionProvider(mentionProvider) { if (mentionProvider) { mentionProvider.subscribe(this.subscriberKey, this.filterChange, this.filterError, undefined, undefined, this.sendAnalytics); } } subscribePresenceProvider(presenceProvider) { if (presenceProvider) { presenceProvider.subscribe(this.subscriberKey, this.presenceUpdate); } } unsubscribeMentionProvider(mentionProvider) { if (mentionProvider) { mentionProvider.unsubscribe(this.subscriberKey); } } unsubscribePresenceProvider(presenceProvider) { if (presenceProvider) { presenceProvider.unsubscribe(this.subscriberKey); } } applyPropChanges(prevProps, nextProps) { const oldResourceProvider = prevProps.resourceProvider; const oldPresenceProvider = prevProps.presenceProvider; const oldQuery = prevProps.query; const newResourceProvider = nextProps.resourceProvider; const newPresenceProvider = nextProps.presenceProvider; const newQuery = nextProps.query; const resourceProviderChanged = oldResourceProvider !== newResourceProvider; const queryChanged = oldQuery !== newQuery; const canFilter = !!(typeof newQuery === 'string' && newResourceProvider); const shouldFilter = canFilter && (queryChanged || resourceProviderChanged); // resource provider if (resourceProviderChanged) { this.unsubscribeMentionProvider(oldResourceProvider); this.subscribeMentionProvider(newResourceProvider); } // presence provider if (oldPresenceProvider !== newPresenceProvider) { this.unsubscribePresenceProvider(oldPresenceProvider); this.subscribePresenceProvider(newPresenceProvider); } if (shouldFilter) { newResourceProvider.filter(newQuery); } } refreshPresences(mentions) { if (this.props.presenceProvider) { const ids = mentions.map(mention => mention.id); this.props.presenceProvider.refreshPresence(ids); } } render() { const { mentions, resourceError } = this.state; return /*#__PURE__*/React.createElement(MentionList, { mentions: mentions, resourceError: resourceError, onSelection: this.notifySelection, ref: this.handleMentionListRef }); } } const ResourcedMentionList = withAnalyticsEvents({})(ResourcedMentionListWithoutAnalytics); export default ResourcedMentionList;