@electerm/electerm-react 1.34.50 → 1.34.58

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,
@@ -57,7 +61,12 @@ const keys = [
57
61
  export default class Setting extends Component {
58
62
  state = {
59
63
  ready: false,
60
- languageChanged: false
64
+ languageChanged: false,
65
+ passwordChanged: false,
66
+ submittingPass: false,
67
+ passInputFocused: false,
68
+ placeholderLogin: window.pre.requireAuth ? '********' : f('notSet'),
69
+ loginPass: ''
61
70
  }
62
71
 
63
72
  componentDidMount () {
@@ -70,6 +79,61 @@ export default class Setting extends Component {
70
79
 
71
80
  componentWillUnmount () {
72
81
  clearTimeout(this.timer)
82
+ clearTimeout(this.timer1)
83
+ }
84
+
85
+ handleLoginSubmit = async () => {
86
+ if (this.submitting) {
87
+ return
88
+ }
89
+ this.setState({
90
+ submittingPass: true
91
+ })
92
+ this.submitting = true
93
+ const pass = this.state.loginPass
94
+ const r = await window.pre.runGlobalAsync(
95
+ 'setPassword',
96
+ pass
97
+ )
98
+ if (r === true) {
99
+ window.pre.requireAuth = !!pass
100
+ this.setState({
101
+ loginPass: pass ? '********' : '',
102
+ submittingPass: false,
103
+ passwordChanged: true,
104
+ placeholderLogin: pass ? '********' : f('notSet')
105
+ })
106
+ message.success('OK')
107
+ } else {
108
+ this.setState({
109
+ submittingPass: false
110
+ })
111
+ }
112
+ this.submitting = false
113
+ }
114
+
115
+ handleLoginPassFocus = () => {
116
+ this.setState({
117
+ passInputFocused: true
118
+ })
119
+ }
120
+
121
+ blurPassInput = () => {
122
+ this.setState({
123
+ passInputFocused: false
124
+ })
125
+ }
126
+
127
+ handleLoginPassBlur = () => {
128
+ this.timer1 = setTimeout(
129
+ this.blurPassInput, 300
130
+ )
131
+ }
132
+
133
+ handleChangeLoginPass = e => {
134
+ this.setState({
135
+ loginPass: e.target.value
136
+ })
73
137
  }
74
138
 
75
139
  handleRestart = () => {
@@ -182,8 +246,8 @@ export default class Setting extends Component {
182
246
  )
183
247
  }
184
248
 
185
- renderLanguageChangeTip = () => {
186
- if (!this.state.languageChanged) {
249
+ renderRestart = (name) => {
250
+ if (!this.state[name]) {
187
251
  return null
188
252
  }
189
253
  return (
@@ -617,6 +681,57 @@ export default class Setting extends Component {
617
681
  }
618
682
  }
619
683
 
684
+ renderLoginPassAfter () {
685
+ const {
686
+ loginPass,
687
+ submittingPass,
688
+ passInputFocused
689
+ } = this.state
690
+ if (!loginPass && !passInputFocused) {
691
+ return null
692
+ } else if (
693
+ submittingPass
694
+ ) {
695
+ return <LoadingOutlined />
696
+ }
697
+ return (
698
+ <ArrowRightOutlined
699
+ className='pointer'
700
+ onClick={this.handleLoginSubmit}
701
+ />
702
+ )
703
+ }
704
+
705
+ renderLoginPass () {
706
+ if (window.et.isWebApp) {
707
+ return null
708
+ }
709
+ const {
710
+ loginPass,
711
+ submittingPass,
712
+ placeholderLogin
713
+ } = this.state
714
+ const props = {
715
+ value: loginPass,
716
+ disabled: submittingPass,
717
+ onFocus: this.handleLoginPassFocus,
718
+ onBlur: this.handleLoginPassBlur,
719
+ onChange: this.handleChangeLoginPass,
720
+ addonAfter: this.renderLoginPassAfter(),
721
+ placeholder: placeholderLogin
722
+ }
723
+ return (
724
+ <div>
725
+ <div className='pd1b'>{f('loginPassword')}</div>
726
+ <div className='pd2b'>
727
+ <Input.Password
728
+ {...props}
729
+ />
730
+ </div>
731
+ </div>
732
+ )
733
+ }
734
+
620
735
  render () {
621
736
  const { ready } = this.state
622
737
  if (!ready) {
@@ -746,7 +861,7 @@ export default class Setting extends Component {
746
861
  </Select>
747
862
  <Link className='mg1l' to={createEditLangLink(language)}>{p('edit')}</Link>
748
863
  </div>
749
- {this.renderLanguageChangeTip()}
864
+ {this.renderRestart('languageChanged')}
750
865
  <div className='pd1y font16 bold'>
751
866
  <CodeOutlined className='mg1r' />
752
867
  {s('terminal')} {e('settings')}
@@ -789,9 +904,9 @@ export default class Setting extends Component {
789
904
  {
790
905
  this.renderTerminalBgSelect('terminalBackgroundImagePath')
791
906
  }
792
- <div className='pd1b'>{t('default')} {e('editorTip')}</div>
907
+ <div className='pd1b'>{e('terminalWordSeparator')}</div>
793
908
  {
794
- this.renderText('defaultEditor', e('editorTip'))
909
+ this.renderText('terminalWordSeparator', e('terminalWordSeparator'))
795
910
  }
796
911
  <div className='pd1b'>{t('default')} {e('execWindows')}</div>
797
912
  {
@@ -829,6 +944,8 @@ export default class Setting extends Component {
829
944
  {this.renderToggle('saveTerminalLogToFile', (
830
945
  <ShowItem to={terminalLogPath} className='mg1l'>{p('open')}</ShowItem>
831
946
  ))}
947
+
948
+ {this.renderLoginPass()}
832
949
  {this.renderReset()}
833
950
  </div>
834
951
  )
@@ -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: {
@@ -142,7 +142,7 @@ export default (Store) => {
142
142
  }
143
143
  Store.prototype.initApp = async function () {
144
144
  const { store } = window
145
- const globs = await window.pre.runGlobalAsync('init')
145
+ const globs = window.et.globs || await window.pre.runGlobalAsync('init')
146
146
  window.langMap = globs.langMap
147
147
  store.installSrc = globs.installSrc
148
148
  store.appPath = globs.appPath
@@ -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.58",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",