From 22a16c45403aac474f4bce126a10678bfadd0197 Mon Sep 17 00:00:00 2001
From: VIAUD Nathan <nathan.viaud@inria.fr>
Date: Wed, 27 Sep 2023 08:29:38 +0000
Subject: [PATCH] Issue #239: Fix custom icon on prod

---
 electron/components/file.js                    |  9 +++++++--
 electron/components/ipc.js                     |  5 +++--
 src/features/badge/components/BadgeItem.vue    |  3 ++-
 src/features/badge/components/BadgePreview.vue |  7 ++++---
 src/features/badge/components/IconModal.vue    |  8 +++++---
 src/shared/services/badge.service.ts           | 13 +++++++++++--
 src/shared/services/graph.service.ts           |  4 ++--
 7 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/electron/components/file.js b/electron/components/file.js
index fa79cb3c..787f0437 100644
--- a/electron/components/file.js
+++ b/electron/components/file.js
@@ -235,10 +235,15 @@ const writeEpocData = async function (workdir, data) {
  * Copy the imported file to the workdir
  * @param {string} workdir
  * @param {string} filepath
+ * @param {boolean} isIcon
  * @return {string} the path of the copied file
  */
-const copyFileToWorkdir = async function (workdir, filepath) {
-    const assetsPath = path.join(workdir, 'assets');
+const copyFileToWorkdir = async function (workdir, filepath, isIcon) {
+    const pathEnd = isIcon ? path.join('assets', 'icons') : 'assets';
+    const assetsPath = path.join(workdir, pathEnd);
+
+    if(!fs.existsSync(assetsPath)) fs.mkdirSync(assetsPath, {recursive: true});
+
     const copyPath = path.join(assetsPath, path.basename(filepath).replace(/[^a-z0-9.]/gi, '_'));
     if (!fs.existsSync(assetsPath)) fs.mkdirSync(assetsPath);
     fs.copyFileSync(filepath, copyPath);
diff --git a/electron/components/ipc.js b/electron/components/ipc.js
index a3e34e4c..16421600 100644
--- a/electron/components/ipc.js
+++ b/electron/components/ipc.js
@@ -102,10 +102,11 @@ const setupIpcListener = function (targetWindow) {
         await writeEpocData(store.state.projects[targetWindow.id].workdir, data);
     });
 
-    ipcMain.on('importFile', async (event, filepath) => {
+    ipcMain.on('importFile', async (event, data) => {
+        const { filepath, isIcon } = data;
         if(event.sender !== targetWindow.webContents) return;
         
-        sendToFrontend(event.sender, 'fileImported', await copyFileToWorkdir(store.state.projects[targetWindow.id].workdir, filepath));
+        sendToFrontend(event.sender, 'fileImported', await copyFileToWorkdir(store.state.projects[targetWindow.id].workdir, filepath, isIcon));
     });
     
     
diff --git a/src/features/badge/components/BadgeItem.vue b/src/features/badge/components/BadgeItem.vue
index d5b6cfbc..86851e0e 100644
--- a/src/features/badge/components/BadgeItem.vue
+++ b/src/features/badge/components/BadgeItem.vue
@@ -30,7 +30,8 @@ const badgeItem = computed(() => {
 
 function getIconPath() {
     const icon = props.badge ? props.badge.icon : props.icon;
-    return icon.endsWith('.svg') ? icon : `${iconsPath}/${icon}.svg`;
+    if(icon.startsWith('blob')) return icon;
+    return icon.endsWith('.svg') ? `assets://${icon}` : `${iconsPath}/${icon}.svg`;
 }
 
 </script>
diff --git a/src/features/badge/components/BadgePreview.vue b/src/features/badge/components/BadgePreview.vue
index b51cbdf5..ce24a2bf 100644
--- a/src/features/badge/components/BadgePreview.vue
+++ b/src/features/badge/components/BadgePreview.vue
@@ -1,7 +1,6 @@
 <script setup lang="ts">
 import BadgeItem from '@/src/features/badge/components/BadgeItem.vue';
 import { ref } from 'vue';
-import { graphService } from '@/src/shared/services';
 
 const emit = defineEmits<{
     (e: 'click', icon: string): void;
@@ -21,13 +20,15 @@ async function changeIcon(event: Event) {
     const file = target.files[0];
     if (!file) return;
     fileInput.value.value = '';
-    url.value = await graphService.importFile(file.path);
+    url.value = file.path;
+    blob.value = URL.createObjectURL(file);
 }
 function deleteFile() {
     url.value = '';
 }
 
 const url = ref('');
+const blob = ref('');
 const fileInput = ref(null);
 
 </script>
@@ -35,7 +36,7 @@ const fileInput = ref(null);
 <template>
     <div class="new-icon">
         <BadgeItem
-            :icon="url"
+            :icon="blob"
             :inactive="!url"
             @click="onClick"
         />
diff --git a/src/features/badge/components/IconModal.vue b/src/features/badge/components/IconModal.vue
index b0205377..f658ee04 100644
--- a/src/features/badge/components/IconModal.vue
+++ b/src/features/badge/components/IconModal.vue
@@ -5,6 +5,7 @@ import { saveState } from '@/src/shared/services/undoRedo.service';
 
 import BadgeItem from '@/src/features/badge/components/BadgeItem.vue';
 import BadgePreview from '@/src/features/badge/components/BadgePreview.vue';
+import { saveCustomIcon } from '@/src/shared/services';
 
 const editorStore = useEditorStore();
 const projectStore = useProjectStore();
@@ -24,9 +25,10 @@ function chooseIcon(icon: string) {
     close();
 }
 
-function chooseCustomIcon(icon: string) {
-    projectStore.addCustomIcon(icon);
-    chooseIcon(icon);
+async function chooseCustomIcon(icon: string) {
+    const iconPath = await saveCustomIcon(icon);
+
+    chooseIcon(iconPath);
 }
 
 </script>
diff --git a/src/shared/services/badge.service.ts b/src/shared/services/badge.service.ts
index d54d3e4c..62eac53f 100644
--- a/src/shared/services/badge.service.ts
+++ b/src/shared/services/badge.service.ts
@@ -1,10 +1,10 @@
 import { Verbs, ElementType, Condition, Badge } from '@/src/shared/interfaces';
 import { Operand, Operands, Rule } from '@epoc/epoc-types/src/v2';
-import { useEditorStore } from '@/src/shared/stores';
+import { useEditorStore, useProjectStore } from '@/src/shared/stores';
 import { useVueFlow} from '@vue-flow/core';
 import { saveState } from '@/src/shared/services/undoRedo.service';
 import { elementVerbs, verbs } from '@/src/shared/data';
-import { generateContentId } from '@/src/shared/services';
+import { generateContentId, graphService } from '@/src/shared/services';
 
 const { findNode } = useVueFlow({id: 'main'});
 
@@ -200,4 +200,13 @@ export function addNewBadge() {
     };
 
     openBadge(id);
+}
+
+export async function saveCustomIcon(icon: string) {
+    const projectStore = useProjectStore();
+
+    const iconPath = await graphService.importFile(icon, true);
+    projectStore.addCustomIcon(iconPath);
+
+    return iconPath;
 }
\ No newline at end of file
diff --git a/src/shared/services/graph.service.ts b/src/shared/services/graph.service.ts
index 14ac4e52..3c38677a 100644
--- a/src/shared/services/graph.service.ts
+++ b/src/shared/services/graph.service.ts
@@ -27,8 +27,8 @@ function writeProjectData(): void {
     });
 }
 
-function importFile(filepath: string): Promise<string> {
-    api.send('importFile', filepath);
+function importFile(filepath: string, isIcon?: boolean): Promise<string> {
+    api.send('importFile', { filepath, isIcon: Boolean(isIcon) });
 
     return new Promise((resolve) => {
         api.receiveOnce('fileImported', (data) => {
-- 
GitLab