Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_34031325
engine
提交
1d23f210
E
engine
项目概览
qq_34031325
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1d23f210
编写于
5月 05, 2016
作者:
A
Adam Barth
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support for app messages to iOS (#2651)
Fixes
https://github.com/flutter/flutter/issues/3256
上级
86837edd
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
272 addition
and
16 deletion
+272
-16
sky/shell/BUILD.gn
sky/shell/BUILD.gn
+6
-0
sky/shell/platform/ios/framework/Headers/Flutter.h
sky/shell/platform/ios/framework/Headers/Flutter.h
+4
-0
sky/shell/platform/ios/framework/Headers/FlutterAsyncMessageListener.h
...tform/ios/framework/Headers/FlutterAsyncMessageListener.h
+20
-0
sky/shell/platform/ios/framework/Headers/FlutterMessageListener.h
...l/platform/ios/framework/Headers/FlutterMessageListener.h
+19
-0
sky/shell/platform/ios/framework/Headers/FlutterViewController.h
...ll/platform/ios/framework/Headers/FlutterViewController.h
+18
-3
sky/shell/platform/ios/framework/Source/FlutterViewController.mm
...ll/platform/ios/framework/Source/FlutterViewController.mm
+60
-9
sky/shell/platform/ios/framework/Source/application_messages_impl.h
...platform/ios/framework/Source/application_messages_impl.h
+55
-0
sky/shell/platform/ios/framework/Source/application_messages_impl.mm
...latform/ios/framework/Source/application_messages_impl.mm
+67
-0
sky/shell/platform/mac/sky_window.mm
sky/shell/platform/mac/sky_window.mm
+2
-1
sky/shell/platform/mac/view_service_provider.cc
sky/shell/platform/mac/view_service_provider.cc
+13
-2
sky/shell/platform/mac/view_service_provider.h
sky/shell/platform/mac/view_service_provider.h
+8
-1
未找到文件。
sky/shell/BUILD.gn
浏览文件 @
1d23f210
...
...
@@ -251,11 +251,15 @@ if (is_android) {
sources = [
"platform/ios/framework/Headers/Flutter.h",
"platform/ios/framework/Headers/FlutterAppDelegate.h",
"platform/ios/framework/Headers/FlutterAsyncMessageListener.h",
"platform/ios/framework/Headers/FlutterDartProject.h",
"platform/ios/framework/Headers/FlutterMacros.h",
"platform/ios/framework/Headers/FlutterMessageListener.h",
"platform/ios/framework/Headers/FlutterViewController.h",
"platform/ios/framework/Source/accessibility_bridge.h",
"platform/ios/framework/Source/accessibility_bridge.mm",
"platform/ios/framework/Source/application_messages_impl.h",
"platform/ios/framework/Source/application_messages_impl.mm",
"platform/ios/framework/Source/FlutterAppDelegate.mm",
"platform/ios/framework/Source/FlutterDartProject.mm",
"platform/ios/framework/Source/FlutterDartProject_Internal.h",
...
...
@@ -379,8 +383,10 @@ if (is_android) {
sources = [
"platform/ios/framework/Headers/Flutter.h",
"platform/ios/framework/Headers/FlutterAppDelegate.h",
"platform/ios/framework/Headers/FlutterAsyncMessageListener.h",
"platform/ios/framework/Headers/FlutterDartProject.h",
"platform/ios/framework/Headers/FlutterMacros.h",
"platform/ios/framework/Headers/FlutterMessageListener.h",
"platform/ios/framework/Headers/FlutterViewController.h",
]
outputs = [ "$framework_dir/Headers/{{source_file_part}}" ]
...
...
sky/shell/platform/ios/framework/Headers/Flutter.h
浏览文件 @
1d23f210
...
...
@@ -5,7 +5,11 @@
#ifndef FLUTTER_FLUTTER_H_
#define FLUTTER_FLUTTER_H_
#include "FlutterAppDelegate.h"
#include "FlutterAsyncMessageListener.h"
#include "FlutterDartProject.h"
#include "FlutterMacros.h"
#include "FlutterMessageListener.h"
#include "FlutterViewController.h"
#endif // FLUTTER_FLUTTER_H_
sky/shell/platform/ios/framework/Headers/FlutterAsyncMessageListener.h
0 → 100644
浏览文件 @
1d23f210
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FLUTTERASYNCMESSAGELISTENER_H_
#define FLUTTER_FLUTTERASYNCMESSAGELISTENER_H_
#import <Foundation/Foundation.h>
#include "FlutterMacros.h"
FLUTTER_EXPORT
@protocol
FlutterAsyncMessageListener
<
NSObject
>
-
(
void
)
didReceiveString
:(
NSString
*
)
message
callback
:(
void
(
^
)(
NSString
*
))
sendResponse
;
@end
#endif // FLUTTER_FLUTTERASYNCMESSAGELISTENER_H_
sky/shell/platform/ios/framework/Headers/FlutterMessageListener.h
0 → 100644
浏览文件 @
1d23f210
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FLUTTERMESSAGELISTENER_H_
#define FLUTTER_FLUTTERMESSAGELISTENER_H_
#import <Foundation/Foundation.h>
#include "FlutterMacros.h"
FLUTTER_EXPORT
@protocol
FlutterMessageListener
<
NSObject
>
-
(
NSString
*
)
didReceiveString
:(
NSString
*
)
message
;
@end
#endif // FLUTTER_FLUTTERMESSAGELISTENER_H_
sky/shell/platform/ios/framework/Headers/FlutterViewController.h
浏览文件 @
1d23f210
...
...
@@ -5,11 +5,13 @@
#ifndef FLUTTER_FLUTTERVIEWCONTROLLER_H_
#define FLUTTER_FLUTTERVIEWCONTROLLER_H_
#include "FlutterMacros.h"
#include "FlutterDartProject.h"
#import <UIKit/UIKit.h>
#include "FlutterAsyncMessageListener.h"
#include "FlutterDartProject.h"
#include "FlutterMacros.h"
#include "FlutterMessageListener.h"
FLUTTER_EXPORT
@interface
FlutterViewController
:
UIViewController
...
...
@@ -18,6 +20,19 @@ FLUTTER_EXPORT
bundle
:(
NSBundle
*
)
nibBundleOrNil
NS_DESIGNATED_INITIALIZER
;
-
(
void
)
sendString
:(
NSString
*
)
message
withMessageName
:(
NSString
*
)
messageName
;
-
(
void
)
sendString
:(
NSString
*
)
message
withMessageName
:(
NSString
*
)
messageName
callback
:(
void
(
^
)(
NSString
*
))
callback
;
-
(
void
)
setMessageListener
:(
NSObject
<
FlutterMessageListener
>*
)
listener
forMessagesWithName
:(
NSString
*
)
messageName
;
-
(
void
)
setAsyncMessageListener
:(
NSObject
<
FlutterAsyncMessageListener
>*
)
listener
forMessagesWithName
:(
NSString
*
)
messageName
;
@end
// Initializes Flutter for this process. Need only be called once per process.
...
...
sky/shell/platform/ios/framework/Source/FlutterViewController.mm
浏览文件 @
1d23f210
...
...
@@ -4,13 +4,20 @@
#import "sky/shell/platform/ios/framework/Headers/FlutterViewController.h"
#include "base/bind.h"
#include "base/mac/scoped_block.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/public/interfaces/application/service_provider.mojom.h"
#include "sky/engine/wtf/MakeUnique.h"
#include "sky/services/engine/sky_engine.mojom.h"
#include "sky/services/platform/app_messages.mojom.h"
#include "sky/services/platform/ios/system_chrome_impl.h"
#include "sky/services/semantics/semantics.mojom.h"
#include "sky/shell/platform/ios/framework/Source/application_messages_impl.h"
#include "sky/shell/platform/ios/framework/Source/flutter_touch_mapper.h"
#include "sky/shell/platform/ios/framework/Source/FlutterDartProject_Internal.h"
#include "sky/shell/platform/ios/framework/Source/FlutterDynamicServiceLoader.h"
...
...
@@ -30,14 +37,16 @@ void FlutterInit(int argc, const char* argv[]) {
}
@implementation
FlutterViewController
{
FlutterDartProject
*
_dartProject
;
base
::
scoped_nsprotocol
<
FlutterDartProject
*>
_dartProject
;
UIInterfaceOrientationMask
_orientationPreferences
;
FlutterDynamicServiceLoader
*
_dynamicServiceLoader
;
base
::
scoped_nsprotocol
<
FlutterDynamicServiceLoader
*>
_dynamicServiceLoader
;
sky
::
ViewportMetricsPtr
_viewportMetrics
;
sky
::
shell
::
TouchMapper
_touchMapper
;
std
::
unique_ptr
<
sky
::
shell
::
ShellView
>
_shellView
;
sky
::
SkyEnginePtr
_engine
;
mojo
::
ServiceProviderPtr
_dartServices
;
flutter
::
platform
::
ApplicationMessagesPtr
_appMessageSender
;
sky
::
shell
::
ApplicationMessagesImpl
_appMessageReceiver
;
BOOL
_initialized
;
}
...
...
@@ -49,7 +58,7 @@ void FlutterInit(int argc, const char* argv[]) {
self
=
[
super
initWithNibName
:
nibNameOrNil
bundle
:
nibBundleOrNil
];
if
(
self
)
{
_dartProject
=
[
project
retain
]
;
_dartProject
.
reset
([
project
retain
])
;
[
self
performCommonViewControllerInitialization
];
}
...
...
@@ -74,7 +83,7 @@ void FlutterInit(int argc, const char* argv[]) {
_initialized
=
YES
;
_orientationPreferences
=
UIInterfaceOrientationMaskAll
;
_dynamicServiceLoader
=
[[
FlutterDynamicServiceLoader
alloc
]
init
]
;
_dynamicServiceLoader
.
reset
([[
FlutterDynamicServiceLoader
alloc
]
init
])
;
_viewportMetrics
=
sky
::
ViewportMetrics
::
New
();
_shellView
=
WTF
::
MakeUnique
<
sky
::
shell
::
ShellView
>
(
sky
::
shell
::
Shell
::
Shared
());
...
...
@@ -160,6 +169,9 @@ void FlutterInit(int argc, const char* argv[]) {
[
alert
release
];
}
}];
DCHECK
(
_dartServices
);
mojo
::
ConnectToService
(
_dartServices
.
get
(),
&
_appMessageSender
);
}
static
void
DynamicServiceResolve
(
void
*
baton
,
...
...
@@ -178,13 +190,16 @@ static void DynamicServiceResolve(void* baton,
// the engine could outlive this controller
auto
serviceResolutionCallback
=
base
::
Bind
(
&
DynamicServiceResolve
,
base
::
Unretained
(
reinterpret_cast
<
void
*>
(
_dynamicServiceLoader
)));
base
::
Unretained
(
reinterpret_cast
<
void
*>
(
_dynamicServiceLoader
.
get
()
)));
new
sky
::
shell
::
PlatformServiceProvider
(
serviceProviderProxy
.
Pass
(),
serviceResolutionCallback
);
mojo
::
ServiceProviderPtr
viewServiceProvider
;
new
sky
::
shell
::
ViewServiceProvider
(
mojo
::
GetProxy
(
&
viewServiceProvider
));
new
sky
::
shell
::
ViewServiceProvider
(
base
::
Bind
(
&
sky
::
shell
::
ApplicationMessagesImpl
::
AddBinding
,
_appMessageReceiver
.
GetWeakPtr
()),
mojo
::
GetProxy
(
&
viewServiceProvider
));
DCHECK
(
!
_dartServices
.
is_bound
());
sky
::
ServicesDataPtr
services
=
sky
::
ServicesData
::
New
();
...
...
@@ -435,11 +450,47 @@ static inline PointerTypeMapperPhase PointerTypePhaseFromUITouchPhase(
-
(
void
)
dealloc
{
[[
NSNotificationCenter
defaultCenter
]
removeObserver
:
self
];
[
super
dealloc
];
}
[
_dynamicServiceLoader
release
];
[
_dartProject
release
];
#pragma mark - Application Messages
[
super
dealloc
];
-
(
void
)
sendString
:(
NSString
*
)
message
withMessageName
:(
NSString
*
)
messageName
{
NSAssert
(
message
,
@"The message must not be null"
);
NSAssert
(
messageName
,
@"The messageName must not be null"
);
_appMessageSender
->
SendString
(
messageName
.
UTF8String
,
message
.
UTF8String
,
[](
const
mojo
::
String
&
response
)
{
});
}
-
(
void
)
sendString
:(
NSString
*
)
message
withMessageName
:(
NSString
*
)
messageName
callback
:(
void
(
^
)(
NSString
*
))
callback
{
NSAssert
(
message
,
@"The message must not be null"
);
NSAssert
(
messageName
,
@"The messageName must not be null"
);
NSAssert
(
callback
,
@"The callback must not be null"
);
base
::
mac
::
ScopedBlock
<
void
(
^
)(
NSString
*
)
>
callback_ptr
(
callback
,
base
::
scoped_policy
::
RETAIN
);
_appMessageSender
->
SendString
(
messageName
.
UTF8String
,
message
.
UTF8String
,
[
callback_ptr
](
const
mojo
::
String
&
response
)
{
callback_ptr
.
get
()(
base
::
SysUTF8ToNSString
(
response
));
});
}
-
(
void
)
setMessageListener
:(
NSObject
<
FlutterMessageListener
>*
)
listener
forMessagesWithName
:(
NSString
*
)
messageName
{
NSAssert
(
listener
,
@"The listener must not be null"
);
NSAssert
(
messageName
,
@"The messageName must not be null"
);
_appMessageReceiver
.
SetMessageListener
(
messageName
.
UTF8String
,
base
::
scoped_nsprotocol
<
NSObject
<
FlutterMessageListener
>*>
(
listener
));
}
-
(
void
)
setAsyncMessageListener
:(
NSObject
<
FlutterAsyncMessageListener
>*
)
listener
forMessagesWithName
:(
NSString
*
)
messageName
{
NSAssert
(
listener
,
@"The listener must not be null"
);
NSAssert
(
messageName
,
@"The messageName must not be null"
);
_appMessageReceiver
.
SetAsyncMessageListener
(
messageName
.
UTF8String
,
base
::
scoped_nsprotocol
<
NSObject
<
FlutterAsyncMessageListener
>*>
(
listener
));
}
@end
sky/shell/platform/ios/framework/Source/application_messages_impl.h
0 → 100644
浏览文件 @
1d23f210
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_APPLICATION_MESSAGES_IMPL_H_
#define SKY_SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_APPLICATION_MESSAGES_IMPL_H_
#include <unordered_map>
#include "base/memory/weak_ptr.h"
#include "base/mac/scoped_nsobject.h"
#include "mojo/common/binding_set.h"
#include "sky/services/platform/app_messages.mojom.h"
#include "sky/shell/platform/ios/framework/Headers/FlutterAsyncMessageListener.h"
#include "sky/shell/platform/ios/framework/Headers/FlutterMessageListener.h"
namespace
sky
{
namespace
shell
{
class
ApplicationMessagesImpl
:
public
flutter
::
platform
::
ApplicationMessages
{
public:
ApplicationMessagesImpl
();
~
ApplicationMessagesImpl
()
override
;
base
::
WeakPtr
<
ApplicationMessagesImpl
>
GetWeakPtr
();
void
AddBinding
(
mojo
::
InterfaceRequest
<
flutter
::
platform
::
ApplicationMessages
>
request
);
void
SetMessageListener
(
const
std
::
string
&
message_name
,
base
::
scoped_nsprotocol
<
NSObject
<
FlutterMessageListener
>*>
listener
);
void
SetAsyncMessageListener
(
const
std
::
string
&
message_name
,
base
::
scoped_nsprotocol
<
NSObject
<
FlutterAsyncMessageListener
>*>
listener
);
private:
void
SendString
(
const
mojo
::
String
&
message_name
,
const
mojo
::
String
&
message
,
const
SendStringCallback
&
callback
)
override
;
mojo
::
BindingSet
<
flutter
::
platform
::
ApplicationMessages
>
binding_
;
std
::
unordered_map
<
std
::
string
,
base
::
scoped_nsprotocol
<
NSObject
<
FlutterMessageListener
>*>>
listeners_
;
std
::
unordered_map
<
std
::
string
,
base
::
scoped_nsprotocol
<
NSObject
<
FlutterAsyncMessageListener
>*>>
async_listeners_
;
base
::
WeakPtrFactory
<
ApplicationMessagesImpl
>
weak_factory_
;
};
}
// namespace shell
}
// namespace sky
#endif // SKY_SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_ACCESSIBILITY_BRIDGE_H_
sky/shell/platform/ios/framework/Source/application_messages_impl.mm
0 → 100644
浏览文件 @
1d23f210
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sky/shell/platform/ios/framework/Source/application_messages_impl.h"
#include "base/strings/sys_string_conversions.h"
namespace
sky
{
namespace
shell
{
ApplicationMessagesImpl
::
ApplicationMessagesImpl
()
:
weak_factory_
(
this
)
{
}
ApplicationMessagesImpl
::~
ApplicationMessagesImpl
()
{
}
base
::
WeakPtr
<
ApplicationMessagesImpl
>
ApplicationMessagesImpl
::
GetWeakPtr
()
{
return
weak_factory_
.
GetWeakPtr
();
}
void
ApplicationMessagesImpl
::
AddBinding
(
mojo
::
InterfaceRequest
<
flutter
::
platform
::
ApplicationMessages
>
request
)
{
binding_
.
AddBinding
(
this
,
request
.
Pass
());
}
void
ApplicationMessagesImpl
::
SetMessageListener
(
const
std
::
string
&
message_name
,
base
::
scoped_nsprotocol
<
NSObject
<
FlutterMessageListener
>*>
listener
)
{
listeners_
[
message_name
]
=
listener
;
}
void
ApplicationMessagesImpl
::
SetAsyncMessageListener
(
const
std
::
string
&
message_name
,
base
::
scoped_nsprotocol
<
NSObject
<
FlutterAsyncMessageListener
>*>
listener
)
{
async_listeners_
[
message_name
]
=
listener
;
}
void
ApplicationMessagesImpl
::
SendString
(
const
mojo
::
String
&
message_name
,
const
mojo
::
String
&
message
,
const
SendStringCallback
&
callback
)
{
std
::
string
message_name_str
=
message_name
;
NSString
*
ns_message
=
base
::
SysUTF8ToNSString
(
message
);
{
auto
it
=
listeners_
.
find
(
message_name_str
);
if
(
it
!=
listeners_
.
end
())
{
NSString
*
response
=
[
it
->
second
didReceiveString
:
ns_message
];
callback
.
Run
(
base
::
SysNSStringToUTF8
(
response
));
return
;
}
}
{
auto
it
=
async_listeners_
.
find
(
message_name_str
);
if
(
it
!=
async_listeners_
.
end
())
{
SendStringCallback
local_callback
=
callback
;
[
it
->
second
didReceiveString
:
ns_message
callback
:
^
(
NSString
*
response
){
local_callback
.
Run
(
base
::
SysNSStringToUTF8
(
response
));
}];
}
}
}
}
// namespace shell
}
// namespace sky
sky/shell/platform/mac/sky_window.mm
浏览文件 @
1d23f210
...
...
@@ -84,7 +84,8 @@ static inline pointer::PointerType EventTypeFromNSEventPhase(
base
::
Bind
(
DynamicServiceResolve
));
mojo
::
ServiceProviderPtr
view_service_provider
;
new
sky
::
shell
::
ViewServiceProvider
(
mojo
::
GetProxy
(
&
view_service_provider
));
new
sky
::
shell
::
ViewServiceProvider
(
AppMesssagesConnector
(),
mojo
::
GetProxy
(
&
view_service_provider
));
sky
::
ServicesDataPtr
services
=
sky
::
ServicesData
::
New
();
services
->
incoming_services
=
service_provider
.
Pass
();
...
...
sky/shell/platform/mac/view_service_provider.cc
浏览文件 @
1d23f210
...
...
@@ -9,14 +9,25 @@ namespace sky {
namespace
shell
{
ViewServiceProvider
::
ViewServiceProvider
(
AppMesssagesConnector
connect_to_app_messages
,
mojo
::
InterfaceRequest
<
mojo
::
ServiceProvider
>
request
)
:
binding_
(
this
,
request
.
Pass
())
{}
:
binding_
(
this
,
request
.
Pass
()),
connect_to_app_messages_
(
connect_to_app_messages
)
{
}
ViewServiceProvider
::~
ViewServiceProvider
()
{}
ViewServiceProvider
::~
ViewServiceProvider
()
{
}
void
ViewServiceProvider
::
ConnectToService
(
const
mojo
::
String
&
service_name
,
mojo
::
ScopedMessagePipeHandle
client_handle
)
{
if
(
service_name
==
::
flutter
::
platform
::
ApplicationMessages
::
Name_
&&
!
connect_to_app_messages_
.
is_null
())
{
connect_to_app_messages_
.
Run
(
mojo
::
MakeRequest
<::
flutter
::
platform
::
ApplicationMessages
>
(
client_handle
.
Pass
()));
return
;
}
#if TARGET_OS_IPHONE
if
(
service_name
==
::
editing
::
Keyboard
::
Name_
)
{
keyboard_
.
Create
(
...
...
sky/shell/platform/mac/view_service_provider.h
浏览文件 @
1d23f210
...
...
@@ -9,6 +9,7 @@
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/interfaces/application/service_provider.mojom.h"
#include "sky/engine/wtf/Assertions.h"
#include "sky/services/platform/app_messages.mojom.h"
#if TARGET_OS_IPHONE
#include "sky/services/editing/ios/keyboard_impl.h"
...
...
@@ -17,9 +18,14 @@
namespace
sky
{
namespace
shell
{
typedef
base
::
Callback
<
void
(
mojo
::
InterfaceRequest
<
flutter
::
platform
::
ApplicationMessages
>
)
>
AppMesssagesConnector
;
class
ViewServiceProvider
:
public
mojo
::
ServiceProvider
{
public:
ViewServiceProvider
(
mojo
::
InterfaceRequest
<
mojo
::
ServiceProvider
>
request
);
ViewServiceProvider
(
AppMesssagesConnector
connect_to_app_messages
,
mojo
::
InterfaceRequest
<
mojo
::
ServiceProvider
>
request
);
~
ViewServiceProvider
()
override
;
void
ConnectToService
(
const
mojo
::
String
&
service_name
,
...
...
@@ -27,6 +33,7 @@ class ViewServiceProvider : public mojo::ServiceProvider {
private:
mojo
::
StrongBinding
<
mojo
::
ServiceProvider
>
binding_
;
AppMesssagesConnector
connect_to_app_messages_
;
#if TARGET_OS_IPHONE
sky
::
services
::
editing
::
KeyboardFactory
keyboard_
;
#endif
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录