151 lines
4.9 KiB
PHP
151 lines
4.9 KiB
PHP
<div class="user-presence-container border rounded p-4 my-3 bg-white">
|
|
<div class="mb-4">
|
|
<h4 class="font-bold text-lg">Online Users ({{ $guard }})</h4>
|
|
|
|
@if($showCount)
|
|
<div class="flex items-center space-x-2 text-sm text-theme-secondary mt-2">
|
|
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
|
|
<span>{{ count($onlineUsers) }} {{__('online') }}</span>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="space-y-2 mb-4">
|
|
@forelse($onlineUsers as $user)
|
|
<div class="flex items-center space-x-2 bg-gray-50 rounded">
|
|
<div class="w-2 h-2 bg-green-500 rounded-full"></div>
|
|
<span class="text-sm font-medium">{{ $user['name'] ?? 'Unknown' }}</span>
|
|
<small class="text-theme-muted">
|
|
@if(isset($user['last_seen']))
|
|
{{ \Carbon\Carbon::parse($user['last_seen'])->diffForHumans() }}
|
|
@else
|
|
{{__('Now')}}
|
|
@endif
|
|
</small>
|
|
</div>
|
|
@empty
|
|
<div class="text-theme-muted text-sm italic">{{__('No users online') }}</div>
|
|
@endforelse
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{{-- Enhanced JavaScript with offline detection --}}
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
let lastActivity = Date.now();
|
|
let offlineTimeout;
|
|
|
|
function dispatchUserActivity() {
|
|
let success = false;
|
|
|
|
try {
|
|
// Method 1: Direct component method call (most reliable)
|
|
const presenceContainers = document.querySelectorAll('.user-presence-container');
|
|
presenceContainers.forEach(container => {
|
|
const wireId = container.getAttribute('wire:id');
|
|
if (wireId) {
|
|
try {
|
|
const component = window.Livewire.find(wireId);
|
|
if (component && typeof component.call === 'function') {
|
|
component.call('handleUserActivity');
|
|
success = true;
|
|
}
|
|
} catch (e) {
|
|
// component not available
|
|
}
|
|
}
|
|
});
|
|
|
|
// Method 2: Global dispatch (as backup)
|
|
if (!success && window.Livewire && typeof window.Livewire.dispatch === 'function') {
|
|
window.Livewire.dispatch('user-activity');
|
|
}
|
|
|
|
} catch (e) {
|
|
// dispatch failed
|
|
}
|
|
}
|
|
|
|
function dispatchUserOffline() {
|
|
try {
|
|
// Direct component method call (most reliable)
|
|
const presenceContainers = document.querySelectorAll('.user-presence-container');
|
|
presenceContainers.forEach(container => {
|
|
const wireId = container.getAttribute('wire:id');
|
|
if (wireId) {
|
|
try {
|
|
const component = window.Livewire.find(wireId);
|
|
if (component && typeof component.call === 'function') {
|
|
component.call('handleUserOffline');
|
|
}
|
|
} catch (e) {
|
|
// component not available
|
|
}
|
|
}
|
|
});
|
|
|
|
} catch (e) {
|
|
// dispatch failed
|
|
}
|
|
}
|
|
|
|
function updateActivity() {
|
|
const now = Date.now();
|
|
|
|
// Clear existing offline timeout
|
|
if (offlineTimeout) {
|
|
clearTimeout(offlineTimeout);
|
|
}
|
|
|
|
// Only dispatch if 15 seconds have passed
|
|
if (now - lastActivity > 15000) {
|
|
lastActivity = now;
|
|
dispatchUserActivity();
|
|
}
|
|
|
|
// Set offline timeout for 2 minutes of inactivity
|
|
offlineTimeout = setTimeout(() => {
|
|
dispatchUserOffline();
|
|
}, 120000);
|
|
}
|
|
|
|
// Activity tracking
|
|
['click', 'keypress', 'mousemove', 'scroll'].forEach(event => {
|
|
document.addEventListener(event, updateActivity, { passive: true });
|
|
});
|
|
|
|
// Page visibility handling
|
|
document.addEventListener('visibilitychange', function() {
|
|
if (document.hidden) {
|
|
// User switched tabs - set shorter offline timeout
|
|
if (offlineTimeout) clearTimeout(offlineTimeout);
|
|
offlineTimeout = setTimeout(() => {
|
|
dispatchUserOffline();
|
|
}, 30000);
|
|
} else {
|
|
// User came back - immediate activity
|
|
updateActivity();
|
|
}
|
|
});
|
|
|
|
// Handle page unload
|
|
window.addEventListener('beforeunload', function() {
|
|
dispatchUserOffline();
|
|
});
|
|
|
|
// Initial activity setup
|
|
updateActivity();
|
|
|
|
// Manual triggers for testing
|
|
window.triggerPresenceActivity = function() {
|
|
dispatchUserActivity();
|
|
};
|
|
|
|
window.triggerPresenceOffline = function() {
|
|
dispatchUserOffline();
|
|
};
|
|
});
|
|
</script>
|
|
@endpush |