Initial commit
This commit is contained in:
325
resources/views/vendor/wirechat/livewire/chat/chat.blade.php
vendored
Normal file
325
resources/views/vendor/wirechat/livewire/chat/chat.blade.php
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
{{-- Import helper function to use in chatbox --}}
|
||||
@use('Namu\WireChat\Helpers\Helper')
|
||||
@use('Namu\WireChat\Facades\WireChat')
|
||||
|
||||
@php
|
||||
$primaryColor = WireChat::getColor();
|
||||
@endphp
|
||||
|
||||
|
||||
|
||||
@assets
|
||||
<style>
|
||||
|
||||
emoji-picker {
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Emoji picker configuration */
|
||||
emoji-picker {
|
||||
--background: none !important;
|
||||
--border-radius: 12px;
|
||||
--input-border-color: rgb(229 229 229);
|
||||
--input-padding: 0.45rem;
|
||||
--outline-color: none;
|
||||
--outline-size: 1px;
|
||||
--num-columns: 8;
|
||||
/* Mobile-first default */
|
||||
--emoji-padding: 0.7rem;
|
||||
--emoji-size: 1.5rem;
|
||||
/* Smaller size for mobile */
|
||||
--border-color: none;
|
||||
--indicator-color: #9ca3af;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (min-width: 600px) {
|
||||
emoji-picker {
|
||||
--num-columns: 10;
|
||||
/* Increase columns for larger screens */
|
||||
--emoji-size: 1.8rem;
|
||||
/* Larger size for desktop */
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
emoji-picker {
|
||||
--num-columns: 16;
|
||||
/* Increase columns for larger screens */
|
||||
--emoji-size: 1.9rem;
|
||||
/* Larger size for desktop */
|
||||
}
|
||||
}
|
||||
/* Dark mode using prefers-color-scheme */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
emoji-picker {
|
||||
--background: none !important;
|
||||
--input-border-color: var(--wc-dark-border);
|
||||
--outline-color: none;
|
||||
--outline-size: 1px;
|
||||
--border-color: none;
|
||||
--input-font-color: white;
|
||||
--indicator-color: var(--wc-dark-accent);
|
||||
--button-hover-background: var(--wc-dark-accent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Ensure dark mode takes precedence */
|
||||
.dark emoji-picker {
|
||||
--background: none !important;
|
||||
--input-border-color: var(--wc-dark-border);
|
||||
--outline-color: none;
|
||||
--outline-size: 1px;
|
||||
--border-color: none;
|
||||
--input-font-color: white;
|
||||
--indicator-color: var(--wc-dark-accent);
|
||||
--button-hover-background: var(--wc-dark-accent);
|
||||
}
|
||||
</style>
|
||||
|
||||
@endassets
|
||||
|
||||
<div x-data="{
|
||||
initializing: true,
|
||||
conversationId:@js($conversation->id),
|
||||
conversationElement: document.getElementById('conversation'),
|
||||
loadEmojiPicker() {
|
||||
if (!document.head.querySelector('script[src*=\'/js/vendor/emoji-picker-element/index.js\']')) {
|
||||
// Clear old IndexedDB database that may have cached CDN data
|
||||
if (window.indexedDB) {
|
||||
indexedDB.deleteDatabase('emoji-picker-element');
|
||||
}
|
||||
|
||||
let script = document.createElement('script');
|
||||
script.type = 'module';
|
||||
script.async = true; // Load asynchronously
|
||||
// Add cache-busting parameter to force reload of updated files
|
||||
script.src = '/js/vendor/emoji-picker-element/index.js?v=' + Date.now();
|
||||
|
||||
// After the script loads, configure all emoji pickers
|
||||
script.onload = () => {
|
||||
setTimeout(() => {
|
||||
document.querySelectorAll('emoji-picker').forEach(picker => {
|
||||
picker.dataSource = '/js/vendor/emoji-picker-element-data/en/emojibase/data.json';
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
},
|
||||
get isWidget() {
|
||||
|
||||
return $wire.widget == true;
|
||||
}
|
||||
}"
|
||||
|
||||
x-init="setTimeout(() => {
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
initializing = false;
|
||||
$wire.dispatch('focus-input-field');
|
||||
loadEmojiPicker();
|
||||
{{-- if (isWidget) { --}}
|
||||
//NotifyListeners about chat opened
|
||||
$wire.dispatch('chat-opened',{conversation:conversationId});
|
||||
{{-- } --}}
|
||||
});
|
||||
}, 120);"
|
||||
class="w-full transition bg-[var(--wc-light-primary)] dark:bg-[var(--wc-dark-primary)] overflow-hidden h-full relative" style="contain:content">
|
||||
|
||||
<div class=" flex flex-col grow h-full min-h-0 relative ">
|
||||
{{-- ---------- --}}
|
||||
{{-- --Header-- --}}
|
||||
{{-- ---------- --}}
|
||||
@include('wirechat::livewire.chat.partials.header', [ 'conversation' => $conversation, 'receiver' => $receiver])
|
||||
{{-- ---------- --}}
|
||||
{{-- -Body----- --}}
|
||||
{{-- ---------- --}}
|
||||
<div class="flex-1 min-h-0">
|
||||
@include('wirechat::livewire.chat.partials.body', [ 'conversation' => $conversation, 'authParticipant' => $authParticipant, 'loadedMessages' => $loadedMessages, 'isPrivate' => $conversation->isPrivate(), 'isGroup' => $conversation->isGroup(), 'receiver' => $receiver])
|
||||
</div>
|
||||
{{-- ---------- --}}
|
||||
{{-- -Footer--- --}}
|
||||
{{-- ---------- --}}
|
||||
<livewire:wire-chat.typing-indicator :conversation-id="$conversation->id" />
|
||||
|
||||
@include('wirechat::livewire.chat.partials.footer', [ 'conversation' => $conversation, 'authParticipant' => $authParticipant, 'media' => $media, 'files' => $files, 'replyMessage' => $replyMessage])
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<livewire:wirechat.chat.drawer />
|
||||
|
||||
|
||||
{{-- Add this script directly to your WireChat chat template --}}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
function setupWireChatTyping() {
|
||||
const typingIndicators = document.querySelectorAll('.wirechat-typing-indicator');
|
||||
|
||||
if (typingIndicators.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
typingIndicators.forEach((indicator, index) => {
|
||||
const wireId = indicator.getAttribute('wire:id');
|
||||
|
||||
if (!wireId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find WireChat specific inputs
|
||||
const messageInputs = document.querySelectorAll(
|
||||
'input[wire\\:model*="message"], ' +
|
||||
'textarea[wire\\:model*="message"], ' +
|
||||
'input[placeholder*="message"], ' +
|
||||
'textarea[placeholder*="message"], ' +
|
||||
'input[placeholder*="Type"], ' +
|
||||
'textarea[placeholder*="Type"]'
|
||||
);
|
||||
|
||||
|
||||
if (messageInputs.length === 0) {
|
||||
messageInputs = document.querySelectorAll('input[type="text"], textarea');
|
||||
}
|
||||
|
||||
let typingTimer;
|
||||
let isTyping = false;
|
||||
|
||||
function startTyping() {
|
||||
|
||||
if (!isTyping) {
|
||||
isTyping = true;
|
||||
|
||||
try {
|
||||
const component = window.Livewire.find(wireId);
|
||||
if (component && typeof component.call === 'function') {
|
||||
|
||||
component.call('startTyping');
|
||||
} else {
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
// Reset timer
|
||||
clearTimeout(typingTimer);
|
||||
typingTimer = setTimeout(() => {
|
||||
stopTyping();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function stopTyping() {
|
||||
if (isTyping) {
|
||||
isTyping = false;
|
||||
clearTimeout(typingTimer);
|
||||
|
||||
try {
|
||||
const component = window.Livewire.find(wireId);
|
||||
if (component && typeof component.call === 'function') {
|
||||
component.call('stopTyping');
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add event listeners with improved logic
|
||||
messageInputs.forEach((input, inputIndex) => {
|
||||
const inputDesc = input.placeholder || input.getAttribute('wire:model') || `input-${inputIndex}`;
|
||||
|
||||
// Input event - most reliable for typing detection
|
||||
input.addEventListener('input', function(e) {
|
||||
startTyping();
|
||||
});
|
||||
|
||||
// Keydown event - for immediate response
|
||||
input.addEventListener('keydown', function(e) {
|
||||
// Only log actual typing keys to reduce noise
|
||||
if (e.key.length === 1 || e.key === 'Backspace' || e.key === 'Delete') {
|
||||
startTyping();
|
||||
} else if (e.key === 'Enter' && !e.shiftKey) {
|
||||
stopTyping();
|
||||
}
|
||||
});
|
||||
|
||||
// Focus event - just for logging
|
||||
input.addEventListener('focus', function() {
|
||||
});
|
||||
|
||||
// Blur event - only stop if not typing recently
|
||||
input.addEventListener('blur', function() {
|
||||
// Add a small delay before stopping to prevent immediate stop
|
||||
setTimeout(() => {
|
||||
if (isTyping) {
|
||||
stopTyping();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// Setup with delay to ensure Livewire is ready
|
||||
setTimeout(setupWireChatTyping, 500);
|
||||
|
||||
// Re-setup on navigation
|
||||
document.addEventListener('livewire:navigated', function() {
|
||||
setTimeout(setupWireChatTyping, 500);
|
||||
});
|
||||
});
|
||||
|
||||
// Global test functions
|
||||
window.testWireChatTyping = {
|
||||
start: function() {
|
||||
const indicators = document.querySelectorAll('.wirechat-typing-indicator');
|
||||
indicators.forEach(indicator => {
|
||||
const wireId = indicator.getAttribute('wire:id');
|
||||
if (wireId) {
|
||||
try {
|
||||
const component = window.Livewire.find(wireId);
|
||||
component.call('startTyping');
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
const indicators = document.querySelectorAll('.wirechat-typing-indicator');
|
||||
indicators.forEach(indicator => {
|
||||
const wireId = indicator.getAttribute('wire:id');
|
||||
if (wireId) {
|
||||
try {
|
||||
const component = window.Livewire.find(wireId);
|
||||
component.call('stopTyping');
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
checkRedis: function() {
|
||||
// This would need to be done server-side, but we can check component state
|
||||
const indicators = document.querySelectorAll('.wirechat-typing-indicator');
|
||||
indicators.forEach(indicator => {
|
||||
const wireId = indicator.getAttribute('wire:id');
|
||||
if (wireId) {
|
||||
try {
|
||||
const component = window.Livewire.find(wireId);
|
||||
component.call('debug');
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
</div>
|
||||
Reference in New Issue
Block a user