Browse Source

删除老文件。

oldj 8 years ago
parent
commit
98ffe9f056
100 changed files with 0 additions and 25107 deletions
  1. 0 107
      src1/bg/check_for_update.js
  2. 0 54
      src1/bg/events.js
  3. 0 18848
      src1/build/bundle.js
  4. 0 80
      src1/common/lang/cn.js
  5. 0 80
      src1/common/lang/en.js
  6. 0 12
      src1/index.html
  7. 0 148
      src1/main.js
  8. 0 33
      src1/package.json
  9. 0 61
      src1/renderer/Agent.js
  10. 0 24
      src1/server/Server.js
  11. 0 8
      src1/server/actions.js
  12. 0 22
      src1/server/actions/getHosts.js
  13. 0 14
      src1/server/actions/getLang.js
  14. 0 25
      src1/server/actions/getPref.js
  15. 0 21
      src1/server/actions/getSysHosts.js
  16. 0 30
      src1/server/actions/getUserHosts.js
  17. 0 16
      src1/server/actions/index.js
  18. 0 11
      src1/server/actions/test.js
  19. 0 57
      src1/server/io.js
  20. 0 43
      src1/server/lang.js
  21. 0 42
      src1/server/paths.js
  22. 0 369
      src1/ui/agent.js
  23. BIN
      src1/ui/assets/app.icns
  24. BIN
      src1/ui/assets/icon_0.pdf
  25. BIN
      src1/ui/assets/icon_1.pdf
  26. BIN
      src1/ui/assets/icon_2.pdf
  27. BIN
      src1/ui/assets/ilogoTemplate.png
  28. BIN
      src1/ui/assets/[email protected]
  29. BIN
      src1/ui/assets/[email protected]
  30. BIN
      src1/ui/assets/logo.png
  31. BIN
      src1/ui/assets/[email protected]
  32. BIN
      src1/ui/assets/[email protected]
  33. BIN
      src1/ui/assets/[email protected]
  34. BIN
      src1/ui/assets/logoTemplate.png
  35. BIN
      src1/ui/assets/[email protected]
  36. BIN
      src1/ui/assets/[email protected]
  37. BIN
      src1/ui/assets/[email protected]
  38. BIN
      src1/ui/assets/logo_512.png
  39. 0 129
      src1/ui/components/app.js
  40. 0 20
      src1/ui/components/app.less
  41. 0 13
      src1/ui/components/cfg.less
  42. 0 50
      src1/ui/components/content/cm_hl.js
  43. 0 95
      src1/ui/components/content/content.js
  44. 0 61
      src1/ui/components/content/content.less
  45. 0 127
      src1/ui/components/content/editor.js
  46. 0 33
      src1/ui/components/content/editor.less
  47. 0 295
      src1/ui/components/frame/edit.js
  48. 0 55
      src1/ui/components/frame/edit.less
  49. 0 73
      src1/ui/components/frame/frame.js
  50. 0 108
      src1/ui/components/frame/frame.less
  51. 0 95
      src1/ui/components/frame/group.js
  52. 0 62
      src1/ui/components/frame/group.less
  53. 0 239
      src1/ui/components/frame/preferences.js
  54. 0 35
      src1/ui/components/frame/preferences.less
  55. 0 85
      src1/ui/components/frame/sudo.js
  56. 0 7
      src1/ui/components/frame/sudo.less
  57. 0 118
      src1/ui/components/panel/buttons.js
  58. 0 53
      src1/ui/components/panel/buttons.less
  59. 0 83
      src1/ui/components/panel/iconfont/iconfont.css
  60. BIN
      src1/ui/components/panel/iconfont/iconfont.eot
  61. 0 102
      src1/ui/components/panel/iconfont/iconfont.js
  62. 0 150
      src1/ui/components/panel/iconfont/iconfont.svg
  63. BIN
      src1/ui/components/panel/iconfont/iconfont.ttf
  64. BIN
      src1/ui/components/panel/iconfont/iconfont.woff
  65. 0 316
      src1/ui/components/panel/list.js
  66. 0 10
      src1/ui/components/panel/list.less
  67. 0 151
      src1/ui/components/panel/list_item.js
  68. 0 65
      src1/ui/components/panel/list_item.less
  69. 0 26
      src1/ui/components/panel/panel.js
  70. 0 10
      src1/ui/components/panel/panel.less
  71. 0 79
      src1/ui/components/panel/searchbar.js
  72. 0 19
      src1/ui/components/panel/searchbar.less
  73. 0 14
      src1/ui/configs.js
  74. 0 13
      src1/ui/event.js
  75. 0 24
      src1/ui/libs/default_data.js
  76. 0 34
      src1/ui/libs/io.js
  77. 0 72
      src1/ui/libs/kw.js
  78. 0 40
      src1/ui/libs/paths.js
  79. 0 60
      src1/ui/libs/pref.js
  80. 0 15
      src1/ui/libs/util.js
  81. 0 28
      src1/ui/mock.js
  82. 0 305
      src1/ui/modules/mainMenu.js
  83. 0 66
      src1/ui/modules/stat.js
  84. 0 116
      src1/ui/modules/tray.js
  85. 0 17
      src1/ui/ui.js
  86. 0 108
      src1/ui2/components/app.js
  87. 0 20
      src1/ui2/components/app.less
  88. 0 13
      src1/ui2/components/cfg.less
  89. 0 50
      src1/ui2/components/content/cm_hl.js
  90. 0 95
      src1/ui2/components/content/content.js
  91. 0 61
      src1/ui2/components/content/content.less
  92. 0 127
      src1/ui2/components/content/editor.js
  93. 0 33
      src1/ui2/components/content/editor.less
  94. 0 295
      src1/ui2/components/frame/edit.js
  95. 0 55
      src1/ui2/components/frame/edit.less
  96. 0 73
      src1/ui2/components/frame/frame.js
  97. 0 108
      src1/ui2/components/frame/frame.less
  98. 0 95
      src1/ui2/components/frame/group.js
  99. 0 62
      src1/ui2/components/frame/group.less
  100. 0 239
      src1/ui2/components/frame/preferences.js

+ 0 - 107
src1/bg/check_for_update.js

@@ -1,107 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-const request = require('request')
-const cheerio = require('cheerio')
-const {shell, dialog} = require('electron')
-const current_version = require('../version').version
-const m_lang = require('../server/lang')
-const util = require('../ui/libs/util')
-const lang = m_lang.getLang(global.user_language)
-
-function convertStrVersion (v) {
-  let a = v.match(/\d+/g)
-  return a.map(i => parseInt(i))
-}
-
-function compareVersion (a, b) {
-  if (typeof a === 'string') {
-    a = convertStrVersion(a)
-  }
-  if (typeof b === 'string') {
-    b = convertStrVersion(b)
-  }
-
-  let len = Math.max(a.length, b.length)
-  for (let i = 0; i < len; i++) {
-    let ai = a[i]
-    let bi = b[i]
-
-    if (typeof ai === 'number' && typeof bi === 'number') {
-      if (ai === bi) {
-        continue
-      }
-
-      return ai - bi
-    }
-
-    if (typeof ai === 'number' && typeof bi !== 'number') {
-      return 1
-    }
-    if (typeof ai !== 'number' && typeof bi === 'number') {
-      return -1
-    }
-    return 0
-  }
-}
-
-exports.check = (is_silent = false, renderer = null) => {
-  let release_url = require('../ui/configs').url_download
-  console.log('start check updates..')
-  request(release_url, (err, res, body) => {
-    let buttons = [lang.ok]
-    if (err) {
-      console.log(err)
-
-      if (!is_silent) {
-        dialog.showMessageBox({
-          type: 'error',
-          message: lang.check_update_err,
-          buttons
-        })
-      }
-      return
-    }
-
-    let $ = cheerio.load(body)
-    let a = $('.release-meta .css-truncate-target')
-    if (a.length <= 0) {
-      console.log('not found versios!')
-      return
-    }
-    let last_v = $(a[0]).text()
-    // Array.from(a).map(i => {
-    //     console.log($(i).text());
-    // });
-
-    let cmp = compareVersion(current_version, last_v)
-    console.log('cmp', cmp)
-    let message
-    if (cmp >= 0) {
-      // 没有发现新版本
-      message = m_lang.fill(lang.check_update_nofound, util.formatVersion(current_version))
-
-    } else {
-      // 发现新版本
-      message = m_lang.fill(lang.check_update_found, last_v)
-      buttons.unshift(lang.cancel)
-      renderer.send('update_found', last_v)
-    }
-
-    if (!is_silent) {
-      dialog.showMessageBox({
-        type: 'info',
-        message,
-        buttons
-      }, (res) => {
-        if (cmp < 0 && res === 1) {
-          shell.openExternal(release_url)
-        }
-      })
-    }
-  })
-}

+ 0 - 54
src1/bg/events.js

@@ -1,54 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const fs = require('fs');
-const {ipcMain, shell} = require('electron');
-
-exports.init = (app, contents) => {
-
-    ipcMain.on('show_app', () => {
-        app.emit('show');
-    });
-
-    ipcMain.on('to_add_host', () => {
-        if (contents && contents.send) {
-            contents.send('to_add_host');
-        }
-    });
-
-    ipcMain.on('to_export', (fn) => {
-        if (contents && contents.send) {
-            contents.send('get_export_data', fn);
-        }
-    });
-
-    ipcMain.on('export_data', (e, fn, data) => {
-        console.log(fn);
-        console.log(data);
-        fs.writeFile(fn, data, 'utf-8', (err) => {
-            if (err) {
-                electron.dialog.showErrorBox('error', err.message || 'Fail to export!');
-            }
-        });
-    });
-
-    ipcMain.on('to_import', (fn) => {
-        if (contents && contents.send) {
-            contents.send('to_import', fn);
-        }
-    });
-
-    ipcMain.on('relaunch', (fn) => {
-        app.relaunch({args: process.argv.slice(1) + ['--relaunch']});
-        app.exit(0);
-    });
-
-    ipcMain.on('open_url', (e, url) => {
-        shell.openExternal(url);
-    });
-
-};

File diff suppressed because it is too large
+ 0 - 18848
src1/build/bundle.js


+ 0 - 80
src1/common/lang/cn.js

@@ -1,80 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-exports.content = {
-    _lang_name: '简体中文'
-    , add: '添加'
-    , add_host: '添加 host 规则'
-    , auto_launch: '随系统一起启动'
-    , auto_refresh: '自动更新'
-    , bad_url: 'URL 地址有误。'
-    , cancel: '取消'
-    , check_update: '检查更新'
-    , check_update_err: '检查更新出错,请稍后再试。:-('
-    , check_update_found: '发现新版本 ${0},前往下载?'
-    , check_update_nofound: '当前版本 ${0} 已是最新版本。'
-    , comment: '注释'
-    , confirm_del: '确定要删除此 host 吗?'
-    , confirm_import: '确定要导入吗?原方案列表将被覆盖,此操作不可撤销。'
-    // , current_version: '当前版本:'
-    , day: '天'
-    , days: '天'
-    , del_host: '删除当前 host'
-    , edit: '编辑'
-    , edit_host: '修改 host'
-    , export: '导出'
-    , feedback: '意见反馈'
-    , file: '文件'
-    , help: '帮助'
-    , hide_at_launch: '启动时隐藏'
-    , hide_dock_icon: '隐藏 Dock 图标'
-    , homepage: '主页'
-    , host_title: 'host 方案名'
-    , host_title_cant_be_empty: 'Host 方案名不能为空!'
-    , hour: '小时'
-    , hours: '小时'
-    , import: '导入'
-    , input_sudo_pswd: '请输入您的开机密码(sudo 密码)'
-    , is_updated: '当前版本是最新版本。'
-    , is_updated_title: '已是最新'
-    , language: '语言'
-    , last_refresh: '上次更新:'
-    , never: '从不'
-    , new: '新建'
-    , new_version_available: '检测到新版本,立刻下载?'
-    , no_valid_host_found: '所指定的文件中未找到合法的 host 配置'
-    , ok: '确定'
-    , please_run_as_admin: '请以管理员身份运行 SwitchHosts!'
-    , pref_after_cmd: 'Host 应用后命令'
-    , pref_after_cmd_info: '每次 Host 应用后将执行下面的系统命令:'
-    , pref_after_cmd_placeholder: '在这儿输入你的命令'
-    , pref_choice_mode: '选择模式'
-    , pref_choice_mode_multiple: '多选'
-    , pref_choice_mode_single: '单选'
-    , preferences: '设置'
-    , quit: '退出'
-    , readonly: '只读'
-    , refresh: '刷新'
-    , remote_hosts: '远程方案'
-    , search: '搜索'
-    , set_and_back: '设置并返回'
-    , set_and_relaunch_app: '确定并重启程序'
-    , should_restart_after_change_language: '修改语言后需要重启应用方可生效。'
-    , show_dock_icon: '显示 Dock 图标'
-    , sudo_pswd: '密码'
-    , sys_host_title: '系统 Hosts'
-    , tmp_clean: '临时去掉所有绑定'
-    , tmp_recover: '恢复绑定'
-    , toggle_dock_icon: '显示/隐藏 Dock 图标'
-    , untitled: '未命名'
-    , url: 'URL 地址'
-    , view: '视图'
-    , where_group: '分组'
-    , where_local: '本地'
-    , where_remote: '远程'
-    , window: '窗口'
-};

+ 0 - 80
src1/common/lang/en.js

@@ -1,80 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-exports.content = {
-    _lang_name: 'English'
-    , add: 'Add'
-    , add_host: 'Add new rules'
-    , auto_launch: 'Run at login'
-    , auto_refresh: 'Auto refresh'
-    , bad_url: 'URL is not valid.'
-    , cancel: 'Cancel'
-    , check_update: 'Check for updates'
-    , check_update_err: 'Something went wrong while checking updates, please try again later. :-('
-    , check_update_found: 'New version ${0} is avaliable, download it now?'
-    , check_update_nofound: 'Current version ${0} is the latest version.'
-    , comment: 'Comment'
-    , confirm_del: 'Are you sure you want to delete this host?'
-    , confirm_import: 'You sure you want to import it? The original rules will be overwriten, this operation can not be undone.'
-    // , current_version: 'Current version: '
-    , day: 'day'
-    , days: 'days'
-    , del_host: 'Delete current host'
-    , edit: 'Edit'
-    , edit_host: 'Edit host'
-    , export: 'Export'
-    , feedback: 'Feedback'
-    , file: 'File'
-    , help: 'Help'
-    , hide_at_launch: 'Hide at launch'
-    , hide_dock_icon: 'Hide Dock Icon'
-    , homepage: 'Homepage'
-    , host_title: 'Host title'
-    , host_title_cant_be_empty: 'Host title could not be empty!'
-    , hour: 'hour'
-    , hours: 'hours'
-    , import: 'Import'
-    , input_sudo_pswd: 'Input your sudo password'
-    , is_updated: 'You already have the latest version of SwitchHosts! installed.'
-    , is_updated_title: 'You are up to date!'
-    , language: 'Language'
-    , last_refresh: 'Last refresh: '
-    , never: 'never'
-    , new: 'New'
-    , new_version_available: 'New version available, download now?'
-    , no_valid_host_found: 'There is no valid host in the file.'
-    , ok: 'OK'
-    , please_run_as_admin: 'Please run SwitchHosts! as an Administrator.'
-    , pref_after_cmd: 'Command after a host be applied'
-    , pref_after_cmd_info: 'The following system commands will be executed when Host applied: '
-    , pref_after_cmd_placeholder: 'input your commands here'
-    , pref_choice_mode: 'Choide mode'
-    , pref_choice_mode_multiple: 'Multiple choice'
-    , pref_choice_mode_single: 'Single choice'
-    , preferences: 'Preferences'
-    , quit: 'Quit'
-    , readonly: 'Read only'
-    , refresh: 'Refresh'
-    , remote_hosts: 'Remote hosts'
-    , search: 'Search'
-    , set_and_back: 'Set and back'
-    , set_and_relaunch_app: 'Set and Relaunch App'
-    , should_restart_after_change_language: 'Should relaunch this App after changing language.'
-    , show_dock_icon: 'Show Dock Icon'
-    , sudo_pswd: 'Password'
-    , sys_host_title: 'System Hosts'
-    , tmp_clean: 'Temporarily turn off all rules.'
-    , tmp_recover: 'Recover rules.'
-    , toggle_dock_icon: 'Toggle Dock Icon'
-    , untitled: 'untitled'
-    , url: 'URL'
-    , view: 'View'
-    , where_group: 'Group'
-    , where_local: 'local'
-    , where_remote: 'remote'
-    , window: 'Window'
-};

+ 0 - 12
src1/index.html

@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-	<meta charset="UTF-8">
-	<title>SwitchHosts!</title>
-</head>
-<body>
-<div id="app"></div>
-<script>require('./build/bundle')</script>
-<!--<script src="./build/bundle.js"></script>-->
-</body>
-</html>

+ 0 - 148
src1/main.js

@@ -1,148 +0,0 @@
-/**
- * SwitchHosts!
- *
- * @author oldj
- * @blog http://oldj.net
- * @homepage https://oldj.github.io/SwitchHosts/
- * @source https://github.com/oldj/SwitchHosts
- */
-
-const electron = require('electron')
-const fs = require('fs')
-// Module to control application life.
-const app = electron.app
-// Module to create native browser window.
-const BrowserWindow = electron.BrowserWindow
-const pref = require('./ui/libs/pref')
-
-let user_language = pref.get('user_language') ||
-  (app.getLocale() || '').split('-')[0].toLowerCase() || 'en'
-global.user_language = user_language
-//const tray = require('./ui/modules/tray')
-const SHServer = require('./server/Server')
-
-// Keep a global reference of the window object, if you don't, the window will
-// be closed automatically when the JavaScript object is garbage collected.
-let mainWindow
-let contents
-let willQuitApp = false
-let is_tray_initialized
-let renderer
-
-function createWindow () {
-  // Create the browser window.
-  mainWindow = new BrowserWindow({
-    width: 800, height: 500,
-    minWidth: 400, minHeight: 250,
-    fullscreenable: true
-  })
-  contents = mainWindow.webContents
-  app.mainWindow = mainWindow
-
-  // and load the index.html of the app.
-  mainWindow.loadURL(`file://${__dirname}/index.html?lang=${user_language}`)
-
-  if (process.env && process.env.ENV === 'dev') {
-    // Open the DevTools.
-    mainWindow.webContents.openDevTools()
-  }
-
-  if (pref.get('hide_at_launch')) {
-    // mainWindow.minimize();
-    mainWindow.hide()
-  }
-
-  mainWindow.on('close', (e) => {
-    if (willQuitApp) {
-      /* the user tried to quit the app */
-      mainWindow = null
-    } else {
-      /* the user only tried to close the window */
-      e.preventDefault()
-      mainWindow.hide()
-    }
-  })
-
-  // Emitted when the window is closed.
-  mainWindow.on('closed', () => {
-    // Dereference the window object, usually you would store windows
-    // in an array if your app supports multi windows, this is the time
-    // when you should delete the corresponding element.
-    mainWindow = null
-    contents = null
-  })
-
-  contents.on('did-finish-load', () => {
-    if (!is_tray_initialized) {
-      //tray.makeTray(app, contents, user_language)
-      is_tray_initialized = true
-    }
-  })
-
-  require('./bg/events').init(app, contents)
-}
-
-const should_quit = app.makeSingleInstance((commandLine, workingDirectory) => {
-  // Someone tried to run a second instance, we should focus our window.
-  if (mainWindow) {
-    if (mainWindow.isMinimized()) {
-      mainWindow.restore()
-    }
-    mainWindow.show()
-    // mainWindow.focus();
-  }
-})
-
-if (should_quit) {
-  app.quit()
-}
-
-// This method will be called when Electron has finished
-// initialization and is ready to create browser windows.
-// Some APIs can only be used after this event occurs.
-app.on('ready', () => {
-  createWindow()
-  require('./ui/modules/mainMenu').init(app, user_language)
-
-  setTimeout(() => {
-    if (renderer) {
-      require('./bg/check_for_update').check(true, renderer)
-    }
-  }, 1000)
-})
-
-electron.ipcMain.on('reg_renderer', (e) => {
-  renderer = e.sender
-})
-
-// Quit when all windows are closed.
-app.on('window-all-closed', function () {
-  // if (process.platform !== 'darwin') {
-  //     app.quit();
-  // }
-})
-
-app.on('show', function () {
-  if (mainWindow) {
-    if (mainWindow.isMinimized()) {
-      mainWindow.restore()
-    }
-    mainWindow.show()
-  } else {
-    createWindow()
-  }
-})
-
-app.on('activate', function () {
-  // On OS X it's common to re-create a window in the app when the
-  // dock icon is clicked and there are no other windows open.
-  if (mainWindow === null) {
-    createWindow()
-  } else if (mainWindow.isMinimized()) {
-    mainWindow.restore()
-  } else {
-    mainWindow.show()
-  }
-})
-
-app.on('before-quit', () => willQuitApp = true)

+ 0 - 33
src1/package.json

@@ -1,33 +0,0 @@
-{
-  "name": "SwitchHosts!",
-  "version": "3.3.0",
-  "description": "Switch hosts quickly!",
-  "main": "main.js",
-  "scripts": {},
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/oldj/SwitchHosts.git"
-  },
-  "keywords": ["SwitchHosts!", "host"],
-  "author": "oldj",
-  "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/oldj/SwitchHosts/issues"
-  },
-  "homepage": "https://oldj.github.io/SwitchHosts/",
-  "dependencies": {
-    "cheerio": "^0.22.0",
-    "classnames": "^2.2.5",
-    "codemirror": "^5.17.0",
-    "moment": "^2.14.1",
-    "node-notifier": "^4.6.1",
-    "react": "^15.3.1",
-    "react-addons-update": "^15.3.1",
-    "react-dom": "^15.3.1",
-    "request": "^2.79.0",
-    "sortablejs": "^1.5.1",
-    "wheel-js": "0.0.2",
-    "yargs": "^6.6.0"
-  },
-  "devDependencies": {}
-}

+ 0 - 61
src1/renderer/Agent.js

@@ -1,61 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-const IS_DEV = process.env.ENV === 'dev'
-//const SH_event = require('./ui/event').event
-//const SH_Agent = require('./ui/agent')
-const {ipcRenderer} = require('electron')
-const notifier = require('node-notifier')
-const platform = process.platform
-
-ipcRenderer.setMaxListeners(20)
-
-const EventEmitter = require('events')
-class MyEmitter extends EventEmitter {}
-const evt = new MyEmitter();
-
-let x_get_idx = 0
-
-/**
- * act
- * @param action {String}
- * @param [data] {Any}
- * @param callback {Function}
- */
-function act (action, data, callback) {
-  let fn = ['_cb', (new Date()).getTime(), (x_get_idx++)].join('_')
-
-  if (!callback && typeof data === 'function') {
-    callback = data
-    data = null
-  }
-
-  if (typeof callback === 'function') {
-    ipcRenderer.once(fn, (e, d) => callback.apply(null, d))
-  }
-
-  ipcRenderer.send('x', {
-    action
-    , data
-    , callback: fn
-  })
-}
-
-function pact (action, data) {
-  return new Promise((resolve, reject) => act(action, data,
-    (err, result) => err ? reject(err) : resolve(result)))
-}
-
-module.exports = {
-  IS_DEV
-  , notifier
-  , platform
-  , act
-  , pact
-  , on: (...args) => evt.on(...args)
-  , emit: (...args) => evt.emit(...args)
-}

+ 0 - 24
src1/server/Server.js

@@ -1,24 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-const {ipcMain} = require('electron')
-const actions = require('./actions')
-
-ipcMain.on('x', (e, d) => {
-  let sender = e.sender
-  let action = d.action
-  if (typeof actions[action] === 'function') {
-    actions[action](...(d.args || []))
-      .then(v => {
-        sender.send(d.callback, [null, v])
-      })
-      .catch(e => {
-        console.log(e)
-        sender.send(d.callback, [e])
-      })
-  }
-})

+ 0 - 8
src1/server/actions.js

@@ -1,8 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-module.exports = require('./actions/index')

+ 0 - 22
src1/server/actions/getHosts.js

@@ -1,22 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- *
- * 读取系统 hosts 以及本地保存的 hosts 数据
- */
-
-'use strict'
-
-const getSysHosts = require('./getSysHosts')
-const getUserHosts = require('./getUserHosts')
-
-module.exports = () => {
-  return Promise
-    .all([getSysHosts(), getUserHosts()])
-    .then(([sys_hosts, user_hosts]) => {
-      return {
-        sys: sys_hosts,
-        list: user_hosts
-      }
-    })
-}

+ 0 - 14
src1/server/actions/getLang.js

@@ -1,14 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-const m_lang = require('../lang')
-
-exports.getLang = (user_lang = 'en') => {
-  let lang = m_lang.getLang(user_lang)
-
-  return Promise.resolve().then(() => lang)
-}

+ 0 - 25
src1/server/actions/getPref.js

@@ -1,25 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-const paths = require('../paths')
-const io = require('../io')
-
-module.exports = () => {
-  let fn = paths.preference_path
-  return io
-    .pReadFile(fn)
-    .then(cnt => {
-      let data
-      try {
-        data = JSON.parse(cnt)
-      } catch (e) {
-        console.log(e)
-        data = {}
-      }
-      return data
-    })
-}

+ 0 - 21
src1/server/actions/getSysHosts.js

@@ -1,21 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-const paths = require('../paths')
-const io = require('../io')
-
-module.exports = () => {
-  let fn = paths.sys_host_path
-  return io
-    .pReadFile(fn)
-    .then(cnt => {
-      return {
-        content: cnt
-        , is_sys: true
-      }
-    })
-}

+ 0 - 30
src1/server/actions/getUserHosts.js

@@ -1,30 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-const paths = require('../paths')
-const io = require('../io')
-
-module.exports = () => {
-  let fn = paths.data_path
-  return io.pReadFile(fn)
-    .then(cnt => {
-      let data
-      try {
-        data = JSON.parse(cnt)
-      } catch (e) {
-        console.log(e)
-        data = {}
-      }
-      return data
-    })
-    .then(data => {
-      if (!Array.isArray(data.list)) {
-        data.list = []
-      }
-      return data
-    })
-}

+ 0 - 16
src1/server/actions/index.js

@@ -1,16 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-const path = require('path')
-
-require('fs').readdirSync(__dirname).map((file) => {
-  /* If its the current file ignore it */
-  if (file === 'index.js') return
-
-  /* Store module with its name (from filename) */
-  module.exports[path.basename(file, '.js')] = require(path.join(__dirname, file))
-})

+ 0 - 11
src1/server/actions/test.js

@@ -1,11 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-module.exports = () => {
-  return Promise.resolve().then(() => 'ttt33')
-}
-

+ 0 - 57
src1/server/io.js

@@ -1,57 +0,0 @@
-/**
- * io
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-const fs = require('fs')
-
-exports.getUserHome = () => {
-  return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME']
-}
-
-let isFile = exports.isFile = (p) => {
-  try {
-    if (fs.statSync(p).isFile()) {
-      return true
-    }
-  } catch (e) {
-  }
-  return false
-}
-
-exports.isDirectory = (p) => {
-  try {
-    if (fs.statSync(p).isDirectory()) {
-      return true
-    }
-  } catch (e) {
-  }
-  return false
-}
-
-let writeFile = exports.writeFile = (fn, data, callback) => {
-  fs.writeFile(fn, data, 'utf-8', callback)
-}
-
-exports.pWriteFile = (fn, data) => {
-  return new Promise((resolve, reject) => {
-    writeFile(fn, data, (e, v) => e ? reject(e) : resolve(v))
-  })
-}
-
-let readFile = exports.readFile = (fn, callback) => {
-  if (!isFile) {
-    callback(null, '')
-  } else {
-    fs.readFile(fn, 'utf-8', callback)
-  }
-}
-
-exports.pReadFile = (fn) => {
-  return new Promise((resolve, reject) => {
-    readFile(fn, (e, v) => e ? reject(e) : resolve(v))
-  })
-}

+ 0 - 43
src1/server/lang.js

@@ -1,43 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-const languages = {
-  'en': require('../common/lang/en').content,
-  'cn': require('../common/lang/cn').content
-}
-
-module.exports = {
-  languages: languages,
-  lang_list: (() => {
-    let list = []
-    for (let k in languages) {
-      if (languages.hasOwnProperty(k)) {
-        list.push({
-          key: k,
-          name: languages[k]._lang_name
-        })
-      }
-    }
-    return list
-  })(),
-  getLang: (lang) => {
-    lang = lang.toLowerCase()
-    if (lang === 'cn' || lang === 'zh-cn') {
-      lang = 'cn'
-    } else {
-      lang = 'en'
-    }
-    return languages[lang] || languages['en']
-  },
-  fill: (tpl, ...vals) => {
-    vals.map((v, idx) => {
-      let r = new RegExp('\\$\\{' + idx + '\\}', 'g')
-      tpl = tpl.replace(r, v)
-    })
-    return tpl
-  }
-}

+ 0 - 42
src1/server/paths.js

@@ -1,42 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-const path = require('path')
-const io = require('./io')
-const platform = process.platform
-
-// Windows 系统有可能不安装在 C 盘
-const sys_host_path = platform === 'win32' ? `${process.env.windir ||
-  'C:\\WINDOWS'}\\system32\\drivers\\etc\\hosts` : '/etc/hosts'
-
-const home_path = io.getUserHome()
-const work_path = path.join(home_path, '.SwitchHosts')
-const data_path = path.join(work_path, 'data.json')
-const preference_path = path.join(work_path, 'preferences.json')
-
-function getCurrentAppPath () {
-  let a = __dirname.split(path.sep)
-  // console.log(a);
-  while (a.length > 0) {
-    let i = a[a.length - 1]
-    if (i.endsWith('.app')) {
-      return a.join(path.sep)
-    }
-    a.pop()
-  }
-
-  return null
-}
-
-module.exports = {
-  home_path: home_path
-  , work_path: work_path
-  , data_path: data_path
-  , preference_path: preference_path
-  , sys_host_path: sys_host_path
-  // ,current_app_path: getCurrentAppPath()
-}

+ 0 - 369
src1/ui/agent.js

@@ -1,369 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- *
- * 和系统、平台相关的方法
- */
-
-'use strict';
-
-const fs = require('fs');
-const path = require('path');
-const request = require('request');
-const moment = require('moment');
-const io = require('./libs/io');
-const platform = process.platform;
-
-const paths = require('./libs/paths');
-const pref = require('./libs/pref');
-const sys_host_path = paths.sys_host_path;
-const work_path = paths.work_path;
-const data_path = paths.data_path;
-const preference_path = paths.preference_path;
-
-const exec = require('child_process').exec;
-const stat = require('./modules/stat');
-stat.init();
-
-const crypto = require('crypto');
-function md5(text) {
-    return crypto.createHash('md5').update(text).digest('hex');
-}
-
-const m_lang = require('./lang');
-let sudo_pswd = '';
-
-function getUserLang() {
-    let user_lang;
-
-    let p_lang = location.search.match(/\blang=(\w+)/);
-
-    user_lang = (p_lang && p_lang[1]) || pref.get('user_language') || navigator.language || navigator.userLanguage || '';
-    user_lang = user_lang.toString().toLowerCase();
-
-    if (user_lang == 'cn' || user_lang == 'zh_cn') {
-        user_lang = 'cn';
-    } else {
-        user_lang = 'en';
-    }
-
-    return user_lang;
-}
-
-let lang_key = getUserLang();
-const lang = m_lang.getLang(lang_key);
-
-
-function getSysHosts() {
-    let cnt = '';
-
-    try {
-        cnt = fs.readFileSync(sys_host_path, 'utf-8');
-    } catch (e) {
-        console.log(e.message);
-    }
-
-    return cnt;
-}
-
-function tryToCreateWorkDir() {
-    if (io.isDirectory((work_path))) {
-        console.log('work dir exists.');
-        return;
-    }
-
-    console.log(`try to create work directory: ${work_path}`);
-    try {
-        fs.mkdirSync(work_path);
-        console.log('work directory created.');
-    } catch (e) {
-        alert('Fail to create work directory!');
-    }
-}
-
-function saveData(content) {
-
-    let txt = JSON.stringify({
-        list: content
-    });
-
-    fs.writeFile(data_path, txt, 'utf-8', (error) => {
-        if (error) {
-            alert(error.message);
-        }
-    });
-}
-
-
-function apply_UNIX(content, success) {
-    let tmp_fn = path.join(work_path, 'tmp.txt');
-    if (content) {
-        fs.writeFileSync(tmp_fn, content, 'utf-8');
-    }
-
-    let cmd;
-    if (!sudo_pswd) {
-        cmd = [
-            `cat "${tmp_fn}" > ${sys_host_path}`
-            , `rm -rf ${tmp_fn}`
-        ].join(' && ');
-    } else {
-        sudo_pswd = sudo_pswd.replace(/'/g, '\\x27');
-        cmd = [
-            `echo '${sudo_pswd}' | sudo -S chmod 777 ${sys_host_path}`
-            , `cat "${tmp_fn}" > ${sys_host_path}`
-            , `echo '${sudo_pswd}' | sudo -S chmod 644 ${sys_host_path}`
-            // , 'rm -rf ' + tmp_fn
-        ].join(' && ');
-    }
-
-    exec(cmd, function (error, stdout, stderr) {
-        // command output is in stdout
-        if (error) {
-            if (!sudo_pswd) {
-                // 尝试让用户输入管理密码
-                SH_event.emit('show_app');
-                SH_event.emit('sudo_prompt', (pswd) => {
-                    sudo_pswd = pswd;
-                    tryToApply(null, success);
-                });
-            } else {
-                alert(stderr);
-            }
-            return;
-        }
-
-        if (!error) {
-            after_apply(success);
-        }
-    });
-}
-
-function _after_apply_unix(callback) {
-    let cmd_fn = path.join(work_path, '_restart_mDNSResponder.sh');
-    let cmd = `
-p1=/System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
-if [ -f $p1 ]; then
-    sudo launchctl unload -w $p1
-    sudo launchctl load -w $p1
-fi
-
-p2=/System/Library/LaunchDaemons/com.apple.discoveryd.plist
-if [ -f p2 ]; then
-    sudo launchctl unload -w $p2
-    sudo launchctl load -w $p2
-fi
-
-sudo killall -HUP mDNSResponder
-`;
-
-    fs.writeFileSync(cmd_fn, cmd, 'utf-8');
-
-    exec(`/bin/sh ${cmd_fn}`, function (error, stdout, stderr) {
-        // command output is in stdout
-        if (error) {
-            console.log(error);
-        }
-        console.log(stdout, stderr);
-
-        callback();
-    });
-}
-
-function after_apply(callback) {
-
-    SH_event.emit('after_apply');
-
-    if (!sudo_pswd) {
-        callback();
-        return;
-    }
-
-    if (platform === 'darwin') {
-        _after_apply_unix(callback);
-        return;
-    }
-
-    callback();
-}
-
-function apply_Win32(content, success) {
-    // todo 判断写入权限
-    try {
-        fs.writeFileSync(sys_host_path, content, 'utf-8');
-    } catch (e) {
-        console.log(e);
-        let msg = e.message;
-        if (platform === 'win32') {
-            msg = `${msg}\n\n${lang.please_run_as_admin}`;
-        }
-        alert(msg);
-        return;
-    }
-    success && success();
-
-    // todo 更新 DNS 缓存
-}
-
-
-function tryToApply(content, success) {
-
-    if (platform !== 'win32') {
-        apply_UNIX(content, success);
-    } else {
-        apply_Win32(content, success);
-    }
-}
-
-
-// init
-tryToCreateWorkDir();
-
-SH_event.on('test', () => {
-    console.log('ttt');
-});
-
-SH_event.on('apply', (content, success) => {
-    tryToApply(content, () => {
-        let cmd = pref.get('after_cmd');
-        if (cmd) {
-            exec(cmd, function (error, stdout, stderr) {
-                // command output is in stdout
-                if (error) {
-                    alert(`AfterCmdError:\n\n${stderr}`);
-                }
-            });
-        }
-
-        success && success();
-    });
-});
-
-SH_event.on('sudo_pswd', (pswd) => {
-    sudo_pswd = pswd;
-});
-
-SH_event.on('show_app', (pswd) => {
-    ipcRenderer.send('show_app');
-});
-
-SH_event.on('save_data', (content) => {
-    saveData(content);
-    ipcRenderer.send('send_host_list', content);
-});
-
-SH_event.on('check_host_refresh', (host, force = false) => {
-    if (host.where !== 'remote' || !host.url || (!force && !host.refresh_interval)) {
-        return;
-    }
-
-    let last_refresh = host.last_refresh;
-    let refresh_interval = parseInt(host.refresh_interval) || 0;
-    if (last_refresh && !force) {
-        last_refresh = new Date(last_refresh);
-        let delta = ((new Date()).getTime() - (last_refresh.getTime() || 0)) / (1000 * 3600);
-        if (delta < refresh_interval) {
-            return;
-        }
-    }
-
-    // refresh
-    // console.log(`getting '${host.url}' ..`);
-    SH_event.emit('loading', host);
-    host.is_loading = true;
-    request(host.url, (err, res, body) => {
-        console.log('got', res && res.statusCode);
-        let out = {};
-        // console.log(err, res && res.statusCode);
-        host.is_loading = false;
-        if (!err && res.statusCode === 200) {
-            // console.log(body);
-            host.content = body;
-            delete host.error;
-            host.last_refresh = moment().format('YYYY-MM-DD HH:mm:ss');
-
-            SH_event.emit('change');
-        } else {
-            console.log(err, res && res.statusCode);
-            // out.content = 'Error: ' + err.message;
-            out.error = 'Error: ' + err.message;
-        }
-        SH_event.emit('loading_done', host, Object.assign({}, host, out));
-    });
-});
-
-/**
- * 如果本地没有 data 文件,认为是第一次运行
- */
-function initGet() {
-    let dd = require('./libs/default_data');
-    let data = dd.make();
-
-    data.sys.content = getSysHosts();
-    data.list.push({
-        title: 'backup',
-        content: data.sys.content
-    });
-
-    return data;
-}
-
-module.exports = {
-    md5: md5,
-    getHosts: function () {
-        let data = null;
-
-        if (!io.isFile(data_path)) {
-            return initGet();
-        }
-
-        try {
-            let cnt = fs.readFileSync(data_path, 'utf-8');
-            data = JSON.parse(cnt);
-        } catch (e) {
-            console.log(e);
-            alert('bad data file.. :(');
-            return initGet();
-        }
-
-        return {
-            sys: {
-                is_sys: true
-                , content: getSysHosts()
-            },
-            list: data.list.map((i) => {
-                return {
-                    title: i.title || ''
-                    , content: i.content || ''
-                    , on: !!i.on
-                    , where: i.where || 'local'
-                    , url: i.url || ''
-                    , last_refresh: i.last_refresh || null
-                    , refresh_interval: i.refresh_interval || 0
-                }
-            })
-        };
-    },
-    getSysHosts: function () {
-        return {
-            is_sys: true
-            , content: getSysHosts()
-        }
-    },
-    readFile: function (fn, callback) {
-        fs.readFile(fn, 'utf-8', callback);
-    },
-    notify: (options) => {
-        notifier.notify(Object.assign({
-            title: 'SwitchHosts!',
-            message: '',
-            icon: path.join(__dirname, 'assets', 'logo_512.png')
-        }, options));
-    },
-    lang: lang,
-    lang_key: lang_key,
-    pref: pref,
-    relaunch() {
-        ipcRenderer.send('relaunch');
-    }
-};

BIN
src1/ui/assets/app.icns


BIN
src1/ui/assets/icon_0.pdf


BIN
src1/ui/assets/icon_1.pdf


BIN
src1/ui/assets/icon_2.pdf


BIN
src1/ui/assets/ilogoTemplate.png


BIN
src1/ui/assets/[email protected]


BIN
src1/ui/assets/[email protected]


BIN
src1/ui/assets/logo.png


BIN
src1/ui/assets/[email protected]


BIN
src1/ui/assets/[email protected]


BIN
src1/ui/assets/[email protected]


BIN
src1/ui/assets/logoTemplate.png


BIN
src1/ui/assets/[email protected]


BIN
src1/ui/assets/[email protected]


BIN
src1/ui/assets/[email protected]


BIN
src1/ui/assets/logo_512.png


+ 0 - 129
src1/ui/components/app.js

@@ -1,129 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-import React from 'react'
-import Panel from './panel/panel'
-import Content from './content/content'
-import SudoPrompt from './frame/sudo'
-import EditPrompt from './frame/edit'
-import PreferencesPrompt from './frame/preferences'
-import util from '../libs/util'
-import './app.less'
-
-class App extends React.Component {
-  constructor (props) {
-    super(props)
-
-    let _data = SH_Agent.getHosts()
-
-    this.state = {
-      hosts: _data,
-      current: _data.sys
-    }
-
-    SH_event.on('after_apply', () => {
-      if (this.state.current.is_sys) {
-        // 重新读取
-        this.setState({
-          current: SH_Agent.getSysHosts()
-        })
-      }
-    })
-
-    ipcRenderer.on('to_import', (e, fn) => {
-      if (!confirm(SH_Agent.lang.confirm_import)) return
-
-      SH_Agent.readFile(fn, (err, cnt) => {
-        if (err) {
-          alert(err.message || 'Import Error!')
-          return
-        }
-        let data
-        try {
-          data = JSON.parse(cnt)
-        } catch (e) {
-          console.log(e)
-          alert(
-            e.message || 'Bad format, the import file should be a JSON file.')
-          return
-        }
-
-        if (!data.list || !Array.isArray(data.list)) {
-          alert('Bad format, the data JSON should have a [list] field.')
-          return
-        }
-
-        data.list.map(item => {
-          if (!item.id) {
-            item.id = util.makeId()
-          }
-        })
-
-        this.setState({
-          hosts: Object.assign({}, this.state.hosts, {list: data.list})
-        }, () => {
-          SH_event.emit('imported')
-        })
-        console.log('imported.')
-      })
-    })
-
-    ipcRenderer.send('reg_renderer')
-  }
-
-  setCurrent (host) {
-    this.setState({
-      current: host.is_sys ? SH_Agent.getSysHosts() : host
-    })
-  }
-
-  static isReadOnly (host) {
-    return host.is_sys || host.where === 'remote'
-  }
-
-  toSave () {
-    clearTimeout(this._t)
-
-    this._t = setTimeout(() => {
-      SH_event.emit('change')
-    }, 1000)
-  }
-
-  setHostContent (v) {
-    if (this.state.current.content === v) return // not changed
-
-    this.state.current.content = v || ''
-    this.toSave()
-  }
-
-  componentDidMount () {
-    window.addEventListener('keydown', (e) => {
-      if (e.keyCode === 27) {
-        SH_event.emit('esc')
-      }
-    }, false)
-  }
-
-  render () {
-    let current = this.state.current
-    return (
-      <div id="app" className={'platform-' + platform}>
-        <Panel hosts={this.state.hosts} current={current}
-               setCurrent={this.setCurrent.bind(this)}/>
-        <Content current={current} readonly={App.isReadOnly(current)}
-                 setHostContent={this.setHostContent.bind(this)}/>
-        <div className="frames">
-          <SudoPrompt/>
-          <EditPrompt hosts={this.state.hosts}/>
-          <PreferencesPrompt/>
-        </div>
-      </div>
-    )
-  }
-}
-
-export default App

+ 0 - 20
src1/ui/components/app.less

@@ -1,20 +0,0 @@
-@import "./cfg.less";
-
-html, body {
-  margin: 0;
-  padding: 0;
-  height: 100%;
-  font-size: 12px;
-  font-family: Arial, Helvetica, sans-serif;
-  color: @font_color;
-  line-height: 20px;
-  background: #fff;
-}
-
-a {
-  text-decoration: none;
-}
-
-#app {
-  height: 100%;
-}

+ 0 - 13
src1/ui/components/cfg.less

@@ -1,13 +0,0 @@
-@font_color: #212121;
-@bd_color: bg_left;
-@bg_prompt: #f5f5f5;
-@color_hover: #09f;
-@color_on: #af9;
-@color_off: font_color_left;
-@color_danger: #f03;
-
-// left
-@bg_left: #373d47;
-@bg_left_search: @bg_left * 1.1;
-@left_width: 240px;
-@font_color_left: #979da7;

+ 0 - 50
src1/ui/components/content/cm_hl.js

@@ -1,50 +0,0 @@
-// custom mode
-
-'use strict';
-
-import CodeMirror from 'codemirror';
-
-export default function () {
-
-    CodeMirror.defineMode('host', function () {
-        function tokenBase(stream) {
-            if (stream.eatSpace()) return null;
-
-            var sol = stream.sol();
-            var ch = stream.next();
-
-            var s = stream.string;
-
-            if (ch === '#') {
-                stream.skipToEnd();
-                return 'comment';
-            }
-            if (!s.match(/^\s*([\d\.]+|[\da-f:\.%lo]+)\s+\w/i)) {
-                return 'error';
-            }
-
-            if (sol && ch.match(/[\w\.:%]/)) {
-                stream.eatWhile(/[\w\.:%]/);
-                return 'ip';
-            }
-
-            return null;
-        }
-
-        function tokenize(stream, state) {
-            return (state.tokens[0] || tokenBase)(stream, state);
-        }
-
-        return {
-            startState: function () {
-                return {tokens: []};
-            },
-            token: function (stream, state) {
-                return tokenize(stream, state);
-            },
-            lineComment: '#'
-        };
-    });
-
-    //CodeMirror.defineMIME('text/x-host', 'host');
-}

+ 0 - 95
src1/ui/components/content/content.js

@@ -1,95 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import Editor from './editor';
-import classnames from 'classnames';
-import './content.less';
-
-export default class Content extends React.Component {
-
-    constructor(props) {
-        super(props);
-
-        this.codemirror = null;
-        this.state = {
-            is_loading: this.props.current.is_loading,
-            code: this.props.current.content || ''
-        };
-        this._t = null;
-
-        SH_event.on('loading', (host) => {
-            if (host === this.props.current) {
-                this.setState({
-                    is_loading: true
-                });
-            }
-        });
-
-        SH_event.on('loading_done', (host, data) => {
-            if (host === this.props.current) {
-                this.setState({
-                    is_loading: false,
-                    code: data.content || ''
-                });
-            }
-        });
-    }
-
-
-    setValue(v) {
-        this.props.setHostsContent(v);
-    }
-
-    componentWillReceiveProps(next_props) {
-        this.setState({
-            is_loading: next_props.current.is_loading,
-            code: next_props.current.content || ''
-        });
-    }
-
-    render() {
-        let {current} = this.props;
-
-        return (
-            <div id="sh-content">
-                <div className="inform">
-                    <span
-                        className={classnames({
-                            loading: 1,
-                            show: this.state.is_loading
-                        })}
-                    >loading...</span>
-                    <i
-                        className={classnames({
-                            show: current.where === 'remote',
-                            iconfont: 1,
-                            'icon-earth': 1
-                        })}
-                        title={SH_Agent.lang.remote_hosts}
-                    />
-                    <i
-                        className={classnames({
-                            show: this.props.readonly,
-                            iconfont: 1,
-                            'icon-lock2': 1
-                        })}
-                        title={SH_Agent.lang.readonly}
-                    />
-                </div>
-                <div className={classnames({
-                    errorMessage: 1,
-                    show: !!this.props.current.error
-                })}>{this.props.current.error}</div>
-                <Editor
-                    code={this.state.code}
-                    readonly={this.props.readonly}
-                    setValue={this.setValue.bind(this)}/>
-            </div>
-        );
-    }
-}

+ 0 - 61
src1/ui/components/content/content.less

@@ -1,61 +0,0 @@
-#sh-content {
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 240px;
-  height: 100%;
-
-  .inform {
-    position: absolute;
-    z-index: 100;
-    top: 5px;
-    right: 10px;
-    opacity: 0.5;
-    background: #fff;
-
-    i {
-      display: none;
-      color: #666;
-      margin-left: 5px;
-
-      &.show {
-        display: inline-block;
-      }
-    }
-
-    span {
-      display: none;
-
-      &.show {
-        display: inline-block;
-      }
-    }
-  }
-
-  .errorMessage {
-    display: none;
-    position: absolute;
-    z-index: 101;
-    top: 0;
-    left: 0;
-    right: 0;
-    padding: 4px 40px;
-    text-align: center;
-    background: rgba(153, 0, 0, 0.5);
-    color: #fff;
-    transition: 0.5s;
-
-    &.show {
-      display: block;
-    }
-  }
-}
-
-.platform-win32 {
-  #sh-content {
-    .inform {
-      right: 20px;
-    }
-  }
-}

+ 0 - 127
src1/ui/components/content/editor.js

@@ -1,127 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import CodeMirror from 'codemirror';
-// import '../../../node_modules/codemirror/addon/comment/comment';
-import 'codemirror/addon/comment/comment';
-import classnames from 'classnames';
-import modeHost from './cm_hl';
-import m_kw from '../../libs/kw';
-import 'codemirror/lib/codemirror.css';
-import './editor.less'
-
-export default class Editor extends React.Component {
-
-    constructor(props) {
-        super(props);
-
-        this.codemirror = null;
-
-        modeHost();
-
-        this.marks = [];
-        this.kw = '';
-
-        SH_event.on('search', (kw) => {
-            this.kw = kw;
-            this.highlightKeyword();
-        });
-    }
-
-    highlightKeyword() {
-        while (this.marks.length > 0) {
-            this.marks.shift().clear();
-        }
-
-        let code = this.props.code;
-        let pos = m_kw.findPositions(this.kw, code) || [];
-        // this.codemirror.markText({line: 6, ch: 16}, {line: 6, ch: 22}, {className: 'cm-hl'});
-
-        pos.map((p) => {
-            this.marks.push(this.codemirror.markText(p[0], p[1], {className: 'cm-hl'}));
-        });
-    }
-
-    setValue(v) {
-        this.props.setValue(v);
-    }
-
-    toComment() {
-        let doc = this.codemirror.getDoc();
-        let cur = doc.getCursor();
-        let line = cur.line;
-        let info = doc.lineInfo(line);
-        this.codemirror.toggleComment({
-            line: line,
-            cur: 0
-        }, {
-            line: line,
-            cur: info.text.length
-        });
-    }
-
-    componentDidMount() {
-        // console.log(this.cnt_node, this.cnt_node.value);
-        this.codemirror = CodeMirror.fromTextArea(this.cnt_node, {
-            lineNumbers: true,
-            readOnly: true,
-            mode: 'host'
-        });
-
-        this.codemirror.setSize('100%', '100%');
-
-        this.codemirror.on('change', (a) => {
-            let v = a.getDoc().getValue();
-            this.setValue(v);
-        });
-
-        this.codemirror.on('gutterClick', (cm, n) => {
-            if (this.props.readonly === true) return;
-
-            let info = cm.lineInfo(n);
-            //cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
-            let ln = info.text;
-            if (/^\s*$/.test(ln)) return;
-
-            let new_ln;
-            if (/^#/.test(ln)) {
-                new_ln = ln.replace(/^#\s*/, '');
-            } else {
-                new_ln = '# ' + ln;
-            }
-            this.codemirror.getDoc().replaceRange(new_ln, {line: info.line, ch: 0}, {line: info.line, ch: ln.length});
-            //app.caculateHosts();
-        });
-
-        ipcRenderer.on('to_comment', () => {
-            this.toComment();
-        });
-    }
-
-    componentWillReceiveProps(next_props) {
-        // console.log(next_props);
-        this.codemirror.getDoc().setValue(next_props.code);
-        this.codemirror.setOption('readOnly', next_props.readonly);
-        setTimeout(() => {
-            this.highlightKeyword();
-        }, 100);
-    }
-
-    render() {
-        return (
-            <div id="sh-editor" className={classnames({
-                readonly: this.props.readonly
-            })}>
-                <textarea
-                    ref={(c) => this.cnt_node = c}
-                    defaultValue={this.props.code || ''}
-                />
-            </div>
-        );
-    }
-}

+ 0 - 33
src1/ui/components/content/editor.less

@@ -1,33 +0,0 @@
-#sh-editor {
-  height: 100%;
-  font-family: Menlo, "Source Code Pro", Monaco, "Courier New", sans-serif;
-
-  // CodeMirror
-  .cm-s-default .cm-comment {
-    color: #090;
-  }
-  .cm-s-default .cm-ip {
-    color: #00a;
-    font-weight: bold;
-  }
-  .cm-s-default .cm-hl {
-    background: #ff0;
-  }
-  .CodeMirror-gutters {
-    border-right: none;
-    padding-right: 6px;
-  }
-
-  .CodeMirror-linenumber {
-    cursor: pointer;
-  }
-
-  &.readonly .CodeMirror {
-    .CodeMirror-linenumber {
-      cursor: default;
-    }
-    .CodeMirror-cursors {
-      display: none;
-    }
-  }
-}

+ 0 - 295
src1/ui/components/frame/edit.js

@@ -1,295 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-import React from 'react'
-import MyFrame from './frame'
-import classnames from 'classnames'
-import Group from './group'
-import util from '../../libs/util'
-import './edit.less'
-
-export default class EditPrompt extends React.Component {
-  constructor (props) {
-    super(props)
-
-    this.state = {
-      show: false,
-      add: true,
-      where: 'local',
-      title: '',
-      url: '',
-      last_refresh: null,
-      refresh_interval: 0,
-      is_loading: false,
-    }
-
-    this.current_host = null
-  }
-
-  tryToFocus () {
-    let el = this.refs.body && this.refs.body.querySelector('input[type=text]')
-    el && el.focus()
-  }
-
-  clear () {
-    this.setState({
-      where: 'local',
-      title: '',
-      url: '',
-      last_refresh: null,
-      refresh_interval: 0,
-    })
-  }
-
-  componentDidMount () {
-    SH_event.on('add_host', () => {
-      this.setState({
-        show: true,
-        add: true,
-      })
-      setTimeout(() => {
-        this.tryToFocus()
-      }, 100)
-    })
-
-    SH_event.on('edit_host', (host) => {
-      this.current_host = host
-      this.setState({
-        show: true,
-        add: false,
-        where: host.where || 'local',
-        title: host.title || '',
-        url: host.url || '',
-        last_refresh: host.last_refresh || null,
-        refresh_interval: host.refresh_interval || 0,
-      })
-      setTimeout(() => {
-        this.tryToFocus()
-      }, 100)
-    })
-
-    SH_event.on('loading_done', (old_host, data) => {
-      if (old_host === this.current_host) {
-        this.setState({
-          last_refresh: data.last_refresh,
-          is_loading: false,
-        })
-        SH_event.emit('host_refreshed', data, this.current_host)
-      }
-    })
-  }
-
-  onOK () {
-    this.setState({
-      title: (this.state.title || '').replace(/^\s+|\s+$/g, ''),
-      url: (this.state.url || '').replace(/^\s+|\s+$/g, ''),
-    })
-
-    if (this.state.title === '') {
-      this.refs.title.focus()
-      return false
-    }
-    if (this.state.where === 'remote' && this.state.url === '') {
-      this.refs.url.focus()
-      return false
-    }
-
-    let data = Object.assign({}, this.current_host, this.state,
-      this.state.add ? {
-        content: `# ${this.state.title}`,
-        on: false,
-      } : {})
-
-    if (!data.id) data.id = util.makeId()
-
-    delete data['add']
-    SH_event.emit('host_' + (this.state.add ? 'add' : 'edit') + 'ed', data,
-      this.current_host)
-
-    this.setState({
-      show: false,
-    })
-    this.clear()
-  }
-
-  onCancel () {
-    this.setState({
-      show: false,
-    })
-    this.clear()
-  }
-
-  confirmDel () {
-    if (!confirm(SH_Agent.lang.confirm_del)) return
-    SH_event.emit('del_host', this.current_host)
-    this.setState({
-      show: false,
-    })
-    this.clear()
-  }
-
-  static getRefreshOptions () {
-    let k = [
-      [0, `${SH_Agent.lang.never}`],
-      [1, `1 ${SH_Agent.lang.hour}`],
-      [24, `24 ${SH_Agent.lang.hours}`],
-      [168, `7 ${SH_Agent.lang.days}`],
-    ]
-    if (IS_DEV) {
-      k.splice(1, 0, [0.002778, `10s (for DEV)`]) // dev test only
-    }
-    return k.map(([v, n], idx) => {
-      return (
-        <option value={v} key={idx}>{n}</option>
-      )
-    })
-  }
-
-  getEditOperations () {
-    if (this.state.add) return null
-
-    return (
-      <div>
-        <div className="ln">
-          <a href="#" className="del"
-             onClick={this.confirmDel.bind(this)}
-          >
-            <i className="iconfont icon-delete"/>
-            <span>{SH_Agent.lang.del_host}</span>
-          </a>
-        </div>
-      </div>
-    )
-  }
-
-  refresh () {
-    if (this.state.is_loading) return
-
-    SH_event.emit('check_host_refresh', this.current_host, true)
-    this.setState({
-      is_loading: true,
-    }, () => {
-      setTimeout(() => {
-        this.setState({
-          is_loading: false,
-        })
-      }, 1000)
-    })
-
-  }
-
-  renderGroup () {
-    if (this.state.where !== 'group') return null
-
-    return <Group hosts={this.props.hosts}/>
-  }
-
-  renderRemoteInputs () {
-    if (this.state.where !== 'remote') return null
-
-    return (
-      <div className="remote-ipts">
-        <div className="ln">
-          <div className="title">{SH_Agent.lang.url}</div>
-          <div className="cnt">
-            <input
-              type="text"
-              ref="url"
-              value={this.state.url}
-              placeholder="http://"
-              onChange={(e) => this.setState({url: e.target.value})}
-              onKeyDown={(e) => (e.keyCode === 13 && this.onOK()) ||
-              (e.keyCode === 27 && this.onCancel())}
-            />
-          </div>
-        </div>
-        <div className="ln">
-          <div className="title">{SH_Agent.lang.auto_refresh}</div>
-          <div className="cnt">
-            <select
-              value={this.state.refresh_interval}
-              onChange={(e) => this.setState(
-                {refresh_interval: parseFloat(e.target.value) || 0})}
-            >
-              {EditPrompt.getRefreshOptions()}
-            </select>
-
-            <i
-              className={classnames({
-                iconfont: 1,
-                'icon-refresh': 1,
-                'invisible': !this.current_host ||
-                this.state.url != this.current_host.url,
-                'loading': this.state.is_loading,
-              })}
-              title={SH_Agent.lang.refresh}
-              onClick={() => this.refresh()}
-            />
-
-            <span className="last-refresh">
-                            {SH_Agent.lang.last_refresh}
-              {this.state.last_refresh || 'N/A'}
-                        </span>
-          </div>
-        </div>
-      </div>
-    )
-  }
-
-  body () {
-    return (
-      <div ref="body">
-        <div className="ln">
-          <input id="ipt-local" type="radio" name="where" value="local"
-                 checked={this.state.where === 'local'}
-                 onChange={(e) => this.setState({where: e.target.value})}
-          />
-          <label htmlFor="ipt-local">{SH_Agent.lang.where_local}</label>
-          <input id="ipt-remote" type="radio" name="where" value="remote"
-                 checked={this.state.where === 'remote'}
-                 onChange={(e) => this.setState({where: e.target.value})}
-          />
-          <label htmlFor="ipt-remote">{SH_Agent.lang.where_remote}</label>
-          <input id="ipt-remote" type="radio" name="where" value="group"
-                 checked={this.state.where === 'group'}
-                 onChange={(e) => this.setState({where: e.target.value})}
-          />
-          <label htmlFor="ipt-remote">{SH_Agent.lang.where_group}</label>
-        </div>
-        <div className="ln">
-          <div className="title">{SH_Agent.lang.host_title}</div>
-          <div className="cnt">
-            <input
-              type="text"
-              ref="title"
-              name="text"
-              value={this.state.title}
-              onChange={(e) => this.setState({title: e.target.value})}
-              onKeyDown={(e) => (e.keyCode === 13 && this.onOK() ||
-              e.keyCode === 27 && this.onCancel())}
-            />
-          </div>
-        </div>
-        {this.renderRemoteInputs()}
-        {this.renderGroup()}
-        {this.getEditOperations()}
-      </div>
-    )
-  }
-
-  render () {
-    return (
-      <MyFrame
-        show={this.state.show}
-        head={SH_Agent.lang[this.state.add ? 'add_host' : 'edit_host']}
-        body={this.body()}
-        onOK={() => this.onOK()}
-        onCancel={() => this.onCancel()}
-      />
-    )
-  }
-}

+ 0 - 55
src1/ui/components/frame/edit.less

@@ -1,55 +0,0 @@
-@keyframes loading {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
-
-.frame {
-  label {
-    padding: 0 4em 0 0.5em;
-  }
-
-  .spiner {
-    transform-origin: right center;
-    animation: spin 1s;
-    animation-iteration-count: 1;
-    -webkit-animation-iteration-count: 1;
-  }
-
-  .ln {
-    i.icon-refresh {
-      display: inline-block;
-      color: #999;
-      margin: 0 0.6em;
-      cursor: pointer;
-
-      &:hover {
-        color: #333;
-      }
-
-      &.loading {
-        animation: loading 1s infinite linear;
-      }
-
-      &.invisible {
-        visibility: hidden;
-      }
-    }
-  }
-
-  .last-refresh {
-    //padding-left: 1em;
-    color: #999;
-  }
-
-  a.del {
-    color: red;
-
-    span {
-      padding-left: 0.5em;
-    }
-  }
-}

+ 0 - 73
src1/ui/components/frame/frame.js

@@ -1,73 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import './frame.less';
-
-export default class MyFrame extends React.Component {
-    constructor(props) {
-        super(props);
-    }
-
-    componentDidMount() {
-        SH_event.on('esc', () => {
-            this.onCancel();
-        });
-    }
-
-    onOK() {
-        this.props.onOK();
-    }
-
-    onCancel() {
-        this.props.onCancel();
-    }
-
-    renderFootButtons() {
-        let html = [];
-
-        html.push(
-            <div
-                className="button btn-cancel"
-                key="btn-cancel"
-                onClick={this.onCancel.bind(this)}
-            >
-                {this.props.cancel_title || SH_Agent.lang.cancel}
-            </div>
-        );
-
-        html.push(
-            <div
-                className="button btn-ok btn-default"
-                key="btn-ok"
-                onClick={this.onOK.bind(this)}
-            >
-                {this.props.ok_title || SH_Agent.lang.ok}
-            </div>
-        );
-
-        return html;
-    }
-
-
-    render() {
-        if (!this.props.show) {
-            return null;
-        }
-
-        return (
-            <div className="frame" ref="frame">
-                <div className="overlay"></div>
-                <div className="prompt">
-                    <div className="head">{this.props.head}</div>
-                    <div className="body">{this.props.body}</div>
-                    <div className="foot">{this.renderFootButtons()}</div>
-                </div>
-            </div>
-        );
-    }
-}

+ 0 - 108
src1/ui/components/frame/frame.less

@@ -1,108 +0,0 @@
-.frame {
-  @bg: #f5f5f5;
-  @btn_default: #05a;
-  @lh: 24px;
-
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-
-  .overlay {
-    position: absolute;
-    z-index: -1;
-    width: 100%;
-    height: 100%;
-    background: #000;
-    opacity: 0.5;
-  }
-
-  .prompt {
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    min-width: 300px;
-    max-width: 600px;
-    background: #fff;
-    box-shadow: 0 0 4px 4px rgba(0, 0, 0, 0.1);
-
-    .head {
-      padding: 20px;
-      font-size: 16px;
-      background: @bg;
-      //border-bottom: solid 1px #ccc;
-    }
-
-    .body {
-      padding: 20px 20px;
-
-      .ln {
-        line-height: 30px;
-        padding: 2px 0;
-
-        .title {
-          float: left;
-          width: 100px;
-          line-height: @lh;
-        }
-        .cnt {
-          margin-left: 100px;
-          line-height: @lh;
-          input[type=text] {
-            width: 240px;
-            outline: none;
-            padding: 6px 10px;
-          }
-          textarea {
-            font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
-          }
-        }
-
-        .inform {
-          color: #999;
-          line-height: @lh;
-        }
-      }
-
-      input {
-        padding: 6px 4px;
-      }
-
-      input[type=password] {
-        letter-spacing: 8px;
-        width: 240px;
-        outline: none;
-        padding: 6px 10px;
-      }
-    }
-
-    .foot {
-      padding: 20px;
-      background: @bg;
-      text-align: right;
-
-      .button {
-        display: inline-block;
-        background: #ccc;
-        padding: 8px 20px;
-        margin-left: 1em;
-        cursor: pointer;
-
-        &:hover {
-          background: #ddd;
-        }
-
-        &.btn-default {
-          background: @btn_default;
-          color: #fff;
-
-          &:hover {
-            background: @btn_default * 1.4;
-          }
-        }
-      }
-    }
-  }
-}

+ 0 - 95
src1/ui/components/frame/group.js

@@ -1,95 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-import React from 'react'
-import classnames from 'classnames'
-import Sortable from 'sortablejs'
-import listToArray from 'wheel-js/src/common/list-to-array'
-import './group.less'
-
-export default class Group extends React.Component {
-  constructor (props) {
-    super(props)
-
-    this.state = {
-      list: this.props.hosts.list
-    }
-
-    this.current_host = null
-  }
-
-  makeItem (item) {
-    let attrs = {
-      'data-id': 'id:' + (item.id || '')
-    }
-    return (
-      <div className="hosts-item" {...attrs}>
-        <i className={classnames({
-          'iconfont': 1
-          , 'item-icon': 1
-          , 'icon-file': item.where !== 'group'
-          , 'icon-files': item.where === 'group'
-        })}
-        />
-        <span>{item.title}</span>
-      </div>
-    )
-  }
-
-  makeList () {
-    let items = this.state.list
-      .filter(item => item.where !== 'group')
-      .map(item => this.makeItem(item))
-
-    return (
-      <div id="hosts-group-valid">
-        <div ref="group_valid" className="hosts-group-list">
-          {items}
-        </div>
-      </div>
-    )
-  }
-
-  currentList () {
-    return (
-      <div id="hosts-group-current">
-        <div ref="group_current" className="hosts-group-list"></div>
-      </div>
-    )
-  }
-
-  getCurrentListFromDOM () {
-    let nodes = this.refs.group_current.getElementsByClassName('hosts-item')
-    nodes = listToArray(nodes)
-    console.log(nodes)
-  }
-
-  componentDidMount () {
-    Sortable.create(this.refs.group_valid, {
-      group: 'sorting'
-      , sort: false
-    })
-
-    Sortable.create(this.refs.group_current, {
-      group: 'sorting'
-      , sort: true
-      , onSort: evt => {
-        this.getCurrentListFromDOM()
-      }
-    })
-  }
-
-  render () {
-    return (
-      <div id="hosts-group">
-        {this.makeList()}
-        <div className="arrow"/>
-        {this.currentList()}
-      </div>
-    )
-  }
-}

+ 0 - 62
src1/ui/components/frame/group.less

@@ -1,62 +0,0 @@
-#hosts-group {
-  @h: 160px;
-
-  position: relative;
-  margin-top: 20px;
-  height: @h + 2px;
-  overflow: hidden;
-
-  &::after {
-    content: '';
-    clear: both;
-  }
-
-  .arrow {
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    width: 20px;
-    height: 20px;
-    line-height: 20px;
-    text-align: center;
-    transform: translate(-50%, -50%);
-
-    &::after {
-      content: '→';
-    }
-  }
-
-  .hosts-group-list {
-    height: @h;
-    overflow: auto;
-    border: solid 1px #ccc;
-
-    .hosts-item {
-      cursor: move;
-      padding: 2px 6px;
-
-      &:hover {
-        background: #f5f5f5;
-      }
-
-      i {
-        font-size: 12px;
-        color: #999;
-      }
-
-      & > span {
-        padding-left: 6px;
-      }
-    }
-  }
-}
-
-#hosts-group-valid {
-  width: 45%;
-  float: left;
-}
-
-#hosts-group-current {
-  width: 45%;
-  float: right;
-}

+ 0 - 239
src1/ui/components/frame/preferences.js

@@ -1,239 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import Frame from './frame';
-import classnames from 'classnames';
-import './preferences.less';
-import lang from '../../lang';
-import util from '../../libs/util';
-const current_version = require('../../../version').version;
-
-const AUTO_LAUNCH = 'auto_launch';
-
-export default class PreferencesPrompt extends React.Component {
-    constructor(props) {
-        super(props);
-
-        let choice_mode = SH_Agent.pref.get('choice_mode');
-        if (!choice_mode || (choice_mode != 'multiple' && choice_mode != 'single')) {
-            choice_mode = 'multiple';
-        }
-
-        this.state = {
-            show: false,
-            lang_key: SH_Agent.lang_key,
-            after_cmd: SH_Agent.pref.get('after_cmd') || '',
-            choice_mode: choice_mode,
-            auto_launch: !!SH_Agent.pref.get(AUTO_LAUNCH),
-            hide_at_launch: !!SH_Agent.pref.get('hide_at_launch'),
-            update_found: false // 发现新版本
-        };
-
-    }
-
-    componentDidMount() {
-        SH_event.on('show_preferences', () => {
-            this.setState({
-                show: true
-            });
-        });
-        ipcRenderer.on('show_preferences', () => {
-            this.setState({
-                show: true
-            });
-        });
-
-        ipcRenderer.on('update_found', (v) => {
-            console.log(v);
-            this.setState({
-                update_found: true
-            });
-        });
-    }
-
-    onOK() {
-        this.setState({
-            show: false
-        }, () => {
-            setTimeout(() => {
-                SH_Agent.relaunch();
-            }, 200);
-        });
-    }
-
-    onCancel() {
-        this.setState({
-            show: false
-        });
-    }
-
-    static getLanguageOptions() {
-        return lang.lang_list.map(({key, name}, idx) => {
-            return (
-                <option value={key} key={idx}>{name}</option>
-            );
-        });
-    }
-
-    updateLangKey(v) {
-        SH_Agent.lang_key = v;
-        SH_Agent.pref.set('user_language', v);
-        this.setState({
-            lange_key: v
-        });
-    }
-
-    updateChoiceMode(v) {
-        SH_Agent.pref.set('choice_mode', v);
-        this.setState({
-            choice_mode: v
-        });
-    }
-
-    updateAfterCmd(v) {
-        SH_Agent.pref.set('after_cmd', v);
-        this.setState({
-            after_cmd: v
-        });
-    }
-
-    updateAutoLaunch(v) {
-        SH_Agent.pref.set(AUTO_LAUNCH, v);
-        this.setState({
-            auto_launch: v
-        });
-
-        // todo set auto launch
-    }
-
-    updateMinimizeAtLaunch(v) {
-        SH_Agent.pref.set('hide_at_launch', v);
-        this.setState({
-            hide_at_launch: v
-        });
-    }
-
-    prefLanguage() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.language}</div>
-                <div className="cnt">
-                    <select
-                        value={SH_Agent.lang_key}
-                        onChange={(e) => this.updateLangKey(e.target.value)}
-                    >
-                        {PreferencesPrompt.getLanguageOptions()}
-                    </select>
-
-                    <div className="inform">{SH_Agent.lang.should_restart_after_change_language}</div>
-                </div>
-            </div>
-        )
-    }
-
-    prefChoiceMode() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.pref_choice_mode}</div>
-                <div className="cnt">
-                    <input type="radio" id="pref-choice-mode-single" name="choice_mode" value="single"
-                           defaultChecked={this.state.choice_mode === 'single'}
-                           onChange={(e) => this.updateChoiceMode(e.target.value)}
-                    />
-                    <label htmlFor="pref-choice-mode-single">{SH_Agent.lang.pref_choice_mode_single}</label>
-                    <input type="radio" id="pref-choice-mode-multiple" name="choice_mode" value="multiple"
-                           defaultChecked={this.state.choice_mode === 'multiple'}
-                           onChange={(e) => this.updateChoiceMode(e.target.value)}
-                    />
-                    <label htmlFor="pref-choice-mode-multiple">{SH_Agent.lang.pref_choice_mode_multiple}</label>
-                </div>
-            </div>
-        )
-    }
-
-    prefAfterCmd() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.pref_after_cmd}</div>
-                <div className="cnt">
-                    <div className="inform">{SH_Agent.lang.pref_after_cmd_info}</div>
-                    <textarea
-                        name=""
-                        defaultValue={this.state.after_cmd}
-                        placeholder={SH_Agent.lang.pref_after_cmd_placeholder}
-                        onChange={(e) => this.updateAfterCmd(e.target.value)}
-                    />
-                </div>
-            </div>
-        )
-    }
-
-    prefAutoLaunch() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.auto_launch}</div>
-                <div className="cnt">
-                    <input type="checkbox" name=""
-                           defaultChecked={this.state.auto_launch}
-                           onChange={(e) => this.updateAutoLaunch(e.target.checked)}
-                    />
-                </div>
-            </div>
-        )
-    }
-
-    prefMinimizeAtLaunch() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.hide_at_launch}</div>
-                <div className="cnt">
-                    <input type="checkbox" name=""
-                           defaultChecked={this.state.hide_at_launch}
-                           onChange={(e) => this.updateMinimizeAtLaunch(e.target.checked)}
-                    />
-                </div>
-            </div>
-        )
-    }
-
-    openDownloadPage() {
-        ipcRenderer.send('open_url', require('../../configs').url_download);
-    }
-
-    body() {
-        return (
-            <div ref="body">
-                {/*<div className="title">{SH_Agent.lang.host_title}</div>*/}
-                {/*<div className="cnt">*/}
-                {/*</div>*/}
-                <div className={classnames("current-version", {"update-found": this.state.update_found})}>
-                    <a href="#" onClick={this.openDownloadPage}>{util.formatVersion(current_version)}</a>
-                </div>
-                {this.prefLanguage()}
-                {this.prefChoiceMode()}
-                {this.prefAfterCmd()}
-                {/*{this.prefAutoLaunch()}*/}
-                {this.prefMinimizeAtLaunch()}
-            </div>
-        )
-    }
-
-    render() {
-        return (
-            <Frame
-                show={this.state.show}
-                head={SH_Agent.lang.preferences}
-                body={this.body()}
-                onOK={() => this.onOK()}
-                onCancel={() => this.onCancel()}
-                cancel_title={SH_Agent.lang.set_and_back}
-                ok_title={SH_Agent.lang.set_and_relaunch_app}
-            />
-        );
-    }
-}

+ 0 - 35
src1/ui/components/frame/preferences.less

@@ -1,35 +0,0 @@
-.frame {
-  textarea {
-    width: 300px;
-    height: 80px;
-    padding: 2px 4px;
-    outline: none;
-    border: solid 1px #ccc;
-  }
-
-  .current-version {
-    float: right;
-    margin-top: -60px;
-    color: #999;
-
-    a {
-      color: #999;
-
-      &:hover {
-        color: #000;
-      }
-    }
-
-    &.update-found {
-      &:after {
-        content: '';
-        display: block;
-        float: right;
-        width: 6px;
-        height: 6px;
-        background: #f00;
-        border-radius: 3px;
-      }
-    }
-  }
-}

+ 0 - 85
src1/ui/components/frame/sudo.js

@@ -1,85 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import Frame from './frame';
-import './sudo.less';
-
-export default class SudoPrompt extends React.Component {
-    constructor(props) {
-        super(props);
-
-        this.onSuccess = null;
-        this.state = {
-            show: false,
-            pswd: ''
-        }
-    }
-
-    componentDidMount() {
-        SH_event.on('sudo_prompt', (success) => {
-            this.setState({show: true});
-            this.onSuccess = success;
-            setTimeout(() => {
-                let el = this.refs.body;
-                el && el.querySelector('input').focus();
-            }, 100);
-        });
-    }
-
-    onOK() {
-        let pswd = this.refs.pswd.value;
-        if (!pswd) return;
-
-        this.setState({
-            show: false,
-            pswd: pswd
-        });
-
-        SH_event.emit('sudo_pswd', pswd);
-        if (typeof this.onSuccess === 'function') {
-            this.onSuccess(pswd);
-        }
-        this.onSuccess = null;
-    }
-
-    onCancel() {
-        this.setState({
-            show: false
-        });
-        this.onSuccess = null;
-    }
-
-    body() {
-        return (
-            <div ref="body">
-                <div className="ln">
-                    <div className="title">{SH_Agent.lang.sudo_pswd}</div>
-                    <div className="cnt">
-                        <input
-                            type="password"
-                            ref="pswd"
-                            onKeyDown={(e)=>(e.keyCode === 13 && this.onOK()||e.keyCode===27 && this.onCancel())}
-                        />
-                    </div>
-                </div>
-            </div>
-        )
-    }
-
-    render() {
-        return (
-            <Frame
-                show={this.state.show}
-                head={SH_Agent.lang.input_sudo_pswd}
-                body={this.body()}
-                onOK={() => this.onOK()}
-                onCancel={() => this.onCancel()}
-            />
-        );
-    }
-}

+ 0 - 7
src1/ui/components/frame/sudo.less

@@ -1,7 +0,0 @@
-@import "frame";
-
-.frame {
-  .prompt {
-    width: 480px;
-  }
-}

+ 0 - 118
src1/ui/components/panel/buttons.js

@@ -1,118 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import classnames from 'classnames';
-import './buttons.less';
-
-export default class Buttons extends React.Component {
-
-    constructor(props) {
-        super(props);
-
-        this.state = {
-            top_toggle_on: true,
-            search_on: false
-        };
-
-        this.on_items = null;
-
-        SH_event.on('toggle_host', (on) => {
-            if (on && !this.state.top_toggle_on) {
-                this.setState({
-                    top_toggle_on: true
-                });
-                this.on_items = null;
-            }
-        });
-
-        SH_event.on('cancel_search', () => {
-            this.calcelSearch();
-        });
-
-        ipcRenderer.on('to_add_host', () => {
-            SH_event.emit('add_host');
-        });
-
-    }
-
-    static btnAdd() {
-        SH_event.emit('add_host');
-    }
-
-    btnToggle() {
-        if (this.state.top_toggle_on) {
-            SH_event.emit('get_on_hosts', (items) => {
-                this.on_items = items;
-            });
-        }
-
-        this.setState({
-            top_toggle_on: !this.state.top_toggle_on
-        }, () => {
-            SH_event.emit('top_toggle', this.state.top_toggle_on, this.on_items);
-            if (this.state.top_toggle_on) {
-                this.on_items = null;
-            }
-        });
-    }
-
-    btnSearch() {
-        this.setState({
-            search_on: !this.state.search_on
-        }, () => {
-            SH_event.emit(this.state.search_on ? 'search_on' : 'search_off');
-        });
-    }
-
-    calcelSearch() {
-        this.setState({
-            search_on: false
-        }, () => {
-            SH_event.emit('search_off');
-        });
-    }
-
-    componentDidMount() {
-        ipcRenderer.on('to_search', () => {
-            this.btnSearch();
-        });
-    }
-
-    render() {
-        return (
-            <div id="sh-buttons">
-                <div className="left">
-                    <a
-                        className="btn-add"
-                        href="#"
-                        onClick={() => Buttons.btnAdd()}
-                    >+</a>
-                </div>
-
-                <div className="right">
-                    <i
-                        className={classnames({
-                            iconfont: 1,
-                            'icon-search': 1,
-                            'on': this.state.search_on
-                        })}
-                        onClick={() => this.btnSearch()}
-                    />
-                    <i
-                        className={classnames({
-                            iconfont: 1,
-                            'icon-switchon': this.state.top_toggle_on,
-                            'icon-switchoff': !this.state.top_toggle_on
-                        })}
-                        onClick={() => this.btnToggle()}
-                    />
-                </div>
-            </div>
-        );
-    }
-}

+ 0 - 53
src1/ui/components/panel/buttons.less

@@ -1,53 +0,0 @@
-@import '../cfg.less';
-
-#sh-buttons {
-  @bg_left: #373d47;
-
-  position: absolute;
-  bottom: 0;
-  width: 240px;
-  height: 30px;
-  line-height: 30px;
-  background: @bg_left;
-
-  .left {
-    float: left;
-    padding-left: 10px;
-
-    .btn-add {
-      display: inline-block;
-      text-align: center;
-      width: 20px;
-      color: @font_color_left;
-      text-decoration: none;
-
-      &:hover {
-        background: rgba(255, 255, 255, 0.1);
-      }
-    }
-  }
-
-  .right {
-    float: right;
-    padding-right: 17px;
-    height: 30px;
-
-    i {
-      display: inline-block;
-      margin-left: 10px;
-      cursor: pointer;
-
-      &.icon-switchoff {
-        position: relative;
-        top: -1px;
-      }
-
-      &.icon-search {
-        padding: 0 8px;
-        &.on {
-          background: @bg_left_search;
-        }
-      }
-    }
-  }
-}

+ 0 - 83
src1/ui/components/panel/iconfont/iconfont.css

@@ -1,83 +0,0 @@
-
-@font-face {font-family: "iconfont";
-  src: url('iconfont.eot?t=1490237956135'); /* IE9*/
-  src: url('iconfont.eot?t=1490237956135#iefix') format('embedded-opentype'), /* IE6-IE8 */
-  url('iconfont.woff?t=1490237956135') format('woff'), /* chrome, firefox */
-  url('iconfont.ttf?t=1490237956135') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
-  url('iconfont.svg?t=1490237956135#iconfont') format('svg'); /* iOS 4.1- */
-}
-
-.iconfont {
-  font-family:"iconfont" !important;
-  font-size:16px;
-  font-style:normal;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-}
-
-.icon-switchoff:before { content: "\e60d"; }
-
-.icon-icon:before { content: "\e600"; }
-
-.icon-warnfill:before { content: "\e607"; }
-
-.icon-warn:before { content: "\e608"; }
-
-.icon-refresh:before { content: "\e616"; }
-
-.icon-ok:before { content: "\e604"; }
-
-.icon-h:before { content: "\e617"; }
-
-.icon-lock:before { content: "\e61d"; }
-
-.icon-off:before { content: "\e613"; }
-
-.icon-on:before { content: "\e614"; }
-
-.icon-search:before { content: "\e61c"; }
-
-.icon-edit:before { content: "\e609"; }
-
-.icon-info:before { content: "\e601"; }
-
-.icon-add-s:before { content: "\e612"; }
-
-.icon-more:before { content: "\e602"; }
-
-.icon-grid:before { content: "\e603"; }
-
-.icon-movedown:before { content: "\e60a"; }
-
-.icon-moveup:before { content: "\e60b"; }
-
-.icon-add:before { content: "\e60c"; }
-
-.icon-folder:before { content: "\e618"; }
-
-.icon-group:before { content: "\e619"; }
-
-.icon-lock2:before { content: "\e61e"; }
-
-.icon-files:before { content: "\e61f"; }
-
-.icon-timescircle:before { content: "\e60e"; }
-
-.icon-earth:before { content: "\e61a"; }
-
-.icon-move:before { content: "\e60f"; }
-
-.icon-delete:before { content: "\e610"; }
-
-.icon-doc:before { content: "\e606"; }
-
-.icon-line:before { content: "\e611"; }
-
-.icon-file-box:before { content: "\e61b"; }
-
-.icon-switchon:before { content: "\e615"; }
-
-.icon-sysserver:before { content: "\e605"; }
-
-.icon-file:before { content: "\e77d"; }
-

BIN
src1/ui/components/panel/iconfont/iconfont.eot


File diff suppressed because it is too large
+ 0 - 102
src1/ui/components/panel/iconfont/iconfont.js


+ 0 - 150
src1/ui/components/panel/iconfont/iconfont.svg

@@ -1,150 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
-<svg xmlns="http://www.w3.org/2000/svg">
-<metadata>
-Created by FontForge 20120731 at Thu Mar 23 10:59:16 2017
- By admin
-</metadata>
-<defs>
-<font id="iconfont" horiz-adv-x="1024" >
-  <font-face 
-    font-family="iconfont"
-    font-weight="500"
-    font-stretch="normal"
-    units-per-em="1024"
-    panose-1="2 0 6 3 0 0 0 0 0 0"
-    ascent="896"
-    descent="-128"
-    x-height="792"
-    bbox="0 -212 1024 896"
-    underline-thickness="0"
-    underline-position="0"
-    unicode-range="U+0078-E77D"
-  />
-<missing-glyph 
- />
-    <glyph glyph-name=".notdef" 
- />
-    <glyph glyph-name=".notdef" 
- />
-    <glyph glyph-name=".null" horiz-adv-x="0" 
- />
-    <glyph glyph-name="nonmarkingreturn" horiz-adv-x="341" 
- />
-    <glyph glyph-name="x" unicode="x" horiz-adv-x="1001" 
-d="M281 543q-27 -1 -53 -1h-83q-18 0 -36.5 -6t-32.5 -18.5t-23 -32t-9 -45.5v-76h912v41q0 16 -0.5 30t-0.5 18q0 13 -5 29t-17 29.5t-31.5 22.5t-49.5 9h-133v-97h-438v97zM955 310v-52q0 -23 0.5 -52t0.5 -58t-10.5 -47.5t-26 -30t-33 -16t-31.5 -4.5q-14 -1 -29.5 -0.5
-t-29.5 0.5h-32l-45 128h-439l-44 -128h-29h-34q-20 0 -45 1q-25 0 -41 9.5t-25.5 23t-13.5 29.5t-4 30v167h911zM163 247q-12 0 -21 -8.5t-9 -21.5t9 -21.5t21 -8.5q13 0 22 8.5t9 21.5t-9 21.5t-22 8.5zM316 123q-8 -26 -14 -48q-5 -19 -10.5 -37t-7.5 -25t-3 -15t1 -14.5
-t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-5 19 -11 39h-368zM336 498v228q0 11 2.5 23t10 21.5t20.5 15.5t34 6h188q31 0 51.5 -14.5t20.5 -52.5v-227h-327z" />
-    <glyph glyph-name="switchoff" unicode="&#xe60d;" 
-d="M832 812h-640q-80 0 -136 -56t-56 -136v-640q0 -79 56 -135.5t136 -56.5h640q79 0 135.5 56.5t56.5 135.5v640q0 80 -56.5 136t-135.5 56zM160 -84q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM160 620q-13 0 -22.5 9.5
-t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM704 -20q0 -27 -18.5 -45.5t-45.5 -18.5h-256q-27 0 -45.5 18.5t-18.5 45.5v640q0 26 19 45t45 19h256q27 0 45.5 -18.5t18.5 -45.5v-640zM864 -84q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5
-t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM864 620q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM576 300h-128q-26 0 -45 -19t-19 -45v-192q0 -27 18.5 -45.5t45.5 -18.5h128q27 0 45.5 18.5t18.5 45.5v192
-q0 27 -18.5 45.5t-45.5 18.5z" />
-    <glyph glyph-name="icon" unicode="&#xe600;" 
-d="M488 745l132 -269l297 -43l-215 -209l51 -296l-265 140l-266 -140l51 296l-215 209l297 43z" />
-    <glyph glyph-name="warnfill" unicode="&#xe607;" 
-d="M943 127l-341 609q-35 63 -90.5 63t-90.5 -63l-340 -609q-34 -62 -6 -111q29 -48 100 -48h674q71 0 99.5 48.5t-5.5 110.5zM480 576q0 13 9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5v-288q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5v288zM512 64q-20 0 -34 14t-14 34
-t14 34t34 14t34 -14t14 -34t-14 -34t-34 -14z" />
-    <glyph glyph-name="warn" unicode="&#xe608;" 
-d="M849 -33h-674q-71 0 -99.5 49t5.5 111l340 609q35 63 90.5 63t90.5 -63l341 -609q34 -63 5.5 -111.5t-99.5 -48.5zM512 735q-18 0 -35 -30l-340 -610q-17 -30 -7 -47t45 -17h674q35 0 45 17t-7 47l-341 610q-16 30 -34 30zM512 256q-13 0 -22.5 9.5t-9.5 22.5v288
-q0 13 9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5v-288q0 -13 -9.5 -22.5t-22.5 -9.5zM512 144zM464 144q0 20 14 34t34 14t34 -14t14 -34t-14 -34t-34 -14t-34 14t-14 34z" />
-    <glyph glyph-name="refresh" unicode="&#xe616;" 
-d="M504 17q-97 0 -179.5 48t-130.5 130.5t-48 179.5q0 110 62 201l93 -93v245h-246l92 -92q-85 -116 -85 -261q0 -90 35 -171.5t94.5 -141t141 -94.5t171.5 -35q85 0 163 31l-50 71q-55 -18 -113 -18v0zM720 277v-246h246l-96 96q76 112 76 248q0 90 -35 172t-94 141
-t-141 94t-172 35q-70 0 -136 -21l52 -73q41 10 84 10q98 0 180.5 -47.5t130 -130t47.5 -180.5q0 -101 -52 -187z" />
-    <glyph glyph-name="ok" unicode="&#xe604;" 
-d="M512 709q-111 0 -205.5 -54.5t-149 -149t-54.5 -205.5t54.5 -205.5t149 -149t205.5 -54.5t205.5 54.5t149 149t54.5 205.5t-54.5 205.5t-149 149t-205.5 54.5zM376 253q0 -1 5 -6l9 -9t10 -7.5t10 -3.5q16 0 109 104l138 158q7 8 15 9q13 0 21 -7l45 -44q7 -8 7.5 -18.5
-t-6.5 -18.5l-250 -264v0l-53 -57q-7 -7 -18 -7.5t-18 6.5l-151 142q-8 7 -8.5 18t7.5 19l35 37q7 8 18 8.5t19 -7.5z" />
-    <glyph glyph-name="h" unicode="&#xe617;" 
-d="M512 802q-104 0 -192.5 -51.5t-140 -140t-51.5 -193t51.5 -193t140 -140t192.5 -51.5t192.5 51.5t140 140t51.5 193t-51.5 193t-140 140t-192.5 51.5zM660 214h-50v175h-196v-175h-50v395h50v-179h196v179h50v-395z" />
-    <glyph glyph-name="lock" unicode="&#xe61d;" 
-d="M427 151q0 35 25 60t60 25t60 -25t25 -60q0 -47 -39 -72q9 -50 18 -110q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5l18 110q-39 25 -39 72zM341 385v150q0 70 50 120t121 50t121 -50t50 -120v-150h-342zM235 535v-150h-64q-36 0 -61 -25t-25 -60v-427
-q0 -35 25 -60t61 -25h682q36 0 61 25t25 60v427q0 35 -25 60t-61 25h-64v150q0 115 -81 196t-196 81t-196 -81t-81 -196v0z" />
-    <glyph glyph-name="off" unicode="&#xe613;" 
-d="M729 90h-434q-116 0 -197.5 81.5t-81.5 196.5v32q0 115 81.5 196.5t197.5 81.5h434q116 0 197.5 -81.5t81.5 -196.5v-32q0 -115 -81.5 -196.5t-197.5 -81.5zM946 400q0 90 -63.5 153t-153.5 63h-434q-90 0 -153.5 -63t-63.5 -153v-32q0 -90 63.5 -153.5t153.5 -63.5h434
-q90 0 153.5 63.5t63.5 153.5v32zM322 223q-68 0 -116 48.5t-48 116.5t48 116t116 48t116 -48t48 -116t-48 -116.5t-116 -48.5z" />
-    <glyph glyph-name="on" unicode="&#xe614;" 
-d="M729 90h-434q-116 0 -197.5 81.5t-81.5 196.5v32q0 115 81.5 196.5t197.5 81.5h434q116 0 197.5 -81.5t81.5 -196.5v-32q0 -115 -81.5 -196.5t-197.5 -81.5zM947 399q0 90 -63.5 153.5t-153.5 63.5h-436q-89 0 -152.5 -63.5t-63.5 -153.5v-31q0 -90 63.5 -153.5
-t152.5 -63.5h436q90 0 153.5 63.5t63.5 153.5v31v0zM702 223q-68 0 -116 48.5t-48 116.5t48 116t116 48t116.5 -48t48.5 -116t-48.5 -116.5t-116.5 -48.5z" />
-    <glyph glyph-name="search" unicode="&#xe61c;" 
-d="M995 3l-272 227q-2 2 -6 4q37 79 37 160q0 82 -34.5 158t-99.5 131q-105 89 -243 89q-82 0 -158 -35t-131 -100q-88 -105 -88 -243q0 -82 34.5 -158.5t100.5 -131.5q105 -88 241 -88h1q121 0 221 72q1 0 2 -1.5l1 -1.5l272 -227q27 -23 63 -18.5t59 33.5l6 7
-q24 28 22 64.5t-28 58.5zM585 219q-40 -47 -94.5 -72t-113.5 -25q-98 1 -174 64q-47 39 -72 94t-25 114q0 99 64 174q39 48 93.5 72.5t113.5 24.5q99 0 174 -63q47 -40 72 -94.5t25 -113.5q0 -99 -63 -175z" />
-    <glyph glyph-name="edit" unicode="&#xe609;" 
-d="M384 3l-169 169q-6 5 -6 13.5t6 14.5l380 380q6 6 14 6t14 -6l169 -169q6 -6 6 -14t-6 -14l-380 -380q-6 -6 -14.5 -6t-13.5 6zM693 678q18 18 42.5 18t42.5 -18l112 -112q18 -18 18 -42.5t-18 -42.5l-56 -56l-197 197zM116 -96l56 254l198 -198z" />
-    <glyph glyph-name="info" unicode="&#xe601;" 
-d="M512 -20q-110 0 -203 54t-147 147t-54 203t54 203t147 147t203 54t203 -54t147 -147t54 -203t-54 -203t-147 -147t-203 -54zM567 605q0 7 -5.5 12.5t-12.5 5.5h-74q-7 0 -12.5 -5.5t-5.5 -12.5v-74q0 -8 5.5 -13t12.5 -5h74q7 0 12.5 5t5.5 13v74zM567 402q0 8 -5.5 13.5
-t-12.5 5.5h-74q-7 0 -12.5 -5.5t-5.5 -13.5v-239q0 -7 5.5 -12.5t12.5 -5.5h74q7 0 12.5 5.5t5.5 12.5v239z" />
-    <glyph glyph-name="add-s" unicode="&#xe612;" 
-d="M699 358h-157v-158q0 -10 -7.5 -18t-18.5 -8t-19 8t-8 18v158h-157q-11 0 -18.5 7.5t-7.5 18.5t7.5 18.5t18.5 7.5h157v157q0 11 8 18.5t19 7.5t18.5 -7.5t7.5 -18.5v-157h157q11 0 18.5 -7.5t7.5 -18.5t-7.5 -18.5t-18.5 -7.5v0z" />
-    <glyph glyph-name="more" unicode="&#xe602;" 
-d="M174.5 501q-41.5 0 -71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71.5 29.5t30 71.5t-30 71.5t-71.5 29.5zM511 501q-42 0 -71.5 -29.5t-29.5 -71.5t29.5 -71.5t71.5 -29.5t71.5 29.5t29.5 71.5t-29.5 71.5t-71.5 29.5zM848 501q-42 0 -71.5 -29.5t-29.5 -71.5t29.5 -71.5
-t71.5 -29.5t71.5 29.5t29.5 71.5t-29.5 71.5t-71.5 29.5z" />
-    <glyph glyph-name="grid" unicode="&#xe603;" 
-d="M601 830h-179q-12 0 -21 -9t-9 -21v-179q0 -12 9 -21t21 -9h179q12 0 21 9t9 21v179q0 12 -9 21t-21 9zM929 830h-179q-12 0 -21 -9t-9 -21v-179q0 -12 9 -21t21 -9h179q12 0 21 9t9 21v179q0 12 -9 21t-21 9zM273 830h-179q-12 0 -21 -9t-9 -21v-179q0 -12 9 -21t21 -9
-h179q12 0 21 9t9 21v179q0 12 -9 21t-21 9zM601 502h-179q-12 0 -21 -9t-9 -21v-179q0 -13 9 -21.5t21 -8.5h179q12 0 21 8.5t9 21.5v179q0 12 -9 21t-21 9zM929 502h-179q-12 0 -21 -9t-9 -21v-179q0 -13 9 -21.5t21 -8.5h179q12 0 21 8.5t9 21.5v179q0 12 -9 21t-21 9z
-M273 502h-179q-12 0 -21 -9t-9 -21v-179q0 -13 9 -21.5t21 -8.5h179q12 0 21 8.5t9 21.5v179q0 12 -9 21t-21 9zM601 174h-179q-12 0 -21 -9t-9 -21v-179q0 -13 9 -21.5t21 -8.5h179q12 0 21 8.5t9 21.5v179q0 12 -9 21t-21 9zM929 174h-179q-12 0 -21 -9t-9 -21v-179
-q0 -13 9 -21.5t21 -8.5h179q12 0 21 8.5t9 21.5v179q0 12 -9 21t-21 9zM273 174h-179q-12 0 -21 -9t-9 -21v-179q0 -13 9 -21.5t21 -8.5h179q12 0 21 8.5t9 21.5v179q0 12 -9 21t-21 9z" />
-    <glyph glyph-name="movedown" unicode="&#xe60a;" 
-d="M768 108v384h-64v-384h-160l192 -192l192 192h-160zM320 556v-192h-192v192h192zM384 620h-320v-320h320v320zM64 172h96v-64h-96v64zM192 172h96v-64h-96v64zM320 172h64v-96h-64v96zM64 -52h64v-96h-64v96zM160 -84h96v-64h-96v64zM288 -84h96v-64h-96v64zM64 76h64
-v-96h-64v96zM320 44h64v-96h-64v96z" />
-    <glyph glyph-name="moveup" unicode="&#xe60b;" 
-d="M704 300v-384h64v384h160l-192 192l-192 -192h160zM64 620h96v-64h-96v64zM192 620h96v-64h-96v64zM320 620h64v-96h-64v96zM64 396h64v-96h-64v96zM160 364h96v-64h-96v64zM288 364h96v-64h-96v64zM64 524h64v-96h-64v96zM320 492h64v-96h-64v96zM320 108v-192h-192v192
-h192zM384 172h-320v-320h320v320z" />
-    <glyph glyph-name="add" unicode="&#xe60c;" 
-d="M512 -41q-115 0 -213 57t-155 155t-57 213t57 213t155 155t213 57t213 -57t155 -155t57 -213t-57 -213t-155 -155t-213 -57zM724 426h-170v170h-84v-170h-170v-84h170v-170h84v170h170v84z" />
-    <glyph glyph-name="folder" unicode="&#xe618;" 
-d="M961 640q0 40 -28.5 68t-67.5 28h-186h-1h-1q-6 -1 -10 -2l-1 -1h-1q-5 -3 -8 -6q-18 -17 -35 -88q-3 -12 -4 -14q-4 -17 -27 -17h-7.5h-7.5h-416q-40 0 -68 -28.5t-28 -69.5l32 -414q0 -40 28 -68t68 -28h640q40 0 68 28t28 66zM864 96q0 -13 -9.5 -22.5t-22.5 -9.5
-h-640q-13 0 -22.5 10t-9.5 24l-32 414q0 13 9.5 22.5t22.5 9.5h416h7.5h7.5q35 0 58.5 17t30.5 48q2 4 4 15q8 34 13 48h168q13 0 22.5 -9.5t9.5 -22.5v-2v-1zM128 672h416q13 0 22.5 9.5t9.5 22.5t-9.5 22.5t-22.5 9.5h-416q-13 0 -22.5 -9.5t-9.5 -22.5t9.5 -22.5
-t22.5 -9.5z" />
-    <glyph glyph-name="group" unicode="&#xe619;" 
-d="M521 194l-376 247l-50 -52l426 -291l426 291l-51 53zM947 550l-426 291l-426 -291l426 -291zM521 756l302 -206l-302 -207l-302 207zM521 33l-376 248l-50 -52l426 -291l426 291l-51 53z" />
-    <glyph glyph-name="lock2" unicode="&#xe61e;" 
-d="M769 448v135v0q-3 104 -77.5 176.5t-178.5 72.5t-178.5 -72.5t-77.5 -175.5v0v-136h-1q-27 0 -45.5 -18.5t-18.5 -45.5v-384q0 -27 18.5 -45.5t45.5 -18.5h512q27 0 45.5 18.5t18.5 45.5v384q0 26 -18.5 45t-44.5 19zM321 581v0q2 78 58 132.5t134 54.5t134 -54.5
-t58 -132.5v0v-133h-384v133zM768 32q0 -13 -9.5 -22.5t-22.5 -9.5h-448q-13 0 -22.5 9.5t-9.5 22.5v320q0 13 9.5 22.5t22.5 9.5h448q13 0 22.5 -9.5t9.5 -22.5v-320zM544 206v52q0 13 -9.5 22.5t-22.5 9.5t-22.5 -9.5t-9.5 -22.5v-52q-28 -18 -28 -51q0 -25 17.5 -42.5
-t42.5 -17.5t42.5 17.5t17.5 42.5q0 33 -28 51z" />
-    <glyph glyph-name="files" unicode="&#xe61f;" 
-d="M744 434h-260q-12 0 -20.5 -8.5t-8.5 -20.5t8.5 -20.5t20.5 -8.5h260q12 0 20.5 8.5t8.5 20.5t-8.5 20.5t-20.5 8.5zM744 290h-260q-12 0 -20.5 -8.5t-8.5 -20.5t8.5 -20.5t20.5 -8.5h260q12 0 20.5 8.5t8.5 20.5t-8.5 20.5t-20.5 8.5zM744 839h-347q-45 0 -80 -35.5
-t-35 -80.5h-34q-45 0 -78 -35t-33 -80v-578q0 -45 35 -80.5t81 -35.5h433q46 0 81 35.5t35 80.5h29q46 0 81 35.5t35 79.5v405v57zM686 -28h-433q-23 0 -40.5 18t-17.5 40v578q0 22 16.5 39.5t38.5 17.5l32 1v-521q0 -44 35 -79.5t80 -35.5h347q0 -22 -17.5 -40t-40.5 -18v0
-zM889 145q0 -22 -17.5 -39.5t-40.5 -17.5h-434q-22 0 -39.5 17.5t-17.5 39.5v578q0 23 17.5 40.5t39.5 17.5h289v-116q0 -45 35 -80t81 -35h87v-405zM802 608q-21 0 -39.5 30.5t-18.5 55.5v86v0l145 -172h-87z" />
-    <glyph glyph-name="timescircle" unicode="&#xe60e;" 
-d="M657 171q0 15 -11 26l-104 103l104 103q11 11 11 26q0 16 -11 26l-52 52q-11 11 -26 11t-26 -11l-103 -104l-104 104q-10 11 -25 11q-16 0 -27 -11l-51 -52q-11 -10 -11 -26q0 -15 11 -26l103 -103l-103 -103q-11 -11 -11 -26q0 -16 11 -26l51 -52q11 -11 27 -11
-q15 0 25 11l104 104l103 -104q11 -11 26 -11t26 11l52 52q11 10 11 26zM878 300q0 -119 -59 -220t-160 -160t-220.5 -59t-220 59t-159.5 160t-59 220t59 220t159.5 160t220 59t220.5 -59t160 -160t59 -220z" />
-    <glyph glyph-name="earth" unicode="&#xe61a;" 
-d="M874 662q-73 73 -166 111.5t-196 38.5t-196 -38.5t-166 -111.5t-111.5 -166t-38.5 -196t38.5 -196t111.5 -166t166 -111.5t196 -38.5t196 38.5t166 111.5t111.5 166t38.5 196t-38.5 196t-111.5 166zM942 466q-7 12 -22 19.5t-46 18.5q-16 5 -28.5 20t-18.5 28.5t-15 41.5
-q-8 24 -13.5 37t-17 31t-25.5 29q130 -82 186 -225zM798 290q2 -19 2.5 -35.5t-8.5 -38.5t-29 -45q-12 -13 -26 -50q-8 -22 -13.5 -33.5t-16.5 -26t-28 -21t-41 -6.5q-7 8 -12 37q-4 24 -10 90q-8 111 -21 160q-25 92 -84 112q-26 9 -55 9q-14 0 -39 -3q-17 -2 -24 -2v0
-q-8 0 -13 1.5t-13 10.5t-16 26q-11 30 -10 63.5t20.5 69t53.5 57.5q55 37 89 37q27 0 69 -23q39 -20 81 -20q8 0 22 1h16q18 0 31 -9t21.5 -26t19.5 -48q8 -24 13.5 -37.5t16.5 -33t27 -32t37 -19.5q22 -8 31 -11q-9 -9 -36 -34q-21 -18 -30 -27q-21 -19 -25.5 -46t0.5 -47
-v0zM51 304q8 -1 18 -3q34 -8 48 -15q-3 -6 -12 -18q-28 -41 -22 -65q5 -22 -6 -56q-26 74 -26 153v2v2v0zM512 -161q-129 0 -238 66.5t-168 176.5q40 76 27 132q0 5 14 24q6 8 9 12.5t7 13t5.5 14.5t1 14.5t-4.5 15.5q-12 26 -80 41q-13 3 -31 6q14 113 78 206t164 146.5
-t216 53.5q119 0 223 -58q-19 8 -43 8h-19q-13 -1 -19 -1q-29 0 -57 15q-53 28 -93 28q-49 0 -117 -45q-64 -42 -88 -117q-23 -73 5 -136q30 -69 89 -69v0q10 0 30 2q22 3 33 3q20 0 38 -6q34 -11 51 -77q12 -44 20 -151q6 -80 13 -110q6 -26 17 -41q16 -24 41 -24
-q68 0 108 44q21 24 41 77q11 28 16 34q27 30 39.5 61.5t11 53.5t-2.5 44q-3 21 -1.5 31.5t9.5 18.5q13 11 30 26q32 29 41 39q22 24 18 44v1q27 -75 27 -156q0 -94 -36.5 -179t-98.5 -147t-147.5 -98.5t-178.5 -36.5v0z" />
-    <glyph glyph-name="move" unicode="&#xe60f;" 
-d="M1008 330l-156 155q-14 14 -33.5 14t-33 -13.5t-13.5 -33t14 -33.5l76 -76h-303v309l76 -75q14 -14 33.5 -14t33 13.5t13.5 33t-14 33.5l-155 155q-14 14 -33.5 14t-32.5 -14l-156 -155q-14 -14 -14 -33.5t13.5 -33t33 -13.5t33.5 13l76 76v-309h-304l76 76
-q14 14 14 33.5t-13.5 33t-33 13.5t-33.5 -14l-156 -155q-13 -14 -13 -33.5t13 -32.5l156 -156q14 -14 33.5 -14t33 14t13.5 33t-14 33l-76 76h304v-303l-76 76q-14 14 -33.5 14t-33 -13.5t-13.5 -33t14 -33.5l155 -155q14 -14 33.5 -14t33.5 14l155 155q14 14 14 33.5
-t-13.5 33t-33 13.5t-33.5 -14l-76 -75v302h303l-76 -76q-14 -14 -14 -33t13.5 -33t33 -14t33.5 14l156 156q13 13 13 32.5t-13 33.5z" />
-    <glyph glyph-name="delete" unicode="&#xe610;" 
-d="M924 573h-154v105q0 29 -20.5 49.5t-49.5 20.5h-376q-29 0 -49.5 -20.5t-20.5 -49.5v-105h-155q-14 0 -24 -10t-10 -24.5t10 -24.5t24 -10h79v-581q0 -29 20.5 -49.5t49.5 -20.5h528q29 0 49.5 20.5t20.5 49.5v558v0v23h78q15 0 25 10t10 24.5t-10 24.5t-25 10z
-M412.5 -10q-14.5 0 -24.5 10t-10 25l-1 372q0 15 10.5 25t25 10t24.5 -10t10 -25v-372q0 -15 -10 -25t-24.5 -10zM611.5 -10q-14.5 0 -24.5 10t-10 25v372q0 15 10 25t24.5 10t24.5 -10t10 -25l1 -372q0 -15 -10.5 -25t-25 -10zM323 635q0 17 13 30t31 13h290q18 0 31 -13
-t13 -30v-62h-378v62z" />
-    <glyph glyph-name="doc" unicode="&#xe606;" horiz-adv-x="1281" 
-d="M1280 422zM492 -7q2 -1 3.5 -2t5.5 -5.5t5.5 -9.5t-1.5 -11.5t-12 -13.5h-151q-4 0 -10.5 1.5t-24.5 9.5t-32 20.5t-26.5 38t-15.5 58.5v397v0q0 4 1 12t7.5 28.5t17 37t32 32t49.5 19.5h341q4 0 10.5 -1.5t24 -10.5t31.5 -22t26.5 -40t14.5 -62v-102v-160t0 -75
-q-1 -4 -2.5 -11.5t-11.5 -29.5t-24.5 -43t-43 -48t-65.5 -49h-2h-5h-7h-8.5h-7.5h-5h-2q-15 4 -15.5 24.5t0.5 86.5v0q0 3 1 8t6 18.5t12.5 24.5t23.5 21.5t36 14.5h81v326q0 3 -1 8.5t-5.5 20t-11.5 25.5t-21 21.5t-32 12.5h-332q-3 0 -7.5 -1t-16.5 -6t-21 -13.5
-t-17.5 -27.5t-10.5 -44q-1 -203 -1 -386q1 -3 1.5 -9t5 -21t11.5 -26.5t21.5 -22.5t34.5 -13h146zM736 106h-70q-4 -1 -9.5 -3.5t-16.5 -15.5t-12 -30v-16v-31.5v-15.5l8 -1q5 0 34 29q37 37 66 84zM651 430q0 -10 -7.5 -17.5t-17.5 -7.5h-221q-10 0 -17.5 7.5t-7.5 17.5v0
-q0 11 7.5 18.5t17.5 7.5h221q10 0 17.5 -7.5t7.5 -18.5v0zM652 282q0 -11 -7.5 -18.5t-18.5 -7.5h-220q-11 0 -18.5 7.5t-7.5 18.5v0q0 11 7.5 18.5t18.5 7.5h220q11 0 18.5 -7.5t7.5 -18.5v0zM524 133q0 -11 -7.5 -19t-18.5 -8h-91q-11 0 -19 8t-8 19v0q0 11 8 19t19 8h91
-q11 0 18.5 -8t7.5 -19v0z" />
-    <glyph glyph-name="line" unicode="&#xe611;" 
-d="M960 552q0 -17 -12 -29.5t-30 -12.5h-812q-18 0 -30 12.5t-12 29.5v0q0 18 12 30t30 12h812q18 0 30 -12t12 -30v0zM960 300q0 -17 -12 -29.5t-30 -12.5h-812q-18 0 -30 12.5t-12 29.5v0q0 17 12 29.5t30 12.5h812q18 0 30 -12.5t12 -29.5v0zM960 48q0 -18 -12 -30
-t-30 -12h-812q-18 0 -30 12t-12 30v0q0 17 12 29.5t30 12.5h812q18 0 30 -12.5t12 -29.5v0z" />
-    <glyph glyph-name="file-box" unicode="&#xe61b;" 
-d="M804 770l50 -431l-57 -7l-45 386h-480l-45 -386l-57 7l50 431h584zM319 674h386v-48h-386v48zM319 577h386v-48h-386v48zM319 481h386v-49h-386v49zM319 384h386v-48h-386v48zM874 287h-724q-10 0 -15 -6.5t-2 -15.5l82 -244q3 -10 12 -16.5t19 -6.5h532q10 0 19 6.5
-t12 16.5l82 244q3 9 -2 15.5t-15 6.5zM609 191h-194v48h194v-48z" />
-    <glyph glyph-name="switchon" unicode="&#xe615;" 
-d="M832 896h-640q-80 0 -136 -56t-56 -136v-640q0 -79 56 -135.5t136 -56.5h640q79 0 135.5 56.5t56.5 135.5v640q0 80 -56.5 136t-135.5 56zM160 0q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM160 704q-13 0 -22.5 9.5
-t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM704 64q0 -27 -18.5 -45.5t-45.5 -18.5h-256q-27 0 -45.5 18.5t-18.5 45.5v640q0 26 19 45t45 19h256q27 0 45.5 -18.5t18.5 -45.5v-640zM864 0q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5
-t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM864 704q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM576 704h-128q-26 0 -45 -19t-19 -45v-192q0 -26 19 -45t45 -19h128q27 0 45.5 18.5t18.5 45.5v192q0 27 -18.5 45.5
-t-45.5 18.5z" />
-    <glyph glyph-name="sysserver" unicode="&#xe605;" 
-d="M515 145q-36 0 -71 -12t-64 -41t-36 -69h338q-5 53 -57 87.5t-110 34.5zM955 157q-3 265 0 528q0 34 -12.5 47t-46.5 13q-45 -1 -384 -1v0q-339 0 -390 1q-28 0 -40.5 -11t-12.5 -39q1 -231 0 -544q0 -28 11.5 -40.5t39.5 -11.5q35 1 107 0.5t107 0.5q25 1 48 17
-q56 40 115.5 45t116.5 -28q63 -37 150 -35q94 2 132 0q33 -2 46 11t13 47zM892 213h-760v456h760v-456z" />
-    <glyph glyph-name="file" unicode="&#xe77d;" 
-d="M645 809h-372q-44 0 -75 -31t-31 -75v-638q0 -44 31 -75t75 -31h478q44 0 75 31t31 75v532zM643 726l127 -127h-104q-9 0 -16 6.5t-7 16.5v104zM751 19h-478q-19 0 -32.5 13.5t-13.5 32.5v638q0 19 13.5 32.5t32.5 13.5h310v-127q0 -34 24.5 -58.5t58.5 -24.5h131v-474
-q0 -19 -13.5 -32.5t-32.5 -13.5zM682 388h-340q-12 0 -21 -9t-9 -21.5t9 -21t21 -8.5h340q12 0 21 8.5t9 21t-9 21.5t-21 9zM682 232h-340q-12 0 -21 -9t-9 -21.5t9 -21t21 -8.5h340q12 0 21 8.5t9 21t-9 21.5t-21 9z" />
-  </font>
-</defs></svg>

BIN
src1/ui/components/panel/iconfont/iconfont.ttf


BIN
src1/ui/components/panel/iconfont/iconfont.woff


+ 0 - 316
src1/ui/components/panel/list.js

@@ -1,316 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import ListItem from './list_item';
-import update from 'react-addons-update';
-import './list.less';
-
-
-class List extends React.Component {
-
-    constructor(props) {
-        super(props);
-
-        this.state = {
-            current: this.props.current,
-            list: this.props.hosts.list
-        };
-        this.last_content = this.props.hosts.sys.content;
-
-        SH_event.on('imported', () => {
-            this.setState({
-                current: this.props.current,
-                list: this.props.hosts.list
-            }, () => {
-                SH_event.emit('change');
-            });
-        });
-
-        SH_event.on('change', () => {
-            SH_event.emit('save_data', this.state.list);
-            let content = this.getOnContent();
-            if (content !== this.last_content) {
-                SH_event.emit('apply', content, () => {
-                    this.last_content = content;
-                });
-            }
-        });
-
-        SH_event.on('host_added', (data) => {
-            this.setState({
-                list: update(this.state.list, {$push: [data]})
-            }, () => {
-                this.selectOne(data);
-
-                setTimeout(() => {
-                    SH_event.emit('change', true);
-                    let el = this.refs.items;
-                    el.scrollTop = document.querySelector('.list-item.selected').offsetTop - el.offsetHeight + 50;
-                    this.checkUpdateHost(data);
-                }, 100);
-            });
-
-        });
-
-        SH_event.on('host_edited', (data, host) => {
-            let idx = this.state.list.findIndex((item) => item == host);
-            if (idx == -1) return;
-
-            this.setState({
-                list: update(this.state.list, {$splice: [[idx, 1, data]]})
-            }, () => {
-                this.selectOne(data);
-
-                setTimeout(() => {
-                    SH_event.emit('change', true);
-                    this.checkUpdateHost(data, true);
-                }, 100);
-            });
-        });
-
-        SH_event.on('host_refreshed', (data, host) => {
-            let idx = this.state.list.findIndex((item) => item == host);
-            if (idx == -1) return;
-
-            this.setState({
-                list: update(this.state.list, {$splice: [[idx, 1, data]]})
-            }, () => {
-                setTimeout(() => {
-                    if (host === this.state.current) {
-                        this.selectOne(data);
-                    }
-                    SH_event.emit('change', true);
-                }, 100);
-            });
-        });
-
-        SH_event.on('del_host', (host) => {
-            let list = this.state.list;
-            let idx_to_del = list.findIndex((item) => {
-                return host === item;
-            });
-            if (idx_to_del == -1) return;
-            // list.splice(idx_to_del, 1);
-            this.setState({
-                list: update(this.state.list, {$splice: [[idx_to_del, 1]]})
-                // list: this.state.list.filter((item, idx) => idx != idx_to_del)
-            }, () => {
-                setTimeout(() => {
-                    let list = this.state.list;
-                    let next_host = list[idx_to_del] || list[list.length - 1] || this.props.hosts.sys;
-                    if (next_host) {
-                        this.selectOne(next_host);
-                    }
-                    SH_event.emit('change');
-                }, 100);
-            });
-        });
-
-        SH_event.on('get_on_hosts', (callback) => {
-            callback(this.getOnItems());
-        });
-
-        ipcRenderer.on('get_host_list', () => {
-            ipcRenderer.send('send_host_list', this.state.list);
-        });
-
-        ipcRenderer.on('get_export_data', (e, fn) => {
-            let data = Object.assign({}, {
-                version: require('../../configs').version,
-                list: this.state.list.map(item => {
-                    let new_item = Object.assign({}, item);
-                    new_item.on = false;
-                    return new_item;
-                })
-            });
-            ipcRenderer.send('export_data', fn, JSON.stringify(data));
-        });
-
-        SH_event.on('top_toggle', (on, items) => {
-            this.setState({
-                list: this.state.list.map((item) => {
-                    if (items.findIndex((i) => i == item) > -1) {
-                        item.on = on;
-                    }
-                    return item;
-                })
-            }, () => {
-                SH_event.emit('change');
-            });
-        });
-
-        SH_event.on('loading_done', (host, data) => {
-            SH_event.emit('host_refreshed', data, host);
-            // if (host == this.state.current || host._ == this.state.current) {
-            //     setTimeout(() => {
-            //         this.selectOne(this.state.current);
-            //     }, 100);
-            // }
-            if (data.error) {
-                console.log(data.error);
-            }
-        });
-
-        // auto check refresh
-        setTimeout(() => {
-            this.autoCheckRefresh();
-        }, 1000 * 5);
-    }
-
-    /**
-     * 检查当前 host 是否需要从网络下载更新
-     * @param host
-     * @param force {Boolean} 如果为 true,则只要是 remote 且 refresh_interval != 0,则强制更新
-     */
-    checkUpdateHost(host, force = false) {
-        SH_event.emit('check_host_refresh', host, force);
-    }
-
-    autoCheckRefresh() {
-        let remote_idx = -1;
-        this.state.list.map((host, idx) => {
-            if (host.where === 'remote') {
-                remote_idx++;
-            }
-            setTimeout(() => {
-                SH_event.emit('check_host_refresh', host);
-            }, 1000 * 5 * remote_idx + idx);
-        });
-
-        // let wait = 1000 * 60 * 10;
-        let wait = 1000 * 30; // test only
-        setTimeout(() => {
-            this.autoCheckRefresh();
-        }, wait);
-    }
-
-    apply(content, success) {
-        SH_event.emit('apply', content, () => {
-            this.last_content = content;
-            success();
-            SH_event.emit('save_data', this.state.list);
-            SH_Agent.notify({
-                message: 'host updated.'
-            });
-        });
-    }
-
-    selectOne(host) {
-        this.setState({
-            current: host
-        });
-
-        this.props.setCurrent(host);
-    }
-
-    toggleOne(idx, success) {
-
-        let content = this.getOnContent(idx);
-        this.apply(content, () => {
-            let choice_mode = SH_Agent.pref.get('choice_mode');
-            if (choice_mode === 'single') {
-                // 单选模式
-                this.setState({
-                    list: this.state.list.map((item, _idx) => {
-                        if (idx != _idx) {
-                            item.on = false;
-                        }
-                        return item;
-                    })
-                });
-            }
-
-            if (typeof success === 'function') {
-                success();
-            }
-        });
-    }
-
-    getOnItems(idx = -1) {
-        let choice_mode = SH_Agent.pref.get('choice_mode');
-        return this.state.list.filter((item, _idx) => {
-            if (choice_mode === 'single') {
-                return !item.on && _idx == idx;
-            } else {
-                return (item.on && _idx != idx) || (!item.on && _idx == idx);
-            }
-        });
-    }
-
-    getOnContent(idx = -1) {
-        let contents = this.getOnItems(idx).map((item) => {
-            return item.content || '';
-        });
-
-        contents.unshift('# SwitchHosts!');
-
-        return contents.join(`\n\n`);
-    }
-
-    customItems() {
-        return this.state.list.map((item, idx) => {
-            return (
-                <ListItem
-                    data={item}
-                    idx={idx}
-                    selectOne={this.selectOne.bind(this)}
-                    current={this.state.current}
-                    onToggle={(success)=> this.toggleOne(idx, success)}
-                    key={'host-' + idx}
-                    dragOrder={(sidx, tidx) => this.dragOrder(sidx, tidx)}
-                />
-            )
-        });
-    }
-
-    dragOrder(source_idx, target_idx) {
-        let source = this.state.list[source_idx];
-        let target = this.state.list[target_idx];
-
-        let list = this.state.list.filter((item, idx) => idx != source_idx);
-        let new_target_idx = list.findIndex((item) => item == target);
-
-        let to_idx;
-        if (source_idx < target_idx) {
-            // append
-            to_idx = new_target_idx + 1;
-        } else {
-            // insert before
-            to_idx = new_target_idx;
-        }
-        list.splice(to_idx, 0, source);
-
-        this.setState({
-            list: list
-        });
-
-        setTimeout(() => {
-            SH_event.emit('change');
-        }, 100);
-    }
-
-    componentDidMount() {
-    }
-
-    render() {
-        return (
-            <div id="sh-list">
-                <ListItem
-                    data={this.props.hosts.sys}
-                    selectOne={this.selectOne.bind(this)}
-                    current={this.state.current}
-                    sys="1"/>
-                <div ref="items" className="custom-items">
-                    {this.customItems()}
-                </div>
-            </div>
-        );
-    }
-}
-
-export default List;

+ 0 - 10
src1/ui/components/panel/list.less

@@ -1,10 +0,0 @@
-#sh-list {
-
-  .custom-items {
-    position: fixed;
-    width: 240px;
-    top: 36px;
-    bottom: 30px;
-    overflow: auto;
-  }
-}

+ 0 - 151
src1/ui/components/panel/list_item.js

@@ -1,151 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import classnames from 'classnames';
-import {kw2re} from '../../libs/kw';
-import './list_item.less';
-
-export default class ListItem extends React.Component {
-    constructor(props) {
-        super(props);
-
-        this.is_sys = !!this.props.sys;
-        this.state = {
-            is_selected: false,
-            search_kw: '',
-            search_re: null,
-            // on: this.props.data.on,
-        };
-
-        SH_event.on('search', (kw) => {
-            this.setState({
-                search_kw: kw,
-                search_re: kw ? kw2re(kw) : null
-            });
-        });
-
-        ipcRenderer.on('tray_toggle_hosts', (e, idx) => {
-            // ipcRenderer.send('send_host_list', this.state.list);
-            // this.toggleOne(idx);
-            if (idx === this.props.idx) {
-                this.toggle();
-            }
-        });
-
-    }
-
-    getTitle() {
-        return this.is_sys ? SH_Agent.lang.sys_host_title : this.props.data.title || SH_Agent.lang.untitled;
-    }
-
-    beSelected() {
-        // this.setState({
-        //     is_selected: true
-        // });
-
-        this.props.selectOne(this.props.data);
-    }
-
-    toEdit() {
-        SH_event.emit('edit_host', this.props.data);
-    }
-
-    toggle() {
-        let on = !this.props.data.on;
-
-        this.props.onToggle(() => {
-            this.props.data.on = on;
-            this.forceUpdate();
-        });
-
-        SH_event.emit('toggle_host', on);
-    }
-
-    allowedDrop(e) {
-        e.preventDefault();
-    }
-
-    onDrop(e) {
-        if (this.props.sys) {
-            e.preventDefault();
-            return false;
-        }
-        let source_idx = parseInt(e.dataTransfer.getData('text'));
-
-        this.props.dragOrder(source_idx, this.props.idx);
-    }
-
-    onDrag(e) {
-        e.dataTransfer.setData('text', this.props.idx);
-    }
-
-    isMatched() {
-        if (this.props.sys) return true;
-        let kw = this.state.search_kw;
-        let re = this.state.search_re;
-        if (!kw || kw === '/') return true;
-
-        let {title, content} = this.props.data;
-
-        if (re) {
-            return re.test(title) || re.test(content);
-        } else {
-            return title.indexOf(kw) > -1 || content.indexOf(kw) > -1;
-        }
-    }
-
-    render() {
-        let {data, sys, current} = this.props;
-        let is_selected = data == current;
-
-        return (
-            <div className={classnames({
-                'list-item': 1
-                , 'hidden': !this.isMatched()
-                , 'sys-host': sys
-                , 'selected': is_selected
-            })}
-                 onClick={this.beSelected.bind(this)}
-                 draggable={!sys}
-                 onDragStart={(e) => this.onDrag(e)}
-                 onDragOver={(e) => this.allowedDrop(e)}
-                 onDrop={(e) => this.onDrop(e)}
-            >
-                { sys ? null :
-                    (
-                        <div>
-                            <i className={classnames({
-                                'switch': 1
-                                , 'iconfont': 1
-                                , 'icon-on': data.on
-                                , 'icon-off': !data.on
-                            })}
-                               onClick={this.toggle.bind(this)}
-                            />
-                            <i
-                                className="iconfont icon-edit"
-                                onClick={this.toEdit.bind(this)}
-                            />
-                        </div>
-                    )
-                }
-                <i className={classnames({
-                    'iconfont': 1
-                    , 'item-icon': 1
-                    , 'icon-warn': !!data.error
-                    , 'icon-file': !sys && !data.error && data.where !== 'group'
-                    , 'icon-files': data.where === 'group'
-                    , 'icon-sysserver': sys && !data.error
-                })}
-                   title={data.error || ''}
-                />
-                <span>{this.getTitle()}</span>
-            </div>
-        );
-    }
-}

+ 0 - 65
src1/ui/components/panel/list_item.less

@@ -1,65 +0,0 @@
-#sh-list {
-  .list-item {
-    padding: 7px 10px 7px 15px;
-    cursor: pointer;
-
-    &.hidden {
-      display: none;
-    }
-
-    &.sys-host {
-      font-size: 14px;
-      padding: 8px 10px 8px 12px;
-
-      i {
-        width: 23px;
-      }
-    }
-
-    &.selected {
-      background: #2d3138;
-
-      span {
-        color: #fff;
-      }
-
-      i.item-icon {
-        color: #fff;
-      }
-
-      &:hover {
-        i.icon-edit {
-          display: block;
-          color: #fff;
-        }
-      }
-    }
-
-    i {
-      display: inline-block;
-      width: 20px;
-      text-align: center;
-      margin-right: 5px;
-
-      &.item-icon {
-        font-size: 12px;
-      }
-
-      &.switch {
-        float: right;
-        cursor: pointer;
-        line-height: 23px;
-
-        &.icon-on {
-          color: #af9;
-        }
-      }
-
-      &.icon-edit {
-        float: right;
-        display: none;
-      }
-    }
-
-  }
-}

+ 0 - 26
src1/ui/components/panel/panel.js

@@ -1,26 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import Buttons from './buttons';
-import SearchBar from './searchbar';
-import List from './list';
-import './panel.less';
-
-export default class Panel extends React.Component {
-    render() {
-        let {current, hosts} = this.props;
-
-        return (
-            <div id="panel">
-                <List hosts={hosts} current={current} setCurrent={this.props.setCurrent}/>
-                <SearchBar/>
-                <Buttons/>
-            </div>
-        );
-    }
-}

+ 0 - 10
src1/ui/components/panel/panel.less

@@ -1,10 +0,0 @@
-@import '../cfg.less';
-@import "iconfont/iconfont.css";
-
-#panel {
-
-  width: 240px;
-  height: 100%;
-  background: @bg_left;
-  color: @font_color_left;
-}

+ 0 - 79
src1/ui/components/panel/searchbar.js

@@ -1,79 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import classnames from 'classnames';
-import './searchbar.less';
-
-export default class SearchBar extends React.Component {
-
-    constructor(props) {
-        super(props);
-
-        this.state = {
-            show: false,
-            keyword: ''
-        };
-
-        this._t = null;
-
-        SH_event.on('search_on', () => {
-            this.setState({
-                show: true
-            }, () => {
-                setTimeout(() => {
-                    this.refs.keyword.focus();
-                }, 100);
-            });
-        });
-
-        SH_event.on('search_off', () => {
-            this.clearSearch();
-        });
-    }
-
-    clearSearch() {
-        this.setState({
-            show: false,
-            keyword: ''
-        });
-        SH_event.emit('search', '')
-    }
-
-    doSearch(kw) {
-        this.setState({
-            keyword: kw
-        });
-
-        clearTimeout(this._t);
-        this._t = setTimeout(() => {
-            SH_event.emit('search', kw)
-        }, 300);
-    }
-
-    onCancel() {
-        SH_event.emit('cancel_search');
-    }
-
-    render() {
-        if (!this.state.show) {
-            return null;
-        }
-        return (
-            <div id="sh-searchbar">
-                <input
-                    ref="keyword"
-                    type="text"
-                    placeholder="keyword"
-                    value={this.state.keyword}
-                    onChange={(e) => this.doSearch(e.target.value)}
-                    onKeyDown={(e)=>(e.keyCode===27 && this.onCancel())}
-                />
-            </div>
-        );
-    }
-}

+ 0 - 19
src1/ui/components/panel/searchbar.less

@@ -1,19 +0,0 @@
-@import '../cfg.less';
-
-#sh-searchbar {
-  position: fixed;
-  width: 240px;
-  left: 0;
-  bottom: 30px;
-  background: @bg_left_search;
-  padding: 6px 20px 5px 18px;
-  border-top: solid 1px @bg_left * 0.9;
-
-  input {
-    background: transparent;
-    border: 0;
-    outline: 0;
-    color: #fff;
-    font-size: 13px;
-  }
-}

+ 0 - 14
src1/ui/configs.js

@@ -1,14 +0,0 @@
-/**
- * configs.js
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const m_ver = require('../version').version;
-
-exports.version = m_ver.slice(0, 3).join('.');
-exports.version_full = m_ver.join('.');
-exports.url_download = 'https://github.com/oldj/SwitchHosts/releases';
-

+ 0 - 13
src1/ui/event.js

@@ -1,13 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const EventEmitter = require('events');
-
-let event = new EventEmitter();
-event.setMaxListeners(50);
-
-exports.event = event;

+ 0 - 24
src1/ui/libs/default_data.js

@@ -1,24 +0,0 @@
-/**
- * default_data, created on 2016/8/27.
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-function makeDefaultData() {
-    return {
-        sys: {
-            is_sys: true
-            , content: ''
-        },
-        list: [
-            {
-                title: 'my hosts',
-                content: '# input hosts here\n\n'
-            }
-        ]
-    };
-}
-
-exports.make = makeDefaultData;

+ 0 - 34
src1/ui/libs/io.js

@@ -1,34 +0,0 @@
-/**
- * io
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const fs = require('fs');
-
-exports.getUserHome = function () {
-    return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'];
-};
-
-exports.isFile = function (p) {
-    try {
-        if (fs.statSync(p).isFile()) {
-            return true;
-        }
-    } catch (e) {
-    }
-    return false;
-};
-
-exports.isDirectory = function (p) {
-    try {
-        if (fs.statSync(p).isDirectory()) {
-            return true;
-        }
-    } catch (e) {
-    }
-    return false;
-};
-

+ 0 - 72
src1/ui/libs/kw.js

@@ -1,72 +0,0 @@
-/**
- * kw
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-function kw2re(kw) {
-    // 模糊搜索
-    let r;
-    let m;
-    let flag = [];
-
-    if (kw === '/') {
-        return;
-    } else if ((m = kw.match(/^\/([^\/]+)\/?(\w*)$/))) {
-        if (m[2].indexOf('i') > -1) {
-            flag.push('i');
-        }
-        // if (m[2].indexOf('g') > -1) {
-        flag.push('g');
-        // }
-        try {
-            r = new RegExp(m[1], flag.join(''));
-        } catch (e) {
-        }
-    } else if (kw.indexOf('*') > -1) {
-        try {
-            r = new RegExp(kw.replace(/\*/g, '.*'), 'ig');
-        } catch (e) {
-        }
-    }
-
-    return r;
-}
-
-exports.findPositions = function (kw, code) {
-    if (!kw || kw === '/') return;
-
-    let r = kw2re(kw);
-    if (!r) {
-        try {
-            r = new RegExp(kw
-                    .replace(/([\.\?\*\+\^\$\(\)\-\[\]\{\}])/g, '\\$1')
-                , 'ig');
-        } catch (e) {
-            console.log(e);
-            return;
-        }
-    }
-    let indexes = [];
-
-    let lines = code.split('\n');
-
-    lines.map((ln, idx) => {
-        let match;
-        let max_loop = 30;
-        while (match = r.exec(ln)) {
-            indexes.push([
-                {line: idx, ch: match.index},
-                {line: idx, ch: match.index + match[0].length},
-            ]);
-            max_loop--;
-            if (max_loop < 0) break;
-        }
-    });
-
-    return indexes;
-};
-
-exports.kw2re = kw2re;

+ 0 - 40
src1/ui/libs/paths.js

@@ -1,40 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const path = require('path');
-const io = require('./io');
-const platform = process.platform;
-const sys_host_path = platform == 'win32' ?
-    `${process.env.windir || 'C:\\WINDOWS'}\\system32\\drivers\\etc\\hosts` : // Windows 系统有可能不安装在 C 盘
-    '/etc/hosts';
-const home_path = io.getUserHome();
-const work_path = path.join(home_path, '.SwitchHosts');
-const data_path = path.join(work_path, 'data.json');
-const preference_path = path.join(work_path, 'preferences.json');
-
-function getCurrentAppPath() {
-    let a = __dirname.split(path.sep);
-    // console.log(a);
-    while (a.length > 0) {
-        let i = a[a.length - 1];
-        if (i.endsWith('.app')) {
-            return a.join(path.sep);
-        }
-        a.pop();
-    }
-
-    return null;
-}
-
-module.exports = {
-    home_path: home_path
-    , work_path: work_path
-    , data_path: data_path
-    , preference_path: preference_path
-    , sys_host_path: sys_host_path
-    // ,current_app_path: getCurrentAppPath()
-};

+ 0 - 60
src1/ui/libs/pref.js

@@ -1,60 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const fs = require('fs');
-const paths = require('./paths');
-const util = require('./util');
-const io = require('./io');
-// const AutoLaunch = require('auto-launch');
-// const auto_launch = new AutoLaunch({
-//     name: 'SwitchHosts!',
-//     path: paths.current_app_path,
-// });
-
-let is_loaded;
-let data = {};
-let _t;
-
-
-function load() {
-    if (io.isFile(paths.preference_path)) {
-        let cnt = fs.readFileSync(paths.preference_path, 'utf-8');
-        try {
-            data = JSON.parse(cnt);
-        } catch (e) {
-            console.log(e);
-        }
-    }
-
-    return data;
-}
-
-function get(key, default_value=null) {
-    if (!is_loaded) load();
-    return key in data ? data[key] : default_value;
-}
-
-function set(key, value, callback) {
-    clearTimeout(_t);
-    if (!is_loaded) load();
-
-    data[key] = value;
-    _t = setTimeout(() => {
-        fs.writeFile(paths.preference_path, JSON.stringify(data), 'utf-8', (err) => {
-            if (err) {
-                console.log(err);
-            }
-            typeof callback === 'function' && callback(err);
-        });
-    }, 100);
-}
-
-module.exports = {
-    load: load,
-    get: get,
-    set: set
-};

+ 0 - 15
src1/ui/libs/util.js

@@ -1,15 +0,0 @@
-/**
- * util
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-exports.formatVersion = (v) => {
-  return 'v' + v.slice(0, 3).join('.') + ` (${v[3]})`
-}
-
-exports.makeId = () => {
-  return (new Date()).getTime() + '-' + Math.floor(Math.random() * 1e6)
-}

+ 0 - 28
src1/ui/mock.js

@@ -1,28 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-exports.hosts = {
-    sys: {
-        content: 'test'
-    },
-    custom: [{
-        title: 'c1',
-        content: '1111',
-        is_remote: false,
-        url: ''
-    }, {
-        title: 'c2',
-        content: '2222',
-        is_remote: false,
-        url: ''
-    }, {
-        title: 'c3',
-        content: '3333',
-        is_remote: true,
-        url: 'http://test.com/t.txt'
-    }]
-};

+ 0 - 305
src1/ui/modules/mainMenu.js

@@ -1,305 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const path = require('path');
-const paths = require('../libs/paths');
-const {Menu, shell, ipcMain, dialog} = require('electron');
-const m_chk_update = require('../../bg/check_for_update');
-const m_lang = require('../lang');
-const pref = require('./../libs/pref');
-const version = require('../../version').version;
-
-exports.init = function (app, sys_lang = 'en') {
-    let lang = m_lang.getLang(pref.get('user_language', sys_lang));
-    let last_path = null;
-
-    const template = [
-        {
-            label: lang.file,
-            submenu: [
-                {
-                    label: lang.new,
-                    accelerator: 'CommandOrControl+N',
-                    click: () => {
-                        ipcMain.emit('to_add_host');
-                    }
-                }, {
-                    type: 'separator'
-                }, {
-                    label: lang.import,
-                    accelerator: 'Alt+CommandOrControl+I',
-                    click: () => {
-                        dialog.showOpenDialog({
-                            title: lang.import,
-                            defaultPath: path.join(last_path || paths.home_path, 'sh.json'),
-                            filters: [
-                                {name: 'JSON', extensions: ['json']},
-                                {name: 'All Files', extensions: ['*']}
-                            ]
-                        }, (fns) => {
-                            if (fns && fns.length > 0) {
-                                ipcMain.emit('to_import', fns[0]);
-                                last_path = path.dirname(fns[0]);
-                            }
-                        });
-                    }
-                }, {
-                    label: lang.export,
-                    accelerator: 'Alt+CommandOrControl+E',
-                    click: () => {
-                        dialog.showSaveDialog({
-                            title: lang.export,
-                            defaultPath: path.join(last_path || paths.home_path, 'sh.json'),
-                            filters: [
-                                {name: 'JSON', extensions: ['json']},
-                                {name: 'All Files', extensions: ['*']}
-                            ]
-                        }, (fn) => {
-                            if (fn) {
-                                ipcMain.emit('to_export', fn);
-                                last_path = path.dirname(fn);
-                            }
-                        });
-                    }
-                }, {
-                    type: 'separator'
-                }, {
-                    label: lang.preferences,
-                    accelerator: 'CommandOrControl+,',
-                    click: () => {
-                        app.mainWindow.webContents.send('show_preferences');
-                    }
-                }
-            ]
-        },
-        {
-            label: lang.edit,
-            submenu: [{
-                role: 'undo'
-            }, {
-                role: 'redo'
-            }, {
-                type: 'separator'
-            }, {
-                role: 'cut'
-            }, {
-                role: 'copy'
-            }, {
-                role: 'paste'
-            }, {
-                role: 'pasteandmatchstyle'
-            }, {
-                role: 'delete'
-            }, {
-                role: 'selectall'
-            }, {
-                type: 'separator'
-            }, {
-                label: lang.search,
-                accelerator: 'CommandOrControl+F',
-                click () {
-                    // ipcMain.emit('to_search');
-                    app.mainWindow.webContents.send('to_search');
-                }
-            }, {
-                label: lang.comment,
-                accelerator: 'CommandOrControl+/',
-                click () {
-                    // ipcMain.emit('to_search');
-                    app.mainWindow.webContents.send('to_comment');
-                }
-            }]
-        }, {
-            label: lang.view,
-            submenu: [
-                // {
-                //     label: 'Reload',
-                //     accelerator: 'CmdOrCtrl+R',
-                //     click (item, focusedWindow) {
-                //         if (focusedWindow) focusedWindow.reload()
-                //     }
-                // },
-                // {
-                //     label: 'Toggle Developer Tools',
-                //     accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
-                //     click (item, focusedWindow) {
-                //         if (focusedWindow) focusedWindow.webContents.toggleDevTools()
-                //     }
-                // },
-                // {
-                //     type: 'separator'
-                // },
-                {
-                    role: 'resetzoom'
-                }, {
-                    role: 'zoomin'
-                }, {
-                    role: 'zoomout'
-                }, {
-                    type: 'separator'
-                }, {
-                    role: 'togglefullscreen'
-                }
-            ]
-        }, {
-            label: lang.window,
-            role: 'window',
-            submenu: [{
-                role: 'minimize'
-            }, {
-                role: 'close'
-            }]
-        }, {
-            label: lang.help,
-            role: 'help',
-            submenu: [{
-                label: lang.check_update,
-                click () {
-                    m_chk_update.check();
-                }
-            }, {
-                type: 'separator'
-            }, {
-                label: lang.feedback,
-                click () {
-                    shell.openExternal('https://github.com/oldj/SwitchHosts/issues');
-                }
-            }, {
-                label: lang.homepage,
-                click () {
-                    shell.openExternal('http://oldj.github.io/SwitchHosts/');
-                }
-            }]
-        }
-    ];
-
-    const name = require('electron').app.getName();
-    const os = process.platform;
-    if (os === 'darwin') {
-        template.unshift({
-            label: name,
-            submenu: [{
-                role: 'about'
-            }, {
-                type: 'separator'
-            },
-                // {
-                //     role: 'services',
-                //     submenu: []
-                // },
-                // {
-                //     type: 'separator'
-                // },
-                {
-                    role: 'hide'
-                }, {
-                    role: 'hideothers'
-                }, {
-                    role: 'unhide'
-                }, {
-                    type: 'separator'
-                }, {
-                    role: 'quit'
-                }]
-        });
-        // Edit menu.
-        /*template[2].submenu.push(
-         {
-         type: 'separator'
-         },
-         {
-         label: 'Speech',
-         submenu: [
-         {
-         role: 'startspeaking'
-         },
-         {
-         role: 'stopspeaking'
-         }
-         ]
-         }
-         );*/
-        // Window menu.
-        template[4].submenu = [
-            {
-                label: 'Close',
-                accelerator: 'CmdOrCtrl+W',
-                role: 'close'
-            },
-            {
-                label: 'Minimize',
-                accelerator: 'CmdOrCtrl+M',
-                role: 'minimize'
-            },
-            {
-                label: 'Zoom',
-                role: 'zoom'
-            },
-            {
-                type: 'separator'
-            },
-            {
-                label: 'Bring All to Front',
-                role: 'front'
-            }
-        ]
-    } else if (os == 'win32') {
-        template[0].submenu.unshift({
-            type: 'separator'
-        });
-        template[0].submenu.unshift({
-            role: 'about',
-            click: () => {
-                dialog.showMessageBox({
-                    type: 'info',
-                    buttons: [],
-                    title: 'About',
-                    message: `${name} v${version.slice(0, 3).join('.')} (${version[3]})`
-                });
-            }
-        });
-
-        template[0].submenu.push({
-            type: 'separator'
-        });
-        template[0].submenu.push({
-            label: 'Quit',
-            role: 'quit',
-            accelerator: 'CmdOrCtrl+Q',
-        });
-
-        // VIEW
-        template[2].submenu.splice(0, 4);
-    }
-
-    if (process.env.ENV == 'dev') {
-        // VIEW
-        template[3].submenu = [
-            {
-                label: 'Reload',
-                accelerator: 'CmdOrCtrl+R',
-                click (item, focusedWindow) {
-                    if (focusedWindow) focusedWindow.reload()
-                }
-            },
-            {
-                label: 'Toggle Developer Tools',
-                accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
-                click (item, focusedWindow) {
-                    if (focusedWindow) focusedWindow.webContents.toggleDevTools()
-                }
-            },
-            {
-                type: 'separator'
-            }
-        ].concat(template[3].submenu);
-    }
-
-    const menu = Menu.buildFromTemplate(template);
-    Menu.setApplicationMenu(menu);
-}
-;

+ 0 - 66
src1/ui/modules/stat.js

@@ -1,66 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const request = require('request');
-const version = require('../configs').version_full;
-
-const url = 'http://lab.oldj.net/s.gif';
-const session_id = (new Date()).getTime() + ':' + Math.random();
-const queue = [];
-let is_initialized = false;
-
-function log(action) {
-    let u = url + '?' + [
-            'app=sh3',
-            'action=' + encodeURIComponent(action),
-            'v=' + encodeURIComponent(version),
-            'os=' + process.platform,
-            'sid=' + encodeURIComponent(session_id),
-            '_r=' + Math.random()
-        ].join('&');
-
-    console.log('stat: ' + action);
-    request.get(u)
-        .on('response', function(response) {
-            // console.log('log ' + response.statusCode); // 200
-        })
-        .on('error', function(err) {
-            console.log(err);
-        });
-}
-
-function record(action) {
-    queue.push(action);
-}
-
-function send() {
-    if (queue.length === 0) return;
-
-    let action = queue.splice(0).join(',');
-    log(action);
-}
-
-function init() {
-    if (is_initialized) return;
-    is_initialized = true;
-
-    record('launch');
-    SH_event.on('toggle_host', () => {
-        record('switch');
-    });
-
-    setInterval(function () {
-        // 每一段时间自动打点
-        record('tick');
-    }, 60 * 1000 * 42);
-
-    setInterval(() => {
-        send();
-    }, 5000);
-}
-
-exports.init = init;

+ 0 - 116
src1/ui/modules/tray.js

@@ -1,116 +0,0 @@
-/**
- * tray
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const fs = require('fs');
-const path = require('path');
-const {Menu, Tray, ipcMain, shell} = require('electron');
-const m_lang = require('../lang');
-const m_chk_update = require('../../bg/check_for_update');
-const pref = require('./../libs/pref');
-const os = process.platform;
-const util = require('../libs/util');
-const current_version = require('../../version').version;
-
-let tray = null;
-
-function makeMenu(app, list, contents, sys_lang) {
-    let menu = [];
-    let lang = m_lang.getLang(pref.get('user_language', sys_lang));
-
-    menu.push({
-        label: 'SwitchHosts!',
-        type: 'normal',
-        // sublabel: util.formatVersion(current_version), // does not work on Mac
-        click: () => {
-            app.emit('show');
-        }
-    });
-    menu.push({label: util.formatVersion(current_version), type: 'normal', enabled: false});
-    menu.push({label: '-', type: 'separator'});
-
-    let ac = '1234567890abcdefghijklmnopqrstuvwxyz'.split('');
-    list.map((item, idx) => {
-        menu.push({
-            label: item.title || 'untitled',
-            type: 'checkbox',
-            checked: item.on,
-            accelerator: ac[idx],
-            click: () => {
-                contents.send('tray_toggle_host', idx);
-                contents.send('get_host_list');
-            }
-        });
-    });
-
-    menu.push({type: 'separator'});
-    menu.push({
-        label: lang.feedback, type: 'normal', click: () => {
-            shell.openExternal('https://github.com/oldj/SwitchHosts/issues');
-        }
-    });
-
-    menu.push({
-        label: lang.check_update, type: 'normal', click: () => {
-            m_chk_update.check();
-        }
-    });
-
-    if (os === 'darwin') {
-        menu.push({
-            label: lang.toggle_dock_icon, type: 'normal', click: () => {
-                let is_dock_visible = app.dock.isVisible();
-                if (is_dock_visible) {
-                    app.dock.hide();
-                } else {
-                    app.dock.show();
-                }
-                pref.set('is_dock_icon_hidden', is_dock_visible);
-            }
-        });
-    }
-
-    menu.push({type: 'separator'});
-    menu.push({
-        label: lang.quit, type: 'normal', accelerator: 'CommandOrControl+Q', click: () => {
-            app.quit();
-        }
-    });
-
-    return menu;
-}
-
-function makeTray(app, contents, sys_lang = 'en') {
-    let icon = 'logo.png';
-    if (process.platform === 'darwin') {
-        icon = 'ilogoTemplate.png';
-    }
-
-    tray = new Tray(path.join(__dirname, '..', 'assets', icon));
-    tray.setToolTip('SwitchHosts!');
-
-    contents.send('get_host_list');
-
-    ipcMain.on('send_host_list', (e, d) => {
-        const contextMenu = Menu.buildFromTemplate(makeMenu(app, d, contents, sys_lang));
-        tray.setContextMenu(contextMenu);
-    });
-
-    let is_dock_icon_hidden = pref.get('is_dock_icon_hidden', false);
-    if (is_dock_icon_hidden) {
-        app.dock.hide();
-    }
-
-    // windows only
-    if (process.platform === 'win32') {
-        tray.on('click', () => {
-            app.emit('show');
-        });
-    }
-}
-
-exports.makeTray = makeTray;

+ 0 - 17
src1/ui/ui.js

@@ -1,17 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import ReactDom from 'react-dom';
-import App from './components/app';
-
-ipcRenderer.setMaxListeners(20);
-
-ReactDom.render(
-    <App/>
-    , document.getElementById('app')
-);

+ 0 - 108
src1/ui2/components/app.js

@@ -1,108 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-import React from 'react'
-import Panel from './panel/panel'
-import Content from './content/content'
-import SudoPrompt from './frame/sudo'
-import EditPrompt from './frame/edit'
-import PreferencesPrompt from './frame/preferences'
-import Agent from '../../renderer/Agent'
-import './app.less'
-
-class App extends React.Component {
-  constructor (props) {
-    super(props)
-
-    this.state = {
-      list: [],
-      sys: {},
-      current: {},
-      lang: {}
-    }
-
-    Agent.act('getUserHosts', (e, data) => {
-      this.setState({
-        list: data.list,
-        sys: data.sys
-      })
-    })
-
-    Agent.act('getLang', (e, lang) => {
-      this.setState({lang})
-    })
-  }
-
-  setCurrent (hosts) {
-    if (hosts.is_sys) {
-      Agent.act('getSysHosts', (e, _hosts) => {
-        this.setState({
-          current: _hosts
-        })
-      })
-    } else {
-      this.setState({
-        current: hosts
-      })
-    }
-  }
-
-  static isReadOnly (hosts) {
-    return !hosts || hosts.is_sys || hosts.where === 'remote'
-  }
-
-  toSave () {
-    clearTimeout(this._t)
-
-    this._t = setTimeout(() => {
-      Agent.emit('change')
-    }, 1000)
-  }
-
-  setHostContent (v) {
-    if (this.state.current.content === v) return // not changed
-
-    this.state.current.content = v || ''
-    this.toSave()
-  }
-
-  componentDidMount () {
-    window.addEventListener('keydown', (e) => {
-      if (e.keyCode === 27) {
-        Agent.emit('esc')
-      }
-    }, false)
-  }
-
-  render () {
-    let current = this.state.current
-    return (
-      <div id="app" className={'platform-' + Agent.platform}>
-        <Panel
-          list={this.state.list}
-          sys={this.state.sys}
-          current={current}
-          setCurrent={this.setCurrent.bind(this)}
-          lang={this.state.lang}
-        />
-        <Content
-          current={current}
-          readonly={App.isReadOnly(current)}
-          setHostContent={this.setHostContent.bind(this)}
-          lang={this.state.lang}
-        />
-        <div className="frames">
-          <SudoPrompt/>
-          <EditPrompt hosts={this.state.hosts}/>
-          <PreferencesPrompt/>
-        </div>
-      </div>
-    )
-  }
-}
-
-export default App

+ 0 - 20
src1/ui2/components/app.less

@@ -1,20 +0,0 @@
-@import "./cfg.less";
-
-html, body {
-  margin: 0;
-  padding: 0;
-  height: 100%;
-  font-size: 12px;
-  font-family: Arial, Helvetica, sans-serif;
-  color: @font_color;
-  line-height: 20px;
-  background: #fff;
-}
-
-a {
-  text-decoration: none;
-}
-
-#app {
-  height: 100%;
-}

+ 0 - 13
src1/ui2/components/cfg.less

@@ -1,13 +0,0 @@
-@font_color: #212121;
-@bd_color: bg_left;
-@bg_prompt: #f5f5f5;
-@color_hover: #09f;
-@color_on: #af9;
-@color_off: font_color_left;
-@color_danger: #f03;
-
-// left
-@bg_left: #373d47;
-@bg_left_search: @bg_left * 1.1;
-@left_width: 240px;
-@font_color_left: #979da7;

+ 0 - 50
src1/ui2/components/content/cm_hl.js

@@ -1,50 +0,0 @@
-// custom mode
-
-'use strict';
-
-import CodeMirror from 'codemirror';
-
-export default function () {
-
-    CodeMirror.defineMode('host', function () {
-        function tokenBase(stream) {
-            if (stream.eatSpace()) return null;
-
-            var sol = stream.sol();
-            var ch = stream.next();
-
-            var s = stream.string;
-
-            if (ch === '#') {
-                stream.skipToEnd();
-                return 'comment';
-            }
-            if (!s.match(/^\s*([\d\.]+|[\da-f:\.%lo]+)\s+\w/i)) {
-                return 'error';
-            }
-
-            if (sol && ch.match(/[\w\.:%]/)) {
-                stream.eatWhile(/[\w\.:%]/);
-                return 'ip';
-            }
-
-            return null;
-        }
-
-        function tokenize(stream, state) {
-            return (state.tokens[0] || tokenBase)(stream, state);
-        }
-
-        return {
-            startState: function () {
-                return {tokens: []};
-            },
-            token: function (stream, state) {
-                return tokenize(stream, state);
-            },
-            lineComment: '#'
-        };
-    });
-
-    //CodeMirror.defineMIME('text/x-host', 'host');
-}

+ 0 - 95
src1/ui2/components/content/content.js

@@ -1,95 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-import React from 'react'
-import Editor from './editor'
-import Agent from '../../../renderer/Agent'
-import classnames from 'classnames'
-import './content.less'
-
-export default class Content extends React.Component {
-
-  constructor (props) {
-    super(props)
-
-    this.codemirror = null
-    this.state = {
-      is_loading: this.props.current.is_loading,
-      code: this.props.current.content || ''
-    }
-    this._t = null
-
-    Agent.on('loading', (hosts) => {
-      if (hosts === this.props.current) {
-        this.setState({
-          is_loading: true
-        })
-      }
-    })
-
-    Agent.on('loading_done', (hosts, data) => {
-      if (hosts === this.props.current) {
-        this.setState({
-          is_loading: false,
-          code: data.content || ''
-        })
-      }
-    })
-  }
-
-  setValue (v) {
-    this.props.setHostsContent(v)
-  }
-
-  componentWillReceiveProps (next_props) {
-    this.setState({
-      is_loading: next_props.current.is_loading,
-      code: next_props.current.content || ''
-    })
-  }
-
-  render () {
-    let {current} = this.props
-
-    return (
-      <div id="sh-content">
-        <div className="inform">
-                    <span
-                      className={classnames({
-                        loading: 1,
-                        show: this.state.is_loading
-                      })}
-                    >loading...</span>
-          <i
-            className={classnames({
-              show: current.where === 'remote',
-              iconfont: 1,
-              'icon-earth': 1
-            })}
-            title={Agent.lang.remote_hosts}
-          />
-          <i
-            className={classnames({
-              show: this.props.readonly,
-              iconfont: 1,
-              'icon-lock2': 1
-            })}
-            title={Agent.lang.readonly}
-          />
-        </div>
-        <div className={classnames({
-          errorMessage: 1,
-          show: !!this.props.current.error
-        })}>{this.props.current.error}</div>
-        <Editor
-          code={this.state.code}
-          readonly={this.props.readonly}
-          setValue={this.setValue.bind(this)}/>
-      </div>
-    )
-  }
-}

+ 0 - 61
src1/ui2/components/content/content.less

@@ -1,61 +0,0 @@
-#sh-content {
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 240px;
-  height: 100%;
-
-  .inform {
-    position: absolute;
-    z-index: 100;
-    top: 5px;
-    right: 10px;
-    opacity: 0.5;
-    background: #fff;
-
-    i {
-      display: none;
-      color: #666;
-      margin-left: 5px;
-
-      &.show {
-        display: inline-block;
-      }
-    }
-
-    span {
-      display: none;
-
-      &.show {
-        display: inline-block;
-      }
-    }
-  }
-
-  .errorMessage {
-    display: none;
-    position: absolute;
-    z-index: 101;
-    top: 0;
-    left: 0;
-    right: 0;
-    padding: 4px 40px;
-    text-align: center;
-    background: rgba(153, 0, 0, 0.5);
-    color: #fff;
-    transition: 0.5s;
-
-    &.show {
-      display: block;
-    }
-  }
-}
-
-.platform-win32 {
-  #sh-content {
-    .inform {
-      right: 20px;
-    }
-  }
-}

+ 0 - 127
src1/ui2/components/content/editor.js

@@ -1,127 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import CodeMirror from 'codemirror';
-// import '../../../node_modules/codemirror/addon/comment/comment';
-import 'codemirror/addon/comment/comment';
-import classnames from 'classnames';
-import modeHost from './cm_hl';
-import m_kw from '../../libs/kw';
-import 'codemirror/lib/codemirror.css';
-import './editor.less'
-
-export default class Editor extends React.Component {
-
-    constructor(props) {
-        super(props);
-
-        this.codemirror = null;
-
-        modeHost();
-
-        this.marks = [];
-        this.kw = '';
-
-        SH_event.on('search', (kw) => {
-            this.kw = kw;
-            this.highlightKeyword();
-        });
-    }
-
-    highlightKeyword() {
-        while (this.marks.length > 0) {
-            this.marks.shift().clear();
-        }
-
-        let code = this.props.code;
-        let pos = m_kw.findPositions(this.kw, code) || [];
-        // this.codemirror.markText({line: 6, ch: 16}, {line: 6, ch: 22}, {className: 'cm-hl'});
-
-        pos.map((p) => {
-            this.marks.push(this.codemirror.markText(p[0], p[1], {className: 'cm-hl'}));
-        });
-    }
-
-    setValue(v) {
-        this.props.setValue(v);
-    }
-
-    toComment() {
-        let doc = this.codemirror.getDoc();
-        let cur = doc.getCursor();
-        let line = cur.line;
-        let info = doc.lineInfo(line);
-        this.codemirror.toggleComment({
-            line: line,
-            cur: 0
-        }, {
-            line: line,
-            cur: info.text.length
-        });
-    }
-
-    componentDidMount() {
-        // console.log(this.cnt_node, this.cnt_node.value);
-        this.codemirror = CodeMirror.fromTextArea(this.cnt_node, {
-            lineNumbers: true,
-            readOnly: true,
-            mode: 'host'
-        });
-
-        this.codemirror.setSize('100%', '100%');
-
-        this.codemirror.on('change', (a) => {
-            let v = a.getDoc().getValue();
-            this.setValue(v);
-        });
-
-        this.codemirror.on('gutterClick', (cm, n) => {
-            if (this.props.readonly === true) return;
-
-            let info = cm.lineInfo(n);
-            //cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
-            let ln = info.text;
-            if (/^\s*$/.test(ln)) return;
-
-            let new_ln;
-            if (/^#/.test(ln)) {
-                new_ln = ln.replace(/^#\s*/, '');
-            } else {
-                new_ln = '# ' + ln;
-            }
-            this.codemirror.getDoc().replaceRange(new_ln, {line: info.line, ch: 0}, {line: info.line, ch: ln.length});
-            //app.caculateHosts();
-        });
-
-        ipcRenderer.on('to_comment', () => {
-            this.toComment();
-        });
-    }
-
-    componentWillReceiveProps(next_props) {
-        // console.log(next_props);
-        this.codemirror.getDoc().setValue(next_props.code);
-        this.codemirror.setOption('readOnly', next_props.readonly);
-        setTimeout(() => {
-            this.highlightKeyword();
-        }, 100);
-    }
-
-    render() {
-        return (
-            <div id="sh-editor" className={classnames({
-                readonly: this.props.readonly
-            })}>
-                <textarea
-                    ref={(c) => this.cnt_node = c}
-                    defaultValue={this.props.code || ''}
-                />
-            </div>
-        );
-    }
-}

+ 0 - 33
src1/ui2/components/content/editor.less

@@ -1,33 +0,0 @@
-#sh-editor {
-  height: 100%;
-  font-family: Menlo, "Source Code Pro", Monaco, "Courier New", sans-serif;
-
-  // CodeMirror
-  .cm-s-default .cm-comment {
-    color: #090;
-  }
-  .cm-s-default .cm-ip {
-    color: #00a;
-    font-weight: bold;
-  }
-  .cm-s-default .cm-hl {
-    background: #ff0;
-  }
-  .CodeMirror-gutters {
-    border-right: none;
-    padding-right: 6px;
-  }
-
-  .CodeMirror-linenumber {
-    cursor: pointer;
-  }
-
-  &.readonly .CodeMirror {
-    .CodeMirror-linenumber {
-      cursor: default;
-    }
-    .CodeMirror-cursors {
-      display: none;
-    }
-  }
-}

+ 0 - 295
src1/ui2/components/frame/edit.js

@@ -1,295 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict'
-
-import React from 'react'
-import MyFrame from './frame'
-import classnames from 'classnames'
-import Group from './group'
-import util from '../../libs/util'
-import './edit.less'
-
-export default class EditPrompt extends React.Component {
-  constructor (props) {
-    super(props)
-
-    this.state = {
-      show: false,
-      add: true,
-      where: 'local',
-      title: '',
-      url: '',
-      last_refresh: null,
-      refresh_interval: 0,
-      is_loading: false,
-    }
-
-    this.current_host = null
-  }
-
-  tryToFocus () {
-    let el = this.refs.body && this.refs.body.querySelector('input[type=text]')
-    el && el.focus()
-  }
-
-  clear () {
-    this.setState({
-      where: 'local',
-      title: '',
-      url: '',
-      last_refresh: null,
-      refresh_interval: 0,
-    })
-  }
-
-  componentDidMount () {
-    SH_event.on('add_host', () => {
-      this.setState({
-        show: true,
-        add: true,
-      })
-      setTimeout(() => {
-        this.tryToFocus()
-      }, 100)
-    })
-
-    SH_event.on('edit_host', (host) => {
-      this.current_host = host
-      this.setState({
-        show: true,
-        add: false,
-        where: host.where || 'local',
-        title: host.title || '',
-        url: host.url || '',
-        last_refresh: host.last_refresh || null,
-        refresh_interval: host.refresh_interval || 0,
-      })
-      setTimeout(() => {
-        this.tryToFocus()
-      }, 100)
-    })
-
-    SH_event.on('loading_done', (old_host, data) => {
-      if (old_host === this.current_host) {
-        this.setState({
-          last_refresh: data.last_refresh,
-          is_loading: false,
-        })
-        SH_event.emit('host_refreshed', data, this.current_host)
-      }
-    })
-  }
-
-  onOK () {
-    this.setState({
-      title: (this.state.title || '').replace(/^\s+|\s+$/g, ''),
-      url: (this.state.url || '').replace(/^\s+|\s+$/g, ''),
-    })
-
-    if (this.state.title === '') {
-      this.refs.title.focus()
-      return false
-    }
-    if (this.state.where === 'remote' && this.state.url === '') {
-      this.refs.url.focus()
-      return false
-    }
-
-    let data = Object.assign({}, this.current_host, this.state,
-      this.state.add ? {
-        content: `# ${this.state.title}`,
-        on: false,
-      } : {})
-
-    if (!data.id) data.id = util.makeId()
-
-    delete data['add']
-    SH_event.emit('host_' + (this.state.add ? 'add' : 'edit') + 'ed', data,
-      this.current_host)
-
-    this.setState({
-      show: false,
-    })
-    this.clear()
-  }
-
-  onCancel () {
-    this.setState({
-      show: false,
-    })
-    this.clear()
-  }
-
-  confirmDel () {
-    if (!confirm(SH_Agent.lang.confirm_del)) return
-    SH_event.emit('del_host', this.current_host)
-    this.setState({
-      show: false,
-    })
-    this.clear()
-  }
-
-  static getRefreshOptions () {
-    let k = [
-      [0, `${SH_Agent.lang.never}`],
-      [1, `1 ${SH_Agent.lang.hour}`],
-      [24, `24 ${SH_Agent.lang.hours}`],
-      [168, `7 ${SH_Agent.lang.days}`],
-    ]
-    if (IS_DEV) {
-      k.splice(1, 0, [0.002778, `10s (for DEV)`]) // dev test only
-    }
-    return k.map(([v, n], idx) => {
-      return (
-        <option value={v} key={idx}>{n}</option>
-      )
-    })
-  }
-
-  getEditOperations () {
-    if (this.state.add) return null
-
-    return (
-      <div>
-        <div className="ln">
-          <a href="#" className="del"
-             onClick={this.confirmDel.bind(this)}
-          >
-            <i className="iconfont icon-delete"/>
-            <span>{SH_Agent.lang.del_host}</span>
-          </a>
-        </div>
-      </div>
-    )
-  }
-
-  refresh () {
-    if (this.state.is_loading) return
-
-    SH_event.emit('check_host_refresh', this.current_host, true)
-    this.setState({
-      is_loading: true,
-    }, () => {
-      setTimeout(() => {
-        this.setState({
-          is_loading: false,
-        })
-      }, 1000)
-    })
-
-  }
-
-  renderGroup () {
-    if (this.state.where !== 'group') return null
-
-    return <Group hosts={this.props.hosts}/>
-  }
-
-  renderRemoteInputs () {
-    if (this.state.where !== 'remote') return null
-
-    return (
-      <div className="remote-ipts">
-        <div className="ln">
-          <div className="title">{SH_Agent.lang.url}</div>
-          <div className="cnt">
-            <input
-              type="text"
-              ref="url"
-              value={this.state.url}
-              placeholder="http://"
-              onChange={(e) => this.setState({url: e.target.value})}
-              onKeyDown={(e) => (e.keyCode === 13 && this.onOK()) ||
-              (e.keyCode === 27 && this.onCancel())}
-            />
-          </div>
-        </div>
-        <div className="ln">
-          <div className="title">{SH_Agent.lang.auto_refresh}</div>
-          <div className="cnt">
-            <select
-              value={this.state.refresh_interval}
-              onChange={(e) => this.setState(
-                {refresh_interval: parseFloat(e.target.value) || 0})}
-            >
-              {EditPrompt.getRefreshOptions()}
-            </select>
-
-            <i
-              className={classnames({
-                iconfont: 1,
-                'icon-refresh': 1,
-                'invisible': !this.current_host ||
-                this.state.url != this.current_host.url,
-                'loading': this.state.is_loading,
-              })}
-              title={SH_Agent.lang.refresh}
-              onClick={() => this.refresh()}
-            />
-
-            <span className="last-refresh">
-                            {SH_Agent.lang.last_refresh}
-              {this.state.last_refresh || 'N/A'}
-                        </span>
-          </div>
-        </div>
-      </div>
-    )
-  }
-
-  body () {
-    return (
-      <div ref="body">
-        <div className="ln">
-          <input id="ipt-local" type="radio" name="where" value="local"
-                 checked={this.state.where === 'local'}
-                 onChange={(e) => this.setState({where: e.target.value})}
-          />
-          <label htmlFor="ipt-local">{SH_Agent.lang.where_local}</label>
-          <input id="ipt-remote" type="radio" name="where" value="remote"
-                 checked={this.state.where === 'remote'}
-                 onChange={(e) => this.setState({where: e.target.value})}
-          />
-          <label htmlFor="ipt-remote">{SH_Agent.lang.where_remote}</label>
-          <input id="ipt-remote" type="radio" name="where" value="group"
-                 checked={this.state.where === 'group'}
-                 onChange={(e) => this.setState({where: e.target.value})}
-          />
-          <label htmlFor="ipt-remote">{SH_Agent.lang.where_group}</label>
-        </div>
-        <div className="ln">
-          <div className="title">{SH_Agent.lang.host_title}</div>
-          <div className="cnt">
-            <input
-              type="text"
-              ref="title"
-              name="text"
-              value={this.state.title}
-              onChange={(e) => this.setState({title: e.target.value})}
-              onKeyDown={(e) => (e.keyCode === 13 && this.onOK() ||
-              e.keyCode === 27 && this.onCancel())}
-            />
-          </div>
-        </div>
-        {this.renderRemoteInputs()}
-        {this.renderGroup()}
-        {this.getEditOperations()}
-      </div>
-    )
-  }
-
-  render () {
-    return (
-      <MyFrame
-        show={this.state.show}
-        head={SH_Agent.lang[this.state.add ? 'add_host' : 'edit_host']}
-        body={this.body()}
-        onOK={() => this.onOK()}
-        onCancel={() => this.onCancel()}
-      />
-    )
-  }
-}

+ 0 - 55
src1/ui2/components/frame/edit.less

@@ -1,55 +0,0 @@
-@keyframes loading {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
-
-.frame {
-  label {
-    padding: 0 4em 0 0.5em;
-  }
-
-  .spiner {
-    transform-origin: right center;
-    animation: spin 1s;
-    animation-iteration-count: 1;
-    -webkit-animation-iteration-count: 1;
-  }
-
-  .ln {
-    i.icon-refresh {
-      display: inline-block;
-      color: #999;
-      margin: 0 0.6em;
-      cursor: pointer;
-
-      &:hover {
-        color: #333;
-      }
-
-      &.loading {
-        animation: loading 1s infinite linear;
-      }
-
-      &.invisible {
-        visibility: hidden;
-      }
-    }
-  }
-
-  .last-refresh {
-    //padding-left: 1em;
-    color: #999;
-  }
-
-  a.del {
-    color: red;
-
-    span {
-      padding-left: 0.5em;
-    }
-  }
-}

+ 0 - 73
src1/ui2/components/frame/frame.js

@@ -1,73 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import './frame.less';
-
-export default class MyFrame extends React.Component {
-    constructor(props) {
-        super(props);
-    }
-
-    componentDidMount() {
-        SH_event.on('esc', () => {
-            this.onCancel();
-        });
-    }
-
-    onOK() {
-        this.props.onOK();
-    }
-
-    onCancel() {
-        this.props.onCancel();
-    }
-
-    renderFootButtons() {
-        let html = [];
-
-        html.push(
-            <div
-                className="button btn-cancel"
-                key="btn-cancel"
-                onClick={this.onCancel.bind(this)}
-            >
-                {this.props.cancel_title || SH_Agent.lang.cancel}
-            </div>
-        );
-
-        html.push(
-            <div
-                className="button btn-ok btn-default"
-                key="btn-ok"
-                onClick={this.onOK.bind(this)}
-            >
-                {this.props.ok_title || SH_Agent.lang.ok}
-            </div>
-        );
-
-        return html;
-    }
-
-
-    render() {
-        if (!this.props.show) {
-            return null;
-        }
-
-        return (
-            <div className="frame" ref="frame">
-                <div className="overlay"></div>
-                <div className="prompt">
-                    <div className="head">{this.props.head}</div>
-                    <div className="body">{this.props.body}</div>
-                    <div className="foot">{this.renderFootButtons()}</div>
-                </div>
-            </div>
-        );
-    }
-}

+ 0 - 108
src1/ui2/components/frame/frame.less

@@ -1,108 +0,0 @@
-.frame {
-  @bg: #f5f5f5;
-  @btn_default: #05a;
-  @lh: 24px;
-
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-
-  .overlay {
-    position: absolute;
-    z-index: -1;
-    width: 100%;
-    height: 100%;
-    background: #000;
-    opacity: 0.5;
-  }
-
-  .prompt {
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    min-width: 300px;
-    max-width: 600px;
-    background: #fff;
-    box-shadow: 0 0 4px 4px rgba(0, 0, 0, 0.1);
-
-    .head {
-      padding: 20px;
-      font-size: 16px;
-      background: @bg;
-      //border-bottom: solid 1px #ccc;
-    }
-
-    .body {
-      padding: 20px 20px;
-
-      .ln {
-        line-height: 30px;
-        padding: 2px 0;
-
-        .title {
-          float: left;
-          width: 100px;
-          line-height: @lh;
-        }
-        .cnt {
-          margin-left: 100px;
-          line-height: @lh;
-          input[type=text] {
-            width: 240px;
-            outline: none;
-            padding: 6px 10px;
-          }
-          textarea {
-            font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
-          }
-        }
-
-        .inform {
-          color: #999;
-          line-height: @lh;
-        }
-      }
-
-      input {
-        padding: 6px 4px;
-      }
-
-      input[type=password] {
-        letter-spacing: 8px;
-        width: 240px;
-        outline: none;
-        padding: 6px 10px;
-      }
-    }
-
-    .foot {
-      padding: 20px;
-      background: @bg;
-      text-align: right;
-
-      .button {
-        display: inline-block;
-        background: #ccc;
-        padding: 8px 20px;
-        margin-left: 1em;
-        cursor: pointer;
-
-        &:hover {
-          background: #ddd;
-        }
-
-        &.btn-default {
-          background: @btn_default;
-          color: #fff;
-
-          &:hover {
-            background: @btn_default * 1.4;
-          }
-        }
-      }
-    }
-  }
-}

+ 0 - 95
src1/ui2/components/frame/group.js

@@ -1,95 +0,0 @@
-/**
- * @author oldj
- * @blog https://oldj.net
- */
-
-'use strict'
-
-import React from 'react'
-import classnames from 'classnames'
-import Sortable from 'sortablejs'
-import listToArray from 'wheel-js/src/common/list-to-array'
-import './group.less'
-
-export default class Group extends React.Component {
-  constructor (props) {
-    super(props)
-
-    this.state = {
-      list: this.props.hosts.list
-    }
-
-    this.current_host = null
-  }
-
-  makeItem (item) {
-    let attrs = {
-      'data-id': 'id:' + (item.id || '')
-    }
-    return (
-      <div className="hosts-item" {...attrs}>
-        <i className={classnames({
-          'iconfont': 1
-          , 'item-icon': 1
-          , 'icon-file': item.where !== 'group'
-          , 'icon-files': item.where === 'group'
-        })}
-        />
-        <span>{item.title}</span>
-      </div>
-    )
-  }
-
-  makeList () {
-    let items = this.state.list
-      .filter(item => item.where !== 'group')
-      .map(item => this.makeItem(item))
-
-    return (
-      <div id="hosts-group-valid">
-        <div ref="group_valid" className="hosts-group-list">
-          {items}
-        </div>
-      </div>
-    )
-  }
-
-  currentList () {
-    return (
-      <div id="hosts-group-current">
-        <div ref="group_current" className="hosts-group-list"></div>
-      </div>
-    )
-  }
-
-  getCurrentListFromDOM () {
-    let nodes = this.refs.group_current.getElementsByClassName('hosts-item')
-    nodes = listToArray(nodes)
-    console.log(nodes)
-  }
-
-  componentDidMount () {
-    Sortable.create(this.refs.group_valid, {
-      group: 'sorting'
-      , sort: false
-    })
-
-    Sortable.create(this.refs.group_current, {
-      group: 'sorting'
-      , sort: true
-      , onSort: evt => {
-        this.getCurrentListFromDOM()
-      }
-    })
-  }
-
-  render () {
-    return (
-      <div id="hosts-group">
-        {this.makeList()}
-        <div className="arrow"/>
-        {this.currentList()}
-      </div>
-    )
-  }
-}

+ 0 - 62
src1/ui2/components/frame/group.less

@@ -1,62 +0,0 @@
-#hosts-group {
-  @h: 160px;
-
-  position: relative;
-  margin-top: 20px;
-  height: @h + 2px;
-  overflow: hidden;
-
-  &::after {
-    content: '';
-    clear: both;
-  }
-
-  .arrow {
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    width: 20px;
-    height: 20px;
-    line-height: 20px;
-    text-align: center;
-    transform: translate(-50%, -50%);
-
-    &::after {
-      content: '→';
-    }
-  }
-
-  .hosts-group-list {
-    height: @h;
-    overflow: auto;
-    border: solid 1px #ccc;
-
-    .hosts-item {
-      cursor: move;
-      padding: 2px 6px;
-
-      &:hover {
-        background: #f5f5f5;
-      }
-
-      i {
-        font-size: 12px;
-        color: #999;
-      }
-
-      & > span {
-        padding-left: 6px;
-      }
-    }
-  }
-}
-
-#hosts-group-valid {
-  width: 45%;
-  float: left;
-}
-
-#hosts-group-current {
-  width: 45%;
-  float: right;
-}

+ 0 - 239
src1/ui2/components/frame/preferences.js

@@ -1,239 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-import React from 'react';
-import Frame from './frame';
-import classnames from 'classnames';
-import './preferences.less';
-import lang from '../../lang';
-import util from '../../libs/util';
-const current_version = require('../../../version').version;
-
-const AUTO_LAUNCH = 'auto_launch';
-
-export default class PreferencesPrompt extends React.Component {
-    constructor(props) {
-        super(props);
-
-        let choice_mode = SH_Agent.pref.get('choice_mode');
-        if (!choice_mode || (choice_mode != 'multiple' && choice_mode != 'single')) {
-            choice_mode = 'multiple';
-        }
-
-        this.state = {
-            show: false,
-            lang_key: SH_Agent.lang_key,
-            after_cmd: SH_Agent.pref.get('after_cmd') || '',
-            choice_mode: choice_mode,
-            auto_launch: !!SH_Agent.pref.get(AUTO_LAUNCH),
-            hide_at_launch: !!SH_Agent.pref.get('hide_at_launch'),
-            update_found: false // 发现新版本
-        };
-
-    }
-
-    componentDidMount() {
-        SH_event.on('show_preferences', () => {
-            this.setState({
-                show: true
-            });
-        });
-        ipcRenderer.on('show_preferences', () => {
-            this.setState({
-                show: true
-            });
-        });
-
-        ipcRenderer.on('update_found', (v) => {
-            console.log(v);
-            this.setState({
-                update_found: true
-            });
-        });
-    }
-
-    onOK() {
-        this.setState({
-            show: false
-        }, () => {
-            setTimeout(() => {
-                SH_Agent.relaunch();
-            }, 200);
-        });
-    }
-
-    onCancel() {
-        this.setState({
-            show: false
-        });
-    }
-
-    static getLanguageOptions() {
-        return lang.lang_list.map(({key, name}, idx) => {
-            return (
-                <option value={key} key={idx}>{name}</option>
-            );
-        });
-    }
-
-    updateLangKey(v) {
-        SH_Agent.lang_key = v;
-        SH_Agent.pref.set('user_language', v);
-        this.setState({
-            lange_key: v
-        });
-    }
-
-    updateChoiceMode(v) {
-        SH_Agent.pref.set('choice_mode', v);
-        this.setState({
-            choice_mode: v
-        });
-    }
-
-    updateAfterCmd(v) {
-        SH_Agent.pref.set('after_cmd', v);
-        this.setState({
-            after_cmd: v
-        });
-    }
-
-    updateAutoLaunch(v) {
-        SH_Agent.pref.set(AUTO_LAUNCH, v);
-        this.setState({
-            auto_launch: v
-        });
-
-        // todo set auto launch
-    }
-
-    updateMinimizeAtLaunch(v) {
-        SH_Agent.pref.set('hide_at_launch', v);
-        this.setState({
-            hide_at_launch: v
-        });
-    }
-
-    prefLanguage() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.language}</div>
-                <div className="cnt">
-                    <select
-                        value={SH_Agent.lang_key}
-                        onChange={(e) => this.updateLangKey(e.target.value)}
-                    >
-                        {PreferencesPrompt.getLanguageOptions()}
-                    </select>
-
-                    <div className="inform">{SH_Agent.lang.should_restart_after_change_language}</div>
-                </div>
-            </div>
-        )
-    }
-
-    prefChoiceMode() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.pref_choice_mode}</div>
-                <div className="cnt">
-                    <input type="radio" id="pref-choice-mode-single" name="choice_mode" value="single"
-                           defaultChecked={this.state.choice_mode === 'single'}
-                           onChange={(e) => this.updateChoiceMode(e.target.value)}
-                    />
-                    <label htmlFor="pref-choice-mode-single">{SH_Agent.lang.pref_choice_mode_single}</label>
-                    <input type="radio" id="pref-choice-mode-multiple" name="choice_mode" value="multiple"
-                           defaultChecked={this.state.choice_mode === 'multiple'}
-                           onChange={(e) => this.updateChoiceMode(e.target.value)}
-                    />
-                    <label htmlFor="pref-choice-mode-multiple">{SH_Agent.lang.pref_choice_mode_multiple}</label>
-                </div>
-            </div>
-        )
-    }
-
-    prefAfterCmd() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.pref_after_cmd}</div>
-                <div className="cnt">
-                    <div className="inform">{SH_Agent.lang.pref_after_cmd_info}</div>
-                    <textarea
-                        name=""
-                        defaultValue={this.state.after_cmd}
-                        placeholder={SH_Agent.lang.pref_after_cmd_placeholder}
-                        onChange={(e) => this.updateAfterCmd(e.target.value)}
-                    />
-                </div>
-            </div>
-        )
-    }
-
-    prefAutoLaunch() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.auto_launch}</div>
-                <div className="cnt">
-                    <input type="checkbox" name=""
-                           defaultChecked={this.state.auto_launch}
-                           onChange={(e) => this.updateAutoLaunch(e.target.checked)}
-                    />
-                </div>
-            </div>
-        )
-    }
-
-    prefMinimizeAtLaunch() {
-        return (
-            <div className="ln">
-                <div className="title">{SH_Agent.lang.hide_at_launch}</div>
-                <div className="cnt">
-                    <input type="checkbox" name=""
-                           defaultChecked={this.state.hide_at_launch}
-                           onChange={(e) => this.updateMinimizeAtLaunch(e.target.checked)}
-                    />
-                </div>
-            </div>
-        )
-    }
-
-    openDownloadPage() {
-        ipcRenderer.send('open_url', require('../../configs').url_download);
-    }
-
-    body() {
-        return (
-            <div ref="body">
-                {/*<div className="title">{SH_Agent.lang.host_title}</div>*/}
-                {/*<div className="cnt">*/}
-                {/*</div>*/}
-                <div className={classnames("current-version", {"update-found": this.state.update_found})}>
-                    <a href="#" onClick={this.openDownloadPage}>{util.formatVersion(current_version)}</a>
-                </div>
-                {this.prefLanguage()}
-                {this.prefChoiceMode()}
-                {this.prefAfterCmd()}
-                {/*{this.prefAutoLaunch()}*/}
-                {this.prefMinimizeAtLaunch()}
-            </div>
-        )
-    }
-
-    render() {
-        return (
-            <Frame
-                show={this.state.show}
-                head={SH_Agent.lang.preferences}
-                body={this.body()}
-                onOK={() => this.onOK()}
-                onCancel={() => this.onCancel()}
-                cancel_title={SH_Agent.lang.set_and_back}
-                ok_title={SH_Agent.lang.set_and_relaunch_app}
-            />
-        );
-    }
-}

Some files were not shown because too many files changed in this diff