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`);
}
if (warningAsErrors && !newArgs.some(arg => arg.includes('--max-warnings'))) {
if (warningAsErrors && newArgs.every(arg => !arg.includes('--max-warnings'))) {
newArgs.push('--max-warnings=0');
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,
parserOptions: {
...sharedParserOptions,
...(enableVue
? {
extraFileExtensions: ['.vue']
}
: {})
...(enableVue && {
extraFileExtensions: ['.vue']
})
}
}
};
+1 -1
View File
@@ -32,4 +32,4 @@ export const darkColors = () => ({
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
*/
function onFocus(e: boolean): void {
if (!e) {
const playbackSpeedIndex = defaultPlaybackSpeeds.indexOf(playbackManager.playbackSpeed.value);
if (e) {
return;
}
if (playbackSpeedIndex !== -1) {
_playbackSpeed.value = playbackItems.value[playbackSpeedIndex];
}
const playbackSpeedIndex = defaultPlaybackSpeeds.indexOf(playbackManager.playbackSpeed.value);
if (playbackSpeedIndex !== -1) {
_playbackSpeed.value = playbackItems.value[playbackSpeedIndex];
}
}
</script>
@@ -211,30 +211,32 @@ const displayName = computed(() => {
return selectedMediaSource.value?.Name ?? t('mediaInfo');
});
const generalProperties = computed(() => {
if (selectedMediaSource.value) {
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();
if (!selectedMediaSource.value) {
return;
}
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 currentSubtitle = computed<undefined | { index: number; sub?: Dialogue }>((previous) => {
if (!isNil(dialogue.value)) {
const hasPrevious = !isNil(previous);
const nextIndex = hasPrevious ? previous.index + 1 : 0;
const isNext = hasPrevious && predicate(dialogue.value[nextIndex]);
const isCurrent = hasPrevious && predicate(dialogue.value[previous.index]);
if (isNil(dialogue.value)) {
return;
}
if (isCurrent) {
return previous;
} else {
const newIndex = isNext ? nextIndex : findSubtitle(dialogue.value, nextIndex);
const hasPrevious = !isNil(previous);
const nextIndex = hasPrevious ? previous.index + 1 : 0;
const isNext = hasPrevious && predicate(dialogue.value[nextIndex]);
const isCurrent = hasPrevious && predicate(dialogue.value[previous.index]);
if (!isNil(newIndex)) {
return { index: newIndex, sub: dialogue.value[newIndex] };
}
if (isCurrent) {
return previous;
} else {
const newIndex = isNext ? nextIndex : findSubtitle(dialogue.value, nextIndex);
if (hasPrevious) {
return { index: previous.index };
}
if (!isNil(newIndex)) {
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
*/
if (!normalizedArgs.every((a, index) => deepEqual(a, toValue(old[index])))) {
if (normalizedArgs.some((a, index) => !deepEqual(a, toValue(old[index])))) {
argsRef.value = normalizedArgs;
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
*/
public readonly refreshCurrentUserInfo = async (): Promise<void> => {
if (!isNil(this.currentUser.value) && !isNil(this.currentServer.value)) {
const api = useOneTimeAPI(
this.currentServer.value.PublicAddress,
this.currentUserToken.value
);
this._state.value.users[this._state.value.currentUserIndex] = (
await getUserApi(api).getCurrentUser()
).data;
if (isNil(this.currentUser.value) || isNil(this.currentServer.value)) {
return;
}
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> => {
@@ -256,7 +258,7 @@ class RemotePluginAuth extends BaseState<AuthState> {
* @param skipRequest - Skips the request and directly removes the user from the store
*/
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;
}
+12 -12
View File
@@ -16,21 +16,21 @@ class RemotePluginSocket {
* == STATE ==
*/
private readonly _socketUrl = computed(() => {
if (
auth.currentUserToken.value
if (!(auth.currentUserToken.value
&& auth.currentServer.value
&& sdk.deviceInfo.id
&& sdk.api?.basePath
) {
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:');
&& 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:');
});
private readonly _keepAliveMessage = 'KeepAlive';
@@ -10,7 +10,7 @@ import { remote } from '#/plugins/remote/index.ts';
export function adminGuard(
to: RouteLocationNormalized
): NavigationGuardReturn {
if (!(to.meta.admin && !remote.auth.currentUser.value?.Policy?.IsAdministrator)) {
if (!to.meta.admin || remote.auth.currentUser.value?.Policy?.IsAdministrator) {
return;
}
@@ -10,13 +10,15 @@ import { useSnackbar } from '#/composables/use-snackbar.ts';
export function validateGuard(
to: RouteLocationNormalized
): NavigationGuardReturn {
if (('itemId' in to.params) && isStr(to.params.itemId)) {
const check = /[\da-f]{32}/i.test(to.params.itemId);
if (!(('itemId' in to.params) && isStr(to.params.itemId))) {
return;
}
if (!check) {
useSnackbar(i18next.t('routeValidationError'), 'error');
const check = /[\da-f]{32}/i.test(to.params.itemId);
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 => {
if (this.currentItemId.value) {
const newIndex = queue.indexOf(this.currentItemId.value);
this._state.value.queue = queue;
this._state.value.currentItemIndex = newIndex;
if (!this.currentItemId.value) {
return;
}
const newIndex = queue.indexOf(this.currentItemId.value);
this._state.value.queue = queue;
this._state.value.currentItemIndex = newIndex;
};
public readonly changeItemPosition = (
itemId: string | undefined,
newIndex: number
): void => {
if (itemId && this.queueHasItem(itemId)) {
const newQueue = this._state.value.queue.filter(id => id !== itemId);
newQueue.splice(newIndex, 0, itemId);
this.setNewQueue(newQueue);
if (!(itemId && this.queueHasItem(itemId))) {
return;
}
const newQueue = this._state.value.queue.filter(id => id !== itemId);
newQueue.splice(newIndex, 0, itemId);
this.setNewQueue(newQueue);
};
public readonly stop = (): void => {
const sessionId = String(this._state.value.playSessionId ?? '');
const sessionId = (this._state.value.playSessionId ?? '');
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);
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.
*/
private readonly _applySsaSubtitles = async (): Promise<void> => {
if (
mediaElementRef.value
if (!(mediaElementRef.value
&& this.currentExternalSubtitleTrack.value
&& (mediaElementRef.value instanceof HTMLVideoElement)
) {
this._clear();
&& (mediaElementRef.value instanceof HTMLVideoElement))) {
return;
}
const trackSrc = this.currentExternalSubtitleTrack.value.src;
const subtitleTrackPayload = await this._fetchSubtitleTrack(trackSrc);
this._clear();
if (subtitleTrackPayload[trackSrc]) {
/**
* video_width works better with ultrawide monitors
*/
this._asssub = new ASSSUB(
subtitleTrackPayload[trackSrc],
mediaElementRef.value,
{ resampling: 'video_width' }
);
const trackSrc = this.currentExternalSubtitleTrack.value.src;
const subtitleTrackPayload = await this._fetchSubtitleTrack(trackSrc);
this._cleanups.add(() => {
this._asssub?.destroy();
this._asssub = undefined;
});
}
if (subtitleTrackPayload[trackSrc]) {
/**
* 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.
*/
private readonly _applyVttSubtitles = () => {
if (
mediaElementRef.value
&& this.currentExternalSubtitleTrack.value
) {
const subtitleTrack = this.currentExternalSubtitleTrack.value;
if (!(mediaElementRef.value
&& this.currentExternalSubtitleTrack.value)) {
return;
}
/**
* Check if client is able to display custom subtitle track
* otherwise show default subtitle track
*/
if (!this._useCustomSubtitleTrack.value && !isNil(mediaElementRef.value.textTracks[subtitleTrack.srcIndex])) {
mediaElementRef.value.textTracks[subtitleTrack.srcIndex].mode = 'showing';
}
const subtitleTrack = this.currentExternalSubtitleTrack.value;
/**
* Check if client is able to display custom subtitle track
* otherwise show default subtitle track
*/
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
*/
private readonly _updateState = async (): Promise<void> => {
if (remote.auth.currentUser.value) {
/**
* Creates a config syncing task, so UI can show that there's a syncing in progress
*/
const syncTaskId = taskManager.startConfigSync();
if (!remote.auth.currentUser.value) {
return;
}
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) {
newPrefs[String(key)] = this._serializeCustomPref(this._state.value[key]);
}
try {
const newPrefs: DisplayPreferencesDto['CustomPrefs'] = {};
const displayPreferences = await this._fetchDisplayPreferences();
displayPreferences.CustomPrefs = newPrefs;
await this._updateDisplayPreferences(displayPreferences);
} catch {
useSnackbar(i18next.t('failedSyncingUserSettings'), 'error');
} finally {
taskManager.finishTask(syncTaskId);
for (const key of this._syncedKeys) {
newPrefs[String(key)] = this._serializeCustomPref(this._state.value[key]);
}
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
*/
const refreshProgressAction = async (type: string, data: object) => {
if (
type === 'RefreshProgress'
if (!(type === 'RefreshProgress'
&& 'ItemId' in data
&& isStr(data.ItemId)
&& 'Progress' in data
) {
// TODO: Verify all the different tasks that this message may belong to - here we assume libraries.
&& 'Progress' in data)) {
return;
}
const progress = Number(data.Progress);
const taskPayload = this.getTask(data.ItemId);
// TODO: Verify all the different tasks that this message may belong to - here we assume libraries.
/**
* Start task if update its received and it doesn't exist in the store.
* 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);
const progress = Number(data.Progress);
const taskPayload = this.getTask(data.ItemId);
if (item?.Id && item.Name) {
this.startTask({
type: TaskType.LibraryRefresh,
id: item.Id,
data: item.Name,
progress
});
}
} else if (progress >= 0 && progress < 100) {
taskPayload.progress = progress;
} else if (progress >= 0) {
this.finishTask(data.ItemId);
/**
* Start task if update its received and it doesn't exist in the store.
* 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({
type: TaskType.LibraryRefresh,
id: item.Id,
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 ?? [];
for (const episode of episodes) {
if (episode.Id && !isNil(episode.Name)) {
const url = getItemDownloadUrl(episode.Id);
if (!episode.Id || isNil(episode.Name)) {
continue;
}
if (url) {
result.set(episode.Name, url);
}
const url = getItemDownloadUrl(episode.Id);
if (url) {
result.set(episode.Name, url);
}
}
@@ -529,11 +531,13 @@ export async function getItemSeriesDownloadMap(
).data.Items ?? [];
for (const season of seasons) {
if (season.Id) {
const map = await getItemSeasonDownloadMap(season.Id);
result = new Map([...result, ...map]);
if (!season.Id) {
continue;
}
const map = await getItemSeasonDownloadMap(season.Id);
result = new Map([...result, ...map]);
}
return result;
@@ -188,7 +188,7 @@ export function getCodecProfiles(
|| videoTestElement
.canPlayType('video/mp4; codecs="avc1.6e0033"')
.replace(/no/, '')) // TODO: These tests are passing in Safari, but playback is failing
&& (!isApple() || !isWebOS() || !(isEdge() && !isChromiumBased()))
&& (!isApple() || !isWebOS() || !isEdge() || isChromiumBased())
) {
h264Profiles += '|high 10';
}
+1 -1
View File
@@ -59,7 +59,7 @@ export function formatTime(seconds: number): string {
let minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
minutes = minutes - hours * 60;
minutes -= hours * 60;
seconds = Math.floor(seconds - (minutes * 60 + hours * 60 * 60));
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"
*/
} else if (testStrings[0] && keys.includes(testStrings[0])) {
}
if (testStrings[0] && keys.includes(testStrings[0])) {
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.MIN_VALUE)).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.NaN)).toBe(true);
expect(isNumber(NaN)).toBe(true);
expect(isNumber(() => 0)).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.MIN_VALUE)).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.NaN)).toBe(false);
expect(isBool(NaN)).toBe(false);
expect(isBool(() => 0)).toBe(false);
expect(isBool(() => true)).toBe(false);
expect(isBool({})).toBe(false);
@@ -55,9 +55,9 @@ test('isStr', () => {
expect(isStr(Number.MAX_VALUE)).toBe(false);
expect(isStr(Number.MIN_VALUE)).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.NaN)).toBe(false);
expect(isStr(NaN)).toBe(false);
expect(isStr(() => 0)).toBe(false);
expect(isStr(() => '0')).toBe(false);
expect(isStr({})).toBe(false);
@@ -76,9 +76,9 @@ test('isFunc', () => {
expect(isFunc(Number.MAX_VALUE)).toBe(false);
expect(isFunc(Number.MIN_VALUE)).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.NaN)).toBe(false);
expect(isFunc(NaN)).toBe(false);
expect(isFunc(() => 0)).toBe(true);
expect(isFunc(() => '0')).toBe(true);
expect(isFunc({})).toBe(false);
@@ -97,9 +97,9 @@ test('isUndef', () => {
expect(isUndef(Number.MAX_VALUE)).toBe(false);
expect(isUndef(Number.MIN_VALUE)).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.NaN)).toBe(false);
expect(isUndef(NaN)).toBe(false);
expect(isUndef(() => 0)).toBe(false);
expect(isUndef(() => undefined)).toBe(false);
expect(isUndef({})).toBe(false);
@@ -118,9 +118,9 @@ test('isNull', () => {
expect(isNull(Number.MAX_VALUE)).toBe(false);
expect(isNull(Number.MIN_VALUE)).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.NaN)).toBe(false);
expect(isNull(NaN)).toBe(false);
expect(isNull(() => 0)).toBe(false);
expect(isNull(() => null)).toBe(false);
expect(isNull({})).toBe(false);
@@ -139,9 +139,9 @@ test('isNil', () => {
expect(isNil(Number.MAX_VALUE)).toBe(false);
expect(isNil(Number.MIN_VALUE)).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.NaN)).toBe(false);
expect(isNil(NaN)).toBe(false);
expect(isNil(() => 0)).toBe(false);
expect(isNil(() => null)).toBe(false);
expect(isNil(() => undefined)).toBe(false);
@@ -161,9 +161,9 @@ test('isObj', () => {
expect(isObj(Number.MAX_VALUE)).toBe(false);
expect(isObj(Number.MIN_VALUE)).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.NaN)).toBe(false);
expect(isObj(NaN)).toBe(false);
expect(isObj(() => 0)).toBe(false);
expect(isObj(() => ({}))).toBe(false);
expect(isObj({})).toBe(true);
@@ -182,9 +182,9 @@ test('isArray', () => {
expect(isArray(Number.MAX_VALUE)).toBe(false);
expect(isArray(Number.MIN_VALUE)).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.NaN)).toBe(false);
expect(isArray(NaN)).toBe(false);
expect(isArray(() => 0)).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
...(process.env.TAURI_ENV_DEBUG ? { minify: false } : {}),
...(process.env.TAURI_ENV_DEBUG && { minify: false }),
// Produce sourcemaps for debug builds
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
strictPort: true,
// 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`.
envPrefix: ['VITE_', 'TAURI_ENV_*']
@@ -241,7 +241,7 @@ async function readSelectedFileAsBase64(): Promise<string | undefined> {
useEventListener(reader, 'load', () => {
const result = reader.result as string;
const base64FileContent = result.split(',')[1];
const base64FileContent = result.split(',', 2)[1];
if (!base64FileContent) {
reject(new Error('Failed to read file content'));
@@ -27,7 +27,7 @@ useResizeObserver(el, (entries) => {
const entry = entries[0];
height.value = toPx(entry!.contentRect.height);
});
}, 0);
});
useLayoutStyle(() => ({ 'padding-bottom': height.value }));
@@ -217,19 +217,21 @@ const visibleItems = computed<InternalItem[]>((previous) => {
const visibleItemsLength = computed(() => visibleItems.value.length);
const scrollParents = computed(() => rootRef.value && getScrollParents(rootRef.value));
const scrollTargets = computed(() => {
if (scrollParents.value) {
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)
);
if (!scrollParents.value) {
return;
}
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.
*/
globalThis.requestAnimationFrame(() => {
if (cache.size !== 0) {
cache.set(offset, values);
workerUpdates.value++;
if (cache.size === 0) {
return;
}
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
*/
return function (): void {
if (!isUndef(resizeMeasurement.value)
if (!(!isUndef(resizeMeasurement.value)
&& Number.isFinite(bufferLength.value)
&& Number.isFinite(bufferOffset.value)
) {
const area = bufferLength.value * 2;
const start = Math.max(1, bufferOffset.value - area);
const finish = bufferOffset.value + area;
&& Number.isFinite(bufferOffset.value))) {
return;
}
/**
* We always populate 0 first, so there's no blank space shown at the beginning
* or when scrolling to top after a resize in the bottom area.
*/
if (!cache.has(0)) {
void setCache(0);
}
const area = bufferLength.value * 2;
const start = Math.max(1, bufferOffset.value - area);
const finish = bufferOffset.value + area;
for (let i = finish; i >= start && !cache.has(i); i--) {
/**
* Fire all the operations concurrently, no need to await them
*/
void setCache(i);
}
/**
* We always populate 0 first, so there's no blank space shown at the beginning
* or when scrolling to top after a resize in the bottom area.
*/
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
*/
watch(() => scrollTo, () => {
if (!isNil(rootRef.value)
if (!(!isNil(rootRef.value)
&& !isUndef(scrollTo)
&& !isUndef(resizeMeasurement.value)
&& !isNil(scrollParents.value)
&& scrollTo > 0
&& scrollTo < itemsLength.value) {
const { target, top, left } = getScrollToInfo(scrollParents.value, rootRef.value, resizeMeasurement.value, scrollTo);
target.scrollTo({ top, left, behavior: 'smooth' });
&& scrollTo < itemsLength.value)) {
return;
}
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
*/
name: (id) => {
if (id.includes('virtual:') || id.includes('i18next/resources')) {
const targetPath = basename(id.split('/').at(-1)!);
const isIndex = targetPath === 'resources';
return isIndex ? 'localization' : `localization/strings/${targetPath}`;
if (!(id.includes('virtual:') || id.includes('i18next/resources'))) {
return;
}
const targetPath = basename(id.split('/').at(-1)!);
const isIndex = targetPath === 'resources';
return isIndex ? 'localization' : `localization/strings/${targetPath}`;
},
priority: 8
}