tray.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /**
  2. * tray
  3. * @author oldj
  4. * @blog http://oldj.net
  5. */
  6. 'use strict'
  7. //const fs = require('fs')
  8. const path = require('path')
  9. const {Menu, Tray, shell} = require('electron')
  10. const m_lang = require('../server/lang')
  11. const checkUpdate = require('../server/checkUpdate')
  12. const pref = require('../server/pref')
  13. const setPref = require('../server/actions/setPref')
  14. const os = process.platform
  15. const current_version = require('../version')
  16. const svr = require('../server/svr')
  17. const formatVersion = require('../libs/formatVersion')
  18. const getUserHosts = require('../server/actions/getUserHosts')
  19. let tray = null
  20. function formatTitle (title) {
  21. if (!title) {
  22. return 'untitled'
  23. }
  24. let max_len = 30
  25. title = title.trim()
  26. if (title.length < max_len) {
  27. return title
  28. }
  29. return title.substr(0, max_len) + '..'
  30. }
  31. function makeMenu (app, list, contents, sys_lang) {
  32. let menu = []
  33. let lang = m_lang.getLang(pref.get('user_language', sys_lang))
  34. menu.push({
  35. label: 'SwitchHosts!',
  36. type: 'normal',
  37. // sublabel: util.formatVersion(current_version), // does not work on Mac
  38. click: () => {
  39. app.emit('show')
  40. }
  41. })
  42. menu.push({
  43. label: formatVersion(current_version),
  44. type: 'normal',
  45. enabled: false
  46. })
  47. menu.push({label: '-', type: 'separator'})
  48. let ac = '1234567890abcdefghijklmnopqrstuvwxyz'.split('')
  49. let item_idx = 0
  50. const addItem = (item, level = 0) => {
  51. menu.push({
  52. label: (''.padStart(level, '\u3000')) + formatTitle(item.title),
  53. type: 'checkbox',
  54. checked: item.on,
  55. accelerator: ac[item_idx],
  56. click: () => {
  57. svr.broadcast('toggle_hosts', Object.assign({}, item))
  58. //svr.emit('update_tray')
  59. }
  60. })
  61. item_idx++
  62. (item.children || []).map(i => addItem(i, level + 1))
  63. }
  64. list.map(i => addItem(i))
  65. menu.push({type: 'separator'})
  66. menu.push({
  67. label: lang.feedback, type: 'normal', click: () => {
  68. shell.openExternal('https://github.com/oldj/SwitchHosts/issues')
  69. }
  70. })
  71. menu.push({
  72. label: lang.check_update, type: 'normal', click: () => {
  73. checkUpdate.check()
  74. }
  75. })
  76. if (os === 'darwin') {
  77. menu.push({
  78. label: lang.toggle_dock_icon, type: 'normal', click: () => {
  79. let is_dock_visible = app.dock.isVisible()
  80. if (is_dock_visible) {
  81. app.dock.hide()
  82. } else {
  83. app.dock.show()
  84. }
  85. setPref(svr, 'is_dock_icon_hidden', is_dock_visible)
  86. }
  87. })
  88. }
  89. menu.push({type: 'separator'})
  90. menu.push({
  91. label: lang.quit,
  92. type: 'normal',
  93. accelerator: 'CommandOrControl+Q',
  94. click: () => {
  95. app.quit()
  96. }
  97. })
  98. return menu
  99. }
  100. function makeTitle (list = []) {
  101. const currItems = (list || []).filter(item => item.on) || []
  102. const appendTitleEvt = function (lis = [], opr = ',') {
  103. let _str = ''
  104. if (lis.length) {
  105. const appendTitle = (prev, curr) => {
  106. return {
  107. title: `${prev.title}${prev.title ? `${opr}` : ''}${curr.title}`
  108. }
  109. }
  110. _str = currItems.reduce(appendTitle, {title: ''}).title || ''
  111. }
  112. return _str
  113. }
  114. const _ori = appendTitleEvt(list)
  115. return {
  116. ori: _ori,
  117. show: _ori.length > 20 ? `${_ori.substr(0, 20)}...` : _ori,
  118. tips: `${appendTitleEvt(list, '\n')}`
  119. }
  120. }
  121. function makeTray (app, contents, sys_lang = 'en') {
  122. const lang = m_lang.getLang(sys_lang)
  123. let icon = 'logo.png'
  124. if (process.platform === 'darwin') {
  125. icon = 'logoTemplate.png'
  126. }
  127. tray = new Tray(path.join(__dirname, '..', 'assets', icon))
  128. svr.on('update_tray', () => {
  129. getUserHosts()
  130. .then(list => {
  131. let contextMenu = Menu.buildFromTemplate(makeMenu(app, list, contents, sys_lang))
  132. tray.setContextMenu(contextMenu)
  133. const {ori = '', show = '', tips = ''} = makeTitle(list)
  134. if (pref.get('show_title_on_tray')) {
  135. tray.setTitle(show)
  136. tray.setToolTip(ori ? `\n${lang.current_active_hosts}: \n\n${tips}\n` : 'SwitchHosts!')
  137. }
  138. })
  139. })
  140. let is_dock_icon_hidden = pref.get('is_dock_icon_hidden', false)
  141. if (is_dock_icon_hidden) {
  142. app.dock.hide()
  143. }
  144. tray.on('click', () => {
  145. if (process.platform === 'win32') {
  146. app.emit('show')
  147. }
  148. })
  149. svr.on('hosts_saved', () => {
  150. svr.emit('update_tray')
  151. })
  152. svr.emit('update_tray')
  153. }
  154. exports.makeTray = makeTray