diff options
author | Saturnino Abril <saturnino.abril@gmail.com> | 2017-03-24 18:05:43 +0900 |
---|---|---|
committer | George Goldberg <george@gberg.me> | 2017-03-24 09:05:43 +0000 |
commit | 1167b391854957a5d58ed569c1dc2f80e9ccc599 (patch) | |
tree | 071e2e2217dee77fee5b310620aa946d4f68a69d | |
parent | 98baf1536eb1b47d8258e188e1c80393182c6525 (diff) | |
download | chat-1167b391854957a5d58ed569c1dc2f80e9ccc599.tar.gz chat-1167b391854957a5d58ed569c1dc2f80e9ccc599.tar.bz2 chat-1167b391854957a5d58ed569c1dc2f80e9ccc599.zip |
Fixed mobile search focus - keyboard collapse/focus (#5766)
-rw-r--r-- | webapp/components/rhs_thread.jsx | 120 | ||||
-rw-r--r-- | webapp/components/search_bar.jsx | 37 | ||||
-rw-r--r-- | webapp/components/search_results.jsx | 37 | ||||
-rw-r--r-- | webapp/components/sidebar_right.jsx | 53 | ||||
-rw-r--r-- | webapp/components/suggestion/suggestion_box.jsx | 5 |
5 files changed, 132 insertions, 120 deletions
diff --git a/webapp/components/rhs_thread.jsx b/webapp/components/rhs_thread.jsx index 2c1d03901..8e26fb347 100644 --- a/webapp/components/rhs_thread.jsx +++ b/webapp/components/rhs_thread.jsx @@ -1,12 +1,10 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import SearchBox from './search_bar.jsx'; import CreateComment from './create_comment.jsx'; import RhsHeaderPost from './rhs_header_post.jsx'; import RootPost from './rhs_root_post.jsx'; import Comment from './rhs_comment.jsx'; -import FileUploadOverlay from './file_upload_overlay.jsx'; import FloatingTimestamp from './post_view/components/floating_timestamp.jsx'; import DateSeparator from './post_view/components/date_separator.jsx'; @@ -334,12 +332,6 @@ export default class RhsThread extends React.Component { ); } - var currentId = UserStore.getCurrentId(); - var searchForm; - if (currentId != null) { - searchForm = <SearchBox isCommentsPage={true}/>; - } - let profile; if (UserStore.getCurrentId() === selected.user_id) { profile = this.props.currentUser; @@ -407,66 +399,62 @@ export default class RhsThread extends React.Component { } return ( - <div className='post-right__container'> - <FileUploadOverlay overlayType='right'/> - <div className='search-bar__container sidebar--right__search-header'>{searchForm}</div> - <div className='sidebar-right__body'> - <FloatingTimestamp - isScrolling={this.state.isScrolling} - isMobile={Utils.isMobile()} - createAt={this.state.topRhsPostCreateAt} - isRhsPost={true} - /> - <RhsHeaderPost - fromFlaggedPosts={this.props.fromFlaggedPosts} - fromSearch={this.props.fromSearch} - isWebrtc={this.props.isWebrtc} - isMentionSearch={this.props.isMentionSearch} - toggleSize={this.props.toggleSize} - shrink={this.props.shrink} - /> - <Scrollbars - autoHide={true} - autoHideTimeout={500} - autoHideDuration={500} - renderThumbHorizontal={renderThumbHorizontal} - renderThumbVertical={renderThumbVertical} - renderView={renderView} - onScroll={this.handleScroll} - > - <div className='post-right__scroll'> - <DateSeparator - date={previousPostDay} - /> - <RootPost - ref={selected.id} - post={selected} - commentCount={postsArray.length} - user={profile} - currentUser={this.props.currentUser} - compactDisplay={this.state.compactDisplay} - useMilitaryTime={this.props.useMilitaryTime} - isFlagged={isRootFlagged} - status={rootStatus} - previewCollapsed={this.state.previewsCollapsed} - isBusy={this.state.isBusy} + <div className='sidebar-right__body'> + <FloatingTimestamp + isScrolling={this.state.isScrolling} + isMobile={Utils.isMobile()} + createAt={this.state.topRhsPostCreateAt} + isRhsPost={true} + /> + <RhsHeaderPost + fromFlaggedPosts={this.props.fromFlaggedPosts} + fromSearch={this.props.fromSearch} + isWebrtc={this.props.isWebrtc} + isMentionSearch={this.props.isMentionSearch} + toggleSize={this.props.toggleSize} + shrink={this.props.shrink} + /> + <Scrollbars + autoHide={true} + autoHideTimeout={500} + autoHideDuration={500} + renderThumbHorizontal={renderThumbHorizontal} + renderThumbVertical={renderThumbVertical} + renderView={renderView} + onScroll={this.handleScroll} + > + <div className='post-right__scroll'> + <DateSeparator + date={previousPostDay} + /> + <RootPost + ref={selected.id} + post={selected} + commentCount={postsArray.length} + user={profile} + currentUser={this.props.currentUser} + compactDisplay={this.state.compactDisplay} + useMilitaryTime={this.props.useMilitaryTime} + isFlagged={isRootFlagged} + status={rootStatus} + previewCollapsed={this.state.previewsCollapsed} + isBusy={this.state.isBusy} + /> + <div + ref='rhspostlist' + className='post-right-comments-container' + > + {commentsLists} + </div> + <div className='post-create__container'> + <CreateComment + channelId={selected.channel_id} + rootId={selected.id} + latestPostId={postsArray.length > 0 ? postsArray[postsArray.length - 1].id : selected.id} /> - <div - ref='rhspostlist' - className='post-right-comments-container' - > - {commentsLists} - </div> - <div className='post-create__container'> - <CreateComment - channelId={selected.channel_id} - rootId={selected.id} - latestPostId={postsArray.length > 0 ? postsArray[postsArray.length - 1].id : selected.id} - /> - </div> </div> - </Scrollbars> - </div> + </div> + </Scrollbars> </div> ); } diff --git a/webapp/components/search_bar.jsx b/webapp/components/search_bar.jsx index b88e67a11..42a124eda 100644 --- a/webapp/components/search_bar.jsx +++ b/webapp/components/search_bar.jsx @@ -1,7 +1,6 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import $ from 'jquery'; import * as GlobalActions from 'actions/global_actions.jsx'; import SearchStore from 'stores/search_store.jsx'; import UserStore from 'stores/user_store.jsx'; @@ -31,7 +30,9 @@ export default class SearchBar extends React.Component { this.handleUserFocus = this.handleUserFocus.bind(this); this.handleClear = this.handleClear.bind(this); this.handleUserBlur = this.handleUserBlur.bind(this); - this.performSearch = this.performSearch.bind(this); + this.handleSearch = this.handleSearch.bind(this); + this.handleSearchOnSuccess = this.handleSearchOnSuccess.bind(this); + this.handleSearchOnError = this.handleSearchOnError.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.searchMentions = this.searchMentions.bind(this); this.getFlagged = this.getFlagged.bind(this); @@ -125,7 +126,7 @@ export default class SearchBar extends React.Component { this.setState({focused: true}); } - performSearch(terms, isMentionSearch) { + handleSearch(terms, isMentionSearch) { if (terms.length) { this.setState({ isSearching: true, @@ -136,23 +137,35 @@ export default class SearchBar extends React.Component { terms, isMentionSearch, () => { - this.setState({isSearching: false}); - - if (Utils.isMobile() && this.search) { - this.search.value = ''; - } + this.handleSearchOnSuccess(); }, () => { - this.setState({isSearching: false}); + this.handleSearchOnError(); } ); } } + handleSearchOnSuccess() { + if (this.mounted) { + this.setState({isSearching: false}); + + if (Utils.isMobile() && this.search) { + this.search.value = ''; + } + } + } + + handleSearchOnError() { + if (this.mounted) { + this.setState({isSearching: false}); + } + } + handleSubmit(e) { e.preventDefault(); - this.performSearch(this.state.searchTerm.trim()); - $(this.search).find('input').blur(); + this.handleSearch(this.state.searchTerm.trim()); + this.search.blur(); } searchMentions(e) { @@ -310,7 +323,7 @@ export default class SearchBar extends React.Component { listComponent={SearchSuggestionList} providers={this.suggestionProviders} type='search' - autoFocus={this.props.isFocus} + autoFocus={this.props.isFocus && this.state.searchTerm === ''} /> <div className={clearClass} diff --git a/webapp/components/search_results.jsx b/webapp/components/search_results.jsx index ce72ec3b1..70f686f42 100644 --- a/webapp/components/search_results.jsx +++ b/webapp/components/search_results.jsx @@ -3,7 +3,6 @@ import SearchResultsHeader from './search_results_header.jsx'; import SearchResultsItem from './search_results_item.jsx'; -import SearchBox from './search_bar.jsx'; import ChannelStore from 'stores/channel_store.jsx'; import SearchStore from 'stores/search_store.jsx'; @@ -168,11 +167,6 @@ export default class SearchResults extends React.Component { render() { var results = this.state.results; - var currentId = UserStore.getCurrentId(); - var searchForm = null; - if (currentId) { - searchForm = <SearchBox isFocus={Utils.isMobile()}/>; - } var noResults = (!results || !results.order || !results.order.length); const searchTerm = this.state.searchTerm; const profiles = this.state.profiles || {}; @@ -312,23 +306,20 @@ export default class SearchResults extends React.Component { } return ( - <div className='sidebar--right__content'> - <div className='search-bar__container sidebar--right__search-header'>{searchForm}</div> - <div className='sidebar-right__body'> - <SearchResultsHeader - isMentionSearch={this.props.isMentionSearch} - toggleSize={this.props.toggleSize} - shrink={this.props.shrink} - isFlaggedPosts={this.props.isFlaggedPosts} - isPinnedPosts={this.props.isPinnedPosts} - channelDisplayName={this.props.channelDisplayName} - /> - <div - id='search-items-container' - className='search-items-container' - > - {ctls} - </div> + <div className='sidebar-right__body'> + <SearchResultsHeader + isMentionSearch={this.props.isMentionSearch} + toggleSize={this.props.toggleSize} + shrink={this.props.shrink} + isFlaggedPosts={this.props.isFlaggedPosts} + isPinnedPosts={this.props.isPinnedPosts} + channelDisplayName={this.props.channelDisplayName} + /> + <div + id='search-items-container' + className='search-items-container' + > + {ctls} </div> </div> ); diff --git a/webapp/components/sidebar_right.jsx b/webapp/components/sidebar_right.jsx index 42b7381f4..6a0716ce1 100644 --- a/webapp/components/sidebar_right.jsx +++ b/webapp/components/sidebar_right.jsx @@ -5,6 +5,8 @@ import $ from 'jquery'; import SearchResults from './search_results.jsx'; import RhsThread from './rhs_thread.jsx'; +import SearchBox from './search_bar.jsx'; +import FileUploadOverlay from './file_upload_overlay.jsx'; import SearchStore from 'stores/search_store.jsx'; import PostStore from 'stores/post_store.jsx'; import UserStore from 'stores/user_store.jsx'; @@ -188,30 +190,43 @@ export default class SidebarRight extends React.Component { expandedClass = 'sidebar--right--expanded'; } + var currentId = UserStore.getCurrentId(); + var searchForm = null; + if (currentId) { + searchForm = <SearchBox isFocus={this.state.searchVisible && Utils.isMobile()}/>; + } + if (this.state.searchVisible) { content = ( - <SearchResults - isMentionSearch={this.state.isMentionSearch} - isFlaggedPosts={this.state.isFlaggedPosts} - isPinnedPosts={this.state.isPinnedPosts} - useMilitaryTime={this.state.useMilitaryTime} - toggleSize={this.toggleSize} - shrink={this.onShrink} - channelDisplayName={this.props.channel ? this.props.channel.display_name : ''} - /> + <div className='sidebar--right__content'> + <div className='search-bar__container sidebar--right__search-header'>{searchForm}</div> + <SearchResults + isMentionSearch={this.state.isMentionSearch} + isFlaggedPosts={this.state.isFlaggedPosts} + isPinnedPosts={this.state.isPinnedPosts} + useMilitaryTime={this.state.useMilitaryTime} + toggleSize={this.toggleSize} + shrink={this.onShrink} + channelDisplayName={this.props.channel ? this.props.channel.display_name : ''} + /> + </div> ); } else if (this.state.postRightVisible) { content = ( - <RhsThread - fromFlaggedPosts={this.state.fromFlaggedPosts} - fromSearch={this.state.fromSearch} - isWebrtc={WebrtcStore.isBusy()} - isMentionSearch={this.state.isMentionSearch} - currentUser={this.state.currentUser} - useMilitaryTime={this.state.useMilitaryTime} - toggleSize={this.toggleSize} - shrink={this.onShrink} - /> + <div className='post-right__container'> + <FileUploadOverlay overlayType='right'/> + <div className='search-bar__container sidebar--right__search-header'>{searchForm}</div> + <RhsThread + fromFlaggedPosts={this.state.fromFlaggedPosts} + fromSearch={this.state.fromSearch} + isWebrtc={WebrtcStore.isBusy()} + isMentionSearch={this.state.isMentionSearch} + currentUser={this.state.currentUser} + useMilitaryTime={this.state.useMilitaryTime} + toggleSize={this.toggleSize} + shrink={this.onShrink} + /> + </div> ); } diff --git a/webapp/components/suggestion/suggestion_box.jsx b/webapp/components/suggestion/suggestion_box.jsx index eade494ef..2ac842846 100644 --- a/webapp/components/suggestion/suggestion_box.jsx +++ b/webapp/components/suggestion/suggestion_box.jsx @@ -25,6 +25,7 @@ export default class SuggestionBox extends React.Component { this.handleCompositionEnd = this.handleCompositionEnd.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.handlePretextChanged = this.handlePretextChanged.bind(this); + this.blur = this.blur.bind(this); this.suggestionId = Utils.generateId(); SuggestionStore.registerSuggestionBox(this.suggestionId); @@ -189,6 +190,10 @@ export default class SuggestionBox extends React.Component { } } + blur() { + this.refs.textbox.blur(); + } + render() { const { type, |