昨日介紹了 Dialog 的基本使用 , 今天我們來將 Dialog 與 "動物聊天室" 做結合吧 !
第一個要追加的功能是 "上傳圖片"
功能說明:按下 
 後 , 讓使用者選擇一個圖片檔 , 然後將選擇的圖片存到 firestore 中
製作流程 :
 觸發 @click
 觸發 @click在 Chatroom.vue 中的 flaticon-image 上追加 @click 與對應的 method
<div class="input-left">
    <i class="flaticon flaticon-happy cursor-pointer" title="emoji"></i>
-    <i class="flaticon flaticon-image cursor-pointer" title="圖片" ></i>
+    <i class="flaticon flaticon-image cursor-pointer" title="圖片" @click="uploadImage"></i>
    <i class="flaticon flaticon-attachment cursor-pointer" title="檔案"></i>
</div>
uploadImage() {
    window.ipcRenderer
        .invoke('image:choose-image') // 呼叫 ipcMain.handle('image:choose-image'
},
使用 ipcMain.handle('image:choose-image' 監聽按鈕事件的觸發
// 選擇圖片
ipcMain.handle('image:choose-image', async event => {
    ...
});
dialog.showOpenDialog 開啟 dialog , 讓使用者選擇檔案
// 選擇圖片
ipcMain.handle('image:choose-image', async event => {
    const result = await dialog.showOpenDialog({
        properties: ['openFile'],
        filters: [
            {name: '圖片', extensions: ['jpg', 'png', 'gif']},
        ],
    });
    if (result.canceled) return {canceled: true};
    else {
        const filePath = result.filePaths[0];
        const contentType = mime.lookup(filePath);
        const base64Image = fs.readFileSync(filePath, {encoding: 'base64'});
        return {
           path: filePath, 
           base64: `data:${contentType};base64,${base64Image}`
        };
    }
});
如果 result.canceled === true 時 , 代表使用者取消選擇 , 因此不做任何事
 if (result.canceled) return {canceled: true};
其他狀況 , 就取出 result.filePaths[0] 當作圖片的檔案路徑 ( filePath )
const filePath = result.filePaths[0];
我們需要利用副檔名 , 建立 contentType , 因此追加第三方套件 mime-types
$ npm i -s mime-types
利用 fs.readFileSync(filePath, {encoding: 'base64'}) 取得圖片的 base64 字串 , 然後補上 contentType 以符合網頁使用的 base64 格式
else {
    const filePath = result.filePaths[0];
    const contentType = mime.lookup(filePath);
    const base64Image = fs.readFileSync(filePath, {encoding: 'base64'});
    return {
       path: filePath, 
       base64: `data:${contentType};base64,${base64Image}`
    };
}
整合第 2 . 3 步驟後 , 代表我們獲得如下方所示完整的 image:choose-image 處理
// 選擇圖片
ipcMain.handle('image:choose-image', async event => {
    const result = await dialog.showOpenDialog({
        properties: ['openFile'],
        filters: [
            {name: '圖片', extensions: ['jpg', 'png', 'gif']},
        ],
    });
    if (result.canceled) return {canceled: true};
    else {
        const filePath = result.filePaths[0];
        const contentType = mime.lookup(filePath);
        const base64Image = fs.readFileSync(filePath, {encoding: 'base64'});
        return {
           path: filePath, 
           base64: `data:${contentType};base64,${base64Image}`
        };
    }
});
新增 type='image' 的聊天訊息 , 並將 base64 放入聊天訊息之中
uploadImage() {
    window.ipcRenderer
        .invoke('image:choose-image')
        .then(({base64}) => {
            const message = {
                name: '你',
                team: 'right',
                avatar: 'cat-3.png',
                type: 'image',
                base64,
                msg: '這是圖片',
            }
            this.addMessage(message);
        })
        .catch(e => console.error(e));
},
修改 msg 區塊的顯示 , 當 chat.type === 'image' 時 , 顯示圖片 (img) 而非文字 (span)
<div class="msg" :class="[chat.team]" @contextmenu="openMenu(chat)">
    <img v-if="chat.type === 'image'" width="100%" :src="chat.base64" :alt="chat.avatar">
    <span v-else class="break-words">{{chat.msg}}</span>
</div>
然後 , 你完成了 "上傳圖片" 的功能 , 下圖為功能操作

要追加的第二個功能是 "儲存圖片"
功能說明:如果聊天內容是 type="圖片" 時 , 右鍵選單會多一個 "下載" 的功能 , 讓使用者可以儲存圖片到本機中
製作流程 :
實際成品如下圖所示:
製作的細節 , 相信以各位邦友的聰明才智 , 肯定能根據上述的 "製作流程" 完成的 (^.^)/
今年小弟第一次參加 `鐵人賽` , 如文章有誤 , 請各位前輩提出指正 , 感謝  <(_ _)>