diff --git a/app/Events/ChatMessageDeleted.php b/app/Events/ChatMessageDeleted.php
index c511060..a84b456 100644
--- a/app/Events/ChatMessageDeleted.php
+++ b/app/Events/ChatMessageDeleted.php
@@ -32,8 +32,10 @@ public function __construct(int $messageId, ?string $deletedAt = null)
*/
public function broadcastOn(): array
{
+ $channel = app()->environment('production') ? 'global-chat' : app()->environment().'.global-chat';
+
return [
- new Channel('global-chat'),
+ new Channel($channel),
];
}
diff --git a/app/Events/ChatMessageReacted.php b/app/Events/ChatMessageReacted.php
index 8f6262e..eb888cc 100644
--- a/app/Events/ChatMessageReacted.php
+++ b/app/Events/ChatMessageReacted.php
@@ -32,8 +32,10 @@ public function __construct(int $messageId, array $reactions)
*/
public function broadcastOn(): array
{
+ $channel = app()->environment('production') ? 'global-chat' : app()->environment().'.global-chat';
+
return [
- new Channel('global-chat'),
+ new Channel($channel),
];
}
diff --git a/app/Events/ChatMessageSent.php b/app/Events/ChatMessageSent.php
index de7c362..debc56a 100644
--- a/app/Events/ChatMessageSent.php
+++ b/app/Events/ChatMessageSent.php
@@ -50,8 +50,10 @@ public function __construct(ChatMessage $chatMessage)
*/
public function broadcastOn(): array
{
+ $channel = app()->environment('production') ? 'global-chat' : app()->environment().'.global-chat';
+
return [
- new Channel('global-chat'),
+ new Channel($channel),
];
}
diff --git a/app/Events/ChatSettingsUpdated.php b/app/Events/ChatSettingsUpdated.php
index 4f917fb..cd0ec48 100644
--- a/app/Events/ChatSettingsUpdated.php
+++ b/app/Events/ChatSettingsUpdated.php
@@ -38,8 +38,10 @@ public function __construct()
*/
public function broadcastOn(): array
{
+ $channel = app()->environment('production') ? 'global-chat' : app()->environment().'.global-chat';
+
return [
- new Channel('global-chat'),
+ new Channel($channel),
];
}
diff --git a/app/Http/Controllers/ChatController.php b/app/Http/Controllers/ChatController.php
index cf50ac3..4b4c089 100644
--- a/app/Http/Controllers/ChatController.php
+++ b/app/Http/Controllers/ChatController.php
@@ -79,6 +79,8 @@ public function index(Request $request)
$allowedEmojis = (array) AppSetting::get('global_chat_allowed_emojis', ['👍', '❤️', '🔥', '😂', '🎉', '😮', '😢', '👏']);
+ $channelName = app()->environment('production') ? 'global-chat' : app()->environment().'.global-chat';
+
if (! $request->wantsJson() && ! $request->is('api/*')) {
return Inertia::render('Chat/Index', [
'chatState' => [
@@ -92,6 +94,7 @@ public function index(Request $request)
'can_delete' => (bool) $user?->can('manage chat'),
'reaction_emojis' => $allowedEmojis,
'messages' => $messages,
+ 'channel_name' => $channelName,
'pusher_key' => config('broadcasting.connections.pusher.key'),
'pusher_cluster' => config('broadcasting.connections.pusher.options.cluster', 'ap2'),
],
@@ -109,6 +112,7 @@ public function index(Request $request)
'can_delete' => (bool) $user?->can('manage chat'),
'reaction_emojis' => $allowedEmojis,
'messages' => $messages,
+ 'channel_name' => $channelName,
'pusher_key' => config('broadcasting.connections.pusher.key'),
'pusher_cluster' => config('broadcasting.connections.pusher.options.cluster', 'ap2'),
]);
@@ -362,14 +366,19 @@ public function toggleReaction(Request $request, ChatMessage $message)
], 422);
}
- $existing = $message->reactions()
+ $existingReaction = $message->reactions()
->where('user_id', $user->id)
- ->where('emoji', $emoji)
->first();
- if ($existing) {
- $existing->delete();
+ if ($existingReaction && $existingReaction->emoji === $emoji) {
+ // Same emoji clicked again -> toggle off / remove
+ $existingReaction->delete();
} else {
+ // Different emoji or no previous reaction -> remove existing and add new
+ if ($existingReaction) {
+ $existingReaction->delete();
+ }
+
$message->reactions()->create([
'user_id' => $user->id,
'emoji' => $emoji,
diff --git a/app/Http/Requests/User/StoreUserRequest.php b/app/Http/Requests/User/StoreUserRequest.php
index 6c40ad0..ca451fe 100644
--- a/app/Http/Requests/User/StoreUserRequest.php
+++ b/app/Http/Requests/User/StoreUserRequest.php
@@ -25,6 +25,7 @@ public function rules(): array
return [
'name' => ['required', 'string', 'max:255'],
+ 'username' => ['nullable', 'string', 'min:3', 'max:30', 'regex:/^[a-zA-Z0-9_]+$/', 'unique:users,username'],
'email' => ['required', 'email', 'unique:users,email'],
'role' => ['nullable', 'string'],
'permissions' => ['nullable', 'array'],
diff --git a/app/Http/Requests/User/UpdateUserRequest.php b/app/Http/Requests/User/UpdateUserRequest.php
index 2c6a2ab..8a2d28b 100644
--- a/app/Http/Requests/User/UpdateUserRequest.php
+++ b/app/Http/Requests/User/UpdateUserRequest.php
@@ -26,6 +26,15 @@ public function rules(): array
$rules = [
'name' => ['sometimes', 'string', 'max:255'],
+ 'username' => [
+ 'sometimes',
+ 'nullable',
+ 'string',
+ 'min:3',
+ 'max:30',
+ 'regex:/^[a-zA-Z0-9_]+$/',
+ 'unique:users,username,'.$user->id,
+ ],
'email' => ['sometimes', 'email', 'unique:users,email,'.$user->id],
'file' => ['sometimes', 'nullable', 'image', 'max:2048'],
'about' => ['sometimes', 'nullable', 'string'],
diff --git a/resources/js/components/ChatBanModal.vue b/resources/js/components/ChatBanModal.vue
index 7f296d6..6eb9fad 100644
--- a/resources/js/components/ChatBanModal.vue
+++ b/resources/js/components/ChatBanModal.vue
@@ -24,11 +24,13 @@ const banUntilInput = ref('');
const isSubmittingBan = ref(false);
const banPresets = [
- { label: '1 Hour', hours: 1 },
- { label: '24 Hours', hours: 24 },
- { label: '3 Days', hours: 72 },
- { label: '7 Days', hours: 168 },
- { label: '30 Days', hours: 720 },
+ { label: '3 Mins', minutes: 3 },
+ { label: '5 Mins', minutes: 5 },
+ { label: '15 Mins', minutes: 15 },
+ { label: '1 Hour', minutes: 60 },
+ { label: '24 Hours', minutes: 24 * 60 },
+ { label: '3 Days', minutes: 3 * 24 * 60 },
+ { label: '7 Days', minutes: 7 * 24 * 60 },
];
const formatForDatetimeLocal = (dateString?: string | null) => {
@@ -70,8 +72,8 @@ const formatDate = (isoString?: string | null) => {
}
};
-const applyBanPreset = (hours: number) => {
- const futureDate = new Date(Date.now() + hours * 60 * 60 * 1000);
+const applyBanPreset = (minutes: number) => {
+ const futureDate = new Date(Date.now() + minutes * 60 * 1000);
banUntilInput.value = formatForDatetimeLocal(futureDate.toISOString());
};
@@ -209,7 +211,7 @@ const submitBan = () => {
v-for="preset in banPresets"
:key="preset.label"
type="button"
- @click="applyBanPreset(preset.hours)"
+ @click="applyBanPreset(preset.minutes)"
class="cursor-pointer rounded-lg border border-slate-200 bg-slate-50 px-2.5 py-1 text-xs font-semibold text-slate-700 transition hover:border-rose-200 hover:bg-rose-50 hover:text-rose-700 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-rose-950/40 dark:hover:text-rose-400"
>
+{{ preset.label }}
diff --git a/resources/js/components/Footer.vue b/resources/js/components/Footer.vue
index 48ef995..4b48af3 100644
--- a/resources/js/components/Footer.vue
+++ b/resources/js/components/Footer.vue
@@ -75,17 +75,6 @@ const isFullFooter = computed(() => {
- A concern of - Tajim -
-diff --git a/resources/js/components/admin/UserRow.vue b/resources/js/components/admin/UserRow.vue index 114087d..c3c9f31 100644 --- a/resources/js/components/admin/UserRow.vue +++ b/resources/js/components/admin/UserRow.vue @@ -1,6 +1,8 @@ @@ -1423,17 +1447,25 @@ onUnmounted(() => {