Skip to content

Commit

Permalink
Add file to upload
Browse files Browse the repository at this point in the history
  • Loading branch information
jrmi committed Aug 6, 2023
1 parent 0c4e8f5 commit 05b525d
Show file tree
Hide file tree
Showing 20 changed files with 437 additions and 97 deletions.
1 change: 1 addition & 0 deletions backend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const main = async ({ store, schedules, functions, hooks }) => {
await store.createOrUpdateBox("room", { security: "public" });
await store.createOrUpdateBox("session", { security: "public" });
await store.createOrUpdateBox("user", { security: "private" });
await store.createOrUpdateBox("files", { security: "private" });

// Add schedules
schedules["daily"] = [deleteOldSession(store)];
Expand Down
7 changes: 2 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"lodash.debounce": "^4.0.8",
"marked": "^4.0.12",
"memoizee": "^0.4.14",
"mime-types": "^2.1.35",
"nanoid": "^3.3.0",
"openvidu-browser": "^2.26.0",
"p-limit": "^4.0.0",
Expand Down
2 changes: 0 additions & 2 deletions src/gameComponents/Canvas.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ const NoCanvas = ({ layers, width, height }) => {
}
}, [actions, firstImage.url]);

console.log(firstImage.url, state.status, state.error);

if (state.status === "error") {
return <Error />;
}
Expand Down
10 changes: 10 additions & 0 deletions src/gameComponents/Image/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ const Template = createItemTemplate({
},
name: i18n.t("Image"),
template: {},
async mapMedia(item, fn) {
const result = await Promise.all([
fn(item.content),
fn(item.backContent),
fn(item.overlay?.content),
]);
item.content = result[0];
item.backContent = result[1];
item.overlay = { content: result[2] };
},
});

export default Template;
13 changes: 5 additions & 8 deletions src/gameComponents/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const resize = (prop) => ({ width, actualWidth, prevState }) => {
export const sizeResize = resize("size");
export const radiusResize = resize("radius");

const defaultTemplate = {
const defaultTemplate = () => ({
resizeDirections: {
w: true,
h: true,
Expand All @@ -25,15 +25,12 @@ const defaultTemplate = {
applyDefault(item) {
return item;
},
};
// eslint-disable-next-line no-unused-vars
mapMedia(item, fn) {},
});

export const createItemTemplate = (template) => {
return Object.assign(
{},
JSON.parse(JSON.stringify(defaultTemplate)),
template,
{ uid: uid() }
);
return Object.assign({}, defaultTemplate(), template, { uid: uid() });
};

export default createItemTemplate;
7 changes: 7 additions & 0 deletions src/games/testGame.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,13 @@ const genGame = () => {
color: "#D00022",
size: 80,
},
{
type: "image",
content: "/game_assets/JC.jpg",
backContent: "/game_assets/Red_back.jpg",
overlay: { content: "/game_assets/overlay.png" },
width: 100,
},
],
board: {
size: 1000,
Expand Down
8 changes: 6 additions & 2 deletions src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@
"Error while loading the module, please report the error...": "Error while loading the module, please report the error...",
"Drag'n'drop a vassal module here": "Drag'n'drop a vassal module here",
"Load a Vassal module": "Load a Vassal module",
"Load a Vassal module?": "Load a Vassal module?",
"Load a Vassal module?": "Load a Vassal module? (experimental)",
"Load Vassal module": "Load Vassal module",
"Import Vassal module": "Import Vassal module",
"Secondary color": "Secondary color",
Expand All @@ -351,5 +351,9 @@
"Don't forget to save your game using the save button located in the middle of the left sidebar.\n\n": "Don't forget to save your game using the save button located in the middle of the left sidebar.\n\n",
"Have fun exploring the possibilities and enjoy the process of game creation!": "Have fun exploring the possibilities and enjoy the process of game creation!",
"Login failed. Please try again.": "Login failed. Please try again.",
"Home": "Home"
"Home": "Home",
"Die": "Die",
"Image die": "Image die",
"Include files": "Include files",
"An error occurred. Try again!": "An error occurred. Try again!"
}
12 changes: 8 additions & 4 deletions src/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"Game saved": "Sauvegarde effectuée",
"Game studio": "Créer",
"Game": "Jeu",
"Generating export": "Génération de l'export",
"Generating export": "Génération de l'export...",
"Github": "Github",
"Go back to studio": "Retourner au studio",
"Go back": "Retour",
Expand Down Expand Up @@ -322,9 +322,9 @@
"Next": "Suivant",
"Previous": "Précédent",
"Error while loading the module, please report the error...": "Une erreur est survenue pendant le chargement de ce module, merci de nous prévenir...",
"Drag'n'drop a vassal module here": "Glisser&Déposer un module Vassal ici",
"Drag'n'drop a vassal module here": "Glisser & Déposer un module Vassal ici",
"Load a Vassal module": "Charger un module Vassal",
"Load a Vassal module?": "Charger un module Vassal ?",
"Load a Vassal module?": "Charger un module Vassal ? (Expérimental)",
"Load Vassal module": "Charger le module Vassal",
"Import Vassal module": "Importer le module Vassal",
"Secondary color": "Couleur secondaire",
Expand All @@ -351,5 +351,9 @@
"Don't forget to save your game using the save button located in the middle of the left sidebar.\n\n": "N'oubliez pas de sauvegarder votre jeu en utilisant le bouton de sauvegarde situé au milieu de la barre latérale gauche.\n\n",
"Have fun exploring the possibilities and enjoy the process of game creation!": "Amusez-vous à explorer les possibilités !",
"Login failed. Please try again.": "Échec de l'authentification, veuillez réessayer...",
"Home": "Accueil"
"Home": "Accueil",
"Die": "",
"Image die": "Dé image",
"Include files": "Inclure les fichiers",
"An error occurred. Try again!": "Une erreur est survenue. Veuillez réessayer !"
}
73 changes: 68 additions & 5 deletions src/utils/image.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import pLimit from "p-limit";
import { itemTemplates } from "../gameComponents";

const imageCache = {};

export const getImageWithRetry = async (url, retry = 0) => {
console.log("called with", url, retry);
if (!url) {
return null;
}
Expand All @@ -10,15 +12,12 @@ export const getImageWithRetry = async (url, retry = 0) => {
img.onload = () => {
resolve(img);
};
img.onerror = (e) => {
console.log("onError", url, e);
img.onerror = () => {
if (retry < 3) {
console.log("call retry", retry);
getImageWithRetry(url, retry + 1)
.then(resolve)
.catch(reject);
} else {
console.log("reject");
reject(new Error(`Failed to load: <${url}>`));
}
};
Expand All @@ -35,3 +34,67 @@ export const getImage = async (url) => {
}
return imageCache[url];
};

export class ItemMediaUploader {
constructor(onFile) {
this.onFile = onFile;
this.queue = pLimit(4);
this.cache = {};
}

async upload(item) {
const template = itemTemplates[item.type];
const itemCloned = JSON.parse(JSON.stringify(item));

await template.mapMedia(itemCloned, async (media) => {
if (typeof media === "object" && media?.file) {
if (!this.cache[media.file]) {
this.cache[media.file] = this.queue(this.onFile, media.file);
}
return { type: "local", content: await this.cache[media.file] };
} else {
return media;
}
});

return itemCloned;
}
}

export const imageAsBlob = async (image) => {
const response = await fetch(image.src);
return await response.blob();
};

export const URLAsBlob = async (url) => {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch file: ${response.statusText}`);
}
return await response.blob();
};

export async function hashBlob(blob) {
// Read the blob as an ArrayBuffer
const blobBuffer = await readBlobAsArrayBuffer(blob);

// Use the SubtleCrypto API to hash the content
const hashBuffer = await crypto.subtle.digest("SHA-256", blobBuffer);

// Convert the hash to a hex string
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray
.map((b) => b.toString(16).padStart(2, "0"))
.join("");

return hashHex;
}

function readBlobAsArrayBuffer(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(new Error("Failed to read blob"));
reader.readAsArrayBuffer(blob);
});
}
11 changes: 11 additions & 0 deletions src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,14 @@ export const playAudio = (url, volume = 1) => {
console.log("Fail to play audio", e);
}
};

export const triggerFileDownload = (url, filename) => {
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", filename);
document.body.appendChild(link);
link.click();

// Clean up and remove the link
link.parentNode.removeChild(link);
};
16 changes: 16 additions & 0 deletions src/utils/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,19 @@ export const getItemElement = (id) => {
}
return elem;
};

export const availableItemVisitor = async (items, callback) => {
return await Promise.all(
items.map(async (node) => {
if (node.items) {
return {
...node,
items: await availableItemVisitor(node.items, callback),
};
} else {
// It's an element
return await callback(node);
}
})
);
};
1 change: 0 additions & 1 deletion src/utils/vassal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// import { ZipReader, BlobReader, TextWriter, BlobWriter } from "@zip.js/zip.js";
import X2JS from "x2js";
import pLimit from "p-limit";
import JSZip from "jszip";
Expand Down
Loading

1 comment on commit 05b525d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.