修复普通定向发言公屏可见

This commit is contained in:
pllx
2026-04-27 14:43:43 +08:00
parent c0cb7f5ead
commit 2c8cb21206
3 changed files with 78 additions and 12 deletions
+5 -7
View File
@@ -26,9 +26,9 @@ class MessageSent implements ShouldBroadcastNow
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
* 创建消息广播事件实例。
*
* @param int $roomId 房间ID
* @param int $roomId 房间 ID
* @param array $message 发送的消息数据
*/
public function __construct(
@@ -39,8 +39,8 @@ class MessageSent implements ShouldBroadcastNow
/**
* 获取消息应广播到的频道。
*
* 公共消息走房间 Presence 频道;
* 定向消息 / 悄悄话只发给发送方与接收方的私有用户频道。
* 公共消息和普通定向发言走房间 Presence 频道;
* 悄悄话只发给发送方与接收方的私有用户频道。
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
@@ -78,9 +78,7 @@ class MessageSent implements ShouldBroadcastNow
*/
private function shouldBroadcastPrivately(): bool
{
$toUser = trim((string) ($this->message['to_user'] ?? ''));
return $toUser !== '' && $toUser !== '大家';
return (bool) ($this->message['is_secret'] ?? false);
}
/**
+2 -2
View File
@@ -248,8 +248,8 @@ class ChatController extends Controller
return $fromUser === $username || $toUser === $username;
}
// 对特定人说话:只显示发给自己或自己发出的(含系统通知)
return $fromUser === $username || $toUser === $username;
// 非悄悄话的定向发言仍属于公屏消息,历史回放也要让房间内其他人可见。
return true;
}));
// 7. 如果用户有在职職务,开始记录这次入场的心跳登录 (仅初次)
+71 -3
View File
@@ -568,9 +568,54 @@ class ChatControllerTest extends TestCase
}
/**
* 测试定向消息仅广播到发送方与接收方私有频道
* 测试历史消息会让旁观用户看到普通定向发言,但不会泄露悄悄话
*/
public function test_targeted_message_event_uses_private_user_channels(): void
public function test_room_history_keeps_non_secret_targeted_messages_visible_to_others(): void
{
$room = Room::create(['room_name' => 'histtg']);
$sender = User::factory()->create(['username' => 'history-sender']);
$receiver = User::factory()->create(['username' => 'history-receiver']);
$observer = User::factory()->create(['username' => 'history-observer']);
$chatState = app(\App\Services\ChatStateService::class);
$chatState->pushMessage($room->id, [
'id' => 1,
'room_id' => $room->id,
'from_user' => $sender->username,
'to_user' => $receiver->username,
'content' => '公开对你说',
'is_secret' => false,
'font_color' => '#000000',
'action' => '',
'sent_at' => now()->toDateTimeString(),
]);
$chatState->pushMessage($room->id, [
'id' => 2,
'room_id' => $room->id,
'from_user' => $sender->username,
'to_user' => $receiver->username,
'content' => '旁人不可见悄悄话',
'is_secret' => true,
'font_color' => '#000000',
'action' => '',
'sent_at' => now()->toDateTimeString(),
]);
$response = $this->actingAs($observer)->get(route('chat.room', $room->id));
$response->assertOk();
$response->assertViewHas('historyMessages', function (array $messages): bool {
$contents = collect($messages)->pluck('content');
return $contents->contains('公开对你说')
&& ! $contents->contains('旁人不可见悄悄话');
});
}
/**
* 测试悄悄话消息仅广播到发送方与接收方私有频道。
*/
public function test_secret_message_event_uses_private_user_channels(): void
{
$sender = User::factory()->create(['username' => 'sender-user']);
$receiver = User::factory()->create(['username' => 'receiver-user']);
@@ -597,7 +642,30 @@ class ChatControllerTest extends TestCase
}
/**
* 测试公共消息仍广播到房间 Presence 频道。
* 测试普通定向消息仍广播到房间 Presence 频道。
*/
public function test_non_secret_targeted_message_event_uses_room_presence_channel(): void
{
$event = new MessageSent(3, [
'room_id' => 3,
'from_user' => 'tester',
'to_user' => 'receiver-user',
'content' => '公开对你说',
'is_secret' => false,
'font_color' => '#000000',
'action' => '',
'sent_at' => now()->toDateTimeString(),
]);
$channels = $event->broadcastOn();
$this->assertCount(1, $channels);
$this->assertInstanceOf(PresenceChannel::class, $channels[0]);
$this->assertSame('presence-room.3', $channels[0]->name);
}
/**
* 测试对大家消息仍广播到房间 Presence 频道。
*/
public function test_public_message_event_still_uses_room_presence_channel(): void
{