valtech-components 4.0.396 → 4.0.397

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -58,7 +58,7 @@ import fixWebmDuration from 'fix-webm-duration';
58
58
  * Current version of valtech-components.
59
59
  * This is automatically updated during the publish process.
60
60
  */
61
- const VERSION = '4.0.396';
61
+ const VERSION = '4.0.397';
62
62
 
63
63
  // Control de estado de refresco (singleton a nivel de módulo)
64
64
  let isRefreshing = false;
@@ -61664,11 +61664,11 @@ class ChessimalsOnlineService {
61664
61664
  this.assertNotExpired(state);
61665
61665
  if (this.isParticipant(state, uid))
61666
61666
  return;
61667
- if (state.status === 'waiting' && state.online?.lobby?.uid === uid)
61667
+ if (this.isHostWaiting(state, uid))
61668
61668
  return;
61669
61669
  if (state.status !== 'waiting' || !state.online?.lobby)
61670
61670
  return;
61671
- if (state.online.pendingGuest?.uid === uid)
61671
+ if (this.isPendingGuest(state, uid))
61672
61672
  return;
61673
61673
  const now = new Date();
61674
61674
  const guest = this.createParticipant(uid, now.toISOString());
@@ -61693,7 +61693,7 @@ class ChessimalsOnlineService {
61693
61693
  throw new Error('CHESSIMALS_GAME_NOT_FOUND');
61694
61694
  const state = snapshot.data();
61695
61695
  this.assertNotExpired(state);
61696
- if (state.status !== 'waiting' || state.online?.lobby?.uid !== uid || !state.online.pendingGuest)
61696
+ if (!this.isHostWaiting(state, uid) || !state.online.pendingGuest)
61697
61697
  return;
61698
61698
  const now = new Date();
61699
61699
  const [hostSide, guestSide] = Math.random() > 0.5 ? ['white', 'black'] : ['black', 'white'];
@@ -61729,7 +61729,7 @@ class ChessimalsOnlineService {
61729
61729
  throw new Error('CHESSIMALS_GAME_NOT_FOUND');
61730
61730
  const state = snapshot.data();
61731
61731
  this.assertNotExpired(state);
61732
- if (state.status !== 'waiting' || state.online?.lobby?.uid !== uid || !state.online.pendingGuest)
61732
+ if (!this.isHostWaiting(state, uid) || !state.online.pendingGuest)
61733
61733
  return;
61734
61734
  const now = new Date();
61735
61735
  const online = { ...state.online, updatedAt: now.toISOString() };
@@ -61831,8 +61831,12 @@ class ChessimalsOnlineService {
61831
61831
  const participants = state.online?.participants;
61832
61832
  if (!participants?.white || !participants.black || !state.online)
61833
61833
  return;
61834
- const requests = Array.from(new Set([...(state.online.rematchRequests ?? []), uid]));
61835
- const bothReady = [participants.white.uid, participants.black.uid].every((item) => requests.includes(item));
61834
+ const currentParticipant = this.participantForSide(state, this.participantSide(state, uid));
61835
+ const requestKey = this.participantKey(currentParticipant);
61836
+ if (!requestKey)
61837
+ return;
61838
+ const requests = Array.from(new Set([...(state.online.rematchRequests ?? []), requestKey]));
61839
+ const bothReady = [participants.white, participants.black].every((item) => this.participantRequestKeys(item).some((key) => requests.includes(key)));
61836
61840
  const now = new Date();
61837
61841
  if (!bothReady) {
61838
61842
  transaction.set(ref, {
@@ -61863,20 +61867,62 @@ class ChessimalsOnlineService {
61863
61867
  });
61864
61868
  }
61865
61869
  participantSide(state, uid = this.currentUid) {
61866
- if (!uid)
61867
- return undefined;
61868
- const participants = state.online?.participants;
61869
- if (participants?.white?.uid === uid)
61870
- return 'white';
61871
- if (participants?.black?.uid === uid)
61872
- return 'black';
61870
+ const entries = this.participantEntries(state);
61871
+ const currentSeatKey = this.currentSeatKey(uid);
61872
+ if (currentSeatKey) {
61873
+ const seatMatch = entries.find(([, participant]) => this.participantKey(participant) === currentSeatKey);
61874
+ if (seatMatch)
61875
+ return seatMatch[0];
61876
+ }
61877
+ if (uid) {
61878
+ const currentProfile = this.profiles.activeProfile();
61879
+ if (currentProfile) {
61880
+ const legacyProfileMatch = entries.find(([, participant]) => participant.uid === uid
61881
+ && participant.avatar === currentProfile.avatar
61882
+ && this.normalizeColor(participant.color) === this.normalizeColor(currentProfile.color));
61883
+ if (legacyProfileMatch)
61884
+ return legacyProfileMatch[0];
61885
+ }
61886
+ const uidMatches = entries.filter(([, participant]) => participant.uid === uid);
61887
+ if (uidMatches.length === 1)
61888
+ return uidMatches[0][0];
61889
+ }
61890
+ const accountUserId = this.auth.user()?.userId;
61891
+ if (accountUserId) {
61892
+ const accountMatches = entries.filter(([, participant]) => participant.accountUserId === accountUserId);
61893
+ if (accountMatches.length === 1)
61894
+ return accountMatches[0][0];
61895
+ }
61873
61896
  return undefined;
61874
61897
  }
61875
61898
  isParticipant(state, uid = this.currentUid) {
61876
61899
  return !!this.participantSide(state, uid);
61877
61900
  }
61878
61901
  isHostWaiting(state, uid = this.currentUid) {
61879
- return !!uid && state.status === 'waiting' && state.online?.lobby?.uid === uid;
61902
+ return state.status === 'waiting' && this.matchesCurrentParticipant(state.online?.lobby, uid);
61903
+ }
61904
+ isPendingGuest(state, uid = this.currentUid) {
61905
+ return state.status === 'waiting' && this.matchesCurrentParticipant(state.online?.pendingGuest, uid);
61906
+ }
61907
+ hasCurrentRematchRequest(state, uid = this.currentUid) {
61908
+ const side = this.participantSide(state, uid);
61909
+ const participant = this.participantForSide(state, side);
61910
+ return this.participantRequestKeys(participant).some((key) => (state.online?.rematchRequests ?? []).includes(key));
61911
+ }
61912
+ hasOpponentRematchRequest(state, uid = this.currentUid) {
61913
+ const side = this.participantSide(state, uid);
61914
+ if (!side)
61915
+ return false;
61916
+ const opponent = this.participantForSide(state, side === 'white' ? 'black' : 'white');
61917
+ return this.participantRequestKeys(opponent).some((key) => (state.online?.rematchRequests ?? []).includes(key));
61918
+ }
61919
+ participantKey(participant) {
61920
+ return participant?.seatKey
61921
+ || this.buildSeatKey(participant?.uid, participant?.profileId)
61922
+ || participant?.profileId
61923
+ || participant?.accountUserId
61924
+ || participant?.uid
61925
+ || '';
61880
61926
  }
61881
61927
  shareUrl(gameId, baseRoute = '/mini-games') {
61882
61928
  const origin = typeof window === 'undefined' ? '' : window.location.origin;
@@ -61927,15 +61973,19 @@ class ChessimalsOnlineService {
61927
61973
  const profile = this.profiles.activeProfile();
61928
61974
  const handle = this.normalizeHandle(user?.handle);
61929
61975
  const avatarUrl = user?.avatarUrl?.trim() || firebaseUser?.photoURL?.trim() || undefined;
61976
+ const email = user?.email?.trim() || firebaseUser?.email?.trim() || undefined;
61977
+ const profileId = profile?.id ?? user?.userId ?? uid;
61930
61978
  return {
61931
61979
  uid,
61932
- profileId: user?.userId ?? profile?.id ?? 'local-player',
61980
+ accountUserId: user?.userId,
61981
+ profileId,
61982
+ seatKey: this.buildSeatKey(uid, profileId),
61933
61983
  name: user?.name?.trim()
61934
61984
  || firebaseUser?.displayName?.trim()
61935
- || user?.email?.trim()
61936
- || firebaseUser?.email?.trim()
61985
+ || email
61937
61986
  || this.profiles.displayName(profile, 'Jugador'),
61938
61987
  handle,
61988
+ email,
61939
61989
  avatar: profile?.avatar ?? '♟️',
61940
61990
  avatarUrl,
61941
61991
  color: profile?.color ?? '#ff00b2',
@@ -61948,6 +61998,58 @@ class ChessimalsOnlineService {
61948
61998
  return undefined;
61949
61999
  return trimmed.startsWith('@') ? trimmed : `@${trimmed}`;
61950
62000
  }
62001
+ buildSeatKey(uid, profileId) {
62002
+ const normalizedUid = uid?.trim();
62003
+ const normalizedProfileId = profileId?.trim();
62004
+ if (!normalizedUid || !normalizedProfileId)
62005
+ return undefined;
62006
+ return `${normalizedUid}:${normalizedProfileId}`;
62007
+ }
62008
+ currentSeatKey(uid = this.currentUid) {
62009
+ return this.buildSeatKey(uid, this.profiles.activeProfile()?.id);
62010
+ }
62011
+ participantForSide(state, side) {
62012
+ if (!side)
62013
+ return undefined;
62014
+ return state.online?.participants?.[side];
62015
+ }
62016
+ participantEntries(state) {
62017
+ const participants = state.online?.participants;
62018
+ return ['white', 'black']
62019
+ .map((side) => [side, participants?.[side]])
62020
+ .filter((entry) => !!entry[1]);
62021
+ }
62022
+ participantRequestKeys(participant) {
62023
+ if (!participant)
62024
+ return [];
62025
+ const keys = [
62026
+ this.participantKey(participant),
62027
+ participant.uid,
62028
+ participant.accountUserId,
62029
+ participant.profileId,
62030
+ ];
62031
+ return Array.from(new Set(keys.filter((key) => !!key)));
62032
+ }
62033
+ matchesCurrentParticipant(participant, uid = this.currentUid) {
62034
+ if (!participant)
62035
+ return false;
62036
+ const seatKey = this.currentSeatKey(uid);
62037
+ if (seatKey && this.participantKey(participant) === seatKey)
62038
+ return true;
62039
+ const profile = this.profiles.activeProfile();
62040
+ if (uid && profile) {
62041
+ return participant.uid === uid
62042
+ && participant.avatar === profile.avatar
62043
+ && this.normalizeColor(participant.color) === this.normalizeColor(profile.color);
62044
+ }
62045
+ if (uid && participant.uid === uid)
62046
+ return true;
62047
+ const accountUserId = this.auth.user()?.userId;
62048
+ return !!accountUserId && participant.accountUserId === accountUserId;
62049
+ }
62050
+ normalizeColor(color) {
62051
+ return (color ?? '').trim().toLowerCase();
62052
+ }
61951
62053
  withUpdatedAt(state, date = new Date()) {
61952
62054
  if (!state.online)
61953
62055
  return state;
@@ -61966,10 +62068,13 @@ class ChessimalsOnlineService {
61966
62068
  };
61967
62069
  }
61968
62070
  createMoveLogEntry(args) {
62071
+ const participant = this.participantForSide(args.state, args.side);
61969
62072
  return this.withoutUndefined({
61970
62073
  id: args.id,
61971
62074
  at: new Date().toISOString(),
61972
62075
  uid: args.uid,
62076
+ profileId: participant?.profileId,
62077
+ seatKey: this.participantKey(participant) || undefined,
61973
62078
  side: args.side,
61974
62079
  status: args.status,
61975
62080
  code: args.code,
@@ -61994,8 +62099,8 @@ class ChessimalsOnlineService {
61994
62099
  if (!state.online)
61995
62100
  return undefined;
61996
62101
  const side = this.participantSide(state, uid);
61997
- const isLobbyHost = state.online.lobby?.uid === uid;
61998
- const isPendingGuest = state.online.pendingGuest?.uid === uid;
62102
+ const isLobbyHost = this.isHostWaiting(state, uid);
62103
+ const isPendingGuest = this.isPendingGuest(state, uid);
61999
62104
  if (!side && !isLobbyHost && !isPendingGuest)
62000
62105
  return undefined;
62001
62106
  const opponent = side
@@ -63189,7 +63294,7 @@ class ChessimalsGameComponent {
63189
63294
  return 'spectator';
63190
63295
  if (this.online.isHostWaiting(game, uid))
63191
63296
  return 'waiting';
63192
- if (game.status === 'waiting' && game.online?.pendingGuest?.uid === uid)
63297
+ if (this.online.isPendingGuest(game, uid))
63193
63298
  return 'pending';
63194
63299
  return this.online.participantSide(game, uid) ?? 'spectator';
63195
63300
  });
@@ -63211,9 +63316,8 @@ class ChessimalsGameComponent {
63211
63316
  const uid = this.onlineUid();
63212
63317
  if (!uid || this.onlineRole() === 'spectator')
63213
63318
  return 'none';
63214
- const requests = game.online?.rematchRequests ?? [];
63215
- const hasMine = requests.includes(uid);
63216
- const hasOther = requests.some((item) => item !== uid);
63319
+ const hasMine = this.online.hasCurrentRematchRequest(game, uid);
63320
+ const hasOther = this.online.hasOpponentRematchRequest(game, uid);
63217
63321
  if (hasOther && !hasMine)
63218
63322
  return 'incoming';
63219
63323
  if (hasMine)
@@ -63935,8 +64039,7 @@ class ChessimalsGameComponent {
63935
64039
  const uid = this.onlineUid();
63936
64040
  return !!uid
63937
64041
  && game.mode === 'online'
63938
- && game.status === 'waiting'
63939
- && game.online?.lobby?.uid === uid
64042
+ && this.online.isHostWaiting(game, uid)
63940
64043
  && !!game.online.pendingGuest;
63941
64044
  }
63942
64045
  pendingGuestName() {
@@ -64117,12 +64220,12 @@ class ChessimalsGameComponent {
64117
64220
  this.game.set(state);
64118
64221
  this.selectedBoardSize.set(state.boardSize);
64119
64222
  this.resumeSplashVisible.set(false);
64120
- const previousPendingUid = previous.id === state.id ? previous.online?.pendingGuest?.uid : undefined;
64121
- const nextPendingUid = state.online?.pendingGuest?.uid;
64223
+ const previousPendingKey = previous.id === state.id ? this.online.participantKey(previous.online?.pendingGuest) : '';
64224
+ const nextPendingKey = this.online.participantKey(state.online?.pendingGuest);
64122
64225
  if (state.status === 'waiting' &&
64123
- state.online?.lobby?.uid === this.online.currentUid &&
64124
- !!nextPendingUid &&
64125
- nextPendingUid !== previousPendingUid) {
64226
+ this.online.isHostWaiting(state, this.online.currentUid) &&
64227
+ !!nextPendingKey &&
64228
+ nextPendingKey !== previousPendingKey) {
64126
64229
  this.audio.chessimalsJoinRequest();
64127
64230
  void this.haptics.success();
64128
64231
  }