Electric + Vue chat imitating wechat interface | electronic Vue chat practice

brief introduction

Electronic VChat practice chat project It is a chat room based on the technology of electron + Vue + electron Vue + vuex + node. It has the functions of message sending / expression, picture / video preview, drag upload / paste screenshot sending / wechat dll screenshot, right-click menu, friend circle / red packet / skin changing, etc.

Design sketch

Technical framework

  • Frame technology: electron + electron Vue + Vue
  • State management: Vuex
  • Address routing: Vue router
  • Font Icon: ali iconfont Font Icon Library
  • Pop up plug-in: wcPop
  • Packaging tool: electronic builder
  • Picture preview: Vue photo Preview
  • Video component: Vue video player
/**
 * @Desc   Public and global component configuration
 * @about  Q: 282310962  wx: xy190310
 */

// Introduce common components
import winBar from './components/winbar'
import sideBar from './components/sidebar'

// Bring in public styles
import './assets/fonts/iconfont.css'
import './assets/css/reset.css'
import './assets/css/layout.css'

// Introduction of pop-up window wcPop
import wcPop from './assets/js/wcPop/wcPop'
import './assets/js/wcPop/skin/wcPop.css'

// Introducing Vue photo preview component
import photoView from 'vue-photo-preview'
import 'vue-photo-preview/dist/skin.css'

// Introduce video player
import videoPlayer from 'vue-video-player'
import 'video.js/dist/video-js.css'

const install = Vue => {
    // Registration component
    Vue.component('win-bar', winBar)
    Vue.component('side-bar', sideBar)

    // Application example
    Vue.use(photoView, {
        // loop: false, / / loop
        // fullscreenEl: true, / / full screen
        // Arrow El: true, / / left and right buttons
    })
    Vue.use(videoPlayer)
}

export default install

Electron is an open source library developed by Github to build cross platform desktop applications using HTML,CSS and JavaScript. As for how to build a project, I will not introduce it here, just go to the official website.

https://electronjs.org/

https://github.com/SimulatedGREG/electron-vue

electron main process create form

Create and control browser window through BrowserWindow object in electron ic

import { BrowserWindow, app, ipcMain, Tray, Menu } from 'electron'

// Introduce main thread public configuration
import Common from './utils/common'

/**
 * Set `__static` path to static files in production
 * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
 */
if (process.env.NODE_ENV !== 'development') {
  global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
}

let mainWin
let tray
let forceQuit = false
let logined = false

/**
 * Create main window=============================
 */
function createMainWin() {
  mainWin = new BrowserWindow({
    // background color
    // backgroundColor: '#ebebeb',
    width: Common.WIN_SIZE_MAIN.width,
    height: Common.WIN_SIZE_MAIN.height,
    title: Common.WIN_TITLE,
    useContentSize: true,
    autoHideMenuBar: true,
    // Borderless window
    frame: false,
    resizable: true,
    // Whether to display when creating a window. The default value is true
    show: false,
    webPreferences: {
      // devTools: false,
      webSecurity: false
    }
  })

  mainWin.setMenu(null)
  mainWin.loadURL(Common.WIN_LOAD_URL())

  mainWin.once('ready-to-show', () => {
    mainWin.show()
    mainWin.focus()
  })

  mainWin.on('close', (e) => {
    if(logined && !forceQuit) {
      e.preventDefault()
      mainWin.hide()
    }else {
      mainWin = null
      app.quit()
    }
  })

  initialIPC()
}

app.on('ready', createMainWin)

app.on('activate', () => {
  if(mainWin === null) {
    createMainWin()
  }
})

app.on('before-quit', () => {
  forceQuit = true
})

app.on('window-all-closed', () => {
  if(process.platform !== 'darwin') {
    app.quit()
  }
})

System tray icon + icon blinking + right-click menu realized by electron

electron creates Tray icons and right-click through Tray and Menu objects

/**
 * Tray icon event
 */
let flashTrayTimer = null
let trayIco1 = `${__static}/icon.ico`
let trayIco2 = `${__static}/empty.ico`
let apptray = {
  // Create tray icon
  createTray() {
    tray = new Tray(trayIco1)
    const menu = Menu.buildFromTemplate([
      {
        label: 'Open the main interface',
        icon: `${__static}/tray-ico1.png`,
        click: () => {
          if(mainWin.isMinimized()) mainWin.restore()
          mainWin.show()
          mainWin.focus()
          
          this.flashTray(false)
        }
      },
      {
        label: 'about',
      },
      {
        label: 'Sign out',
        click: () => {
          if(process.platform !== 'darwin') {
            mainWin.show()
            // Clear login information
            mainWin.webContents.send('clearLoggedInfo')
            
            forceQuit = true
            mainWin = null
            app.quit()
          }
        }
      },
    ])
    tray.setContextMenu(menu)
    tray.setToolTip('electron-vchat v1.0.0')

    // Tray click event
    tray.on('click', () => {
      if(mainWin.isMinimized()) mainWin.restore()
      mainWin.show()
      mainWin.focus()

      this.flashTray(false)
    })
  },
  // Tray icon blinks
  flashTray(bool) {
    let hasIco = false

    if(bool) {
      if(flashTrayTimer) return
      flashTrayTimer = setInterval(() => {
        tray.setImage(hasIco ? trayIco1 : trayIco2)
        hasIco = !hasIco
      }, 500)
    }else {
      if(flashTrayTimer) {
        clearInterval(flashTrayTimer)
        flashTrayTimer = null
      }

      tray.setImage(trayIco1)
    }
  },
  // Destroy tray icon
  destroyTray() {
    this.flashTray(false)
    tray.destroy()
    tray = null
  }
}

Electronic borderless form drag, custom top bar

// Top window
handleFixTop() {
	this.isAlwaysOnTop = !this.isAlwaysOnTop
	currentWin.setAlwaysOnTop(this.isAlwaysOnTop)
},

// minimize
handleMin() {
	currentWin.minimize()
},

// Maximization
handleMax() {
	if(!currentWin.isMaximizable()) return
	if(currentWin.isMaximized()) {
		currentWin.unmaximize()
		this.SET_WINMAXIMIZE(false)
	}else {
		currentWin.maximize()
		this.SET_WINMAXIMIZE(true)
	}
},

Local drag by setting WebKit app region: drag

Note: after the default setting - WebKit app region: drag, the following elements cannot be clicked. You can click no drag through the setting.

Electronic implements contentable = "true" two-way binding and inserts an expression at the cursor

In vue, set div to edit contentable = "true" user-defined two-way binding v-model, and insert dynamic expression at the cursor.

You can refer to the previous sharing: https://juejin.im/post/5e141ffc5188253a57049a63

Electronic + Vue implementation of editable box paste screenshot send picture

// Paste and send pictures in the editable div contentable
handlePastImage {
	let that = this
	this.$refs.editor.addEventListener('paste', function(e) {
		let cbd = e.clipboardData
		let ua = window.navigator.userAgent
		if(!(e.clipboardData && e.clipboardData.items)) return
		
		if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" &&
			cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" &&
			ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49){
			return;
		}
		for(var i = 0; i < cbd.items.length; i++){
			var item = cbd.items[i];
			console.log(item);
			console.log(item.kind);
			if(item.kind == "file"){
				var blob = item.getAsFile();
				if(blob.size === 0){
					return;
				}
				// Insert picture record
				var reader = new FileReader();
				reader.readAsDataURL(blob);
				reader.onload = function(){
					var _img = this.result;

					// ***Return picture to parent component
					that.$emit('pasteFn', _img)
				}
			}
		}
	})
},

Well, based on the electronic + Vue desktop chat practice sharing is here, I hope it can help a little~~

Finally, two latest multi terminal (Uniapp, Taro) chat instances are sent:

Based on vue+uniapp live project |uni-app imitation voice / unfamiliar street Live Room

Taro chat room | react+taro imitating wechat chat App interface | taro chat instance

Tags: Front-end Vue github Javascript React

Posted on Fri, 10 Jan 2020 11:04:45 -0500 by larand