Add friend chat; replace betting wording (شرط) with entry coins

- Friend-to-friend chat outside the game (ChatScreen) with mock replies,
  per-friend history, unread tracking; chat button on each friend row
- OnlineService + mock + online-store extended with chat (list/get/send/markRead)
- Reframe gambling term: "شرط"/"Stake" -> "سکه ورودی"/"Entry coins";
  free entry labeled رایگان/Free

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-04 10:21:44 +03:30
parent e2d0a602b6
commit 5776036d78
10 changed files with 290 additions and 4 deletions
+41
View File
@@ -3,6 +3,7 @@
import { create } from "zustand";
import { CreateRoomOptions, MatchmakingOptions, getService } from "./online/service";
import {
ChatMessage,
Friend,
FriendRequest,
LeaderboardEntry,
@@ -35,11 +36,19 @@ interface OnlineStore {
cancelMatchmaking: () => Promise<void>;
loadLeaderboard: () => Promise<void>;
// chat
activeChatFriend: Friend | null;
chatMessages: ChatMessage[];
openChat: (friend: Friend) => Promise<void>;
sendChat: (text: string) => Promise<void>;
closeChat: () => void;
}
let roomUnsub: (() => void) | null = null;
let mmUnsub: (() => void) | null = null;
let friendUnsub: (() => void) | null = null;
let chatUnsub: (() => void) | null = null;
export const useOnlineStore = create<OnlineStore>((set, get) => ({
friends: [],
@@ -128,4 +137,36 @@ export const useOnlineStore = create<OnlineStore>((set, get) => ({
const leaderboard = await getService().getLeaderboard();
set({ leaderboard });
},
activeChatFriend: null,
chatMessages: [],
openChat: async (friend) => {
const svc = getService();
set({ activeChatFriend: friend, chatMessages: await svc.getMessages(friend.id) });
await svc.markRead(friend.id);
if (chatUnsub) chatUnsub();
chatUnsub = svc.onChat((friendId, msgs) => {
const active = get().activeChatFriend;
if (active && active.id === friendId) {
set({ chatMessages: msgs });
svc.markRead(friendId);
}
});
},
sendChat: async (text) => {
const friend = get().activeChatFriend;
if (!friend || !text.trim()) return;
await getService().sendMessage(friend.id, text);
set({ chatMessages: await getService().getMessages(friend.id) });
},
closeChat: () => {
if (chatUnsub) {
chatUnsub();
chatUnsub = null;
}
set({ activeChatFriend: null, chatMessages: [] });
},
}));