personal web client for Bluesky
typescript solidjs bluesky atcute

fix: throttle bandwidth estimate updates

mary.my.id f4012a98 543e25fb

verified
Changed files
+78 -5
src
components
embeds
lib
utils
+9 -5
src/components/embeds/players/video-player.tsx
··· 8 9 import { replaceVideoCdnUrl } from '~/lib/bsky/video'; 10 import { useSession } from '~/lib/states/session'; 11 12 const isMobile = /Android|iPhone|iPad|iPod/.test(navigator.userAgent); 13 ··· 70 node.volume = currentAccount.preferences.ui.mediaVolume; 71 } 72 73 - hls.on(Hls.Events.FRAG_LOADED, () => { 74 - if (currentAccount) { 75 - currentAccount.preferences.ui.videoBwEstimate = hls.bandwidthEstimate; 76 - } 77 - }); 78 79 hls.on(Hls.Events.LEVEL_LOADED, (_event, data) => { 80 const hasAudio = data.levelInfo.audioCodec !== undefined;
··· 8 9 import { replaceVideoCdnUrl } from '~/lib/bsky/video'; 10 import { useSession } from '~/lib/states/session'; 11 + import { throttleTrailing } from '~/lib/utils/misc'; 12 13 const isMobile = /Android|iPhone|iPad|iPod/.test(navigator.userAgent); 14 ··· 71 node.volume = currentAccount.preferences.ui.mediaVolume; 72 } 73 74 + hls.on( 75 + Hls.Events.FRAG_LOADED, 76 + throttleTrailing(() => { 77 + if (currentAccount && !Number.isNaN(hls.bandwidthEstimate)) { 78 + currentAccount.preferences.ui.videoBwEstimate = Math.round(hls.bandwidthEstimate); 79 + } 80 + }, 5_000), 81 + ); 82 83 hls.on(Hls.Events.LEVEL_LOADED, (_event, data) => { 84 const hasAudio = data.levelInfo.audioCodec !== undefined;
+69
src/lib/utils/misc.ts
··· 88 89 return result as Omit<T, K>; 90 };
··· 88 89 return result as Omit<T, K>; 90 }; 91 + 92 + export const throttleLeading = <T extends (...args: any[]) => void>( 93 + fn: T, 94 + wait: number, 95 + ): ((...args: Parameters<T>) => void) => { 96 + let lastCallTime: number | undefined; 97 + 98 + return (...args: Parameters<T>) => { 99 + const now = performance.now(); 100 + 101 + if (lastCallTime === undefined || now - lastCallTime >= wait) { 102 + lastCallTime = now; 103 + fn(...args); 104 + } 105 + }; 106 + }; 107 + 108 + export const throttleTrailing = <T extends (...args: any[]) => void>( 109 + fn: T, 110 + wait: number, 111 + ): ((...args: Parameters<T>) => void) => { 112 + let timeoutId: ReturnType<typeof setTimeout> | undefined; 113 + let lastArgs: Parameters<T> | undefined; 114 + 115 + return (...args: Parameters<T>) => { 116 + lastArgs = args; 117 + 118 + if (timeoutId === undefined) { 119 + timeoutId = setTimeout(() => { 120 + timeoutId = undefined; 121 + fn(...lastArgs!); 122 + }, wait); 123 + } 124 + }; 125 + }; 126 + 127 + export const throttle = <T extends (...args: any[]) => void>( 128 + fn: T, 129 + wait: number, 130 + ): ((...args: Parameters<T>) => void) => { 131 + let timeoutId: ReturnType<typeof setTimeout> | undefined; 132 + let lastArgs: Parameters<T> | undefined; 133 + let lastCallTime: number | undefined; 134 + 135 + return (...args: Parameters<T>) => { 136 + const now = performance.now(); 137 + const elapsed = lastCallTime !== undefined ? now - lastCallTime : wait; 138 + 139 + if (elapsed >= wait) { 140 + if (timeoutId !== undefined) { 141 + clearTimeout(timeoutId); 142 + timeoutId = undefined; 143 + } 144 + 145 + lastCallTime = now; 146 + fn(...args); 147 + } else { 148 + lastArgs = args; 149 + 150 + if (timeoutId === undefined) { 151 + timeoutId = setTimeout(() => { 152 + timeoutId = undefined; 153 + lastCallTime = performance.now(); 154 + fn(...lastArgs!); 155 + }, wait - elapsed); 156 + } 157 + } 158 + }; 159 + };