@@ -49,6 +50,8 @@ class Prompt extends Component {
onKeyDown = e => {
if (e.keyCode === 13) {
+ e.preventDefault()
+ e.stopPropagation()
this.confirm(e.target.value)
}
}
diff --git a/app/components/Modal/modals/index.js b/app/components/Modal/modals/index.js
index fe3fff6a..6e50bbae 100644
--- a/app/components/Modal/modals/index.js
+++ b/app/components/Modal/modals/index.js
@@ -2,9 +2,9 @@ export Prompt from './Prompt'
export Confirm from './Confirm'
export Alert from './Alert'
export Form from './Form'
+export About from './About'
export { GitCommitView } from '../../Git'
export { CommandPalette } from '../../../commands'
-export { FilePalette } from '../FilePalette'
export GitStashView from '../../Git/modals/stash'
export GitUnstashView from '../../Git/modals/unstash'
export GitResetView from '../../Git/modals/reset'
@@ -22,3 +22,12 @@ export GitCommitDiffView from '../../Git/modals/commitDiff'
export GitCheckoutView from '../../Git/modals/checkout'
export GitCheckoutStashView from '../../Git/modals/checkoutStash'
export FileSelectorView from '../FileSelector'
+export LanguageServerConfig from '../LanguageServerConfig'
+export { ProjectSelector, ProjectCreator } from '../ProjectSelector'
+export FilePalette from '../FilePalette';
+export BindQcloudView from '../BindQcloud';
+export ImportFromGit from '../ImportFromGit';
+export ResetRemote from '../ResetRemote'
+export GitCommit from '../GitCommitView'
+export CreateProject from '../CreateProject'
+export ProjectTypeSelector from '../ProjectTypeSelector'
diff --git a/app/components/Modal/modals/modalCache.js b/app/components/Modal/modals/modalCache.js
index ba8ed549..4cbd20ba 100644
--- a/app/components/Modal/modals/modalCache.js
+++ b/app/components/Modal/modals/modalCache.js
@@ -28,9 +28,18 @@ import {
GitCheckoutStashView,
FileSelectorView,
Form,
+ About,
+ ProjectSelector,
+ ProjectCreator,
+ LanguageServerConfig,
+ BindQcloudView,
+ ImportFromGit,
+ ResetRemote,
+ GitCommit,
+ CreateProject,
+ ProjectTypeSelector,
} from './index'
-
const modalCache = observable.map({
Form,
GitCommit: GitCommitView,
@@ -51,11 +60,21 @@ const modalCache = observable.map({
Prompt,
Confirm,
Alert,
+ About,
CommandPalette,
FilePalette,
Settings: SettingsView,
FileSelectorView,
GitDiffFile: GitDiffFileView,
+ ProjectSelector,
+ ProjectCreator,
+ LanguageServerConfig,
+ BindQcloud: BindQcloudView,
+ ImportFromGit,
+ ResetRemote,
+ GitCommitView: GitCommit,
+ CreateProject,
+ ProjectTypeSelector
})
window.modalCache = modalCache
diff --git a/app/components/MonacoEditor/ConditionWidget.js b/app/components/MonacoEditor/ConditionWidget.js
new file mode 100644
index 00000000..d4cd26ba
--- /dev/null
+++ b/app/components/MonacoEditor/ConditionWidget.js
@@ -0,0 +1,136 @@
+import React, { PureComponent } from 'react'
+import styled from 'styled-components'
+import i18n from 'utils/createI18n'
+
+const Container = styled.div`
+ border-bottom-color: rgb(0, 122, 204);
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+ border-left-color: rgb(0, 122, 204);
+ border-right-color: rgb(0, 122, 204);
+ border-top-color: rgb(0, 122, 204);
+ border-top-style: solid;
+ border-top-width: 1px;
+ color: rgb(171, 178, 191);
+ display: flex;
+ font-family: -apple-system, system-ui, 'Segoe WPC', 'Segoe UI', HelveticaNeue-Light, 'Noto Sans',
+ 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', 'Source Han Sans CN',
+ 'Source Han Sans', sans-serif;
+ font-feature-settings: 'liga' 1, 'calt' 1;
+ font-size: 13px;
+ height: 30px;
+ line-height: 18.2px;
+ overflow-x: hidden;
+ overflow-y: hidden;
+ position: relative;
+ text-size-adjust: 100%;
+ top: 0px;
+ user-select: none;
+ white-space: normal;
+ z-index: 100;
+`
+
+const SelectContainer = styled.div`
+ display: flex;
+ align-items: center;
+ padding: 0 10px;
+ &>select {
+ font-size: 12px;
+ box-sizing: border-box;
+ align-items: center;
+ white-space: pre;
+ outline: none;
+ }
+`
+
+const InputContainer = styled.div`
+ flex: 1;
+ display: flex;
+ align-items: center;
+ &>input {
+ background-color: rgba(0, 0, 0, 0);
+ font-size: 12px;
+ border: none;
+ width: 100%;
+ outline: none;
+ }
+`
+
+class ConditionWidget extends PureComponent {
+ state = {
+ logMessage: this.props.breakpoint.logMessage || '',
+ condition: this.props.breakpoint.condition || '',
+ hitCondition: this.props.breakpoint.hitCondition || '',
+ conditionType: 'condition'
+ }
+
+ componentDidMount () {
+ if (this.inputNode) {
+ const timer = setTimeout(() => {
+ this.inputNode.focus()
+ clearTimeout(timer)
+ }, 500)
+ }
+
+ document.body.addEventListener('keydown', this.handleCancelEvent)
+ }
+
+ componentWillUnmount () {
+ document.body.removeEventListener('keydown', this.handleCancelEvent)
+ }
+
+ handleCancelEvent = (e) => {
+ if (e.keyCode === 27 && e.key === 'Escape') {
+ this.props.onCancel()
+ }
+ }
+
+ handleChange = (e) => {
+ const { conditionType } = this.state
+ this.setState({ [conditionType]: e.target.value })
+ }
+
+ handleChangeType = (e) => {
+ this.setState({ conditionType: e.target.value })
+ }
+
+ handleKeyDown = (e) => {
+ const { logMessage, condition, hitCondition } = this.state
+ const { onChange, onCancel } = this.props
+ if (e.keyCode === 13) {
+ onChange({
+ logMessage,
+ condition,
+ hitCondition,
+ })
+ onCancel()
+ }
+ }
+
+ render () {
+ const { conditionType } = this.state
+ return (
+
+ )
+ }
+}
+
+export default ConditionWidget
diff --git a/app/components/MonacoEditor/Editors/CodeEditor.jsx b/app/components/MonacoEditor/Editors/CodeEditor.jsx
new file mode 100644
index 00000000..4c81033f
--- /dev/null
+++ b/app/components/MonacoEditor/Editors/CodeEditor.jsx
@@ -0,0 +1,18 @@
+// import React from 'react'
+import addMixinMechanism from './addMixinMechanism'
+import MonacoEditor from '../MonacoReact/BaseEditor'
+
+class CodeEditor extends MonacoEditor {
+ componentWillReceiveProps (nextProps) {
+ const { editorInfo } = nextProps
+ if (editorInfo && this.editor === editorInfo) return
+ if (editorInfo && this.containerElement) {
+ const prevElement = this.props.editorInfo.monacoElement
+ this.containerElement.replaceChild(editorInfo.monacoElement, prevElement)
+ }
+ }
+}
+
+addMixinMechanism(CodeEditor, MonacoEditor)
+
+export default CodeEditor
diff --git a/app/components/MonacoEditor/Editors/HtmlEditor.jsx b/app/components/MonacoEditor/Editors/HtmlEditor.jsx
new file mode 100644
index 00000000..d0e64cbf
--- /dev/null
+++ b/app/components/MonacoEditor/Editors/HtmlEditor.jsx
@@ -0,0 +1,101 @@
+import React, { Component } from 'react';
+import { autorun, extendObservable } from 'mobx';
+import { observer } from 'mobx-react';
+import CodeEditor from './CodeEditor';
+import * as actions from './actions';
+import uniqueId from 'lodash/uniqueId';
+import config from '../../../config';
+
+@observer
+class PreviewEditor extends Component {
+ render() {
+ const { url, isResizing } = this.props;
+ return (
+
+ )
+ }
+}
+
+const startResize = (e, actions, state) => {
+ if (e.button !== 0) return // do nothing unless left button pressed
+ e.preventDefault();
+ state.isResizing = true;
+ let oX = e.pageX; // origin x-distince
+ const handleResize = (e) => {
+ // get destination of difference of two distince x
+ const dX = oX - e.pageX;
+ oX = e.pageX; // reset x
+ actions.editorResize(dX, state, 'editor_preview_html_editor', 'editor_preview_html_preview');
+ }
+ const stopResize = () => {
+ state.isResizing = false;
+ window.document.removeEventListener('mousemove', handleResize)
+ window.document.removeEventListener('mouseup', stopResize)
+ }
+ window.document.addEventListener('mousemove', handleResize)
+ window.document.addEventListener('mouseup', stopResize)
+}
+
+const ResizeBar = ({ startResize, actions, state }) => {
+ return
+}
+
+@observer
+class HtmlEditor extends Component {
+ constructor(props) {
+ super(props);
+ if (!props.tab.previewUniqueId) {
+ extendObservable(props.tab, {
+ leftGrow: 50,
+ rightGrow: 50,
+ showBigSize: false,
+ showPreview: false,
+ previewUniqueId: '1',
+ isResizing: false,
+ });
+ }
+ }
+
+ componentDidMount() {
+ autorun(() => {
+ if (this.props.tab.file && this.props.tab.file.isSynced) {
+ this.props.tab.previewUniqueId = uniqueId();
+ }
+ })
+ }
+
+ render() {
+ const { tab, editorInfo } = this.props;
+ const { leftGrow, rightGrow, showBigSize, showPreview, previewUniqueId } = tab;
+ const editorStyle = { flexGrow: leftGrow, display: !showBigSize || (showBigSize && !showPreview) ? 'block' : 'none' };
+ const previewStyle = { flexGrow: rightGrow };
+ const expandIcon = showBigSize ? 'fa fa-compress' : 'fa fa-expand';
+ const eyeIcon = showPreview ? 'fa fa-eye-slash' : 'fa fa-eye';
+ return (
+
+ );
+ }
+}
+
+export default HtmlEditor;
diff --git a/app/components/MonacoEditor/Editors/MarkDownEditor.jsx b/app/components/MonacoEditor/Editors/MarkDownEditor.jsx
new file mode 100644
index 00000000..2696b6a7
--- /dev/null
+++ b/app/components/MonacoEditor/Editors/MarkDownEditor.jsx
@@ -0,0 +1,205 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { autorun, extendObservable, observable } from 'mobx'
+import debounce from 'lodash/debounce'
+import cx from 'classnames'
+import Remarkable from 'remarkable'
+import { observer } from 'mobx-react'
+import CodeEditor from './CodeEditor'
+import * as actions from './actions'
+import scrollMixin from './scrollMixin';
+// import mdMixin from './mdMixin'
+
+// CodeEditor.use(mdMixin)
+
+const eventXSSReg = /\son[a-z]{3,20}=('\S*'|"\S*")/ig;
+const hrefXSSReg = /\shref=('javascript:\S+'|"javascript:\S+")/ig;
+const scriptLtReg = /<(\/?script)/ig;
+const scriptGtReg = /(\/?script)>/ig;
+
+const md = new Remarkable('full', {
+ html: true, // Enable HTML tags in source
+ xhtmlOut: false, // Use '/' to close single tags (
+ langPrefix: 'language-', // CSS language prefix for fenced blocks
+ linkify: true, // autoconvert URL-like texts to links
+ linkTarget: '_blank', // set target to open link in
+
+ // Enable some language-neutral replacements + quotes beautification
+ typographer: false,
+
+ // Double + single quotes replacement pairs, when typographer enabled,
+ // and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
+ quotes: '“”‘’',
+
+ // Highlighter function. Should return escaped HTML,
+ // or '' if input not changed
+ highlight: (str, lang) => {
+ require('highlight.js/styles/monokai-sublime.css')
+ const hljs = require('highlight.js')
+ if (lang && hljs.getLanguage(lang)) {
+ try {
+ return hljs.highlight(lang, str).value
+ } catch (__) {}
+ }
+
+ try {
+ return hljs.highlightAuto(str).value
+ } catch (__) {}
+
+ return '' // use external default escaping
+ }
+})
+
+md.renderer.rules.table_open = () => {
+ return '
\n'
+}
+
+md.renderer.rules.paragraph_open = (tokens, idx) => {
+ let line
+ if (tokens[idx].lines && tokens[idx].level === 0) {
+ line = tokens[idx].lines[0]
+ return ''
+ }
+ return '
'
+}
+
+md.renderer.rules.heading_open = (tokens, idx) => {
+ let line
+ if (tokens[idx].lines && tokens[idx].level === 0) {
+ line = tokens[idx].lines[0]
+ return ''
+ }
+ return ''
+}
+
+md.renderer.rules.bullet_list_open = (tokens, idx) => {
+ let line
+ if (tokens[idx].lines && tokens[idx].level === 0) {
+ line = tokens[idx].lines[0]
+ return '