Skip to content

Commit

Permalink
Merge pull request #277 from scottbenton/feat/delete-old-character-ph…
Browse files Browse the repository at this point in the history
…oto-on-new-upload

feat(portraits): Character portraits now get deleted when changed or …
  • Loading branch information
scottbenton authored Nov 1, 2023
2 parents 958ad3c + 4911d89 commit 9a7ab05
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 8 deletions.
25 changes: 22 additions & 3 deletions src/api-calls/character/deleteCharacter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,27 @@ import {
} from "../assets/_getRef";
import { deleteNotes } from "api-calls/notes/deleteNotes";
import { getCharacterSettingsDoc } from "api-calls/custom-move-oracle-settings/_getRef";
import { getCharacterDoc } from "./_getRef";
import {
constructCharacterPortraitFolderPath,
getCharacterDoc,
} from "./_getRef";
import { deleteAllLogs } from "api-calls/game-log/deleteAllLogs";
import { deleteAllProgressTracks } from "api-calls/tracks/deleteAllProgressTracks";
import { deleteAllAssets } from "api-calls/assets/deleteAllAssets";
import { removeCharacterPortrait } from "./removeCharacterPortrait";
import { deleteImage } from "lib/storage.lib";

export const deleteCharacter = createApiFunction<
{ characterId: string; campaignId?: string },
{
uid: string;
characterId: string;
campaignId?: string;
portraitFilename?: string;
},
void
>((params) => {
return new Promise(async (resolve, reject) => {
const { characterId, campaignId } = params;
const { uid, characterId, campaignId, portraitFilename } = params;

try {
if (campaignId) {
Expand All @@ -30,6 +40,15 @@ export const deleteCharacter = createApiFunction<
}
const promises: Promise<any>[] = [];

if (portraitFilename) {
promises.push(
deleteImage(
constructCharacterPortraitFolderPath(uid, characterId),
portraitFilename
)
);
}

promises.push(deleteNotes({ characterId }));
promises.push(deleteDoc(getCharacterSettingsDoc(characterId)));
promises.push(deleteAllAssets({ characterId }));
Expand Down
38 changes: 38 additions & 0 deletions src/api-calls/character/removeCharacterPortrait.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createApiFunction } from "api-calls/createApiFunction";
import { deleteImage } from "lib/storage.lib";
import { constructCharacterPortraitFolderPath } from "./_getRef";
import { updateCharacter } from "./updateCharacter";
import { FieldValue, deleteField } from "firebase/firestore";

export const removeCharacterPortrait = createApiFunction<
{
uid: string;
characterId: string;
oldPortraitFilename: string;
},
void
>((params) => {
const { uid, characterId, oldPortraitFilename } = params;

return new Promise((resolve, reject) => {
updateCharacter({
characterId,
character: {
profileImage: deleteField() as unknown as undefined,
},
})
.then(() => {
deleteImage(
constructCharacterPortraitFolderPath(uid, characterId),
oldPortraitFilename
)
.then(() => {
resolve();
})
.catch((e) => {
reject(e);
});
})
.catch((e) => reject(e));
});
}, "Failed to remove old character portrait");
17 changes: 16 additions & 1 deletion src/api-calls/character/updateCharacterPortrait.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,35 @@ import {
getCharacterDoc,
} from "./_getRef";
import { createApiFunction } from "api-calls/createApiFunction";
import { removeCharacterPortrait } from "./removeCharacterPortrait";

export const updateCharacterPortrait = createApiFunction<
{
uid: string;
characterId: string;
oldPortraitFilename?: string;
portrait?: File;
scale: number;
position: { x: number; y: number };
},
void
>((params) => {
const { uid, characterId, portrait, scale, position } = params;
const { uid, characterId, oldPortraitFilename, portrait, scale, position } =
params;

return new Promise(async (resolve, reject) => {
try {
if (oldPortraitFilename) {
await removeCharacterPortrait({
uid,
characterId,
oldPortraitFilename,
});
}
} catch (e) {
reject(e);
return;
}
try {
if (portrait) {
await uploadImage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useSnackbar } from "providers/SnackbarProvider/useSnackbar";
import { PortraitAvatarDisplay } from "components/features/characters/PortraitAvatar/PortraitAvatarDisplay";
import ZoomInIcon from "@mui/icons-material/ZoomIn";
import ZoomOutIcon from "@mui/icons-material/ZoomOut";
import { LoadingButton } from "@mui/lab";

export interface PortraitUploaderDialogProps {
open: boolean;
Expand Down Expand Up @@ -155,13 +156,13 @@ export function PortraitUploaderDialog(props: PortraitUploaderDialogProps) {
>
Cancel
</Button>
<Button
<LoadingButton
variant={"contained"}
onClick={() => onUpload()}
disabled={loading}
loading={loading}
>
Upload
</Button>
</LoadingButton>
</DialogActions>
</Dialog>
);
Expand Down
22 changes: 21 additions & 1 deletion src/lib/storage.lib.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { storage } from "config/firebase.config";
import { getDownloadURL, ref, uploadBytes } from "firebase/storage";
import {
getDownloadURL,
ref,
uploadBytes,
deleteObject,
} from "firebase/storage";

export const MAX_FILE_SIZE = 5 * 1024 * 1024;
export const MAX_FILE_SIZE_LABEL = "5 MB";
Expand All @@ -19,6 +24,21 @@ export function uploadImage(path: string, image: File): Promise<boolean> {
});
}

export function deleteImage(path: string, filename: string): Promise<void> {
return new Promise((resolve, reject) => {
const imageRef = ref(storage, `${path}/${filename}`);

deleteObject(imageRef)
.then(() => {
resolve();
})
.catch((e) => {
console.error(e);
reject(`Failed to delete ${filename}.`);
});
});
}

export function getImageUrl(path: string): Promise<string> {
return new Promise((resolve, reject) => {
const imageRef = ref(storage, path);
Expand Down
3 changes: 3 additions & 0 deletions src/stores/character/character.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,18 @@ export const createCharacterSlice: CreateSliceType<CharacterSlice> = (
});
},
deleteCharacter: (characterId) => {
const uid = getState().auth.uid;
const character = getState().characters.characterMap[characterId];
if (!character) {
return new Promise((res, reject) =>
reject("Could not find character in order to delete it.")
);
}
return deleteCharacter({
uid,
characterId,
campaignId: character.campaignId,
portraitFilename: character.profileImage?.filename,
});
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ export const createCurrentCharacterSlice: CreateSliceType<
return updateCharacterPortrait({
uid,
characterId,
oldPortraitFilename:
state.characters.currentCharacter.currentCharacter?.profileImage
?.filename,
portrait,
scale,
position,
Expand Down

0 comments on commit 9a7ab05

Please sign in to comment.