chat 0.2.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -8
  3. data/Rakefile +2 -0
  4. data/app/assets/javascripts/chat/channels/message.coffee +33 -43
  5. data/app/assets/javascripts/chat/channels/status.coffee +2 -2
  6. data/app/assets/javascripts/chat/messages.coffee +12 -11
  7. data/app/assets/stylesheets/chat/avatar_grid.sass +40 -0
  8. data/app/assets/stylesheets/chat/chat.sass +9 -4
  9. data/app/assets/stylesheets/chat/checkbox.sass +3 -3
  10. data/app/assets/stylesheets/chat/emojionearea.min.css +1 -1
  11. data/app/assets/stylesheets/chat/header.sass +25 -8
  12. data/app/assets/stylesheets/chat/launch.sass +39 -3
  13. data/app/assets/stylesheets/chat/list.sass +56 -23
  14. data/app/assets/stylesheets/chat/message_form.sass +7 -4
  15. data/app/assets/stylesheets/chat/new.sass +27 -22
  16. data/app/assets/stylesheets/chat/transcript.sass +60 -64
  17. data/app/channels/chat/messages_channel.rb +3 -2
  18. data/app/channels/chat/notification_channel.rb +2 -0
  19. data/app/channels/chat/status_channel.rb +12 -10
  20. data/app/controllers/chat/application_controller.rb +5 -1
  21. data/app/controllers/chat/conversations_controller.rb +24 -2
  22. data/app/controllers/chat/messages_controller.rb +8 -2
  23. data/app/helpers/chat/application_helper.rb +35 -24
  24. data/app/jobs/chat/application_job.rb +9 -1
  25. data/app/jobs/chat/message_relay_job.rb +5 -13
  26. data/app/jobs/chat/notification_relay_job.rb +10 -4
  27. data/app/jobs/chat/status_relay_job.rb +3 -3
  28. data/app/mailers/chat/application_mailer.rb +2 -0
  29. data/app/models/chat/application_record.rb +2 -0
  30. data/app/models/chat/conversation.rb +12 -0
  31. data/app/models/chat/dot_command.rb +2 -0
  32. data/app/models/chat/dot_command/gif.rb +2 -0
  33. data/app/models/chat/dot_command/shrug.rb +3 -1
  34. data/app/models/chat/dot_command/validator.rb +3 -1
  35. data/app/models/chat/message.rb +10 -2
  36. data/app/models/chat/session.rb +3 -3
  37. data/app/views/chat/_chat.html.haml +10 -6
  38. data/app/views/chat/conversations/_conversation.html.haml +23 -0
  39. data/app/views/chat/conversations/_index.html.haml +1 -6
  40. data/app/views/chat/conversations/_new.html.haml +2 -4
  41. data/app/views/chat/conversations/_show.html.haml +8 -7
  42. data/app/views/chat/conversations/create.js.erb +14 -10
  43. data/app/views/chat/conversations/show.js.erb +8 -5
  44. data/app/views/chat/messages/_message.haml +9 -12
  45. data/config/routes.rb +4 -2
  46. data/lib/chat.rb +5 -1
  47. data/lib/chat/engine.rb +2 -0
  48. data/lib/chat/user.rb +7 -12
  49. data/lib/chat/version.rb +3 -1
  50. data/lib/generators/chat/install/install_generator.rb +2 -0
  51. data/lib/generators/chat/install/templates/add_chat_to_users.rb +3 -1
  52. data/lib/generators/chat/install/templates/chat.rb +2 -0
  53. data/lib/generators/chat/install/templates/create_chat.rb +19 -7
  54. data/lib/tasks/chat_tasks.rake +1 -0
  55. metadata +15 -48
  56. data/app/models/chat/dot_command/leave.rb +0 -16
@@ -1,7 +1,7 @@
1
- @import "https://fonts.googleapis.com/css?family=Lato:300&subset=latin-ext"
1
+ @import "https://fonts.googleapis.com/css?family=Lato:300,400,700,900"
2
2
 
3
3
  #chat .new_message
4
- margin: 0px 40px 36px 40px
4
+ margin: 0px 20px 25px 20px
5
5
  flex-direction: column
6
6
  display: flex
7
7
  position: relative
@@ -15,7 +15,7 @@
15
15
  cursor: pointer
16
16
  font-size: 22px
17
17
  &:hover
18
- color: #212121
18
+ color: #fff
19
19
  input[type='text'], textarea
20
20
  font-size: 17px
21
21
  font-family: "Lato" !important
@@ -35,7 +35,7 @@
35
35
  width: 0
36
36
  bottom: 0px
37
37
  position: absolute
38
- background: #3f51b5
38
+ background: #fff
39
39
  transition: 0.2s ease all
40
40
  -moz-transition: 0.2s ease all
41
41
  -webkit-transition: 0.2s ease all
@@ -48,3 +48,6 @@
48
48
  width: 50%
49
49
  input[type='file']
50
50
  display: none !important
51
+ .emojionearea .emojionearea-editor
52
+ border-bottom: 1px solid #bdbdbd !important
53
+ color: #fff !important
@@ -1,52 +1,57 @@
1
- @import "https://fonts.googleapis.com/css?family=Lato:300&subset=latin-ext"
1
+ @import "https://fonts.googleapis.com/css?family=Lato:300,400,700,900"
2
2
 
3
3
  #chat .new_conversation
4
- height: calc(100% - 48px)
5
- display: none
4
+ height: calc(100% - 50px)
5
+ overflow-y: scroll
6
+ position: absolute
7
+ right: 100%
8
+ transition: 0.5s
9
+ width: 100%
10
+ z-index: 13
11
+ display: flex
6
12
  flex-direction: column
7
- .chat__user-check-boxes
8
- margin: 10px 20px 0px 20px
9
- display: flex
10
- flex-direction: column
11
- height: calc(100% - 48px)
12
- overflow-y: auto
13
- &::-webkit-scrollbar
14
- display: none
13
+ &::-webkit-scrollbar
14
+ visibility: hidden
15
15
  label
16
16
  position: relative
17
17
  margin: 1rem
18
- line-height: 135%
19
18
  cursor: pointer
20
- font-size: 18px
21
19
  font-family: "Lato" !important
22
20
  letter-spacing: 1.5px !important
23
21
  padding-left: 40px
22
+ color: #fff
23
+ width: calc(100% - 40px - 1rem)
24
24
  .chat__status
25
25
  &:after
26
26
  content: "\2022"
27
27
  &.offline
28
28
  &:after
29
- color: #EF5350
29
+ color: hsl(355, 65%, 65%)
30
30
  &.online
31
31
  &:after
32
32
  color: #AED581
33
33
 
34
+ .chat__submit-container
35
+ margin: 1rem
36
+ padding: 10px 0
37
+ width: calc(100% - 1rem)
38
+ display: flex
39
+ flex-direction: column
40
+ justify-content: center
41
+ align-items: center
42
+
34
43
  input[type='submit']
35
- border-top: 1px solid #BDBDBD
36
- border-left: none
37
- border-bottom: none
38
- border-right: none
44
+ border: none
39
45
  font-family: "Lato" !important
40
46
  letter-spacing: 1.5px !important
41
47
  font-size: 17px
42
48
  background: transparent
43
- width: 100%
44
- padding: 10px 0 10px 0
49
+ padding: 0
45
50
  cursor: pointer
46
51
  transition: all 0.3s ease
47
52
  z-index: 10
48
- &:hover
49
- background: #BDBDBD
53
+ color: #fff
54
+ margin: 0px
50
55
 
51
56
  #chat .chat__errors
52
57
  text-align: center
@@ -1,76 +1,72 @@
1
1
  #chat .current_chat
2
- height: calc(100% - 48px)
2
+ display: flex
3
3
  flex-direction: column
4
+ overflow-y: scroll
5
+ position: absolute
6
+ width: 100%
7
+ height: calc(100% - 50px)
8
+ left: 100%
9
+ opacity: 1
10
+ transition: 0.5s
11
+ z-index: 13
12
+ &::-webkit-scrollbar
13
+ visibility: hidden
4
14
  img.chat__user-avatar
5
15
  width: 50px
6
16
  height: 50px
7
17
  object-fit: cover
8
18
  border-radius: 50%
19
+ .transcript_placeholder_avatar
20
+ width: 50px
21
+ height: 50px
9
22
  i.chat__user-avatar
10
23
  font-size: 50px
11
24
  .chat__transcript
12
- max-height: calc(100% - 78px)
13
- overflow-y: auto
14
- &::-webkit-scrollbar
15
- display: none
16
- .chat__image-message
17
- width: 100%
18
- padding-top: 10px
19
- padding-bottom: 10px
20
- img
21
- width: 100%
22
- border-bottom: 4px solid #C8E6C9
23
- &.current img
24
- border-bottom: 4px solid #B2EBF2
25
- .chat__message
26
- padding: 10px
27
- display: flex
28
- flex-direction: row
29
- img
30
- font-size: inherit
31
- height: 2ex
32
- width: 2.1ex
33
- min-height: 20px
34
- min-width: 20px
35
- display: inline-block
36
- margin: -.2ex .15em .2ex
37
- line-height: normal
38
- vertical-align: middle
39
- max-width: 100%
40
- top: 0
41
- .text
42
- padding: 5px
43
- flex: 1
44
- position: relative
25
+ margin-left: 25px
26
+ margin-right: 25px
27
+ .message-container
28
+ display: flex
29
+ flex-direction: row
45
30
  &.right
46
- margin-right: 10px
47
- border-radius: 5px 0px 5px 5px
48
- background: #B2EBF2
49
- border: none
50
- &:after
51
- content: ""
52
- position: absolute
53
- border-style: solid
54
- border-width: 0px 0 13px 15px
55
- border-color: transparent #B2EBF2
56
- display: block
57
- width: 0
58
- z-index: 1
59
- right: -15px
60
- top: 0px
61
- &.left
62
- margin-left: 10px
63
- border-radius: 0px 5px 5px 5px
64
- background: #C8E6C9
65
- border: none
66
- &:after
67
- content: ""
68
- position: absolute
69
- border-style: solid
70
- border-width: 0px 15px 13px 0px
71
- border-color: transparent #C8E6C9
31
+ text-align: right
32
+ flex-direction: row-reverse
33
+ .message
34
+ flex-direction: row-reverse
35
+ .content
36
+ border-top-right-radius: 0 !important
37
+ border-top-left-radius: 10px !important
38
+ &.image img
39
+ border-top-right-radius: 0 !important
40
+ border-top-left-radius: 10px !important
41
+ .message
42
+ min-height: 50px
43
+ display: flex
44
+ margin: 0 10px 5px 10px
45
+ flex: 1
46
+ flex-direction: row
47
+ max-width: 100%
48
+ &.image
72
49
  display: block
73
- width: 0
74
- z-index: 1
75
- left: -15px
76
- top: 0px
50
+ img
51
+ max-width: 100%
52
+ border-radius: 10px
53
+ border-top-left-radius: 0
54
+ .content
55
+ background: #fff
56
+ padding: 10px
57
+ border-radius: 10px
58
+ color: #212121
59
+ border-top-left-radius: 0
60
+ word-break: break-all
61
+ img
62
+ font-size: inherit
63
+ height: 2ex
64
+ width: 2.1ex
65
+ min-height: 20px
66
+ min-width: 20px
67
+ display: inline-block
68
+ margin: -.2ex .15em .2ex
69
+ line-height: normal
70
+ vertical-align: middle
71
+ max-width: 100%
72
+ top: 0
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Chat::MessagesChannel < ApplicationCable::Channel
2
4
  def follow(data)
3
5
  stop_all_streams
4
6
  stream_from "chats::#{data['chat_id']}::messages"
5
7
  end
6
8
 
7
- def unfollow
9
+ def unsubscribed
8
10
  stop_all_streams
9
11
  end
10
- alias unsubscribed unfollow
11
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Chat::NotificationChannel < ApplicationCable::Channel
2
4
  def follow(data)
3
5
  stop_all_streams
@@ -1,12 +1,14 @@
1
- class Chat::StatusChannel < ApplicationCable::Channel
2
- def online
3
- stop_all_streams
4
- stream_from "chat::status"
5
- current_user.online
6
- end
1
+ # frozen_string_literal: true
7
2
 
8
- def unsubscribed
9
- current_user.offline
10
- stop_all_streams
11
- end
3
+ class Chat::StatusChannel < ApplicationCable::Channel
4
+ def online
5
+ stop_all_streams
6
+ stream_from "chat::status"
7
+ current_user.online
12
8
  end
9
+
10
+ def unsubscribed
11
+ current_user.offline
12
+ stop_all_streams
13
+ end
14
+ end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Chat
2
- class ApplicationController < ActionController::Base
4
+ class ApplicationController < ::ApplicationController
3
5
  protect_from_forgery with: :exception
6
+
7
+ before_action Chat.logged_in_check
4
8
  end
5
9
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Chat
2
4
  class ConversationsController < ApplicationController
3
- before_action Chat.logged_in_check
4
5
  before_action :set_conversation, only: :show
5
6
 
6
7
  def show
@@ -8,6 +9,14 @@ module Chat
8
9
 
9
10
  def create
10
11
  @conversation = Chat::Conversation.create(conversation_params)
12
+
13
+ if @conversation.persisted? ||
14
+ @conversation.errors.messages[:sessions].present?
15
+ render template: :create
16
+ else
17
+ @conversation = find_existing_conversation
18
+ render template: "chat/conversations/show"
19
+ end
11
20
  end
12
21
 
13
22
  private
@@ -20,11 +29,24 @@ module Chat
20
29
 
21
30
  def conversation_params
22
31
  chat_params = params.require(:conversation).permit(user_ids: [])
23
- if chat_params[:user_ids].reject(&:blank?).present?
32
+ if chat_params[:user_ids].reject!(&:blank?).present?
24
33
  chat_params[:user_ids] << current_user.id
34
+ chat_params[:user_ids].map!(&:to_i)
25
35
  end
26
36
 
27
37
  chat_params
28
38
  end
39
+
40
+ def find_existing_conversation
41
+ Chat::Conversation.includes(
42
+ :users, messages: :user
43
+ ).find(
44
+ Chat::Conversation.joins(:users).having(
45
+ "COUNT(DISTINCT users.id) = ?", conversation_params[:user_ids].count
46
+ ).group(:id).find_by(
47
+ users: { id: conversation_params[:user_ids] }
48
+ ).id
49
+ )
50
+ end
29
51
  end
30
52
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Chat
2
4
  class MessagesController < ApplicationController
3
- before_action Chat.logged_in_check
4
5
  before_action :set_conversation
6
+ before_action :set_session
5
7
 
6
8
  def create
7
9
  @conversation.messages.create(message_params)
@@ -19,9 +21,13 @@ module Chat
19
21
  @conversation = Chat::Conversation.find(params[:conversation_id])
20
22
  end
21
23
 
24
+ def set_session
25
+ @session = @conversation.sessions.find_by(user: current_user)
26
+ end
27
+
22
28
  def message_params
23
29
  params.require(:message).permit(:text, :image).merge(
24
- user_id: current_user.id
30
+ user_id: current_user.id, session_id: @session.id
25
31
  )
26
32
  end
27
33
  end
@@ -1,18 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Chat
2
4
  module ApplicationHelper
3
- def render_chat(background = nil, color = nil)
5
+ def render_chat
4
6
  return unless send Chat.signed_in
5
7
 
6
- render "chat/chat", background: background, color: color
8
+ render "chat/chat"
7
9
  end
8
10
 
9
- def launch_chat_fab(background = "#4CAF50", color = "light")
11
+ def launch_chat_fab
10
12
  attrs = {
11
- class: "chat__launch", style: "background: #{background}",
12
- data: { "current-user" => current_user.id }
13
+ class: "chat__launch", data: { "current-user" => current_user.id }
13
14
  }
14
15
  button_tag(attrs) do
15
- material_icon.forum.css_class("md-#{color}").to_s.html_safe
16
+ material_icon.forum.css_class("md-dark").to_s.html_safe
16
17
  end
17
18
  end
18
19
 
@@ -32,31 +33,41 @@ module Chat
32
33
  end
33
34
 
34
35
  def chat_avatar(user)
35
- if user.send(Chat.user_avatar.to_s + "?")
36
- image_tag(user.send(Chat.user_avatar), class: "chat__user-avatar")
36
+ if user.chat_avatar?
37
+ image_tag(user.chat_avatar, class: "chat__user-avatar")
37
38
  else
38
39
  MaterialIcon.new.css_class("chat__user-avatar").person
39
40
  end
40
41
  end
41
42
 
42
43
  def chat_list
43
- @chat_list ||=
44
- Chat::Conversation.joins(:users)
45
- .group("chat_sessions.conversation_id")
46
- .select(:id, group_concat)
47
- .merge(current_user.conversations)
48
- .order(created_at: :desc)
49
- end
50
-
51
- private
52
-
53
- def group_concat
54
- if ActiveRecord::Base.connection.adapter_name == "SQLite"
55
- "GROUP_CONCAT(users.#{::User.first_name} || ' ' || users.#{::User.last_name}, ', ') as names"
56
- elsif ActiveRecord::Base.connection.adapter_name == "MySQL"
57
- "GROUP_CONCAT(CONCAT(\"users.#{User.first_name}\",\" \", \"users.#{User.last_name}\") "\
58
- "SEPARATOR ', ') as names"
44
+ @chat_list ||= current_user.conversations.includes(:users).order(
45
+ "chat_conversations.created_at desc"
46
+ )
47
+ end
48
+
49
+ def chat_avatars(conversation)
50
+ (conversation.users - [current_user]).first(2).map do |u|
51
+ chat_avatar(u)
59
52
  end
60
53
  end
54
+
55
+ def chat_avatar_count(conversation)
56
+ if (count = conversation_user_count(conversation)) <= 2
57
+ "count_#{count}"
58
+ else
59
+ "count_default"
60
+ end
61
+ end
62
+
63
+ def conversation_user_count(conversation)
64
+ conversation.users.to_a.size - 1
65
+ end
66
+
67
+ def message_classes(message)
68
+ css_class = message.user == current_user ? "right" : "left"
69
+ css_class += message.image? ? " image" : ""
70
+ css_class
71
+ end
61
72
  end
62
73
  end