appchat 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f741156bd18664bfb66a4700b633dad255bc2c5e41cacc6b297acbc6d67492b8
4
- data.tar.gz: d4612a8a1ee88a6caf7bc4e039cf74fa44b369fe79b5d595b0e9544329749819
3
+ metadata.gz: 3071421a8c3c49e11f5c5186b9f17a00bd37d45229d0d95a3b466ae9b9032fee
4
+ data.tar.gz: 79284185b56a3efaeb60e1ec1ad144ada532fd499e686b4604db7a29aabccd16
5
5
  SHA512:
6
- metadata.gz: '0959e29a0ed53649f7f51523e5b4c6f4089b05449f8649165ed7bf7505bdb111774e0c24661e5344f0752df1fa08a38b250a3fe911543530adb7f8a3020f2bd6'
7
- data.tar.gz: '08f3d14d68ea6c2cf9c50da6842051b78bafa250bf58fc77475e09c32090344d06fe4d98205294aa08e9331bf1817e8d5b23213da001b136dd1fb2101c98aca8'
6
+ metadata.gz: 9e642582fe817de68a171c14b272a0b0ceb2257b96021ae9a51e630c5ef562ed982c452fdc9694c2d6e6c81378720f636e0e8218f51d1704134d383602cf2df7
7
+ data.tar.gz: a71996c59642154416cb3178b9406d44242b5626ab7069aeb6341a15e1062d6c297131dfd19de2455c7e59be0cbf8af8c43e6daa0879afb269c001a88723f0a3
@@ -23,14 +23,22 @@ class AppchatGenerator < Rails::Generators::Base
23
23
  run 'rails tailwindcss:install'
24
24
  end
25
25
 
26
- def generate_scaffolds
27
- generate "model", "Chat context:text"
26
+ def set_routes
28
27
  route "resources :chats"
29
- generate "scaffold", "Message chat:references content:text role:integer"
28
+ route "resources :messages"
30
29
  end
31
30
 
32
- def create_views
31
+ def generate_models
32
+ generate "model", "Chat context:text"
33
+ generate "model", "Message chat:references content:text role:integer"
34
+ end
35
+
36
+ def create_controllers
33
37
  copy_file "chats_controller.rb", "app/controllers/chats_controller.rb"
38
+ copy_file "messages_controller.rb", "app/controllers/messages_controller.rb", force: true
39
+ end
40
+
41
+ def create_views
34
42
  copy_file "chats/chat.html.erb", "app/views/chats/_chat.html.erb", force: true
35
43
  copy_file "chats/index.html.erb", "app/views/chats/index.html.erb", force: true
36
44
  copy_file "chats/show.html.erb", "app/views/chats/show.html.erb", force: true
@@ -38,8 +46,15 @@ class AppchatGenerator < Rails::Generators::Base
38
46
  copy_file "messages/new.html.erb", "app/views/messages/new.html.erb", force: true
39
47
  copy_file "messages/message.html.erb", "app/views/messages/_message.html.erb", force: true
40
48
  copy_file "messages/_typing_bubbles.html.erb", "app/views/messages/_typing_bubbles.html.erb", force: true
49
+ end
50
+
51
+ def create_stylesheets
41
52
  copy_file "assets/appchat.tailwind.css", "app/assets/stylesheets/appchat.tailwind.css", force: true
53
+ end
54
+
55
+ def create_stimulus_controllers
42
56
  copy_file "javascript/chat_message_controller.js", "app/javascript/controllers/chat_message_controller.js"
57
+ copy_file "javascript/speech_to_text_controller.js", "app/javascript/controllers/speech_to_text_controller.js"
43
58
  end
44
59
 
45
60
  def copy_models
@@ -63,8 +78,14 @@ class AppchatGenerator < Rails::Generators::Base
63
78
  copy_file "get_ai_response_job.rb", "app/jobs/get_ai_response_job.rb"
64
79
  end
65
80
 
66
- def create_messages_controller
67
- copy_file "messages_controller.rb", "app/controllers/messages_controller.rb", force: true
81
+ def swap_class_in_layout
82
+ layout_file = "app/views/layouts/application.html.erb"
83
+
84
+ if File.exist?(layout_file)
85
+ gsub_file layout_file, /\bmt-28\b/, "mt-10"
86
+ else
87
+ say "Layout file not found. No changes were made.", :red
88
+ end
68
89
  end
69
90
 
70
91
  def show_art
@@ -59,4 +59,18 @@
59
59
  }
60
60
  }
61
61
 
62
+ #microphone-button.recording {
63
+ animation: flash 1s infinite;
64
+ }
65
+
66
+ @keyframes flash {
67
+ 0%, 100% {
68
+ opacity: 80;
69
+ background-color: #EE4B2B; /* Ensure the color remains during the flash */
70
+ }
71
+ 50% {
72
+ opacity: 0.5;
73
+ background-color: #EE4B2B; /* Ensure the color remains during the flash */
74
+ }
75
+ }
62
76
  }
@@ -1,5 +1,5 @@
1
1
  <%= link_to chat, data: { turbo_frame: :chat } do %>
2
- <div class="w-full text-gray-100 hover:text-green-500">
3
- <%= chat&.messages&.first&.content || "New AI chat conversation" %>
4
- </div>
2
+ <div class="w-full text-gray-100 hover:text-green-500">
3
+ <%= chat&.messages&.first&.content&.truncate(45) || "New AI chat conversation" %>
4
+ </div>
5
5
  <% end %>
@@ -3,20 +3,23 @@
3
3
  background-color: black;
4
4
  }
5
5
  </style>
6
+
6
7
  <div class="flex w-full">
7
- <%= turbo_stream_from :chats %>
8
- <div class="max-w-sm w-full h-full flex flex-col gap-4 p-2 w-full flex-shrink-0 bg-[#2e2e2e] rounded-lg" id="chats">
9
- <%= link_to chats_path, data: { turbo_method: :post, turbo_frame: :chat }, class: "flex gap-2 justify-center items-center bg-gray-500 text-gray-100 rounded-lg p-2 text-center mr-auto" do %>
10
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
11
- <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
12
- </svg>
13
- <span> Create Chat </span>
14
- <% end %>
15
- <% @chats.each do |chat| %>
16
- <%= render "chat", chat: chat %>
17
- <% end %>
18
- </div>
19
- <div class="w-full ml-4">
20
- <%= turbo_frame_tag :chat, src: ( chat_path(@chats.first) if @chats.any? ) %>
21
- </div>
8
+ <%= turbo_stream_from :chats %>
9
+ <div class="max-w-sm w-full h-full flex flex-col gap-4 p-2 w-full flex-shrink-0 bg-[#2e2e2e] rounded-lg" id="chats">
10
+ <%= link_to chats_path, data: { turbo_method: :post, turbo_frame: :chat }, class: "flex gap-2 justify-center items-center bg-gray-500 text-gray-100 rounded-lg p-2 text-center mr-auto" do %>
11
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
12
+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
13
+ </svg>
14
+ <span> Create Chat </span>
15
+ <% end %>
16
+ <div class="h-[70vh] overflow-y-hidden overflow-y-scroll">
17
+ <% @chats.each do |chat| %>
18
+ <%= render "chat", chat: chat %>
19
+ <% end %>
20
+ </div>
21
+ </div>
22
+ <div class="w-full ml-4">
23
+ <%= turbo_frame_tag :chat, src: ( chat_path(@chats.first) if @chats.any? ) %>
24
+ </div>
22
25
  </div>
@@ -3,7 +3,7 @@ class ChatsController < ApplicationController
3
3
  @chat = Chat.find(params[:id])
4
4
  end
5
5
  def index
6
- @chats = Chat.all
6
+ @chats = Chat.all.reverse
7
7
  end
8
8
  def create
9
9
  @chat = Chat.create
@@ -0,0 +1,65 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ // Connects to data-controller="speech-to-text"
4
+ export default class extends Controller {
5
+ static targets = ["microphoneButton", "chatInput"]
6
+
7
+ connect() {
8
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
9
+ if (SpeechRecognition) {
10
+ this.microphoneButtonTarget.classList.remove("hidden")
11
+ } else {
12
+ return
13
+ }
14
+
15
+ this.recognition = new SpeechRecognition();
16
+ this.recognition.continuous = false;
17
+ this.recognition.lang = 'en-US';
18
+ this.recognition.interimResults = false;
19
+ this.recognition.maxAlternatives = 1;
20
+
21
+ this.recognition.onresult = this.handleResult.bind(this);
22
+ this.recognition.onerror = this.handleError.bind(this);
23
+ this.recognition.onstart = this.handleStart.bind(this);
24
+ this.recognition.onend = this.handleEnd.bind(this);
25
+
26
+ this.isRecognizing = false; // Track if recognition is active
27
+ }
28
+
29
+ startRecognition(event) {
30
+ event.preventDefault();
31
+ if (this.isRecognizing) {
32
+ console.log("Recognition already started");
33
+ return;
34
+ }
35
+
36
+ try {
37
+ this.recognition.start();
38
+ this.isRecognizing = true;
39
+ } catch (error) {
40
+ console.error("Recognition start failed:", error);
41
+ this.isRecognizing = false;
42
+ }
43
+ }
44
+
45
+ handleStart() {
46
+ this.microphoneButtonTarget.classList.add("recording");
47
+ }
48
+
49
+ handleEnd() {
50
+ this.microphoneButtonTarget.classList.remove("recording");
51
+ this.isRecognizing = false;
52
+ }
53
+
54
+ handleResult(event) {
55
+ const transcript = event.results[0][0].transcript;
56
+ this.chatInputTarget.value += ` ${transcript}`;
57
+ this.recognition.stop();
58
+ }
59
+
60
+ handleError(event) {
61
+ console.error(`Error occurred in recognition: ${event.error}`);
62
+ this.isRecognizing = false;
63
+ alert(`Speech recognition error: ${event.error}`);
64
+ }
65
+ }
@@ -1,16 +1,39 @@
1
1
  <%= turbo_frame_tag :new_message do %>
2
2
  <%= form_with model: @chat.messages.new, url: messages_path(chat_id: @chat.id) do |f| %>
3
- <div class="w-full flex items-center gap-2">
4
- <div class="flex flex-col w-full">
5
- <%= f.label :content, "What do you want to ask?" %>
6
- <%= f.text_area :content, class: "w-full" %>
7
- </div>
8
- <%= button_tag class: "mt-4 flex p-2 rounded-lg bg-gradient-to-r from-indigo-500 to-blue-500 text-blue-100 font-semibold" do %>
9
- Send Message
10
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
11
- <path stroke-linecap="round" stroke-linejoin="round" d="M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5" />
12
- </svg>
13
- <% end %>
14
- </div>
3
+ <div class="w-full flex items-center gap-2 mt-4">
4
+ <div class="flex flex-col w-full" data-controller="speech-to-text">
5
+ <div class="relative w-full">
6
+ <%= f.text_area :content, class: "w-full pr-32 rounded-lg", "data-speech-to-text-target":"chatInput" %>
7
+ <button id="microphone-button"
8
+ data-speech-to-text-target="microphoneButton"
9
+ data-speech-to-text-recording-class="recording"
10
+ data-action="click->speech-to-text#startRecognition"
11
+ class="absolute right-14 top-1/2 transform -translate-y-1/2 p-1 mr-2 bg-gray-200 rounded-full hidden">
12
+ <svg
13
+ fill="#000000"
14
+ height="40px"
15
+ width="40px"
16
+ version="1.1"
17
+ xmlns="http://www.w3.org/2000/svg"
18
+ viewBox="0 0 512 512"
19
+ xmlns:xlink="http://www.w3.org/1999/xlink"
20
+ enable-background="new 0 0 512 512">
21
+ <g>
22
+ <g>
23
+ <path d="m439.5,236c0-11.3-9.1-20.4-20.4-20.4s-20.4,9.1-20.4,20.4c0,70-64,126.9-142.7,126.9-78.7,0-142.7-56.9-142.7-126.9 0-11.3-9.1-20.4-20.4-20.4s-20.4,9.1-20.4,20.4c0,86.2 71.5,157.4 163.1,166.7v57.5h-23.6c-11.3,0-20.4,9.1-20.4,20.4 0,11.3 9.1,20.4 20.4,20.4h88c11.3,0 20.4-9.1 20.4-20.4 0-11.3-9.1-20.4-20.4-20.4h-23.6v-57.5c91.6-9.3 163.1-80.5 163.1-166.7z"/>
24
+ <path d="m256,323.5c51,0 92.3-41.3 92.3-92.3v-127.9c0-51-41.3-92.3-92.3-92.3s-92.3,41.3-92.3,92.3v127.9c0,51 41.3,92.3 92.3,92.3zm-52.3-220.2c0-28.8 23.5-52.3 52.3-52.3s52.3,23.5 52.3,52.3v127.9c0,28.8-23.5,52.3-52.3,52.3s-52.3-23.5-52.3-52.3v-127.9z"/>
25
+ </g>
26
+ </g>
27
+ </svg>
28
+ </button>
29
+ <%= button_tag class: "absolute top-1 right-0 flex p-2 rounded-lg text-gray-900 font-semibold" do %>
30
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-10">
31
+ <path stroke-linecap="round" stroke-linejoin="round" d="M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5" />
32
+ </svg>
33
+ <% end %>
34
+ </div>
35
+ </div>
36
+
37
+ </div>
15
38
  <% end %>
16
39
  <% end %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appchat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - hackliteracy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-26 00:00:00.000000000 Z
11
+ date: 2024-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,7 @@ files:
80
80
  - lib/generators/appchat/templates/chats_controller.rb
81
81
  - lib/generators/appchat/templates/get_ai_response_job.rb
82
82
  - lib/generators/appchat/templates/javascript/chat_message_controller.js
83
+ - lib/generators/appchat/templates/javascript/speech_to_text_controller.js
83
84
  - lib/generators/appchat/templates/messages/_typing_bubbles.html.erb
84
85
  - lib/generators/appchat/templates/messages/index.html.erb
85
86
  - lib/generators/appchat/templates/messages/message.html.erb