os.js 8.2 KB

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