blob: 05e270edd71b6aea7d21b5eb0536cbab9f1c7622 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#import "WXVoiceOverModule.h"
#import "WXUtility.h"
#import "WXComponent_internal.h"
#import "WXComponentManager.h"
#import "WXThreadSafeMutableDictionary.h"
@implementation WXVoiceOverModule
{
BOOL _voiceOverStatus;
WXThreadSafeMutableDictionary * _announcementCallback;
}
@synthesize weexInstance;
WX_EXPORT_METHOD(@selector(read:callback:))
WX_EXPORT_METHOD(@selector(focusToElement:))
WX_EXPORT_METHOD_SYNC(@selector(isVoiceOverOn))
- (instancetype)init
{
if ([super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(voiceOverStatusListener) name:UIAccessibilityVoiceOverStatusChanged object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(voiceOverAnnounceFinish:) name:UIAccessibilityAnnouncementDidFinishNotification object:nil];
_voiceOverStatus = UIAccessibilityIsVoiceOverRunning();
_announcementCallback = [WXThreadSafeMutableDictionary new];
}
return self;
}
- (void)read:(NSDictionary*)param callback:(WXKeepAliveCallback)callback
{
if (![param isKindOfClass:[NSDictionary class]]) {
WXLogError(@"first param must be json type");
return;
}
NSString * string = nil;
if (param[@"value"]) {
string = [WXConvert NSString:param[@"value"]];
}
if (!string ) {
NSString * errorDesc = @"you didn't specify any value to read";
WXLogError(@"%@", errorDesc);
if (callback) {
callback(@{@"success":@false,@"errorDesc": errorDesc}, NO);
}
return;
}
if (![self isVoiceOverOn]) {
NSString * errorDesc = @"please check the voice status";
WXLogInfo(@"%@",errorDesc);
if (callback) {
callback(@{@"success":@false, @"errorDesc":errorDesc}, NO);
}
return;
}
float delay = 0.5;
if (param[@"delay"]) {
delay = [param[@"delay"] floatValue];
}
if (callback) {
NSMutableArray * callbacks = (NSMutableArray*)_announcementCallback[string];
if (callbacks) {
[callbacks addObject:callback];
} else {
callbacks = [NSMutableArray arrayWithObject:callback];
}
[_announcementCallback setObject:callbacks forKey:string];
}
if ([string isKindOfClass:[NSString class]]) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, string);
});
}
}
- (void)voiceOverAnnounceFinish:(NSNotification*)notification
{
NSString * string = notification.userInfo[UIAccessibilityAnnouncementKeyStringValue];
if (!_announcementCallback[string]) {
return;
}
BOOL announcementResult = [notification.userInfo[UIAccessibilityAnnouncementKeyWasSuccessful] boolValue];
NSMutableArray * callbacks = (NSMutableArray*)_announcementCallback[string];
if(![callbacks count]) {
return;
}
for (WXKeepAliveCallback callback in callbacks) {
callback(@{@"success":@(announcementResult),
@"value":string}, NO);
}
}
- (void)focusToElement:(NSString *)ref {
WXPerformBlockOnComponentThread(^{
WXComponent * compoent = [weexInstance componentForRef:ref];
if (compoent) {
WXPerformBlockOnMainThread(^{
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, compoent.view);
});
}
});
}
- (BOOL)isVoiceOverOn
{
return UIAccessibilityIsVoiceOverRunning();
}
- (void)voiceOverStatusListener
{
if (_voiceOverStatus != [self isVoiceOverOn]) {
_voiceOverStatus = [self isVoiceOverOn];
if ([weexInstance checkModuleEventRegistered:@"WXVoiceOverStatusChanged" moduleClassName:NSStringFromClass([self class])]) {
[weexInstance fireModuleEvent:[self class] eventName:@"WXVoiceOverStatusChanged" params:@{@"status":[self isVoiceOverOn]?@"on":@"off"}];
}
}
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityVoiceOverStatusChanged object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityAnnouncementDidFinishNotification object:nil];
}
@end