diff --git a/package.json b/package.json index 8cda349e03..5999935517 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "flux": "2.1.1", "focus-visible": "^5.0.2", "fuse.js": "^2.2.0", - "gemini-scrollbar": "github:matrix-org/gemini-scrollbar#91e1e566", "gfm.css": "^1.1.1", "glob-to-regexp": "^0.4.1", "highlight.js": "^9.15.8", @@ -93,7 +92,6 @@ "react-beautiful-dnd": "^4.0.1", "react-dom": "^16.9.0", "react-focus-lock": "^2.2.1", - "react-gemini-scrollbar": "github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594", "resize-observer-polyfill": "^1.5.0", "sanitize-html": "^1.18.4", "text-encoding-utf-8": "^1.0.1", diff --git a/res/css/_common.scss b/res/css/_common.scss index a4ef603242..ad64aced50 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -207,37 +207,6 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { transition: opacity 0.2s ease-in-out; } -/* XXX: critical hack to GeminiScrollbar to allow them to work in FF 42 and Chrome 48. - Stop the scrollbar view from pushing out the container's overall sizing, which causes - flexbox to adapt to the new size and cause the view to keep growing. - */ -.gm-scrollbar-container .gm-scroll-view { - position: absolute; -} - -/* Expand thumbs on hoverover */ -.gm-scrollbar { - border-radius: 5px !important; -} -.gm-scrollbar.-vertical { - width: 6px; - transition: width 120ms ease-out !important; -} -.gm-scrollbar.-vertical:hover, -.gm-scrollbar.-vertical:active { - width: 8px; - transition: width 120ms ease-out !important; -} -.gm-scrollbar.-horizontal { - height: 6px; - transition: height 120ms ease-out !important; -} -.gm-scrollbar.-horizontal:hover, -.gm-scrollbar.-horizontal:active { - height: 8px; - transition: height 120ms ease-out !important; -} - // These are magic constants which are excluded from tinting, to let themes // (which only have CSS, unlike skins) tell the app what their non-tinted // colourscheme is by inspecting the stylesheet DOM. diff --git a/res/css/_components.scss b/res/css/_components.scss index bc636eb3c6..68322b9660 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -177,7 +177,6 @@ @import "./views/rooms/_RoomTile.scss"; @import "./views/rooms/_RoomUpgradeWarningBar.scss"; @import "./views/rooms/_SearchBar.scss"; -@import "./views/rooms/_SearchableEntityList.scss"; @import "./views/rooms/_SendMessageComposer.scss"; @import "./views/rooms/_Stickers.scss"; @import "./views/rooms/_TopUnreadMessagesBar.scss"; diff --git a/res/css/structures/_GroupView.scss b/res/css/structures/_GroupView.scss index 517b8b1922..2575169664 100644 --- a/res/css/structures/_GroupView.scss +++ b/res/css/structures/_GroupView.scss @@ -180,10 +180,6 @@ limitations under the License. line-height: 2em; } -.mx_GroupView > .mx_MainSplit { - flex: 1; -} - .mx_GroupView_body { flex-grow: 1; } @@ -341,8 +337,8 @@ limitations under the License. display: none; } -.mx_GroupView_body .gm-scroll-view > * { - margin: 11px 50px 0px 68px; +.mx_GroupView_body .mx_AutoHideScrollbar_offset > * { + margin: 11px 50px 50px 68px; } .mx_GroupView_groupDesc textarea { @@ -370,7 +366,7 @@ limitations under the License. padding: 40px 20px; } -.mx_GroupView .mx_MemberInfo .gm-scroll-view > :not(.mx_MemberInfo_avatar) { +.mx_GroupView .mx_MemberInfo .mx_AutoHideScrollbar_offset > :not(.mx_MemberInfo_avatar) { padding-left: 16px; padding-right: 16px; } diff --git a/res/css/structures/_MainSplit.scss b/res/css/structures/_MainSplit.scss index 4d73953cd7..25e1153fce 100644 --- a/res/css/structures/_MainSplit.scss +++ b/res/css/structures/_MainSplit.scss @@ -18,6 +18,7 @@ limitations under the License. display: flex; flex-direction: row; min-width: 0; + height: 100%; } // move hit area 5px to the right so it doesn't overlap with the timeline scrollbar diff --git a/res/css/structures/_MatrixChat.scss b/res/css/structures/_MatrixChat.scss index f2ce7e1d5c..c5a5d50068 100644 --- a/res/css/structures/_MatrixChat.scss +++ b/res/css/structures/_MatrixChat.scss @@ -76,13 +76,6 @@ limitations under the License. flex: 1 1 0; min-width: 0; - /* Experimental fix for https://github.com/vector-im/vector-web/issues/947 - and https://github.com/vector-im/vector-web/issues/946. - Empirically this stops the MessagePanel's width exploding outwards when - gemini is in 'prevented' mode - */ - overflow-x: auto; - /* To fix https://github.com/vector-im/riot-web/issues/3298 where Safari needed height 100% all the way down to the HomePage. Height does not have to be auto, empirically. diff --git a/res/css/structures/_MyGroups.scss b/res/css/structures/_MyGroups.scss index d25789ab94..36150c33a5 100644 --- a/res/css/structures/_MyGroups.scss +++ b/res/css/structures/_MyGroups.scss @@ -67,9 +67,6 @@ limitations under the License. } } - - - .mx_MyGroups_headerCard_header { font-weight: bold; margin-bottom: 10px; @@ -98,6 +95,11 @@ limitations under the License. display: flex; flex-direction: column; + overflow-y: auto; +} + +.mx_MyGroups_scrollable { + overflow-y: inherit; } .mx_MyGroups_placeholder { diff --git a/res/css/structures/_TagPanel.scss b/res/css/structures/_TagPanel.scss index dddd2e324c..03f5ce230c 100644 --- a/res/css/structures/_TagPanel.scss +++ b/res/css/structures/_TagPanel.scss @@ -23,6 +23,7 @@ limitations under the License. flex-direction: column; align-items: center; justify-content: space-between; + height: 100%; } .mx_TagPanel_items_selected { @@ -57,6 +58,7 @@ limitations under the License. .mx_TagPanel .mx_TagPanel_scroller { flex-grow: 1; + width: 100%; } .mx_TagPanel .mx_TagPanel_tagTileContainer { diff --git a/res/css/views/dialogs/_UnknownDeviceDialog.scss b/res/css/views/dialogs/_UnknownDeviceDialog.scss index 02e0fb1fe5..2b0f8dceca 100644 --- a/res/css/views/dialogs/_UnknownDeviceDialog.scss +++ b/res/css/views/dialogs/_UnknownDeviceDialog.scss @@ -14,14 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -// CSS voodoo to support a gemini-scrollbar for the contents of the dialog -.mx_Dialog_unknownDevice .mx_Dialog { - // ideally we'd shrink the height to fit when needed, but in practice this - // is a pain in the ass. plus might as well make the dialog big given how - // important it is. - height: 100%; -} - .mx_UnknownDeviceDialog { height: 100%; display: flex; @@ -44,6 +36,7 @@ limitations under the License. .mx_UnknownDeviceDialog .mx_Dialog_content { margin-bottom: 24px; + overflow-y: scroll; } .mx_UnknownDeviceDialog_deviceList > li { diff --git a/res/css/views/rooms/_SearchableEntityList.scss b/res/css/views/rooms/_SearchableEntityList.scss deleted file mode 100644 index 37a663123d..0000000000 --- a/res/css/views/rooms/_SearchableEntityList.scss +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2016 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_SearchableEntityList { - display: flex; - - flex-direction: column; -} - -.mx_SearchableEntityList_query { - font-family: $font-family; - border-radius: 3px; - border: 1px solid $input-border-color; - padding: 9px; - color: $primary-fg-color; - background-color: $primary-bg-color; - margin-left: 3px; - font-size: 15px; - margin-bottom: 8px; - width: 189px; -} - -.mx_SearchableEntityList_query::-moz-placeholder { - color: $primary-fg-color; - opacity: 0.5; - font-size: 12px; -} - -.mx_SearchableEntityList_query::-webkit-input-placeholder { - color: $primary-fg-color; - opacity: 0.5; - font-size: 12px; -} - -.mx_SearchableEntityList_listWrapper { - flex: 1; - - overflow-y: auto; -} - -.mx_SearchableEntityList_list { - display: table; - table-layout: fixed; - width: 100%; -} - -.mx_SearchableEntityList_list .mx_EntityTile_chevron { - display: none; -} - -.mx_SearchableEntityList_hrWrapper { - width: 100%; - flex: 0 0 auto; -} - -.mx_SearchableEntityList hr { - height: 1px; - border: 0px; - color: $primary-fg-color; - background-color: $primary-fg-color; - margin-right: 15px; - margin-top: 11px; - margin-bottom: 11px; -} diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index a3515a9d99..33670c39bf 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -219,10 +219,6 @@ $user-tile-hover-bg-color: $header-panel-bg-color; filter: invert(1); } -.gm-scrollbar .thumb { - filter: invert(1); -} - // markdown overrides: .mx_EventTile_content .markdown-body pre:hover { border-color: #808080 !important; // inverted due to rules below diff --git a/src/components/structures/EmbeddedPage.js b/src/components/structures/EmbeddedPage.js index 6d734c3838..f854dc955f 100644 --- a/src/components/structures/EmbeddedPage.js +++ b/src/components/structures/EmbeddedPage.js @@ -23,11 +23,11 @@ import PropTypes from 'prop-types'; import request from 'browser-request'; import { _t } from '../../languageHandler'; import sanitizeHtml from 'sanitize-html'; -import * as sdk from '../../index'; import dis from '../../dispatcher'; import {MatrixClientPeg} from '../../MatrixClientPeg'; import classnames from 'classnames'; import MatrixClientContext from "../../contexts/MatrixClientContext"; +import AutoHideScrollbar from "./AutoHideScrollbar"; export default class EmbeddedPage extends React.PureComponent { static propTypes = { @@ -117,10 +117,9 @@ export default class EmbeddedPage extends React.PureComponent { ; if (this.props.scrollbar) { - const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); - return + return {content} - ; + ; } else { return
{content} diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index af90fbbe83..cadc511fc3 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -39,6 +39,7 @@ import {makeGroupPermalink, makeUserPermalink} from "../../utils/permalinks/Perm import {Group} from "matrix-js-sdk"; import {allSettled, sleep} from "../../utils/promise"; import RightPanelStore from "../../stores/RightPanelStore"; +import AutoHideScrollbar from "./AutoHideScrollbar"; const LONG_DESC_PLACEHOLDER = _td( `

HTML for your community's page

@@ -1173,7 +1174,6 @@ export default createReactClass({ render: function() { const GroupAvatar = sdk.getComponent("avatars.GroupAvatar"); const Spinner = sdk.getComponent("elements.Spinner"); - const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); if (this.state.summaryLoading && this.state.error === null || this.state.saving) { return ; @@ -1332,10 +1332,10 @@ export default createReactClass({
- + { this._getMembershipSection() } { this._getGroupSection() } - + ); diff --git a/src/components/structures/MyGroups.js b/src/components/structures/MyGroups.js index b26ab5ff70..f1209b7b9e 100644 --- a/src/components/structures/MyGroups.js +++ b/src/components/structures/MyGroups.js @@ -22,6 +22,7 @@ import { _t } from '../../languageHandler'; import dis from '../../dispatcher'; import AccessibleButton from '../views/elements/AccessibleButton'; import MatrixClientContext from "../../contexts/MatrixClientContext"; +import AutoHideScrollbar from "./AutoHideScrollbar"; export default createReactClass({ displayName: 'MyGroups', @@ -62,8 +63,6 @@ export default createReactClass({ const Loader = sdk.getComponent("elements.Spinner"); const SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader'); const GroupTile = sdk.getComponent("groups.GroupTile"); - const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); - let content; let contentHeader; @@ -74,7 +73,7 @@ export default createReactClass({ }); contentHeader = groupNodes.length > 0 ?

{ _t('Your Communities') }

:
; content = groupNodes.length > 0 ? - +

{ _t( @@ -93,7 +92,7 @@ export default createReactClass({

{ groupNodes }
- : + :
{ _t( "You're not currently a member of any communities.", diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 36e30343e4..17a496b037 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -405,21 +405,6 @@ export default createReactClass({ this.onResize(); document.addEventListener("keydown", this.onKeyDown); - - // XXX: EVIL HACK to autofocus inviting on empty rooms. - // We use the setTimeout to avoid racing with focus_composer. - if (this.state.room && - this.state.room.getJoinedMemberCount() == 1 && - this.state.room.getLiveTimeline() && - this.state.room.getLiveTimeline().getEvents() && - this.state.room.getLiveTimeline().getEvents().length <= 6) { - const inviteBox = document.getElementById("mx_SearchableEntityList_query"); - setTimeout(function() { - if (inviteBox) { - inviteBox.focus(); - } - }, 50); - } }, shouldComponentUpdate: function(nextProps, nextState) { diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index b81b3ebede..c218fee5d6 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -782,7 +782,7 @@ export default createReactClass({ if (!this._divScroll) { // Likewise, we should have the ref by this point, but if not // turn the NPE into something meaningful. - throw new Error("ScrollPanel._getScrollNode called before gemini ref collected"); + throw new Error("ScrollPanel._getScrollNode called before AutoHideScrollbar ref collected"); } return this._divScroll; diff --git a/src/components/structures/TagPanel.js b/src/components/structures/TagPanel.js index 622e63d8ce..f1a39d6fcf 100644 --- a/src/components/structures/TagPanel.js +++ b/src/components/structures/TagPanel.js @@ -28,6 +28,7 @@ import { _t } from '../../languageHandler'; import { Droppable } from 'react-beautiful-dnd'; import classNames from 'classnames'; import MatrixClientContext from "../../contexts/MatrixClientContext"; +import AutoHideScrollbar from "./AutoHideScrollbar"; const TagPanel = createReactClass({ displayName: 'TagPanel', @@ -106,7 +107,6 @@ const TagPanel = createReactClass({ const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const ActionButton = sdk.getComponent('elements.ActionButton'); const TintableSvg = sdk.getComponent('elements.TintableSvg'); - const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); const tags = this.state.orderedTags.map((tag, index) => { return
- ) } - +
; }, }); diff --git a/src/components/views/dialogs/UnknownDeviceDialog.js b/src/components/views/dialogs/UnknownDeviceDialog.js index d58961f964..69ebb72a6f 100644 --- a/src/components/views/dialogs/UnknownDeviceDialog.js +++ b/src/components/views/dialogs/UnknownDeviceDialog.js @@ -122,7 +122,6 @@ export default createReactClass({ }, render: function() { - const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); if (this.props.devices === null) { const Spinner = sdk.getComponent("elements.Spinner"); return ; @@ -168,7 +167,7 @@ export default createReactClass({ title={_t('Room contains unknown sessions')} contentId='mx_Dialog_content' > - +

{ _t('"%(RoomName)s" contains sessions that you haven\'t seen before.', {RoomName: this.props.room.name}) }

@@ -176,7 +175,7 @@ export default createReactClass({ { _t("Unknown sessions") }: - +
diff --git a/src/components/views/elements/GeminiScrollbarWrapper.js b/src/components/views/elements/GeminiScrollbarWrapper.js deleted file mode 100644 index 13eb14ecc3..0000000000 --- a/src/components/views/elements/GeminiScrollbarWrapper.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2018 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. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import GeminiScrollbar from 'react-gemini-scrollbar'; - -function GeminiScrollbarWrapper(props) { - const {wrappedRef, ...wrappedProps} = props; - - // Enable forceGemini so that gemini is always enabled. This is - // to avoid future issues where a feature is implemented without - // doing QA on every OS/browser combination. - // - // By default GeminiScrollbar allows native scrollbars to be used - // on macOS. Use forceGemini to enable Gemini's non-native - // scrollbars on all OSs. - return - { props.children } - ; -} -export default GeminiScrollbarWrapper; - diff --git a/src/components/views/groups/GroupMemberInfo.js b/src/components/views/groups/GroupMemberInfo.js index e659352b74..f70c769ad7 100644 --- a/src/components/views/groups/GroupMemberInfo.js +++ b/src/components/views/groups/GroupMemberInfo.js @@ -27,6 +27,7 @@ import { GroupMemberType } from '../../../groups'; import GroupStore from '../../../stores/GroupStore'; import AccessibleButton from '../elements/AccessibleButton'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; +import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; export default createReactClass({ displayName: 'GroupMemberInfo', @@ -182,10 +183,9 @@ export default createReactClass({ this.props.groupMember.displayname || this.props.groupMember.userId ); - const GeminiScrollbarWrapper = sdk.getComponent('elements.GeminiScrollbarWrapper'); return (
- + @@ -199,7 +199,7 @@ export default createReactClass({
{ adminTools } -
+
); }, diff --git a/src/components/views/groups/GroupMemberList.js b/src/components/views/groups/GroupMemberList.js index 05af70b266..2853e70afa 100644 --- a/src/components/views/groups/GroupMemberList.js +++ b/src/components/views/groups/GroupMemberList.js @@ -26,6 +26,7 @@ import { showGroupInviteDialog } from '../../../GroupAddressPicker'; import AccessibleButton from '../elements/AccessibleButton'; import TintableSvg from '../elements/TintableSvg'; import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases"; +import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; const INITIAL_LOAD_NUM_MEMBERS = 30; @@ -172,7 +173,6 @@ export default createReactClass({ }, render: function() { - const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); if (this.state.fetching || this.state.fetchingInvitedMembers) { const Spinner = sdk.getComponent("elements.Spinner"); return (
@@ -225,10 +225,10 @@ export default createReactClass({ return (
{ inviteButton } - + { joined } { invited } - + { inputBox }
); diff --git a/src/components/views/groups/GroupRoomInfo.js b/src/components/views/groups/GroupRoomInfo.js index 7b9f43f15f..91d84be4d1 100644 --- a/src/components/views/groups/GroupRoomInfo.js +++ b/src/components/views/groups/GroupRoomInfo.js @@ -24,6 +24,7 @@ import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import GroupStore from '../../../stores/GroupStore'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; +import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; export default createReactClass({ displayName: 'GroupRoomInfo', @@ -153,7 +154,6 @@ export default createReactClass({ render: function() { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const InlineSpinner = sdk.getComponent('elements.InlineSpinner'); - const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); if (this.state.groupRoomRemoveLoading || !this.state.groupRoom) { const Spinner = sdk.getComponent("elements.Spinner"); return
@@ -216,7 +216,7 @@ export default createReactClass({ const groupRoomName = this.state.groupRoom.displayname; return (
- + @@ -231,7 +231,7 @@ export default createReactClass({
{ adminTools } - +
); }, diff --git a/src/components/views/groups/GroupRoomList.js b/src/components/views/groups/GroupRoomList.js index 5fd8c9f31d..dee304e1f6 100644 --- a/src/components/views/groups/GroupRoomList.js +++ b/src/components/views/groups/GroupRoomList.js @@ -22,6 +22,7 @@ import PropTypes from 'prop-types'; import { showGroupAddRoomDialog } from '../../../GroupAddressPicker'; import AccessibleButton from '../elements/AccessibleButton'; import TintableSvg from '../elements/TintableSvg'; +import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; const INITIAL_LOAD_NUM_ROOMS = 30; @@ -150,17 +151,16 @@ export default createReactClass({ placeholder={_t('Filter community rooms')} autoComplete="off" /> ); - const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); const TruncatedList = sdk.getComponent("elements.TruncatedList"); return (
{ inviteButton } - + { this.makeGroupRoomTiles(this.state.searchQuery) } - + { inputBox }
); diff --git a/src/components/views/rooms/SearchableEntityList.js b/src/components/views/rooms/SearchableEntityList.js deleted file mode 100644 index 807ddbf729..0000000000 --- a/src/components/views/rooms/SearchableEntityList.js +++ /dev/null @@ -1,186 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import PropTypes from 'prop-types'; -import createReactClass from 'create-react-class'; -import * as sdk from "../../../index"; -import { _t } from '../../../languageHandler'; - -// A list capable of displaying entities which conform to the SearchableEntity -// interface which is an object containing getJsx(): Jsx and matches(query: string): boolean -const SearchableEntityList = createReactClass({ - displayName: 'SearchableEntityList', - - propTypes: { - emptyQueryShowsAll: PropTypes.bool, - showInputBox: PropTypes.bool, - onQueryChanged: PropTypes.func, // fn(inputText) - onSubmit: PropTypes.func, // fn(inputText) - entities: PropTypes.array, - truncateAt: PropTypes.number, - }, - - getDefaultProps: function() { - return { - showInputBox: true, - entities: [], - emptyQueryShowsAll: false, - onSubmit: function() {}, - onQueryChanged: function(input) {}, - }; - }, - - getInitialState: function() { - return { - query: "", - focused: false, - truncateAt: this.props.truncateAt, - results: this.getSearchResults("", this.props.entities), - }; - }, - - componentWillReceiveProps: function(newProps) { - // recalculate the search results in case we got new entities - this.setState({ - results: this.getSearchResults(this.state.query, newProps.entities), - }); - }, - - componentWillUnmount: function() { - // pretend the query box was blanked out else filters could still be - // applied to other components which rely on onQueryChanged. - this.props.onQueryChanged(""); - }, - - /** - * Public-facing method to set the input query text to the given input. - * @param {string} input - */ - setQuery: function(input) { - this.setState({ - query: input, - results: this.getSearchResults(input, this.props.entities), - }); - }, - - onQueryChanged: function(ev) { - const q = ev.target.value; - this.setState({ - query: q, - // reset truncation if they back out the entire text - truncateAt: (q.length === 0 ? this.props.truncateAt : this.state.truncateAt), - results: this.getSearchResults(q, this.props.entities), - }, () => { - // invoke the callback AFTER we've flushed the new state. We need to - // do this because onQueryChanged can result in new props being passed - // to this component, which will then try to recalculate the search - // list. If we do this without flushing, we'll recalc with the last - // search term and not the current one! - this.props.onQueryChanged(q); - }); - }, - - onQuerySubmit: function(ev) { - ev.preventDefault(); - this.props.onSubmit(this.state.query); - }, - - getSearchResults: function(query, entities) { - if (!query || query.length === 0) { - return this.props.emptyQueryShowsAll ? entities : []; - } - return entities.filter(function(e) { - return e.matches(query); - }); - }, - - _showAll: function() { - this.setState({ - truncateAt: -1, - }); - }, - - _createOverflowEntity: function(overflowCount, totalCount) { - const EntityTile = sdk.getComponent("rooms.EntityTile"); - const BaseAvatar = sdk.getComponent("avatars.BaseAvatar"); - const text = _t("and %(count)s others...", { count: overflowCount }); - return ( - - } name={text} presenceState="online" suppressOnHover={true} - onClick={this._showAll} /> - ); - }, - - render: function() { - let inputBox; - - if (this.props.showInputBox) { - inputBox = ( -
- { this.setState({ focused: true }); }} - onBlur= {() => { this.setState({ focused: false }); }} - placeholder={_t("Search")} /> -
- ); - } - - let list; - if (this.state.results.length > 1 || this.state.focused) { - if (this.props.truncateAt) { // caller wants list truncated - const TruncatedList = sdk.getComponent("elements.TruncatedList"); - list = ( - - { this.state.results.map((entity) => { - return entity.getJsx(); - }) } - - ); - } else { - list = ( -
- { this.state.results.map((entity) => { - return entity.getJsx(); - }) } -
- ); - } - const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); - list = ( - - { list } - - ); - } - - return ( -
- { inputBox } - { list } - { list ?

: '' } -
- ); - }, -}); - -export default SearchableEntityList; diff --git a/yarn.lock b/yarn.lock index ac511949ce..744cfbc563 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3902,10 +3902,6 @@ fuse.js@^2.2.0: resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-2.7.4.tgz#96e420fde7ef011ac49c258a621314fe576536f9" integrity sha1-luQg/efvARrEnCWKYhMU/ldlNvk= -"gemini-scrollbar@github:matrix-org/gemini-scrollbar#91e1e566", gemini-scrollbar@matrix-org/gemini-scrollbar#91e1e566: - version "1.4.3" - resolved "https://codeload.github.com/matrix-org/gemini-scrollbar/tar.gz/91e1e566fa33324188f278801baf4a79f9f554ab" - gensync@^1.0.0-beta.1: version "1.0.0-beta.1" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" @@ -6963,12 +6959,6 @@ react-focus-lock@^2.2.1: use-callback-ref "^1.2.1" use-sidecar "^1.0.1" -"react-gemini-scrollbar@github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594": - version "2.1.5" - resolved "https://codeload.github.com/matrix-org/react-gemini-scrollbar/tar.gz/9cf17f63b7c0b0ec5f31df27da0f82f7238dc594" - dependencies: - gemini-scrollbar matrix-org/gemini-scrollbar#91e1e566 - react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: version "16.13.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527"