Merge branch 'develop' into matthew/retina

This commit is contained in:
Bruno Windels 2019-04-09 10:55:05 +02:00
commit 15ba24f7fb
64 changed files with 1283 additions and 546 deletions

View file

@ -1,6 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017, 2018 New Vector Ltd
Copyright 2017, 2018, 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -566,7 +566,7 @@ module.exports = React.createClass({
rows="1"
id="textinput"
ref="textinput"
className="mx_ChatInviteDialog_input"
className="mx_AddressPickerDialog_input"
onChange={this.onQueryChanged}
placeholder={this.props.placeholder}
defaultValue={this.props.value}
@ -578,7 +578,7 @@ module.exports = React.createClass({
let addressSelector;
if (this.state.error) {
const validTypeDescriptions = this.props.validAddressTypes.map((t) => _t(addressTypeName[t]));
error = <div className="mx_ChatInviteDialog_error">
error = <div className="mx_AddressPickerDialog_error">
{ _t("You have entered an invalid address.") }
<br />
{ _t("Try using one of the following valid address types: %(validTypesList)s.", {
@ -586,9 +586,9 @@ module.exports = React.createClass({
}) }
</div>;
} else if (this.state.searchError) {
error = <div className="mx_ChatInviteDialog_error">{ this.state.searchError }</div>;
error = <div className="mx_AddressPickerDialog_error">{ this.state.searchError }</div>;
} else if (this.state.query.length > 0 && filteredSuggestedList.length === 0 && !this.state.busy) {
error = <div className="mx_ChatInviteDialog_error">{ _t("No results") }</div>;
error = <div className="mx_AddressPickerDialog_error">{ _t("No results") }</div>;
} else {
addressSelector = (
<AddressSelector ref={(ref) => {this.addressSelector = ref;}}
@ -601,13 +601,13 @@ module.exports = React.createClass({
}
return (
<BaseDialog className="mx_ChatInviteDialog" onKeyDown={this.onKeyDown}
<BaseDialog className="mx_AddressPickerDialog" onKeyDown={this.onKeyDown}
onFinished={this.props.onFinished} title={this.props.title}>
<div className="mx_ChatInviteDialog_label">
<div className="mx_AddressPickerDialog_label">
<label htmlFor="textinput">{ this.props.description }</label>
</div>
<div className="mx_Dialog_content">
<div className="mx_ChatInviteDialog_inputContainer">{ query }</div>
<div className="mx_AddressPickerDialog_inputContainer">{ query }</div>
{ error }
{ addressSelector }
{ this.props.extraNode }

View file

@ -1,6 +1,6 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2018 New Vector Ltd
Copyright 2018, 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -55,6 +55,11 @@ export default React.createClass({
// CSS class to apply to dialog div
className: PropTypes.string,
// if true, dialog container is 60% of the viewport width. Otherwise,
// the container will have no fixed size, allowing its contents to
// determine its size. Default: true.
fixedWidth: PropTypes.bool,
// Title for the dialog.
title: PropTypes.node.isRequired,
@ -72,6 +77,7 @@ export default React.createClass({
getDefaultProps: function() {
return {
hasCancel: true,
fixedWidth: true,
};
},
@ -113,7 +119,10 @@ export default React.createClass({
return (
<FocusTrap onKeyDown={this._onKeyDown}
className={this.props.className}
className={classNames({
[this.props.className]: true,
'mx_Dialog_fixedWidth': this.props.fixedWidth,
})}
role="dialog"
aria-labelledby='mx_BaseDialog_title'
// This should point to a node describing the dialog.
@ -131,8 +140,8 @@ export default React.createClass({
{ this.props.title }
</div>
{ this.props.headerButton }
{ cancelButton }
</div>
{ cancelButton }
{ this.props.children }
</FocusTrap>
);

View file

@ -87,6 +87,7 @@ export default class UploadConfirmDialog extends React.Component {
return (
<BaseDialog className='mx_UploadConfirmDialog'
fixedWidth={false}
onFinished={this._onCancelClick}
title={title}
contentId='mx_Dialog_content'

View file

@ -42,7 +42,7 @@ export default class NetworkDropdown extends React.Component {
expanded: false,
selectedServer: server,
selectedInstanceId: null,
includeAllNetworks: true,
includeAllNetworks: false,
};
}
@ -109,7 +109,7 @@ export default class NetworkDropdown extends React.Component {
expanded: false,
selectedServer: e.target.value,
selectedNetwork: null,
includeAllNetworks: true,
includeAllNetworks: false,
});
this.props.onOptionChange(e.target.value, null);
}

View file

@ -339,9 +339,7 @@ export default class AppTile extends React.Component {
// Destroy the old widget messaging before starting it back up again. Some widgets
// have startup routines that run when they are loaded, so we just need to reinitialize
// the messaging for them.
if (ActiveWidgetStore.getWidgetMessaging(this.props.id)) {
ActiveWidgetStore.delWidgetMessaging(this.props.id);
}
ActiveWidgetStore.delWidgetMessaging(this.props.id);
this._setupWidgetMessaging();
ActiveWidgetStore.setRoomId(this.props.id, this.props.room.roomId);

View file

@ -27,10 +27,8 @@ const Modal = require('../../../Modal');
const sdk = require('../../../index');
import { _t } from '../../../languageHandler';
module.exports = React.createClass({
displayName: 'ImageView',
propTypes: {
export default class ImageView extends React.Component {
static propTypes = {
src: React.PropTypes.string.isRequired, // the source of the image being displayed
name: React.PropTypes.string, // the main title ('name') for the image
link: React.PropTypes.string, // the link (if any) applied to the name of the image
@ -44,27 +42,32 @@ module.exports = React.createClass({
// properties above, which let us use lightboxes to display images which aren't associated
// with events.
mxEvent: React.PropTypes.object,
},
};
constructor(props) {
super(props);
this.state = { rotationDegrees: 0 };
}
// XXX: keyboard shortcuts for managing dialogs should be done by the modal
// dialog base class somehow, surely...
componentDidMount: function() {
componentDidMount() {
document.addEventListener("keydown", this.onKeyDown);
},
}
componentWillUnmount: function() {
componentWillUnmount() {
document.removeEventListener("keydown", this.onKeyDown);
},
}
onKeyDown: function(ev) {
onKeyDown = (ev) => {
if (ev.keyCode == 27) { // escape
ev.stopPropagation();
ev.preventDefault();
this.props.onFinished();
}
},
};
onRedactClick: function() {
onRedactClick = () => {
const ConfirmRedactDialog = sdk.getComponent("dialogs.ConfirmRedactDialog");
Modal.createTrackedDialog('Confirm Redact Dialog', 'Image View', ConfirmRedactDialog, {
onFinished: (proceed) => {
@ -83,17 +86,29 @@ module.exports = React.createClass({
}).done();
},
});
},
};
getName: function() {
getName() {
let name = this.props.name;
if (name && this.props.link) {
name = <a href={ this.props.link } target="_blank" rel="noopener">{ name }</a>;
}
return name;
},
}
render: function() {
rotateCounterClockwise = () => {
const cur = this.state.rotationDegrees;
const rotationDegrees = (cur - 90) % 360;
this.setState({ rotationDegrees });
};
rotateClockwise = () => {
const cur = this.state.rotationDegrees;
const rotationDegrees = (cur + 90) % 360;
this.setState({ rotationDegrees });
};
render() {
/*
// In theory max-width: 80%, max-height: 80% on the CSS should work
// but in practice, it doesn't, so do it manually:
@ -122,7 +137,8 @@ module.exports = React.createClass({
height: displayHeight
};
*/
let style; let res;
let style = {};
let res;
if (this.props.width && this.props.height) {
style = {
@ -168,15 +184,26 @@ module.exports = React.createClass({
</div>);
}
const rotationDegrees = this.state.rotationDegrees;
const effectiveStyle = {transform: `rotate(${rotationDegrees}deg)`, ...style};
return (
<div className="mx_ImageView">
<div className="mx_ImageView_lhs">
</div>
<div className="mx_ImageView_content">
<img src={this.props.src} title={this.props.name} style={style} />
<img src={this.props.src} title={this.props.name} style={effectiveStyle} className="mainImage" />
<div className="mx_ImageView_labelWrapper">
<div className="mx_ImageView_label">
<AccessibleButton className="mx_ImageView_cancel" onClick={ this.props.onFinished }><img src={require("../../../../res/img/cancel-white.svg")} width="18" height="18" alt={ _t('Close') } /></AccessibleButton>
<AccessibleButton className="mx_ImageView_rotateCounterClockwise" onClick={ this.rotateCounterClockwise }>
<img src={require("../../../../res/img/rotate-ccw.svg")} alt={ _t('Rotate counter-clockwise') } width="18" height="18" />
</AccessibleButton>
<AccessibleButton className="mx_ImageView_rotateClockwise" onClick={ this.rotateClockwise }>
<img src={require("../../../../res/img/rotate-cw.svg")} alt={ _t('Rotate clockwise') } width="18" height="18" />
</AccessibleButton>
<AccessibleButton className="mx_ImageView_cancel" onClick={ this.props.onFinished }>
<img src={require("../../../../res/img/cancel-white.svg")} width="18" height="18" alt={ _t('Close') } />
</AccessibleButton>
<div className="mx_ImageView_shim">
</div>
<div className="mx_ImageView_name">
@ -199,5 +226,5 @@ module.exports = React.createClass({
</div>
</div>
);
},
});
}
}

View file

@ -73,8 +73,12 @@ module.exports = React.createClass({
_initStateFromProps: function(newProps) {
// This needs to be done now because levelRoleMap has translated strings
const levelRoleMap = Roles.levelRoleMap(newProps.usersDefault);
const options = Object.keys(levelRoleMap).filter((l) => {
return l === undefined || l <= newProps.maxValue;
const options = Object.keys(levelRoleMap).filter(level => {
return (
level === undefined ||
level <= newProps.maxValue ||
level == newProps.value
);
});
const isCustom = levelRoleMap[newProps.value] === undefined;
@ -130,7 +134,7 @@ module.exports = React.createClass({
<Field id={`powerSelector_custom_${this.props.powerLevelKey}`} type="number"
label={this.props.label || _t("Power level")} max={this.props.maxValue}
onBlur={this.onCustomBlur} onKeyPress={this.onCustomKeyPress} onChange={this.onCustomChange}
value={this.state.customValue} disabled={this.props.disabled} />
value={String(this.state.customValue)} disabled={this.props.disabled} />
);
} else {
// Each level must have a definition in this.state.levelRoleMap
@ -148,7 +152,7 @@ module.exports = React.createClass({
picker = (
<Field id={`powerSelector_notCustom_${this.props.powerLevelKey}`} element="select"
label={this.props.label || _t("Power level")} onChange={this.onSelectChange}
value={this.state.selectValue} disabled={this.props.disabled}>
value={String(this.state.selectValue)} disabled={this.props.disabled}>
{options}
</Field>
);

View file

@ -362,18 +362,22 @@ export default class MessageComposer extends React.Component {
} else if (this.state.tombstone) {
const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
const continuesLink = replacementRoomId ? (
<a href={makeRoomPermalink(replacementRoomId)}
className="mx_MessageComposer_roomReplaced_link"
onClick={this._onTombstoneClick}
>
{_t("The conversation continues here.")}
</a>
) : '';
controls.push(<div className="mx_MessageComposer_replaced_wrapper">
<div className="mx_MessageComposer_replaced_valign">
<img className="mx_MessageComposer_roomReplaced_icon" src={require("../../../../res/img/room_replaced.svg")} />
<span className="mx_MessageComposer_roomReplaced_header">
{_t("This room has been replaced and is no longer active.")}
</span><br />
<a href={makeRoomPermalink(replacementRoomId)}
className="mx_MessageComposer_roomReplaced_link"
onClick={this._onTombstoneClick}
>
{_t("The conversation continues here.")}
</a>
{ continuesLink }
</div>
</div>);
} else {

View file

@ -47,7 +47,7 @@ import {Completion} from "../../../autocomplete/Autocompleter";
import Markdown from '../../../Markdown';
import ComposerHistoryManager from '../../../ComposerHistoryManager';
import MessageComposerStore from '../../../stores/MessageComposerStore';
import ContentMessage from '../../../ContentMessages';
import ContentMessages from '../../../ContentMessages';
import {MATRIXTO_URL_PATTERN} from '../../../linkify-matrix';
@ -139,8 +139,6 @@ export default class MessageComposerInput extends React.Component {
// js-sdk Room object
room: PropTypes.object.isRequired,
onFilesPasted: PropTypes.func,
onInputStateChanged: PropTypes.func,
};
@ -1014,7 +1012,7 @@ export default class MessageComposerInput extends React.Component {
// neither chrome nor firefox let you paste a plain file copied
// from Finder) but more images copied from a different website
// / word processor etc.
return ContentMessage.sharedInstance().sendContentListToRoom(
return ContentMessages.sharedInstance().sendContentListToRoom(
transfer.files, this.props.room.roomId, this.client,
);
case 'html': {

View file

@ -14,14 +14,19 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
'use strict';
import React from "react";
import dis from "../../../dispatcher";
import MatrixClientPeg from "../../../MatrixClientPeg";
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
import AccessibleButton from '../elements/AccessibleButton';
import RoomAvatar from '../avatars/RoomAvatar';
import classNames from 'classnames';
import sdk from "../../../index";
import Analytics from "../../../Analytics";
import * as RoomNotifs from '../../../RoomNotifs';
import * as FormattingUtils from "../../../utils/FormattingUtils";
import DMRoomMap from "../../../utils/DMRoomMap";
import {_t} from "../../../languageHandler";
const MAX_ROOMS = 20;
@ -36,46 +41,58 @@ export default class RoomBreadcrumbs extends React.Component {
componentWillMount() {
this._dispatcherRef = dis.register(this.onAction);
const roomStr = localStorage.getItem("mx_breadcrumb_rooms");
if (roomStr) {
try {
const roomIds = JSON.parse(roomStr);
this.setState({
rooms: roomIds.map((r) => {
return {
room: MatrixClientPeg.get().getRoom(r),
animated: false,
};
}).filter((r) => r.room),
});
} catch (e) {
console.error("Failed to parse breadcrumbs:", e);
let storedRooms = SettingsStore.getValue("breadcrumb_rooms");
if (!storedRooms || !storedRooms.length) {
// Fallback to the rooms stored in localstorage for those who would have had this.
// TODO: Remove this after a bit - the feature was only on develop, so a few weeks should be plenty time.
const roomStr = localStorage.getItem("mx_breadcrumb_rooms");
if (roomStr) {
try {
storedRooms = JSON.parse(roomStr);
} catch (e) {
console.error("Failed to parse breadcrumbs:", e);
}
}
}
this._loadRoomIds(storedRooms || []);
this._settingWatchRef = SettingsStore.watchSetting("breadcrumb_rooms", null, this.onBreadcrumbsChanged);
MatrixClientPeg.get().on("Room.myMembership", this.onMyMembership);
MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt);
MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline);
MatrixClientPeg.get().on("Event.decrypted", this.onEventDecrypted);
}
componentWillUnmount() {
dis.unregister(this._dispatcherRef);
SettingsStore.unwatchSetting(this._settingWatchRef);
const client = MatrixClientPeg.get();
if (client) client.removeListener("Room.myMembership", this.onMyMembership);
if (client) {
client.removeListener("Room.myMembership", this.onMyMembership);
client.removeListener("Room.receipt", this.onRoomReceipt);
client.removeListener("Room.timeline", this.onRoomTimeline);
client.removeListener("Event.decrypted", this.onEventDecrypted);
}
}
componentDidUpdate() {
const rooms = this.state.rooms.slice();
if (rooms.length) {
const {room, animated} = rooms[0];
if (!animated) {
rooms[0] = {room, animated: true};
const roomModel = rooms[0];
if (!roomModel.animated) {
roomModel.animated = true;
setTimeout(() => this.setState({rooms}), 0);
}
}
const roomStr = JSON.stringify(rooms.map((r) => r.room.roomId));
localStorage.setItem("mx_breadcrumb_rooms", roomStr);
const roomIds = rooms.map((r) => r.room.roomId);
if (roomIds.length > 0) {
SettingsStore.setValue("breadcrumb_rooms", null, SettingLevel.ACCOUNT, roomIds);
}
}
onAction(payload) {
@ -97,24 +114,142 @@ export default class RoomBreadcrumbs extends React.Component {
}
};
_appendRoomId(roomId) {
const room = MatrixClientPeg.get().getRoom(roomId);
if (!room) {
return;
onRoomReceipt = (event, room) => {
if (this.state.rooms.map(r => r.room.roomId).includes(room.roomId)) {
this._calculateRoomBadges(room);
}
};
onRoomTimeline = (event, room) => {
if (this.state.rooms.map(r => r.room.roomId).includes(room.roomId)) {
this._calculateRoomBadges(room);
}
};
onEventDecrypted = (event) => {
if (this.state.rooms.map(r => r.room.roomId).includes(event.getRoomId())) {
this._calculateRoomBadges(MatrixClientPeg.get().getRoom(event.getRoomId()));
}
};
onBreadcrumbsChanged = (settingName, roomId, level, valueAtLevel, value) => {
if (!value) return;
const currentState = this.state.rooms.map((r) => r.room.roomId);
if (currentState.length === value.length) {
let changed = false;
for (let i = 0; i < currentState.length; i++) {
if (currentState[i] !== value[i]) {
changed = true;
break;
}
}
if (!changed) return;
}
this._loadRoomIds(value);
};
_loadRoomIds(roomIds) {
if (!roomIds || roomIds.length <= 0) return; // Skip updates with no rooms
// If we're here, the list changed.
const rooms = roomIds.map((r) => MatrixClientPeg.get().getRoom(r)).filter((r) => r).map((r) => {
const badges = this._calculateBadgesForRoom(r) || {};
return {
room: r,
animated: false,
...badges,
};
});
this.setState({
rooms: rooms,
});
}
_calculateBadgesForRoom(room) {
if (!room) return null;
// Reset the notification variables for simplicity
const roomModel = {
redBadge: false,
formattedCount: "0",
showCount: false,
};
const notifState = RoomNotifs.getRoomNotifsState(room.roomId);
if (RoomNotifs.MENTION_BADGE_STATES.includes(notifState)) {
const highlightNotifs = RoomNotifs.getUnreadNotificationCount(room, 'highlight');
const unreadNotifs = RoomNotifs.getUnreadNotificationCount(room);
const redBadge = highlightNotifs > 0;
const greyBadge = redBadge || (unreadNotifs > 0 && RoomNotifs.BADGE_STATES.includes(notifState));
if (redBadge || greyBadge) {
const notifCount = redBadge ? highlightNotifs : unreadNotifs;
const limitedCount = FormattingUtils.formatCount(notifCount);
roomModel.redBadge = redBadge;
roomModel.formattedCount = limitedCount;
roomModel.showCount = true;
}
}
return roomModel;
}
_calculateRoomBadges(room) {
if (!room) return;
const rooms = this.state.rooms.slice();
const roomModel = rooms.find((r) => r.room.roomId === room.roomId);
if (!roomModel) return; // No applicable room, so don't do math on it
const badges = this._calculateBadgesForRoom(room);
if (!badges) return; // No badges for some reason
Object.assign(roomModel, badges);
this.setState({rooms});
}
_appendRoomId(roomId) {
let room = MatrixClientPeg.get().getRoom(roomId);
if (!room) return;
const rooms = this.state.rooms.slice();
// If the room is upgraded, use that room instead. We'll also splice out
// any children of the room.
const history = MatrixClientPeg.get().getRoomUpgradeHistory(roomId);
if (history.length > 1) {
room = history[history.length - 1]; // Last room is most recent
// Take out any room that isn't the most recent room
for (let i = 0; i < history.length - 1; i++) {
const idx = rooms.findIndex((r) => r.room.roomId === history[i].roomId);
if (idx !== -1) rooms.splice(idx, 1);
}
}
const existingIdx = rooms.findIndex((r) => r.room.roomId === room.roomId);
if (existingIdx !== -1) {
rooms.splice(existingIdx, 1);
}
rooms.splice(0, 0, {room, animated: false});
if (rooms.length > MAX_ROOMS) {
rooms.splice(MAX_ROOMS, rooms.length - MAX_ROOMS);
}
this.setState({rooms});
if (this.refs.scroller) {
this.refs.scroller.moveToOrigin();
}
}
_viewRoom(room) {
_viewRoom(room, index) {
Analytics.trackEvent("Breadcrumbs", "click_node", index);
dis.dispatch({action: "view_room", room_id: room.roomId});
}
@ -134,17 +269,21 @@ export default class RoomBreadcrumbs extends React.Component {
this.setState({rooms});
}
_isDmRoom(room) {
const dmRooms = DMRoomMap.shared().getUserIdForRoomId(room.roomId);
return Boolean(dmRooms);
}
render() {
const Tooltip = sdk.getComponent('elements.Tooltip');
const IndicatorScrollbar = sdk.getComponent('structures.IndicatorScrollbar');
// check for collapsed here and
// not at parent so we keep
// rooms in our state
// check for collapsed here and not at parent so we keep rooms in our state
// when collapsing and expanding
if (this.props.collapsed) {
return null;
}
const rooms = this.state.rooms;
const avatars = rooms.map((r, i) => {
const isFirst = i === 0;
@ -160,16 +299,42 @@ export default class RoomBreadcrumbs extends React.Component {
tooltip = <Tooltip label={r.room.name} />;
}
let badge;
if (r.showCount) {
const badgeClasses = classNames({
'mx_RoomTile_badge': true,
'mx_RoomTile_badgeButton': true,
'mx_RoomTile_badgeRed': r.redBadge,
'mx_RoomTile_badgeUnread': !r.redBadge,
});
badge = <div className={badgeClasses}>{r.formattedCount}</div>;
}
let dmIndicator;
if (this._isDmRoom(r.room)) {
dmIndicator = <img
src={require("../../../../res/img/icon_person.svg")}
className="mx_RoomBreadcrumbs_dmIndicator"
width="13"
height="15"
alt={_t("Direct Chat")}
/>;
}
return (
<AccessibleButton className={classes} key={r.room.roomId} onClick={() => this._viewRoom(r.room)}
<AccessibleButton className={classes} key={r.room.roomId} onClick={() => this._viewRoom(r.room, i)}
onMouseEnter={() => this._onMouseEnter(r.room)} onMouseLeave={() => this._onMouseLeave(r.room)}>
<RoomAvatar room={r.room} width={32} height={32} />
{badge}
{dmIndicator}
{tooltip}
</AccessibleButton>
);
});
return (
<IndicatorScrollbar ref="scroller" className="mx_RoomBreadcrumbs" trackHorizontalOverflow={true}>
<IndicatorScrollbar ref="scroller" className="mx_RoomBreadcrumbs"
trackHorizontalOverflow={true} verticalScrollsHorizontally={true}>
{ avatars }
</IndicatorScrollbar>
);

View file

@ -68,12 +68,11 @@ module.exports = React.createClass({
},
_shouldShowNotifBadge: function() {
const showBadgeInStates = [RoomNotifs.ALL_MESSAGES, RoomNotifs.ALL_MESSAGES_LOUD];
return showBadgeInStates.indexOf(this.state.notifState) > -1;
return RoomNotifs.BADGE_STATES.includes(this.state.notifState);
},
_shouldShowMentionBadge: function() {
return this.state.notifState !== RoomNotifs.MUTE;
return RoomNotifs.MENTION_BADGE_STATES.includes(this.state.notifState);
},
_isDirectMessageRoom: function(roomId) {

View file

@ -37,6 +37,8 @@ const STICKERPICKER_Z_INDEX = 3500;
const PERSISTED_ELEMENT_KEY = "stickerPicker";
export default class Stickerpicker extends React.Component {
static currentWidget;
constructor(props) {
super(props);
this._onShowStickersClick = this._onShowStickersClick.bind(this);
@ -130,8 +132,13 @@ export default class Stickerpicker extends React.Component {
_updateWidget() {
const stickerpickerWidget = WidgetUtils.getStickerpickerWidgets()[0];
if (!stickerpickerWidget) {
Stickerpicker.currentWidget = null;
this.setState({stickerpickerWidget: null, widgetId: null});
return;
}
const currentWidget = this.state.stickerpickerWidget;
const currentWidget = Stickerpicker.currentWidget;
let currentUrl = null;
if (currentWidget && currentWidget.content && currentWidget.content.url) {
currentUrl = currentWidget.content.url;
@ -147,6 +154,7 @@ export default class Stickerpicker extends React.Component {
PersistedElement.destroyElement(PERSISTED_ELEMENT_KEY);
}
Stickerpicker.currentWidget = stickerpickerWidget;
this.setState({
stickerpickerWidget,
widgetId: stickerpickerWidget ? stickerpickerWidget.id : null,