mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
Feature - Add upload functionality on Web (#231)
* Added file selector * Extract metadata to upload files to the web * Added request for uploading * Generate jpeg/Webp thumbnail for asset uploaded without thumbnail data * Added generating thumbnail for video and WebSocket broadcast after thumbnail is generated * Added video length extraction * Added Uploading Panel * Added upload progress store and styling the uploaded asset * Added condition to only show upload panel when there is upload in progress * Remove asset from the upload list after successfully uploading * Added WebSocket to listen to upload event on the web * Added mechanism to check for existing assets before uploading on the web * Added test workflow * Update readme
This commit is contained in:
@@ -1,33 +1,29 @@
|
||||
import { writable, derived } from 'svelte/store';
|
||||
import { getRequest } from '$lib/api';
|
||||
import type { ImmichAsset } from '$lib/models/immich-asset'
|
||||
import type { ImmichAsset } from '$lib/models/immich-asset';
|
||||
import lodash from 'lodash-es';
|
||||
import moment from 'moment';
|
||||
|
||||
export const assets = writable<ImmichAsset[]>([]);
|
||||
|
||||
export const assetsGroupByDate = derived(assets, ($assets) => {
|
||||
|
||||
try {
|
||||
return lodash.chain($assets)
|
||||
.groupBy((a) => moment(a.createdAt).format('ddd, MMM DD'))
|
||||
.sortBy((group) => $assets.indexOf(group[0]))
|
||||
.value();
|
||||
} catch (e) {
|
||||
console.log("error deriving state assets", e)
|
||||
return []
|
||||
}
|
||||
|
||||
})
|
||||
try {
|
||||
return lodash
|
||||
.chain($assets)
|
||||
.groupBy((a) => moment(a.createdAt).format('ddd, MMM DD'))
|
||||
.sortBy((group) => $assets.indexOf(group[0]))
|
||||
.value();
|
||||
} catch (e) {
|
||||
console.log('error deriving state assets', e);
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
export const flattenAssetGroupByDate = derived(assetsGroupByDate, ($assetsGroupByDate) => {
|
||||
return $assetsGroupByDate.flat();
|
||||
})
|
||||
return $assetsGroupByDate.flat();
|
||||
});
|
||||
|
||||
export const getAssetsInfo = async (accessToken: string) => {
|
||||
const res = await getRequest('asset', accessToken);
|
||||
|
||||
assets.set(res);
|
||||
|
||||
}
|
||||
|
||||
const res = await getRequest('asset', accessToken);
|
||||
assets.set(res);
|
||||
};
|
||||
|
||||
45
web/src/lib/stores/upload.ts
Normal file
45
web/src/lib/stores/upload.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { writable, derived } from 'svelte/store';
|
||||
import type { UploadAsset } from '../models/upload-asset';
|
||||
|
||||
function createUploadStore() {
|
||||
const uploadAssets = writable<Array<UploadAsset>>([]);
|
||||
|
||||
const { subscribe } = uploadAssets;
|
||||
|
||||
const isUploading = derived(uploadAssets, ($uploadAssets) => {
|
||||
return $uploadAssets.length > 0 ? true : false;
|
||||
});
|
||||
|
||||
const addNewUploadAsset = (newAsset: UploadAsset) => {
|
||||
uploadAssets.update((currentSet) => [...currentSet, newAsset]);
|
||||
};
|
||||
|
||||
const updateProgress = (id: string, progress: number) => {
|
||||
uploadAssets.update((uploadingAssets) => {
|
||||
return uploadingAssets.map((asset) => {
|
||||
if (asset.id == id) {
|
||||
return {
|
||||
...asset,
|
||||
progress: progress,
|
||||
};
|
||||
}
|
||||
|
||||
return asset;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const removeUploadAsset = (id: string) => {
|
||||
uploadAssets.update((uploadingAsset) => uploadingAsset.filter((a) => a.id != id));
|
||||
};
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
isUploading,
|
||||
addNewUploadAsset,
|
||||
updateProgress,
|
||||
removeUploadAsset,
|
||||
};
|
||||
}
|
||||
|
||||
export const uploadAssetsStore = createUploadStore();
|
||||
30
web/src/lib/stores/websocket.ts
Normal file
30
web/src/lib/stores/websocket.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Socket, io } from 'socket.io-client';
|
||||
import { serverEndpoint } from '../constants';
|
||||
import type { ImmichAsset } from '../models/immich-asset';
|
||||
import { assets } from './assets';
|
||||
|
||||
export const openWebsocketConnection = (accessToken: string) => {
|
||||
const websocket = io(serverEndpoint, {
|
||||
transports: ['polling'],
|
||||
reconnection: true,
|
||||
forceNew: true,
|
||||
autoConnect: true,
|
||||
extraHeaders: {
|
||||
Authorization: 'Bearer ' + accessToken,
|
||||
},
|
||||
});
|
||||
|
||||
listenToEvent(websocket);
|
||||
};
|
||||
|
||||
const listenToEvent = (socket: Socket) => {
|
||||
socket.on('on_upload_success', (data) => {
|
||||
const newUploadedAsset: ImmichAsset = JSON.parse(data);
|
||||
|
||||
assets.update((assets) => [...assets, newUploadedAsset]);
|
||||
});
|
||||
|
||||
socket.on('error', (e) => {
|
||||
console.log('Websocket Error', e);
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user