Merge pull request #1810 from matrix-org/luke/force-gemini

Wrap GeminiScrollbar in a component, enabled forceGemini
This commit is contained in:
Luke Barnard 2018-03-27 17:29:00 +01:00 committed by GitHub
commit d3e2c4c561
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 100 additions and 47 deletions

View file

@ -31,7 +31,6 @@ import GroupStoreCache from '../../stores/GroupStoreCache';
import GroupStore from '../../stores/GroupStore'; import GroupStore from '../../stores/GroupStore';
import FlairStore from '../../stores/FlairStore'; import FlairStore from '../../stores/FlairStore';
import { showGroupAddRoomDialog } from '../../GroupAddressPicker'; import { showGroupAddRoomDialog } from '../../GroupAddressPicker';
import GeminiScrollbar from 'react-gemini-scrollbar';
import {makeGroupPermalink, makeUserPermalink} from "../../matrix-to"; import {makeGroupPermalink, makeUserPermalink} from "../../matrix-to";
const LONG_DESC_PLACEHOLDER = _td( const LONG_DESC_PLACEHOLDER = _td(
@ -969,6 +968,7 @@ export default React.createClass({
const GroupAvatar = sdk.getComponent("avatars.GroupAvatar"); const GroupAvatar = sdk.getComponent("avatars.GroupAvatar");
const Spinner = sdk.getComponent("elements.Spinner"); const Spinner = sdk.getComponent("elements.Spinner");
const TintableSvg = sdk.getComponent("elements.TintableSvg"); const TintableSvg = sdk.getComponent("elements.TintableSvg");
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
if (this.state.summaryLoading && this.state.error === null || this.state.saving) { if (this.state.summaryLoading && this.state.error === null || this.state.saving) {
return <Spinner />; return <Spinner />;
@ -1119,9 +1119,9 @@ export default React.createClass({
{ rightButtons } { rightButtons }
</div> </div>
</div> </div>
<GeminiScrollbar className="mx_GroupView_body"> <GeminiScrollbarWrapper className="mx_GroupView_body">
{ bodyNodes } { bodyNodes }
</GeminiScrollbar> </GeminiScrollbarWrapper>
</div> </div>
); );
} else if (this.state.error) { } else if (this.state.error) {

View file

@ -16,7 +16,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import GeminiScrollbar from 'react-gemini-scrollbar';
import sdk from '../../index'; import sdk from '../../index';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
@ -63,6 +62,8 @@ export default withMatrixClient(React.createClass({
const SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader'); const SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
const TintableSvg = sdk.getComponent("elements.TintableSvg"); const TintableSvg = sdk.getComponent("elements.TintableSvg");
const GroupTile = sdk.getComponent("groups.GroupTile"); const GroupTile = sdk.getComponent("groups.GroupTile");
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
let content; let content;
let contentHeader; let contentHeader;
@ -73,7 +74,7 @@ export default withMatrixClient(React.createClass({
}); });
contentHeader = groupNodes.length > 0 ? <h3>{ _t('Your Communities') }</h3> : <div />; contentHeader = groupNodes.length > 0 ? <h3>{ _t('Your Communities') }</h3> : <div />;
content = groupNodes.length > 0 ? content = groupNodes.length > 0 ?
<GeminiScrollbar> <GeminiScrollbarWrapper>
<div className="mx_MyGroups_microcopy"> <div className="mx_MyGroups_microcopy">
<p> <p>
{ _t( { _t(
@ -92,7 +93,7 @@ export default withMatrixClient(React.createClass({
<div className="mx_MyGroups_joinedGroups"> <div className="mx_MyGroups_joinedGroups">
{ groupNodes } { groupNodes }
</div> </div>
</GeminiScrollbar> : </GeminiScrollbarWrapper> :
<div className="mx_MyGroups_placeholder"> <div className="mx_MyGroups_placeholder">
{ _t( { _t(
"You're not currently a member of any communities.", "You're not currently a member of any communities.",

View file

@ -17,9 +17,9 @@ limitations under the License.
const React = require("react"); const React = require("react");
const ReactDOM = require("react-dom"); const ReactDOM = require("react-dom");
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const GeminiScrollbar = require('react-gemini-scrollbar');
import Promise from 'bluebird'; import Promise from 'bluebird';
import { KeyCode } from '../../Keyboard'; import { KeyCode } from '../../Keyboard';
import sdk from '../../index.js';
const DEBUG_SCROLL = false; const DEBUG_SCROLL = false;
// var DEBUG_SCROLL = true; // var DEBUG_SCROLL = true;
@ -224,7 +224,7 @@ module.exports = React.createClass({
onResize: function() { onResize: function() {
this.props.onResize(); this.props.onResize();
this.checkScroll(); this.checkScroll();
this.refs.geminiPanel.forceUpdate(); if (this._gemScroll) this._gemScroll.forceUpdate();
}, },
// after an update to the contents of the panel, check that the scroll is // after an update to the contents of the panel, check that the scroll is
@ -665,14 +665,25 @@ module.exports = React.createClass({
throw new Error("ScrollPanel._getScrollNode called when unmounted"); throw new Error("ScrollPanel._getScrollNode called when unmounted");
} }
return this.refs.geminiPanel.scrollbar.getViewElement(); if (!this._gemScroll) {
// 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");
}
return this._gemScroll.scrollbar.getViewElement();
},
_collectGeminiScroll: function(gemScroll) {
this._gemScroll = gemScroll;
}, },
render: function() { render: function() {
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
// TODO: the classnames on the div and ol could do with being updated to // TODO: the classnames on the div and ol could do with being updated to
// reflect the fact that we don't necessarily contain a list of messages. // reflect the fact that we don't necessarily contain a list of messages.
// it's not obvious why we have a separate div and ol anyway. // it's not obvious why we have a separate div and ol anyway.
return (<GeminiScrollbar autoshow={true} ref="geminiPanel" return (<GeminiScrollbarWrapper autoshow={true} wrappedRef={this._collectGeminiScroll}
onScroll={this.onScroll} onResize={this.onResize} onScroll={this.onScroll} onResize={this.onResize}
className={this.props.className} style={this.props.style}> className={this.props.className} style={this.props.style}>
<div className="mx_RoomView_messageListWrapper"> <div className="mx_RoomView_messageListWrapper">
@ -680,7 +691,7 @@ module.exports = React.createClass({
{ this.props.children } { this.props.children }
</ol> </ol>
</div> </div>
</GeminiScrollbar> </GeminiScrollbarWrapper>
); );
}, },
}); });

View file

@ -17,7 +17,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { MatrixClient } from 'matrix-js-sdk'; import { MatrixClient } from 'matrix-js-sdk';
import GeminiScrollbar from 'react-gemini-scrollbar';
import TagOrderStore from '../../stores/TagOrderStore'; import TagOrderStore from '../../stores/TagOrderStore';
import GroupActions from '../../actions/GroupActions'; import GroupActions from '../../actions/GroupActions';
@ -102,6 +101,8 @@ const TagPanel = React.createClass({
const DNDTagTile = sdk.getComponent('elements.DNDTagTile'); const DNDTagTile = sdk.getComponent('elements.DNDTagTile');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const TintableSvg = sdk.getComponent('elements.TintableSvg'); const TintableSvg = sdk.getComponent('elements.TintableSvg');
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
const tags = this.state.orderedTags.map((tag, index) => { const tags = this.state.orderedTags.map((tag, index) => {
return <DNDTagTile return <DNDTagTile
@ -124,7 +125,7 @@ const TagPanel = React.createClass({
{ clearButton } { clearButton }
</AccessibleButton> </AccessibleButton>
<div className="mx_TagPanel_divider" /> <div className="mx_TagPanel_divider" />
<GeminiScrollbar <GeminiScrollbarWrapper
className="mx_TagPanel_scroller" className="mx_TagPanel_scroller"
autoshow={true} autoshow={true}
// XXX: Use onMouseDown as a workaround for https://github.com/atlassian/react-beautiful-dnd/issues/273 // XXX: Use onMouseDown as a workaround for https://github.com/atlassian/react-beautiful-dnd/issues/273
@ -145,7 +146,7 @@ const TagPanel = React.createClass({
</div> </div>
) } ) }
</Droppable> </Droppable>
</GeminiScrollbar> </GeminiScrollbarWrapper>
<div className="mx_TagPanel_divider" /> <div className="mx_TagPanel_divider" />
<div className="mx_TagPanel_createGroupButton"> <div className="mx_TagPanel_createGroupButton">
<GroupsButton tooltip={true} /> <GroupsButton tooltip={true} />

View file

@ -30,7 +30,6 @@ import Promise from 'bluebird';
const packageJson = require('../../../package.json'); const packageJson = require('../../../package.json');
const UserSettingsStore = require('../../UserSettingsStore'); const UserSettingsStore = require('../../UserSettingsStore');
const CallMediaHandler = require('../../CallMediaHandler'); const CallMediaHandler = require('../../CallMediaHandler');
const GeminiScrollbar = require('react-gemini-scrollbar');
const Email = require('../../email'); const Email = require('../../email');
const AddThreepid = require('../../AddThreepid'); const AddThreepid = require('../../AddThreepid');
const SdkConfig = require('../../SdkConfig'); const SdkConfig = require('../../SdkConfig');
@ -1118,6 +1117,7 @@ module.exports = React.createClass({
const ChangeAvatar = sdk.getComponent('settings.ChangeAvatar'); const ChangeAvatar = sdk.getComponent('settings.ChangeAvatar');
const Notifications = sdk.getComponent("settings.Notifications"); const Notifications = sdk.getComponent("settings.Notifications");
const EditableText = sdk.getComponent('elements.EditableText'); const EditableText = sdk.getComponent('elements.EditableText');
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
const avatarUrl = ( const avatarUrl = (
this.state.avatarUrl ? MatrixClientPeg.get().mxcUrlToHttp(this.state.avatarUrl) : null this.state.avatarUrl ? MatrixClientPeg.get().mxcUrlToHttp(this.state.avatarUrl) : null
@ -1213,8 +1213,9 @@ module.exports = React.createClass({
onCancelClick={this.props.onClose} onCancelClick={this.props.onClose}
/> />
<GeminiScrollbar className="mx_UserSettings_body" <GeminiScrollbarWrapper
autoshow={true}> className="mx_UserSettings_body"
autoshow={true}>
<h3>{ _t("Profile") }</h3> <h3>{ _t("Profile") }</h3>
@ -1327,7 +1328,7 @@ module.exports = React.createClass({
{ this._renderDeactivateAccount() } { this._renderDeactivateAccount() }
</GeminiScrollbar> </GeminiScrollbarWrapper>
</div> </div>
); );
}, },

View file

@ -146,6 +146,7 @@ export default React.createClass({
}, },
render: function() { render: function() {
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
if (this.props.devices === null) { if (this.props.devices === null) {
const Spinner = sdk.getComponent("elements.Spinner"); const Spinner = sdk.getComponent("elements.Spinner");
return <Spinner />; return <Spinner />;
@ -191,7 +192,7 @@ export default React.createClass({
title={_t('Room contains unknown devices')} title={_t('Room contains unknown devices')}
contentId='mx_Dialog_content' contentId='mx_Dialog_content'
> >
<GeminiScrollbar autoshow={false} className="mx_Dialog_content" id='mx_Dialog_content'> <GeminiScrollbarWrapper autoshow={false} className="mx_Dialog_content" id='mx_Dialog_content'>
<h4> <h4>
{ _t('"%(RoomName)s" contains devices that you haven\'t seen before.', {RoomName: this.props.room.name}) } { _t('"%(RoomName)s" contains devices that you haven\'t seen before.', {RoomName: this.props.room.name}) }
</h4> </h4>
@ -199,7 +200,7 @@ export default React.createClass({
{ _t("Unknown devices") }: { _t("Unknown devices") }:
<UnknownDeviceList devices={this.props.devices} /> <UnknownDeviceList devices={this.props.devices} />
</GeminiScrollbar> </GeminiScrollbarWrapper>
<DialogButtons primaryButton={sendButtonLabel} <DialogButtons primaryButton={sendButtonLabel}
onPrimaryButtonClick={sendButtonOnClick} onPrimaryButtonClick={sendButtonOnClick}
onCancel={this._onDismissClicked} /> onCancel={this._onDismissClicked} />

View file

@ -0,0 +1,33 @@
/*
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) {
// 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 <GeminiScrollbar ref={props.wrappedRef} forceGemini={true} {...props}>
{ props.children }
</GeminiScrollbar>;
}
export default GeminiScrollbarWrapper;

View file

@ -25,7 +25,6 @@ import { _t } from '../../../languageHandler';
import { GroupMemberType } from '../../../groups'; import { GroupMemberType } from '../../../groups';
import GroupStoreCache from '../../../stores/GroupStoreCache'; import GroupStoreCache from '../../../stores/GroupStoreCache';
import AccessibleButton from '../elements/AccessibleButton'; import AccessibleButton from '../elements/AccessibleButton';
import GeminiScrollbar from 'react-gemini-scrollbar';
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'GroupMemberInfo', displayName: 'GroupMemberInfo',
@ -180,9 +179,10 @@ module.exports = React.createClass({
); );
const EmojiText = sdk.getComponent('elements.EmojiText'); const EmojiText = sdk.getComponent('elements.EmojiText');
const GeminiScrollbarWrapper = sdk.getComponent('elements.GeminiScrollbarWrapper');
return ( return (
<div className="mx_MemberInfo"> <div className="mx_MemberInfo">
<GeminiScrollbar autoshow={true}> <GeminiScrollbarWrapper autoshow={true}>
<AccessibleButton className="mx_MemberInfo_cancel"onClick={this._onCancel}> <AccessibleButton className="mx_MemberInfo_cancel"onClick={this._onCancel}>
<img src="img/cancel.svg" width="18" height="18" className="mx_filterFlipColor" /> <img src="img/cancel.svg" width="18" height="18" className="mx_filterFlipColor" />
</AccessibleButton> </AccessibleButton>
@ -199,7 +199,7 @@ module.exports = React.createClass({
</div> </div>
{ adminTools } { adminTools }
</GeminiScrollbar> </GeminiScrollbarWrapper>
</div> </div>
); );
}, },

View file

@ -18,7 +18,6 @@ import React from 'react';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import sdk from '../../../index'; import sdk from '../../../index';
import GroupStoreCache from '../../../stores/GroupStoreCache'; import GroupStoreCache from '../../../stores/GroupStoreCache';
import GeminiScrollbar from 'react-gemini-scrollbar';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const INITIAL_LOAD_NUM_MEMBERS = 30; const INITIAL_LOAD_NUM_MEMBERS = 30;
@ -134,6 +133,7 @@ export default React.createClass({
}, },
render: function() { render: function() {
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
if (this.state.fetching || this.state.fetchingInvitedMembers) { if (this.state.fetching || this.state.fetchingInvitedMembers) {
const Spinner = sdk.getComponent("elements.Spinner"); const Spinner = sdk.getComponent("elements.Spinner");
return (<div className="mx_MemberList"> return (<div className="mx_MemberList">
@ -162,10 +162,10 @@ export default React.createClass({
return ( return (
<div className="mx_MemberList"> <div className="mx_MemberList">
{ inputBox } { inputBox }
<GeminiScrollbar autoshow={true} className="mx_MemberList_outerWrapper"> <GeminiScrollbarWrapper autoshow={true} className="mx_MemberList_outerWrapper">
{ joined } { joined }
{ invited } { invited }
</GeminiScrollbar> </GeminiScrollbarWrapper>
</div> </div>
); );
}, },

View file

@ -22,7 +22,6 @@ import Modal from '../../../Modal';
import sdk from '../../../index'; import sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import GroupStoreCache from '../../../stores/GroupStoreCache'; import GroupStoreCache from '../../../stores/GroupStoreCache';
import GeminiScrollbar from 'react-gemini-scrollbar';
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'GroupRoomInfo', displayName: 'GroupRoomInfo',
@ -157,6 +156,7 @@ module.exports = React.createClass({
const EmojiText = sdk.getComponent('elements.EmojiText'); const EmojiText = sdk.getComponent('elements.EmojiText');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const InlineSpinner = sdk.getComponent('elements.InlineSpinner'); const InlineSpinner = sdk.getComponent('elements.InlineSpinner');
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
if (this.state.groupRoomRemoveLoading || !this.state.groupRoom) { if (this.state.groupRoomRemoveLoading || !this.state.groupRoom) {
const Spinner = sdk.getComponent("elements.Spinner"); const Spinner = sdk.getComponent("elements.Spinner");
return <div className="mx_MemberInfo"> return <div className="mx_MemberInfo">
@ -216,7 +216,7 @@ module.exports = React.createClass({
const avatar = <BaseAvatar name={groupRoomName} width={36} height={36} url={avatarUrl} />; const avatar = <BaseAvatar name={groupRoomName} width={36} height={36} url={avatarUrl} />;
return ( return (
<div className="mx_MemberInfo"> <div className="mx_MemberInfo">
<GeminiScrollbar autoshow={true}> <GeminiScrollbarWrapper autoshow={true}>
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this._onCancel}> <AccessibleButton className="mx_MemberInfo_cancel" onClick={this._onCancel}>
<img src="img/cancel.svg" width="18" height="18" className="mx_filterFlipColor" /> <img src="img/cancel.svg" width="18" height="18" className="mx_filterFlipColor" />
</AccessibleButton> </AccessibleButton>
@ -233,7 +233,7 @@ module.exports = React.createClass({
</div> </div>
{ adminTools } { adminTools }
</GeminiScrollbar> </GeminiScrollbarWrapper>
</div> </div>
); );
}, },

View file

@ -17,7 +17,6 @@ import React from 'react';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import sdk from '../../../index'; import sdk from '../../../index';
import GroupStoreCache from '../../../stores/GroupStoreCache'; import GroupStoreCache from '../../../stores/GroupStoreCache';
import GeminiScrollbar from 'react-gemini-scrollbar';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const INITIAL_LOAD_NUM_ROOMS = 30; const INITIAL_LOAD_NUM_ROOMS = 30;
@ -120,16 +119,17 @@ export default React.createClass({
</form> </form>
); );
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
const TruncatedList = sdk.getComponent("elements.TruncatedList"); const TruncatedList = sdk.getComponent("elements.TruncatedList");
return ( return (
<div className="mx_GroupRoomList"> <div className="mx_GroupRoomList">
{ inputBox } { inputBox }
<GeminiScrollbar autoshow={true} className="mx_GroupRoomList_joined mx_GroupRoomList_outerWrapper"> <GeminiScrollbarWrapper autoshow={true} className="mx_GroupRoomList_joined mx_GroupRoomList_outerWrapper">
<TruncatedList className="mx_GroupRoomList_wrapper" truncateAt={this.state.truncateAt} <TruncatedList className="mx_GroupRoomList_wrapper" truncateAt={this.state.truncateAt}
createOverflowElement={this._createOverflowTile}> createOverflowElement={this._createOverflowTile}>
{ this.makeGroupRoomTiles(this.state.searchQuery) } { this.makeGroupRoomTiles(this.state.searchQuery) }
</TruncatedList> </TruncatedList>
</GeminiScrollbar> </GeminiScrollbarWrapper>
</div> </div>
); );
}, },

View file

@ -39,7 +39,6 @@ import Unread from '../../../Unread';
import { findReadReceiptFromUserId } from '../../../utils/Receipt'; import { findReadReceiptFromUserId } from '../../../utils/Receipt';
import withMatrixClient from '../../../wrappers/withMatrixClient'; import withMatrixClient from '../../../wrappers/withMatrixClient';
import AccessibleButton from '../elements/AccessibleButton'; import AccessibleButton from '../elements/AccessibleButton';
import GeminiScrollbar from 'react-gemini-scrollbar';
import RoomViewStore from '../../../stores/RoomViewStore'; import RoomViewStore from '../../../stores/RoomViewStore';
import SdkConfig from '../../../SdkConfig'; import SdkConfig from '../../../SdkConfig';
@ -897,11 +896,12 @@ module.exports = withMatrixClient(React.createClass({
</div>; </div>;
} }
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
const EmojiText = sdk.getComponent('elements.EmojiText'); const EmojiText = sdk.getComponent('elements.EmojiText');
return ( return (
<div className="mx_MemberInfo"> <div className="mx_MemberInfo">
<GeminiScrollbar autoshow={true}> <GeminiScrollbarWrapper autoshow={true}>
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}> <img src="img/cancel.svg" width="18" height="18" /></AccessibleButton> <AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}> <img src="img/cancel.svg" width="18" height="18" /></AccessibleButton>
<div className="mx_MemberInfo_avatar"> <div className="mx_MemberInfo_avatar">
<MemberAvatar onClick={this.onMemberAvatarClick} member={this.props.member} width={48} height={48} /> <MemberAvatar onClick={this.onMemberAvatarClick} member={this.props.member} width={48} height={48} />
@ -925,7 +925,7 @@ module.exports = withMatrixClient(React.createClass({
{ this._renderDevices() } { this._renderDevices() }
{ spinner } { spinner }
</GeminiScrollbar> </GeminiScrollbarWrapper>
</div> </div>
); );
}, },

View file

@ -21,7 +21,6 @@ import { _t } from '../../../languageHandler';
import SdkConfig from '../../../SdkConfig'; import SdkConfig from '../../../SdkConfig';
const MatrixClientPeg = require("../../../MatrixClientPeg"); const MatrixClientPeg = require("../../../MatrixClientPeg");
const sdk = require('../../../index'); const sdk = require('../../../index');
const GeminiScrollbar = require('react-gemini-scrollbar');
const rate_limited_func = require('../../../ratelimitedfunc'); const rate_limited_func = require('../../../ratelimitedfunc');
const CallHandler = require("../../../CallHandler"); const CallHandler = require("../../../CallHandler");
@ -395,6 +394,7 @@ module.exports = React.createClass({
render: function() { render: function() {
const TruncatedList = sdk.getComponent("elements.TruncatedList"); const TruncatedList = sdk.getComponent("elements.TruncatedList");
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
let invitedSection = null; let invitedSection = null;
if (this._getChildCountInvited() > 0) { if (this._getChildCountInvited() > 0) {
@ -423,14 +423,14 @@ module.exports = React.createClass({
return ( return (
<div className="mx_MemberList"> <div className="mx_MemberList">
{ inputBox } { inputBox }
<GeminiScrollbar autoshow={true} className="mx_MemberList_joined mx_MemberList_outerWrapper"> <GeminiScrollbarWrapper autoshow={true} className="mx_MemberList_joined mx_MemberList_outerWrapper">
<TruncatedList className="mx_MemberList_wrapper" truncateAt={this.state.truncateAtJoined} <TruncatedList className="mx_MemberList_wrapper" truncateAt={this.state.truncateAtJoined}
createOverflowElement={this._createOverflowTileJoined} createOverflowElement={this._createOverflowTileJoined}
getChildren={this._getChildrenJoined} getChildren={this._getChildrenJoined}
getChildCount={this._getChildCountJoined} getChildCount={this._getChildCountJoined}
/> />
{ invitedSection } { invitedSection }
</GeminiScrollbar> </GeminiScrollbarWrapper>
</div> </div>
); );
}, },

View file

@ -20,7 +20,6 @@ const React = require("react");
const ReactDOM = require("react-dom"); const ReactDOM = require("react-dom");
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
const GeminiScrollbar = require('react-gemini-scrollbar');
const MatrixClientPeg = require("../../../MatrixClientPeg"); const MatrixClientPeg = require("../../../MatrixClientPeg");
const CallHandler = require('../../../CallHandler'); const CallHandler = require('../../../CallHandler');
const dis = require("../../../dispatcher"); const dis = require("../../../dispatcher");
@ -508,7 +507,8 @@ module.exports = React.createClass({
onShowMoreRooms: function() { onShowMoreRooms: function() {
// kick gemini in the balls to get it to wake up // kick gemini in the balls to get it to wake up
// XXX: uuuuuuugh. // XXX: uuuuuuugh.
this.refs.gemscroll.forceUpdate(); if (!this._gemScroll) return;
this._gemScroll.forceUpdate();
}, },
_getEmptyContent: function(section) { _getEmptyContent: function(section) {
@ -599,13 +599,18 @@ module.exports = React.createClass({
return ret; return ret;
}, },
_collectGemini(gemScroll) {
this._gemScroll = gemScroll;
},
render: function() { render: function() {
const RoomSubList = sdk.getComponent('structures.RoomSubList'); const RoomSubList = sdk.getComponent('structures.RoomSubList');
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
const self = this; const self = this;
return ( return (
<GeminiScrollbar className="mx_RoomList_scrollbar" <GeminiScrollbarWrapper className="mx_RoomList_scrollbar"
autoshow={true} onScroll={self._whenScrolling} ref="gemscroll"> autoshow={true} onScroll={self._whenScrolling} wrappedRef={this._collectGemini}>
<div className="mx_RoomList"> <div className="mx_RoomList">
<RoomSubList list={[]} <RoomSubList list={[]}
extraTiles={this._makeGroupInviteTiles()} extraTiles={this._makeGroupInviteTiles()}
@ -711,7 +716,7 @@ module.exports = React.createClass({
searchFilter={self.props.searchFilter} searchFilter={self.props.searchFilter}
onShowMoreRooms={self.onShowMoreRooms} /> onShowMoreRooms={self.onShowMoreRooms} />
</div> </div>
</GeminiScrollbar> </GeminiScrollbarWrapper>
); );
}, },
}); });

View file

@ -19,7 +19,6 @@ const MatrixClientPeg = require("../../../MatrixClientPeg");
const Modal = require("../../../Modal"); const Modal = require("../../../Modal");
const sdk = require("../../../index"); const sdk = require("../../../index");
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
const GeminiScrollbar = require('react-gemini-scrollbar');
// A list capable of displaying entities which conform to the SearchableEntity // A list capable of displaying entities which conform to the SearchableEntity
// interface which is an object containing getJsx(): Jsx and matches(query: string): boolean // interface which is an object containing getJsx(): Jsx and matches(query: string): boolean
@ -164,11 +163,12 @@ const SearchableEntityList = React.createClass({
</div> </div>
); );
} }
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
list = ( list = (
<GeminiScrollbar autoshow={true} <GeminiScrollbarWrapper autoshow={true}
className="mx_SearchableEntityList_listWrapper"> className="mx_SearchableEntityList_listWrapper">
{ list } { list }
</GeminiScrollbar> </GeminiScrollbarWrapper>
); );
} }