2023-05-08 16:36:10 +00:00
|
|
|
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
2023-05-07 22:29:37 +00:00
|
|
|
import type { PayloadAction } from '@reduxjs/toolkit';
|
2023-05-09 00:22:00 +00:00
|
|
|
import type { RootState } from '~/store';
|
|
|
|
import { decryptionQueue } from '~/decrypt-worker/client';
|
2023-05-07 22:29:37 +00:00
|
|
|
|
|
|
|
export enum ProcessState {
|
|
|
|
UNTOUCHED = 'UNTOUCHED',
|
|
|
|
COMPLETE = 'COMPLETE',
|
|
|
|
ERROR = 'ERROR',
|
|
|
|
}
|
|
|
|
|
|
|
|
export enum ListingMode {
|
|
|
|
LIST = 'LIST',
|
|
|
|
CARD = 'CARD',
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface AudioMetadata {
|
|
|
|
name: string;
|
|
|
|
artist: string;
|
|
|
|
album: string;
|
|
|
|
albumArtist: string;
|
|
|
|
cover: string; // blob uri
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DecryptedAudioFile {
|
|
|
|
fileName: string;
|
|
|
|
raw: string; // blob uri
|
|
|
|
decrypted: string; // blob uri
|
|
|
|
state: ProcessState;
|
|
|
|
errorMessage: null | string;
|
|
|
|
metadata: AudioMetadata;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface FileListingState {
|
2023-05-08 14:54:00 +00:00
|
|
|
files: Record<string, DecryptedAudioFile>;
|
2023-05-07 22:29:37 +00:00
|
|
|
displayMode: ListingMode;
|
|
|
|
}
|
|
|
|
const initialState: FileListingState = {
|
2023-05-08 14:54:00 +00:00
|
|
|
files: Object.create(null),
|
2023-05-07 22:29:37 +00:00
|
|
|
displayMode: ListingMode.LIST,
|
|
|
|
};
|
|
|
|
|
2023-05-08 16:36:10 +00:00
|
|
|
export const processFile = createAsyncThunk('fileListing/processFile', async (fileId: string, thunkAPI) => {
|
|
|
|
const file = selectFiles(thunkAPI.getState() as RootState)[fileId];
|
|
|
|
if (!file) {
|
|
|
|
return thunkAPI.rejectWithValue('ERROR: File not found');
|
|
|
|
}
|
|
|
|
|
|
|
|
return decryptionQueue.add({ id: fileId, blobURI: file.raw });
|
|
|
|
});
|
|
|
|
|
2023-05-07 22:29:37 +00:00
|
|
|
export const fileListingSlice = createSlice({
|
|
|
|
name: 'fileListing',
|
|
|
|
initialState,
|
|
|
|
reducers: {
|
|
|
|
addNewFile: (state, { payload }: PayloadAction<{ id: string; fileName: string; blobURI: string }>) => {
|
2023-05-08 14:54:00 +00:00
|
|
|
state.files[payload.id] = {
|
2023-05-07 22:29:37 +00:00
|
|
|
fileName: payload.fileName,
|
|
|
|
raw: payload.blobURI,
|
|
|
|
decrypted: '',
|
|
|
|
state: ProcessState.UNTOUCHED,
|
|
|
|
errorMessage: null,
|
|
|
|
metadata: {
|
|
|
|
name: '',
|
|
|
|
artist: '',
|
|
|
|
album: '',
|
|
|
|
albumArtist: '',
|
|
|
|
cover: '',
|
|
|
|
},
|
2023-05-08 14:54:00 +00:00
|
|
|
};
|
2023-05-07 22:29:37 +00:00
|
|
|
},
|
|
|
|
setDecryptedContent: (state, { payload }: PayloadAction<{ id: string; decryptedBlobURI: string }>) => {
|
2023-05-08 14:54:00 +00:00
|
|
|
const file = state.files[payload.id];
|
2023-05-07 22:29:37 +00:00
|
|
|
if (file) {
|
|
|
|
file.decrypted = payload.decryptedBlobURI;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
export const { addNewFile, setDecryptedContent } = fileListingSlice.actions;
|
|
|
|
|
|
|
|
export const selectFileCount = (state: RootState) => state.fileListing.files.length;
|
|
|
|
export const selectFiles = (state: RootState) => state.fileListing.files;
|
|
|
|
export const selectFileListingMode = (state: RootState) => state.fileListing.displayMode;
|
|
|
|
|
|
|
|
export default fileListingSlice.reducer;
|