sh.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /**
  2. * @author oldj
  3. * @blog http://oldj.net
  4. */
  5. "use strict";
  6. const config = require('../config');
  7. const $ = require('jquery');
  8. const Vue = require('vue');
  9. //Vue.config.debug = true;
  10. Vue.use(require('./dnd'));
  11. const CodeMirror = require('codemirror');
  12. //require('codemirror/mode/shell/shell');
  13. require('./cm_hl');
  14. const cf = require('./cf');
  15. const lang = require('./lang').getLang(navigator.language);
  16. const is_win = process.platform == 'win32';
  17. let my_codemirror;
  18. const app = new Vue({
  19. el: '#sh-app',
  20. data: {
  21. lang: lang,
  22. hosts: cf.getData({
  23. VERSION: config.VERSION
  24. }),
  25. is_prompt_show: false,
  26. is_edit_show: false,
  27. is_pswd_show: false,
  28. current_host: {
  29. content: cf.getSysHosts(),
  30. is_sys: true,
  31. is_editable: false
  32. },
  33. on_after_permission: [],
  34. could_tmp_clean_on: true,
  35. current_edit_host: {},
  36. add_or_edit: '',
  37. sudo_pswd: ''
  38. },
  39. watch: {
  40. 'current_host': function (host) {
  41. my_codemirror.getDoc().setValue(host.content || '');
  42. if (host.is_editable === false) {
  43. my_codemirror.setOption('readOnly', true);
  44. } else {
  45. my_codemirror.setOption('readOnly', false);
  46. }
  47. host._just_switch = 1;
  48. },
  49. 'current_host.content': function () {
  50. let host = this.current_host;
  51. if (host._just_switch) {
  52. host._just_switch = 0;
  53. return;
  54. }
  55. this.doSave();
  56. if (host.on) {
  57. this.caculateHosts(host);
  58. }
  59. }
  60. },
  61. methods: {
  62. add: function () {
  63. this.is_prompt_show = true;
  64. this.is_edit_show = true;
  65. this.current_edit_host = {};
  66. this.add_or_edit = 'add';
  67. //this.chkHostTitle();
  68. setTimeout(() => $('#ipt-host-title').focus(), 100);
  69. },
  70. edit: function (host) {
  71. this.is_prompt_show = true;
  72. this.is_edit_show = true;
  73. this.current_edit_host = host;
  74. this.add_or_edit = 'edit';
  75. setTimeout(() => $('#ipt-host-title').focus(), 100);
  76. },
  77. chkHostTitle: function () {
  78. let host_title = this.current_edit_host.title.replace(/^\s+|\s+$/g, '');
  79. if (!host_title) {
  80. this.current_edit_host.title_inform = this.lang.host_title_cant_be_empty;
  81. $('#ipt-host-title').focus();
  82. return false;
  83. } else {
  84. this.current_edit_host.title_inform = '';
  85. this.host_title = host_title;
  86. return true;
  87. }
  88. },
  89. toSave: function () {
  90. if (!this.chkHostTitle()) {
  91. return;
  92. }
  93. let host;
  94. //if (this.hosts.list.indexOf(this.current_edit_host) > -1) {
  95. if (this.add_or_edit == 'edit') {
  96. // edit
  97. } else {
  98. // add new
  99. host = {
  100. title: this.current_edit_host.title,
  101. content: `# ${this.current_edit_host.title}`,
  102. on: false
  103. };
  104. this.hosts.list.push(host);
  105. this.selectHost(host);
  106. }
  107. this.doSave(true);
  108. this.closePrompt();
  109. },
  110. doSave: function (now) {
  111. clearTimeout(this._t_save);
  112. this._t_save = setTimeout(() => cf.saveData(this.hosts), now ? 0 : 1000);
  113. },
  114. closePrompt: function (action) {
  115. this.is_prompt_show = false;
  116. this.is_edit_show = false;
  117. this.is_pswd_show = false;
  118. if (action == 'pswd') {
  119. // this._to_switch_host.on = !this._to_switch_host.on;
  120. this.sudo_pswd = '';
  121. //this.tmpRecover();
  122. this._on_hosts && this._on_hosts.map((host) => {
  123. host.on = true;
  124. });
  125. this._on_hosts = [];
  126. }
  127. },
  128. selectHost: function (host) {
  129. this.current_host = host;
  130. },
  131. switchHost: function (host) {
  132. if (!host) return;
  133. this._to_switch_host = host;
  134. if (!host.is_sys) {
  135. this.could_tmp_clean_on = true;
  136. }
  137. this.caculateHosts(host, (err) => {
  138. if (err) {
  139. } else {
  140. host.on = !host.on;
  141. this.doSave();
  142. }
  143. this._to_switch_host = null;
  144. });
  145. },
  146. updateHost: function (host) {
  147. this.doSave();
  148. },
  149. showSysHost: function () {
  150. this.current_host = {
  151. content: cf.getSysHosts(),
  152. is_sys: true,
  153. is_editable: false
  154. };
  155. },
  156. delHosts: function (host) {
  157. if (!confirm(this.lang.confirm_del)) {
  158. return;
  159. }
  160. let i = this.hosts.list.indexOf(host);
  161. if (i > -1) {
  162. this.hosts.list.splice(i, 1);
  163. this.current_edit_host = {};
  164. this.closePrompt();
  165. this.doSave();
  166. }
  167. },
  168. caculateHosts: function (host, callback) {
  169. let on_hosts = [];
  170. host = host || this.current_host;
  171. this.hosts.list.map((host) => {
  172. if ((host.on && host != this._to_switch_host) || (!host.on && host == this._to_switch_host)) {
  173. on_hosts.push(host.content);
  174. }
  175. });
  176. let s_hosts = on_hosts.join('\n\n# --------------------\n\n');
  177. s_hosts = `# SwitchHosts!\n${s_hosts}`;
  178. cf.saveHost(s_hosts, this.sudo_pswd, (err) => {
  179. if (err) {
  180. console.log(err);
  181. if (!is_win) {
  182. // mac & linux
  183. if (err.message.indexOf('EACCES') > -1 || err.message.indexOf('permission denied') > -1) {
  184. // get permission
  185. this.askForPermission(() => {
  186. this.caculateHosts(host, callback)
  187. });
  188. } else if (err.message.indexOf('Command failed') > -1) {
  189. // todo show inform
  190. this.sudo_pswd = '';
  191. } else {
  192. alert(err);
  193. }
  194. } else {
  195. // windows
  196. alert(err);
  197. }
  198. return;
  199. }
  200. callback && callback.call(this);
  201. if (this.current_host.is_sys) {
  202. this.showSysHost();
  203. }
  204. });
  205. },
  206. askForPermission: function (callback) {
  207. this.is_prompt_show = true;
  208. this.is_pswd_show = true;
  209. this.sudo_pswd = '';
  210. callback && this.on_after_permission.push(callback);
  211. setTimeout(() => $('#ipt-pswd').focus(), 100);
  212. },
  213. chkPswd: function () {
  214. //this.switchHost(this._to_switch_host);
  215. this.closePrompt();
  216. //this._to_switch_host = null;
  217. let f;
  218. while (f = this.on_after_permission.shift()) {
  219. f && f.call(this);
  220. }
  221. },
  222. tmpClean: function () {
  223. this.could_tmp_clean_on = false;
  224. this._to_switch_host = null;
  225. this._on_hosts = [];
  226. this.hosts.list.map((host) => {
  227. if (host.on) {
  228. this._on_hosts.push(host);
  229. host.on = false;
  230. }
  231. });
  232. this.caculateHosts();
  233. this.doSave(true);
  234. },
  235. tmpRecover: function () {
  236. this.could_tmp_clean_on = true;
  237. if (!this._on_hosts) return;
  238. this._on_hosts.map((host) => {
  239. host.on = true;
  240. });
  241. this._on_hosts = [];
  242. this.caculateHosts();
  243. this.doSave(1);
  244. },
  245. sort: function (list, id, tag, data) {
  246. let tmp = list[data.index];
  247. list.splice(data.index, 1);
  248. list.splice(id, 0, tmp);
  249. this.doSave(1);
  250. },
  251. move: function (from, to, id, tag, data) {
  252. let tmp = from[data.index];
  253. from.splice(data.index, 1);
  254. to.splice(id, 0, tmp);
  255. },
  256. remove: function (from, tag, data) {
  257. from.splice(data.index, 1);
  258. },
  259. log: function (obj) {
  260. console.log(obj);
  261. return 1;
  262. }
  263. }
  264. });
  265. function resize() {
  266. let wh = window.innerHeight;
  267. let h = wh - $('#sys-list').height() - 20;
  268. $('#custom-list').css('height', h);
  269. my_codemirror.setSize('100%', wh);
  270. }
  271. $(document).ready(function () {
  272. let el_textarea = $('#host-code');
  273. //el_textarea.css('height', window.innerHeight - 8);
  274. my_codemirror = CodeMirror.fromTextArea(el_textarea[0], {
  275. lineNumbers: true,
  276. readOnly: true,
  277. mode: 'host'
  278. });
  279. my_codemirror.on('change', function (a, b) {
  280. app.current_host.content = a.getDoc().getValue();
  281. });
  282. my_codemirror.on('gutterClick', function (cm, n) {
  283. if (app.current_host.is_editable === false) return;
  284. let info = cm.lineInfo(n);
  285. //cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
  286. let ln = info.text;
  287. if (/^\s*$/.test(ln)) return;
  288. let new_ln;
  289. if (/^#/.test(ln)) {
  290. new_ln = ln.replace(/^#\s*/, '');
  291. } else {
  292. new_ln = '# ' + ln;
  293. }
  294. my_codemirror.getDoc().replaceRange(new_ln, {line: info.line, ch: 0}, {line: info.line, ch: ln.length});
  295. //app.caculateHosts();
  296. });
  297. resize();
  298. $(window).resize(resize);
  299. });