2015-03-14 18:24:48 +00:00
|
|
|
#import <Foundation/Foundation.h>
|
2015-03-14 21:47:16 +00:00
|
|
|
#import "assistantpluspluginmanager/AssistantPlusHeaders.h"
|
|
|
|
#import "assistantpluspluginmanager/AssistantHeaders.h"
|
2015-03-30 02:07:27 +00:00
|
|
|
#import "assistantpluspluginmanager/APPluginSystem.h"
|
2015-03-14 21:47:16 +00:00
|
|
|
#import "assistantpluspluginmanager/APSession.h"
|
2015-03-21 06:07:04 +00:00
|
|
|
#import "assistantpluspluginmanager/APSpringboardUtils.h"
|
2015-03-30 02:07:27 +00:00
|
|
|
#import <substrate.h>
|
2015-03-14 21:47:16 +00:00
|
|
|
|
2015-03-14 18:24:48 +00:00
|
|
|
@protocol SAAceSerializable <NSObject>
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface SBUIPluginController : NSObject
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface SAUIAppPunchOut : NSObject
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface SAUIConfirmationOptions : NSObject
|
|
|
|
@end
|
|
|
|
|
|
|
|
static BOOL defaultHandling = YES;
|
2015-03-15 20:51:49 +00:00
|
|
|
static AFConnection *currConnection;
|
2015-03-30 02:07:27 +00:00
|
|
|
static APPluginSystem *pluginManager;
|
|
|
|
static BOOL hasLoadedSnippets = NO;
|
2015-03-15 20:51:49 +00:00
|
|
|
|
2015-03-16 00:40:38 +00:00
|
|
|
BOOL shouldHandleRequest(NSString *text, APSession *currSession) {
|
2015-03-30 02:07:27 +00:00
|
|
|
pluginManager = [[%c(APSpringboardUtils) sharedAPUtils] getPluginManager];
|
2015-04-05 07:03:50 +00:00
|
|
|
NSArray *lowerCaseArr = [[text componentsSeparatedByString: @" "] valueForKey:@"lowercaseString"];
|
|
|
|
NSSet *tokens = [NSSet setWithArray:lowerCaseArr];
|
|
|
|
BOOL pluginWillHandle = [pluginManager handleCommand:text withTokens:tokens withSession:currSession];
|
|
|
|
defaultHandling = !pluginWillHandle;
|
|
|
|
return pluginWillHandle;
|
2015-03-15 20:51:49 +00:00
|
|
|
}
|
2015-03-14 18:24:48 +00:00
|
|
|
|
2015-03-16 00:40:38 +00:00
|
|
|
%hook BasicAceContext
|
2015-03-15 20:51:49 +00:00
|
|
|
- (Class)classWithClassName:(NSString*)name group:(NSString*)group {
|
2015-03-18 06:42:48 +00:00
|
|
|
id r;
|
2015-03-15 20:51:49 +00:00
|
|
|
if ([name isEqualToString:@"SnippetObject"] && [group isEqualToString:@"zaid.assistantplus.plugin"]) {
|
|
|
|
r = NSClassFromString(@"SAUISnippet");
|
2015-03-18 06:42:48 +00:00
|
|
|
} else {
|
|
|
|
r = %orig;
|
2015-03-15 20:51:49 +00:00
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
%end
|
2015-03-14 18:24:48 +00:00
|
|
|
|
2015-03-15 20:51:49 +00:00
|
|
|
%hook SiriUIPluginManager
|
2015-03-14 18:24:48 +00:00
|
|
|
|
2015-03-15 20:51:49 +00:00
|
|
|
- (id)transcriptItemForObject:(AceObject*)arg1 {
|
2015-03-30 02:07:27 +00:00
|
|
|
if (!hasLoadedSnippets) {
|
|
|
|
[self loadAssistantPlusSnippets];
|
|
|
|
}
|
2015-03-15 20:51:49 +00:00
|
|
|
NSDictionary *properties = [arg1 properties];
|
|
|
|
if (properties) {
|
|
|
|
NSString *className = properties[@"snippetClass"];
|
|
|
|
if (className) {
|
2015-03-21 06:07:04 +00:00
|
|
|
id<APPluginSnippet> customClass = [[NSClassFromString(className) alloc] initWithProperties:properties[@"snippetProps"]];
|
|
|
|
if ([customClass respondsToSelector:@selector(view)]) {
|
|
|
|
UIViewController *customVC = (UIViewController*)customClass;
|
2015-03-15 20:51:49 +00:00
|
|
|
SiriUISnippetViewController *vc = [[%c(SiriUISnippetViewController) alloc] init];
|
|
|
|
object_setClass(vc, [%c(APPluginSnippetViewController) class]);
|
|
|
|
[(APPluginSnippetViewController*)vc setCustomView:customVC];
|
|
|
|
SiriUITranscriptItem *item = [%c(SiriUITranscriptItem) transcriptItemWithAceObject:arg1];
|
|
|
|
item.viewController = vc;
|
|
|
|
return item;
|
|
|
|
} else {
|
2015-03-16 00:40:38 +00:00
|
|
|
NSLog(@"AP ERROR: %@ did not respond to customView", className);
|
2015-03-15 20:51:49 +00:00
|
|
|
}
|
|
|
|
} else {
|
2015-03-16 00:40:38 +00:00
|
|
|
NSLog(@"AP: No custom class for snippet, going to default!");
|
2015-03-15 20:51:49 +00:00
|
|
|
}
|
|
|
|
} else {
|
2015-03-16 00:40:38 +00:00
|
|
|
NSLog(@"AP ERROR: No properties for snippet, this shouldn't hapepn...");
|
2015-03-15 20:51:49 +00:00
|
|
|
}
|
2015-03-30 02:07:27 +00:00
|
|
|
id r = %orig(arg1);
|
2015-03-15 20:51:49 +00:00
|
|
|
return r;
|
|
|
|
}
|
2015-03-14 18:24:48 +00:00
|
|
|
|
2015-03-30 02:07:27 +00:00
|
|
|
%new
|
|
|
|
- (void)loadAssistantPlusSnippets {
|
|
|
|
hasLoadedSnippets = YES;
|
|
|
|
|
|
|
|
NSURL *directoryPath = [NSURL URLWithString:@PLUGIN_PATH];
|
|
|
|
|
|
|
|
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
|
|
NSArray *contents = [fileManager contentsOfDirectoryAtURL:directoryPath
|
|
|
|
includingPropertiesForKeys:@[]
|
|
|
|
options:NSDirectoryEnumerationSkipsHiddenFiles
|
|
|
|
error:nil];
|
|
|
|
|
|
|
|
for (NSURL *fileURL in contents) {
|
|
|
|
NSString *name = [[[fileURL absoluteString] lastPathComponent] stringByDeletingPathExtension];
|
|
|
|
|
|
|
|
NSBundle *bundle = [NSBundle bundleWithURL:fileURL];
|
|
|
|
|
|
|
|
if (!bundle) {
|
2015-04-05 07:03:50 +00:00
|
|
|
NSLog(@"Failed to open plugin bundle %@ (%@)!", fileURL, fileURL);
|
2015-03-30 02:07:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (![bundle load]) {
|
2015-04-05 07:03:50 +00:00
|
|
|
NSLog(@"Failed to load plugin bundle %@!", name);
|
2015-03-30 02:07:27 +00:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
NSLog(@"Loaded bundle!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-14 18:24:48 +00:00
|
|
|
|
2015-03-15 20:51:49 +00:00
|
|
|
%end
|
2015-03-14 18:24:48 +00:00
|
|
|
|
|
|
|
%hook AFConnection
|
|
|
|
|
2015-03-16 00:40:38 +00:00
|
|
|
- (void)startRequestWithCorrectedText:(NSString*)text forSpeechIdentifier:(id)arg2 {
|
|
|
|
NSLog(@"AP: Starting request with corrected text: %@", text);
|
2015-03-30 02:07:27 +00:00
|
|
|
APSession *currSession = [APSession sessionWithConnection:self];
|
2015-03-16 00:40:38 +00:00
|
|
|
if (shouldHandleRequest(text, currSession)) {
|
|
|
|
NSLog(@"Handling!");
|
|
|
|
} else {
|
|
|
|
%orig;
|
|
|
|
}
|
|
|
|
}
|
2015-03-14 18:24:48 +00:00
|
|
|
|
|
|
|
- (void)startRequestWithText:(NSString*)text {
|
2015-03-16 00:40:38 +00:00
|
|
|
NSLog(@"AP: Starting request with text: %@", text);
|
2015-03-30 02:07:27 +00:00
|
|
|
APSession *currSession = [APSession sessionWithConnection:self];
|
2015-03-16 00:40:38 +00:00
|
|
|
if (shouldHandleRequest(text, currSession)) {
|
2015-03-14 18:24:48 +00:00
|
|
|
NSLog(@"Handling!");
|
|
|
|
} else {
|
|
|
|
NSLog(@"Default!");
|
2015-03-14 21:47:16 +00:00
|
|
|
%orig;
|
2015-03-14 18:24:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
%end
|
|
|
|
|
|
|
|
%hook AFConnectionClientServiceDelegate
|
|
|
|
|
|
|
|
- (void)speechRecognized:(SASSpeechRecognized*)arg1 {
|
|
|
|
NSMutableString *phraseBuilder = [NSMutableString string];
|
|
|
|
for (AFSpeechPhrase *currPhrase in arg1.recognition.phrases) {
|
|
|
|
if (currPhrase.interpretations.count > 0) {
|
|
|
|
SASInterpretation *currInterpretation = currPhrase.interpretations[0];
|
|
|
|
if (currInterpretation.tokens.count > 0) {
|
2015-04-05 07:03:50 +00:00
|
|
|
for (AFSpeechToken *currToken in currInterpretation.tokens) {
|
|
|
|
[phraseBuilder appendString:[NSString stringWithFormat:@"%@ ", currToken.text]];
|
|
|
|
}
|
2015-03-14 18:24:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 06:42:48 +00:00
|
|
|
NSLog(@"AP Starting Speech Query: %@", phraseBuilder);
|
2015-03-14 18:24:48 +00:00
|
|
|
|
2015-03-21 06:07:04 +00:00
|
|
|
AFConnection *connection = MSHookIvar<AFConnection*>(self, "_connection");
|
2015-03-30 02:07:27 +00:00
|
|
|
APSession *currSession = [APSession sessionWithConnection:connection];
|
2015-03-18 06:42:48 +00:00
|
|
|
if (shouldHandleRequest(phraseBuilder, currSession)) {
|
2015-04-05 07:03:50 +00:00
|
|
|
[connection cancelRequest];
|
|
|
|
[self requestDidFinish];
|
2015-03-15 20:51:49 +00:00
|
|
|
} else {
|
2015-03-18 06:42:48 +00:00
|
|
|
%orig;
|
2015-03-15 20:51:49 +00:00
|
|
|
}
|
2015-03-14 18:24:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)requestDidReceiveCommand:(id)arg1 reply:(CDUnknownBlockType*)arg2 {
|
|
|
|
if (defaultHandling) {
|
2015-04-05 07:03:50 +00:00
|
|
|
NSLog(@"Allowing default!");
|
2015-03-14 18:24:48 +00:00
|
|
|
%orig;
|
2015-04-05 07:03:50 +00:00
|
|
|
} else {
|
|
|
|
NSLog(@"Overriding!");
|
2015-03-14 18:24:48 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-18 06:42:48 +00:00
|
|
|
%end
|