diff --git a/app/assets/stylesheets/chat.scss b/app/assets/stylesheets/chat.scss index d2b4d3240..1cdc52674 100644 --- a/app/assets/stylesheets/chat.scss +++ b/app/assets/stylesheets/chat.scss @@ -63,9 +63,11 @@ margin-bottom: 5px; &:hover { - @include themeable(background, + @include themeable( + background, theme-container-background-hover, - lighten($green, 20%)); + lighten($green, 20%) + ); } } @@ -138,12 +140,8 @@ padding: 8px; font-size: 14px; -webkit-appearance: none; - @include themeable(background, - theme-container-background, - white); - @include themeable(color, - theme-color, - $black); + @include themeable(background, theme-container-background, white); + @include themeable(color, theme-color, $black); @media screen and (min-width: 1000px) { width: calc(100% - 13px); @@ -175,9 +173,7 @@ } .chat__channeltypefilterbutton--active { - @include themeable(color, - theme-anchor-color, - darken($sky-blue, 5%)); + @include themeable(color, theme-anchor-color, darken($sky-blue, 5%)); @media screen and (min-width: 1300px) { border: 1px solid darken($light-medium-gray, 5%); @@ -185,10 +181,7 @@ } .chat__channeltypefilterbutton--inactive { - @include themeable(color, - theme-secondary-color, - lighten($medium-gray, 5%), - ); + @include themeable(color, theme-secondary-color, lighten($medium-gray, 5%)); } .chat_chatconfig { @@ -200,9 +193,7 @@ padding: 3px 12px; display: inline-block; border-radius: 3px; - @include themeable(background, - theme-background, - $lightest-gray); + @include themeable(background, theme-background, $lightest-gray); border: 1px solid $light-medium-gray; font-weight: bold; cursor: default; @@ -305,7 +296,7 @@ box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.4); video { - border-radius: 5px + border-radius: 5px; } } } @@ -318,9 +309,7 @@ top: 0; padding: 80px 7%; z-index: 10; - @include themeable(background, - theme-background, - white); + @include themeable(background, theme-background, white); } .chatNonChatView_exitbutton { @@ -331,9 +320,7 @@ background: transparent; border: 0px; font-size: 1.8em; - @include themeable(color, - theme-color, - $black); + @include themeable(color, theme-color, $black); } .chatNonChatView_contentblock { @@ -341,9 +328,7 @@ padding: 20px; margin-bottom: 10px; max-width: 900px; - @include themeable(box-shadow, - theme-container-box-shadow, - $bold-shadow); + @include themeable(box-shadow, theme-container-box-shadow, $bold-shadow); h2 { margin: 5px auto 5px; @@ -402,22 +387,19 @@ display: flex; flex-direction: row; justify-content: space-between; - @include themeable(border, - theme-container-border, - 1px solid $outline-color); - @include themeable(box-shadow, - theme-container-box-shadow, - $bold-shadow); - @include themeable(background, - theme-container-background, - white); + @include themeable(border, theme-container-border, 1px solid $outline-color); + @include themeable(box-shadow, theme-container-box-shadow, $bold-shadow); + @include themeable(background, theme-container-background, white); flex-flow: row nowrap; } .activechatchannel__conversation { - @include themeable(border-top, + position: relative; + @include themeable( + border-top, theme-container-border, - 1px solid $outline-color); + 1px solid $outline-color + ); order: 1; display: flex; flex-direction: column; @@ -433,21 +415,23 @@ } .activechatchannel__header { - @include themeable(border-bottom, + @include themeable( + border-bottom, theme-container-border, - 1px solid $light-medium-gray); + 1px solid $light-medium-gray + ); padding: 10px 12px; font-weight: bold; font-size: 14px; - @include themeable(background, + @include themeable( + background, theme-container-accent-background, - $light-gray); + $light-gray + ); position: relative; a { - @include themeable(color, - theme-color, - $black); + @include themeable(color, theme-color, $black); } .activechatchannel__channelconfig { @@ -456,9 +440,7 @@ right: 15px; top: 10px; cursor: pointer; - @include themeable(filter, - theme-social-icon-invert, - invert(0)); + @include themeable(filter, theme-social-icon-invert, invert(0)); img { height: 100%; @@ -500,14 +482,15 @@ } .activechatchannel__form { - @include themeable(border-top, + @include themeable( + border-top, theme-container-border, - 1px solid $outline-color); - @include themeable(background, - theme-container-accent-background, - #ededed); + 1px solid $outline-color + ); + @include themeable(background, theme-container-accent-background, #ededed); width: 100%; height: 60px; + position: relative; } .activechatchannel__incomingcall { @@ -525,18 +508,14 @@ .activechatchannel__activecontent { order: 2; flex: 0 1 auto; - @include themeable(border, - theme-border, - 1px solid $outline-color); + @include themeable(border, theme-border, 1px solid $outline-color); padding: 13px; min-width: 50%; @media screen and (min-width: 1440px) { min-width: 45%; } -webkit-overflow-scrolling: touch; - @include themeable(background, - theme-background, - $lightest-gray); + @include themeable(background, theme-background, $lightest-gray); z-index: 200; position: relative; box-sizing: border-box; @@ -576,27 +555,20 @@ .activechatchannel__activecontentexitbutton { border: 0px; font-size: 30px; - @include themeable(color, - theme-container-color, - $medium-gray); + @include themeable(color, theme-container-color, $medium-gray); padding: 0px; background: transparent; position: absolute; left: 4px; top: 4px; - @include themeable(background, - theme-container-accent-background, - white); + @include themeable(background, theme-container-accent-background, white); z-index: 10; height: 29px; width: 29px; line-height: 10px; padding-bottom: 5px; border-radius: 100px; - @include themeable(border, - theme-border, - 1px solid $medium-gray); - + @include themeable(border, theme-border, 1px solid $medium-gray); } .activechatchannel__activeArticle { @@ -618,7 +590,6 @@ border: 0px; } - .activechatchannel__activecontentuserdetails { margin-top: 20px; font-family: $monospace; @@ -627,7 +598,7 @@ .key { color: $medium-gray; margin-bottom: 3px; - font-size: 0.9em + font-size: 0.9em; } } @@ -674,7 +645,8 @@ } } -.activecontent__githubrepo {} +.activecontent__githubrepo { +} .activecontent__githubrepoheader { padding-left: 30px; @@ -738,9 +710,7 @@ padding: 3px 0px; margin-bottom: -5px 0; box-sizing: border-box; - @include themeable(color, - theme-color, - $black); + @include themeable(color, theme-color, $black); &:hover { .chatchanneltab--inactive { @@ -773,9 +743,7 @@ } .chatchanneltab--active { - @include themeable(background, - theme-container-background, - white); + @include themeable(background, theme-container-background, white); border: 1px solid $dark-purple; box-shadow: 3px 3px 0px $dark-purple; } @@ -807,14 +775,12 @@ border: 2px solid $light-medium-gray; border-radius: 100px; } - } .chatchanneltabgroupicon { display: inline-block; margin-left: calc(20px + 0.3vw); } - } .chatchanneltabindicator--new { @@ -863,9 +829,7 @@ bottom: -14px; left: 0; right: 0; - @include themeable(background, - theme-background, - $lightest-gray); + @include themeable(background, theme-background, $lightest-gray); border-top: 1px solid $light-medium-gray; padding: 8px 10px 20px; font-weight: bold; @@ -904,7 +868,7 @@ .chatchannels__misc { height: 70px; - border-top: 1px solid #c9c9c9 + border-top: 1px solid #c9c9c9; } // Chatmessage @@ -914,24 +878,30 @@ max-width: 100%; &:hover { - @include themeable(background, + @include themeable( + background, theme-container-background-hover, - $light-gray); + $light-gray + ); .chatmessagebody__username--link { - @include themeable(background, + @include themeable( + background, theme-container-background-hover, - transparent); + transparent + ); } - } } - -.chatmessage__profileimage {} +.invert-channel-image { + filter: var(--theme-invert-image, none); +} +.chatmessage__profileimage { +} .chatmessage__body { flex-grow: 1; - max-width: calc(100% - 37px) + max-width: calc(100% - 37px); } .chatmessagebody__username { @@ -990,13 +960,16 @@ display: inline-block; &:hover { - @include themeable(background, + @include themeable( + background, theme-container-background-hover, - transparent); + transparent + ); } } -.chatmessagebody__divider {} +.chatmessagebody__divider { +} .chatmessagebody__message { p { @@ -1015,12 +988,8 @@ } a h1 { - @include themeable(color, - theme-container-color, - $black); - @include themeable-important(border-color, - theme-container-color, - #0a0a0a); + @include themeable(color, theme-container-color, $black); + @include themeable-important(border-color, theme-container-color, #0a0a0a); } img { @@ -1050,15 +1019,9 @@ padding: 5px; resize: none; flex-grow: 1; - @include themeable(background, - theme-container-background, - white); - @include themeable(border, - theme-border, - 1px solid $outline-color); - @include themeable(color, - theme-color, - $black); + @include themeable(background, theme-container-background, white); + @include themeable(border, theme-border, 1px solid $outline-color); + @include themeable(color, theme-color, $black); } .messagecomposer__submit { @@ -1096,9 +1059,7 @@ top: -27px; left: 35px; font-family: $monospace; - @include themeable(color, - theme-color, - $dark-gray); + @include themeable(color, theme-color, $dark-gray); } .CodeMirror { @@ -1166,7 +1127,6 @@ display: none; justify-content: end; -webkit-justify-content: flex-end; - } .message__actions span { @@ -1190,9 +1150,7 @@ max-width: 670px; padding: 0px; margin-bottom: 6px; - @include themeable(background, - theme-container-background, - white); + @include themeable(background, theme-container-background, white); .chatchannels__richlinkmainimage { position: relative; width: 100%; @@ -1212,18 +1170,14 @@ vertical-align: -0.25em; &.chatchannels__richlinkprofilepic { border-radius: 100px; - @include themeable(border, - theme-border, - 1px solid $light-medium-gray); + @include themeable(border, theme-border, 1px solid $light-medium-gray); } } } h4 { margin-top: -12px; margin-bottom: 15px; - @include themeable(color, - theme-secondary-color, - $medium-gray); + @include themeable(color, theme-secondary-color, $medium-gray); font-weight: 500; padding: 0px calc(10px + 0.2vw); img { @@ -1231,9 +1185,7 @@ width: 22px; border-radius: 100px; margin-right: 3px; - @include themeable(border, - theme-border, - 1px solid $light-medium-gray); + @include themeable(border, theme-border, 1px solid $light-medium-gray); vertical-align: -6px; } } @@ -1320,3 +1272,50 @@ font-size: 14px; font-weight: bold; } + +.mention__list { + position: absolute; + background: var(--theme-container-background, white); + display: none; + z-index: 1; + border-top: 1px solid #dbdbdb; + bottom: 60px; + width: 100%; + max-height: 280px; + overflow-x: scroll; +} +.mention__list .mention__user { + padding: 5px 10px; + border-bottom: 1px solid #dbdbdb; + cursor: pointer; +} +.compose__outer__container { + position: relative; +} +.mention__user__image { + height: 25px; + width: 25px; + margin-right: 6px; + border-radius: 20px; + align-self: center; +} +.mention__visible { + display: block; +} +.mention__user { + display: grid; + grid-template-columns: 30px 1fr; +} +.mention__user p { + margin: 0px; + font-size: 9px; + color: gray; + width: max-content; +} +.comment-mentioned-all { + color: rgb(213, 138, 0); +} + +.active__message__list { + background: var(--theme-container-accent-background, #f5f6f7); +} diff --git a/app/assets/stylesheets/theme-selector.scss b/app/assets/stylesheets/theme-selector.scss index 6109624b5..33c2b900d 100644 --- a/app/assets/stylesheets/theme-selector.scss +++ b/app/assets/stylesheets/theme-selector.scss @@ -26,7 +26,7 @@ pointer-events: none; } -.rich-selector__radio:focus~.rich-selector__outline { +.rich-selector__radio:focus ~ .rich-selector__outline { position: absolute; top: 1px; right: 7px; @@ -53,7 +53,7 @@ border: 2px solid darken($green, 10%); } -.rich-selector__radio:checked+.rich-selector__indicator { +.rich-selector__radio:checked + .rich-selector__indicator { opacity: 1 !important; } @@ -133,10 +133,10 @@ } .theme-selector--pink-theme { - --theme-background: #FFF7F9; + --theme-background: #fff7f9; --theme-color: #0a0a0a; --theme-top-bar-background: #ff4983; - --theme-top-bar-search-background: #FFF7F9; + --theme-top-bar-search-background: #fff7f9; --theme-container-background: #fff; --theme-container-border: 1px solid #ff4983; } @@ -170,13 +170,8 @@ } .font-selector--default { - font-family: - Palatino, - 'Palatino Linotype', - 'Palatino LT STD', - 'Book Antiqua', - Georgia, - serif; + font-family: Palatino, 'Palatino Linotype', 'Palatino LT STD', 'Book Antiqua', + Georgia, serif; } .font-selector--sans-serif { @@ -198,7 +193,6 @@ font-size: 1.33em; } - // Navbar selector .navbar-selector { @@ -234,7 +228,7 @@ border: 4px solid $green !important; } -.rich-selector__radio:focus~.exp-selector__outline { +.rich-selector__radio:focus ~ .exp-selector__outline { border-radius: 100px; top: 0px; right: 0px; diff --git a/app/controllers/chat_channels_controller.rb b/app/controllers/chat_channels_controller.rb index c92a3a1af..5d44c75eb 100644 --- a/app/controllers/chat_channels_controller.rb +++ b/app/controllers/chat_channels_controller.rb @@ -37,6 +37,7 @@ class ChatChannelsController < ApplicationController def open membership = @chat_channel.chat_channel_memberships.where(user_id: current_user.id).first membership.update(last_opened_at: 1.second.from_now, has_unopened_messages: false) + send_open_notification @chat_channel.index! membership.index! render json: { status: "success", channel: params[:id] }, status: :ok @@ -181,4 +182,13 @@ class ChatChannelsController < ApplicationController render json: { errors: @chat_channel.errors.full_messages } end end + + def send_open_notification + adjusted_slug = if @chat_channel.group? + @chat_channel.adjusted_slug + else + @chat_channel.adjusted_slug(current_user) + end + Pusher.trigger("private-message-notifications-#{session_current_user_id}", "message-opened", { channel_type: @chat_channel.channel_type, adjusted_slug: adjusted_slug }.to_json) + end end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 4421b7b47..d127948fd 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -12,6 +12,8 @@ class MessagesController < ApplicationController pusher_message_created(true) if @message.save pusher_message_created(false) + notify_users(@message.chat_channel.channel_users_ids, "all") + notify_users(@mentioned_users_id, "mention") render json: { status: "success", message: { temp_id: @temp_message_id, id: @message.id } }, status: :created else render json: { @@ -78,12 +80,13 @@ class MessagesController < ApplicationController private def create_pusher_payload(new_message, temp_id) - { + payload = { temp_id: temp_id, id: new_message.id, user_id: new_message.user.id, chat_channel_id: new_message.chat_channel.id, chat_channel_adjusted_slug: new_message.chat_channel.adjusted_slug(current_user, "sender"), + channel_type: new_message.chat_channel.channel_type, username: new_message.user.username, profile_image_url: ProfileImage.new(new_message.user).get(90), message: new_message.message_html, @@ -92,10 +95,16 @@ class MessagesController < ApplicationController timestamp: Time.current, color: new_message.preferred_user_color, reception_method: "pushed" - }.to_json + } + + if new_message.chat_channel.group? + payload[:chat_channel_adjusted_slug] = new_message.chat_channel.adjusted_slug + end + payload.to_json end def message_params + @mentioned_users_id = params[:message][:mentioned_users_id] params.require(:message).permit(:message_markdown, :user_id, :chat_channel_id) end @@ -132,4 +141,17 @@ class MessagesController < ApplicationController logger.info "PUSHER ERROR: #{e.message}" end end + + def notify_users(user_ids, type) + return unless user_ids + + user_ids.each do |id| + message_json = create_pusher_payload(@message, @temp_message_id) + if type == "mention" + Pusher.trigger("private-message-notifications-#{id}", "mentioned", message_json) + else + Pusher.trigger("private-message-notifications-#{id}", "message-created", message_json) + end + end + end end diff --git a/app/javascript/chat/__tests__/__snapshots__/channels.test.jsx.snap b/app/javascript/chat/__tests__/__snapshots__/channels.test.jsx.snap index 21cfbaea2..2cc69af91 100644 --- a/app/javascript/chat/__tests__/__snapshots__/channels.test.jsx.snap +++ b/app/javascript/chat/__tests__/__snapshots__/channels.test.jsx.snap @@ -30,7 +30,7 @@ exports[` expanded with chat channels should render and test snapsho > pic channel name 1 @@ -86,7 +86,7 @@ exports[` expanded with chat channels should render and test snapsho > pic group channel 3 @@ -207,7 +207,7 @@ exports[` not expanded with chat channels should render and test sna > pic channel name 1 @@ -263,7 +263,7 @@ exports[` not expanded with chat channels should render and test sna > pic group channel 3 diff --git a/app/javascript/chat/__tests__/__snapshots__/chat.test.jsx.snap b/app/javascript/chat/__tests__/__snapshots__/chat.test.jsx.snap index 3ee97f2fa..f7145b871 100644 --- a/app/javascript/chat/__tests__/__snapshots__/chat.test.jsx.snap +++ b/app/javascript/chat/__tests__/__snapshots__/chat.test.jsx.snap @@ -73,7 +73,7 @@ exports[` should load chat 1`] = ` > pic channel name 1 @@ -123,7 +123,7 @@ exports[` should load chat 1`] = ` > pic group channel 3 @@ -240,11 +240,19 @@ exports[` should load chat 1`] = ` > More new messages below + +
+
-
+
@@ -253,6 +261,8 @@ exports[` should load chat 1`] = ` id="messageform" maxLength="1000" onKeyDown={[Function]} + onKeyPress={[Function]} + onKeyUp={[Function]} placeholder="Message goes here" />