os.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. 'use strict';
  2. const _ = require('lodash');
  3. const path = require('path');
  4. const { Controller } = require('ee-core');
  5. const {
  6. app: electronApp, dialog, shell, Notification,
  7. powerMonitor, screen, nativeTheme
  8. } = require('electron');
  9. const Conf = require('ee-core/config');
  10. const Ps = require('ee-core/ps');
  11. /**
  12. * 操作系统 - 功能demo
  13. * @class
  14. */
  15. class OsController extends Controller {
  16. constructor(ctx) {
  17. super(ctx);
  18. }
  19. /**
  20. * 所有方法接收两个参数
  21. * @param args 前端传的参数
  22. * @param event - ipc通信时才有值。详情见:控制器文档
  23. */
  24. /**
  25. * 消息提示对话框
  26. */
  27. messageShow () {
  28. dialog.showMessageBoxSync({
  29. type: 'info', // "none", "info", "error", "question" 或者 "warning"
  30. title: '自定义标题-message',
  31. message: '自定义消息内容',
  32. detail: '其它的额外信息'
  33. })
  34. return '打开了消息框';
  35. }
  36. /**
  37. * 消息提示与确认对话框
  38. */
  39. messageShowConfirm () {
  40. const res = dialog.showMessageBoxSync({
  41. type: 'info',
  42. title: '自定义标题-message',
  43. message: '自定义消息内容',
  44. detail: '其它的额外信息',
  45. cancelId: 1, // 用于取消对话框的按钮的索引
  46. defaultId: 0, // 设置默认选中的按钮
  47. buttons: ['确认', '取消'], // 按钮及索引
  48. })
  49. let data = (res === 0) ? '点击确认按钮' : '点击取消按钮';
  50. return data;
  51. }
  52. /**
  53. * 选择目录
  54. */
  55. selectFolder () {
  56. const filePaths = dialog.showOpenDialogSync({
  57. properties: ['openDirectory', 'createDirectory']
  58. });
  59. if (_.isEmpty(filePaths)) {
  60. return null
  61. }
  62. return filePaths[0];
  63. }
  64. /**
  65. * 打开目录
  66. */
  67. openDirectory (args) {
  68. if (!args.id) {
  69. return false;
  70. }
  71. let dir = '';
  72. if (path.isAbsolute(args.id)) {
  73. dir = args.id;
  74. } else {
  75. dir = electronApp.getPath(args.id);
  76. }
  77. shell.openPath(dir);
  78. return true;
  79. }
  80. /**
  81. * 加载视图内容
  82. */
  83. loadViewContent (args) {
  84. const { type, content } = args;
  85. let contentUrl = content;
  86. if (type == 'html') {
  87. contentUrl = path.join('file://', electronApp.getAppPath(), content);
  88. }
  89. this.service.os.createBrowserView(contentUrl);
  90. return true
  91. }
  92. /**
  93. * 移除视图内容
  94. */
  95. removeViewContent () {
  96. this.service.os.removeBrowserView();
  97. return true
  98. }
  99. /**
  100. * 打开新窗口
  101. */
  102. createWindow (args) {
  103. const { type, content, windowName, windowTitle } = args;
  104. let contentUrl = null;
  105. if (type == 'html') {
  106. contentUrl = path.join('file://', electronApp.getAppPath(), content)
  107. } else if (type == 'web') {
  108. contentUrl = content;
  109. } else if (type == 'vue') {
  110. let addr = 'http://localhost:8080'
  111. if (Ps.isProd()) {
  112. const mainServer = Conf.getValue('mainServer');
  113. addr = mainServer.protocol + mainServer.host + ':' + mainServer.port;
  114. }
  115. contentUrl = addr + content;
  116. } else {
  117. // some
  118. }
  119. const addonWindow = this.app.addon.window;
  120. let opt = {
  121. title: windowTitle
  122. }
  123. const win = addonWindow.create(windowName, opt);
  124. const winContentsId = win.webContents.id;
  125. // load page
  126. win.loadURL(contentUrl);
  127. return winContentsId;
  128. }
  129. /**
  130. * 获取窗口contents id
  131. */
  132. getWCid (args) {
  133. const addonWindow = this.app.addon.window;
  134. // 主窗口的name默认是main,其它窗口name开发者自己定义
  135. const name = args;
  136. const id = addonWindow.getWCid(name);
  137. return id;
  138. }
  139. /**
  140. * 加载扩展程序
  141. */
  142. // async loadExtension (args) {
  143. // const crxFile = args[0];
  144. // if (_.isEmpty(crxFile)) {
  145. // return false;
  146. // }
  147. // const extensionId = path.basename(crxFile, '.crx');
  148. // const chromeExtensionDir = chromeExtension.getDirectory();
  149. // const extensionDir = path.join(chromeExtensionDir, extensionId);
  150. // Log.info("[api] [example] [loadExtension] extension id:", extensionId);
  151. // unzip(crxFile, extensionDir).then(() => {
  152. // Log.info("[api] [example] [loadExtension] unzip success!");
  153. // chromeExtension.load(extensionId);
  154. // });
  155. // return true;
  156. // }
  157. /**
  158. * 创建系统通知
  159. */
  160. sendNotification (args, event) {
  161. const { title, subtitle, body, silent, clickEvent, closeEvent} = args;
  162. if (!Notification.isSupported()) {
  163. return '当前系统不支持通知';
  164. }
  165. let options = {};
  166. if (!_.isEmpty(title)) {
  167. options.title = title;
  168. }
  169. if (!_.isEmpty(subtitle)) {
  170. options.subtitle = subtitle;
  171. }
  172. if (!_.isEmpty(body)) {
  173. options.body = body;
  174. }
  175. if (!_.isEmpty(silent)) {
  176. options.silent = silent;
  177. }
  178. this.service.os.createNotification(clickEvent, closeEvent, event);
  179. return true
  180. }
  181. /**
  182. * 电源监控
  183. */
  184. initPowerMonitor (args, event) {
  185. const channel = 'controller.os.initPowerMonitor';
  186. powerMonitor.on('on-ac', (e) => {
  187. let data = {
  188. type: 'on-ac',
  189. msg: '接入了电源'
  190. }
  191. event.reply(`${channel}`, data)
  192. });
  193. powerMonitor.on('on-battery', (e) => {
  194. let data = {
  195. type: 'on-battery',
  196. msg: '使用电池中'
  197. }
  198. event.reply(`${channel}`, data)
  199. });
  200. powerMonitor.on('lock-screen', (e) => {
  201. let data = {
  202. type: 'lock-screen',
  203. msg: '锁屏了'
  204. }
  205. event.reply(`${channel}`, data)
  206. });
  207. powerMonitor.on('unlock-screen', (e) => {
  208. let data = {
  209. type: 'unlock-screen',
  210. msg: '解锁了'
  211. }
  212. event.reply(`${channel}`, data)
  213. });
  214. return true
  215. }
  216. /**
  217. * 获取屏幕信息
  218. */
  219. getScreen (args) {
  220. let data = [];
  221. let res = {};
  222. if (args == 0) {
  223. let res = screen.getCursorScreenPoint();
  224. data = [
  225. {
  226. title: '横坐标',
  227. desc: res.x
  228. },
  229. {
  230. title: '纵坐标',
  231. desc: res.y
  232. },
  233. ]
  234. return data;
  235. }
  236. if (args == 1) {
  237. res = screen.getPrimaryDisplay();
  238. }
  239. if (args == 2) {
  240. let resArr = screen.getAllDisplays();
  241. // 数组,只取一个吧
  242. res = resArr[0];
  243. }
  244. // Log.info('[electron] [ipc] [example] [getScreen] res:', res);
  245. data = [
  246. {
  247. title: '分辨率',
  248. desc: res.bounds.width + ' x ' + res.bounds.height
  249. },
  250. {
  251. title: '单色显示器',
  252. desc: res.monochrome ? '是' : '否'
  253. },
  254. {
  255. title: '色深',
  256. desc: res. colorDepth
  257. },
  258. {
  259. title: '色域',
  260. desc: res.colorSpace
  261. },
  262. {
  263. title: 'scaleFactor',
  264. desc: res.scaleFactor
  265. },
  266. {
  267. title: '加速器',
  268. desc: res.accelerometerSupport
  269. },
  270. {
  271. title: '触控',
  272. desc: res.touchSupport == 'unknown' ? '不支持' : '支持'
  273. },
  274. ]
  275. return data;
  276. }
  277. /**
  278. * 获取系统主题
  279. */
  280. getTheme () {
  281. let theme = 'system';
  282. if (nativeTheme.shouldUseHighContrastColors) {
  283. theme = 'light';
  284. } else if (nativeTheme.shouldUseInvertedColorScheme) {
  285. theme = 'dark';
  286. }
  287. return theme;
  288. }
  289. /**
  290. * 设置系统主题
  291. */
  292. setTheme (args) {
  293. // TODO 好像没有什么明显效果
  294. nativeTheme.themeSource = args;
  295. return args;
  296. }
  297. }
  298. OsController.toString = () => '[class OsController]';
  299. module.exports = OsController;