diff --git a/packages/rocketchat-theme/client/imports/base.less b/packages/rocketchat-theme/client/imports/base.less index 9e7c88f689c..1f429c14618 100644 --- a/packages/rocketchat-theme/client/imports/base.less +++ b/packages/rocketchat-theme/client/imports/base.less @@ -1110,7 +1110,7 @@ label.required::after { top: 0; left: 0; height: 100%; - z-index: 2; + z-index: 3; overflow-y: auto; overflow-x: hidden; width: @rooms-box-width; @@ -1336,6 +1336,8 @@ label.required::after { direction: ltr; padding-left: 8px; padding-bottom: 1em; + position: relative; + padding-top: 50px; } } @@ -1370,7 +1372,7 @@ label.required::after { top: 0; left: 0; width: 100%; - z-index: 1; + z-index: 2; cursor: pointer; min-height: @header-min-height; height: @header-min-height; @@ -1380,7 +1382,7 @@ label.required::after { position: absolute; top: 18px; right: 8px; - z-index: 2; + z-index: 3; cursor: pointer; } @@ -1393,7 +1395,7 @@ label.required::after { text-align: right; min-height: @footer-min-height; height: @footer-min-height; - z-index: 1; + z-index: 2; .logo { display: block; @@ -1585,7 +1587,7 @@ label.required::after { -webkit-justify-content: center; &.top-unread-rooms { - top: 60px; + top: 105px; } &.bottom-unread-rooms { @@ -1611,6 +1613,43 @@ label.required::after { } } +.toolbar { + position: fixed; + width: 244px; + z-index: 3; + top: 60px; + padding-top: 10px; +} + +.toolbar-search { + padding-right: 8px; + position: relative; +} + +.toolbar-search__icon { + position: absolute; + top: 0; + left: 0; + line-height: 35px; + width: 35px; + text-align: center; +} + +.toolbar-search__icon--cancel { + left: auto; + right: 8px; + opacity: 0; + transition: opacity 0.3s; +} + +.toolbar-search__input { + padding: 6px 35px !important; + + &:focus + .toolbar-search__icon--cancel { + opacity: 1; + } +} + .new-room-highlight a { -webkit-animation: highlight 2s infinite; -moz-animation: highlight 2s infinite; @@ -1700,90 +1739,6 @@ label.required::after { } } -.spotlight { - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 1000; - display: flex; - display: -webkit-flex; - justify-content: center; - padding: 0 40px; - - > .spotlight-input { - position: relative; - width: 100%; - max-width: 600px; - font-size: 24px; - margin-top: 6%; - margin-bottom: auto; - border-radius: 5px; - overflow: hidden; - box-shadow: 0 15px 50px rgba(0, 0, 0, 0.5); - - > input { - box-shadow: none; - border-width: 0; - line-height: 46px; - height: 46px; - padding: 0 10px 0 46px; - } - - > i { - position: absolute; - z-index: 10; - line-height: 46px; - width: 46px; - text-align: center; - font-weight: 100; - } - - .message-popup { - position: relative; - box-shadow: none; - border-radius: 0; - - .popup-item { - border-top: 1px solid #eaeaea; - line-height: 40px; - font-size: 20px; - padding: 0 10px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - - i { - margin-right: 4px; - line-height: 28px; - display: inline-block; - border-radius: 20px; - width: 28px; - } - - &.selected { - i { - box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2); - } - } - - span { - float: right; - border-radius: 2px; - margin-top: 10px; - min-width: 20px; - padding: 0 2px; - text-align: center; - font-size: 14px; - line-height: 20px; - font-weight: 800; - } - } - } - } -} - // MAIN CONTENT + MAIN PAGES // .main-content { @@ -2506,11 +2461,30 @@ label.required::after { 0 -1px 10px 0 rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.16); border-radius: 5px; -} -.message-popup.popup-down { - bottom: auto; - top: 0; + &.popup-down { + bottom: auto; + top: 0; + } + + &.search-results-list { + top: 25px; + height: calc(~"100vh - 200px"); + overflow-y: auto; + box-shadow: none; + border-radius: 0; + + .popup-item { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + padding-left: 6px; + } + + .unread { + top: 8px; + } + } } .message-popup-title { diff --git a/packages/rocketchat-theme/client/imports/rtl.less b/packages/rocketchat-theme/client/imports/rtl.less index 23519c92ef4..ccf2f583635 100644 --- a/packages/rocketchat-theme/client/imports/rtl.less +++ b/packages/rocketchat-theme/client/imports/rtl.less @@ -802,19 +802,22 @@ .left(12px); } - .spotlight { - > .spotlight-input { - .icon-search { - left: 0; - } + .toolbar-search { + padding: 0 0 0 8px; + } - .message-popup { - .popup-item { - span { - float: left; - } - } - } + .toolbar-search__icon { + right: 0; + } + + .toolbar-search__icon--cancel { + right: auto; + left: 0; + } + + .message-popup.search-results-list { + .popup-item { + padding-right: 6px; } } } diff --git a/packages/rocketchat-theme/server/colors.less b/packages/rocketchat-theme/server/colors.less index 737a4c43284..c1d83738c3a 100755 --- a/packages/rocketchat-theme/server/colors.less +++ b/packages/rocketchat-theme/server/colors.less @@ -179,6 +179,10 @@ background-color: @transparent-light; } +.border-transparent-lighter { + border-color: @transparent-lighter; +} + .background-transparent-lightest { background-color: @transparent-lightest; } @@ -241,8 +245,18 @@ .input-shade(@primary-font-color, @content-background-color); +.toolbar-search__input { + &:focus { + border-color: fade(@primary-background-contrast, 50%); + } + + &::placeholder { + color: @transparent-lighter; + } +} + .flex-nav { - .input-shade(@primary-background-contrast, @primary-background-color); + .input-shade(@primary-background-contrast, @transparent-lighter); input { &:focus { @@ -529,7 +543,8 @@ a:hover { background-color: @tertiary-font-color; } - .rooms-list { + .rooms-list, + .toolbar { background-color: lighten(@primary-background-color, 2.5%); } @@ -567,6 +582,14 @@ a:hover { } } +.message-popup.search-results-list { + background-color: lighten(@primary-background-color, 2.5%); + + .popup-item.selected { + background-color: @transparent-darker; + } +} + /** ---------------------------------------------------------------------------- * Flex tabs / admin fly-out panels */ diff --git a/packages/rocketchat-theme/server/lesshat.less b/packages/rocketchat-theme/server/lesshat.less index cf7cf4758d6..b56ab5c59d4 100644 --- a/packages/rocketchat-theme/server/lesshat.less +++ b/packages/rocketchat-theme/server/lesshat.less @@ -34,7 +34,7 @@ } } - .diabled label, + .disabled label, [disabled] label { color: mix(@color, @bg, 75%); } diff --git a/packages/rocketchat-ui-master/master/main.coffee b/packages/rocketchat-ui-master/master/main.coffee index dca917d4fcf..3c757092ced 100644 --- a/packages/rocketchat-ui-master/master/main.coffee +++ b/packages/rocketchat-ui-master/master/main.coffee @@ -7,10 +7,7 @@ Template.body.onRendered -> if e.keyCode is 80 and (e.ctrlKey is true or e.metaKey is true) and e.shiftKey is false e.preventDefault() e.stopPropagation() - spotlight.show() - - if e.keyCode is 27 - spotlight.hide() + toolbarSearch.focus() unread = Session.get('unread') if e.keyCode is 27 and e.shiftKey is true and unread? and unread isnt '' diff --git a/packages/rocketchat-ui-master/master/main.html b/packages/rocketchat-ui-master/master/main.html index 216d506f849..7434df1c065 100644 --- a/packages/rocketchat-ui-master/master/main.html +++ b/packages/rocketchat-ui-master/master/main.html @@ -42,7 +42,6 @@ {{#if requirePasswordChange}} {{> loginLayout center="resetPassword"}} {{else}} - {{> spotlight}} {{> videoCall overlay=true}}
{{/each}} + {{#unless data}} + {{#unless isLoading.get}} + {{#if emptyTemplate}} + {{> Template.dynamic template=emptyTemplate}} + {{/if}} + {{/unless}} + {{/unless}} + {{#if isLoading.get}} + {{> loading}} + {{/if}} {{/if}} diff --git a/packages/rocketchat-ui-sidenav/package.js b/packages/rocketchat-ui-sidenav/package.js index d58478b389e..4615b5b5982 100644 --- a/packages/rocketchat-ui-sidenav/package.js +++ b/packages/rocketchat-ui-sidenav/package.js @@ -36,6 +36,7 @@ Package.onUse(function(api) { api.addFiles('side-nav/privateGroupsFlex.html', 'client'); api.addFiles('side-nav/sideNav.html', 'client'); api.addFiles('side-nav/starredRooms.html', 'client'); + api.addFiles('side-nav/toolbar.html', 'client'); api.addFiles('side-nav/unreadRooms.html', 'client'); api.addFiles('side-nav/userStatus.html', 'client'); @@ -55,6 +56,7 @@ Package.onUse(function(api) { api.addFiles('side-nav/privateGroupsFlex.coffee', 'client'); api.addFiles('side-nav/sideNav.coffee', 'client'); api.addFiles('side-nav/starredRooms.coffee', 'client'); + api.addFiles('side-nav/toolbar.js', 'client'); api.addFiles('side-nav/unreadRooms.coffee', 'client'); }); diff --git a/packages/rocketchat-ui-sidenav/side-nav/sideNav.html b/packages/rocketchat-ui-sidenav/side-nav/sideNav.html index 4d15c91a242..9a2ca2abb77 100644 --- a/packages/rocketchat-ui-sidenav/side-nav/sideNav.html +++ b/packages/rocketchat-ui-sidenav/side-nav/sideNav.html @@ -9,6 +9,7 @@
+ {{> toolbar}} {{> unreadRooms }} {{#each roomType}} diff --git a/packages/rocketchat-ui-sidenav/side-nav/toolbar.html b/packages/rocketchat-ui-sidenav/side-nav/toolbar.html new file mode 100644 index 00000000000..5ffa0c4713f --- /dev/null +++ b/packages/rocketchat-ui-sidenav/side-nav/toolbar.html @@ -0,0 +1,23 @@ + + + + + diff --git a/packages/rocketchat-ui-sidenav/side-nav/toolbar.js b/packages/rocketchat-ui-sidenav/side-nav/toolbar.js new file mode 100644 index 00000000000..d44f7fc0198 --- /dev/null +++ b/packages/rocketchat-ui-sidenav/side-nav/toolbar.js @@ -0,0 +1,149 @@ +let isLoading; +let filterText = ''; +let usernamesFromClient; +let resultsFromClient; + +Meteor.startup(() => { + isLoading = new ReactiveVar(false); +}); + +const toolbarSearch = { + clear() { + $('.toolbar-search__input').val(''); + $('.toolbar-search__input').trigger({ + type: 'keyup', + which: 27 + }); + }, + + focus() { + $('.toolbar-search__input').focus(); + } +}; + +this.toolbarSearch = toolbarSearch; + +const getFromServer = (cb) => { + isLoading.set(true); + const currentFilter = filterText; + + Meteor.call('spotlight', currentFilter, usernamesFromClient, (err, results) => { + if (currentFilter !== filterText) { + return; + } + + isLoading.set(false); + + if (err) { + console.log(err); + return false; + } + + const resultsFromServer = []; + const usersLength = results.users.length; + const roomsLength = results.rooms.length; + + if (usersLength) { + for (let i = 0; i < usersLength; i++) { + resultsFromServer.push({ + _id: results.users[i]._id, + t: 'd', + name: results.users[i].username + }); + } + } + + if (roomsLength) { + for (let i = 0; i < roomsLength; i++) { + resultsFromServer.push({ + _id: results.rooms[i]._id, + t: results.rooms[i].t, + name: results.rooms[i].name + }); + } + } + + if (resultsFromServer.length) { + cb(resultsFromClient.concat(resultsFromServer)); + } + }); +}; + +const getFromServerThrottled = _.throttle(getFromServer, 500); + +Template.toolbar.helpers({ + results() { + return Template.instance().resultsList.get(); + }, + popupConfig() { + const config = { + cls: 'search-results-list', + collection: RocketChat.models.Subscriptions, + template: 'toolbarSearchList', + emptyTemplate: 'toolbarSearchListEmpty', + input: '.toolbar-search__input', + closeOnEsc: false, + blurOnSelectItem: true, + isLoading: isLoading, + getFilter: function(collection, filter, cb) { + filterText = filter; + resultsFromClient = collection.find({name: new RegExp((RegExp.escape(filter)), 'i'), rid: {$ne: Session.get('openedRoom')}}, {limit: 10, sort: {unread: -1, ls: -1}}).fetch(); + + const resultsFromClientLength = resultsFromClient.length; + usernamesFromClient = [Meteor.user().username]; + + for (let i = 0; i < resultsFromClientLength; i++) { + if (resultsFromClient[i].t === 'd') { + usernamesFromClient.push(resultsFromClient[i].name); + } + } + + cb(resultsFromClient); + + getFromServerThrottled(cb); + }, + getValue: function(_id, collection, records) { + const doc = _.findWhere(records, {_id: _id}); + + RocketChat.roomTypes.openRouteLink(doc.t, doc, FlowRouter.current().queryParams); + } + }; + + return config; + } +}); + +Template.toolbar.events({ + 'blur .toolbar-search__input'() { + toolbarSearch.clear(); + }, + + 'keyup .toolbar-search__input'(e) { + if (e.which === 27) { + e.preventDefault(); + e.stopPropagation(); + + const $inputMessage = $('textarea.input-message'); + + if (0 === $inputMessage.length) { + return; + } + + $inputMessage.focus(); + } + } +}); + +Template.toolbarSearchList.helpers({ + icon() { + return RocketChat.roomTypes.getIcon(this.t); + }, + + userStatus() { + if (this.t === 'd') { + return 'status-' + (Session.get(`user_${this.name}_status`) || 'offline'); + } else { + return 'status-' + (RocketChat.roomTypes.getUserStatus(this.t, this.rid || this._id) || 'offline'); + } + } +}); diff --git a/packages/rocketchat-ui/package.js b/packages/rocketchat-ui/package.js index 3b868ee1e77..82eb53d0e43 100644 --- a/packages/rocketchat-ui/package.js +++ b/packages/rocketchat-ui/package.js @@ -91,8 +91,6 @@ Package.onUse(function(api) { api.addFiles('views/app/roomSearch.html', 'client'); api.addFiles('views/app/secretURL.html', 'client'); api.addFiles('views/app/userSearch.html', 'client'); - api.addFiles('views/app/spotlight/spotlight.html', 'client'); - api.addFiles('views/app/spotlight/spotlightTemplate.html', 'client'); api.addFiles('views/app/videoCall/videoButtons.html', 'client'); api.addFiles('views/app/videoCall/videoCall.html', 'client'); @@ -106,9 +104,6 @@ Package.onUse(function(api) { api.addFiles('views/app/room.coffee', 'client'); api.addFiles('views/app/roomSearch.coffee', 'client'); api.addFiles('views/app/secretURL.coffee', 'client'); - api.addFiles('views/app/spotlight/mobileMessageMenu.coffee', 'client'); - api.addFiles('views/app/spotlight/spotlight.coffee', 'client'); - api.addFiles('views/app/spotlight/spotlightTemplate.js', 'client'); api.addFiles('views/app/videoCall/videoButtons.coffee', 'client'); api.addFiles('views/app/videoCall/videoCall.coffee', 'client'); }); diff --git a/packages/rocketchat-ui/views/app/spotlight/mobileMessageMenu.coffee b/packages/rocketchat-ui/views/app/spotlight/mobileMessageMenu.coffee deleted file mode 100644 index 5a07bbff3ff..00000000000 --- a/packages/rocketchat-ui/views/app/spotlight/mobileMessageMenu.coffee +++ /dev/null @@ -1,59 +0,0 @@ -@mobileMessageMenu = - show: (message, template, e, scope) -> - if not window.plugins?.actionsheet? - return - - options = - 'androidTheme': window.plugins.actionsheet.ANDROID_THEMES.THEME_HOLO_LIGHT - 'buttonLabels': [ - TAPi18n.__('Report Abuse') - ] - androidEnableCancelButton: true - addCancelButtonWithLabel: TAPi18n.__('Cancel') - # 'position': [20, 40] // for iPad pass in the [x, y] position of the popover - - buttonActions = [ - mobileMessageMenu.reportAbuse - ] - - buttons = RocketChat.MessageAction.getButtons message, (message.customClass or 'message-mobile') - for button in buttons - if button.id is 'delete-message' - options.addDestructiveButtonWithLabel = TAPi18n.__(button.i18nLabel) - buttonActions.unshift button.action - else - buttonActions.push button.action - options.buttonLabels.push TAPi18n.__(button.i18nLabel) - - window.plugins.actionsheet.show options, (buttonIndex) -> - if buttonActions[buttonIndex-1]? - buttonActions[buttonIndex-1].call scope, e, template, message - - reportAbuse: (e, t, message) -> - swal { - title: TAPi18n.__('Report_this_message_question_mark') - text: message.msg - inputPlaceholder: TAPi18n.__('Why_do_you_want_to_report_question_mark') - type: 'input' - showCancelButton: true - confirmButtonColor: '#DD6B55' - confirmButtonText: TAPi18n.__("Report_exclamation_mark") - cancelButtonText: TAPi18n.__('Cancel') - closeOnConfirm: false - html: false - }, (inputValue) -> - if inputValue is false - return false - - if inputValue is "" - swal.showInputError(TAPi18n.__("You_need_to_write_something")) - return false - - Meteor.call 'reportMessage', message, inputValue - - swal - title: TAPi18n.__("Report_sent") - text: TAPi18n.__("Thank_you_exclamation_mark") - type: 'success' - timer: 1000 - showConfirmButton: false diff --git a/packages/rocketchat-ui/views/app/spotlight/spotlight.coffee b/packages/rocketchat-ui/views/app/spotlight/spotlight.coffee deleted file mode 100644 index 5e43e46d9b8..00000000000 --- a/packages/rocketchat-ui/views/app/spotlight/spotlight.coffee +++ /dev/null @@ -1,64 +0,0 @@ -@spotlight = - hide: -> - $('.spotlight').addClass('hidden') - - show: -> - $('.spotlight input').val('') - $('.spotlight').removeClass('hidden') - $('.spotlight input').focus() - -getFromServer = (filter, records, cb) => - Meteor.call 'spotlight', filter, Meteor.user().username, (err, results) -> - if err? - return console.log err - - server = [] - - if results?.users?.length > 0 - for user in results.users when not _.findWhere(records, {t: 'd', name: user.username})? - server.push({ - _id: user._id - t: 'd', - name: user.username - }) - - if results?.rooms?.length > 0 - for room in results.rooms - server.push({ - _id: room._id - t: room.t, - name: room.name - }) - - if server.length > 0 - cb(records.concat(server)) - -getFromServerDelayed = _.throttle getFromServer, 500 - -Template.spotlight.helpers - popupConfig: -> - config = - cls: 'popup-down' - collection: RocketChat.models.Subscriptions - template: 'spotlightTemplate' - input: '[name=spotlight]' - getFilter: (collection, filter, cb) -> - exp = new RegExp("#{RegExp.escape filter}", 'i') - - records = collection.find({name: exp, rid: {$ne: Session.get('openedRoom')}}, {limit: 10, sort: {unread: -1, ls: -1}}).fetch() - - cb(records) - - if filter?.trim().length < 1 or records.length >= 5 - return - - getFromServerDelayed(filter, records, cb) - - getValue: (_id, collection, records, firstPartValue) -> - doc = _.findWhere(records, {_id: _id}) - - RocketChat.roomTypes.openRouteLink(doc.t, doc, FlowRouter.current().queryParams) - - spotlight.hide() - - return config diff --git a/packages/rocketchat-ui/views/app/spotlight/spotlight.html b/packages/rocketchat-ui/views/app/spotlight/spotlight.html deleted file mode 100644 index f291a1bbf9e..00000000000 --- a/packages/rocketchat-ui/views/app/spotlight/spotlight.html +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.html b/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.html deleted file mode 100644 index c0860daa368..00000000000 --- a/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.html +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.js b/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.js deleted file mode 100644 index 631931f6eb6..00000000000 --- a/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.js +++ /dev/null @@ -1,13 +0,0 @@ -Template.spotlightTemplate.helpers({ - icon() { - return RocketChat.roomTypes.getIcon(this.t); - }, - - userStatus() { - if (this.t === 'd') { - return 'status-' + (Session.get(`user_${this.name}_status`) || 'offline'); - } else { - return 'status-' + (RocketChat.roomTypes.getUserStatus(this.t, this.rid || this._id) || 'offline'); - } - } -}); diff --git a/server/publications/spotlight.coffee b/server/publications/spotlight.coffee index 9981a6dd5a6..6d9a20c1052 100644 --- a/server/publications/spotlight.coffee +++ b/server/publications/spotlight.coffee @@ -23,4 +23,4 @@ DDPRateLimiter.addRule name: 'spotlight' userId: (userId) -> return true -, 10, 10000 +, 100, 100000