Merge pull request #2267 from matrix-org/bwindels/roomfilterfield
Redesign: bring back & restyle room filter field
This commit is contained in:
commit
f8f4dde3ec
17 changed files with 311 additions and 280 deletions
|
@ -52,11 +52,6 @@ a:visited {
|
|||
|
||||
input[type=text], input[type=password], textarea {
|
||||
background-color: transparent;
|
||||
color: $primary-fg-color;
|
||||
}
|
||||
|
||||
input[type=text].error, input[type=password].error {
|
||||
border: 1px solid $warning-color;
|
||||
}
|
||||
|
||||
input[type=text]:focus, input[type=password]:focus, textarea:focus {
|
||||
|
|
|
@ -14,55 +14,12 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_SearchBox {
|
||||
height: 24px;
|
||||
margin-left: 16px;
|
||||
margin-right: 16px;
|
||||
padding-top: 24px;
|
||||
padding-bottom: 22px;
|
||||
|
||||
border-bottom: 1px solid $panel-divider-color;
|
||||
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.mx_SearchBox_searchButton {
|
||||
margin-right: 10px;
|
||||
margin-top: 5px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.mx_SearchBox_closeButton {
|
||||
cursor: pointer;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.mx_SearchBox_search {
|
||||
flex: 1 1 auto;
|
||||
width: 0px;
|
||||
font-family: $font-family;
|
||||
font-size: 12px;
|
||||
margin-top: -2px;
|
||||
height: 24px;
|
||||
border: 0px ! important;
|
||||
/* border-bottom: 1px solid rgba(0, 0, 0, 0.1) ! important; */
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.mx_SearchBox_minimise,
|
||||
.mx_SearchBox_maximise {
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_SearchBox_minimise {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.mx_SearchBox_maximise {
|
||||
margin-left: 9px;
|
||||
}
|
||||
|
||||
.mx_SearchBox object {
|
||||
pointer-events: none;
|
||||
background-image: url('../../img/icons-close.svg');
|
||||
background-repeat: no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-position: center;
|
||||
padding: 9px;
|
||||
}
|
||||
|
|
|
@ -43,41 +43,21 @@ limitations under the License.
|
|||
.mx_MemberList form,
|
||||
.mx_GroupMemberList form,
|
||||
.mx_GroupRoomList form {
|
||||
margin: 8px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mx_MemberList form > *:not(:first-child),
|
||||
.mx_GroupMemberList form > *:not(:first-child),
|
||||
.mx_GroupRoomList form > *:not(:first-child) {
|
||||
margin-left: 5px;
|
||||
.mx_MemberList form > *,
|
||||
.mx_GroupMemberList form > *,
|
||||
.mx_GroupRoomList form > * {
|
||||
margin: 9px;
|
||||
}
|
||||
|
||||
.mx_MemberList_query,
|
||||
.mx_GroupMemberList_query,
|
||||
.mx_GroupRoomList_query {
|
||||
flex: 1 1 0;
|
||||
box-sizing: border-box;
|
||||
font-family: $font-family;
|
||||
border-radius: 4px;
|
||||
padding: 9px;
|
||||
color: $input-darker-fg-color;
|
||||
background-color: $input-darker-bg-color;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.mx_MemberList_query::-webkit-input-placeholder,
|
||||
.mx_GroupMemberList_query::-webkit-input-placeholder,
|
||||
.mx_GroupRoomList_query::-webkit-input-placeholder,
|
||||
.mx_MemberList_query::-moz-placeholder,
|
||||
.mx_GroupMemberList_query::-moz-placeholder,
|
||||
.mx_GroupRoomList_query::-moz-placeholder {
|
||||
color: $input-darker-fg-color;
|
||||
opacity: 0.5;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mx_MemberList h2, .mx_GroupMemberList h2 {
|
||||
|
|
|
@ -1,23 +1,96 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-11 13 24 24" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st1{fill:none;stroke-width:2;stroke-linecap:round;}
|
||||
</style>
|
||||
<title>icons_create_room</title>
|
||||
<desc>Created with sketchtool.</desc>
|
||||
<g id="_x30_3-Input" sketch:type="MSPage">
|
||||
<g id="_x30_3_x5F_4-Uploading" transform="translate(-20.000000, -726.000000)" sketch:type="MSArtboardGroup">
|
||||
<g id="Room-list" sketch:type="MSLayerGroup">
|
||||
<g id="Room-list_x2F_Footer" transform="translate(0.000000, 708.000000)" sketch:type="MSShapeGroup">
|
||||
<g id="icons_create_room" transform="translate(20.000000, 18.000000)">
|
||||
<circle id="Oval-1-Copy-7" fill="#76CFA6" cx="1" cy="25" r="12"/>
|
||||
<path id="Line" class="st1" stroke="#FFFFFF" d="M-2.5,28.5l7.1-7.1"/>
|
||||
<path id="Line_1_" class="st1" stroke="#FFFFFF" d="M-2.5,21.5l7.1,7.1"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="-11 13 9.1202002 9.2202005"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="icons-close.svg"
|
||||
width="9.1202002"
|
||||
height="9.2202005"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"><metadata
|
||||
id="metadata21"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title>icons_create_room</dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs19" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
id="namedview17"
|
||||
showgrid="false"
|
||||
showguides="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="-0.15658729"
|
||||
inkscape:cy="-1.4622263"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="icons_create_room"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st1{fill:none;stroke-width:2;stroke-linecap:round;}
|
||||
</style>
|
||||
<title
|
||||
id="title4">icons_create_room</title>
|
||||
<desc
|
||||
id="desc6">Created with sketchtool.</desc>
|
||||
<g
|
||||
id="_x30_3-Input"
|
||||
sketch:type="MSPage"
|
||||
transform="translate(-7.4898998,-7.3898998)">
|
||||
<g
|
||||
id="_x30_3_x5F_4-Uploading"
|
||||
transform="translate(-20,-726)"
|
||||
sketch:type="MSArtboardGroup">
|
||||
<g
|
||||
id="Room-list"
|
||||
sketch:type="MSLayerGroup">
|
||||
<g
|
||||
id="Room-list_x2F_Footer"
|
||||
transform="translate(0,708)"
|
||||
sketch:type="MSShapeGroup">
|
||||
<g
|
||||
id="icons_create_room"
|
||||
transform="translate(20,18)">
|
||||
|
||||
<path
|
||||
id="Line"
|
||||
class="st1"
|
||||
d="M -2.5,28.5 4.6,21.4"
|
||||
style="fill:none;stroke:#9fa9ba;stroke-width:2;stroke-linecap:round;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="Line_1_"
|
||||
class="st1"
|
||||
d="m -2.5,21.5 7.1,7.1"
|
||||
style="fill:none;stroke:#9fa9ba;stroke-width:2;stroke-linecap:round;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.8 KiB |
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="13" height="13" viewBox="0, 0, 13, 13">
|
||||
<g id="Symbols">
|
||||
<g>
|
||||
<path d="M10.229,5.547 C10.229,8.133 8.133,10.229 5.547,10.229 C2.961,10.229 0.865,8.133 0.865,5.547 C0.865,2.961 2.961,0.865 5.547,0.865 C8.133,0.865 10.229,2.961 10.229,5.547 z" fill-opacity="0" stroke="#76CFA6" stroke-width="1" stroke-linecap="round" id="path-1" opacity="0.7"/>
|
||||
<path d="M8.824,8.824 L12.135,12.135" fill-opacity="0" stroke="#76CFA6" stroke-width="1" stroke-linecap="round" id="Line" opacity="0.7"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 776 B |
|
@ -1,8 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="35" height="35" viewBox="0, 0, 35, 35">
|
||||
<g id="Symbols">
|
||||
<path d="M22.4,15.4 C22.4,19.266 19.266,22.4 15.4,22.4 C11.534,22.4 8.4,19.266 8.4,15.4 C8.4,11.534 11.534,8.4 15.4,8.4 C19.266,8.4 22.4,11.534 22.4,15.4 z" stroke="#9FA9BA" stroke-width="1" stroke-linecap="round" id="path-1" fill="none"/>
|
||||
<path d="M20.3,20.3 L25.25,25.25" stroke="#9FA9BA" stroke-width="1" stroke-linecap="round" id="Line"/>
|
||||
</g>
|
||||
</svg>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 52.3 (67297) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Shape</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="agreed" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="matrix-files-list" transform="translate(-96.000000, -71.000000)" fill="#9FA9BA" fill-rule="nonzero">
|
||||
<g id="1-copy" transform="translate(67.000000, 47.000000)">
|
||||
<g id="search" transform="translate(17.000000, 16.000000)">
|
||||
<path d="M27.7960817,22.7689061 L24.2910448,19.2638692 C26.6040192,16.4045943 26.2742638,12.2351072 23.5405883,9.77496046 C20.8069128,7.31481375 16.6258535,7.42483371 14.0253436,10.0253436 C11.4248337,12.6258535 11.3148138,16.8069128 13.7749605,19.5405883 C16.2351072,22.2742638 20.4045943,22.6040192 23.2638692,20.2910448 L26.7689061,23.7960817 C27.0539429,24.0713794 27.5070231,24.0674423 27.7872327,23.7872327 C28.0674423,23.5070231 28.0713794,23.0539429 27.7960817,22.7689061 Z M13.4802761,14.9285199 C13.4778286,12.4654797 15.1281652,10.3071276 17.5057384,9.66391787 C19.8833116,9.02070817 22.3967204,10.0526338 23.6363865,12.1809668 C24.8760525,14.3092997 24.5336194,17.0046354 22.8011317,18.7553664 C22.7924145,18.7633572 22.781518,18.7655365 22.7735272,18.7735272 C22.7655365,18.781518 22.7626308,18.7931409 22.7553664,18.8011317 C21.1935085,20.3473331 18.8551963,20.8029027 16.8271177,19.9561226 C14.799039,19.1093426 13.4789257,17.1262773 13.4802761,14.9285199 Z" id="Shape"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 678 B After Width: | Height: | Size: 1.7 KiB |
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="21px" height="19px" viewBox="0 0 21 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<!-- Generator: bin/sketchtool 1.4 (305) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>icons_search</title>
|
||||
<desc>Created with bin/sketchtool.</desc>
|
||||
<defs></defs>
|
||||
<g id="02-Chat" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="02_13-Chat-member-profile" sketch:type="MSArtboardGroup" transform="translate(-910.000000, -34.000000)" stroke="#76CFA6">
|
||||
<g id="icons_search" sketch:type="MSLayerGroup" transform="translate(906.000000, 30.000000)">
|
||||
<path d="M17.328421,15.3333333 L23.5542961,20.7357275 C23.9574623,21.085568 24.0116667,21.70516 23.6700827,22.1261351 L23.6700827,22.1261351 C23.3308636,22.5441955 22.72562,22.5965299 22.3258751,22.2496583 L16.1,16.8472641" id="Rectangle-9" sketch:type="MSShapeGroup"></path>
|
||||
<g id="search" transform="translate(11.617851, 11.853553) rotate(-45.000000) translate(-11.617851, -11.853553) translate(4.117851, 3.853553)" sketch:type="MSShapeGroup">
|
||||
<ellipse id="Search" cx="7.64433504" cy="7.90518519" rx="7.1665641" ry="7.41111111"></ellipse>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.4 KiB |
|
@ -69,6 +69,8 @@ $primary-hairline-color: #e5e5e5;
|
|||
$input-border-color: #f0f0f0;
|
||||
$input-darker-bg-color: rgba(193, 201, 214, 0.29);
|
||||
$input-darker-fg-color: #9fa9ba;
|
||||
$input-lighter-bg-color: #f2f5f8;
|
||||
$input-lighter-fg-color: $input-darker-fg-color;
|
||||
|
||||
$button-bg-color: #7ac9a1;
|
||||
$button-fg-color: white;
|
||||
|
@ -178,6 +180,93 @@ $lightbox-border-color: #ffffff;
|
|||
// unused?
|
||||
$progressbar-color: #000;
|
||||
|
||||
// form elements
|
||||
|
||||
// .mx_textinput is a container for a text input
|
||||
// + some other controls like buttons, ...
|
||||
// it has the appearance of a text box so the controls
|
||||
// appear to be part of the input
|
||||
|
||||
:not(.mx_textinput) > input[type=text],
|
||||
:not(.mx_textinput) > input[type=search],
|
||||
.mx_textinput {
|
||||
display: block;
|
||||
margin: 9px;
|
||||
box-sizing: border-box;
|
||||
background-color: transparent;
|
||||
color: $input-darker-fg-color;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #c1c1c1;
|
||||
}
|
||||
|
||||
.mx_textinput {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mx_textinput > input[type=text],
|
||||
.mx_textinput > input[type=search] {
|
||||
border: none;
|
||||
flex: 1;
|
||||
color: inherit; //from .mx_textinput
|
||||
}
|
||||
|
||||
input[type=text],
|
||||
input[type=search] {
|
||||
padding: 9px;
|
||||
font-family: $font-family;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.dark-panel {
|
||||
:not(.mx_textinput) > input[type=text],
|
||||
:not(.mx_textinput) > input[type=search],
|
||||
.mx_textinput {
|
||||
color: $input-darker-fg-color;
|
||||
background-color: $input-darker-bg-color;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.light-panel {
|
||||
:not(.mx_textinput) > input[type=text],
|
||||
:not(.mx_textinput) > input[type=search],
|
||||
.mx_textinput {
|
||||
color: $input-lighter-fg-color;
|
||||
background-color: $input-lighter-bg-color;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=text].mx_textinput_icon,
|
||||
input[type=search].mx_textinput_icon {
|
||||
padding-left: 36px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 10px center;
|
||||
}
|
||||
|
||||
input[type=text].mx_textinput_icon.mx_textinput_search,
|
||||
input[type=search].mx_textinput_icon.mx_textinput_search {
|
||||
background-image: url('../../img/icons-search.svg');
|
||||
}
|
||||
|
||||
// dont search UI as not all browsers support it,
|
||||
// we implement it ourselves where needed instead
|
||||
input[type=search]::-webkit-search-decoration,
|
||||
input[type=search]::-webkit-search-cancel-button,
|
||||
input[type=search]::-webkit-search-results-button,
|
||||
input[type=search]::-webkit-search-results-decoration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.input[type=text]::-webkit-input-placeholder,
|
||||
.input[type=text]::-moz-placeholder,
|
||||
.input[type=search]::-webkit-input-placeholder,
|
||||
.input[type=search]::-moz-placeholder {
|
||||
color: #a5aab2;
|
||||
}
|
||||
// ***** Mixins! *****
|
||||
|
||||
@define-mixin mx_DialogButton {
|
||||
|
|
|
@ -1286,9 +1286,10 @@ export default React.createClass({
|
|||
const rightPanel = !this.props.collapsedRhs ? <RightPanel groupId={this.props.groupId} /> : undefined;
|
||||
|
||||
const headerClasses = {
|
||||
mx_GroupView_header: true,
|
||||
mx_GroupView_header_view: !this.state.editing,
|
||||
mx_GroupView_header_isUserMember: this.state.isUserMember,
|
||||
"mx_GroupView_header": true,
|
||||
"light-panel": true,
|
||||
"mx_GroupView_header_view": !this.state.editing,
|
||||
"mx_GroupView_header_isUserMember": this.state.isUserMember,
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -171,6 +171,12 @@ const LeftPanel = React.createClass({
|
|||
this.setState({ searchFilter: term });
|
||||
},
|
||||
|
||||
onSearchCleared: function(source) {
|
||||
if (source === "keyboard") {
|
||||
dis.dispatch({action: 'focus_composer'});
|
||||
}
|
||||
},
|
||||
|
||||
collectRoomList: function(ref) {
|
||||
this._roomList = ref;
|
||||
},
|
||||
|
@ -179,13 +185,9 @@ const LeftPanel = React.createClass({
|
|||
const RoomList = sdk.getComponent('rooms.RoomList');
|
||||
const TagPanel = sdk.getComponent('structures.TagPanel');
|
||||
const TopLeftMenuButton = sdk.getComponent('structures.TopLeftMenuButton');
|
||||
const SearchBox = sdk.getComponent('structures.SearchBox');
|
||||
const CallPreview = sdk.getComponent('voip.CallPreview');
|
||||
|
||||
const topBox = <TopLeftMenuButton collapsed={ this.props.collapsed } />;
|
||||
/*
|
||||
const SearchBox = sdk.getComponent('structures.SearchBox');
|
||||
const topBox = <SearchBox collapsed={ this.props.collapsed } onSearch={ this.onSearch } />;
|
||||
*/
|
||||
const tagPanelEnabled = !SettingsStore.getValue("TagPanel.disableTagPanel");
|
||||
const tagPanel = tagPanelEnabled ? <TagPanel /> : <div />;
|
||||
|
||||
|
@ -198,11 +200,16 @@ const LeftPanel = React.createClass({
|
|||
},
|
||||
);
|
||||
|
||||
const searchBox = !this.props.collapsed ?
|
||||
<SearchBox onSearch={ this.onSearch } onCleared={ this.onSearchCleared } /> :
|
||||
undefined;
|
||||
|
||||
return (
|
||||
<div className={containerClasses}>
|
||||
{ tagPanel }
|
||||
<aside className={"mx_LeftPanel"} onKeyDown={ this._onKeyDown } onFocus={ this._onFocus } onBlur={ this._onBlur }>
|
||||
{ topBox }
|
||||
<aside className={"mx_LeftPanel dark-panel"} onKeyDown={ this._onKeyDown } onFocus={ this._onFocus } onBlur={ this._onBlur }>
|
||||
<TopLeftMenuButton collapsed={ this.props.collapsed } />
|
||||
{ searchBox }
|
||||
<CallPreview ConferenceHandler={VectorConferenceHandler} />
|
||||
<RoomList
|
||||
ref={this.collectRoomList}
|
||||
|
|
|
@ -52,7 +52,7 @@ const RoomSubList = React.createClass({
|
|||
collapsed: PropTypes.bool.isRequired, // is LeftPanel collapsed?
|
||||
onHeaderClick: PropTypes.func,
|
||||
incomingCall: PropTypes.object,
|
||||
searchFilter: PropTypes.string,
|
||||
isFiltered: PropTypes.bool,
|
||||
headerItems: PropTypes.node, // content shown in the sublist header
|
||||
extraTiles: PropTypes.arrayOf(PropTypes.node), // extra elements added beneath tiles
|
||||
},
|
||||
|
@ -60,7 +60,6 @@ const RoomSubList = React.createClass({
|
|||
getInitialState: function() {
|
||||
return {
|
||||
hidden: this.props.startAsHidden || false,
|
||||
sortedList: [],
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -74,9 +73,6 @@ const RoomSubList = React.createClass({
|
|||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.setState({
|
||||
sortedList: this.applySearchFilter(this.props.list, this.props.searchFilter),
|
||||
});
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
},
|
||||
|
||||
|
@ -84,23 +80,6 @@ const RoomSubList = React.createClass({
|
|||
dis.unregister(this.dispatcherRef);
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
// order the room list appropriately before we re-render
|
||||
//if (debug) console.log("received new props, list = " + newProps.list);
|
||||
this.setState({
|
||||
sortedList: this.applySearchFilter(newProps.list, newProps.searchFilter),
|
||||
});
|
||||
},
|
||||
|
||||
applySearchFilter: function(list, filter) {
|
||||
if (filter === "") return list;
|
||||
const lcFilter = filter.toLowerCase();
|
||||
// case insensitive if room name includes filter,
|
||||
// or if starts with `#` and one of room's aliases starts with filter
|
||||
return list.filter((room) => (room.name && room.name.toLowerCase().includes(lcFilter)) ||
|
||||
(filter[0] === '#' && room.getAliases().some((alias) => alias.toLowerCase().startsWith(lcFilter))));
|
||||
},
|
||||
|
||||
// The header is collapsable if it is hidden or not stuck
|
||||
// The dataset elements are added in the RoomList _initAndPositionStickyHeaders method
|
||||
isCollapsableOnClick: function() {
|
||||
|
@ -196,7 +175,7 @@ const RoomSubList = React.createClass({
|
|||
|
||||
makeRoomTiles: function() {
|
||||
const RoomTile = sdk.getComponent("rooms.RoomTile");
|
||||
return this.state.sortedList.map((room, index) => {
|
||||
return this.props.list.map((room, index) => {
|
||||
return <RoomTile
|
||||
room={room}
|
||||
roomSubList={this}
|
||||
|
@ -218,7 +197,7 @@ const RoomSubList = React.createClass({
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
// find first room which has notifications and switch to it
|
||||
for (const room of this.state.sortedList) {
|
||||
for (const room of this.props.list) {
|
||||
const roomNotifState = RoomNotifs.getRoomNotifsState(room.roomId);
|
||||
const highlight = room.getUnreadNotificationCount('highlight') > 0;
|
||||
const notificationCount = room.getUnreadNotificationCount();
|
||||
|
@ -241,10 +220,10 @@ const RoomSubList = React.createClass({
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
// switch to first room in sortedList as that'll be the top of the list for the user
|
||||
if (this.state.sortedList && this.state.sortedList.length > 0) {
|
||||
if (this.props.list && this.props.list.length > 0) {
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: this.state.sortedList[0].roomId,
|
||||
room_id: this.props.list[0].roomId,
|
||||
});
|
||||
} else if (this.props.extraTiles && this.props.extraTiles.length > 0) {
|
||||
// Group Invites are different in that they are all extra tiles and not rooms
|
||||
|
@ -312,7 +291,7 @@ const RoomSubList = React.createClass({
|
|||
);
|
||||
}
|
||||
|
||||
const len = this.state.sortedList.length + this.props.extraTiles.length;
|
||||
const len = this.props.list.length + this.props.extraTiles.length;
|
||||
let chevron;
|
||||
if (len) {
|
||||
const chevronClasses = classNames({
|
||||
|
@ -323,7 +302,7 @@ const RoomSubList = React.createClass({
|
|||
chevron = (<div className={chevronClasses}></div>);
|
||||
}
|
||||
|
||||
const tabindex = this.props.searchFilter === "" ? "0" : "-1";
|
||||
const tabindex = this.props.isFiltered ? "0" : "-1";
|
||||
return (
|
||||
<div className="mx_RoomSubList_labelContainer" title={ title } ref="header">
|
||||
<AccessibleButton onClick={ this.onClick } className="mx_RoomSubList_label" tabIndex={tabindex}>
|
||||
|
@ -338,7 +317,7 @@ const RoomSubList = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
const len = this.state.sortedList.length + this.props.extraTiles.length;
|
||||
const len = this.props.list.length + this.props.extraTiles.length;
|
||||
if (len) {
|
||||
const subListClasses = classNames({
|
||||
"mx_RoomSubList": true,
|
||||
|
|
|
@ -28,8 +28,8 @@ module.exports = React.createClass({
|
|||
displayName: 'SearchBox',
|
||||
|
||||
propTypes: {
|
||||
collapsed: React.PropTypes.bool,
|
||||
onSearch: React.PropTypes.func,
|
||||
onCleared: React.PropTypes.func,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
|
@ -75,86 +75,44 @@ module.exports = React.createClass({
|
|||
100,
|
||||
),
|
||||
|
||||
onToggleCollapse: function(show) {
|
||||
if (show) {
|
||||
dis.dispatch({
|
||||
action: 'show_left_panel',
|
||||
});
|
||||
} else {
|
||||
dis.dispatch({
|
||||
action: 'hide_left_panel',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyDown: function(ev) {
|
||||
switch (ev.keyCode) {
|
||||
case KeyCode.ESCAPE:
|
||||
this._clearSearch();
|
||||
dis.dispatch({action: 'focus_composer'});
|
||||
this._clearSearch("keyboard");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_clearSearch: function() {
|
||||
_clearSearch: function(source) {
|
||||
this.refs.search.value = "";
|
||||
this.onChange();
|
||||
if (this.props.onCleared) {
|
||||
this.props.onCleared(source);
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const TintableSvg = sdk.getComponent('elements.TintableSvg');
|
||||
|
||||
const collapseTabIndex = this.refs.search && this.refs.search.value !== "" ? "-1" : "0";
|
||||
const clearButton = this.state.searchTerm.length > 0 ?
|
||||
(<AccessibleButton key="button"
|
||||
className="mx_SearchBox_closeButton"
|
||||
onClick={ () => {this._clearSearch("button")} }>
|
||||
</AccessibleButton>) : undefined;
|
||||
|
||||
let toggleCollapse;
|
||||
if (this.props.collapsed) {
|
||||
toggleCollapse =
|
||||
<AccessibleButton className="mx_SearchBox_maximise" tabIndex={collapseTabIndex} onClick={ this.onToggleCollapse.bind(this, true) }>
|
||||
<TintableSvg src="img/maximise.svg" width="10" height="16" alt={ _t("Expand panel") } />
|
||||
</AccessibleButton>;
|
||||
} else {
|
||||
toggleCollapse =
|
||||
<AccessibleButton className="mx_SearchBox_minimise" tabIndex={collapseTabIndex} onClick={ this.onToggleCollapse.bind(this, false) }>
|
||||
<TintableSvg src="img/minimise.svg" width="10" height="16" alt={ _t("Collapse panel") } />
|
||||
</AccessibleButton>;
|
||||
}
|
||||
|
||||
let searchControls;
|
||||
if (!this.props.collapsed) {
|
||||
searchControls = [
|
||||
this.state.searchTerm.length > 0 ?
|
||||
<AccessibleButton key="button"
|
||||
className="mx_SearchBox_closeButton"
|
||||
onClick={ ()=>{ this._clearSearch(); } }>
|
||||
<TintableSvg
|
||||
className="mx_SearchBox_searchButton"
|
||||
src="img/icons-close.svg" width="24" height="24"
|
||||
/>
|
||||
</AccessibleButton>
|
||||
:
|
||||
<TintableSvg
|
||||
key="button"
|
||||
className="mx_SearchBox_searchButton"
|
||||
src="img/icons-search-copy.svg" width="13" height="13"
|
||||
/>,
|
||||
<input
|
||||
key="searchfield"
|
||||
type="text"
|
||||
ref="search"
|
||||
className="mx_SearchBox_search"
|
||||
value={ this.state.searchTerm }
|
||||
onChange={ this.onChange }
|
||||
onKeyDown={ this._onKeyDown }
|
||||
placeholder={ _t('Filter room names') }
|
||||
/>,
|
||||
];
|
||||
}
|
||||
|
||||
const self = this;
|
||||
return (
|
||||
<div className="mx_SearchBox">
|
||||
{ searchControls }
|
||||
{ toggleCollapse }
|
||||
<div className="mx_SearchBox mx_textinput">
|
||||
<input
|
||||
key="searchfield"
|
||||
type="text"
|
||||
ref="search"
|
||||
className="mx_textinput_icon mx_textinput_search"
|
||||
value={ this.state.searchTerm }
|
||||
onChange={ this.onChange }
|
||||
onKeyDown={ this._onKeyDown }
|
||||
placeholder={ _t('Filter room names') }
|
||||
/>
|
||||
{ clearButton }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -163,7 +163,7 @@ export default React.createClass({
|
|||
</div> : <div />;
|
||||
|
||||
return (
|
||||
<div className="mx_MemberList">
|
||||
<div className="mx_MemberList dark-panel">
|
||||
{ inputBox }
|
||||
<GeminiScrollbarWrapper autoshow={true}>
|
||||
{ joined }
|
||||
|
|
|
@ -131,7 +131,7 @@ export default React.createClass({
|
|||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||
return (
|
||||
<div className="mx_GroupRoomList">
|
||||
<div className="mx_GroupRoomList dark-panel">
|
||||
{ inputBox }
|
||||
<GeminiScrollbarWrapper autoshow={true} className="mx_GroupRoomList_joined mx_GroupRoomList_outerWrapper">
|
||||
<TruncatedList className="mx_GroupRoomList_wrapper" truncateAt={this.state.truncateAt}
|
||||
|
|
|
@ -449,7 +449,7 @@ module.exports = React.createClass({
|
|||
|
||||
const filterAndButtons = (
|
||||
<form autoComplete="off">
|
||||
<input className="mx_MemberList_query" id="mx_MemberList_query" type="search"
|
||||
<input className="mx_MemberList_query mx_textinput_icon mx_textinput_search" id="mx_MemberList_query" type="search"
|
||||
onChange={this.onSearchQueryChanged} value={this.state.searchQuery}
|
||||
placeholder={_t('Filter room members')} />
|
||||
{ inviteButton }
|
||||
|
@ -457,7 +457,7 @@ module.exports = React.createClass({
|
|||
);
|
||||
|
||||
return (
|
||||
<div className="mx_MemberList">
|
||||
<div className="mx_MemberList dark-panel">
|
||||
{ filterAndButtons }
|
||||
<GeminiScrollbarWrapper autoshow={true}>
|
||||
<div className="mx_MemberList_wrapper">
|
||||
|
|
|
@ -382,7 +382,7 @@ module.exports = React.createClass({
|
|||
if (this.props.onSearchClick && this.props.inRoom) {
|
||||
searchButton =
|
||||
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title={_t("Search")}>
|
||||
<TintableSvg src="img/icons-search.svg" width="35" height="35" />
|
||||
<TintableSvg src="img/icons-search.svg" width="16" height="16" />
|
||||
</AccessibleButton>;
|
||||
}
|
||||
|
||||
|
@ -424,7 +424,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={"mx_RoomHeader " + (this.props.editing ? "mx_RoomHeader_editing" : "")}>
|
||||
<div className={"mx_RoomHeader light-panel " + (this.props.editing ? "mx_RoomHeader_editing" : "")}>
|
||||
<div className="mx_RoomHeader_wrapper">
|
||||
<div className="mx_RoomHeader_avatar">{ roomAvatar }</div>
|
||||
{ name }
|
||||
|
|
|
@ -33,8 +33,9 @@ const Receipt = require('../../../utils/Receipt');
|
|||
import TagOrderStore from '../../../stores/TagOrderStore';
|
||||
import RoomListStore from '../../../stores/RoomListStore';
|
||||
import GroupStore from '../../../stores/GroupStore';
|
||||
|
||||
import RoomSubList from '../../structures/RoomSubList';
|
||||
import ResizeHandle from '../elements/ResizeHandle';
|
||||
|
||||
import {Resizer, FixedDistributor, FlexSizer} from '../../../resizer'
|
||||
const HIDE_CONFERENCE_CHANS = true;
|
||||
const STANDARD_TAGS_REGEX = /^(m\.(favourite|lowpriority|server_notice)|im\.vector\.fake\.(invite|recent|direct|archived))$/;
|
||||
|
@ -440,39 +441,50 @@ module.exports = React.createClass({
|
|||
return ret;
|
||||
},
|
||||
|
||||
_applySearchFilter: function(list, filter) {
|
||||
if (filter === "") return list;
|
||||
const lcFilter = filter.toLowerCase();
|
||||
// case insensitive if room name includes filter,
|
||||
// or if starts with `#` and one of room's aliases starts with filter
|
||||
return list.filter((room) => (room.name && room.name.toLowerCase().includes(lcFilter)) ||
|
||||
(filter[0] === '#' && room.getAliases().some((alias) => alias.toLowerCase().startsWith(lcFilter))));
|
||||
},
|
||||
|
||||
_mapSubListProps: function(subListsProps) {
|
||||
const defaultProps = {
|
||||
collapsed: this.props.collapsed,
|
||||
isFiltered: !!this.props.searchFilter,
|
||||
incomingCall: this.state.incomingCall,
|
||||
};
|
||||
|
||||
subListsProps.forEach((p) => {
|
||||
p.list = this._applySearchFilter(p.list, this.props.searchFilter);
|
||||
});
|
||||
|
||||
subListsProps = subListsProps.filter((props => {
|
||||
const len = props.list.length + (props.extraTiles ? props.extraTiles.length : 0);
|
||||
return len !== 0 || (props.onAddRoom && !this.props.searchFilter);
|
||||
}));
|
||||
|
||||
return subListsProps.reduce((components, props, i) => {
|
||||
props = Object.assign({}, defaultProps, props);
|
||||
const isLast = i === subListsProps.length - 1;
|
||||
const {key, label, ... otherProps} = props;
|
||||
const chosenKey = key || label;
|
||||
|
||||
let subList = <RoomSubList key={chosenKey} label={label} {...otherProps} />;
|
||||
if (!isLast) {
|
||||
return components.concat(
|
||||
subList,
|
||||
<ResizeHandle key={chosenKey+"-resizer"} vertical={true} />
|
||||
);
|
||||
} else {
|
||||
return components.concat(subList);
|
||||
}
|
||||
}, []);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const RoomSubList = sdk.getComponent('structures.RoomSubList');
|
||||
|
||||
const mapProps = (subListsProps) => {
|
||||
const defaultProps = {
|
||||
collapsed: this.props.collapsed,
|
||||
searchFilter: this.props.searchFilter,
|
||||
incomingCall: this.state.incomingCall,
|
||||
};
|
||||
|
||||
subListsProps = subListsProps.filter((props => {
|
||||
const len = props.list.length + (props.extraTiles ? props.extraTiles.length : 0);
|
||||
return len !== 0 || props.onAddRoom;
|
||||
}));
|
||||
|
||||
return subListsProps.reduce((components, props, i) => {
|
||||
props = Object.assign({}, defaultProps, props);
|
||||
const isLast = i === subListsProps.length - 1;
|
||||
const {key, label, ... otherProps} = props;
|
||||
const chosenKey = key || label;
|
||||
|
||||
let subList = <RoomSubList key={chosenKey} label={label} {...otherProps} />;
|
||||
if (!isLast) {
|
||||
return components.concat(
|
||||
subList,
|
||||
<ResizeHandle key={chosenKey+"-resizer"} vertical={true} />
|
||||
);
|
||||
} else {
|
||||
return components.concat(subList);
|
||||
}
|
||||
}, []);
|
||||
}
|
||||
|
||||
let subLists = [
|
||||
{
|
||||
list: [],
|
||||
|
@ -545,7 +557,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
]);
|
||||
|
||||
const subListComponents = mapProps(subLists);
|
||||
const subListComponents = this._mapSubListProps(subLists);
|
||||
|
||||
return (
|
||||
<div ref={(d) => this.resizeContainer = d} className="mx_RoomList">
|
||||
|
|
Loading…
Reference in a new issue