@electerm/electerm-react 1.34.50 → 1.34.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,6 +34,7 @@ export default {
34
34
  useSystemTitleBar: false,
35
35
  opacity: 1,
36
36
  defaultEditor: '',
37
+ terminalWordSeparator: './\\()"\'-:,.;<>~!@#$%^&*|+=[]{}`~ ?',
37
38
  confirmBeforeExit: false,
38
39
  initDefaultTabOnStart: true,
39
40
  screenReaderMode: false,
@@ -46,6 +46,7 @@ window.log = {
46
46
  }
47
47
 
48
48
  window.pre = {
49
+ requireAuth: runSync('shouldAuth'),
49
50
  readClipboard: () => {
50
51
  return runSync('readClipboard')
51
52
  },
@@ -0,0 +1,127 @@
1
+ import { Component } from '../common/react-subx'
2
+ import LogoElem from '../common/logo-elem.jsx'
3
+ import store from '../../store'
4
+ import {
5
+ Input,
6
+ message,
7
+ Spin
8
+ } from 'antd'
9
+ import {
10
+ ArrowRightOutlined
11
+ } from '@ant-design/icons'
12
+ import Main from '../main/main.jsx'
13
+ import './login.styl'
14
+
15
+ const { prefix } = window
16
+ const f = prefix('form')
17
+
18
+ export default class Login extends Component {
19
+ state = {
20
+ pass: '',
21
+ logined: !window.pre.requireAuth,
22
+ loading: false
23
+ }
24
+
25
+ componentDidMount () {
26
+ this.init()
27
+ }
28
+
29
+ init = async () => {
30
+ if (!window.pre.requireAuth) {
31
+ return
32
+ }
33
+ const globs = await window.pre.runGlobalAsync('init')
34
+ window.et.globs = globs
35
+ }
36
+
37
+ handlePassChange = e => {
38
+ this.setState({
39
+ pass: e.target.value
40
+ })
41
+ }
42
+
43
+ handleSubmit = () => {
44
+ const {
45
+ pass
46
+ } = this.state
47
+ if (!pass) {
48
+ return message.warning('password required')
49
+ } else if (
50
+ this.submitting
51
+ ) {
52
+ return
53
+ }
54
+ this.login(
55
+ this.state.pass
56
+ )
57
+ }
58
+
59
+ login = async (pass) => {
60
+ this.submitting = true
61
+ const r = await window.pre.runGlobalAsync('checkPassword', pass)
62
+ if (r) {
63
+ this.setState({
64
+ logined: true,
65
+ loading: false
66
+ })
67
+ } else {
68
+ message.error('Login failed')
69
+ this.setState({
70
+ loading: false
71
+ })
72
+ }
73
+ this.submitting = false
74
+ }
75
+
76
+ renderAfter = () => {
77
+ return (
78
+ <ArrowRightOutlined
79
+ className='mg1x pointer'
80
+ onClick={this.handleSubmit}
81
+ />
82
+ )
83
+ }
84
+
85
+ renderLogin () {
86
+ const {
87
+ pass,
88
+ loading
89
+ } = this.state
90
+ return (
91
+ <div className='login-wrap'>
92
+ <div className='pd3 aligncenter'>
93
+ <LogoElem />
94
+ <div className='pd3 aligncenter'>
95
+ <Input.Password
96
+ value={pass}
97
+ readOnly={loading}
98
+ onChange={this.handlePassChange}
99
+ placeholder={f('password')}
100
+ addonAfter={this.renderAfter()}
101
+ onPressEnter={this.handleSubmit}
102
+ />
103
+ </div>
104
+ <div className='aligncenter'>
105
+ <Spin
106
+ spinning={loading}
107
+ />
108
+ </div>
109
+ </div>
110
+ </div>
111
+ )
112
+ }
113
+
114
+ render () {
115
+ const {
116
+ logined
117
+ } = this.state
118
+ if (!logined) {
119
+ return this.renderLogin()
120
+ }
121
+ return (
122
+ <Main
123
+ store={store}
124
+ />
125
+ )
126
+ }
127
+ }
@@ -0,0 +1,7 @@
1
+ .login-wrap
2
+ position fixed
3
+ left 0
4
+ top 0
5
+ width 100%
6
+ height 100%
7
+ background #fff
@@ -1,11 +1,10 @@
1
1
  import ErrorBoundary from './error-wrapper'
2
- import Main from './main'
3
- import store from '../../store'
2
+ import Login from '../auth/login'
4
3
 
5
4
  export default function MainEntry () {
6
5
  return (
7
6
  <ErrorBoundary>
8
- <Main store={store} />
7
+ <Login />
9
8
  </ErrorBoundary>
10
9
  )
11
10
  }
@@ -6,7 +6,7 @@ import copy from 'json-deep-copy'
6
6
  export default class QmTransport extends BookmarkTransport {
7
7
  beforeUpload = async (file) => {
8
8
  const { store } = this.props
9
- const txt = await window.fs.readFileSync(file.path)
9
+ const txt = await window.fs.readFile(file.path)
10
10
  try {
11
11
  const quickCommands = JSON.parse(txt)
12
12
  const quickCommandsOld = copy(store.quickCommands)
@@ -1,5 +1,9 @@
1
1
  import React, { Component } from 'react'
2
- import { CodeOutlined, LoadingOutlined } from '@ant-design/icons'
2
+ import {
3
+ CodeOutlined,
4
+ ArrowRightOutlined,
5
+ LoadingOutlined
6
+ } from '@ant-design/icons'
3
7
  import {
4
8
  message,
5
9
  Select,
@@ -31,6 +35,7 @@ import mapper from '../../common/auto-complete-data-mapper'
31
35
  import StartSession from './start-session-select'
32
36
  import HelpIcon from '../common/help-icon'
33
37
  import fs from '../../common/fs'
38
+ import delay from '../../common/wait.js'
34
39
  import './setting.styl'
35
40
 
36
41
  const { Option } = Select
@@ -57,7 +62,12 @@ const keys = [
57
62
  export default class Setting extends Component {
58
63
  state = {
59
64
  ready: false,
60
- languageChanged: false
65
+ languageChanged: false,
66
+ passwordChanged: false,
67
+ submittingPass: false,
68
+ passInputFocused: false,
69
+ placeholderLogin: window.pre.requireAuth ? '********' : f('notSet'),
70
+ loginPass: ''
61
71
  }
62
72
 
63
73
  componentDidMount () {
@@ -70,6 +80,65 @@ export default class Setting extends Component {
70
80
 
71
81
  componentWillUnmount () {
72
82
  clearTimeout(this.timer)
83
+ clearTimeout(this.timer1)
84
+ }
85
+
86
+ handleLoginSubmit = async () => {
87
+ if (this.submitting) {
88
+ return
89
+ }
90
+ this.submitting = true
91
+ this.setState({
92
+ submittingPass: true
93
+ })
94
+ const pass = this.state.loginPass
95
+ const r = await window.pre.runGlobalAsync(
96
+ 'setPassword',
97
+ pass
98
+ )
99
+ await delay(600)
100
+ if (r === true) {
101
+ window.pre.requireAuth = !!pass
102
+ this.setState({
103
+ loginPass: pass ? '********' : '',
104
+ submittingPass: false,
105
+ passwordChanged: true,
106
+ placeholderLogin: pass ? '********' : f('notSet')
107
+ }, () => {
108
+ this.submitting = false
109
+ })
110
+ message.success('OK')
111
+ } else {
112
+ this.setState({
113
+ submittingPass: false
114
+ }, () => {
115
+ this.submitting = false
116
+ })
117
+ }
118
+ }
119
+
120
+ handleLoginPassFocus = () => {
121
+ this.setState({
122
+ passInputFocused: true
123
+ })
124
+ }
125
+
126
+ blurPassInput = () => {
127
+ this.setState({
128
+ passInputFocused: false
129
+ })
130
+ }
131
+
132
+ handleLoginPassBlur = () => {
133
+ this.timer1 = setTimeout(
134
+ this.blurPassInput, 300
135
+ )
136
+ }
137
+
138
+ handleChangeLoginPass = e => {
139
+ this.setState({
140
+ loginPass: e.target.value
141
+ })
73
142
  }
74
143
 
75
144
  handleRestart = () => {
@@ -182,8 +251,8 @@ export default class Setting extends Component {
182
251
  )
183
252
  }
184
253
 
185
- renderLanguageChangeTip = () => {
186
- if (!this.state.languageChanged) {
254
+ renderRestart = (name) => {
255
+ if (!this.state[name]) {
187
256
  return null
188
257
  }
189
258
  return (
@@ -617,6 +686,57 @@ export default class Setting extends Component {
617
686
  }
618
687
  }
619
688
 
689
+ renderLoginPassAfter () {
690
+ const {
691
+ loginPass,
692
+ submittingPass,
693
+ passInputFocused
694
+ } = this.state
695
+ if (!loginPass && !passInputFocused) {
696
+ return null
697
+ } else if (
698
+ submittingPass
699
+ ) {
700
+ return <LoadingOutlined />
701
+ }
702
+ return (
703
+ <ArrowRightOutlined
704
+ className='pointer'
705
+ onClick={this.handleLoginSubmit}
706
+ />
707
+ )
708
+ }
709
+
710
+ renderLoginPass () {
711
+ if (window.et.isWebApp) {
712
+ return null
713
+ }
714
+ const {
715
+ loginPass,
716
+ submittingPass,
717
+ placeholderLogin
718
+ } = this.state
719
+ const props = {
720
+ value: loginPass,
721
+ disabled: submittingPass,
722
+ onFocus: this.handleLoginPassFocus,
723
+ onBlur: this.handleLoginPassBlur,
724
+ onChange: this.handleChangeLoginPass,
725
+ addonAfter: this.renderLoginPassAfter(),
726
+ placeholder: placeholderLogin
727
+ }
728
+ return (
729
+ <div>
730
+ <div className='pd1b'>{f('loginPassword')}</div>
731
+ <div className='pd2b'>
732
+ <Input.Password
733
+ {...props}
734
+ />
735
+ </div>
736
+ </div>
737
+ )
738
+ }
739
+
620
740
  render () {
621
741
  const { ready } = this.state
622
742
  if (!ready) {
@@ -746,7 +866,7 @@ export default class Setting extends Component {
746
866
  </Select>
747
867
  <Link className='mg1l' to={createEditLangLink(language)}>{p('edit')}</Link>
748
868
  </div>
749
- {this.renderLanguageChangeTip()}
869
+ {this.renderRestart('languageChanged')}
750
870
  <div className='pd1y font16 bold'>
751
871
  <CodeOutlined className='mg1r' />
752
872
  {s('terminal')} {e('settings')}
@@ -789,9 +909,9 @@ export default class Setting extends Component {
789
909
  {
790
910
  this.renderTerminalBgSelect('terminalBackgroundImagePath')
791
911
  }
792
- <div className='pd1b'>{t('default')} {e('editorTip')}</div>
912
+ <div className='pd1b'>{e('terminalWordSeparator')}</div>
793
913
  {
794
- this.renderText('defaultEditor', e('editorTip'))
914
+ this.renderText('terminalWordSeparator', e('terminalWordSeparator'))
795
915
  }
796
916
  <div className='pd1b'>{t('default')} {e('execWindows')}</div>
797
917
  {
@@ -829,6 +949,8 @@ export default class Setting extends Component {
829
949
  {this.renderToggle('saveTerminalLogToFile', (
830
950
  <ShowItem to={terminalLogPath} className='mg1l'>{p('open')}</ShowItem>
831
951
  ))}
952
+
953
+ {this.renderLoginPass()}
832
954
  {this.renderReset()}
833
955
  </div>
834
956
  )
@@ -808,6 +808,7 @@ export default class Term extends Component {
808
808
  theme: themeConfig,
809
809
  allowTransparency: true,
810
810
  // lineHeight: 1.2,
811
+ wordSeparator: config.terminalWordSeparator,
811
812
  cursorStyle: config.cursorStyle,
812
813
  cursorBlink: config.cursorBlink,
813
814
  fontSize: tab.fontSize || config.fontSize,
@@ -9,6 +9,6 @@
9
9
  .ant-tree-indent-unit
10
10
  width 5px
11
11
  .ant-tree .ant-tree-switcher.ant-tree-switcher-noop
12
- width 18px
12
+ width 0px
13
13
  td.ant-table-column-sort
14
14
  background none
@@ -2,7 +2,7 @@ import { render } from 'react-dom'
2
2
  import 'antd/dist/reset.css'
3
3
  import 'xterm/css/xterm.css'
4
4
  import '../common/trzsz'
5
- import Main from '../components/main'
5
+ import Main from '../components/main/index.jsx'
6
6
  import { notification } from 'antd'
7
7
  notification.config({
8
8
  placement: 'bottomRight'
@@ -83,8 +83,8 @@ export default Store => {
83
83
 
84
84
  Store.prototype.runBatchOp = function (path) {
85
85
  window.store.showModal = modals.batchOps
86
- function updateText () {
87
- const text = window.pre.readFileSync(path).toString()
86
+ async function updateText () {
87
+ const text = await window.fs.readFile(path)
88
88
  postMessage({
89
89
  action: commonActions.batchOp,
90
90
  batchOp: {
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { Modal } from 'antd'
6
6
  import delay from '../common/wait'
7
+ import initWatch from './watch'
7
8
 
8
9
  export default (Store) => {
9
10
  Store.prototype.checkForDbUpgrade = async function () {
@@ -13,6 +14,7 @@ export default (Store) => {
13
14
  }
14
15
  const shouldUpgrade = await window.pre.runGlobalAsync('checkDbUpgrade')
15
16
  if (!shouldUpgrade) {
17
+ initWatch(store)
16
18
  return false
17
19
  }
18
20
  const {
@@ -35,7 +37,7 @@ export default (Store) => {
35
37
  content: 'Database Upgraded',
36
38
  okButtonProps: {}
37
39
  })
38
- await delay(3000)
40
+ await delay(2000)
39
41
  mod.destroy()
40
42
  await store.restart()
41
43
  return true
@@ -3,7 +3,6 @@
3
3
  */
4
4
 
5
5
  import { dbNames, update, getData, fetchInitData, insert, remove } from '../common/db'
6
- import initWatch from './watch'
7
6
  import parseInt10 from '../common/parse-int10'
8
7
  import { infoTabs, statusMap, defaultEnvLang } from '../common/constants'
9
8
  import fs from '../common/fs'
@@ -142,7 +141,7 @@ export default (Store) => {
142
141
  }
143
142
  Store.prototype.initApp = async function () {
144
143
  const { store } = window
145
- const globs = await window.pre.runGlobalAsync('init')
144
+ const globs = window.et.globs || await window.pre.runGlobalAsync('init')
146
145
  window.langMap = globs.langMap
147
146
  store.installSrc = globs.installSrc
148
147
  store.appPath = globs.appPath
@@ -182,7 +181,6 @@ export default (Store) => {
182
181
  store.fetchItermThemes()
183
182
  store.openInitSessions()
184
183
  store.fetchSshConfigItems()
185
- initWatch(store)
186
184
  store.initCommandLine().catch(store.onError)
187
185
  if (store.config.checkUpdateOnStart) {
188
186
  store.onCheckUpdate()
@@ -356,7 +356,7 @@ export default (Store) => {
356
356
 
357
357
  Store.prototype.importAll = async function (file) {
358
358
  const txt = await window.fs
359
- .readFileSync(file.path)
359
+ .readFile(file.path)
360
360
  const { store } = window
361
361
  const objs = JSON.parse(txt)
362
362
  const toInsert = []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.34.50",
3
+ "version": "1.34.63",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",