style: automatic eslint fix

Signed-off-by: GitHub <noreply@github.com>
This commit is contained in:
Fernando Fernández
2026-07-06 17:05:06 +02:00
parent 127f13836f
commit 7169c5d8ef
25 changed files with 275 additions and 246 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ export function getBaseConfig(packageName: string, forceCache = !CI_environment,
console.log(`[@jellyfin-vue/configs/lint] (${packageName}) Force enabling caching for this run`); console.log(`[@jellyfin-vue/configs/lint] (${packageName}) Force enabling caching for this run`);
} }
if (warningAsErrors && !newArgs.some(arg => arg.includes('--max-warnings'))) { if (warningAsErrors && newArgs.every(arg => !arg.includes('--max-warnings'))) {
newArgs.push('--max-warnings=0'); newArgs.push('--max-warnings=0');
console.log(`[@jellyfin-vue/configs/lint] (${packageName}) Force enabling warnings for this run`); console.log(`[@jellyfin-vue/configs/lint] (${packageName}) Force enabling warnings for this run`);
} }
@@ -259,11 +259,9 @@ export function getTSVueConfig(enableVue = true, tsconfigRootDir = import.meta.d
...langOptions, ...langOptions,
parserOptions: { parserOptions: {
...sharedParserOptions, ...sharedParserOptions,
...(enableVue ...(enableVue && {
? { extraFileExtensions: ['.vue']
extraFileExtensions: ['.vue'] })
}
: {})
} }
} }
}; };
+1 -1
View File
@@ -32,4 +32,4 @@ export const darkColors = () => ({
warning: '#FB8C00' warning: '#FB8C00'
}); });
export type ColorPalette = keyof ReturnType<typeof lightColors> & keyof ReturnType<typeof darkColors>; export type ColorPalette = keyof ReturnType<typeof lightColors> & keyof ReturnType<typeof darkColors>;
@@ -171,12 +171,14 @@ const validationRules = [
* Set one of the objects on Combobox's blur * Set one of the objects on Combobox's blur
*/ */
function onFocus(e: boolean): void { function onFocus(e: boolean): void {
if (!e) { if (e) {
const playbackSpeedIndex = defaultPlaybackSpeeds.indexOf(playbackManager.playbackSpeed.value); return;
}
if (playbackSpeedIndex !== -1) { const playbackSpeedIndex = defaultPlaybackSpeeds.indexOf(playbackManager.playbackSpeed.value);
_playbackSpeed.value = playbackItems.value[playbackSpeedIndex];
} if (playbackSpeedIndex !== -1) {
_playbackSpeed.value = playbackItems.value[playbackSpeedIndex];
} }
} }
</script> </script>
@@ -211,30 +211,32 @@ const displayName = computed(() => {
return selectedMediaSource.value?.Name ?? t('mediaInfo'); return selectedMediaSource.value?.Name ?? t('mediaInfo');
}); });
const generalProperties = computed(() => { const generalProperties = computed(() => {
if (selectedMediaSource.value) { if (!selectedMediaSource.value) {
const p = new Map<string, string | number | boolean | null | undefined>(); return;
const formats
= isArray(selectedMediaSource.value.Formats)
&& selectedMediaSource.value.Formats.length
? selectedMediaSource.value.Formats.join(',')
: undefined;
const fileSize = isNumber(selectedMediaSource.value.Size)
? formatFileSize(selectedMediaSource.value.Size)
: undefined;
const bitrate
= isNumber(selectedMediaSource.value.Bitrate)
&& selectedMediaSource.value.Bitrate > 0
? formatBitRate(selectedMediaSource.value.Bitrate)
: undefined;
p.set(t('mediaInfoFileContainer'), selectedMediaSource.value.Container);
p.set(t('mediaInfoFileFormats'), formats);
p.set(t('mediaInfoFilePath'), selectedMediaSource.value.Path);
p.set(t('mediaInfoFileSize'), fileSize);
p.set(t('mediaInfoGenericBitrate'), bitrate);
return p.entries();
} }
const p = new Map<string, string | number | boolean | null | undefined>();
const formats
= isArray(selectedMediaSource.value.Formats)
&& selectedMediaSource.value.Formats.length
? selectedMediaSource.value.Formats.join(',')
: undefined;
const fileSize = isNumber(selectedMediaSource.value.Size)
? formatFileSize(selectedMediaSource.value.Size)
: undefined;
const bitrate
= isNumber(selectedMediaSource.value.Bitrate)
&& selectedMediaSource.value.Bitrate > 0
? formatBitRate(selectedMediaSource.value.Bitrate)
: undefined;
p.set(t('mediaInfoFileContainer'), selectedMediaSource.value.Container);
p.set(t('mediaInfoFileFormats'), formats);
p.set(t('mediaInfoFilePath'), selectedMediaSource.value.Path);
p.set(t('mediaInfoFileSize'), fileSize);
p.set(t('mediaInfoGenericBitrate'), bitrate);
return p.entries();
}); });
/** /**
@@ -47,24 +47,26 @@ const findSubtitle = (dialogue: ParsedSubtitleTrack['dialogue'], start = 0) => {
const dialogue = computed(() => playerElement.currentExternalSubtitleTrack.value?.parsed?.dialogue); const dialogue = computed(() => playerElement.currentExternalSubtitleTrack.value?.parsed?.dialogue);
const currentSubtitle = computed<undefined | { index: number; sub?: Dialogue }>((previous) => { const currentSubtitle = computed<undefined | { index: number; sub?: Dialogue }>((previous) => {
if (!isNil(dialogue.value)) { if (isNil(dialogue.value)) {
const hasPrevious = !isNil(previous); return;
const nextIndex = hasPrevious ? previous.index + 1 : 0; }
const isNext = hasPrevious && predicate(dialogue.value[nextIndex]);
const isCurrent = hasPrevious && predicate(dialogue.value[previous.index]);
if (isCurrent) { const hasPrevious = !isNil(previous);
return previous; const nextIndex = hasPrevious ? previous.index + 1 : 0;
} else { const isNext = hasPrevious && predicate(dialogue.value[nextIndex]);
const newIndex = isNext ? nextIndex : findSubtitle(dialogue.value, nextIndex); const isCurrent = hasPrevious && predicate(dialogue.value[previous.index]);
if (!isNil(newIndex)) { if (isCurrent) {
return { index: newIndex, sub: dialogue.value[newIndex] }; return previous;
} } else {
const newIndex = isNext ? nextIndex : findSubtitle(dialogue.value, nextIndex);
if (hasPrevious) { if (!isNil(newIndex)) {
return { index: previous.index }; return { index: newIndex, sub: dialogue.value[newIndex] };
} }
if (hasPrevious) {
return { index: previous.index };
} }
} }
}); });
+1 -1
View File
@@ -288,7 +288,7 @@ function setupEffects<T extends Record<K, (...args: any[]) => any>, K extends ke
/** /**
* Does a deep comparison to avoid useless double requests * Does a deep comparison to avoid useless double requests
*/ */
if (!normalizedArgs.every((a, index) => deepEqual(a, toValue(old[index])))) { if (normalizedArgs.some((a, index) => !deepEqual(a, toValue(old[index])))) {
argsRef.value = normalizedArgs; argsRef.value = normalizedArgs;
await runNormally(); await runNormally();
} }
+12 -10
View File
@@ -228,16 +228,18 @@ class RemotePluginAuth extends BaseState<AuthState> {
* Refreshes the current user infos, to fetch a new picture for instance * Refreshes the current user infos, to fetch a new picture for instance
*/ */
public readonly refreshCurrentUserInfo = async (): Promise<void> => { public readonly refreshCurrentUserInfo = async (): Promise<void> => {
if (!isNil(this.currentUser.value) && !isNil(this.currentServer.value)) { if (isNil(this.currentUser.value) || isNil(this.currentServer.value)) {
const api = useOneTimeAPI( return;
this.currentServer.value.PublicAddress,
this.currentUserToken.value
);
this._state.value.users[this._state.value.currentUserIndex] = (
await getUserApi(api).getCurrentUser()
).data;
} }
const api = useOneTimeAPI(
this.currentServer.value.PublicAddress,
this.currentUserToken.value
);
this._state.value.users[this._state.value.currentUserIndex] = (
await getUserApi(api).getCurrentUser()
).data;
}; };
private readonly _refreshServers = async (): Promise<void> => { private readonly _refreshServers = async (): Promise<void> => {
@@ -256,7 +258,7 @@ class RemotePluginAuth extends BaseState<AuthState> {
* @param skipRequest - Skips the request and directly removes the user from the store * @param skipRequest - Skips the request and directly removes the user from the store
*/ */
public readonly logoutCurrentUser = async (skipRequest = false): Promise<void> => { public readonly logoutCurrentUser = async (skipRequest = false): Promise<void> => {
if (!(!isNil(this.currentUser.value) && !isNil(this.currentServer.value))) { if (isNil(this.currentUser.value) || isNil(this.currentServer.value)) {
return; return;
} }
+12 -12
View File
@@ -16,21 +16,21 @@ class RemotePluginSocket {
* == STATE == * == STATE ==
*/ */
private readonly _socketUrl = computed(() => { private readonly _socketUrl = computed(() => {
if ( if (!(auth.currentUserToken.value
auth.currentUserToken.value
&& auth.currentServer.value && auth.currentServer.value
&& sdk.deviceInfo.id && sdk.deviceInfo.id
&& sdk.api?.basePath && sdk.api?.basePath)) {
) { return;
const socketParameters = new URLSearchParams({
api_key: auth.currentUserToken.value,
deviceId: sdk.deviceInfo.id
}).toString();
return `${sdk.api.basePath}/socket?${socketParameters}`
.replace('https:', 'wss:')
.replace('http:', 'ws:');
} }
const socketParameters = new URLSearchParams({
api_key: auth.currentUserToken.value,
deviceId: sdk.deviceInfo.id
}).toString();
return `${sdk.api.basePath}/socket?${socketParameters}`
.replace('https:', 'wss:')
.replace('http:', 'ws:');
}); });
private readonly _keepAliveMessage = 'KeepAlive'; private readonly _keepAliveMessage = 'KeepAlive';
@@ -10,7 +10,7 @@ import { remote } from '#/plugins/remote/index.ts';
export function adminGuard( export function adminGuard(
to: RouteLocationNormalized to: RouteLocationNormalized
): NavigationGuardReturn { ): NavigationGuardReturn {
if (!(to.meta.admin && !remote.auth.currentUser.value?.Policy?.IsAdministrator)) { if (!to.meta.admin || remote.auth.currentUser.value?.Policy?.IsAdministrator) {
return; return;
} }
@@ -10,13 +10,15 @@ import { useSnackbar } from '#/composables/use-snackbar.ts';
export function validateGuard( export function validateGuard(
to: RouteLocationNormalized to: RouteLocationNormalized
): NavigationGuardReturn { ): NavigationGuardReturn {
if (('itemId' in to.params) && isStr(to.params.itemId)) { if (!(('itemId' in to.params) && isStr(to.params.itemId))) {
const check = /[\da-f]{32}/i.test(to.params.itemId); return;
}
if (!check) { const check = /[\da-f]{32}/i.test(to.params.itemId);
useSnackbar(i18next.t('routeValidationError'), 'error');
return false; if (!check) {
} useSnackbar(i18next.t('routeValidationError'), 'error');
return false;
} }
} }
+16 -12
View File
@@ -535,30 +535,34 @@ class PlaybackManagerStore extends CommonStore<PlaybackManagerState> {
}; };
public readonly setNewQueue = (queue: string[]): void => { public readonly setNewQueue = (queue: string[]): void => {
if (this.currentItemId.value) { if (!this.currentItemId.value) {
const newIndex = queue.indexOf(this.currentItemId.value); return;
this._state.value.queue = queue;
this._state.value.currentItemIndex = newIndex;
} }
const newIndex = queue.indexOf(this.currentItemId.value);
this._state.value.queue = queue;
this._state.value.currentItemIndex = newIndex;
}; };
public readonly changeItemPosition = ( public readonly changeItemPosition = (
itemId: string | undefined, itemId: string | undefined,
newIndex: number newIndex: number
): void => { ): void => {
if (itemId && this.queueHasItem(itemId)) { if (!(itemId && this.queueHasItem(itemId))) {
const newQueue = this._state.value.queue.filter(id => id !== itemId); return;
newQueue.splice(newIndex, 0, itemId);
this.setNewQueue(newQueue);
} }
const newQueue = this._state.value.queue.filter(id => id !== itemId);
newQueue.splice(newIndex, 0, itemId);
this.setNewQueue(newQueue);
}; };
public readonly stop = (): void => { public readonly stop = (): void => {
const sessionId = String(this._state.value.playSessionId ?? ''); const sessionId = (this._state.value.playSessionId ?? '');
const time = Number(this.currentTime.value); const time = Number(this.currentTime.value);
const itemId = String(this.currentItem.value?.Id ?? ''); const itemId = (this.currentItem.value?.Id ?? '');
const volume = Number(this.currentVolume.value); const volume = Number(this.currentVolume.value);
this._reset(); this._reset();
+33 -33
View File
@@ -196,31 +196,31 @@ class PlayerElementStore extends CommonStore<PlayerElementState, 'isStretched' |
* Applies SSA (SubStation Alpha) subtitles to the media element. * Applies SSA (SubStation Alpha) subtitles to the media element.
*/ */
private readonly _applySsaSubtitles = async (): Promise<void> => { private readonly _applySsaSubtitles = async (): Promise<void> => {
if ( if (!(mediaElementRef.value
mediaElementRef.value
&& this.currentExternalSubtitleTrack.value && this.currentExternalSubtitleTrack.value
&& (mediaElementRef.value instanceof HTMLVideoElement) && (mediaElementRef.value instanceof HTMLVideoElement))) {
) { return;
this._clear(); }
const trackSrc = this.currentExternalSubtitleTrack.value.src; this._clear();
const subtitleTrackPayload = await this._fetchSubtitleTrack(trackSrc);
if (subtitleTrackPayload[trackSrc]) { const trackSrc = this.currentExternalSubtitleTrack.value.src;
/** const subtitleTrackPayload = await this._fetchSubtitleTrack(trackSrc);
* video_width works better with ultrawide monitors
*/
this._asssub = new ASSSUB(
subtitleTrackPayload[trackSrc],
mediaElementRef.value,
{ resampling: 'video_width' }
);
this._cleanups.add(() => { if (subtitleTrackPayload[trackSrc]) {
this._asssub?.destroy(); /**
this._asssub = undefined; * video_width works better with ultrawide monitors
}); */
} this._asssub = new ASSSUB(
subtitleTrackPayload[trackSrc],
mediaElementRef.value,
{ resampling: 'video_width' }
);
this._cleanups.add(() => {
this._asssub?.destroy();
this._asssub = undefined;
});
} }
}; };
@@ -253,19 +253,19 @@ class PlayerElementStore extends CommonStore<PlayerElementState, 'isStretched' |
* Applies VTT (WebVTT) subtitles to the media element. * Applies VTT (WebVTT) subtitles to the media element.
*/ */
private readonly _applyVttSubtitles = () => { private readonly _applyVttSubtitles = () => {
if ( if (!(mediaElementRef.value
mediaElementRef.value && this.currentExternalSubtitleTrack.value)) {
&& this.currentExternalSubtitleTrack.value return;
) { }
const subtitleTrack = this.currentExternalSubtitleTrack.value;
/** const subtitleTrack = this.currentExternalSubtitleTrack.value;
* Check if client is able to display custom subtitle track
* otherwise show default subtitle track /**
*/ * Check if client is able to display custom subtitle track
if (!this._useCustomSubtitleTrack.value && !isNil(mediaElementRef.value.textTracks[subtitleTrack.srcIndex])) { * otherwise show default subtitle track
mediaElementRef.value.textTracks[subtitleTrack.srcIndex].mode = 'showing'; */
} if (!this._useCustomSubtitleTrack.value && !isNil(mediaElementRef.value.textTracks[subtitleTrack.srcIndex])) {
mediaElementRef.value.textTracks[subtitleTrack.srcIndex].mode = 'showing';
} }
}; };
@@ -84,28 +84,30 @@ export abstract class SyncedStore<
* Updates CustomPrefs by merging passed in value with existing custom prefs * Updates CustomPrefs by merging passed in value with existing custom prefs
*/ */
private readonly _updateState = async (): Promise<void> => { private readonly _updateState = async (): Promise<void> => {
if (remote.auth.currentUser.value) { if (!remote.auth.currentUser.value) {
/** return;
* Creates a config syncing task, so UI can show that there's a syncing in progress }
*/
const syncTaskId = taskManager.startConfigSync();
try { /**
const newPrefs: DisplayPreferencesDto['CustomPrefs'] = {}; * Creates a config syncing task, so UI can show that there's a syncing in progress
*/
const syncTaskId = taskManager.startConfigSync();
for (const key of this._syncedKeys) { try {
newPrefs[String(key)] = this._serializeCustomPref(this._state.value[key]); const newPrefs: DisplayPreferencesDto['CustomPrefs'] = {};
}
const displayPreferences = await this._fetchDisplayPreferences(); for (const key of this._syncedKeys) {
newPrefs[String(key)] = this._serializeCustomPref(this._state.value[key]);
displayPreferences.CustomPrefs = newPrefs;
await this._updateDisplayPreferences(displayPreferences);
} catch {
useSnackbar(i18next.t('failedSyncingUserSettings'), 'error');
} finally {
taskManager.finishTask(syncTaskId);
} }
const displayPreferences = await this._fetchDisplayPreferences();
displayPreferences.CustomPrefs = newPrefs;
await this._updateDisplayPreferences(displayPreferences);
} catch {
useSnackbar(i18next.t('failedSyncingUserSettings'), 'error');
} finally {
taskManager.finishTask(syncTaskId);
} }
}; };
+25 -25
View File
@@ -109,37 +109,37 @@ class TaskManagerStore extends CommonStore<TaskManagerState, 'tasks'> {
* Handle refresh progress update for library items * Handle refresh progress update for library items
*/ */
const refreshProgressAction = async (type: string, data: object) => { const refreshProgressAction = async (type: string, data: object) => {
if ( if (!(type === 'RefreshProgress'
type === 'RefreshProgress'
&& 'ItemId' in data && 'ItemId' in data
&& isStr(data.ItemId) && isStr(data.ItemId)
&& 'Progress' in data && 'Progress' in data)) {
) { return;
// TODO: Verify all the different tasks that this message may belong to - here we assume libraries. }
const progress = Number(data.Progress); // TODO: Verify all the different tasks that this message may belong to - here we assume libraries.
const taskPayload = this.getTask(data.ItemId);
/** const progress = Number(data.Progress);
* Start task if update its received and it doesn't exist in the store. const taskPayload = this.getTask(data.ItemId);
* Usually when a running task is started somewhere else and the client is accssed later
*/
if (isNil(taskPayload)) {
const item = await apiStore.getItemById(data.ItemId);
if (item?.Id && item.Name) { /**
this.startTask({ * Start task if update its received and it doesn't exist in the store.
type: TaskType.LibraryRefresh, * Usually when a running task is started somewhere else and the client is accssed later
id: item.Id, */
data: item.Name, if (isNil(taskPayload)) {
progress const item = await apiStore.getItemById(data.ItemId);
});
} if (item?.Id && item.Name) {
} else if (progress >= 0 && progress < 100) { this.startTask({
taskPayload.progress = progress; type: TaskType.LibraryRefresh,
} else if (progress >= 0) { id: item.Id,
this.finishTask(data.ItemId); data: item.Name,
progress
});
} }
} else if (progress >= 0 && progress < 100) {
taskPayload.progress = progress;
} else if (progress >= 0) {
this.finishTask(data.ItemId);
} }
}; };
/** /**
+13 -9
View File
@@ -498,12 +498,14 @@ export async function getItemSeasonDownloadMap(
).data.Items ?? []; ).data.Items ?? [];
for (const episode of episodes) { for (const episode of episodes) {
if (episode.Id && !isNil(episode.Name)) { if (!episode.Id || isNil(episode.Name)) {
const url = getItemDownloadUrl(episode.Id); continue;
}
if (url) { const url = getItemDownloadUrl(episode.Id);
result.set(episode.Name, url);
} if (url) {
result.set(episode.Name, url);
} }
} }
@@ -529,11 +531,13 @@ export async function getItemSeriesDownloadMap(
).data.Items ?? []; ).data.Items ?? [];
for (const season of seasons) { for (const season of seasons) {
if (season.Id) { if (!season.Id) {
const map = await getItemSeasonDownloadMap(season.Id); continue;
result = new Map([...result, ...map]);
} }
const map = await getItemSeasonDownloadMap(season.Id);
result = new Map([...result, ...map]);
} }
return result; return result;
@@ -188,7 +188,7 @@ export function getCodecProfiles(
|| videoTestElement || videoTestElement
.canPlayType('video/mp4; codecs="avc1.6e0033"') .canPlayType('video/mp4; codecs="avc1.6e0033"')
.replace(/no/, '')) // TODO: These tests are passing in Safari, but playback is failing .replace(/no/, '')) // TODO: These tests are passing in Safari, but playback is failing
&& (!isApple() || !isWebOS() || !(isEdge() && !isChromiumBased())) && (!isApple() || !isWebOS() || !isEdge() || isChromiumBased())
) { ) {
h264Profiles += '|high 10'; h264Profiles += '|high 10';
} }
+1 -1
View File
@@ -59,7 +59,7 @@ export function formatTime(seconds: number): string {
let minutes = Math.floor(seconds / 60); let minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60); const hours = Math.floor(minutes / 60);
minutes = minutes - hours * 60; minutes -= hours * 60;
seconds = Math.floor(seconds - (minutes * 60 + hours * 60 * 60)); seconds = Math.floor(seconds - (minutes * 60 + hours * 60 * 60));
return hours return hours
+3 -1
View File
@@ -36,7 +36,9 @@ function localeTransform(keys: string[], l: string): string | undefined {
/** /**
* Takes the part before the potential hyphen to try, for instance "fr-FR" in i18n to "fr" * Takes the part before the potential hyphen to try, for instance "fr-FR" in i18n to "fr"
*/ */
} else if (testStrings[0] && keys.includes(testStrings[0])) { }
if (testStrings[0] && keys.includes(testStrings[0])) {
return `${testStrings[0]} as ${lang}`; return `${testStrings[0]} as ${lang}`;
} }
} }
+18 -18
View File
@@ -14,9 +14,9 @@ test('isNumber', () => {
expect(isNumber(Number.MAX_VALUE)).toBe(true); expect(isNumber(Number.MAX_VALUE)).toBe(true);
expect(isNumber(Number.MIN_VALUE)).toBe(true); expect(isNumber(Number.MIN_VALUE)).toBe(true);
expect(isNumber(Number.EPSILON)).toBe(true); expect(isNumber(Number.EPSILON)).toBe(true);
expect(isNumber(Number.POSITIVE_INFINITY)).toBe(true); expect(isNumber(Infinity)).toBe(true);
expect(isNumber(Number.NEGATIVE_INFINITY)).toBe(true); expect(isNumber(Number.NEGATIVE_INFINITY)).toBe(true);
expect(isNumber(Number.NaN)).toBe(true); expect(isNumber(NaN)).toBe(true);
expect(isNumber(() => 0)).toBe(false); expect(isNumber(() => 0)).toBe(false);
expect(isNumber({})).toBe(false); expect(isNumber({})).toBe(false);
expect(isNumber([])).toBe(false); expect(isNumber([])).toBe(false);
@@ -34,9 +34,9 @@ test('isBool', () => {
expect(isBool(Number.MAX_VALUE)).toBe(false); expect(isBool(Number.MAX_VALUE)).toBe(false);
expect(isBool(Number.MIN_VALUE)).toBe(false); expect(isBool(Number.MIN_VALUE)).toBe(false);
expect(isBool(Number.EPSILON)).toBe(false); expect(isBool(Number.EPSILON)).toBe(false);
expect(isBool(Number.POSITIVE_INFINITY)).toBe(false); expect(isBool(Infinity)).toBe(false);
expect(isBool(Number.NEGATIVE_INFINITY)).toBe(false); expect(isBool(Number.NEGATIVE_INFINITY)).toBe(false);
expect(isBool(Number.NaN)).toBe(false); expect(isBool(NaN)).toBe(false);
expect(isBool(() => 0)).toBe(false); expect(isBool(() => 0)).toBe(false);
expect(isBool(() => true)).toBe(false); expect(isBool(() => true)).toBe(false);
expect(isBool({})).toBe(false); expect(isBool({})).toBe(false);
@@ -55,9 +55,9 @@ test('isStr', () => {
expect(isStr(Number.MAX_VALUE)).toBe(false); expect(isStr(Number.MAX_VALUE)).toBe(false);
expect(isStr(Number.MIN_VALUE)).toBe(false); expect(isStr(Number.MIN_VALUE)).toBe(false);
expect(isStr(Number.EPSILON)).toBe(false); expect(isStr(Number.EPSILON)).toBe(false);
expect(isStr(Number.POSITIVE_INFINITY)).toBe(false); expect(isStr(Infinity)).toBe(false);
expect(isStr(Number.NEGATIVE_INFINITY)).toBe(false); expect(isStr(Number.NEGATIVE_INFINITY)).toBe(false);
expect(isStr(Number.NaN)).toBe(false); expect(isStr(NaN)).toBe(false);
expect(isStr(() => 0)).toBe(false); expect(isStr(() => 0)).toBe(false);
expect(isStr(() => '0')).toBe(false); expect(isStr(() => '0')).toBe(false);
expect(isStr({})).toBe(false); expect(isStr({})).toBe(false);
@@ -76,9 +76,9 @@ test('isFunc', () => {
expect(isFunc(Number.MAX_VALUE)).toBe(false); expect(isFunc(Number.MAX_VALUE)).toBe(false);
expect(isFunc(Number.MIN_VALUE)).toBe(false); expect(isFunc(Number.MIN_VALUE)).toBe(false);
expect(isFunc(Number.EPSILON)).toBe(false); expect(isFunc(Number.EPSILON)).toBe(false);
expect(isFunc(Number.POSITIVE_INFINITY)).toBe(false); expect(isFunc(Infinity)).toBe(false);
expect(isFunc(Number.NEGATIVE_INFINITY)).toBe(false); expect(isFunc(Number.NEGATIVE_INFINITY)).toBe(false);
expect(isFunc(Number.NaN)).toBe(false); expect(isFunc(NaN)).toBe(false);
expect(isFunc(() => 0)).toBe(true); expect(isFunc(() => 0)).toBe(true);
expect(isFunc(() => '0')).toBe(true); expect(isFunc(() => '0')).toBe(true);
expect(isFunc({})).toBe(false); expect(isFunc({})).toBe(false);
@@ -97,9 +97,9 @@ test('isUndef', () => {
expect(isUndef(Number.MAX_VALUE)).toBe(false); expect(isUndef(Number.MAX_VALUE)).toBe(false);
expect(isUndef(Number.MIN_VALUE)).toBe(false); expect(isUndef(Number.MIN_VALUE)).toBe(false);
expect(isUndef(Number.EPSILON)).toBe(false); expect(isUndef(Number.EPSILON)).toBe(false);
expect(isUndef(Number.POSITIVE_INFINITY)).toBe(false); expect(isUndef(Infinity)).toBe(false);
expect(isUndef(Number.NEGATIVE_INFINITY)).toBe(false); expect(isUndef(Number.NEGATIVE_INFINITY)).toBe(false);
expect(isUndef(Number.NaN)).toBe(false); expect(isUndef(NaN)).toBe(false);
expect(isUndef(() => 0)).toBe(false); expect(isUndef(() => 0)).toBe(false);
expect(isUndef(() => undefined)).toBe(false); expect(isUndef(() => undefined)).toBe(false);
expect(isUndef({})).toBe(false); expect(isUndef({})).toBe(false);
@@ -118,9 +118,9 @@ test('isNull', () => {
expect(isNull(Number.MAX_VALUE)).toBe(false); expect(isNull(Number.MAX_VALUE)).toBe(false);
expect(isNull(Number.MIN_VALUE)).toBe(false); expect(isNull(Number.MIN_VALUE)).toBe(false);
expect(isNull(Number.EPSILON)).toBe(false); expect(isNull(Number.EPSILON)).toBe(false);
expect(isNull(Number.POSITIVE_INFINITY)).toBe(false); expect(isNull(Infinity)).toBe(false);
expect(isNull(Number.NEGATIVE_INFINITY)).toBe(false); expect(isNull(Number.NEGATIVE_INFINITY)).toBe(false);
expect(isNull(Number.NaN)).toBe(false); expect(isNull(NaN)).toBe(false);
expect(isNull(() => 0)).toBe(false); expect(isNull(() => 0)).toBe(false);
expect(isNull(() => null)).toBe(false); expect(isNull(() => null)).toBe(false);
expect(isNull({})).toBe(false); expect(isNull({})).toBe(false);
@@ -139,9 +139,9 @@ test('isNil', () => {
expect(isNil(Number.MAX_VALUE)).toBe(false); expect(isNil(Number.MAX_VALUE)).toBe(false);
expect(isNil(Number.MIN_VALUE)).toBe(false); expect(isNil(Number.MIN_VALUE)).toBe(false);
expect(isNil(Number.EPSILON)).toBe(false); expect(isNil(Number.EPSILON)).toBe(false);
expect(isNil(Number.POSITIVE_INFINITY)).toBe(false); expect(isNil(Infinity)).toBe(false);
expect(isNil(Number.NEGATIVE_INFINITY)).toBe(false); expect(isNil(Number.NEGATIVE_INFINITY)).toBe(false);
expect(isNil(Number.NaN)).toBe(false); expect(isNil(NaN)).toBe(false);
expect(isNil(() => 0)).toBe(false); expect(isNil(() => 0)).toBe(false);
expect(isNil(() => null)).toBe(false); expect(isNil(() => null)).toBe(false);
expect(isNil(() => undefined)).toBe(false); expect(isNil(() => undefined)).toBe(false);
@@ -161,9 +161,9 @@ test('isObj', () => {
expect(isObj(Number.MAX_VALUE)).toBe(false); expect(isObj(Number.MAX_VALUE)).toBe(false);
expect(isObj(Number.MIN_VALUE)).toBe(false); expect(isObj(Number.MIN_VALUE)).toBe(false);
expect(isObj(Number.EPSILON)).toBe(false); expect(isObj(Number.EPSILON)).toBe(false);
expect(isObj(Number.POSITIVE_INFINITY)).toBe(false); expect(isObj(Infinity)).toBe(false);
expect(isObj(Number.NEGATIVE_INFINITY)).toBe(false); expect(isObj(Number.NEGATIVE_INFINITY)).toBe(false);
expect(isObj(Number.NaN)).toBe(false); expect(isObj(NaN)).toBe(false);
expect(isObj(() => 0)).toBe(false); expect(isObj(() => 0)).toBe(false);
expect(isObj(() => ({}))).toBe(false); expect(isObj(() => ({}))).toBe(false);
expect(isObj({})).toBe(true); expect(isObj({})).toBe(true);
@@ -182,9 +182,9 @@ test('isArray', () => {
expect(isArray(Number.MAX_VALUE)).toBe(false); expect(isArray(Number.MAX_VALUE)).toBe(false);
expect(isArray(Number.MIN_VALUE)).toBe(false); expect(isArray(Number.MIN_VALUE)).toBe(false);
expect(isArray(Number.EPSILON)).toBe(false); expect(isArray(Number.EPSILON)).toBe(false);
expect(isArray(Number.POSITIVE_INFINITY)).toBe(false); expect(isArray(Infinity)).toBe(false);
expect(isArray(Number.NEGATIVE_INFINITY)).toBe(false); expect(isArray(Number.NEGATIVE_INFINITY)).toBe(false);
expect(isArray(Number.NaN)).toBe(false); expect(isArray(NaN)).toBe(false);
expect(isArray(() => 0)).toBe(false); expect(isArray(() => 0)).toBe(false);
expect(isArray(() => [])).toBe(false); expect(isArray(() => [])).toBe(false);
expect(isArray({})).toBe(false); expect(isArray({})).toBe(false);
+2 -2
View File
@@ -16,7 +16,7 @@ export default defineConfig(
} }
}, },
// Don't minify for debug builds // Don't minify for debug builds
...(process.env.TAURI_ENV_DEBUG ? { minify: false } : {}), ...(process.env.TAURI_ENV_DEBUG && { minify: false }),
// Produce sourcemaps for debug builds // Produce sourcemaps for debug builds
sourcemap: !!process.env.TAURI_ENV_DEBUG sourcemap: !!process.env.TAURI_ENV_DEBUG
}, },
@@ -24,7 +24,7 @@ export default defineConfig(
// Tauri expects a fixed port, fail if that port is not available // Tauri expects a fixed port, fail if that port is not available
strictPort: true, strictPort: true,
// if the host Tauri is expecting is set, use it // if the host Tauri is expecting is set, use it
...(host ? { host } : {}) ...(host && { host })
}, },
// Env variables starting with the item of `envPrefix` will be exposed in tauri's source code through `import.meta.env`. // Env variables starting with the item of `envPrefix` will be exposed in tauri's source code through `import.meta.env`.
envPrefix: ['VITE_', 'TAURI_ENV_*'] envPrefix: ['VITE_', 'TAURI_ENV_*']
@@ -241,7 +241,7 @@ async function readSelectedFileAsBase64(): Promise<string | undefined> {
useEventListener(reader, 'load', () => { useEventListener(reader, 'load', () => {
const result = reader.result as string; const result = reader.result as string;
const base64FileContent = result.split(',')[1]; const base64FileContent = result.split(',', 2)[1];
if (!base64FileContent) { if (!base64FileContent) {
reject(new Error('Failed to read file content')); reject(new Error('Failed to read file content'));
@@ -27,7 +27,7 @@ useResizeObserver(el, (entries) => {
const entry = entries[0]; const entry = entries[0];
height.value = toPx(entry!.contentRect.height); height.value = toPx(entry!.contentRect.height);
}); }, 0);
}); });
useLayoutStyle(() => ({ 'padding-bottom': height.value })); useLayoutStyle(() => ({ 'padding-bottom': height.value }));
@@ -217,19 +217,21 @@ const visibleItems = computed<InternalItem[]>((previous) => {
const visibleItemsLength = computed(() => visibleItems.value.length); const visibleItemsLength = computed(() => visibleItems.value.length);
const scrollParents = computed(() => rootRef.value && getScrollParents(rootRef.value)); const scrollParents = computed(() => rootRef.value && getScrollParents(rootRef.value));
const scrollTargets = computed(() => { const scrollTargets = computed(() => {
if (scrollParents.value) { if (!scrollParents.value) {
const { vertical, horizontal } = scrollParents.value; return;
/**
* If the scrolling parent is the doc root, use window instead as using
* document root might not work properly.
*/
return (
vertical === horizontal ? [vertical] : [vertical, horizontal]
).map(parent =>
(parent === document.documentElement ? globalThis : parent)
);
} }
const { vertical, horizontal } = scrollParents.value;
/**
* If the scrolling parent is the doc root, use window instead as using
* document root might not work properly.
*/
return (
vertical === horizontal ? [vertical] : [vertical, horizontal]
).map(parent =>
(parent === document.documentElement ? globalThis : parent)
);
}); });
/** /**
@@ -263,10 +265,12 @@ const populateCache = (() => {
* old data might be pushed instead, so we avoid it here. * old data might be pushed instead, so we avoid it here.
*/ */
globalThis.requestAnimationFrame(() => { globalThis.requestAnimationFrame(() => {
if (cache.size !== 0) { if (cache.size === 0) {
cache.set(offset, values); return;
workerUpdates.value++;
} }
cache.set(offset, values);
workerUpdates.value++;
}); });
} }
@@ -278,28 +282,29 @@ const populateCache = (() => {
* to the worker when scrolling fast. We cache 2 times the buffer length * to the worker when scrolling fast. We cache 2 times the buffer length
*/ */
return function (): void { return function (): void {
if (!isUndef(resizeMeasurement.value) if (!(!isUndef(resizeMeasurement.value)
&& Number.isFinite(bufferLength.value) && Number.isFinite(bufferLength.value)
&& Number.isFinite(bufferOffset.value) && Number.isFinite(bufferOffset.value))) {
) { return;
const area = bufferLength.value * 2; }
const start = Math.max(1, bufferOffset.value - area);
const finish = bufferOffset.value + area;
/** const area = bufferLength.value * 2;
* We always populate 0 first, so there's no blank space shown at the beginning const start = Math.max(1, bufferOffset.value - area);
* or when scrolling to top after a resize in the bottom area. const finish = bufferOffset.value + area;
*/
if (!cache.has(0)) {
void setCache(0);
}
for (let i = finish; i >= start && !cache.has(i); i--) { /**
/** * We always populate 0 first, so there's no blank space shown at the beginning
* Fire all the operations concurrently, no need to await them * or when scrolling to top after a resize in the bottom area.
*/ */
void setCache(i); if (!cache.has(0)) {
} void setCache(0);
}
for (let i = finish; i >= start && !cache.has(i); i--) {
/**
* Fire all the operations concurrently, no need to await them
*/
void setCache(i);
} }
}; };
})(); })();
@@ -315,16 +320,18 @@ useEventListener(scrollTargets, 'scroll', () => {
* Tracks if the scroll must be pointed at an specific element * Tracks if the scroll must be pointed at an specific element
*/ */
watch(() => scrollTo, () => { watch(() => scrollTo, () => {
if (!isNil(rootRef.value) if (!(!isNil(rootRef.value)
&& !isUndef(scrollTo) && !isUndef(scrollTo)
&& !isUndef(resizeMeasurement.value) && !isUndef(resizeMeasurement.value)
&& !isNil(scrollParents.value) && !isNil(scrollParents.value)
&& scrollTo > 0 && scrollTo > 0
&& scrollTo < itemsLength.value) { && scrollTo < itemsLength.value)) {
const { target, top, left } = getScrollToInfo(scrollParents.value, rootRef.value, resizeMeasurement.value, scrollTo); return;
target.scrollTo({ top, left, behavior: 'smooth' });
} }
const { target, top, left } = getScrollToInfo(scrollParents.value, rootRef.value, resizeMeasurement.value, scrollTo);
target.scrollTo({ top, left, behavior: 'smooth' });
}); });
/** /**
+7 -5
View File
@@ -153,12 +153,14 @@ export function JBundleChunking(): Plugin {
* Split i18next resources into separate chunks * Split i18next resources into separate chunks
*/ */
name: (id) => { name: (id) => {
if (id.includes('virtual:') || id.includes('i18next/resources')) { if (!(id.includes('virtual:') || id.includes('i18next/resources'))) {
const targetPath = basename(id.split('/').at(-1)!); return;
const isIndex = targetPath === 'resources';
return isIndex ? 'localization' : `localization/strings/${targetPath}`;
} }
const targetPath = basename(id.split('/').at(-1)!);
const isIndex = targetPath === 'resources';
return isIndex ? 'localization' : `localization/strings/${targetPath}`;
}, },
priority: 8 priority: 8
} }