Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
徽霖
Vscode
提交
91db8b52
V
Vscode
项目概览
徽霖
/
Vscode
通知
9
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
Vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
91db8b52
编写于
10月 06, 2016
作者:
B
Benjamin Pasero
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
get rid of ICommandLineArguments
上级
68562163
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
44 addition
and
48 deletion
+44
-48
src/vs/code/electron-main/env.ts
src/vs/code/electron-main/env.ts
+4
-9
src/vs/code/electron-main/launch.ts
src/vs/code/electron-main/launch.ts
+7
-7
src/vs/code/electron-main/main.ts
src/vs/code/electron-main/main.ts
+3
-2
src/vs/code/electron-main/menus.ts
src/vs/code/electron-main/menus.ts
+9
-9
src/vs/code/electron-main/window.ts
src/vs/code/electron-main/window.ts
+3
-4
src/vs/code/electron-main/windows.ts
src/vs/code/electron-main/windows.ts
+18
-17
未找到文件。
src/vs/code/electron-main/env.ts
浏览文件 @
91db8b52
...
...
@@ -15,31 +15,26 @@ import * as types from 'vs/base/common/types';
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
parseMainProcessArgv
,
ParsedArgs
}
from
'
vs/platform/environment/node/argv
'
;
export
interface
ICommandLineArguments
extends
ParsedArgs
{
paths
?:
string
[];
}
export
const
IEnvService
=
createDecorator
<
IEnvService
>
(
'
mainEnvironmentService
'
);
export
interface
IEnvService
{
_serviceBrand
:
any
;
cliArgs
:
ICommandLineArgument
s
;
cliArgs
:
ParsedArg
s
;
}
export
class
EnvService
implements
IEnvService
{
_serviceBrand
:
any
;
private
_cliArgs
:
ICommandLineArgument
s
;
get
cliArgs
():
ICommandLineArgument
s
{
return
this
.
_cliArgs
;
}
private
_cliArgs
:
ParsedArg
s
;
get
cliArgs
():
ParsedArg
s
{
return
this
.
_cliArgs
;
}
constructor
()
{
const
argv
=
parseMainProcessArgv
(
process
.
argv
);
const
paths
=
parsePathArguments
(
argv
.
_
,
argv
.
goto
);
this
.
_cliArgs
=
Object
.
freeze
({
_
:
[],
paths
,
_
:
paths
,
performance
:
argv
.
performance
,
verbose
:
argv
.
verbose
,
debugPluginHost
:
argv
.
debugPluginHost
,
...
...
src/vs/code/electron-main/launch.ts
浏览文件 @
91db8b52
...
...
@@ -5,7 +5,6 @@
'
use strict
'
;
import
{
ICommandLineArguments
}
from
'
vs/code/electron-main/env
'
;
import
{
IWindowsService
}
from
'
vs/code/electron-main/windows
'
;
import
{
VSCodeWindow
}
from
'
vs/code/electron-main/window
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
...
...
@@ -13,14 +12,15 @@ import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import
{
ILogService
}
from
'
vs/code/electron-main/log
'
;
import
{
IURLService
}
from
'
vs/platform/url/common/url
'
;
import
{
IProcessEnvironment
}
from
'
vs/base/common/platform
'
;
import
{
ParsedArgs
}
from
'
vs/platform/environment/node/argv
'
;
export
interface
IStartArguments
{
args
:
ICommandLineArgument
s
;
args
:
ParsedArg
s
;
userEnv
:
IProcessEnvironment
;
}
export
interface
ILaunchService
{
start
(
args
:
ICommandLineArgument
s
,
userEnv
:
IProcessEnvironment
):
TPromise
<
void
>
;
start
(
args
:
ParsedArg
s
,
userEnv
:
IProcessEnvironment
):
TPromise
<
void
>
;
}
export
interface
ILaunchChannel
extends
IChannel
{
...
...
@@ -45,7 +45,7 @@ export class LaunchChannelClient implements ILaunchService {
constructor
(
private
channel
:
ILaunchChannel
)
{
}
start
(
args
:
ICommandLineArgument
s
,
userEnv
:
IProcessEnvironment
):
TPromise
<
void
>
{
start
(
args
:
ParsedArg
s
,
userEnv
:
IProcessEnvironment
):
TPromise
<
void
>
{
return
this
.
channel
.
call
(
'
start
'
,
{
args
,
userEnv
});
}
}
...
...
@@ -58,7 +58,7 @@ export class LaunchService implements ILaunchService {
@
IURLService
private
urlService
:
IURLService
)
{}
start
(
args
:
ICommandLineArgument
s
,
userEnv
:
IProcessEnvironment
):
TPromise
<
void
>
{
start
(
args
:
ParsedArg
s
,
userEnv
:
IProcessEnvironment
):
TPromise
<
void
>
{
this
.
logService
.
log
(
'
Received data from other instance:
'
,
args
,
userEnv
);
const
openUrlArg
=
args
[
'
open-url
'
]
||
[];
...
...
@@ -73,9 +73,9 @@ export class LaunchService implements ILaunchService {
let
usedWindows
:
VSCodeWindow
[];
if
(
!!
args
.
extensionDevelopmentPath
)
{
this
.
windowsService
.
openPluginDevelopmentHostWindow
({
cli
:
args
,
userEnv
});
}
else
if
(
args
.
paths
.
length
===
0
&&
args
[
'
new-window
'
])
{
}
else
if
(
args
.
_
.
length
===
0
&&
args
[
'
new-window
'
])
{
usedWindows
=
this
.
windowsService
.
open
({
cli
:
args
,
userEnv
,
forceNewWindow
:
true
,
forceEmpty
:
true
});
}
else
if
(
args
.
paths
.
length
===
0
)
{
}
else
if
(
args
.
_
.
length
===
0
)
{
usedWindows
=
[
this
.
windowsService
.
focusLastActive
(
args
)];
}
else
{
usedWindows
=
this
.
windowsService
.
open
({
...
...
src/vs/code/electron-main/main.ts
浏览文件 @
91db8b52
...
...
@@ -253,9 +253,9 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: platfo
updateService
.
initialize
();
// Open our first window
if
(
envService
.
cliArgs
[
'
new-window
'
]
&&
envService
.
cliArgs
.
paths
.
length
===
0
)
{
if
(
envService
.
cliArgs
[
'
new-window
'
]
&&
envService
.
cliArgs
.
_
.
length
===
0
)
{
windowsService
.
open
({
cli
:
envService
.
cliArgs
,
forceNewWindow
:
true
,
forceEmpty
:
true
});
// new window if "-n" was used without paths
}
else
if
(
global
.
macOpenFiles
&&
global
.
macOpenFiles
.
length
&&
(
!
envService
.
cliArgs
.
paths
||
!
envService
.
cliArgs
.
paths
.
length
))
{
}
else
if
(
global
.
macOpenFiles
&&
global
.
macOpenFiles
.
length
&&
(
!
envService
.
cliArgs
.
_
||
!
envService
.
cliArgs
.
_
.
length
))
{
windowsService
.
open
({
cli
:
envService
.
cliArgs
,
pathsToOpen
:
global
.
macOpenFiles
});
// mac: open-file event received on startup
}
else
{
windowsService
.
open
({
cli
:
envService
.
cliArgs
,
forceNewWindow
:
envService
.
cliArgs
[
'
new-window
'
],
diffMode
:
envService
.
cliArgs
.
diff
});
// default: read paths from cli
...
...
@@ -426,6 +426,7 @@ function getEnvironment(accessor: ServicesAccessor): TPromise<platform.IProcessE
function
createPaths
(
environmentService
:
IEnvironmentService
):
TPromise
<
any
>
{
const
paths
=
[
environmentService
.
appSettingsHome
,
environmentService
.
userHome
,
environmentService
.
extensionsPath
];
return
TPromise
.
join
(
paths
.
map
(
p
=>
mkdirp
(
p
)))
as
TPromise
<
any
>
;
}
...
...
src/vs/code/electron-main/menus.ts
浏览文件 @
91db8b52
...
...
@@ -69,11 +69,11 @@ export class VSCodeMenu {
});
// Listen to "open" & "close" event from window service
this
.
windowsService
.
onOpen
(
(
paths
)
=>
this
.
onOpen
(
paths
));
this
.
windowsService
.
onOpen
(
paths
=>
this
.
onOpen
(
paths
));
this
.
windowsService
.
onClose
(
_
=>
this
.
onClose
(
this
.
windowsService
.
getWindowCount
()));
// Resolve keybindings when any first workbench is loaded
this
.
windowsService
.
onReady
(
(
win
)
=>
this
.
resolveKeybindings
(
win
));
this
.
windowsService
.
onReady
(
win
=>
this
.
resolveKeybindings
(
win
));
// Listen to resolved keybindings
ipc
.
on
(
'
vscode:keybindingsResolved
'
,
(
event
,
rawKeybindings
)
=>
{
...
...
@@ -86,7 +86,7 @@ export class VSCodeMenu {
// Fill hash map of resolved keybindings
let
needsMenuUpdate
=
false
;
keybindings
.
forEach
(
(
keybinding
)
=>
{
keybindings
.
forEach
(
keybinding
=>
{
const
accelerator
=
new
Keybinding
(
keybinding
.
binding
).
_toElectronAccelerator
();
if
(
accelerator
)
{
this
.
mapResolvedKeybindingToActionId
[
keybinding
.
id
]
=
accelerator
;
...
...
@@ -328,7 +328,7 @@ export class VSCodeMenu {
!
platform
.
isMacintosh
?
closeWindow
:
null
,
!
platform
.
isMacintosh
?
__separator__
()
:
null
,
!
platform
.
isMacintosh
?
exit
:
null
]).
forEach
(
(
item
)
=>
fileMenu
.
append
(
item
));
]).
forEach
(
item
=>
fileMenu
.
append
(
item
));
}
private
getPreferencesMenu
():
Electron
.
MenuItem
{
...
...
@@ -434,8 +434,8 @@ export class VSCodeMenu {
let
selectAll
:
Electron
.
MenuItem
;
if
(
platform
.
isMacintosh
)
{
undo
=
this
.
createDevToolsAwareMenuItem
(
nls
.
localize
({
key
:
'
miUndo
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Undo
"
),
'
undo
'
,
(
devTools
)
=>
devTools
.
undo
());
redo
=
this
.
createDevToolsAwareMenuItem
(
nls
.
localize
({
key
:
'
miRedo
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Redo
"
),
'
redo
'
,
(
devTools
)
=>
devTools
.
redo
());
undo
=
this
.
createDevToolsAwareMenuItem
(
nls
.
localize
({
key
:
'
miUndo
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Undo
"
),
'
undo
'
,
devTools
=>
devTools
.
undo
());
redo
=
this
.
createDevToolsAwareMenuItem
(
nls
.
localize
({
key
:
'
miRedo
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Redo
"
),
'
redo
'
,
devTools
=>
devTools
.
redo
());
cut
=
this
.
createRoleMenuItem
(
nls
.
localize
({
key
:
'
miCut
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Cut
"
),
'
editor.action.clipboardCutAction
'
,
'
cut
'
);
copy
=
this
.
createRoleMenuItem
(
nls
.
localize
({
key
:
'
miCopy
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
C&&opy
"
),
'
editor.action.clipboardCopyAction
'
,
'
copy
'
);
paste
=
this
.
createRoleMenuItem
(
nls
.
localize
({
key
:
'
miPaste
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Paste
"
),
'
editor.action.clipboardPasteAction
'
,
'
paste
'
);
...
...
@@ -531,7 +531,7 @@ export class VSCodeMenu {
zoomIn
,
zoomOut
,
resetZoom
]).
forEach
(
(
item
)
=>
viewMenu
.
append
(
item
));
]).
forEach
(
item
=>
viewMenu
.
append
(
item
));
}
private
setGotoMenu
(
gotoMenu
:
Electron
.
Menu
):
void
{
...
...
@@ -673,7 +673,7 @@ export class VSCodeMenu {
(
product
.
licenseUrl
||
product
.
privacyStatementUrl
)
?
__separator__
()
:
null
,
toggleDevToolsItem
,
platform
.
isWindows
&&
product
.
quality
!==
'
stable
'
?
showAccessibilityOptions
:
null
]).
forEach
(
(
item
)
=>
helpMenu
.
append
(
item
));
]).
forEach
(
item
=>
helpMenu
.
append
(
item
));
if
(
!
platform
.
isMacintosh
)
{
const
updateMenuItems
=
this
.
getUpdateMenuItems
();
...
...
@@ -811,7 +811,7 @@ export class VSCodeMenu {
),
buttons
:
[
nls
.
localize
(
'
okButton
'
,
"
OK
"
)],
noLink
:
true
},
(
result
)
=>
null
);
},
result
=>
null
);
this
.
reportMenuActionTelemetry
(
'
showAboutDialog
'
);
}
...
...
src/vs/code/electron-main/window.ts
浏览文件 @
91db8b52
...
...
@@ -11,11 +11,10 @@ import * as objects from 'vs/base/common/objects';
import
{
IStorageService
}
from
'
vs/code/electron-main/storage
'
;
import
{
shell
,
screen
,
BrowserWindow
}
from
'
electron
'
;
import
{
TPromise
,
TValueCallback
}
from
'
vs/base/common/winjs.base
'
;
import
{
ICommandLineArguments
}
from
'
vs/code/electron-main/env
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
ILogService
}
from
'
vs/code/electron-main/log
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
parseArgs
}
from
'
vs/platform/environment/node/argv
'
;
import
{
parseArgs
,
ParsedArgs
}
from
'
vs/platform/environment/node/argv
'
;
import
product
from
'
vs/platform/product
'
;
export
interface
IWindowState
{
...
...
@@ -88,7 +87,7 @@ export interface IPath {
createFilePath
?:
boolean
;
}
export
interface
IWindowConfiguration
extends
ICommandLineArgument
s
{
export
interface
IWindowConfiguration
extends
ParsedArg
s
{
appRoot
:
string
;
execPath
:
string
;
...
...
@@ -387,7 +386,7 @@ export class VSCodeWindow {
}
}
public
reload
(
cli
?:
ICommandLineArgument
s
):
void
{
public
reload
(
cli
?:
ParsedArg
s
):
void
{
// Inherit current properties but overwrite some
const
configuration
:
IWindowConfiguration
=
objects
.
mixin
({},
this
.
currentConfig
);
...
...
src/vs/code/electron-main/windows.ts
浏览文件 @
91db8b52
...
...
@@ -18,7 +18,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import
{
IStorageService
}
from
'
vs/code/electron-main/storage
'
;
import
{
IPath
,
VSCodeWindow
,
ReadyState
,
IWindowConfiguration
,
IWindowState
as
ISingleWindowState
,
defaultWindowState
,
IWindowSettings
}
from
'
vs/code/electron-main/window
'
;
import
{
ipcMain
as
ipc
,
app
,
screen
,
crashReporter
,
BrowserWindow
,
dialog
}
from
'
electron
'
;
import
{
I
CommandLineArguments
,
I
EnvService
,
IParsedPath
,
parseLineAndColumnAware
}
from
'
vs/code/electron-main/env
'
;
import
{
IEnvService
,
IParsedPath
,
parseLineAndColumnAware
}
from
'
vs/code/electron-main/env
'
;
import
{
ILifecycleService
}
from
'
vs/code/electron-main/lifecycle
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IUpdateService
,
IUpdate
}
from
'
vs/code/electron-main/update-manager
'
;
...
...
@@ -27,6 +27,7 @@ import { IWindowEventService } from 'vs/code/common/windows';
import
{
createDecorator
,
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
CommonEvent
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
product
from
'
vs/platform/product
'
;
import
{
ParsedArgs
}
from
'
vs/platform/environment/node/argv
'
;
const
EventTypes
=
{
OPEN
:
'
open
'
,
...
...
@@ -40,7 +41,7 @@ enum WindowError {
}
export
interface
IOpenConfiguration
{
cli
:
ICommandLineArgument
s
;
cli
:
ParsedArg
s
;
userEnv
?:
platform
.
IProcessEnvironment
;
pathsToOpen
?:
string
[];
preferNewWindow
?:
boolean
;
...
...
@@ -99,14 +100,14 @@ export interface IWindowsService {
// methods
ready
(
initialUserEnv
:
platform
.
IProcessEnvironment
):
void
;
reload
(
win
:
VSCodeWindow
,
cli
?:
ICommandLineArgument
s
):
void
;
reload
(
win
:
VSCodeWindow
,
cli
?:
ParsedArg
s
):
void
;
open
(
openConfig
:
IOpenConfiguration
):
VSCodeWindow
[];
openPluginDevelopmentHostWindow
(
openConfig
:
IOpenConfiguration
):
void
;
openFileFolderPicker
(
forceNewWindow
?:
boolean
):
void
;
openFilePicker
(
forceNewWindow
?:
boolean
):
void
;
openFolderPicker
(
forceNewWindow
?:
boolean
):
void
;
openAccessibilityOptions
():
void
;
focusLastActive
(
cli
:
ICommandLineArgument
s
):
VSCodeWindow
;
focusLastActive
(
cli
:
ParsedArg
s
):
VSCodeWindow
;
getLastActiveWindow
():
VSCodeWindow
;
findWindow
(
workspacePath
:
string
,
filePath
?:
string
,
extensionDevelopmentPath
?:
string
):
VSCodeWindow
;
openNewWindow
():
void
;
...
...
@@ -542,7 +543,7 @@ export class WindowsManager implements IWindowsService {
}
}
public
reload
(
win
:
VSCodeWindow
,
cli
?:
ICommandLineArgument
s
):
void
{
public
reload
(
win
:
VSCodeWindow
,
cli
?:
ParsedArg
s
):
void
{
// Only reload when the window has not vetoed this
this
.
lifecycleService
.
unload
(
win
).
done
(
veto
=>
{
...
...
@@ -598,7 +599,7 @@ export class WindowsManager implements IWindowsService {
// Otherwise infer from command line arguments
else
{
const
ignoreFileNotFound
=
openConfig
.
cli
.
paths
.
length
>
0
;
// we assume the user wants to create this file from command line
const
ignoreFileNotFound
=
openConfig
.
cli
.
_
.
length
>
0
;
// we assume the user wants to create this file from command line
iPathsToOpen
=
this
.
cliToPaths
(
openConfig
.
cli
,
ignoreFileNotFound
);
}
...
...
@@ -824,26 +825,26 @@ export class WindowsManager implements IWindowsService {
}
// Fill in previously opened workspace unless an explicit path is provided and we are not unit testing
if
(
openConfig
.
cli
.
paths
.
length
===
0
&&
!
openConfig
.
cli
.
extensionTestsPath
)
{
if
(
openConfig
.
cli
.
_
.
length
===
0
&&
!
openConfig
.
cli
.
extensionTestsPath
)
{
const
workspaceToOpen
=
this
.
windowsState
.
lastPluginDevelopmentHostWindow
&&
this
.
windowsState
.
lastPluginDevelopmentHostWindow
.
workspacePath
;
if
(
workspaceToOpen
)
{
openConfig
.
cli
.
paths
=
[
workspaceToOpen
];
openConfig
.
cli
.
_
=
[
workspaceToOpen
];
}
}
// Make sure we are not asked to open a path that is already opened
if
(
openConfig
.
cli
.
paths
.
length
>
0
)
{
res
=
WindowsManager
.
WINDOWS
.
filter
(
w
=>
w
.
openedWorkspacePath
&&
openConfig
.
cli
.
paths
.
indexOf
(
w
.
openedWorkspacePath
)
>=
0
);
if
(
openConfig
.
cli
.
_
.
length
>
0
)
{
res
=
WindowsManager
.
WINDOWS
.
filter
(
w
=>
w
.
openedWorkspacePath
&&
openConfig
.
cli
.
_
.
indexOf
(
w
.
openedWorkspacePath
)
>=
0
);
if
(
res
.
length
)
{
openConfig
.
cli
.
paths
=
[];
openConfig
.
cli
.
_
=
[];
}
}
// Open it
this
.
open
({
cli
:
openConfig
.
cli
,
forceNewWindow
:
true
,
forceEmpty
:
openConfig
.
cli
.
paths
.
length
===
0
});
this
.
open
({
cli
:
openConfig
.
cli
,
forceNewWindow
:
true
,
forceEmpty
:
openConfig
.
cli
.
_
.
length
===
0
});
}
private
toConfiguration
(
userEnv
:
platform
.
IProcessEnvironment
,
cli
:
ICommandLineArgument
s
,
workspacePath
?:
string
,
filesToOpen
?:
IPath
[],
filesToCreate
?:
IPath
[],
filesToDiff
?:
IPath
[]):
IWindowConfiguration
{
private
toConfiguration
(
userEnv
:
platform
.
IProcessEnvironment
,
cli
:
ParsedArg
s
,
workspacePath
?:
string
,
filesToOpen
?:
IPath
[],
filesToCreate
?:
IPath
[],
filesToDiff
?:
IPath
[]):
IWindowConfiguration
{
const
configuration
:
IWindowConfiguration
=
mixin
({},
cli
);
// inherit all properties from CLI
configuration
.
appRoot
=
this
.
environmentService
.
appRoot
;
configuration
.
execPath
=
process
.
execPath
;
...
...
@@ -888,12 +889,12 @@ export class WindowsManager implements IWindowsService {
return
null
;
}
private
cliToPaths
(
cli
:
ICommandLineArgument
s
,
ignoreFileNotFound
?:
boolean
):
IPath
[]
{
private
cliToPaths
(
cli
:
ParsedArg
s
,
ignoreFileNotFound
?:
boolean
):
IPath
[]
{
// Check for pass in candidate or last opened path
let
candidates
:
string
[]
=
[];
if
(
cli
.
paths
.
length
>
0
)
{
candidates
=
cli
.
paths
;
if
(
cli
.
_
.
length
>
0
)
{
candidates
=
cli
.
_
;
}
// No path argument, check settings for what to do now
...
...
@@ -1139,7 +1140,7 @@ export class WindowsManager implements IWindowsService {
});
}
public
focusLastActive
(
cli
:
ICommandLineArgument
s
):
VSCodeWindow
{
public
focusLastActive
(
cli
:
ParsedArg
s
):
VSCodeWindow
{
const
lastActive
=
this
.
getLastActiveWindow
();
if
(
lastActive
)
{
lastActive
.
focus
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录