Skip to content

Commit f0043db

Browse files
author
chunqiuyiyu
committed
Add ipad support
1 parent e4bbefe commit f0043db

File tree

19 files changed

+192
-20
lines changed

19 files changed

+192
-20
lines changed

app/commons/Tab/TabBar.jsx

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import TabLabel from './TabLabel'
77
import Menu from 'components/Menu'
88
import ContextMenu from 'components/ContextMenu'
99
import i18n from 'utils/createI18n'
10-
10+
import * as SideBar from 'components/Panel/SideBar/actions'
11+
import config from 'config'
12+
import * as Panel from 'components/Panel/actions'
13+
import panelState from 'components/Panel/state'
1114

1215
@defaultProps(props => ({
1316
addTab: () => props.tabGroup.addTab(),
@@ -43,6 +46,7 @@ class TabBar extends Component {
4346
} = this.props
4447

4548
const tabBarId = `tab_bar_${tabGroup.id}`
49+
const size = panelState.panels.get('PANEL_BOTTOM').size
4650

4751
return (
4852
<div id={tabBarId}
@@ -67,12 +71,28 @@ class TabBar extends Component {
6771
</svg>
6872
</div>
6973
<div onDoubleClick={addTab} className='tab-dbclick-area' />
74+
{(!config.isPad || tabGroup.id !== 'terminalGroup')
75+
&& <div className='tab-show-list'
76+
style={{ marginBottom: '-2px' }}
77+
onClick={e => {
78+
e.stopPropagation()
79+
this.setState({ showDropdownMenu: !this.state.showDropdownMenu })
80+
}}
81+
>
82+
<i className='fa fa-ellipsis-h' />
83+
{this.renderDropdownMenu(size)}
84+
</div>}
85+
{tabGroup.id === 'terminalGroup' &&
7086
<div className='tab-show-list'
71-
onClick={(e) => { e.stopPropagation(); this.setState({ showDropdownMenu: true }) }}
87+
style={{ marginBottom: size ? '4px' : '-6px' }}
88+
onClick={e => {
89+
e.stopPropagation()
90+
!size ? Panel.expandPanel('PANEL_BOTTOM')
91+
: Panel.shrinkPanel('PANEL_BOTTOM')
92+
}}
7293
>
73-
<i className='fa fa-sort-desc' />
74-
{this.renderDropdownMenu()}
75-
</div>
94+
<i className={`fa fa-sort-${size ? 'desc' : 'asc'}`} />
95+
</div>}
7696
<ContextMenu
7797
items={contextMenuItems}
7898
isActive={this.state.showContextMenu}
@@ -88,20 +108,26 @@ class TabBar extends Component {
88108
e.stopPropagation()
89109
e.preventDefault()
90110

111+
const rects = e.target.getBoundingClientRect()
112+
const isPad = config.isPad
113+
91114
this.setState({
92115
showContextMenu: true,
93-
contextMenuPos: { x: e.clientX, y: e.clientY },
116+
contextMenuPos: {
117+
x: isPad ? rects.x : e.clientX,
118+
y: isPad ? rects.y : e.clientY
119+
},
94120
contextMenuContext: context,
95121
})
96122
}
97123

98-
renderDropdownMenu () {
124+
renderDropdownMenu (size) {
99125
if (!this.state.showDropdownMenu) return null
100126
const dropdownMenuItems = this.makeDropdownMenuItems()
101127
if (!dropdownMenuItems.length) return null
102-
return (<Menu className='top-down to-left'
128+
return (<Menu className={`${size ? 'top-down' : 'bottom-top'} to-left`}
129+
style={{ bottom: size ? 'initial' : '15px', right: '2px' }}
103130
items={dropdownMenuItems}
104-
style={{ right: '2px' }}
105131
deactivate={e => this.setState({ showDropdownMenu: false })}
106132
/>)
107133
}

app/commons/Tab/TabLabel.jsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as Modal from '../../components/Modal/actions'
99
import config from 'config'
1010
import dispatchCommand from 'commands/dispatchCommand'
1111
import { fileIconProviders } from 'components/FileTree/state'
12+
import { gtouchstart, gtouchend, gtouchmove } from 'utils/touch'
1213

1314
const closeFileTab = async (e, tab, removeTab, activateTab) => {
1415
e.stopPropagation()
@@ -87,7 +88,7 @@ let TabLabel = observer(({ tab, removeTab, activateTab, openContextMenu, dbClick
8788
id={tabLabelId}
8889
data-droppable='TABLABEL'
8990
draggable='true'
90-
onClick={e => activateTab(tab.id)}
91+
onClick={e => { activateTab(tab.id) }}
9192
onMouseUp={e => { e.button === 1 && removeTab(tab.id) }}
9293
onDoubleClick={() => {
9394
if (!tab.isActive) {
@@ -99,7 +100,13 @@ let TabLabel = observer(({ tab, removeTab, activateTab, openContextMenu, dbClick
99100
// Chrome 下直接执行 dragStart 会导致立即又出发了 window.dragend, 添加 timeout 以避免无法拖动的情况
100101
setTimeout(() => dnd.dragStart({ type: 'TAB', id: tab.id }), 0)
101102
}}
102-
onContextMenu={e => openContextMenu(e, tab)}
103+
onContextMenu={e => config.isPad ? '' : openContextMenu(e, tab)}
104+
onTouchStart={e => {
105+
e.persist()
106+
gtouchstart(() => { openContextMenu(e, tab) })
107+
}}
108+
onTouchEnd={gtouchend}
109+
onTouchMove={gtouchmove}
103110
>
104111
{dnd.target.id === tabLabelId ? <div className='tab-label-insert-pos'></div> : null}
105112
{tab.icon && <TabIcon fileName={tab.title} defaultIconStr={tab.icon} />}

app/commons/Tree/TreeNode.jsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { observer } from 'mobx-react'
55
import config from 'config'
66
import cx from 'classnames'
77
import dnd from 'utils/dnd'
8+
import { gtouchstart, gtouchend, gtouchmove } from 'utils/touch'
89
import icons from 'file-icons-js'
910
import { fileIconProviders } from 'components/FileTree/state'
1011

@@ -135,9 +136,20 @@ class TreeNode extends Component {
135136
})}
136137
data-droppable='FILE_TREE_NODE'
137138
onContextMenu={(e) => {
139+
if (config.isPad) return
138140
selectNode(node)
139141
openContextMenu(e, node)
140142
}}
143+
onTouchMove={gtouchmove}
144+
onTouchEnd={gtouchend}
145+
onTouchStart={e => {
146+
e.persist()
147+
gtouchstart(() => {
148+
selectNode(node)
149+
openContextMenu(e, node)
150+
})
151+
e.stopPropagation()
152+
}}
141153
draggable='true'
142154
onDragStart={(e) => {
143155
e.dataTransfer.effectAllowed = 'move'
@@ -151,17 +163,19 @@ class TreeNode extends Component {
151163
<div
152164
className={cx('filetree-node', { focus: node.isFocused })}
153165
ref={r => (this.nodeDOM = r)}
154-
onClick={e => selectNode(node)}
166+
onClick={e => {
167+
selectNode(node)
168+
config.isPad ? openNode(node) : ''
169+
}}
155170
onDoubleClick={e => openNode(node)}
156-
onTouchStart={e => openNode(node)}
157171
style={{ paddingLeft: `${1 + node.depth}em` }}
158172
>
159173
{node.isLoading && <i className='fa fa-spinner fa-pulse fa-fw' />}
160174
{!node.isLoading && (
161175
<span
162176
className='filetree-node-arrow'
163177
onDoubleClick={e => e.stopPropagation()}
164-
onClick={e => openNode(node, null, e.altKey)}
178+
onClick={e => config.isPad ? '' : openNode(node, null, e.altKey)}
165179
>
166180
{node.isDir && (
167181
<i

app/components/ContextMenu/store.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import state from './state'
22
import isFunction from 'lodash/isFunction'
33
import isArray from 'lodash/isArray'
44
import { createAction, handleAction, registerAction } from 'utils/actions'
5+
import config from 'config'
56

67
const OPEN_CONTEXT_MENU = 'menu:open_context_menu'
78
handleAction(OPEN_CONTEXT_MENU, ({ isActive, pos, contextNode, items, className }) => {
@@ -23,7 +24,14 @@ function openContextMenuFactory (items, margin, className) {
2324
const openContextMenu = createAction(OPEN_CONTEXT_MENU, (e, context, items = [], margin = { x: 0, y: 0, relative: false }, className = '') => {
2425
e.stopPropagation()
2526
e.preventDefault()
26-
let pos = { x: e.clientX + margin.x, y: e.clientY + margin.y }
27+
28+
const rects = e.target.getBoundingClientRect()
29+
const isPad = config.isPad
30+
31+
let pos = {
32+
x: (isPad ? rects.x + rects.width / 2 : e.clientX) + margin.x,
33+
y: (isPad ? rects.y + rects.height : e.clientY) + + margin.y
34+
}
2735
if (margin.relative) {
2836
const rect = e.target.getBoundingClientRect()
2937
pos = { x: rect.x + rect.width + margin.x, y: rect.y + rect.height + margin.y }

app/components/Git/GitBranchWidget.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { connect } from 'react-redux'
77
import * as GitActions from './actions'
88
import Menu from '../Menu'
99
import i18n from 'utils/createI18n'
10-
10+
import config from 'config'
1111

1212
// add withRef to deliver ref to the wrapperedcomponent
1313
@connect(state => state.GitState.branches,
@@ -28,7 +28,7 @@ export default class GitBranchWidget extends Component {
2828
const { current: currentBranch, local: localBranches, remote: remoteBranches } = this.props
2929
return (
3030
<div className='status-bar-menu-item'
31-
onClick={e => { this.toggleActive(true, true) }}
31+
onClick={e => { this.toggleActive(true, true); config.menuBars.push(this) }}
3232
>
3333
<span>
3434
<span className='fa fa-code-fork' style={{ fontWeight: 800, marginRight: '5px' }} />

app/components/MenuBar/MenuBar.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ class MenuBarItem extends Component {
114114
onClick={(e) => {
115115
e.stopPropagation()
116116
toggleActive(index, true)
117+
if (config.isPad) {
118+
config.menuBars.push(this.props)
119+
}
117120
}}
118121
onMouseEnter={(e) => { if (shouldHoverToggleActive) toggleActive(index) }}
119122
>

app/components/MonacoEditor/MonacoReact/BaseEditor.jsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ class MonacoEditor extends React.PureComponent {
194194
this.containerElement = component
195195
}
196196

197+
removeMenus = () => {
198+
// Hack tricks to remove active menu
199+
const menuBars = config.menuBars
200+
menuBars.map(menubar => menubar.toggleActive())
201+
}
202+
197203
render () {
198204
const { width, height } = this.props
199205
const fixedWidth = width.toString().indexOf('%') !== -1 ? width : `${width}px`
@@ -207,6 +213,7 @@ class MonacoEditor extends React.PureComponent {
207213
style={{ width: '100%', height: '100%' }}
208214
onWidthChange={this.handleResize}
209215
onHeightChange={this.handleResize}
216+
onTouchStart={this.removeMenus}
210217
>
211218
<div className='react-monaco-editor-container' ref={this.assignRef} style={style} />
212219
</Div>)

app/components/Panel/Panel.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { observer } from 'mobx-react'
44
import cx from 'classnames'
55
import PanelAxis from './PanelAxis'
66
import PanelContent from './PanelContent'
7-
import { confirmResize } from './actions'
7+
import { confirmResize, expandPanel, shrinkPanel } from './actions'
88
import ResizeBar from '../ResizeBar'
99

1010
const Panel = observer((props) => {

app/components/Panel/actions.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,16 @@ export const primiaryPanelBlurControler = registerAction(PRIMIARY_PANEL_BLUR_CON
3939
state.primaryPanelAxis.blur = shouldShow
4040
})
4141

42+
let initSize = 0
43+
export const PANEL_SHRINK = 'PANEL_SHRINK'
44+
export const shrinkPanel = registerAction(PANEL_SHRINK, (panelId) => {
45+
const panel = state.panels.get(panelId)
46+
initSize = panel.size
47+
panel.size = 0
48+
})
49+
50+
export const PANEL_EXPAND = 'PANEL_EXPAND'
51+
export const expandPanel = registerAction(PANEL_EXPAND, (panelId) => {
52+
const panel = state.panels.get(panelId)
53+
panel.size = initSize
54+
})

app/components/Terminal/Xterm.jsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,17 @@ class Term extends Component {
127127
emitter.removeListener(E.THEME_CHANGED, this.onTheme)
128128
state.terminalManager.remove(this.terminal)
129129
}
130+
131+
removeMenus = () => {
132+
// Hack tricks to remove active menu
133+
const menuBars = config.menuBars
134+
menuBars.map(menubar => menubar.toggleActive())
135+
}
130136

131137
render () {
132138
const { tab } = this.props
133139
return (
134-
<div className='ide-terminal'>
140+
<div className='ide-terminal' onTouchStart={this.removeMenus}>
135141
<div className='terminal-container'>
136142
<div className='terminal-body' data-droppable='TERMINAL' ref={r => this.termDOM = r}></div>
137143
</div>

0 commit comments

Comments
 (0)