Fix: Force pull images in deploy workflow
All checks were successful
Build and Push / build-all (push) Successful in 7m30s
All checks were successful
Build and Push / build-all (push) Successful in 7m30s
This commit is contained in:
parent
7f56f19e94
commit
0bb461498e
7 changed files with 104 additions and 23 deletions
|
|
@ -119,8 +119,29 @@ export function clearMessages() {
|
|||
}
|
||||
|
||||
// Set message history
|
||||
export function setMessageHistory(messageList) {
|
||||
messages.set(messageList);
|
||||
// If merge=true, adds new messages to existing ones (for realm switching in global chat)
|
||||
// If merge=false (default), replaces all messages (for initial connection)
|
||||
export function setMessageHistory(messageList, merge = false) {
|
||||
if (merge) {
|
||||
messages.update((existing) => {
|
||||
// Create a Map of existing messages by messageId for O(1) lookup
|
||||
const existingMap = new Map(existing.map((m) => [m.messageId, m]));
|
||||
|
||||
// Add new messages that don't already exist
|
||||
for (const msg of messageList) {
|
||||
if (!existingMap.has(msg.messageId)) {
|
||||
existingMap.set(msg.messageId, msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert back to array and sort by timestamp
|
||||
return Array.from(existingMap.values()).sort(
|
||||
(a, b) => new Date(a.timestamp) - new Date(b.timestamp)
|
||||
);
|
||||
});
|
||||
} else {
|
||||
messages.set(messageList);
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle channel
|
||||
|
|
|
|||
|
|
@ -132,7 +132,11 @@ class ChatWebSocket {
|
|||
break;
|
||||
|
||||
case 'history':
|
||||
setMessageHistory(data.messages || []);
|
||||
// Merge history when switching realms to preserve messages from other realms
|
||||
// Backend includes realmId only for realm-switch history (from handleJoinRealm)
|
||||
// Initial connection history (handleNewConnection) has no realmId
|
||||
const shouldMerge = data.realmId !== undefined;
|
||||
setMessageHistory(data.messages || [], shouldMerge);
|
||||
break;
|
||||
|
||||
case 'new_message':
|
||||
|
|
|
|||
|
|
@ -38,19 +38,39 @@
|
|||
// Self-destruct countdown
|
||||
let countdownSeconds = 0;
|
||||
let countdownInterval = null;
|
||||
let countdownStartedAt = null;
|
||||
let initialCountdown = 0;
|
||||
$: hasSelfDestruct = message.selfDestructAt && message.selfDestructAt > 0;
|
||||
|
||||
function updateCountdown() {
|
||||
if (!message.selfDestructAt) return;
|
||||
const now = Date.now();
|
||||
const remaining = Math.max(0, Math.ceil((message.selfDestructAt - now) / 1000));
|
||||
if (!countdownStartedAt) return;
|
||||
|
||||
// Calculate elapsed time since countdown started (local time only, avoids clock skew)
|
||||
const elapsedSec = Math.floor((Date.now() - countdownStartedAt) / 1000);
|
||||
const remaining = Math.max(0, initialCountdown - elapsedSec);
|
||||
|
||||
countdownSeconds = remaining;
|
||||
|
||||
if (remaining <= 0 && countdownInterval) {
|
||||
clearInterval(countdownInterval);
|
||||
countdownInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
function startCountdown() {
|
||||
if (!message.selfDestructAt || !message.timestamp) return;
|
||||
|
||||
// Calculate the intended duration from server timestamps (no clock skew between them)
|
||||
const intendedDurationSec = Math.ceil((message.selfDestructAt - message.timestamp) / 1000);
|
||||
|
||||
// Record when we started counting down locally
|
||||
countdownStartedAt = Date.now();
|
||||
initialCountdown = intendedDurationSec;
|
||||
countdownSeconds = intendedDurationSec;
|
||||
|
||||
countdownInterval = setInterval(updateCountdown, 1000);
|
||||
}
|
||||
|
||||
function formatCountdown(seconds) {
|
||||
if (seconds >= 60) {
|
||||
const m = Math.floor(seconds / 60);
|
||||
|
|
@ -69,8 +89,7 @@
|
|||
onMount(async () => {
|
||||
// Set up self-destruct countdown if applicable
|
||||
if (message.selfDestructAt && message.selfDestructAt > 0) {
|
||||
updateCountdown();
|
||||
countdownInterval = setInterval(updateCountdown, 1000);
|
||||
startCountdown();
|
||||
}
|
||||
|
||||
// Ensure stickers are loaded (uses shared store - only fetches once across all components)
|
||||
|
|
|
|||
|
|
@ -106,6 +106,18 @@ function createWatchSyncStore() {
|
|||
repeatCount: data.repeatCount || 0,
|
||||
isRepeating: true
|
||||
}));
|
||||
} else if (data.event === 'locked_restart') {
|
||||
// Locked video loop - restart from beginning
|
||||
update(state => ({
|
||||
...state,
|
||||
playbackState: 'playing',
|
||||
currentTime: 0,
|
||||
serverTime: data.serverTime || Date.now(),
|
||||
currentVideo: data.currentVideo !== undefined ? data.currentVideo : state.currentVideo,
|
||||
leadIn: true,
|
||||
repeatCount: 0,
|
||||
isRepeating: true // Video is looping (locked)
|
||||
}));
|
||||
} else if (data.event === 'skip') {
|
||||
// Skip resets repeat state
|
||||
update(state => ({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue