diff --git a/app/controllers/chat_channels_controller.rb b/app/controllers/chat_channels_controller.rb index 61ba656f8..e73e5e5ca 100644 --- a/app/controllers/chat_channels_controller.rb +++ b/app/controllers/chat_channels_controller.rb @@ -42,7 +42,8 @@ class ChatChannelsController < ApplicationController if banned_user banned_user.add_role :banned banned_user.messages.each(&:destroy!) - Pusher.trigger(@chat_channel.id, "user-banned", { userId: banned_user.id }.to_json) + notification_channels = @chat_channel.chat_channel_memberships.pluck(:user_id).map { |id| "message-notifications-#{id}"} + Pusher.trigger(notification_channels, "user-banned", { userId: banned_user.id }.to_json) render json: { status: "success", message: "banned!" }, status: 200 else render json: { status: "error", message: "username not found" }, status: 400 diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index ef410c25a..687714df6 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -10,7 +10,7 @@ class MessagesController < ApplicationController begin message_json = create_pusher_payload(@message) notification_channels = @message.chat_channel.chat_channel_memberships.pluck(:user_id).map { |id| "message-notifications-#{id}"} - Pusher.trigger([@message.chat_channel.id] + notification_channels, "message-created", message_json) + Pusher.trigger(notification_channels, "message-created", message_json) success = true rescue Pusher::Error => e logger.info "PUSHER ERROR: #{e.message}" @@ -46,6 +46,7 @@ class MessagesController < ApplicationController message: new_message.message_html, timestamp: new_message.created_at, color: new_message.preferred_user_color, + reception_method: "pushed" }.to_json end diff --git a/app/controllers/pusher_controller.rb b/app/controllers/pusher_controller.rb new file mode 100644 index 000000000..f382a6609 --- /dev/null +++ b/app/controllers/pusher_controller.rb @@ -0,0 +1,13 @@ +class PusherController < ApplicationController + + def auth + if current_user + response = pusher_client.authenticate(params[:channel_name], params[:socket_id], { + user_id: current_user.id, # => required + }) + render json: response + else + render text: 'Forbidden', status: '403' + end + end +end \ No newline at end of file diff --git a/app/javascript/chat/chat.jsx b/app/javascript/chat/chat.jsx index eb3240409..94874f423 100644 --- a/app/javascript/chat/chat.jsx +++ b/app/javascript/chat/chat.jsx @@ -34,22 +34,12 @@ export default class Chat extends Component { } componentDidMount() { - this.state.chatChannels.forEach(channel => { + this.state.chatChannels.slice(0, 3).forEach(channel => { this.setupChannel(channel.id); }); setupObserver(this.observerCallback); - } - - componentDidUpdate() { - if (!this.state.scrolled) { - scrollToBottom(); - } - } - - setupChannel = channelId => { - getAllMessages(channelId, this.receiveAllMessages); setupPusher(this.props.pusherKey, { - channelId, + channelId: `message-notifications-${window.currentUser.id}`, messageCreated: this.receiveNewMessage, channelCleared: this.clearChannel, redactUserMessages: this.redactUserMessages, @@ -59,6 +49,18 @@ export default class Chat extends Component { this.handleChannelOpenSuccess, null, ); + } + + componentDidUpdate() { + if (!this.state.scrolled) { + scrollToBottom(); + } + } + + setupChannel = channelId => { + if (this.state.messages[channelId].length === 0 || this.state.messages[channelId][0].reception_method === 'pushed'){ + getAllMessages(channelId, this.receiveAllMessages); + } }; observerCallback = entries => { @@ -161,6 +163,7 @@ export default class Chat extends Component { handleSwitchChannel = e => { e.preventDefault(); + this.setupChannel(e.target.dataset.channelId); this.setState({ activeChannelId: parseInt(e.target.dataset.channelId), scrolled: false, diff --git a/app/javascript/src/utils/pusher.js b/app/javascript/src/utils/pusher.js index c006a256c..c55df0bb8 100644 --- a/app/javascript/src/utils/pusher.js +++ b/app/javascript/src/utils/pusher.js @@ -2,10 +2,15 @@ import Pusher from 'pusher-js'; export default function setupPusher(key, callbackObjects) { const pusher = new Pusher(key, { + authEndpoint: '/pusher/auth', + auth: { + headers: { + 'X-CSRF-Token': window.csrfToken + } + }, cluster: 'us2', encrypted: true, }); - const channel = pusher.subscribe(callbackObjects.channelId.toString()); channel.bind('message-created', callbackObjects.messageCreated); channel.bind('channel-cleared', callbackObjects.channelCleared); diff --git a/app/models/chat_channel.rb b/app/models/chat_channel.rb index b4bbd2771..9408ea09d 100644 --- a/app/models/chat_channel.rb +++ b/app/models/chat_channel.rb @@ -10,7 +10,8 @@ class ChatChannel < ApplicationRecord def clear_channel messages.each(&:destroy!) - Pusher.trigger(id, "channel-cleared", { chat_channel_id: id }.to_json) + notification_channels = chat_channel_memberships.pluck(:user_id).map { |id| "message-notifications-#{id}"} + Pusher.trigger(notification_channels, "channel-cleared", { chat_channel_id: id }.to_json) true rescue Pusher::Error => e logger.info "PUSHER ERROR: #{e.message}" diff --git a/config/routes.rb b/config/routes.rb index 3bf87a62f..92e37c38c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -102,6 +102,8 @@ Rails.application.routes.draw do get "/💌" => "chat_channels#index" get "/💌/:slug" => "chat_channels#index" + post "/pusher/auth" => "chat_channels#index" + # resources :users get "/social_previews/article/:id" => "social_previews#article" diff --git a/config/webpack/environment.js b/config/webpack/environment.js index 215c4bfa9..89dc547d1 100644 --- a/config/webpack/environment.js +++ b/config/webpack/environment.js @@ -1,9 +1,14 @@ -const { environment } = require('@rails/webpacker'); -const customConfig = require('./custom'); +// const { environment } = require('@rails/webpacker'); +// const customConfig = require('./custom'); -environment.config.set('resolve.extensions', ['.foo', '.bar']); -environment.config.set('output.filename', '[name].js'); -environment.config.merge(customConfig); -environment.config.delete('output.chunkFilename'); +// environment.config.set('resolve.extensions', ['.foo', '.bar']); +// environment.config.set('output.filename', '[name].js'); +// environment.config.merge(customConfig); +// environment.config.delete('output.chunkFilename'); -module.exports = environment; +// module.exports = environment; + + +const { environment } = require('@rails/webpacker') + +module.exports = environment \ No newline at end of file