昨日介紹了 Dialog 的基本使用 , 今天我們來將 Dialog 與 "動物聊天室" 做結合吧 !
第一個要追加的功能是 "上傳圖片"
功能說明:按下 後 , 讓使用者選擇一個圖片檔 , 然後將選擇的圖片存到 firestore 中
製作流程 :
在 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="圖片" 時 , 右鍵選單會多一個 "下載" 的功能 , 讓使用者可以儲存圖片到本機中
製作流程 :
實際成品如下圖所示:
製作的細節 , 相信以各位邦友的聰明才智 , 肯定能根據上述的 "製作流程" 完成的 (^.^)/
今年小弟第一次參加 `鐵人賽` , 如文章有誤 , 請各位前輩提出指正 , 感謝 <(_ _)>